summaryrefslogtreecommitdiff
path: root/plugins/Clist_modern
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Clist_modern')
-rw-r--r--plugins/Clist_modern/clist_modern_10.vcxproj224
-rw-r--r--plugins/Clist_modern/clist_modern_10.vcxproj.filters302
-rw-r--r--plugins/Clist_modern/docs/clist_modern-translation.txt549
-rw-r--r--plugins/Clist_modern/res/resource.rc1215
-rw-r--r--plugins/Clist_modern/res/version.rc40
-rw-r--r--plugins/Clist_modern/src/MString.cpp205
-rw-r--r--plugins/Clist_modern/src/hdr/MString.h2304
-rw-r--r--plugins/Clist_modern/src/hdr/modern_awaymsg.h37
-rw-r--r--plugins/Clist_modern/src/hdr/modern_cache_funcs.h46
-rw-r--r--plugins/Clist_modern/src/hdr/modern_callproc.h128
-rw-r--r--plugins/Clist_modern/src/hdr/modern_clc.h515
-rw-r--r--plugins/Clist_modern/src/hdr/modern_clcpaint.h191
-rw-r--r--plugins/Clist_modern/src/hdr/modern_clist.h165
-rw-r--r--plugins/Clist_modern/src/hdr/modern_clui.h193
-rw-r--r--plugins/Clist_modern/src/hdr/modern_cluiframes.h150
-rw-r--r--plugins/Clist_modern/src/hdr/modern_commonheaders.h460
-rw-r--r--plugins/Clist_modern/src/hdr/modern_commonprototypes.h356
-rw-r--r--plugins/Clist_modern/src/hdr/modern_defsettings.h284
-rw-r--r--plugins/Clist_modern/src/hdr/modern_effectenum.h93
-rw-r--r--plugins/Clist_modern/src/hdr/modern_gettextasync.h5
-rw-r--r--plugins/Clist_modern/src/hdr/modern_global_structure.h92
-rw-r--r--plugins/Clist_modern/src/hdr/modern_image_array.h104
-rw-r--r--plugins/Clist_modern/src/hdr/modern_layered_window_engine.h51
-rw-r--r--plugins/Clist_modern/src/hdr/modern_log.h27
-rw-r--r--plugins/Clist_modern/src/hdr/modern_popup.h48
-rw-r--r--plugins/Clist_modern/src/hdr/modern_row.h86
-rw-r--r--plugins/Clist_modern/src/hdr/modern_rowheight_funcs.h70
-rw-r--r--plugins/Clist_modern/src/hdr/modern_skinengine.h148
-rw-r--r--plugins/Clist_modern/src/hdr/modern_skinned_profile.h245
-rw-r--r--plugins/Clist_modern/src/hdr/modern_skinselector.h88
-rw-r--r--plugins/Clist_modern/src/hdr/modern_static_clui.h246
-rw-r--r--plugins/Clist_modern/src/hdr/modern_static_cluiframes_service.h192
-rw-r--r--plugins/Clist_modern/src/hdr/modern_statusbar.h44
-rw-r--r--plugins/Clist_modern/src/hdr/modern_statusmodes.h43
-rw-r--r--plugins/Clist_modern/src/hdr/modern_sync.h98
-rw-r--r--plugins/Clist_modern/src/hdr/modern_tstring.h58
-rw-r--r--plugins/Clist_modern/src/init.cpp244
-rw-r--r--plugins/Clist_modern/src/m_api/m_skin_eng.h434
-rw-r--r--plugins/Clist_modern/src/m_api/m_skinbutton.h31
-rw-r--r--plugins/Clist_modern/src/m_api/m_skinned_profile.h44
-rw-r--r--plugins/Clist_modern/src/m_api/m_xpTheme.h35
-rw-r--r--plugins/Clist_modern/src/modern_aniavatars.cpp1300
-rw-r--r--plugins/Clist_modern/src/modern_awaymsg.cpp232
-rw-r--r--plugins/Clist_modern/src/modern_cachefuncs.cpp968
-rw-r--r--plugins/Clist_modern/src/modern_callproc.cpp20
-rw-r--r--plugins/Clist_modern/src/modern_clc.cpp2107
-rw-r--r--plugins/Clist_modern/src/modern_clcidents.cpp299
-rw-r--r--plugins/Clist_modern/src/modern_clcitems.cpp819
-rw-r--r--plugins/Clist_modern/src/modern_clcmsgs.cpp262
-rw-r--r--plugins/Clist_modern/src/modern_clcopts.cpp2068
-rw-r--r--plugins/Clist_modern/src/modern_clcpaint.cpp3385
-rw-r--r--plugins/Clist_modern/src/modern_clcutils.cpp870
-rw-r--r--plugins/Clist_modern/src/modern_clistevents.cpp624
-rw-r--r--plugins/Clist_modern/src/modern_clistmenus.cpp217
-rw-r--r--plugins/Clist_modern/src/modern_clistmod.cpp567
-rw-r--r--plugins/Clist_modern/src/modern_clistopts.cpp1282
-rw-r--r--plugins/Clist_modern/src/modern_clistsettings.cpp531
-rw-r--r--plugins/Clist_modern/src/modern_clisttray.cpp736
-rw-r--r--plugins/Clist_modern/src/modern_clui.cpp3111
-rw-r--r--plugins/Clist_modern/src/modern_cluiframes.cpp4222
-rw-r--r--plugins/Clist_modern/src/modern_cluiservices.cpp178
-rw-r--r--plugins/Clist_modern/src/modern_commonheaders.cpp247
-rw-r--r--plugins/Clist_modern/src/modern_contact.cpp219
-rw-r--r--plugins/Clist_modern/src/modern_docking.cpp372
-rw-r--r--plugins/Clist_modern/src/modern_extraimage.cpp509
-rw-r--r--plugins/Clist_modern/src/modern_framesmenu.cpp214
-rw-r--r--plugins/Clist_modern/src/modern_gdiplus.cpp308
-rw-r--r--plugins/Clist_modern/src/modern_gettextasync.cpp205
-rw-r--r--plugins/Clist_modern/src/modern_global.cpp35
-rw-r--r--plugins/Clist_modern/src/modern_groupmenu.cpp754
-rw-r--r--plugins/Clist_modern/src/modern_image_array.cpp705
-rw-r--r--plugins/Clist_modern/src/modern_keyboard.cpp67
-rw-r--r--plugins/Clist_modern/src/modern_log.cpp46
-rw-r--r--plugins/Clist_modern/src/modern_newrowopts.cpp198
-rw-r--r--plugins/Clist_modern/src/modern_popup.cpp131
-rw-r--r--plugins/Clist_modern/src/modern_row.cpp789
-rw-r--r--plugins/Clist_modern/src/modern_rowheight_funcs.cpp796
-rw-r--r--plugins/Clist_modern/src/modern_rowtemplateopt.cpp704
-rw-r--r--plugins/Clist_modern/src/modern_skinbutton.cpp815
-rw-r--r--plugins/Clist_modern/src/modern_skineditor.cpp841
-rw-r--r--plugins/Clist_modern/src/modern_skinengine.cpp4650
-rw-r--r--plugins/Clist_modern/src/modern_skinned_profile.cpp115
-rw-r--r--plugins/Clist_modern/src/modern_skinopt.cpp771
-rw-r--r--plugins/Clist_modern/src/modern_skinselector.cpp792
-rw-r--r--plugins/Clist_modern/src/modern_statusbar.cpp1136
-rw-r--r--plugins/Clist_modern/src/modern_statusbar_options.cpp541
-rw-r--r--plugins/Clist_modern/src/modern_sync.cpp147
-rw-r--r--plugins/Clist_modern/src/modern_tbbutton.cpp503
-rw-r--r--plugins/Clist_modern/src/modern_toolbar.cpp357
-rw-r--r--plugins/Clist_modern/src/modern_viewmodebar.cpp1574
-rw-r--r--plugins/Clist_modern/src/modern_xptheme.cpp265
-rw-r--r--plugins/Clist_modern/src/resource.h1053
-rw-r--r--plugins/Clist_modern/src/version.h15
93 files changed, 53207 insertions, 355 deletions
diff --git a/plugins/Clist_modern/clist_modern_10.vcxproj b/plugins/Clist_modern/clist_modern_10.vcxproj
index 06921757ee..98e75c7e0d 100644
--- a/plugins/Clist_modern/clist_modern_10.vcxproj
+++ b/plugins/Clist_modern/clist_modern_10.vcxproj
@@ -73,7 +73,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\include;..\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG_LOG;WIN32;_DEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_DEBUG_LOG;_WINDOWS;_USRDLL;CLIST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>Sync</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -83,7 +83,6 @@
<PrecompiledHeaderFile>hdr/modern_commonheaders.h</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
- <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -103,7 +102,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\include;..\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_DEBUG_LOG;WIN64;_DEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_DEBUG_LOG;_USRDLL;CLIST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>Sync</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -112,7 +111,6 @@
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>hdr/modern_commonheaders.h</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
- <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -134,7 +132,7 @@
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..\..\include;..\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<ExceptionHandling>false</ExceptionHandling>
<BufferSecurityCheck>false</BufferSecurityCheck>
@@ -144,7 +142,6 @@
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>hdr/modern_commonheaders.h</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
- <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -168,7 +165,7 @@
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..\..\include;..\ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;CLIST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
@@ -177,7 +174,6 @@
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>hdr/modern_commonheaders.h</PrecompiledHeaderFile>
<WarningLevel>Level3</WarningLevel>
- <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ExceptionHandling>false</ExceptionHandling>
</ClCompile>
<ResourceCompile>
@@ -197,141 +193,95 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
- <ClCompile Include="init.cpp" />
- <ClCompile Include="modern_aniavatars.cpp" />
- <ClCompile Include="modern_awaymsg.cpp" />
- <ClCompile Include="modern_cachefuncs.cpp" />
- <ClCompile Include="modern_clc.cpp" />
- <ClCompile Include="modern_clcidents.cpp" />
- <ClCompile Include="modern_clcitems.cpp" />
- <ClCompile Include="modern_clcmsgs.cpp" />
- <ClCompile Include="modern_clcopts.cpp" />
- <ClCompile Include="modern_clcpaint.cpp" />
- <ClCompile Include="modern_clcutils.cpp" />
- <ClCompile Include="modern_clistevents.cpp" />
- <ClCompile Include="modern_clistmenus.cpp" />
- <ClCompile Include="modern_clistmod.cpp" />
- <ClCompile Include="modern_clistopts.cpp" />
- <ClCompile Include="modern_clistsettings.cpp" />
- <ClCompile Include="modern_clisttray.cpp" />
- <ClCompile Include="modern_clui.cpp" />
- <ClCompile Include="modern_cluiframes.cpp" />
- <ClCompile Include="modern_cluiservices.cpp" />
- <ClCompile Include="modern_commonheaders.cpp">
+ <ClCompile Include="src\init.cpp" />
+ <ClCompile Include="src\modern_aniavatars.cpp" />
+ <ClCompile Include="src\modern_awaymsg.cpp" />
+ <ClCompile Include="src\modern_cachefuncs.cpp" />
+ <ClCompile Include="src\modern_clc.cpp" />
+ <ClCompile Include="src\modern_clcidents.cpp" />
+ <ClCompile Include="src\modern_clcitems.cpp" />
+ <ClCompile Include="src\modern_clcmsgs.cpp" />
+ <ClCompile Include="src\modern_clcopts.cpp" />
+ <ClCompile Include="src\modern_clcpaint.cpp" />
+ <ClCompile Include="src\modern_clcutils.cpp" />
+ <ClCompile Include="src\modern_clistevents.cpp" />
+ <ClCompile Include="src\modern_clistmenus.cpp" />
+ <ClCompile Include="src\modern_clistmod.cpp" />
+ <ClCompile Include="src\modern_clistopts.cpp" />
+ <ClCompile Include="src\modern_clistsettings.cpp" />
+ <ClCompile Include="src\modern_clisttray.cpp" />
+ <ClCompile Include="src\modern_clui.cpp" />
+ <ClCompile Include="src\modern_cluiframes.cpp" />
+ <ClCompile Include="src\modern_cluiservices.cpp" />
+ <ClCompile Include="src\modern_commonheaders.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
- <ClCompile Include="modern_contact.cpp" />
- <ClCompile Include="modern_docking.cpp" />
- <ClCompile Include="modern_extraimage.cpp" />
- <ClCompile Include="modern_framesmenu.cpp" />
- <ClCompile Include="modern_gdiplus.cpp" />
- <ClCompile Include="modern_gettextasync.cpp" />
- <ClCompile Include="modern_global.cpp" />
- <ClCompile Include="modern_groupmenu.cpp" />
- <ClCompile Include="modern_image_array.cpp" />
- <ClCompile Include="modern_keyboard.cpp" />
- <ClCompile Include="modern_log.cpp" />
- <ClCompile Include="modern_newrowopts.cpp" />
- <ClCompile Include="modern_popup.cpp" />
- <ClCompile Include="modern_row.cpp" />
- <ClCompile Include="modern_rowheight_funcs.cpp" />
- <ClCompile Include="modern_rowtemplateopt.cpp" />
- <ClCompile Include="modern_skinbutton.cpp" />
- <ClCompile Include="modern_skineditor.cpp" />
- <ClCompile Include="modern_skinengine.cpp" />
- <ClCompile Include="modern_skinopt.cpp" />
- <ClCompile Include="modern_skinselector.cpp" />
- <ClCompile Include="modern_statusbar.cpp" />
- <ClCompile Include="modern_statusbar_options.cpp" />
- <ClCompile Include="modern_sync.cpp" />
- <ClCompile Include="modern_tbbutton.cpp" />
- <ClCompile Include="modern_toolbar.cpp" />
- <ClCompile Include="modern_viewmodebar.cpp" />
- <ClCompile Include="modern_xptheme.cpp" />
+ <ClCompile Include="src\modern_contact.cpp" />
+ <ClCompile Include="src\modern_docking.cpp" />
+ <ClCompile Include="src\modern_extraimage.cpp" />
+ <ClCompile Include="src\modern_framesmenu.cpp" />
+ <ClCompile Include="src\modern_gdiplus.cpp" />
+ <ClCompile Include="src\modern_gettextasync.cpp" />
+ <ClCompile Include="src\modern_global.cpp" />
+ <ClCompile Include="src\modern_groupmenu.cpp" />
+ <ClCompile Include="src\modern_image_array.cpp" />
+ <ClCompile Include="src\modern_keyboard.cpp" />
+ <ClCompile Include="src\modern_log.cpp" />
+ <ClCompile Include="src\modern_newrowopts.cpp" />
+ <ClCompile Include="src\modern_popup.cpp" />
+ <ClCompile Include="src\modern_row.cpp" />
+ <ClCompile Include="src\modern_rowheight_funcs.cpp" />
+ <ClCompile Include="src\modern_rowtemplateopt.cpp" />
+ <ClCompile Include="src\modern_skinbutton.cpp" />
+ <ClCompile Include="src\modern_skineditor.cpp" />
+ <ClCompile Include="src\modern_skinengine.cpp" />
+ <ClCompile Include="src\modern_skinopt.cpp" />
+ <ClCompile Include="src\modern_skinselector.cpp" />
+ <ClCompile Include="src\modern_statusbar.cpp" />
+ <ClCompile Include="src\modern_statusbar_options.cpp" />
+ <ClCompile Include="src\modern_sync.cpp" />
+ <ClCompile Include="src\modern_tbbutton.cpp" />
+ <ClCompile Include="src\modern_toolbar.cpp" />
+ <ClCompile Include="src\modern_viewmodebar.cpp" />
+ <ClCompile Include="src\modern_xptheme.cpp" />
</ItemGroup>
<ItemGroup>
- <ClInclude Include="hdr\modern_cache_funcs.h" />
- <ClInclude Include="hdr\modern_callproc.h" />
- <ClInclude Include="hdr\modern_clc.h" />
- <ClInclude Include="hdr\modern_clcpaint.h" />
- <ClInclude Include="hdr\modern_clist.h" />
- <ClInclude Include="hdr\modern_clui.h" />
- <ClInclude Include="hdr\modern_cluiframes.h" />
- <ClInclude Include="hdr\modern_commonheaders.h" />
- <ClInclude Include="hdr\modern_commonprototypes.h" />
- <ClInclude Include="hdr\modern_defsettings.h" />
- <ClInclude Include="hdr\modern_effectenum.h" />
- <ClInclude Include="hdr\modern_image_array.h" />
- <ClInclude Include="hdr\modern_layered_window_engine.h" />
- <ClInclude Include="hdr\modern_log.h" />
- <ClInclude Include="hdr\modern_popup.h" />
- <ClInclude Include="hdr\modern_row.h" />
- <ClInclude Include="hdr\modern_rowheight_funcs.h" />
- <ClInclude Include="hdr\modern_skinengine.h" />
- <ClInclude Include="hdr\modern_skinned_profile.h" />
- <ClInclude Include="hdr\modern_static_clui.h" />
- <ClInclude Include="hdr\modern_static_cluiframes_service.h" />
- <ClInclude Include="hdr\modern_statusbar.h" />
- <ClInclude Include="hdr\modern_statusmodes.h" />
- <ClInclude Include="hdr\modern_sync.h" />
- <ClInclude Include="hdr\modern_tstring.h" />
- <ClInclude Include="hdr\MString.h" />
- <ClInclude Include="version.h" />
- <ClInclude Include="resource.h" />
- <ClInclude Include="hdr\modern_awaymsg.h" />
- <ClInclude Include="hdr\modern_gettextasync.h" />
- <ClInclude Include="hdr\modern_global_structure.h" />
- <ClInclude Include="hdr\modern_skinselector.h" />
+ <ClInclude Include="src\hdr\modern_cache_funcs.h" />
+ <ClInclude Include="src\hdr\modern_callproc.h" />
+ <ClInclude Include="src\hdr\modern_clc.h" />
+ <ClInclude Include="src\hdr\modern_clcpaint.h" />
+ <ClInclude Include="src\hdr\modern_clist.h" />
+ <ClInclude Include="src\hdr\modern_clui.h" />
+ <ClInclude Include="src\hdr\modern_cluiframes.h" />
+ <ClInclude Include="src\hdr\modern_commonheaders.h" />
+ <ClInclude Include="src\hdr\modern_commonprototypes.h" />
+ <ClInclude Include="src\hdr\modern_defsettings.h" />
+ <ClInclude Include="src\hdr\modern_effectenum.h" />
+ <ClInclude Include="src\hdr\modern_image_array.h" />
+ <ClInclude Include="src\hdr\modern_layered_window_engine.h" />
+ <ClInclude Include="src\hdr\modern_log.h" />
+ <ClInclude Include="src\hdr\modern_popup.h" />
+ <ClInclude Include="src\hdr\modern_row.h" />
+ <ClInclude Include="src\hdr\modern_rowheight_funcs.h" />
+ <ClInclude Include="src\hdr\modern_skinengine.h" />
+ <ClInclude Include="src\hdr\modern_skinned_profile.h" />
+ <ClInclude Include="src\hdr\modern_static_clui.h" />
+ <ClInclude Include="src\hdr\modern_static_cluiframes_service.h" />
+ <ClInclude Include="src\hdr\modern_statusbar.h" />
+ <ClInclude Include="src\hdr\modern_statusmodes.h" />
+ <ClInclude Include="src\hdr\modern_sync.h" />
+ <ClInclude Include="src\hdr\modern_tstring.h" />
+ <ClInclude Include="src\hdr\MString.h" />
+ <ClInclude Include="res\version.h" />
+ <ClInclude Include="res\resource.h" />
+ <ClInclude Include="src\hdr\modern_awaymsg.h" />
+ <ClInclude Include="src\hdr\modern_gettextasync.h" />
+ <ClInclude Include="src\hdr\modern_global_structure.h" />
+ <ClInclude Include="src\hdr\modern_skinselector.h" />
</ItemGroup>
<ItemGroup>
- <ResourceCompile Include="resource.rc" />
- <ResourceCompile Include="version.rc" />
- </ItemGroup>
- <ItemGroup>
- <None Include="res\1.ico" />
- <None Include="res\2.ico" />
- <None Include="res\3.ico" />
- <None Include="res\4.ico" />
- <None Include="res\5.ico" />
- <None Include="res\6.ico" />
- <None Include="res\7.ico" />
- <None Include="res\8.ico" />
- <None Include="res\addgoupp.ico" />
- <None Include="res\AlwaysVis.ico" />
- <None Include="res\away.ico" />
- <None Include="res\back.tga" />
- <None Include="res\chat.ico" />
- <None Include="res\Chatchannel.ico" />
- <None Include="res\dnd.ico" />
- <None Include="res\hide_avatar.ico" />
- <None Include="res\invisible.ico" />
- <None Include="res\listening_to.ico" />
- <None Include="res\lunch.ico" />
- <None Include="res\MicroAway.ico" />
- <None Include="res\MicroChat.ico" />
- <None Include="res\MicroDnd.ico" />
- <None Include="res\MicroInvisible.ico" />
- <None Include="res\MicroLunch.ico" />
- <None Include="res\MicroNa.ico" />
- <None Include="res\MicroOccupied.ico" />
- <None Include="res\MicroOffline.ico" />
- <None Include="res\MicroPhone.ico" />
- <None Include="res\NA.ico" />
- <None Include="res\neo_meta_create.cur" />
- <None Include="res\neo_meta_default.cur" />
- <None Include="res\neo_meta_move.cur" />
- <None Include="res\NeverVis.ico" />
- <None Include="res\occupied.ico" />
- <None Include="res\offline.ico" />
- <None Include="res\phone.ico" />
- <None Include="res\rate_high.ico" />
- <None Include="res\rate_low.ico" />
- <None Include="res\rate_med.ico" />
- <None Include="res\rate_none.ico" />
- <None Include="res\reset_view.ico" />
- <None Include="res\set_view.ico" />
- <None Include="res\show_avatar.ico" />
- <None Include="res\skin.msf" />
+ <ResourceCompile Include="res\resource.rc" />
+ <ResourceCompile Include="res\version.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/plugins/Clist_modern/clist_modern_10.vcxproj.filters b/plugins/Clist_modern/clist_modern_10.vcxproj.filters
index 2cc9a482c0..cad71e3060 100644
--- a/plugins/Clist_modern/clist_modern_10.vcxproj.filters
+++ b/plugins/Clist_modern/clist_modern_10.vcxproj.filters
@@ -18,392 +18,258 @@
</Filter>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="init.cpp">
+ <ClCompile Include="src\init.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_aniavatars.cpp">
+ <ClCompile Include="src\modern_aniavatars.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_awaymsg.cpp">
+ <ClCompile Include="src\modern_awaymsg.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_cachefuncs.cpp">
+ <ClCompile Include="src\modern_cachefuncs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_clc.cpp">
+ <ClCompile Include="src\modern_clc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_clcidents.cpp">
+ <ClCompile Include="src\modern_clcidents.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_clcitems.cpp">
+ <ClCompile Include="src\modern_clcitems.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_clcmsgs.cpp">
+ <ClCompile Include="src\modern_clcmsgs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_clcopts.cpp">
+ <ClCompile Include="src\modern_clcopts.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_clcpaint.cpp">
+ <ClCompile Include="src\modern_clcpaint.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_clcutils.cpp">
+ <ClCompile Include="src\modern_clcutils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_clistevents.cpp">
+ <ClCompile Include="src\modern_clistevents.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_clistmenus.cpp">
+ <ClCompile Include="src\modern_clistmenus.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_clistmod.cpp">
+ <ClCompile Include="src\modern_clistmod.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_clistopts.cpp">
+ <ClCompile Include="src\modern_clistopts.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_clistsettings.cpp">
+ <ClCompile Include="src\modern_clistsettings.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_clisttray.cpp">
+ <ClCompile Include="src\modern_clisttray.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_clui.cpp">
+ <ClCompile Include="src\modern_clui.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_cluiframes.cpp">
+ <ClCompile Include="src\modern_cluiframes.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_cluiservices.cpp">
+ <ClCompile Include="src\modern_cluiservices.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_commonheaders.cpp">
+ <ClCompile Include="src\modern_commonheaders.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_contact.cpp">
+ <ClCompile Include="src\modern_contact.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_docking.cpp">
+ <ClCompile Include="src\modern_docking.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_extraimage.cpp">
+ <ClCompile Include="src\modern_extraimage.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_framesmenu.cpp">
+ <ClCompile Include="src\modern_framesmenu.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_gdiplus.cpp">
+ <ClCompile Include="src\modern_gdiplus.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_gettextasync.cpp">
+ <ClCompile Include="src\modern_gettextasync.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_global.cpp">
+ <ClCompile Include="src\modern_global.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_groupmenu.cpp">
+ <ClCompile Include="src\modern_groupmenu.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_image_array.cpp">
+ <ClCompile Include="src\modern_image_array.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_keyboard.cpp">
+ <ClCompile Include="src\modern_keyboard.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_log.cpp">
+ <ClCompile Include="src\modern_log.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_newrowopts.cpp">
+ <ClCompile Include="src\modern_newrowopts.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_popup.cpp">
+ <ClCompile Include="src\modern_popup.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_row.cpp">
+ <ClCompile Include="src\modern_row.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_rowheight_funcs.cpp">
+ <ClCompile Include="src\modern_rowheight_funcs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_rowtemplateopt.cpp">
+ <ClCompile Include="src\modern_rowtemplateopt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_skinbutton.cpp">
+ <ClCompile Include="src\modern_skinbutton.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_skineditor.cpp">
+ <ClCompile Include="src\modern_skineditor.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_skinengine.cpp">
+ <ClCompile Include="src\modern_skinengine.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_skinopt.cpp">
+ <ClCompile Include="src\modern_skinopt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_skinselector.cpp">
+ <ClCompile Include="src\modern_skinselector.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_statusbar.cpp">
+ <ClCompile Include="src\modern_statusbar.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_statusbar_options.cpp">
+ <ClCompile Include="src\modern_statusbar_options.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_sync.cpp">
+ <ClCompile Include="src\modern_sync.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_tbbutton.cpp">
+ <ClCompile Include="src\modern_tbbutton.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_toolbar.cpp">
+ <ClCompile Include="src\modern_toolbar.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_viewmodebar.cpp">
+ <ClCompile Include="src\modern_viewmodebar.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="modern_xptheme.cpp">
+ <ClCompile Include="src\modern_xptheme.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
- <ClInclude Include="version.h">
+ <ClInclude Include="src\version.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="resource.h">
+ <ClInclude Include="src\resource.h">
<Filter>Resource Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_commonheaders.h">
+ <ClInclude Include="src\hdr\modern_commonheaders.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_skinselector.h">
+ <ClInclude Include="src\hdr\modern_skinselector.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_awaymsg.h">
+ <ClInclude Include="src\hdr\modern_awaymsg.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_gettextasync.h">
+ <ClInclude Include="src\hdr\modern_gettextasync.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_global_structure.h">
+ <ClInclude Include="src\hdr\modern_global_structure.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_cache_funcs.h">
+ <ClInclude Include="src\hdr\modern_cache_funcs.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_callproc.h">
+ <ClInclude Include="src\hdr\modern_callproc.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_clc.h">
+ <ClInclude Include="src\hdr\modern_clc.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_clcpaint.h">
+ <ClInclude Include="src\hdr\modern_clcpaint.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_clist.h">
+ <ClInclude Include="src\hdr\modern_clist.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_clui.h">
+ <ClInclude Include="src\hdr\modern_clui.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_cluiframes.h">
+ <ClInclude Include="src\hdr\modern_cluiframes.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_commonprototypes.h">
+ <ClInclude Include="src\hdr\modern_commonprototypes.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_defsettings.h">
+ <ClInclude Include="src\hdr\modern_defsettings.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_effectenum.h">
+ <ClInclude Include="src\hdr\modern_effectenum.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_image_array.h">
+ <ClInclude Include="src\hdr\modern_image_array.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_layered_window_engine.h">
+ <ClInclude Include="src\hdr\modern_layered_window_engine.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_log.h">
+ <ClInclude Include="src\hdr\modern_log.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_popup.h">
+ <ClInclude Include="src\hdr\modern_popup.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_row.h">
+ <ClInclude Include="src\hdr\modern_row.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_rowheight_funcs.h">
+ <ClInclude Include="src\hdr\modern_rowheight_funcs.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_skinengine.h">
+ <ClInclude Include="src\hdr\modern_skinengine.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_skinned_profile.h">
+ <ClInclude Include="src\hdr\modern_skinned_profile.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_static_clui.h">
+ <ClInclude Include="src\hdr\modern_static_clui.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_static_cluiframes_service.h">
+ <ClInclude Include="src\hdr\modern_static_cluiframes_service.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_statusbar.h">
+ <ClInclude Include="src\hdr\modern_statusbar.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_statusmodes.h">
+ <ClInclude Include="src\hdr\modern_statusmodes.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_sync.h">
+ <ClInclude Include="src\hdr\modern_sync.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\modern_tstring.h">
+ <ClInclude Include="src\hdr\modern_tstring.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="hdr\MString.h">
+ <ClInclude Include="src\hdr\MString.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
- <ResourceCompile Include="resource.rc">
+ <ResourceCompile Include="res\resource.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
- <ResourceCompile Include="version.rc">
+ <ResourceCompile Include="res\version.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
- <ItemGroup>
- <None Include="res\1.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\2.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\3.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\4.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\5.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\6.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\7.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\8.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\addgoupp.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\AlwaysVis.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\away.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\back.tga">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\chat.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\Chatchannel.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\dnd.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\hide_avatar.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\invisible.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\listening_to.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\lunch.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\MicroAway.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\MicroChat.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\MicroDnd.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\MicroInvisible.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\MicroLunch.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\MicroNa.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\MicroOccupied.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\MicroOffline.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\MicroPhone.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\NA.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\neo_meta_create.cur">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\neo_meta_default.cur">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\neo_meta_move.cur">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\NeverVis.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\occupied.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\offline.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\phone.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\rate_high.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\rate_low.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\rate_med.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\rate_none.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\reset_view.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\set_view.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\show_avatar.ico">
- <Filter>Resource Files\res</Filter>
- </None>
- <None Include="res\skin.msf">
- <Filter>Resource Files\res</Filter>
- </None>
- </ItemGroup>
-</Project> \ No newline at end of file
+ </Project> \ No newline at end of file
diff --git a/plugins/Clist_modern/docs/clist_modern-translation.txt b/plugins/Clist_modern/docs/clist_modern-translation.txt
new file mode 100644
index 0000000000..5301b3f5f2
--- /dev/null
+++ b/plugins/Clist_modern/docs/clist_modern-translation.txt
@@ -0,0 +1,549 @@
+; Common strings that belong to many files
+;[&About]
+;[&Delete Group]
+;[&Find/Add Contacts...]
+;[&Hide Offline Users]
+;[&Hide Offline Users in here]
+;[&Hide/Show]
+;[&Main Menu]
+;[&New Group]
+;[&Options...]
+;[&Rename Group]
+;[&Show Offline Users in here]
+;[&Status]
+;[Additional stuff]
+;[Always Visible]
+;[Away]
+;[Behaviour]
+;[Contact List]
+;[Contact time]
+;[DND]
+;[Disable &Groups]
+;[E&xit]
+;[Floating]
+;[Frames]
+;[Free for chat]
+;[Hide &Empty Groups]
+;[Hide &Offline Users out here]
+;[Invisible]
+;[Listening to]
+;[NA]
+;[Occupied]
+;[Offline]
+;[On the phone]
+;[Online]
+;[Out to lunch]
+;[Skins]
+;[Status]
+;[Status Bar]
+;[Sticky contacts]
+;[Tray]
+;[Visible]
+;[pixels]
+
+; ../../plugins/Clist_modern/modern_clc.cpp
+;[Adding contact to MetaContact]
+;[Changing MetaContacts (Moving)]
+;[Contact List smileys]
+;[Contact List/Avatar Overlay]
+;[Contact List/Status Overlay]
+;[Converting to MetaContact]
+;[Converting to MetaContact (Moving)]
+;[Do You want contact '%s' to be added to MetaContact '%s'?]
+;[Do You want contact '%s' to be converted to MetaContact and '%s' be added to it (remove it from '%s')?]
+;[Do You want contact '%s' to be converted to MetaContact and '%s' be added to it?]
+;[Do You want contact '%s' to be default ?]
+;[Do You want contact '%s' to be removed from MetaContact '%s' and added to '%s'?]
+;[Do you want to contact '%s' be added to metacontact '%s'?]
+;[Set default contact]
+
+; ../../plugins/Clist_modern/modern_clcopts.cpp
+;[3rd party frames transparent back colour]
+;[Away contacts]
+;[Background]
+;[Behind left edge]
+;[Behind right edge]
+;[Closed group member counts]
+;[Closed groups]
+;[Contact List/Contact names]
+;[Contact List/Frame texts]
+;[Contact List/Row Items]
+;[Contact List/Special colours]
+;[Contacts who are 'not on list']
+;[Current view mode text]
+;[DND contacts]
+;[Dividers]
+;[Event area text]
+;[Frame title text]
+;[Free for chat contacts]
+;[General]
+;[Global]
+;[Hide to tray]
+;[Hot text]
+;[Invisible contacts]
+;[List]
+;[List Background]
+;[Menu text]
+;[NA contacts]
+;[Not focused]
+;[Occupied contacts]
+;[Offline contacts]
+;[Offline contacts to whom you have a different visibility]
+;[On the phone contacts]
+;[Online contacts to whom you have a different visibility]
+;[Open group member counts]
+;[Open groups]
+;[Out to lunch contacts]
+;[Quick search text]
+;[Second line]
+;[Selected menu text]
+;[Selected text]
+;[Standard contacts]
+;[Status bar text]
+;[Statusbar text]
+;[Third line]
+;[Window]
+
+; ../../plugins/Clist_modern/modern_clistevents.cpp
+;[Event Area]
+;[No Events]
+
+; ../../plugins/Clist_modern/modern_clistmenus.cpp
+;[Contact rate High]
+;[Contact rate Low]
+;[Contact rate Medium]
+;[Contact rate None]
+
+; ../../plugins/Clist_modern/modern_clistopts.cpp
+;[Animate Avatars (GDI+ and Avatar Service module (avs.dll) are required)]
+;[Avatar]
+;[Extra Icons]
+;[Extra icons]
+;[Icon]
+;[Row]
+;[Row design]
+;[Row items]
+;[Second Line]
+;[Text]
+;[Third Line]
+
+; ../../plugins/Clist_modern/modern_clistsettings.cpp
+;[(Unknown Contact)]
+
+; ../../plugins/Clist_modern/modern_clui.cpp
+;[Hide Contact &Avatar]
+;[My Contacts]
+;[Show Contact &Avatar]
+
+; ../../plugins/Clist_modern/modern_cluiframes.cpp
+;[&Align]
+;[&Border]
+;[&Bottom]
+;[&Client]
+;[&Down]
+;[&Expanded]
+;[&Floating Mode]
+;[&Locked]
+;[&Position]
+;[&Show title]
+;[&Top]
+;[&Up]
+;[&Visible]
+;[Hide All Titlebars]
+;[Lock Frame]
+;[Show All Frames]
+;[Show All Titlebars]
+;[Show TitleBar]
+
+; ../../plugins/Clist_modern/modern_extraimage.cpp
+;[Chat Activity]
+;[Never Visible]
+
+; ../../plugins/Clist_modern/modern_groupmenu.cpp
+;[&New SubGroup]
+;[GroupMenu]
+;[SubGroupMenu]
+
+; ../../plugins/Clist_modern/modern_keyboard.cpp
+;[Close Miranda]
+;[Main]
+;[Restore last status]
+
+; ../../plugins/Clist_modern/modern_rowtemplateopt.cpp
+;[ layered]
+;[%s]
+;[%s, contain %s]
+;[Empty %s cell]
+;[column]
+;[columns]
+;[line]
+;[lines]
+
+; ../../plugins/Clist_modern/modern_skineditor.cpp
+;[Image size is]
+
+; ../../plugins/Clist_modern/modern_skinengine.cpp
+;[Error]
+;[You need an image services plugin to process PNG images.]
+
+; ../../plugins/Clist_modern/modern_skinopt.cpp
+;[%Default Skin%]
+;[%s\n\n%s\n\nAUTHORS:\n%s\n\nCONTACT:\n%s\n\nWEB:\n%s\n\n\n]
+;[%s\n\n%s\n\nAuthor(s): %s\nContact:\t %s\nWeb:\t %s\n\nFile:\t %s]
+;[%s\n\n%s\n\nAuthor(s):\t %s\nContact:\t %s\nWeb:\t %s\n\nFile:\t %s]
+;[( unknown )]
+;[Angeli-Ka (graphics), FYR (template)]
+;[Current skin was not saved to file.\n\nAll changes will be lost.\n\n Continue to load new skin?]
+;[Default Skin]
+;[Inside library]
+;[Load/Save]
+;[Miranda skin file]
+;[Object Editor]
+;[Please select skin to apply]
+;[Preview is not available\n\n%s\n----------------------\n\n%s\n\nAUTHOR(S):\n%s\n\nCONTACT:\n%s\n\nHOMEPAGE:\n%s]
+;[Select skin from list]
+;[Skin Information]
+;[Skin editor contains not stored changes.\n\nAll changes will be lost.\n\n Continue to load new skin?]
+;[This is second default Modern Contact list skin in Vista Aero style]
+;[Warning!]
+;[graphics by Angeli-Ka\ntemplate by FYR]
+;[reVista for Modern v0.5]
+
+; ../../plugins/Clist_modern/modern_statusbar_options.cpp
+;[<<Global>>]
+
+; ../../plugins/Clist_modern/modern_toolbar.cpp
+;[ToolBar]
+
+; ../../plugins/Clist_modern/modern_viewmodebar.cpp
+;[*** All contacts ***]
+;[A view mode with this name does alredy exist]
+;[All Contacts]
+;[All contacts]
+;[And]
+;[Clear view mode and return to default display]
+;[Configure view modes]
+;[Configuring view mode: %s]
+;[Days]
+;[Delete a view mode]
+;[Duplicate name]
+;[Filtering]
+;[Hours]
+;[Minutes]
+;[Newer than]
+;[Older than]
+;[Or]
+;[Really delete this view mode? This cannot be undone]
+;[Reset view mode]
+;[Select a view mode]
+;[Setup View Modes...]
+;[Setup view modes]
+;[Ungrouped contacts]
+;[View Modes]
+
+; ../../plugins/Clist_modern/resource.rc
+;[% of screen]
+;[&Away\tCtrl+2]
+;[&DND\tCtrl+5]
+;[&Free for chat\tCtrl+6]
+;[&Invisible\tCtrl+7]
+;[&NA\tCtrl+3]
+;[&New Subgroup]
+;[&Offline\tCtrl+0]
+;['Hide Offline' means to hide:]
+;[(Variables will be replaced)]
+;[* Restart may be required for all changes to take effect]
+;[* To increase Status Bar height:\nSet in Main menu: Frames->Status Bar->Show TitleBar then pull appeared title of status bar up or down.]
+;[1st:]
+;[2nd:]
+;[3rd:]
+;[Accounts per line]
+;[Active opacity:]
+;[Add container]
+;[After captions:]
+;[Align]
+;[Align left items to left]
+;[Align right items to right]
+;[Align to right]
+;[Allow internal requesting of away message text]
+;[Alpha]
+;[Always on top]
+;[Always show \"Always visibile\" icon]
+;[Always show status in tooltip]
+;[Animate Avatars]
+;[Appearance]
+;[Append nick if different from custom name]
+;[Apply]
+;[Are you sure you want to delete %s?]
+;[Ask before deleting contacts]
+;[Automatically clear this view mode after]
+;[Automatically resize window to height of list]
+;[Autosize toolbar]
+;[Available objects]
+;[Available skins]
+;[Available view modes]
+;[Avoid doubleclick expand]
+;[Away Message]
+;[Background colour:]
+;[Between frames:]
+;[Border]
+;[Border Color:]
+;[Borderless main window]
+;[Borders]
+;[Bottom/Right]
+;[Bring to front if covered]
+;[Browse]
+;[Button width]
+;[Cancel]
+;[Clear all]
+;[Client area margins]
+;[Colour]
+;[Compact mode]
+;[Compact mode\n(Show avatars and additional text\non selected contacts only)]
+;[Contact List Extra Icons]
+;[Contact List Sorting]
+;[Contact icon]
+;[Container height:]
+;[Container type:]
+;[Container width:]
+;[Copy]
+;[Custom corner size:]
+;[Cycle icons every]
+;[Default]
+;[Delete Contact]
+;[Dim idle contacts]
+;[Disable Skin Engine]
+;[Disable drag and drop of items]
+;[Disable groups]
+;[Disable icon blinking]
+;[Disable rename of items by clicking twice]
+;[Disabled]
+;[Dock to sides]
+;[Dont move offline user to bottom]
+;[Down]
+;[Drag to ]
+;[Draw a line alongside group names]
+;[Draw border on avatar]
+;[Draw icon in avatar space]
+;[Draw normal status as overlay]
+;[Draw overlay icons]
+;[Draw smileys on first line]
+;[Draw smileys on second line]
+;[Draw smileys on third line]
+;[Easy Scroll]
+;[Easy move]
+;[Editing view mode]
+;[Enable Aero Glass (Vista)]
+;[Enable custom account settings]
+;[Enable drop shadow (restart required)]
+;[Event notify area]
+;[Expand metacontacts]
+;[Fade contact list in/out]
+;[Fade out entire list when:]
+;[File]
+;[Fit mode]
+;[For other stuff MetaContacts plugin should be loaded.\n\nhttp://miranda-im.org/download]
+;[Fragment location]
+;[Frames Order]
+;[Full selection]
+;[Gamma correction]
+;[Gaps]
+;[Group]
+;[Groups]
+;[Height]
+;[Hide Miranda]
+;[Hide account completely]
+;[Hide all 'Extra icons' for subcontacts]
+;[Hide contact list after ]
+;[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 groups icon]
+;[Hide icon when showing avatar]
+;[Hide method]
+;[Hide offline subcontacts.]
+;[Hide offline users]
+;[Hide vertical scrollbar]
+;[Hints:\n* Use Drag&&Drop feature to change buttons order.\n* You can change button icons at Customize->Icons Toolbar section]
+;[Hold [Shift] to inverse [Right Click] behaviour]
+;[Horizontal Align]
+;[Horizontal align:]
+;[Hot track items as mouse passes over]
+;[Ignore Empty Extra icons places (arrange to right).]
+;[Ignore size for row height calcs]
+;[Image file and fitting mode]
+;[Inactive opacity:]
+;[Include groups]
+;[Include protocols]
+;[Include status modes]
+;[Indent groups by:]
+;[Info]
+;[Items]
+;[Last message ]
+;[Layered]
+;[Left]
+;[Left margin:]
+;[Less selection]
+;[List content:]
+;[List sorting:]
+;[Lock manual resize]
+;[Locked]
+;[Make sections equal width]
+;[Make selection highlight translucent]
+;[Max width]
+;[MetaContacts stuff]
+;[Min row height:]
+;[Minimize to tray]
+;[Move down]
+;[Move up]
+;[Multiline status bar:]
+;[Multiline toolbar]
+;[New]
+;[Nickname]
+;[No]
+;[No selection]
+;[Non-layered mode]
+;[Normal overlay icon]
+;[Nowhere]
+;[OPTION PAGE IS UNDER CONSTRUCTION Please DO NOT notice about any issues here.\n Only high-level design comments are applicable.]
+;[Object properties]
+;[Occ&upied\tCtrl+4]
+;[Ok]
+;[On the &Phone\tCtrl+8]
+;[On&line\tCtrl+1]
+;[Only when statuses differ]
+;[Options]
+;[Order of items:]
+;[Out to &Lunch\tCtrl+9]
+;[Paste]
+;[Pin to desktop]
+;[Place offline users out of groups]
+;[Position (vertical)]
+;[Position:]
+;[Preview]
+;[Protocol]
+;[Protocol status icon]
+;[Quicksearch in open groups only]
+;[Remove away message if contact became offline]
+;[Remove container]
+;[Replace smileys in clist]
+;[Resize smileys and 'Listining to' icon]
+;[Right click opens Miranda menu]
+;[Right click opens status menu]
+;[Right margin:]
+;[Right-To-Left reading mode (mirror template)]
+;[Round corners]
+;[Round corners of avatars]
+;[Row border:]
+;[Row template]
+;[Scroll list smoothly]
+;[Scroll with text]
+;[Selection Mode]
+;[Selection colour:]
+;[Set options per account]
+;[Settings]
+;[Show]
+;[Show Avatars]
+;[Show Title]
+;[Show Toolbar with next buttons:]
+;[Show automaticaly]
+;[Show both icons]
+;[Show contact time as row item]
+;[Show contact time in list]
+;[Show contacts in groups]
+;[Show counts of number of contacts in a group]
+;[Show divider between online and offline contacts]
+;[Show listening to if there isn't away message]
+;[Show menu bar]
+;[Show multiple icons]
+;[Show normal status as overlay]
+;[Show protocol icon]
+;[Show protocol names]
+;[Show second line]
+;[Show selection even when list is not focused]
+;[Show status bar]
+;[Show status if there isn't away message]
+;[Show status text]
+;[Show third line]
+;[Show time only if it is different from current time]
+;[Show title bar]
+;[Show unread emails (if supported)]
+;[Show xStatus Name]
+;[Show xStatus icon]
+;[Single click interface]
+;[Size upwards]
+;[Size:]
+;[Skin Preview]
+;[Slider2]
+;[Snap to edges]
+;[Sort groups alphabetically]
+;[Space between]
+;[Space on Left]
+;[Space on right]
+;[Spin1]
+;[Status bar:]
+;[Status mode]
+;[Status overlay opacity is 75% ]
+;[Stretch proportionally]
+;[Stretch to height]
+;[Stretch to width]
+;[Subcontacts indent:]
+;[System tray icon]
+;[System tray icon mode]
+;[Text:]
+;[Thin border main window]
+;[This will erase all history and settings for this contact!]
+;[Tile horizontally]
+;[Tile vertically]
+;[Tile vertically according to Row Height]
+;[Time:]
+;[Title bar text:]
+;[Tool style main window]
+;[Toolbar settings]
+;[Top]
+;[Top space:]
+;[Top/Left]
+;[Translucency options (Windows 2000/XP only)]
+;[Transparency:]
+;[Transparent contact list]
+;[Trim long text with ellipsis]
+;[Type]
+;[UNDER CONSTRUCTION!!! IT DOES NOT WORK]
+;[Up]
+;[Use 'Meta' protocol icons for Metacontacts]
+;[Use 'XStatus: XMessage']
+;[Use Non-Layered mode]
+;[Use Options->Ignore (expert mode) to unhide contacts.]
+;[Use Windows Colors]
+;[Use background bitmap]
+;[Use connecting Icon]
+;[Use extra status icon instead protocol]
+;[Use old render method (Fast, but has artefacts)]
+;[Use protocol smileys]
+;[Use xStatus icon]
+;[Using the contact list on the left side, you can select contacts which will be \"sticky\" for this view mode. These contacts will ignore the standard filter rules and only use the status mode filter below.]
+;[Variable row height]
+;[Vertical Align]
+;[Vertical align:]
+;[View mode options]
+;[Visual]
+;[W x H: 0 x 0 pixels]
+;[WARNING: \tSkins can modify your current profile. Rollback is not possible. \n\t\tPlease BACKUP your database before applying skin.]
+;[Width]
+;[Window behaviour:]
+;[XStatus has priority]
+;[Yes]
+;[[Ctrl]+[Left Click] to filter only protocol. Click on empty space to show all]
+;[\n\n\nPlease select one of available skins. \n\nOr browse for skin not in list.]
+;[and minimum]
+;[height]
+;[hide delay]
+;[keep on screen]
+;[maximum]
+;[milliseconds]
+;[ms, delay between icon blinking]
+;[only when statuses differ]
+;[seconds]
+;[seconds, when statuses differ]
+;[show delay]
+;[x100 msec]
diff --git a/plugins/Clist_modern/res/resource.rc b/plugins/Clist_modern/res/resource.rc
new file mode 100644
index 0000000000..2e3b4d91f3
--- /dev/null
+++ b/plugins/Clist_modern/res/resource.rc
@@ -0,0 +1,1215 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "..\src\resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <winresrc.h>
+#include "..\src\hdr\modern_statusmodes.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(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_HIDE_AVATAR ICON "hide_avatar.ico"
+IDI_SHOW_AVATAR ICON "show_avatar.ico"
+IDI_NEWGROUP2 ICON "addgoupp.ico"
+IDI_LISTENING_TO ICON "listening_to.ico"
+IDI_ALWAYSVIS ICON "AlwaysVis.ico"
+IDI_NEVERVIS ICON "NeverVis.ico"
+IDI_CHAT ICON "Chatchannel.ico"
+IDI_FAVORITE_0 ICON "rate_none.ico"
+IDI_FAVORITE_1 ICON "rate_low.ico"
+IDI_FAVORITE_2 ICON "rate_med.ico"
+IDI_FAVORITE_3 ICON "rate_high.ico"
+IDI_AVATAR_OVERLAY_NA ICON "NA.ico"
+IDI_AVATAR_OVERLAY_OCCUPIED ICON "occupied.ico"
+IDI_AVATAR_OVERLAY_OFFLINE ICON "offline.ico"
+IDI_AVATAR_OVERLAY_PHONE ICON "phone.ico"
+IDI_AVATAR_OVERLAY_AWAY ICON "Away.ico"
+IDI_AVATAR_OVERLAY_DND ICON "DND.ico"
+IDI_AVATAR_OVERLAY_INVISIBLE ICON "invisible.ico"
+IDI_AVATAR_OVERLAY_LUNCH ICON "lunch.ico"
+IDI_AVATAR_OVERLAY_CHAT ICON "chat.ico"
+IDI_STATUS_OVERLAY_NA ICON "MicroNA.ico"
+IDI_STATUS_OVERLAY_OCCUPIED ICON "Microoccupied.ico"
+IDI_STATUS_OVERLAY_OFFLINE ICON "Microoffline.ico"
+IDI_STATUS_OVERLAY_PHONE ICON "Microphone.ico"
+IDI_STATUS_OVERLAY_AWAY ICON "MicroAway.ico"
+IDI_STATUS_OVERLAY_DND ICON "MicroDND.ico"
+IDI_STATUS_OVERLAY_INVISIBLE ICON "Microinvisible.ico"
+IDI_STATUS_OVERLAY_LUNCH ICON "Microlunch.ico"
+IDI_STATUS_OVERLAY_CHAT ICON "Microchat.ico"
+IDI_ICQC1 ICON "1.ico"
+IDI_ICQC2 ICON "2.ico"
+IDI_ICQC3 ICON "3.ico"
+IDI_ICQC4 ICON "4.ico"
+IDI_ICQC5 ICON "5.ico"
+IDI_ICQC6 ICON "6.ico"
+IDI_ICQC7 ICON "7.ico"
+IDI_ICQC8 ICON "8.ico"
+IDI_SETVIEW ICON "set_view.ico"
+IDI_RESETVIEW ICON "reset_view.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Cursor
+//
+
+IDC_DEFAULTSUB CURSOR "neo_meta_default.cur"
+IDC_DROPMETA CURSOR "neo_meta_create.cur"
+IDC_REGROUP CURSOR "neo_meta_move.cur"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_MODERNOPTS DIALOGEX 0, 0, 369, 173
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ LTEXT "Transparency:",IDC_TXT_TITLE2,0,78,184,8
+ LTEXT "Window behaviour:",IDC_TXT_TITLE1,1,0,182,8
+ LTEXT "List sorting:",IDC_TXT_TITLE4,184,88,183,8
+ LTEXT "Status bar:",IDC_TXT_TITLE5,0,39,184,8
+ LTEXT "List content:",IDC_TXT_TITLE3,184,0,183,8
+ CONTROL "Show counts of number of contacts in a group",IDC_SHOWGROUPCOUNTS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,193,13,176,10
+ CONTROL "Hide group counts when there are none online",IDC_HIDECOUNTSWHENEMPTY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,193,25,176,10
+ RTEXT "1st:",IDC_STATIC,184,102,27,12,SS_CENTERIMAGE
+ RTEXT "2nd:",IDC_STATIC,184,118,27,12,SS_CENTERIMAGE
+ RTEXT "3rd:",IDC_STATIC,184,134,27,12,SS_CENTERIMAGE
+ COMBOBOX IDC_CLSORT1,214,102,155,146,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_CLSORT2,214,118,155,140,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_CLSORT3,214,134,155,140,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Always on top",IDC_ONTOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,13,174,10
+ CONTROL "Hide contact list after ",IDC_AUTOHIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,25,97,10
+ EDITTEXT IDC_HIDETIME,110,24,31,12,ES_RIGHT | ES_NUMBER
+ CONTROL "",IDC_HIDETIMESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,132,23,11,14
+ LTEXT "seconds",IDC_STATIC01,150,26,35,8
+ CONTROL "Fade contact list in/out",IDC_FADEINOUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,91,174,10
+ CONTROL "Transparent contact list",IDC_TRANSPARENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,103,174,10
+ LTEXT "Inactive opacity:",IDC_STATIC11,30,119,57,8
+ CONTROL "",IDC_TRANSINACTIVE,"msctls_trackbar32",TBS_TOP | TBS_NOTICKS | WS_TABSTOP,89,116,64,14
+ LTEXT "000%",IDC_INACTIVEPERC,159,119,24,8,SS_NOPREFIX
+ LTEXT "Active opacity:",IDC_STATIC12,30,134,57,8
+ CONTROL "",IDC_TRANSACTIVE,"msctls_trackbar32",TBS_TOP | TBS_NOTICKS | WS_TABSTOP,89,131,64,14
+ LTEXT "000%",IDC_ACTIVEPERC,159,134,24,8,SS_NOPREFIX
+ CONTROL "Show Avatars",IDC_SHOW_AVATARS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,193,49,175,10
+ CONTROL "Animate Avatars",IDC_SHOW_ANIAVATARS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,213,61,155,10
+ CONTROL "Show contact time in list",IDC_SHOW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,193,73,175,10
+ CONTROL "Compact mode",IDC_MINIMODE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,193,37,175,10
+ CONTROL "Show protocol names",IDC_SHOWPROTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,52,174,10
+ CONTROL "Show status text",IDC_SHOWSTATUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,64,174,10
+END
+
+IDD_OPT_CLIST_LISTBKG DIALOGEX 0, 0, 234, 184
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Settings",IDC_STATIC,4,21,226,152
+ LTEXT "Background colour:",IDC_BC_STATIC,12,48,72,8,NOT WS_GROUP
+ CONTROL "",IDC_BKGCOLOUR,"ColourPicker",WS_TABSTOP,84,47,32,10
+ LTEXT "Selection colour:",IDC_SC_STATIC,12,64,72,8
+ CONTROL "",IDC_SELCOLOUR,"ColourPicker",WS_TABSTOP,84,63,32,10
+ CONTROL "Use background bitmap",IDC_BITMAP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,81,161,10
+ EDITTEXT IDC_FILENAME,22,95,184,12,ES_AUTOHSCROLL
+ PUSHBUTTON "...",IDC_BROWSE,208,95,15,11
+ CONTROL "Stretch to width",IDC_STRETCHH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,112,98,10
+ CONTROL "Stretch to height",IDC_STRETCHV,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,121,112,101,10
+ CONTROL "Tile horizontally",IDC_TILEH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,125,98,10
+ CONTROL "Tile vertically",IDC_TILEV,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,138,98,10
+ CONTROL "Scroll with text",IDC_SCROLL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,121,138,100,10
+ CONTROL "Stretch proportionally",IDC_PROPORTIONAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,121,125,101,10
+ CONTROL "Tile vertically according to Row Height",IDC_TILEVROWH,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,22,153,205,10
+ COMBOBOX IDC_BKGRLIST,4,4,226,155,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Use Windows Colors",IDC_USEWINCOL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,33,213,10
+END
+
+IDD_OPT_SKIN DIALOGEX 0, 0, 303, 220
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ GROUPBOX "Available skins",IDC_STATIC,0,5,173,182,WS_DISABLED
+ EDITTEXT IDC_EDIT_SKIN_FILENAME,4,15,162,12,ES_AUTOHSCROLL | ES_READONLY | WS_GROUP,WS_EX_ACCEPTFILES
+ PUSHBUTTON "Browse",IDC_BUTTON_LOAD,5,170,48,12
+ PUSHBUTTON "Apply",IDC_BUTTON_APPLY_SKIN,61,170,48,12,WS_DISABLED
+ PUSHBUTTON "Info",IDC_BUTTON_INFO,118,170,48,12,WS_DISABLED
+ CTEXT "\n\n\nPlease select one of available skins. \n\nOr browse for skin not in list.",IDC_STATIC_INFO,180,30,108,150
+ CONTROL "",IDC_PREVIEW,"Static",SS_OWNERDRAW | SS_CENTERIMAGE | SS_REALSIZEIMAGE,180,16,113,167
+ GROUPBOX "Skin Preview",IDC_STATIC,175,5,123,182,WS_DISABLED
+ LTEXT "WARNING: \tSkins can modify your current profile. Rollback is not possible. \n\t\tPlease BACKUP your database before applying skin.",IDC_STATIC,3,188,294,17
+ LTEXT "* Restart may be required for all changes to take effect",IDC_STATIC,3,210,200,8
+ COMBOBOX IDC_COMBO1,177,189,123,76,CBS_DROPDOWN | CBS_SORT | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP
+ CONTROL "",IDC_TREE1,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_SHOWSELALWAYS | TVS_SINGLEEXPAND | WS_BORDER | WS_TABSTOP,5,30,161,133
+END
+
+IDD_OPT_SKINEDITOR DIALOGEX 0, 0, 305, 222
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ GROUPBOX "Available objects",IDC_GROUP_0,0,6,124,216,WS_GROUP
+ CONTROL "",IDC_OBJECT_TREE,"SysTreeView32",TVS_HASBUTTONS | TVS_LINESATROOT | TVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP,6,19,112,182
+ PUSHBUTTON "Copy",IDC_COPY,7,205,50,13
+ PUSHBUTTON "Paste",IDC_PASTE,68,205,50,13
+ GROUPBOX "Object properties",IDC_GROUP_1,127,6,178,49,WS_GROUP
+ LTEXT "Type",IDC_STATIC,136,18,29,11,NOT WS_GROUP
+ COMBOBOX IDC_TYPE,168,16,133,69,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Colour",IDC_ST_COLOUR,136,38,29,11
+ CONTROL "",IDC_COLOR,"ColourPicker",WS_TABSTOP,168,37,41,12
+ LTEXT "Alpha",IDC_ST_ALPHA,222,38,33,11
+ EDITTEXT IDC_EDIT_ALPHA,261,37,40,12,ES_NUMBER
+ CONTROL "",IDC_SPIN_ALPHA,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,291,33,10,14
+ GROUPBOX "Image file and fitting mode",IDC_GROUP_2,127,56,178,93,WS_GROUP
+ LTEXT "File",IDC_STATIC,136,72,29,11,NOT WS_GROUP
+ EDITTEXT IDC_FILE,168,70,115,12,ES_AUTOHSCROLL
+ PUSHBUTTON "...",IDC_BROWSE,286,70,15,11
+ LTEXT "Borders",IDC_STATIC,136,93,49,9,NOT WS_GROUP
+ EDITTEXT IDC_E_LEFT,149,105,45,12,ES_NUMBER
+ CONTROL "",IDC_SPIN_LEFT,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,190,105,10,14
+ EDITTEXT IDC_E_TOP,204,96,45,12,ES_NUMBER
+ CONTROL "",IDC_SPIN_TOP,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,244,95,10,14
+ EDITTEXT IDC_E_RIGHT,255,105,43,12,ES_NUMBER
+ CONTROL "",IDC_SPIN_RIGHT,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,292,100,10,14
+ EDITTEXT IDC_E_BOTTOM,204,113,45,12,ES_NUMBER
+ CONTROL "",IDC_SPIN_BOTTOM,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,246,112,10,14
+ RTEXT "Fit mode",IDC_STATIC,134,133,58,11,NOT WS_GROUP
+ COMBOBOX IDC_FIT,198,131,100,69,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "Fragment location",IDC_GROUP_3,127,150,178,72,WS_GROUP
+ LTEXT "Position:",IDC_STATIC,133,163,42,11,NOT WS_GROUP
+ RTEXT "Left",IDC_STATIC,134,176,23,11,NOT WS_GROUP
+ EDITTEXT IDC_E_X,166,175,43,12,ES_NUMBER
+ CONTROL "",IDC_SPIN_POSLEFT,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,211,174,10,14
+ RTEXT "Top",IDC_STATIC,214,176,34,11,NOT WS_GROUP
+ EDITTEXT IDC_E_Y,252,175,46,12,ES_NUMBER
+ CONTROL "",IDC_SPIN_POSTOP,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,292,174,10,14
+ LTEXT "Size:",IDC_STATIC,133,192,67,11,NOT WS_GROUP
+ RTEXT "Width",IDC_STATIC,138,205,24,11,NOT WS_GROUP
+ EDITTEXT IDC_E_W,166,204,45,12,ES_NUMBER
+ CONTROL "",IDC_SPIN_WIDTH,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,211,203,10,14
+ RTEXT "Height",IDC_STATIC,215,206,34,9,NOT WS_GROUP
+ EDITTEXT IDC_E_H,252,204,46,12,ES_NUMBER
+ CONTROL "",IDC_SPIN_HEIGHT,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,293,203,10,14
+ EDITTEXT IDC_EDIT1,0,206,6,12,ES_AUTOHSCROLL | NOT WS_VISIBLE | WS_GROUP
+ RTEXT "W x H: 0 x 0 pixels",IDC_S_SIZE,135,84,148,8,WS_DISABLED
+END
+
+IDD_OPT_ITEMS DIALOGEX 0, 0, 315, 243
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | DS_CENTER | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_TAB,"SysTabControl32",0x0,0,0,315,243
+END
+
+IDD_OPT_VIEWMODES DIALOGEX 0, 0, 309, 295
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_CAPTION | WS_SYSMENU
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "",IDC_TAB,"SysTabControl32",0x0,4,4,301,264
+ LTEXT "",IDC_STATIC7,6,22,297,244
+ GROUPBOX "Available view modes",IDC_STATIC1,9,20,158,85
+ LISTBOX IDC_VIEWMODES,12,30,123,55,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP,WS_EX_CLIENTEDGE
+ GROUPBOX "Include protocols",IDC_STATIC2,171,20,130,85
+ CONTROL "",IDC_PROTOCOLS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,175,30,121,72
+ PUSHBUTTON "+",IDC_ADDVIEWMODE,142,39,18,16
+ PUSHBUTTON "-",IDC_DELETEVIEWMODE,142,60,18,16
+ LTEXT "New",IDC_STATIC5,15,91,38,11,0,WS_EX_TRANSPARENT
+ EDITTEXT IDC_NEWVIEMODE,59,88,76,13,ES_AUTOHSCROLL
+ GROUPBOX "Include groups",IDC_STATIC3,8,105,159,89,0,WS_EX_TRANSPARENT
+ CONTROL "",IDC_GROUPS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,12,116,122,57
+ CONTROL "Show contacts in groups",IDC_USEGROUPS,"Button",BS_AUTO3STATE | WS_TABSTOP,12,178,122,11
+ GROUPBOX "Include status modes",IDC_STATIC4,171,105,130,89,0,WS_EX_TRANSPARENT
+ CONTROL "",IDC_STATUSMODES,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,175,116,121,73
+ PUSHBUTTON "Ok",IDOK,106,275,62,16
+ PUSHBUTTON "Cancel",IDCANCEL,172,275,62,16
+ PUSHBUTTON "Apply",IDC_APPLY,242,275,62,16
+ CONTROL "",IDC_CLIST,"CListControl",0x24a,12,31,286,199,WS_EX_CLIENTEDGE
+ GROUPBOX "Sticky contacts",IDC_STATIC9,8,20,293,215
+ PUSHBUTTON "Clear all",IDC_CLEARALL,13,241,92,14
+ LTEXT "Using the contact list on the left side, you can select contacts which will be ""sticky"" for this view mode. These contacts will ignore the standard filter rules and only use the status mode filter below.",IDC_STATIC10,174,50,124,72,NOT WS_VISIBLE
+ LTEXT "Protocol",IDC_STATIC12,31,206,49,12
+ COMBOBOX IDC_PROTOGROUPOP,85,204,37,56,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ CTEXT "Group",IDC_STATIC13,129,206,44,12
+ COMBOBOX IDC_GROUPSTATUSOP,177,204,37,56,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ RTEXT "Status mode",IDC_STATIC14,221,206,54,12
+ CONTROL "Automatically clear this view mode after",IDC_AUTOCLEAR,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,244,172,11
+ EDITTEXT IDC_AUTOCLEARVAL,222,243,29,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_AUTOCLEARSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,245,243,8,13
+ LTEXT "seconds",IDC_STATIC15,262,244,28,12
+ GROUPBOX "View mode options",IDC_STATIC16,8,195,293,68
+ LTEXT "Editing view mode",IDC_CURVIEWMODE2,119,245,178,14,NOT WS_VISIBLE
+ CONTROL "Last message ",IDC_LASTMSG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,227,86,11
+ COMBOBOX IDC_LASTMESSAGEOP,106,227,81,56,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_LASTMSGVALUE,193,227,31,13,ES_AUTOHSCROLL
+ COMBOBOX IDC_LASTMESSAGEUNIT,229,227,68,56,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_SKIN_TAB DIALOGEX 0, 0, 315, 243
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_SKIN_TAB,"SysTabControl32",0x0,0,0,315,243
+END
+
+IDD_TAB DIALOGEX 0, 0, 315, 243
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_SKIN_TAB,"SysTabControl32",0x0,0,0,315,243
+END
+
+IDD_OPT_SBAR DIALOGEX 0, 0, 308, 231
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | DS_CENTER | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Status Bar",IDC_STATIC,9,3,293,224
+ CONTROL "Show status bar",IDC_SHOWSBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,12,133,10
+ CONTROL "Make sections equal width",IDC_EQUALSECTIONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,27,24,123,10
+ RTEXT "Space between",IDC_STATIC,28,37,60,10
+ EDITTEXT IDC_OFFSETICON3,93,35,48,12,ES_NUMBER
+ CONTROL "",IDC_OFFSETSPIN3,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,131,35,10,12
+ GROUPBOX "Borders",IDC_STATIC,27,47,115,57
+ EDITTEXT IDC_SBAR_BORDER_TOP,73,57,30,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_SBAR_BORDER_TOP_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,93,57,10,12
+ EDITTEXT IDC_OFFSETICON,53,72,30,12,ES_NUMBER
+ CONTROL "",IDC_OFFSETSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,73,72,10,12
+ EDITTEXT IDC_OFFSETICON2,94,72,30,12,ES_NUMBER
+ CONTROL "",IDC_OFFSETSPIN2,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,114,72,10,12
+ EDITTEXT IDC_SBAR_BORDER_BOTTOM,73,88,30,12,ES_AUTOHSCROLL
+ CONTROL "",IDC_SBAR_BORDER_BOTTOM_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,93,88,10,12
+ RTEXT "Vertical Align",IDC_STATIC,27,109,61,10
+ COMBOBOX IDC_SBAR_VERT_ALIGN,93,108,48,48,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ RTEXT "Horizontal Align",IDC_STATIC,27,124,61,10
+ COMBOBOX IDC_SBAR_HORIZ_ALIGN,93,123,48,48,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Multiline status bar:",IDC_STATIC,18,139,133,8
+ RTEXT "Accounts per line",IDC_STATIC,27,150,61,10
+ EDITTEXT IDC_MULTI_COUNT,93,148,48,12,ES_NUMBER
+ CONTROL "",IDC_MULTI_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,129,148,11,12
+ LTEXT "* To increase Status Bar height:\nSet in Main menu: Frames->Status Bar->Show TitleBar then pull appeared title of status bar up or down.",IDC_STATIC,27,163,123,42,WS_DISABLED
+ LTEXT "Hold [Shift] to inverse [Right Click] behaviour",IDC_STATIC,27,207,267,8,WS_DISABLED
+ LTEXT "[Ctrl]+[Left Click] to filter only protocol. Click on empty space to show all",IDC_STATIC,27,216,267,8,WS_DISABLED
+ CONTROL "Set options per account",IDC_STATUSBAR_PER_PROTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,160,12,134,10
+ COMBOBOX IDC_STATUSBAR_PROTO_LIST,160,23,134,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Enable custom account settings",IDC_SBAR_USE_ACCOUNT_SETTINGS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,160,38,124,8
+ CONTROL "Hide account completely",IDC_SBAR_HIDE_ACCOUNT_COMPLETELY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,160,48,134,8
+ CONTROL "Show protocol names",IDC_SHOWPROTO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,160,58,124,8
+ CONTROL "Show status text",IDC_SHOWSTATUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,160,68,124,8
+ CONTROL "Show xStatus Name",IDC_SHOWXSTATUSNAME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,160,78,124,8
+ CONTROL "Show protocol icon",IDC_SHOWICON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,160,88,124,8
+ CONTROL "Use connecting Icon",IDC_USECONNECTINGICON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,98,114,8
+ CONTROL "Show xStatus icon",IDC_SHOWXSTATUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,170,108,124,8
+ CONTROL "Show both icons",IDC_SHOWBOTH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,178,118,116,8
+ CONTROL "Show normal status as overlay",IDC_SHOWNORMAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,178,128,116,8
+ CONTROL "Status overlay opacity is 75% ",IDC_TRANSPARENTOVERLAY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,178,138,116,8
+ CONTROL "Show unread emails (if supported)",IDC_SHOWUNREADEMAIL,
+ "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,160,148,134,16
+ CONTROL "Right click opens status menu",IDC_RIGHTSTATUS,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,160,165,134,8
+ CONTROL "Right click opens Miranda menu",IDC_RIGHTMIRANDA,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,160,175,134,8
+ RTEXT "Space on Left",IDC_STATIC,171,187,60,10
+ EDITTEXT IDC_OFFSETICON_LEFT,237,186,46,12,ES_NUMBER
+ CONTROL "",IDC_OFFSETSPIN_LEFT,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,261,187,10,12
+ RTEXT "Space on right",IDC_STATIC,171,201,60,10
+ EDITTEXT IDC_OFFSETICON_RIGHT,237,200,46,12,ES_NUMBER
+ CONTROL "",IDC_OFFSETSPIN_RIGHT,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,261,201,10,12
+END
+
+IDD_OPT_ITEM_EXTRAICONS DIALOGEX 0, 0, 222, 162
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ GROUPBOX "Contact List Extra Icons",IDC_STATIC,7,19,205,131
+ CONTROL "",IDC_EXTRAORDER,"SysTreeView32",TVS_NOTOOLTIPS | WS_BORDER | WS_TABSTOP,18,36,182,107
+END
+
+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, 302, 202
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | 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,25,124,10
+ CONTROL "Hide empty groups",IDC_HIDEEMPTYGROUPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,37,124,10
+ CONTROL "Disable groups",IDC_DISABLEGROUPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,49,124,10
+ CONTROL "Ask before deleting contacts",IDC_CONFIRMDELETE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,61,124,10
+ CONTROL "Dont move offline user to bottom",IDC_NOOFFLINEMOVE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,153,77,141,10
+ GROUPBOX "Contact List",IDC_STCLISTGROUP,2,8,142,84
+ GROUPBOX "Contact List Sorting",IDC_STATIC,146,8,154,84,WS_GROUP
+ LTEXT "1st:",IDC_STATIC,153,19,14,8
+ LTEXT "2nd:",IDC_STATIC,153,35,14,8
+ LTEXT "3rd:",IDC_STATIC,153,49,14,8
+ COMBOBOX IDC_CLSORT1,169,18,125,146,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_CLSORT2,169,33,125,140,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_CLSORT3,169,48,125,140,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Place offline users out of groups",IDC_OFFLINETOROOT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,153,64,141,10
+ CONTROL "Gamma correction",IDC_GAMMACORRECT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,180,124,10
+ CONTROL "Default",IDC_HILIGHTMODE4,"Button",BS_AUTORADIOBUTTON,12,115,119,10
+ CONTROL "Full selection",IDC_HILIGHTMODE1,"Button",BS_AUTORADIOBUTTON,12,131,119,10
+ CONTROL "Less selection",IDC_HILIGHTMODE2,"Button",BS_AUTORADIOBUTTON,12,147,119,10
+ CONTROL "No selection",IDC_HILIGHTMODE3,"Button",BS_AUTORADIOBUTTON,12,163,119,10
+ GROUPBOX "Selection Mode",IDC_STATIC,2,101,142,95
+END
+
+IDD_OPT_CLUI_2 DIALOGEX 0, 0, 266, 224
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | DS_CENTER | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "Bring to front if covered",IDC_BRINGTOFRONT,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,23,166,8,WS_EX_TRANSPARENT
+ CONTROL "Hide contact list after ",IDC_AUTOHIDE,"Button",BS_AUTOCHECKBOX | BS_TOP | WS_TABSTOP,11,34,94,10
+ EDITTEXT IDC_HIDETIME,108,33,31,12,ES_RIGHT | ES_NUMBER
+ CONTROL "Spin1",IDC_HIDETIMESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,133,32,9,14
+ LTEXT "seconds",IDC_STATIC01,140,35,35,8
+ CONTROL "Automatically resize window to height of list",IDC_AUTOSIZE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,113,237,12,WS_EX_TRANSPARENT
+ LTEXT "maximum",IDC_STATIC21,19,128,38,8
+ EDITTEXT IDC_MAXSIZEHEIGHT,60,126,31,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Spin1",IDC_MAXSIZESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK,92,125,9,14
+ LTEXT "% of screen",IDC_STATIC22,207,128,47,8
+ CONTROL "Size upwards",IDC_AUTOSIZEUPWARD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,143,230,8,WS_EX_TRANSPARENT
+ GROUPBOX "Behaviour",IDC_STWINDOWGROUP2,0,12,258,142,0,WS_EX_TRANSPARENT
+ CONTROL "Lock manual resize",IDC_LOCKSIZING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,102,237,12
+ GROUPBOX "Drag to ",IDC_STATIC,0,158,124,61
+ CONTROL "Easy Scroll",IDC_DRAGTOSCROLL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,181,108,8
+ CONTROL "Easy move",IDC_CLIENTDRAG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,170,108,8
+ COMBOBOX IDC_HIDEMETHOD,93,48,148,73,CBS_DROPDOWNLIST | CBS_DISABLENOSCROLL | WS_TABSTOP
+ EDITTEXT IDC_SHOWDELAY,164,63,36,12,ES_RIGHT | ES_NUMBER
+ CONTROL "",IDC_HIDETIMESPIN2,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,194,61,9,14
+ LTEXT "x100 msec",IDC_STATIC5,206,65,35,8
+ RTEXT "show delay",IDC_STATIC6,94,65,63,8
+ EDITTEXT IDC_HIDEDELAY,164,76,36,12,ES_RIGHT | ES_NUMBER
+ CONTROL "",IDC_HIDETIMESPIN3,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,196,75,9,14
+ LTEXT "x100 msec",IDC_STATIC7,206,78,36,8
+ RTEXT "hide delay",IDC_STATIC8,94,78,63,8
+ LTEXT "Hide method",IDC_STATIC9,23,51,64,8
+ EDITTEXT IDC_HIDEDELAY2,164,89,36,12,ES_RIGHT | ES_NUMBER
+ CONTROL "",IDC_HIDETIMESPIN4,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,196,87,9,14
+ LTEXT "pixels",IDC_STATIC10,206,90,35,8
+ RTEXT "keep on screen",IDC_STATIC13,94,90,63,8
+ CONTROL "Snap to edges",IDC_SNAPTOEDGES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,195,108,8
+ GROUPBOX "Event notify area",IDC_STATIC,128,158,130,61
+ CONTROL "Disabled",IDC_EVENTAREA_NONE,"Button",BS_AUTORADIOBUTTON,138,174,109,8
+ CONTROL "Show automaticaly",IDC_EVENTAREA,"Button",BS_AUTORADIOBUTTON,138,186,106,8
+ CONTROL "Always Visible",IDC_EVENTAREA_ALWAYS,"Button",BS_AUTORADIOBUTTON,138,198,110,8
+ CONTROL "Dock to sides",IDC_DOCKTOSIDES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,206,108,8
+ LTEXT "and minimum",IDC_STATIC24,105,128,50,8
+ EDITTEXT IDC_MINSIZEHEIGHT,160,126,31,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "",IDC_MINSIZESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_HOTTRACK,192,125,9,14
+END
+
+IDD_OPT_CLC DIALOGEX 0, 0, 303, 225
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Items",IDC_STATIC,2,6,298,98
+ CONTROL "Show divider between online and offline contacts",IDC_DIVIDERONOFF,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,17,175,10
+ CONTROL "Hot track items as mouse passes over",IDC_TRACKSELECT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,29,175,10
+ CONTROL "Disable drag and drop of items",IDC_DISABLEDRAGDROP,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,41,175,10
+ CONTROL "Disable rename of items by clicking twice",IDC_NOTEDITLABELS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,53,175,10
+ CONTROL "Show selection even when list is not focused",IDC_SHOWSELALWAYS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,65,175,10
+ CONTROL "Make selection highlight translucent",IDC_NOTNOTRANSLUCENTSEL,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,77,175,10
+ CONTROL "Dim idle contacts",IDC_IDLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,89,153,10
+ LTEXT "'Hide Offline' means to hide:",IDC_STATIC,191,14,104,8
+ CONTROL "Tree1",IDC_HIDEOFFLINEOPTS,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_NOTOOLTIPS | TVS_NONEVENHEIGHT | WS_BORDER | WS_TABSTOP,191,24,105,73
+ GROUPBOX "Groups",IDC_STATIC,2,105,148,115
+ CONTROL "Draw a line alongside group names",IDC_LINEWITHGROUPS,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,114,131,16
+ CONTROL "Show counts of number of contacts in a group",IDC_SHOWGROUPCOUNTS,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,132,131,16
+ CONTROL "Hide group counts when there are none online",IDC_HIDECOUNTSWHENEMPTY,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,150,131,16
+ CONTROL "Sort groups alphabetically",IDC_SORTGROUPSALPHA,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,168,131,16
+ CONTROL "Quicksearch in open groups only",IDC_QUICKSEARCHVISONLY,
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,11,186,131,16
+ LTEXT "Indent groups by:",IDC_STATIC,11,206,67,8
+ EDITTEXT IDC_GROUPINDENT,78,204,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,200,10,14
+ LTEXT "pixels",IDC_STATIC,112,206,36,8
+ GROUPBOX "Visual",IDC_STATIC,156,105,144,115
+ CONTROL "Scroll list smoothly",IDC_NOTNOSMOOTHSCROLLING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,164,115,131,10
+ LTEXT "Time:",IDC_STATIC11,174,129,42,8
+ EDITTEXT IDC_SMOOTHTIME,215,127,31,12,ES_RIGHT | ES_NUMBER
+ CONTROL "Spin1",IDC_SMOOTHTIMESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,237,126,10,14
+ LTEXT "milliseconds",IDC_STATIC12,250,129,45,8,SS_CENTERIMAGE
+ CONTROL "Hide vertical scrollbar",IDC_NOSCROLLBAR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,165,144,130,10
+ CONTROL "Fade out entire list when:",IDC_GREYOUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,165,156,130,10
+ CONTROL "Tree1",IDC_GREYOUTOPTS,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_NOTOOLTIPS | TVS_NONEVENHEIGHT | WS_BORDER | WS_TABSTOP,165,168,130,46
+END
+
+IDD_OPT_TRAY DIALOGEX 0, 0, 296, 152
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "Single click interface",IDC_ONECLK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,19,156,10
+ CONTROL "Always show status in tooltip",IDC_ALWAYSSTATUS,"Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,10,32,156,11
+ CONTROL "Disable icon blinking",IDC_DISABLEBLINK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,45,156,9
+ EDITTEXT IDC_BLINKTIME,12,59,35,12,ES_NUMBER
+ CONTROL "",IDC_BLINKSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,48,58,11,12
+ LTEXT "ms, delay between icon blinking",IDC_STATIC,62,61,104,8
+ CONTROL "Show",IDC_DONTCYCLE,"Button",BS_AUTORADIOBUTTON | WS_GROUP,10,94,97,10
+ COMBOBOX IDC_PRIMARYSTATUS,107,94,78,101,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Cycle icons every",IDC_CYCLE,"Button",BS_AUTORADIOBUTTON,10,110,97,10
+ EDITTEXT IDC_CYCLETIME,107,110,29,12,ES_RIGHT | ES_NUMBER
+ CONTROL "",IDC_CYCLETIMESPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,136,109,11,14
+ LTEXT "seconds, when statuses differ",IDC_STATIC,151,110,132,8,NOT WS_GROUP
+ CONTROL "Show multiple icons",IDC_MULTITRAY,"Button",BS_AUTORADIOBUTTON,10,126,97,10
+ CONTROL "Only when statuses differ",IDC_ALWAYSMULTI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,107,126,181,10
+ GROUPBOX "System tray icon",IDC_STATIC,2,6,292,73
+ GROUPBOX "System tray icon mode",IDC_STATIC,2,80,292,61
+ CONTROL "Use xStatus icon",IDC_SHOWXSTATUS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,171,19,117,10
+ CONTROL "Show normal status as overlay",IDC_SHOWNORMAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,171,30,117,10
+ CONTROL "Status overlay opacity is 75% ",IDC_TRANSPARENTOVERLAY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,171,43,117,10
+ CONTROL "only when statuses differ",IDC_ALWAYSPRIMARY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,190,94,98,10
+END
+
+IDD_OPT_META_CLC DIALOGEX 0, 0, 225, 173
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "Ignore Empty Extra icons places (arrange to right).",IDC_METASUBEXTRA_IGN,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,29,201,10
+ CONTROL "Use 'Meta' protocol icons for Metacontacts",IDC_META,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,85,201,10
+ CONTROL "Expand metacontacts",IDC_METAEXPAND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,97,201,16
+ CONTROL "Avoid doubleclick expand",IDC_METADBLCLK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,114,196,10
+ CONTROL "Hide all 'Extra icons' for subcontacts",IDC_METASUBEXTRA,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,127,196,10
+ CONTROL "Hide offline subcontacts.",IDC_METASUB_HIDEOFFLINE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,141,196,10
+ GROUPBOX "MetaContacts stuff",IDC_FRAME_META,2,71,218,101
+ GROUPBOX "Additional stuff",IDC_FRAME_META2,2,16,218,53
+ CTEXT "For other stuff MetaContacts plugin should be loaded.\n\nhttp://miranda-im.org/download",IDC_FRAME_META_CAPT,11,87,201,26,NOT WS_VISIBLE
+ CONTROL "Allow internal requesting of away message text",IDC_DISCOVER_AWAYMSG,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,42,201,10
+ EDITTEXT IDC_SUBINDENT,154,153,35,12,ES_NUMBER
+ CONTROL "",IDC_SUBINDENTSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,190,152,11,12
+ LTEXT "Subcontacts indent:",IDC_SUBIDENTCAPT,26,154,126,10
+ CONTROL "Remove away message if contact became offline",IDC_REMOVE_OFFLINE_AWAYMSG,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,54,201,10
+END
+
+IDD_OPT_ITEM_CONTACT_TIME DIALOGEX 0, 0, 243, 52
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ CONTROL "Show time only if it is different from current time",IDC_SHOW_ONLY_IF_DIFFERENT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,38,217,8
+ CONTROL "Show contact time as row item",IDC_SHOW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,25,217,8
+END
+
+IDD_OPT_CLUI DIALOGEX 0, 0, 307, 214
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | DS_CENTER | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Appearance",IDC_STWINDOWGROUP,4,11,115,37
+ CONTROL "Always on top",IDC_ONTOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,21,102,8
+ CONTROL "Pin to desktop",IDC_ONDESKTOP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,33,102,8
+ GROUPBOX "Client area margins",IDC_FRAME_META2,124,80,179,45
+ EDITTEXT IDC_LEFTMARGIN,152,98,33,12,ES_NUMBER
+ CONTROL "",IDC_LEFTMARGINSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,174,99,10,12
+ EDITTEXT IDC_RIGHTMARGIN,247,98,33,12,ES_NUMBER
+ CONTROL "",IDC_RIGHTMARGINSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,270,99,10,12
+ EDITTEXT IDC_TOPMARGIN,200,91,33,12,ES_NUMBER
+ CONTROL "",IDC_TOPMARGINSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,219,89,10,12
+ EDITTEXT IDC_BOTTOMMARGIN,200,104,33,12,ES_NUMBER
+ CONTROL "",IDC_BOTTOMMARGINSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,226,106,10,12
+ CONTROL "Thin border main window",IDC_BORDER,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,13,177,102,8
+ CONTROL "Borderless main window",IDC_NOBORDERWND,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,13,165,102,8
+ CONTROL "Show menu bar",IDC_SHOWMAINMENU,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,13,153,102,8
+ CONTROL "Show title bar",IDC_SHOWCAPTION,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,13,141,102,8
+ LTEXT "Title bar text:",IDC_TITLEBAR_STATIC,13,87,102,8,WS_DISABLED
+ EDITTEXT IDC_TITLETEXT,23,97,92,12,ES_AUTOHSCROLL | WS_DISABLED
+ CONTROL "Tool style main window",IDC_TOOLWND,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,13,129,102,8
+ CONTROL "Minimize to tray",IDC_MIN2TRAY,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,13,117,102,8
+ GROUPBOX "Translucency options (Windows 2000/XP only)",-1,124,124,179,86
+ CONTROL "Fade contact list in/out",IDC_FADEINOUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,129,136,133,10
+ CONTROL "Transparent contact list",IDC_TRANSPARENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,129,147,133,9
+ LTEXT "Inactive opacity:",IDC_STATIC11,130,160,67,8
+ CONTROL "Slider2",IDC_TRANSINACTIVE,"msctls_trackbar32",TBS_TOP | TBS_NOTICKS | WS_TABSTOP,197,156,64,14
+ LTEXT "000%",IDC_INACTIVEPERC,267,159,25,8,SS_NOPREFIX
+ LTEXT "Active opacity:",IDC_STATIC12,130,173,67,8
+ CONTROL "Slider2",IDC_TRANSACTIVE,"msctls_trackbar32",TBS_TOP | TBS_NOTICKS | WS_TABSTOP,197,170,64,14
+ LTEXT "000%",IDC_ACTIVEPERC,267,174,25,8,SS_NOPREFIX
+ CONTROL "Enable drop shadow (restart required)",IDC_DROPSHADOW,
+ "Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,130,186,166,10
+ GROUPBOX "Frames",-1,124,11,179,65
+ RTEXT "Between frames:",-1,152,48,86,10
+ EDITTEXT IDC_FRAMESGAP,238,45,26,12,ES_RIGHT | ES_NUMBER
+ CONTROL "",IDC_FRAMESSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,233,45,10,14
+ RTEXT "After captions:",-1,152,59,86,10
+ EDITTEXT IDC_CAPTIONSGAP,238,59,26,12,ES_RIGHT | ES_NUMBER
+ CONTROL "",IDC_CAPTIONSSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,233,59,10,14
+ LTEXT "pixels",IDC_STATIC3,266,60,21,8
+ LTEXT "pixels",IDC_STATIC2,266,46,21,8
+ LTEXT "Gaps",-1,133,37,38,9
+ CONTROL "Use Non-Layered mode",IDC_LAYERENGINE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,13,74,102,11
+ CONTROL "Round corners",IDC_ROUNDCORNERS,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,13,189,102,8
+ GROUPBOX "Non-layered mode",IDC_STWINDOWGROUP3,4,51,115,159
+ CONTROL "Disable Skin Engine",IDC_DISABLEENGINE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,13,60,102,11
+ CONTROL "Enable Aero Glass (Vista)",IDC_AEROGLASS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,130,197,166,10
+END
+
+IDD_OPT_ITEM_ROW DIALOGEX 0, 0, 178, 222
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | DS_CENTER | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LISTBOX IDC_LIST_ORDER,7,26,128,52,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Order of items:",IDC_STATIC,7,13,117,10
+ LTEXT "Min row height:",IDC_STATIC,7,90,50,8
+ LTEXT "pixels",IDC_STATIC,111,92,54,8
+ LTEXT "Row border:",IDC_STATIC,7,104,44,8
+ LTEXT "pixels",IDC_STATIC,111,105,54,8
+ EDITTEXT IDC_MIN_ROW_HEIGHT,65,90,35,12,ES_NUMBER
+ CONTROL "",IDC_MIN_ROW_HEIGHT_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,98,90,11,12
+ EDITTEXT IDC_ROW_BORDER,65,103,35,12,ES_NUMBER
+ CONTROL "",IDC_ROW_BORDER_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,99,104,11,12
+ CONTROL "Variable row height",IDC_VARIABLE_ROW_HEIGHT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,148,126,10
+ CONTROL "Align left items to left",IDC_ALIGN_TO_LEFT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,160,126,10
+ CONTROL "Align right items to right",IDC_ALIGN_TO_RIGHT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,171,126,10
+ PUSHBUTTON "Up",IDC_UP,140,26,31,12
+ PUSHBUTTON "Down",IDC_DOWN,140,39,31,12
+ LTEXT "Left margin:",IDC_STATIC,7,118,52,8
+ EDITTEXT IDC_LEFTMARGIN,65,116,35,12,ES_NUMBER
+ CONTROL "",IDC_LEFTMARGINSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,100,117,11,14
+ LTEXT "pixels",IDC_STATIC,111,118,54,8
+ LTEXT "Right margin:",IDC_STATIC,7,132,52,8
+ EDITTEXT IDC_RIGHTMARGIN,65,129,35,12,ES_NUMBER
+ CONTROL "",IDC_RIGHTMARGINSPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,100,127,11,14
+ LTEXT "pixels",IDC_STATIC,111,131,54,8
+ CONTROL "Compact mode\n(Show avatars and additional text\non selected contacts only)",IDC_MINIMODE,
+ "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,8,183,164,28
+END
+
+IDD_OPT_ITEM_AVATAR DIALOGEX 0, 0, 260, 191
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "Draw border on avatar",IDC_AVATAR_DRAW_BORDER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,50,246,9
+ CONTROL "Show Avatars",IDC_SHOW_AVATARS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,14,246,8
+ CONTROL "Draw overlay icons",IDC_AVATAR_OVERLAY_ICONS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,137,246,8
+ LTEXT "Size:",IDC_AVATAR_SIZE_L,7,121,34,8
+ EDITTEXT IDC_AVATAR_SIZE,170,120,35,12,ES_NUMBER
+ CONTROL "",IDC_AVATAR_SIZE_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,194,120,11,12
+ CONTROL "Round corners of avatars",IDC_AVATAR_ROUND_CORNERS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,80,246,8
+ CONTROL "Ignore size for row height calcs",IDC_AVATAR_IGNORE_SIZE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,108,246,8
+ LTEXT "Border Color:",IDC_AVATAR_BORDER_COLOR_L,20,64,53,10
+ CONTROL "",IDC_AVATAR_BORDER_COLOR,"ColourPicker",WS_TABSTOP,77,62,17,13
+ CONTROL "Custom corner size:",IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,92,78,11
+ EDITTEXT IDC_AVATAR_CUSTOM_CORNER_SIZE,97,91,35,12,ES_NUMBER
+ CONTROL "",IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,125,91,11,12
+ CONTROL "Normal overlay icon",IDC_AVATAR_OVERLAY_ICON_NORMAL,
+ "Button",BS_AUTORADIOBUTTON,29,150,224,8
+ CONTROL "Protocol status icon",IDC_AVATAR_OVERLAY_ICON_PROTOCOL,
+ "Button",BS_AUTORADIOBUTTON,29,161,224,8
+ CONTROL "Contact icon",IDC_AVATAR_OVERLAY_ICON_CONTACT,"Button",BS_AUTORADIOBUTTON,29,172,186,8
+ LTEXT "pixels",IDC_AVATAR_SIZE_PIXELS2,210,122,18,8
+ RTEXT "height",IDC_AVATAR_SIZE_PIXELS3,121,121,44,8
+ EDITTEXT IDC_AVATAR_WIDTH,78,120,35,12,ES_NUMBER
+ CONTROL "",IDC_AVATAR_WIDTH_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,102,120,11,12
+ RTEXT "Max width",IDC_AVATAR_SIZE_PIXELS,31,122,44,8
+ CONTROL "Animate Avatars",IDC_SHOW_ANIAVATARS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,26,246,8
+ CONTROL "Use old render method (Fast, but has artefacts)",IDC_AVATAR_FASTDRAW,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,37,232,8
+END
+
+IDD_OPT_ITEM_ICON DIALOGEX 0, 0, 260, 140
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "Hide icon when showing avatar",IDC_HIDE_ICON_ON_AVATAR,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,24,246,8
+ CONTROL "Ignore size for row height calcs",IDC_NOTCHECKICONSIZE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,61,246,8
+ CONTROL "Draw icon in avatar space",IDC_DRAW_ON_AVATAR_SPACE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,36,234,8
+ CONTROL "Disable icon blinking",IDC_ICONBLINK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,47,246,10
+ CONTROL "Hide groups icon",IDC_HIDE_GROUPSICON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,75,127,8
+ CONTROL "Always show ""Always visibile"" icon",IDC_ALWAYS_VISIBLEICON,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,88,127,8
+ CONTROL "Use extra status icon instead protocol",IDC_USEXSTATUS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,101,236,8
+ CONTROL "Draw normal status as overlay",IDC_DRAWSTATUSOVERLAY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,114,222,8
+END
+
+IDD_OPT_ITEM_TEXT DIALOGEX 0, 0, 260, 160
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "Right-To-Left reading mode (mirror template)",IDC_RTL,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,42,246,8
+ CONTROL "Replace smileys in clist",IDC_REPLACE_SMILEYS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,81,246,8
+ CONTROL "Use protocol smileys",IDC_USE_PROTOCOL_SMILEYS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,94,232,8
+ CONTROL "Draw smileys on first line",IDC_DRAW_SMILEYS_ON_FIRST_LINE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,119,246,8
+ CONTROL "Ignore size for row height calcs",IDC_IGNORE_SIZE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,68,246,8
+ CONTROL "Resize smileys and 'Listining to' icon",IDC_RESIZE_SMILEYS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,107,232,8
+ CONTROL "Align to right",IDC_ALIGN_RIGHT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,55,246,8
+ COMBOBOX IDC_ALIGNGROUPCOMBO,6,24,140,45,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Append nick if different from custom name",IDC_APPEND_NICK,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,131,246,8
+ CONTROL "Trim long text with ellipsis",IDC_TRIM_TEXT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,143,246,8
+END
+
+IDD_OPT_ITEM_SECOND_LINE DIALOGEX 0, 0, 256, 231
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "Show second line",IDC_SHOW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,16,242,8
+ LTEXT "Top space:",IDC_STATIC_TOP,7,37,40,8
+ EDITTEXT IDC_TOP_SPACE,50,35,35,12,ES_NUMBER
+ CONTROL "",IDC_TOP_SPACE_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,84,35,11,12
+ LTEXT "pixels",IDC_STATIC_PIXELS,96,37,18,8
+ CONTROL "Draw smileys on second line",IDC_DRAW_SMILEYS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,52,242,8
+ LTEXT "Text:",IDC_STATIC_TEXT,7,67,83,9
+ CONTROL "Status",IDC_STATUS,"Button",BS_AUTORADIOBUTTON,18,79,118,8
+ CONTROL "Nickname",IDC_NICKNAME,"Button",BS_AUTORADIOBUTTON,18,90,118,8
+ CONTROL "Away Message",IDC_STATUS_MESSAGE,"Button",BS_AUTORADIOBUTTON,18,101,118,8
+ CONTROL "Listening to",IDC_LISTENING_TO,"Button",BS_AUTORADIOBUTTON,18,112,118,8
+ CONTROL "Contact time",IDC_CONTACT_TIME,"Button",BS_AUTORADIOBUTTON,18,123,118,8
+ CONTROL "Text:",IDC_TEXT,"Button",BS_AUTORADIOBUTTON,18,134,118,8
+ EDITTEXT IDC_VARIABLE_TEXT,32,149,217,73,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
+ CONTROL "Show status if there isn't away message",IDC_SHOW_STATUS_IF_NOAWAY,
+ "Button",BS_AUTOCHECKBOX | BS_LEFT | BS_TOP | BS_MULTILINE | WS_TABSTOP,150,76,99,18
+ CONTROL "Show listening to if there isn't away message",IDC_SHOW_LISTENING_IF_NOAWAY,
+ "Button",BS_AUTOCHECKBOX | BS_LEFT | BS_TOP | BS_MULTILINE | WS_TABSTOP,150,94,99,18
+ CONTROL "XStatus has priority",IDC_XSTATUS_HAS_PRIORITY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,150,111,99,12
+ CONTROL "Use 'XStatus: XMessage'",IDC_USE_NAME_AND_MESSAGE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,150,122,99,12
+ RTEXT "(Variables will be replaced)",IDC_VARIABLES_L,141,136,108,8
+END
+
+IDD_OPT_ITEM_THIRD_LINE DIALOGEX 0, 0, 256, 227
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "Show third line",IDC_SHOW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,16,242,8
+ LTEXT "Top space:",IDC_STATIC_TOP,7,37,40,8
+ EDITTEXT IDC_TOP_SPACE,50,35,35,12,ES_NUMBER
+ CONTROL "",IDC_TOP_SPACE_SPIN,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,84,35,11,12
+ LTEXT "pixels",IDC_STATIC_PIXELS,96,37,18,8
+ CONTROL "Draw smileys on third line",IDC_DRAW_SMILEYS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,52,242,8
+ LTEXT "Text:",IDC_STATIC_TEXT,7,67,83,9
+ CONTROL "Status",IDC_STATUS,"Button",BS_AUTORADIOBUTTON,18,79,118,8
+ CONTROL "Nickname",IDC_NICKNAME,"Button",BS_AUTORADIOBUTTON,18,90,118,8
+ CONTROL "Away Message",IDC_STATUS_MESSAGE,"Button",BS_AUTORADIOBUTTON,18,101,118,8
+ CONTROL "Listening to",IDC_LISTENING_TO,"Button",BS_AUTORADIOBUTTON,18,112,118,8
+ CONTROL "Contact time",IDC_CONTACT_TIME,"Button",BS_AUTORADIOBUTTON,18,123,118,8
+ CONTROL "Text:",IDC_TEXT,"Button",BS_AUTORADIOBUTTON,18,134,118,8
+ EDITTEXT IDC_VARIABLE_TEXT,32,150,217,73,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
+ CONTROL "Show status if there isn't away message",IDC_SHOW_STATUS_IF_NOAWAY,
+ "Button",BS_AUTOCHECKBOX | BS_LEFT | BS_TOP | BS_MULTILINE | WS_TABSTOP,150,76,99,18
+ CONTROL "Show listening to if there isn't away message",IDC_SHOW_LISTENING_IF_NOAWAY,
+ "Button",BS_AUTOCHECKBOX | BS_LEFT | BS_TOP | BS_MULTILINE | WS_TABSTOP,150,94,99,18
+ CONTROL "XStatus has priority",IDC_XSTATUS_HAS_PRIORITY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,150,111,99,12
+ CONTROL "Use 'XStatus: XMessage'",IDC_USE_NAME_AND_MESSAGE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,150,122,99,12
+ RTEXT "(Variables will be replaced)",IDC_VARIABLES_L,141,136,108,8
+END
+
+IDD_OPT_EXTFRAMES DIALOGEX 0, 0, 304, 220
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ PUSHBUTTON "Up",IDC_BUTTON_UP,7,189,36,12,WS_DISABLED
+ PUSHBUTTON "Down",IDC_BUTTON_DOWN,52,189,36,12,WS_DISABLED
+ GROUPBOX "Preview",IDC_STATIC,187,28,115,179,WS_TABSTOP
+ CONTROL "Top/Left",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,106,38,43,10
+ CONTROL "Bottom/Right",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,106,49,68,10
+ GROUPBOX "Position (vertical)",IDC_STATIC,101,28,81,33,WS_TABSTOP
+ GROUPBOX "Align",IDC_STATIC,100,68,82,55,WS_TABSTOP
+ CONTROL "",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,120,83,10,9
+ CONTROL "",IDC_RADIO6,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,136,83,10,9
+ CONTROL "",IDC_RADIO7,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,152,83,10,9
+ CONTROL "",IDC_RADIO8,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,120,94,10,9
+ CONTROL "",IDC_RADIO9,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,136,94,10,9
+ CONTROL "",IDC_RADIO10,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,152,94,10,9
+ CONTROL "",IDC_RADIO11,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,120,105,10,9
+ CONTROL "",IDC_RADIO12,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,136,105,10,9
+ CONTROL "",IDC_RADIO13,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,152,105,10,9
+ GROUPBOX "Options",IDC_STATIC,101,127,81,80,WS_TABSTOP
+ CONTROL "Visible",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,106,142,68,10
+ CONTROL "Show Title",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,106,154,68,10
+ CONTROL "Locked",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,106,166,68,10
+ CONTROL "Border",IDC_CHECK10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,106,178,68,10
+ CONTROL "Floating",IDC_CHECK11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,106,190,68,10
+ GROUPBOX "Frames Order",IDC_STATIC,2,28,93,179,WS_TABSTOP
+ CTEXT "UNDER CONSTRUCTION!!! IT DOES NOT WORK",IDC_STATIC,46,4,201,18,SS_CENTERIMAGE | WS_BORDER,WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE
+ LISTBOX IDC_EXTRAORDER,7,41,81,142,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ CONTROL "",IDC_PREVIEW,"Static",SS_OWNERDRAW,195,42,99,160
+END
+
+IDD_OPT_ROWTMPL DIALOGEX 0, 0, 299, 207
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ GROUPBOX "Row template",IDC_STATIC,0,7,295,194
+ CONTROL "",IDC_ROWTREE,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP,3,18,131,140
+ PUSHBUTTON "Add container",IDC_ADDCONTAINER,3,179,63,15
+ PUSHBUTTON "Remove container",IDC_DELCONTAINER,71,179,63,15
+ GROUPBOX "Settings",IDC_STATIC,140,81,150,113
+ LTEXT "Vertical align:",IDC_STATIC,147,111,60,8
+ LTEXT "Horizontal align:",IDC_STATIC,147,128,60,8
+ COMBOBOX IDC_VALIGN,211,109,71,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_HALIGN,211,126,71,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_CONTTYPE,211,91,71,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Container type:",IDC_STATIC,147,93,60,8
+ EDITTEXT IDC_CONTWIDTH,226,143,56,14,ES_AUTOHSCROLL
+ CONTROL "",IDC_SPINCONTWIDTH,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,276,143,9,14
+ EDITTEXT IDC_CONTHEIGHT,226,161,56,14,ES_AUTOHSCROLL
+ CONTROL "",IDC_SPINCONTHEIGHT,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,276,161,9,14
+ LTEXT "Container width:",IDC_STATIC,147,145,54,8
+ LTEXT "Container height:",IDC_STATIC,147,162,57,8
+ CONTROL "Layered",IDC_CONTLAYER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,147,179,135,10
+ PUSHBUTTON "Move up",IDC_CONTUP,3,161,63,14,WS_DISABLED
+ PUSHBUTTON "Move down",IDC_CONTDOWN,71,161,63,14,WS_DISABLED
+ CTEXT "OPTION PAGE IS UNDER CONSTRUCTION Please DO NOT notice about any issues here.\n Only high-level design comments are applicable.",IDC_STATIC,3,0,291,18
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_OPT_SKINEDITOR, DIALOG
+ BEGIN
+ TOPMARGIN, 1
+ BOTTOMMARGIN, 219
+ HORZGUIDE, 22
+ HORZGUIDE, 35
+ HORZGUIDE, 55
+ HORZGUIDE, 76
+ HORZGUIDE, 172
+ HORZGUIDE, 201
+ HORZGUIDE, 207
+ END
+
+ IDD_SKIN_TAB, DIALOG
+ BEGIN
+ RIGHTMARGIN, 298
+ END
+
+ IDD_TAB, DIALOG
+ BEGIN
+ RIGHTMARGIN, 298
+ END
+
+ IDD_OPT_SBAR, DIALOG
+ BEGIN
+ RIGHTMARGIN, 297
+ VERTGUIDE, 17
+ VERTGUIDE, 27
+ VERTGUIDE, 88
+ VERTGUIDE, 93
+ VERTGUIDE, 150
+ VERTGUIDE, 160
+ VERTGUIDE, 170
+ VERTGUIDE, 178
+ VERTGUIDE, 294
+ BOTTOMMARGIN, 228
+ HORZGUIDE, 19
+ END
+
+ IDD_OPT_ITEM_EXTRAICONS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 212
+ VERTGUIDE, 18
+ VERTGUIDE, 200
+ TOPMARGIN, 5
+ BOTTOMMARGIN, 155
+ END
+
+ IDD_DELETECONTACT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 277
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 85
+ END
+
+ IDD_OPT_CLIST, DIALOG
+ BEGIN
+ LEFTMARGIN, 2
+ RIGHTMARGIN, 300
+ VERTGUIDE, 10
+ VERTGUIDE, 107
+ VERTGUIDE, 136
+ VERTGUIDE, 146
+ VERTGUIDE, 171
+ VERTGUIDE, 294
+ VERTGUIDE, 300
+ TOPMARGIN, 2
+ BOTTOMMARGIN, 199
+ HORZGUIDE, 86
+ HORZGUIDE, 93
+ END
+
+ IDD_OPT_CLUI_2, DIALOG
+ BEGIN
+ LEFTMARGIN, 4
+ RIGHTMARGIN, 263
+ VERTGUIDE, 13
+ VERTGUIDE, 23
+ VERTGUIDE, 75
+ VERTGUIDE, 124
+ VERTGUIDE, 128
+ VERTGUIDE, 136
+ VERTGUIDE, 142
+ VERTGUIDE, 164
+ VERTGUIDE, 258
+ TOPMARGIN, 4
+ HORZGUIDE, 14
+ HORZGUIDE, 36
+ HORZGUIDE, 141
+ HORZGUIDE, 148
+ HORZGUIDE, 194
+ END
+
+ IDD_OPT_CLC, DIALOG
+ BEGIN
+ LEFTMARGIN, 2
+ RIGHTMARGIN, 301
+ VERTGUIDE, 11
+ VERTGUIDE, 164
+ VERTGUIDE, 186
+ VERTGUIDE, 216
+ VERTGUIDE, 295
+ VERTGUIDE, 300
+ TOPMARGIN, 2
+ BOTTOMMARGIN, 221
+ HORZGUIDE, 145
+ HORZGUIDE, 163
+ END
+
+ IDD_OPT_TRAY, DIALOG
+ BEGIN
+ LEFTMARGIN, 4
+ RIGHTMARGIN, 291
+ BOTTOMMARGIN, 149
+ END
+
+ IDD_OPT_META_CLC, DIALOG
+ BEGIN
+ LEFTMARGIN, 2
+ RIGHTMARGIN, 220
+ VERTGUIDE, 11
+ VERTGUIDE, 16
+ VERTGUIDE, 212
+ TOPMARGIN, 2
+ BOTTOMMARGIN, 168
+ END
+
+ IDD_OPT_ITEM_CONTACT_TIME, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 236
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 35
+ END
+
+ IDD_OPT_CLUI, DIALOG
+ BEGIN
+ LEFTMARGIN, 4
+ RIGHTMARGIN, 304
+ VERTGUIDE, 13
+ VERTGUIDE, 23
+ VERTGUIDE, 75
+ VERTGUIDE, 115
+ VERTGUIDE, 119
+ VERTGUIDE, 136
+ VERTGUIDE, 142
+ VERTGUIDE, 164
+ VERTGUIDE, 230
+ VERTGUIDE, 234
+ VERTGUIDE, 303
+ TOPMARGIN, 4
+ BOTTOMMARGIN, 210
+ HORZGUIDE, 14
+ HORZGUIDE, 36
+ END
+
+ IDD_OPT_ITEM_ROW, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 171
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 215
+ END
+
+ IDD_OPT_ITEM_AVATAR, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 253
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 184
+ END
+
+ IDD_OPT_ITEM_ICON, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 253
+ VERTGUIDE, 243
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 133
+ END
+
+ IDD_OPT_ITEM_TEXT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 253
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 151
+ END
+
+ IDD_OPT_ITEM_SECOND_LINE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 249
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 224
+ END
+
+ IDD_OPT_ITEM_THIRD_LINE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 249
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 205
+ END
+
+ IDD_OPT_EXTFRAMES, DIALOG
+ BEGIN
+ LEFTMARGIN, 2
+ RIGHTMARGIN, 302
+ TOPMARGIN, 4
+ BOTTOMMARGIN, 217
+ END
+
+ IDD_OPT_ROWTMPL, DIALOG
+ BEGIN
+ VERTGUIDE, 14
+ VERTGUIDE, 77
+ VERTGUIDE, 82
+ VERTGUIDE, 145
+ VERTGUIDE, 151
+ VERTGUIDE, 158
+ VERTGUIDE, 211
+ VERTGUIDE, 282
+ TOPMARGIN, 1
+ BOTTOMMARGIN, 201
+ HORZGUIDE, 7
+ HORZGUIDE, 17
+ HORZGUIDE, 81
+ HORZGUIDE, 157
+ HORZGUIDE, 161
+ HORZGUIDE, 175
+ HORZGUIDE, 179
+ HORZGUIDE, 194
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// TGA
+//
+
+IDR_TGA_DEFAULT_SKIN TGA "Back.tga"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// MSF
+//
+
+IDR_MSF_DEFAULT_SKIN MSF "skin.msf"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 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 "&Show Offline Users in here", POPUP_GROUPSHOWOFFLINE
+ MENUITEM SEPARATOR
+ MENUITEM "&Rename Group", POPUP_RENAMEGROUP
+ MENUITEM "&Delete Group", POPUP_DELETEGROUP
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog Info
+//
+
+IDD_OPT_CLUI_2 DLGINIT
+BEGIN
+ IDC_HIDEMETHOD, 0x403, 9, 0
+0x6f63, 0x706d, 0x656c, 0x6574, "\000"
+ 0
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "..\src\resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include <winresrc.h>\r\n"
+ "#include ""..\src\hdr\modern_statusmodes.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Neutral resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
diff --git a/plugins/Clist_modern/res/version.rc b/plugins/Clist_modern/res/version.rc
new file mode 100644
index 0000000000..afc9b038c9
--- /dev/null
+++ b/plugins/Clist_modern/res/version.rc
@@ -0,0 +1,40 @@
+#ifdef APSTUDIO_INVOKED
+#error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+#include <winresrc.h>
+#include "..\src\version.h"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION FILE_VERSION
+ PRODUCTVERSION PRODUCT_VERSION
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Comments", "Licensed under the terms of the GNU General Public License"
+ VALUE "CompanyName", " "
+ VALUE "FileDescription", "Miranda IM Contact List. Display contacts, event notifications, protocol status with advantage visual modifications. Supported MW modifications, enchanced metacontact cooperation."
+ VALUE "FileVersion", FILE_VERSION_STR
+ VALUE "InternalName", "Modern Contact List"
+ VALUE "LegalCopyright", "Copyright © 2000-2005 Artem Shpynov, Richard Hughes, Roland Rabien, Tristan Van de Vreede, Martin Oberg, Robert Rainwater, Sam Kothari and Lyon Lim"
+ VALUE "OriginalFilename", "clist_modern.dll"
+ VALUE "ProductName", "Miranda IM Contact List. Display contacts, event notifications, protocol status with advantage visual modifications. Supported MW modifications, enchanced metacontact cooperation."
+ VALUE "ProductVersion", PRODUCT_VERSION_STR
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
diff --git a/plugins/Clist_modern/src/MString.cpp b/plugins/Clist_modern/src/MString.cpp
new file mode 100644
index 0000000000..caba4e022c
--- /dev/null
+++ b/plugins/Clist_modern/src/MString.cpp
@@ -0,0 +1,205 @@
+
+#include <windows.h>
+#include <stdio.h>
+#include <win2k.h>
+#include "hdr/MString.h"
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CMBaseString
+
+CNilMStringData CMBaseString::m_nil;
+
+CMStringData* CMBaseString::Allocate( int nChars, int nCharSize )
+{
+ CMStringData* pData;
+ nChars++; // nil char
+ size_t nDataBytes = nCharSize * nChars;
+ size_t nTotalSize = nDataBytes + sizeof(CMStringData);
+
+ pData = static_cast<CMStringData*>(malloc(nTotalSize));
+ if (pData == NULL)
+ return NULL;
+
+ pData->nRefs = 1;
+ pData->nAllocLength = nChars - 1;
+ pData->nDataLength = 0;
+ return pData;
+}
+
+void CMBaseString::Free(CMStringData* pData)
+{
+ free(pData);
+}
+
+CMStringData* CMBaseString::Realloc(CMStringData* pData, int nChars, int nCharSize)
+{
+ CMStringData* pNewData;
+ nChars++; // nil char
+ ULONG nDataBytes = nCharSize * nChars;
+ ULONG nTotalSize = nDataBytes + sizeof(CMStringData);
+
+ pNewData = static_cast<CMStringData*>(realloc(pData, nTotalSize));
+ if (pNewData == NULL)
+ return NULL;
+
+ pNewData->nAllocLength = nChars - 1;
+ return pNewData;
+}
+
+CMStringData* CMBaseString::GetNilString()
+{
+ m_nil.AddRef();
+ return &m_nil;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CMStringData
+
+void* CMStringData::data()
+{
+ return (this + 1);
+}
+
+void CMStringData::AddRef()
+{
+ InterlockedIncrement(&nRefs);
+}
+
+bool CMStringData::IsLocked() const
+{
+ return nRefs < 0;
+}
+
+bool CMStringData::IsShared() const
+{
+ return (nRefs > 1);
+}
+
+void CMStringData::Lock()
+{
+ nRefs--; // Locked buffers can't be shared, so no interlocked operation necessary
+ if ( nRefs == 0 )
+ nRefs = -1;
+}
+
+void CMStringData::Release()
+{
+ if (InterlockedDecrement(&nRefs) <= 0)
+ CMBaseString::Free(this);
+}
+
+void CMStringData::Unlock()
+{
+ if (IsLocked())
+ {
+ nRefs++; // Locked buffers can't be shared, so no interlocked operation necessary
+ if (nRefs == 0)
+ nRefs = 1;
+ }
+}
+
+CNilMStringData::CNilMStringData()
+{
+ nRefs = 2; // Never gets freed
+ nDataLength = 0;
+ nAllocLength = 0;
+ achNil[0] = 0;
+ achNil[1] = 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// ChTraitsCRT<wchar_t>
+
+#if _MSC_VER < 1400
+static HINSTANCE hCrt = NULL;
+
+typedef int ( __cdecl *_vscprintf_func )( LPCSTR pszFormat, va_list args );
+static _vscprintf_func _vscprintf_ptr = NULL;
+
+typedef int ( __cdecl *_vscwprintf_func )( LPCWSTR pszFormat, va_list args );
+static _vscwprintf_func _vscwprintf_ptr = NULL;
+
+typedef int ( __cdecl *_vsnprintf_func )( char*, size_t, const char*, va_list );
+static _vsnprintf_func _vsnprintf_ptr = NULL;
+
+typedef int ( __cdecl *_vsnwprintf_func )( wchar_t *, size_t, const wchar_t *, va_list );
+static _vsnwprintf_func _vsnwprintf_ptr = NULL;
+
+typedef int ( __cdecl *vswprintf_func )( wchar_t *, size_t, const wchar_t *, va_list );
+static vswprintf_func vswprintf_ptr = NULL;
+
+typedef int ( __cdecl *vsprintf_func )( char*, size_t, const char*, va_list );
+static vsprintf_func vsprintf_ptr = NULL;
+
+static void checkCrt( void )
+{
+ if ( hCrt == NULL ) {
+ hCrt = GetModuleHandleA( "msvcrt.dll" );
+ _vscprintf_ptr = (_vscprintf_func)GetProcAddress( hCrt, "_vscprintf" );
+ _vscwprintf_ptr = (_vscwprintf_func)GetProcAddress( hCrt, "_vscwprintf" );
+ _vsnprintf_ptr = (_vsnprintf_func)GetProcAddress( hCrt, "_vsnprintf" );
+ _vsnwprintf_ptr = (_vsnwprintf_func)GetProcAddress( hCrt, "_vsnwprintf" );
+ vswprintf_ptr = (vswprintf_func)GetProcAddress( hCrt, "vswprintf" );
+ vsprintf_ptr = (vsprintf_func)GetProcAddress( hCrt, "vsprintf" );
+} }
+#endif
+
+int __stdcall ChTraitsCRT<wchar_t>::GetFormattedLength( LPCWSTR pszFormat, va_list args )
+{
+ #if _MSC_VER < 1400
+ checkCrt();
+
+ if ( _vscwprintf_ptr != NULL )
+ return _vscwprintf_ptr( pszFormat, args );
+
+ WCHAR buf[ 4000 ];
+ return vswprintf_ptr( buf, SIZEOF(buf), pszFormat, args );
+ #else
+ return _vscwprintf( pszFormat, args );
+ #endif
+}
+
+int __stdcall ChTraitsCRT<wchar_t>::Format( LPWSTR pszBuffer, size_t nLength, LPCWSTR pszFormat, va_list args)
+{
+ #if _MSC_VER < 1400
+ checkCrt();
+
+ if ( _vsnwprintf_ptr != NULL )
+ return _vsnwprintf_ptr( pszBuffer, nLength, pszFormat, args );
+
+ return vswprintf_ptr( pszBuffer, nLength, pszFormat, args );
+ #else
+ return _vsnwprintf( pszBuffer, nLength, pszFormat, args );
+ #endif
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// ChTraitsCRT<char>
+
+int __stdcall ChTraitsCRT<char>::GetFormattedLength( LPCSTR pszFormat, va_list args )
+{
+ #if _MSC_VER < 1400
+ checkCrt();
+
+ if ( _vscprintf_ptr != NULL )
+ return _vscprintf_ptr( pszFormat, args );
+
+ char buf[4000];
+ return vsprintf_ptr( buf, sizeof(buf), pszFormat, args );
+ #else
+ return _vscprintf( pszFormat, args );
+ #endif
+}
+
+int __stdcall ChTraitsCRT<char>::Format( LPSTR pszBuffer, size_t nlength, LPCSTR pszFormat, va_list args )
+{
+ #if _MSC_VER < 1400
+ checkCrt();
+
+ return _vsnprintf( pszBuffer, nlength, pszFormat, args );
+ #else
+ return vsprintf_s( pszBuffer, nlength, pszFormat, args );
+ #endif
+}
+
diff --git a/plugins/Clist_modern/src/hdr/MString.h b/plugins/Clist_modern/src/hdr/MString.h
new file mode 100644
index 0000000000..497f074e5d
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/MString.h
@@ -0,0 +1,2304 @@
+#pragma once
+
+#include <string.h>
+#include <mbstring.h>
+#include <wchar.h>
+
+#ifdef __MINGW32__
+#include <limits.h>
+
+__inline size_t strnlen(const char *string, size_t maxlen)
+{
+ const char *end = (const char *)memchr ((const void *)string, '\0', maxlen);
+ return end ? (size_t) (end - string) : maxlen;
+}
+__inline size_t wcsnlen(const wchar_t *string, size_t maxlen)
+{
+ const wchar_t *end = wmemchr (string, L'\0', maxlen);
+ return end ? (size_t) (end - string) : maxlen;
+}
+
+/* FIXME: This may be wrong assumption about _AtlGetConversionACP */
+#define _AtlGetConversionACP() CP_THREAD_ACP
+/* FIXME: This is unsafe */
+#define memcpy_s(dest,size,src,count) memcpy(dest,src,count)
+/* FIXME: This is quite silly implementation of _mbsstr */
+#define _mbsstr(str,search) strstr((const char *)str,(const char *)search)
+#define __max(x,y) (((x)<(y))?(y):(x))
+#endif /* __MINGW32__ */
+
+struct CMStringData
+{
+ int nDataLength; // Length of currently used data in XCHARs (not including terminating null)
+ int nAllocLength; // Length of allocated data in XCHARs (not including terminating null)
+ long nRefs; // Reference count: negative == locked
+ // XCHAR data[nAllocLength+1] // A CStringData is always followed in memory by the actual array of character data
+ void* data();
+ void AddRef();
+ bool IsLocked() const;
+ bool IsShared() const;
+ void Lock();
+ void Release();
+ void Unlock();
+};
+
+class CNilMStringData : public CMStringData
+{
+public:
+ CNilMStringData();
+
+public:
+ wchar_t achNil[2];
+};
+
+template< typename BaseType = char >
+class ChTraitsBase
+{
+public:
+ typedef char XCHAR;
+ typedef LPSTR PXSTR;
+ typedef LPCSTR PCXSTR;
+ typedef wchar_t YCHAR;
+ typedef LPWSTR PYSTR;
+ typedef LPCWSTR PCYSTR;
+};
+
+template<>
+class ChTraitsBase< wchar_t >
+{
+public:
+ typedef wchar_t XCHAR;
+ typedef LPWSTR PXSTR;
+ typedef LPCWSTR PCXSTR;
+ typedef char YCHAR;
+ typedef LPSTR PYSTR;
+ typedef LPCSTR PCYSTR;
+};
+
+class CMBaseString
+{
+public:
+ static CMStringData* Allocate(int nChars, int nCharSize);
+ static void Free(CMStringData* pData);
+ static CMStringData* Realloc(CMStringData* pData, int nChars, int nCharSize);
+
+protected:
+ static CMStringData* GetNilString();
+ static CNilMStringData m_nil;
+};
+
+template< typename BaseType >
+class CMSimpleStringT : public CMBaseString
+{
+public:
+ typedef typename ChTraitsBase< BaseType >::XCHAR XCHAR;
+ typedef typename ChTraitsBase< BaseType >::PXSTR PXSTR;
+ typedef typename ChTraitsBase< BaseType >::PCXSTR PCXSTR;
+ typedef typename ChTraitsBase< BaseType >::YCHAR YCHAR;
+ typedef typename ChTraitsBase< BaseType >::PYSTR PYSTR;
+ typedef typename ChTraitsBase< BaseType >::PCYSTR PCYSTR;
+
+public:
+ explicit CMSimpleStringT()
+ {
+ CMStringData* pData = GetNilString();
+ Attach(pData);
+ }
+
+ CMSimpleStringT(const CMSimpleStringT& strSrc)
+ {
+ CMStringData* pSrcData = strSrc.GetData();
+ CMStringData* pNewData = CloneData( pSrcData );
+ Attach( pNewData );
+ }
+
+ CMSimpleStringT(PCXSTR pszSrc)
+ {
+ int nLength = StringLength( pszSrc );
+ CMStringData* pData = Allocate( nLength, sizeof( XCHAR ));
+ if (pData != NULL)
+ {
+ Attach( pData );
+ SetLength( nLength );
+ CopyChars( m_pszData, nLength, pszSrc, nLength );
+ }
+ }
+ CMSimpleStringT(const XCHAR* pchSrc, int nLength)
+ {
+ CMStringData* pData = Allocate( nLength, sizeof( XCHAR ));
+ if ( pData != NULL )
+ {
+ Attach( pData );
+ SetLength( nLength );
+ CopyChars( m_pszData, nLength, pchSrc, nLength );
+ }
+ }
+ ~CMSimpleStringT()
+ {
+ CMStringData* pData = GetData();
+ pData->Release();
+ }
+
+ operator CMSimpleStringT<BaseType>&()
+ {
+ return *(CMSimpleStringT<BaseType>*)this;
+ }
+
+ CMSimpleStringT& operator=(const CMSimpleStringT& strSrc )
+ {
+ CMStringData* pSrcData = strSrc.GetData();
+ CMStringData* pOldData = GetData();
+ if ( pSrcData != pOldData)
+ {
+ if ( pOldData->IsLocked())
+ SetString( strSrc.GetString(), strSrc.GetLength());
+ else
+ {
+ CMStringData* pNewData = CloneData( pSrcData );
+ pOldData->Release();
+ Attach( pNewData );
+ }
+ }
+
+ return *this;
+ }
+
+ CMSimpleStringT& operator=(PCXSTR pszSrc)
+ {
+ SetString( pszSrc );
+ return *this;
+ }
+
+ CMSimpleStringT& operator+=( const CMSimpleStringT& strSrc )
+ {
+ Append( strSrc );
+
+ return *this;
+ }
+
+ CMSimpleStringT& operator+=( PCXSTR pszSrc )
+ {
+ Append( pszSrc );
+
+ return *this;
+ }
+ CMSimpleStringT& operator+=( char ch )
+ {
+ AppendChar(XCHAR(ch));
+
+ return *this;
+ }
+ CMSimpleStringT& operator+=( unsigned char ch )
+ {
+ AppendChar(XCHAR(ch));
+
+ return *this;
+ }
+ CMSimpleStringT& operator+=( wchar_t ch )
+ {
+ AppendChar(XCHAR(ch));
+
+ return *this;
+ }
+
+ XCHAR operator[]( int iChar ) const
+ {
+ return m_pszData[iChar];
+ }
+
+ operator PCXSTR() const
+ {
+ return m_pszData;
+ }
+
+ PCXSTR c_str() const
+ {
+ return m_pszData;
+ }
+
+ void Append( PCXSTR pszSrc )
+ {
+ Append( pszSrc, StringLength( pszSrc ));
+ }
+ void Append( PCXSTR pszSrc, int nLength )
+ {
+ // See comment in SetString() about why we do this
+ UINT_PTR nOffset = pszSrc - GetString();
+
+ UINT nOldLength = GetLength();
+ if (nOldLength < 0)
+ {
+ // protects from underflow
+ nOldLength = 0;
+ }
+
+ //Make sure we don't read pass end of the terminating NULL
+ int nSrcLength = StringLength(pszSrc);
+ nLength = nLength > nSrcLength ? nSrcLength: nLength;
+
+ int nNewLength = nOldLength+nLength;
+ PXSTR pszBuffer = GetBuffer( nNewLength );
+ if ( nOffset <= nOldLength )
+ {
+ pszSrc = pszBuffer+nOffset;
+ // No need to call CopyCharsOverlapped, since the destination is
+ // beyond the end of the original buffer
+ }
+ CopyChars( pszBuffer+nOldLength, nLength, pszSrc, nLength );
+ ReleaseBufferSetLength( nNewLength );
+ }
+ void AppendChar( XCHAR ch )
+ {
+ UINT nOldLength = GetLength();
+ int nNewLength = nOldLength+1;
+ PXSTR pszBuffer = GetBuffer( nNewLength );
+ pszBuffer[nOldLength] = ch;
+ ReleaseBufferSetLength( nNewLength );
+ }
+ void Append( const CMSimpleStringT& strSrc )
+ {
+ Append( strSrc.GetString(), strSrc.GetLength());
+ }
+ void Empty()
+ {
+ CMStringData* pOldData = GetData();
+ if ( pOldData->nDataLength == 0 )
+ return;
+
+ if ( pOldData->IsLocked())
+ {
+ // Don't reallocate a locked buffer that's shrinking
+ SetLength( 0 );
+ }
+ else
+ {
+ pOldData->Release();
+ CMStringData* pNewData = GetNilString();
+ Attach( pNewData );
+ }
+ }
+ void FreeExtra()
+ {
+ CMStringData* pOldData = GetData();
+ int nLength = pOldData->nDataLength;
+ if ( pOldData->nAllocLength == nLength )
+ return;
+
+ if ( !pOldData->IsLocked()) // Don't reallocate a locked buffer that's shrinking
+ {
+ CMStringData* pNewData = Allocate( nLength, sizeof( XCHAR ));
+ if ( pNewData == NULL ) {
+ SetLength( nLength );
+ return;
+ }
+
+ CopyChars( PXSTR( pNewData->data()), nLength, PCXSTR( pOldData->data()), nLength );
+
+ pOldData->Release();
+ Attach( pNewData );
+ SetLength( nLength );
+ }
+ }
+
+ int GetAllocLength() const
+ {
+ return GetData()->nAllocLength;
+ }
+ XCHAR GetAt( int iChar ) const
+ {
+ return m_pszData[iChar];
+ }
+ PXSTR GetBuffer()
+ {
+ CMStringData* pData = GetData();
+ if ( pData->IsShared())
+ Fork( pData->nDataLength );
+
+ return m_pszData;
+ }
+ PXSTR GetBuffer( int nMinBufferLength )
+ {
+ return PrepareWrite( nMinBufferLength );
+ }
+ PXSTR GetBufferSetLength( int nLength )
+ {
+ PXSTR pszBuffer = GetBuffer( nLength );
+ SetLength( nLength );
+
+ return pszBuffer;
+ }
+ int GetLength() const
+ {
+ return GetData()->nDataLength;
+ }
+
+ PCXSTR GetString() const
+ {
+ return m_pszData;
+ }
+ bool IsEmpty() const
+ {
+ return GetLength() == 0;
+ }
+ PXSTR LockBuffer()
+ {
+ CMStringData* pData = GetData();
+ if ( pData->IsShared())
+ {
+ Fork( pData->nDataLength );
+ pData = GetData(); // Do it again, because the fork might have changed it
+ }
+ pData->Lock();
+
+ return m_pszData;
+ }
+ void UnlockBuffer()
+ {
+ CMStringData* pData = GetData();
+ pData->Unlock();
+ }
+ void Preallocate( int nLength )
+ {
+ PrepareWrite( nLength );
+ }
+ void ReleaseBuffer( int nNewLength = -1 )
+ {
+ if ( nNewLength == -1 )
+ {
+ int nAlloc = GetData()->nAllocLength;
+ nNewLength = StringLengthN( m_pszData, nAlloc);
+ }
+ SetLength( nNewLength );
+ }
+ void ReleaseBufferSetLength( int nNewLength )
+ {
+ SetLength( nNewLength );
+ }
+ void Truncate( int nNewLength )
+ {
+ GetBuffer( nNewLength );
+ ReleaseBufferSetLength( nNewLength );
+ }
+ void SetAt( int iChar, XCHAR ch )
+ {
+ int nLength = GetLength();
+ PXSTR pszBuffer = GetBuffer();
+ pszBuffer[iChar] = ch;
+ ReleaseBufferSetLength( nLength );
+
+ }
+ void SetString( PCXSTR pszSrc )
+ {
+ SetString( pszSrc, StringLength( pszSrc ));
+ }
+ void assign( PCXSTR pszSrc )
+ {
+ SetString( pszSrc, StringLength( pszSrc ));
+ }
+ void SetString( PCXSTR pszSrc, int nLength )
+ {
+ if ( nLength == 0 )
+ {
+ Empty();
+ }
+ else
+ {
+
+ UINT nOldLength = GetLength();
+ UINT_PTR nOffset = pszSrc - GetString();
+
+ PXSTR pszBuffer = GetBuffer( nLength );
+ if ( nOffset <= nOldLength )
+ {
+ CopyCharsOverlapped( pszBuffer, GetAllocLength(),
+ pszBuffer+nOffset, nLength );
+ }
+ else
+ {
+ CopyChars( pszBuffer, GetAllocLength(), pszSrc, nLength );
+ }
+ ReleaseBufferSetLength( nLength );
+ }
+ }
+public:
+ friend CMSimpleStringT __stdcall operator+(const CMSimpleStringT& str1, const CMSimpleStringT& str2)
+ {
+ CMSimpleStringT s;
+
+ Concatenate( s, str1, str1.GetLength(), str2, str2.GetLength());
+
+ return s;
+ }
+
+ friend CMSimpleStringT __stdcall operator+(const CMSimpleStringT& str1, PCXSTR psz2)
+ {
+ CMSimpleStringT s;
+
+ Concatenate( s, str1, str1.GetLength(), psz2, StringLength( psz2 ));
+
+ return s;
+ }
+
+ friend CMSimpleStringT __stdcall operator+(PCXSTR psz1, const CMSimpleStringT& str2)
+ {
+ CMSimpleStringT s;
+
+ Concatenate( s, psz1, StringLength( psz1 ), str2, str2.GetLength());
+
+ return s;
+ }
+
+ static void __stdcall CopyChars(XCHAR* pchDest, const XCHAR* pchSrc, int nChars )
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ memcpy(pchDest, pchSrc, nChars * sizeof(XCHAR));
+#pragma warning (pop)
+ }
+ static void __stdcall CopyChars(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars )
+ {
+ #if _MSC_VER >= 1400
+ memcpy_s(pchDest, nDestLen * sizeof(XCHAR), pchSrc, nChars * sizeof(XCHAR));
+ #else
+ memcpy(pchDest, pchSrc, nDestLen * sizeof(XCHAR));
+ #endif
+ }
+
+ static void __stdcall CopyCharsOverlapped(XCHAR* pchDest, const XCHAR* pchSrc, int nChars )
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ memmove(pchDest, pchSrc, nChars * sizeof(XCHAR));
+#pragma warning (pop)
+ }
+ static void __stdcall CopyCharsOverlapped(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars)
+ {
+ #if _MSC_VER >= 1400
+ memmove_s(pchDest, nDestLen * sizeof(XCHAR), pchSrc, nChars * sizeof(XCHAR));
+ #else
+ memmove(pchDest, pchSrc, nDestLen * sizeof(XCHAR));
+ #endif
+ }
+ static int __stdcall StringLength(const char* psz)
+ {
+ if (psz == NULL)
+ {
+ return(0);
+ }
+ return (int(strlen(psz)));
+ }
+ static int __stdcall StringLength(const wchar_t* psz)
+ {
+ if (psz == NULL)
+ return 0;
+
+ return int(wcslen(psz));
+ }
+ static int __stdcall StringLengthN(const char* psz, size_t sizeInXChar )
+ {
+ if ( psz == NULL )
+ return 0;
+
+ return int( strnlen( psz, sizeInXChar ));
+ }
+ static int __stdcall StringLengthN(const wchar_t* psz, size_t sizeInXChar )
+ {
+ if ( psz == NULL )
+ return 0;
+
+ return int( wcsnlen( psz, sizeInXChar ));
+ }
+protected:
+ static void __stdcall Concatenate(CMSimpleStringT& strResult, PCXSTR psz1, int nLength1, PCXSTR psz2, int nLength2)
+ {
+ int nNewLength = nLength1+nLength2;
+ PXSTR pszBuffer = strResult.GetBuffer(nNewLength);
+ CopyChars(pszBuffer, nLength1, psz1, nLength1 );
+ CopyChars(pszBuffer + nLength1, nLength2, psz2, nLength2);
+ strResult.ReleaseBufferSetLength(nNewLength);
+ }
+ // Implementation
+private:
+ void Attach(CMStringData* pData)
+ {
+ m_pszData = static_cast<PXSTR>(pData->data());
+ }
+ void Fork(int nLength)
+ {
+ CMStringData* pOldData = GetData();
+ int nOldLength = pOldData->nDataLength;
+ CMStringData* pNewData = Allocate(nLength, sizeof(XCHAR));
+ if (pNewData != NULL)
+ {
+ int nCharsToCopy = ((nOldLength < nLength) ? nOldLength : nLength)+1; // Copy '\0'
+ CopyChars( PXSTR( pNewData->data()), nCharsToCopy, PCXSTR( pOldData->data()), nCharsToCopy );
+ pNewData->nDataLength = nOldLength;
+ pOldData->Release();
+ Attach(pNewData);
+ }
+ }
+ CMStringData* GetData() const
+ {
+ return (reinterpret_cast<CMStringData *>(m_pszData) - 1);
+ }
+ PXSTR PrepareWrite( int nLength )
+ {
+ CMStringData* pOldData = GetData();
+ int nShared = 1 - pOldData->nRefs; // nShared < 0 means true, >= 0 means false
+ int nTooShort = pOldData->nAllocLength-nLength; // nTooShort < 0 means true, >= 0 means false
+ if ((nShared | nTooShort) < 0 ) // If either sign bit is set (i.e. either is less than zero), we need to copy data
+ PrepareWrite2(nLength);
+
+ return m_pszData;
+ }
+ void PrepareWrite2(int nLength)
+ {
+ CMStringData* pOldData = GetData();
+ if (pOldData->nDataLength > nLength)
+ nLength = pOldData->nDataLength;
+
+ if (pOldData->IsShared())
+ {
+ Fork(nLength);
+ }
+ else if (pOldData->nAllocLength < nLength)
+ {
+ // Grow exponentially, until we hit 1K.
+ int nNewLength = pOldData->nAllocLength;
+ if ( nNewLength > 1024 )
+ nNewLength += 1024;
+ else
+ nNewLength *= 2;
+
+ if ( nNewLength < nLength )
+ nNewLength = nLength;
+
+ Reallocate( nNewLength );
+ }
+ }
+ void Reallocate( int nLength )
+ {
+ CMStringData* pOldData = GetData();
+ if ( pOldData->nAllocLength >= nLength || nLength <= 0)
+ return;
+
+ CMStringData* pNewData = Realloc( pOldData, nLength, sizeof( XCHAR ));
+ if ( pNewData != NULL )
+ Attach( pNewData );
+ }
+
+ void SetLength( int nLength )
+ {
+ GetData()->nDataLength = nLength;
+ m_pszData[nLength] = 0;
+ }
+
+ static CMStringData* __stdcall CloneData(CMStringData* pData)
+ {
+ CMStringData* pNewData = NULL;
+
+ if (!pData->IsLocked()) {
+ pNewData = pData;
+ pNewData->AddRef();
+ }
+
+ return pNewData;
+ }
+
+public :
+ // typedef CStrBufT<BaseType> CStrBuf;
+private:
+ PXSTR m_pszData;
+};
+
+
+template< typename _CharType = char >
+class ChTraitsCRT : public ChTraitsBase< _CharType >
+{
+public:
+ static char* __stdcall CharNext( const char* p )
+ {
+ return reinterpret_cast< char* >( _mbsinc( reinterpret_cast< const unsigned char* >( p )));
+ }
+
+ static int __stdcall IsDigit( char ch )
+ {
+ return _ismbcdigit( ch );
+ }
+
+ static int __stdcall IsSpace( char ch )
+ {
+ return _ismbcspace( ch );
+ }
+
+ static int __stdcall StringCompare( LPCSTR pszA, LPCSTR pszB )
+ {
+ return _mbscmp( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ));
+ }
+
+ static int __stdcall StringCompareIgnore( LPCSTR pszA, LPCSTR pszB )
+ {
+ return _mbsicmp( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ));
+ }
+
+ static int __stdcall StringCollate( LPCSTR pszA, LPCSTR pszB )
+ {
+ return _mbscoll( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ));
+ }
+
+ static int __stdcall StringCollateIgnore( LPCSTR pszA, LPCSTR pszB )
+ {
+ return _mbsicoll( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ));
+ }
+
+ static LPCSTR __stdcall StringFindString( LPCSTR pszBlock, LPCSTR pszMatch )
+ {
+ return reinterpret_cast< LPCSTR >( _mbsstr( reinterpret_cast< const unsigned char* >( pszBlock ),
+ reinterpret_cast< const unsigned char* >( pszMatch )));
+ }
+
+ static LPSTR __stdcall StringFindString( LPSTR pszBlock, LPCSTR pszMatch )
+ {
+ return const_cast< LPSTR >( StringFindString( const_cast< LPCSTR >( pszBlock ), pszMatch ));
+ }
+
+ static LPCSTR __stdcall StringFindChar( LPCSTR pszBlock, char chMatch )
+ {
+ return reinterpret_cast< LPCSTR >( _mbschr( reinterpret_cast< const unsigned char* >( pszBlock ), (unsigned char)chMatch ));
+ }
+
+ static LPCSTR __stdcall StringFindCharRev( LPCSTR psz, char ch )
+ {
+ return reinterpret_cast< LPCSTR >( _mbsrchr( reinterpret_cast< const unsigned char* >( psz ), (unsigned char)ch ));
+ }
+
+ static LPCSTR __stdcall StringScanSet( LPCSTR pszBlock, LPCSTR pszMatch )
+ {
+ return reinterpret_cast< LPCSTR >( _mbspbrk( reinterpret_cast< const unsigned char* >( pszBlock ),
+ reinterpret_cast< const unsigned char* >( pszMatch )));
+ }
+
+ static int __stdcall StringSpanIncluding( LPCSTR pszBlock, LPCSTR pszSet )
+ {
+ return (int)_mbsspn( reinterpret_cast< const unsigned char* >( pszBlock ), reinterpret_cast< const unsigned char* >( pszSet ));
+ }
+
+ static int __stdcall StringSpanExcluding( LPCSTR pszBlock, LPCSTR pszSet )
+ {
+ return (int)_mbscspn( reinterpret_cast< const unsigned char* >( pszBlock ), reinterpret_cast< const unsigned char* >( pszSet ));
+ }
+
+ static LPSTR __stdcall StringUppercase( LPSTR psz )
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ return reinterpret_cast< LPSTR >( _mbsupr( reinterpret_cast< unsigned char* >( psz )) );
+#pragma warning (pop)
+ }
+
+ static LPSTR __stdcall StringLowercase( LPSTR psz )
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ return reinterpret_cast< LPSTR >( _mbslwr( reinterpret_cast< unsigned char* >( psz )) );
+#pragma warning (pop)
+ }
+
+ static LPSTR __stdcall StringUppercase( LPSTR psz, size_t size )
+ {
+ #if _MSC_VER >= 1400
+ _mbsupr_s(reinterpret_cast< unsigned char* >( psz ), size);
+ #else
+ _mbsupr(reinterpret_cast< unsigned char* >( psz ));
+ #endif
+ return psz;
+ }
+
+ static LPSTR __stdcall StringLowercase( LPSTR psz, size_t size )
+ {
+ #if _MSC_VER >= 1400
+ _mbslwr_s( reinterpret_cast< unsigned char* >( psz ), size );
+ #else
+ _mbsupr(reinterpret_cast< unsigned char* >( psz ));
+ #endif
+ return psz;
+ }
+
+ static LPSTR __stdcall StringReverse( LPSTR psz )
+ {
+ return reinterpret_cast< LPSTR >( _mbsrev( reinterpret_cast< unsigned char* >( psz )) );
+ }
+
+ static int __stdcall GetFormattedLength( LPCSTR pszFormat, va_list args );
+
+ static int __stdcall Format( LPSTR pszBuffer, LPCSTR pszFormat, va_list args )
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ return vsprintf( pszBuffer, pszFormat, args );
+#pragma warning (pop)
+
+ }
+
+ static int __stdcall Format( LPSTR pszBuffer, size_t nlength, LPCSTR pszFormat, va_list args );
+
+ static int __stdcall GetBaseTypeLength( LPCSTR pszSrc )
+ {
+ // Returns required buffer length in XCHARs
+ return int( strlen( pszSrc ));
+ }
+
+ static int __stdcall GetBaseTypeLength( LPCSTR pszSrc, int nLength )
+ {
+ (void)pszSrc;
+ // Returns required buffer length in XCHARs
+ return nLength;
+ }
+
+ static int __stdcall GetBaseTypeLength( LPCWSTR pszSource )
+ {
+ // Returns required buffer length in XCHARs
+ return ::WideCharToMultiByte( _AtlGetConversionACP(), 0, pszSource, -1, NULL, 0, NULL, NULL )-1;
+ }
+
+ static int __stdcall GetBaseTypeLength( LPCWSTR pszSource, int nLength )
+ {
+ // Returns required buffer length in XCHARs
+ return ::WideCharToMultiByte( _AtlGetConversionACP(), 0, pszSource, nLength, NULL, 0, NULL, NULL );
+ }
+
+ static void __stdcall ConvertToBaseType( LPSTR pszDest, int nDestLength, LPCSTR pszSrc, int nSrcLength = -1 )
+ {
+ if (nSrcLength == -1) { nSrcLength=1 + GetBaseTypeLength(pszSrc); }
+ // nLen is in XCHARs
+ memcpy_s( pszDest, nDestLength*sizeof( char ),
+ pszSrc, nSrcLength*sizeof( char ));
+ }
+
+ static void __stdcall ConvertToBaseType( LPSTR pszDest, int nDestLength, LPCWSTR pszSrc, int nSrcLength = -1)
+ {
+ // nLen is in XCHARs
+ ::WideCharToMultiByte( _AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL );
+ }
+
+ static void ConvertToOem( _CharType* pstrString)
+ {
+ BOOL fSuccess=::CharToOemA(pstrString, pstrString);
+ }
+
+ static void ConvertToAnsi( _CharType* pstrString)
+ {
+ BOOL fSuccess=::OemToCharA(pstrString, pstrString);
+ }
+
+ static void ConvertToOem( _CharType* pstrString, size_t size)
+ {
+ if(size>UINT_MAX)
+ {
+ return;
+ }
+ DWORD dwSize=static_cast<DWORD>(size);
+ BOOL fSuccess=::CharToOemBuffA(pstrString, pstrString, dwSize);
+ }
+
+ static void ConvertToAnsi( _CharType* pstrString, size_t size)
+ {
+ if(size>UINT_MAX)
+ return;
+
+ DWORD dwSize=static_cast<DWORD>(size);
+ BOOL fSuccess=::OemToCharBuffA(pstrString, pstrString, dwSize);
+ }
+
+ static void __stdcall FloodCharacters( char ch, int nLength, char* pch )
+ {
+ // nLength is in XCHARs
+ memset( pch, ch, nLength );
+ }
+
+ static BSTR __stdcall AllocSysString( const char* pchData, int nDataLength )
+ {
+ int nLen = ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pchData, nDataLength, NULL, NULL );
+ BSTR bstr = ::SysAllocStringLen( NULL, nLen );
+ if ( bstr != NULL )
+ ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pchData, nDataLength, bstr, nLen );
+
+ return bstr;
+ }
+
+ static BOOL __stdcall ReAllocSysString( const char* pchData, BSTR* pbstr, int nDataLength )
+ {
+ int nLen = ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pchData, nDataLength, NULL, NULL );
+ BOOL bSuccess = ::SysReAllocStringLen( pbstr, NULL, nLen );
+ if ( bSuccess )
+ ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pchData, nDataLength, *pbstr, nLen );
+
+ return bSuccess;
+ }
+
+ static int __stdcall SafeStringLen( LPCSTR psz )
+ {
+ // returns length in bytes
+ return (psz != NULL) ? int( strlen( psz )) : 0;
+ }
+
+ static int __stdcall SafeStringLen( LPCWSTR psz )
+ {
+ // returns length in wchar_ts
+ return (psz != NULL) ? int( wcslen( psz )) : 0;
+ }
+
+ static int __stdcall GetCharLen( const wchar_t* pch )
+ {
+ // returns char length
+ return 1;
+ }
+
+ static int __stdcall GetCharLen( const char* pch )
+ {
+ // returns char length
+ return int( _mbclen( reinterpret_cast< const unsigned char* >( pch )) );
+ }
+
+ static DWORD __stdcall GetEnvironmentVariable( LPCSTR pszVar, LPSTR pszBuffer, DWORD dwSize )
+ {
+ return ::GetEnvironmentVariableA( pszVar, pszBuffer, dwSize );
+ }
+};
+
+// specialization for wchar_t
+template<>
+class ChTraitsCRT< wchar_t > : public ChTraitsBase< wchar_t >
+{
+ static DWORD __stdcall _GetEnvironmentVariableW( LPCWSTR pszName, LPWSTR pszBuffer, DWORD nSize )
+ {
+ return ::GetEnvironmentVariableW( pszName, pszBuffer, nSize );
+ }
+
+public:
+ static LPWSTR __stdcall CharNext( LPCWSTR psz )
+ {
+ return const_cast< LPWSTR >( psz+1 );
+ }
+
+ static int __stdcall IsDigit( wchar_t ch )
+ {
+ return iswdigit( static_cast<unsigned short>(ch));
+ }
+
+ static int __stdcall IsSpace( wchar_t ch )
+ {
+ return iswspace( static_cast<unsigned short>(ch));
+ }
+
+ static int __stdcall StringCompare( LPCWSTR pszA, LPCWSTR pszB )
+ {
+ return wcscmp( pszA, pszB );
+ }
+
+ static int __stdcall StringCompareIgnore( LPCWSTR pszA, LPCWSTR pszB )
+ {
+ return _wcsicmp( pszA, pszB );
+ }
+
+ static int __stdcall StringCollate( LPCWSTR pszA, LPCWSTR pszB )
+ {
+ return wcscoll( pszA, pszB );
+ }
+
+ static int __stdcall StringCollateIgnore( LPCWSTR pszA, LPCWSTR pszB )
+ {
+ return _wcsicoll( pszA, pszB );
+ }
+
+ static LPCWSTR __stdcall StringFindString( LPCWSTR pszBlock, LPCWSTR pszMatch )
+ {
+ return wcsstr( pszBlock, pszMatch );
+ }
+
+ static LPWSTR __stdcall StringFindString( LPWSTR pszBlock, LPCWSTR pszMatch )
+ {
+ return const_cast< LPWSTR >( StringFindString( const_cast< LPCWSTR >( pszBlock ), pszMatch ));
+ }
+
+ static LPCWSTR __stdcall StringFindChar( LPCWSTR pszBlock, wchar_t chMatch )
+ {
+ return wcschr( pszBlock, chMatch );
+ }
+
+ static LPCWSTR __stdcall StringFindCharRev( LPCWSTR psz, wchar_t ch )
+ {
+ return wcsrchr( psz, ch );
+ }
+
+ static LPCWSTR __stdcall StringScanSet( LPCWSTR pszBlock, LPCWSTR pszMatch )
+ {
+ return wcspbrk( pszBlock, pszMatch );
+ }
+
+ static int __stdcall StringSpanIncluding( LPCWSTR pszBlock, LPCWSTR pszSet )
+ {
+ return (int)wcsspn( pszBlock, pszSet );
+ }
+
+ static int __stdcall StringSpanExcluding( LPCWSTR pszBlock, LPCWSTR pszSet )
+ {
+ return (int)wcscspn( pszBlock, pszSet );
+ }
+
+ static LPWSTR __stdcall StringUppercase( LPWSTR psz )
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ return _wcsupr( psz );
+#pragma warning (pop)
+ }
+
+ static LPWSTR __stdcall StringLowercase( LPWSTR psz )
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ return _wcslwr( psz );
+#pragma warning (pop)
+ }
+
+ static LPWSTR __stdcall StringUppercase( LPWSTR psz, size_t size )
+ {
+ return _wcsupr( psz );
+ }
+
+ static LPWSTR __stdcall StringLowercase( LPWSTR psz, size_t size )
+ {
+ return _wcslwr( psz );
+ }
+
+ static LPWSTR __stdcall StringReverse( LPWSTR psz )
+ {
+ return _wcsrev( psz );
+ }
+
+ static int __stdcall GetFormattedLength( LPCWSTR pszFormat, va_list args);
+
+ static int __stdcall Format( LPWSTR pszBuffer, LPCWSTR pszFormat, va_list args)
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ return vswprintf( pszBuffer, pszFormat, args );
+#pragma warning (pop)
+ }
+
+ static int __stdcall Format( LPWSTR pszBuffer, size_t nLength, LPCWSTR pszFormat, va_list args);
+
+ static int __stdcall GetBaseTypeLength( LPCSTR pszSrc )
+ {
+ // Returns required buffer size in wchar_ts
+ return ::MultiByteToWideChar( CP_ACP, 0, pszSrc, -1, NULL, 0 )-1;
+ }
+
+ static int __stdcall GetBaseTypeLength( LPCSTR pszSrc, int nLength )
+ {
+ // Returns required buffer size in wchar_ts
+ return ::MultiByteToWideChar( CP_ACP, 0, pszSrc, nLength, NULL, 0 );
+ }
+
+ static int __stdcall GetBaseTypeLength( LPCWSTR pszSrc )
+ {
+ // Returns required buffer size in wchar_ts
+ return (int)wcslen( pszSrc );
+ }
+
+ static int __stdcall GetBaseTypeLength( LPCWSTR pszSrc, int nLength )
+ {
+ (void)pszSrc;
+ // Returns required buffer size in wchar_ts
+ return nLength;
+ }
+
+ static void __stdcall ConvertToBaseType( LPWSTR pszDest, int nDestLength, LPCSTR pszSrc, int nSrcLength = -1)
+ {
+ // nLen is in wchar_ts
+ ::MultiByteToWideChar( CP_ACP, 0, pszSrc, nSrcLength, pszDest, nDestLength );
+ }
+
+ static void __stdcall ConvertToBaseType( LPWSTR pszDest, int nDestLength, LPCWSTR pszSrc, int nSrcLength = -1 )
+ {
+ if (nSrcLength == -1) { nSrcLength=1 + GetBaseTypeLength(pszSrc); }
+ // nLen is in wchar_ts
+ #if _MSC_VER >= 1400
+ wmemcpy_s(pszDest, nDestLength, pszSrc, nSrcLength);
+ #else
+ wmemcpy(pszDest, pszSrc, nDestLength);
+ #endif
+ }
+
+ static void __stdcall FloodCharacters( wchar_t ch, int nLength, LPWSTR psz )
+ {
+ // nLength is in XCHARs
+ for ( int i = 0; i < nLength; i++ )
+ {
+ psz[i] = ch;
+ }
+ }
+
+ static BSTR __stdcall AllocSysString( const wchar_t* pchData, int nDataLength )
+ {
+ return ::SysAllocStringLen( pchData, nDataLength );
+ }
+
+ static BOOL __stdcall ReAllocSysString( const wchar_t* pchData, BSTR* pbstr, int nDataLength )
+ {
+ return ::SysReAllocStringLen( pbstr, pchData, nDataLength );
+ }
+
+ static int __stdcall SafeStringLen( LPCSTR psz )
+ {
+ // returns length in bytes
+ return (psz != NULL) ? (int)strlen( psz ) : 0;
+ }
+
+ static int __stdcall SafeStringLen( LPCWSTR psz )
+ {
+ // returns length in wchar_ts
+ return (psz != NULL) ? (int)wcslen( psz ) : 0;
+ }
+
+ static int __stdcall GetCharLen( const wchar_t* pch )
+ {
+ (void)pch;
+ // returns char length
+ return 1;
+ }
+
+ static int __stdcall GetCharLen( const char* pch )
+ {
+ // returns char length
+ return (int)( _mbclen( reinterpret_cast< const unsigned char* >( pch )) );
+ }
+
+ static DWORD __stdcall GetEnvironmentVariable( LPCWSTR pszVar, LPWSTR pszBuffer, DWORD dwSize )
+ {
+ return _GetEnvironmentVariableW( pszVar, pszBuffer, dwSize );
+ }
+
+ static void __stdcall ConvertToOem( LPWSTR /*psz*/ )
+ {
+ }
+
+ static void __stdcall ConvertToAnsi( LPWSTR /*psz*/ )
+ {
+ }
+
+ static void __stdcall ConvertToOem( LPWSTR /*psz*/, size_t )
+ {
+ }
+
+ static void __stdcall ConvertToAnsi( LPWSTR /*psz*/, size_t )
+ {
+ }
+};
+
+template< typename BaseType, class StringTraits >
+class CMStringT : public CMSimpleStringT< BaseType >
+{
+public:
+ typedef CMSimpleStringT< BaseType> CThisSimpleString;
+ typedef typename CThisSimpleString::XCHAR XCHAR;
+ typedef typename CThisSimpleString::PXSTR PXSTR;
+ typedef typename CThisSimpleString::PCXSTR PCXSTR;
+ typedef typename CThisSimpleString::YCHAR YCHAR;
+ typedef typename CThisSimpleString::PYSTR PYSTR;
+ typedef typename CThisSimpleString::PCYSTR PCYSTR;
+
+public:
+ CMStringT() : CThisSimpleString()
+ {
+ }
+
+ static void __stdcall Construct( CMStringT* pString )
+ {
+ new( pString ) CMStringT;
+ }
+
+ // Copy constructor
+ CMStringT( const CMStringT& strSrc ) :
+ CThisSimpleString( strSrc )
+ {
+ }
+
+ CMStringT( const XCHAR* pszSrc ) :
+ CThisSimpleString()
+ {
+ // nDestLength is in XCHARs
+ *this = pszSrc;
+ }
+
+ CMStringT( const YCHAR* pszSrc ) :
+ CThisSimpleString()
+ {
+ *this = pszSrc;
+ }
+
+
+ CMStringT( const unsigned char* pszSrc ) :
+ CThisSimpleString()
+ {
+ *this = reinterpret_cast< const char* >( pszSrc );
+ }
+
+ CMStringT( char ch, int nLength = 1 ) :
+ CThisSimpleString()
+ {
+ if ( nLength > 0 )
+ {
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::FloodCharacters( XCHAR( ch ), nLength, pszBuffer );
+ this->ReleaseBufferSetLength( nLength );
+ }
+ }
+
+ CMStringT( wchar_t ch, int nLength = 1 ) :
+ CThisSimpleString()
+ {
+ if ( nLength > 0 )
+ {
+ //Convert ch to the BaseType
+ wchar_t pszCh[2] = { ch , 0 };
+ int nBaseTypeCharLen = 1;
+
+ if(ch != L'\0')
+ {
+ nBaseTypeCharLen = StringTraits::GetBaseTypeLength(pszCh);
+ }
+
+ XCHAR *buffBaseTypeChar = new XCHAR[nBaseTypeCharLen+1];
+ StringTraits::ConvertToBaseType( buffBaseTypeChar, nBaseTypeCharLen+1, pszCh, 1 );
+ //Allocate enough characters in String and flood (replicate) with the (converted character)*nLength
+ PXSTR pszBuffer = this->GetBuffer( nLength*nBaseTypeCharLen );
+ if (nBaseTypeCharLen == 1)
+ { //Optimization for a common case - wide char translates to 1 ansi/wide char.
+ StringTraits::FloodCharacters( buffBaseTypeChar[0], nLength, pszBuffer );
+ } else
+ {
+ XCHAR* p=pszBuffer;
+ for (int i=0 ; i < nLength ;++i)
+ {
+ for (int j=0 ; j < nBaseTypeCharLen ;++j)
+ {
+ *p=buffBaseTypeChar[j];
+ ++p;
+ }
+ }
+ }
+ this->ReleaseBufferSetLength( nLength*nBaseTypeCharLen );
+ delete [] buffBaseTypeChar;
+ }
+ }
+
+ CMStringT( const XCHAR* pch, int nLength ) :
+ CThisSimpleString( pch, nLength )
+ {
+ }
+
+ CMStringT( const YCHAR* pch, int nLength ) :
+ CThisSimpleString()
+ {
+ if ( nLength > 0 )
+ {
+ int nDestLength = StringTraits::GetBaseTypeLength( pch, nLength );
+ PXSTR pszBuffer = this->GetBuffer( nDestLength );
+ StringTraits::ConvertToBaseType( pszBuffer, nDestLength, pch, nLength );
+ this->ReleaseBufferSetLength( nDestLength );
+ }
+ }
+
+ // Destructor
+ ~CMStringT()
+ {
+ }
+
+ // Assignment operators
+ CMStringT& operator=( const CMStringT& strSrc )
+ {
+ CThisSimpleString::operator=( strSrc );
+
+ return *this;
+ }
+
+ CMStringT& operator=( PCXSTR pszSrc )
+ {
+ CThisSimpleString::operator=( pszSrc );
+
+ return *this;
+ }
+
+ CMStringT& operator=( PCYSTR pszSrc )
+ {
+ // nDestLength is in XCHARs
+ int nDestLength = (pszSrc != NULL) ? StringTraits::GetBaseTypeLength( pszSrc ) : 0;
+ if ( nDestLength > 0 )
+ {
+ PXSTR pszBuffer = this->GetBuffer( nDestLength );
+ StringTraits::ConvertToBaseType( pszBuffer, nDestLength, pszSrc);
+ this->ReleaseBufferSetLength( nDestLength );
+ }
+ else
+ {
+ this->Empty();
+ }
+
+ return *this;
+ }
+
+ CMStringT& operator=( const unsigned char* pszSrc )
+ {
+ return operator=( reinterpret_cast< const char* >( pszSrc ));
+ }
+
+ CMStringT& operator=( char ch )
+ {
+ char ach[2] = { ch, 0 };
+
+ return operator=( ach );
+ }
+
+ CMStringT& operator=( wchar_t ch )
+ {
+ wchar_t ach[2] = { ch, 0 };
+
+ return operator=( ach );
+ }
+
+// CMStringT& operator=( const VARIANT& var );
+
+ CMStringT& operator+=( const CMStringT& str )
+ {
+ CThisSimpleString::operator+=( str );
+ return *this;
+ }
+
+ CMStringT& operator+=( const CThisSimpleString& str )
+ {
+ CThisSimpleString::operator+=( str );
+ return *this;
+ }
+
+ CMStringT& operator+=( PCXSTR pszSrc )
+ {
+ CThisSimpleString::operator+=( pszSrc );
+ return *this;
+ }
+// template< int t_nSize >
+// CMStringT& operator+=( const CStaticString< XCHAR, t_nSize >& strSrc )
+// {
+// CThisSimpleString::operator+=( strSrc );
+//
+// return *this;
+// }
+ CMStringT& operator+=( PCYSTR pszSrc )
+ {
+ CMStringT str( pszSrc );
+
+ return operator+=( str );
+ }
+
+ CMStringT& operator+=( char ch )
+ {
+ CThisSimpleString::operator+=( ch );
+
+ return *this;
+ }
+
+ CMStringT& operator+=( unsigned char ch )
+ {
+ CThisSimpleString::operator+=( ch );
+
+ return *this;
+ }
+
+ CMStringT& operator+=( wchar_t ch )
+ {
+ CThisSimpleString::operator+=( ch );
+
+ return *this;
+ }
+
+ // Comparison
+
+ int Compare( PCXSTR psz ) const
+ {
+ return StringTraits::StringCompare( this->GetString(), psz );
+ }
+
+ int CompareNoCase( PCXSTR psz ) const
+ {
+ return StringTraits::StringCompareIgnore( this->GetString(), psz );
+ }
+
+ int Collate( PCXSTR psz ) const
+ {
+ return StringTraits::StringCollate( this->GetString(), psz );
+ }
+
+ int CollateNoCase( PCXSTR psz ) const
+ {
+ return StringTraits::StringCollateIgnore( this->GetString(), psz );
+ }
+
+ // Advanced manipulation
+
+ // Delete 'nCount' characters, starting at index 'iIndex'
+ int Delete( int iIndex, int nCount = 1 )
+ {
+ if ( iIndex < 0 )
+ iIndex = 0;
+
+ if ( nCount < 0 )
+ nCount = 0;
+
+ int nLength = this->GetLength();
+ if ( nCount + iIndex > nLength )
+ {
+ nCount = nLength-iIndex;
+ }
+ if ( nCount > 0 )
+ {
+ int nNewLength = nLength-nCount;
+ int nXCHARsToCopy = nLength-(iIndex+nCount)+1;
+ PXSTR pszBuffer = this->GetBuffer();
+ #if _MSC_VER >= 1400
+ memmove_s( pszBuffer+iIndex, nXCHARsToCopy*sizeof( XCHAR ), pszBuffer+iIndex+nCount, nXCHARsToCopy*sizeof( XCHAR ));
+ #else
+ memmove( pszBuffer+iIndex, pszBuffer+iIndex+nCount, nXCHARsToCopy*sizeof( XCHAR ));
+ #endif
+ this->ReleaseBufferSetLength( nNewLength );
+ }
+
+ return this->GetLength();
+ }
+
+ // Insert character 'ch' before index 'iIndex'
+ int Insert( int iIndex, XCHAR ch )
+ {
+ if ( iIndex < 0 )
+ iIndex = 0;
+
+ if ( iIndex > this->GetLength())
+ iIndex = this->GetLength();
+
+ int nNewLength = this->GetLength()+1;
+
+ PXSTR pszBuffer = this->GetBuffer( nNewLength );
+
+ // move existing bytes down
+ #if _MSC_VER >= 1400
+ memmove_s( pszBuffer+iIndex+1, (nNewLength-iIndex)*sizeof( XCHAR ), pszBuffer+iIndex, (nNewLength-iIndex)*sizeof( XCHAR ));
+ #else
+ memmove( pszBuffer+iIndex+1, pszBuffer+iIndex, (nNewLength-iIndex)*sizeof( XCHAR ));
+ #endif
+ pszBuffer[iIndex] = ch;
+
+ this->ReleaseBufferSetLength( nNewLength );
+ return nNewLength;
+ }
+
+ // Insert string 'psz' before index 'iIndex'
+ int Insert( int iIndex, PCXSTR psz )
+ {
+ if ( iIndex < 0 )
+ iIndex = 0;
+
+ if ( iIndex > this->GetLength())
+ {
+ iIndex = this->GetLength();
+ }
+
+ // nInsertLength and nNewLength are in XCHARs
+ int nInsertLength = StringTraits::SafeStringLen( psz );
+ int nNewLength = this->GetLength();
+ if ( nInsertLength > 0 )
+ {
+ nNewLength += nInsertLength;
+
+ PXSTR pszBuffer = this->GetBuffer( nNewLength );
+ // move existing bytes down
+ #if _MSC_VER >= 1400
+ memmove_s( pszBuffer+iIndex+nInsertLength, (nNewLength-iIndex-nInsertLength+1)*sizeof( XCHAR ), pszBuffer+iIndex, (nNewLength-iIndex-nInsertLength+1)*sizeof( XCHAR ));
+ memcpy_s( pszBuffer+iIndex, nInsertLength*sizeof( XCHAR ), psz, nInsertLength*sizeof( XCHAR ));
+ #else
+ memmove( pszBuffer+iIndex+nInsertLength, pszBuffer+iIndex, (nNewLength-iIndex-nInsertLength+1)*sizeof( XCHAR ));
+ memcpy( pszBuffer+iIndex, psz, nInsertLength*sizeof( XCHAR ));
+ #endif
+ this->ReleaseBufferSetLength( nNewLength );
+ }
+
+ return nNewLength;
+ }
+
+ // Replace all occurrences of character 'chOld' with character 'chNew'
+ int Replace( XCHAR chOld, XCHAR chNew )
+ {
+ int nCount = 0;
+
+ // short-circuit the nop case
+ if ( chOld != chNew )
+ {
+ // otherwise modify each character that matches in the string
+ bool bCopied = false;
+ PXSTR pszBuffer = const_cast< PXSTR >( this->GetString()); // We don't actually write to pszBuffer until we've called GetBuffer().
+
+ int nLength = this->GetLength();
+ int iChar = 0;
+ while( iChar < nLength )
+ {
+ // replace instances of the specified character only
+ if ( pszBuffer[iChar] == chOld )
+ {
+ if ( !bCopied )
+ {
+ bCopied = true;
+ pszBuffer = this->GetBuffer( nLength );
+ }
+ pszBuffer[iChar] = chNew;
+ nCount++;
+ }
+ iChar = int( StringTraits::CharNext( pszBuffer+iChar )-pszBuffer );
+ }
+ if ( bCopied )
+ {
+ this->ReleaseBufferSetLength( nLength );
+ }
+ }
+
+ return nCount;
+ }
+
+ // Replace all occurrences of string 'pszOld' with string 'pszNew'
+ int Replace( PCXSTR pszOld, PCXSTR pszNew )
+ {
+ // can't have empty or NULL lpszOld
+
+ // nSourceLen is in XCHARs
+ int nSourceLen = StringTraits::SafeStringLen( pszOld );
+ if ( nSourceLen == 0 )
+ return 0;
+ // nReplacementLen is in XCHARs
+ int nReplacementLen = StringTraits::SafeStringLen( pszNew );
+
+ // loop once to figure out the size of the result string
+ int nCount = 0;
+ {
+ PCXSTR pszStart = this->GetString();
+ PCXSTR pszEnd = pszStart+this->GetLength();
+ while( pszStart < pszEnd )
+ {
+ PCXSTR pszTarget;
+ while((pszTarget = StringTraits::StringFindString( pszStart, pszOld )) != NULL)
+ {
+ nCount++;
+ pszStart = pszTarget+nSourceLen;
+ }
+ pszStart += StringTraits::SafeStringLen( pszStart )+1;
+ }
+ }
+
+ // if any changes were made, make them
+ if ( nCount > 0 )
+ {
+ // if the buffer is too small, just
+ // allocate a new buffer (slow but sure)
+ int nOldLength = this->GetLength();
+ int nNewLength = nOldLength+(nReplacementLen-nSourceLen)*nCount;
+
+ PXSTR pszBuffer = this->GetBuffer( __max( nNewLength, nOldLength ));
+
+ PXSTR pszStart = pszBuffer;
+ PXSTR pszEnd = pszStart+nOldLength;
+
+ // loop again to actually do the work
+ while( pszStart < pszEnd )
+ {
+ PXSTR pszTarget;
+ while((pszTarget = StringTraits::StringFindString( pszStart, pszOld )) != NULL )
+ {
+ int nBalance = nOldLength-int(pszTarget-pszBuffer+nSourceLen);
+ memmove_s( pszTarget+nReplacementLen, nBalance*sizeof( XCHAR ),
+ pszTarget+nSourceLen, nBalance*sizeof( XCHAR ));
+ memcpy_s( pszTarget, nReplacementLen*sizeof( XCHAR ),
+ pszNew, nReplacementLen*sizeof( XCHAR ));
+ pszStart = pszTarget+nReplacementLen;
+ pszTarget[nReplacementLen+nBalance] = 0;
+ nOldLength += (nReplacementLen-nSourceLen);
+ }
+ pszStart += StringTraits::SafeStringLen( pszStart )+1;
+ }
+ this->ReleaseBufferSetLength( nNewLength );
+ }
+
+ return nCount;
+ }
+
+ // Remove all occurrences of character 'chRemove'
+ int Remove( XCHAR chRemove )
+ {
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+
+ PXSTR pszSource = pszBuffer;
+ PXSTR pszDest = pszBuffer;
+ PXSTR pszEnd = pszBuffer+nLength;
+
+ while( pszSource < pszEnd )
+ {
+ PXSTR pszNewSource = StringTraits::CharNext( pszSource );
+ if ( *pszSource != chRemove )
+ {
+ // Copy the source to the destination. Remember to copy all bytes of an MBCS character
+ // Copy the source to the destination. Remember to copy all bytes of an MBCS character
+ size_t NewSourceGap = (pszNewSource-pszSource);
+ PXSTR pszNewDest = pszDest + NewSourceGap;
+ size_t i = 0;
+ for (i = 0; pszDest != pszNewDest && i < NewSourceGap; i++)
+ {
+ *pszDest = *pszSource;
+ pszSource++;
+ pszDest++;
+ }
+ }
+ pszSource = pszNewSource;
+ }
+ *pszDest = 0;
+ int nCount = int( pszSource-pszDest );
+ this->ReleaseBufferSetLength( nLength-nCount );
+
+ return nCount;
+ }
+
+ CMStringT Tokenize( PCXSTR pszTokens, int& iStart ) const
+ {
+ if ((pszTokens == NULL) || (*pszTokens == (XCHAR)0))
+ {
+ if (iStart < this->GetLength())
+ return CMStringT( this->GetString()+iStart );
+ }
+ else
+ {
+ PCXSTR pszPlace = this->GetString()+iStart;
+ PCXSTR pszEnd = this->GetString()+this->GetLength();
+ if ( pszPlace < pszEnd )
+ {
+ int nIncluding = StringTraits::StringSpanIncluding( pszPlace, pszTokens );
+
+ if ((pszPlace+nIncluding) < pszEnd )
+ {
+ pszPlace += nIncluding;
+ int nExcluding = StringTraits::StringSpanExcluding( pszPlace, pszTokens );
+
+ int iFrom = iStart+nIncluding;
+ int nUntil = nExcluding;
+ iStart = iFrom+nUntil+1;
+
+ return Mid( iFrom, nUntil );
+ }
+ }
+ }
+
+ // return empty string, done tokenizing
+ iStart = -1;
+
+ return CMStringT();
+ }
+
+ // find routines
+
+ // Find the first occurrence of character 'ch', starting at index 'iStart'
+ int Find( XCHAR ch, int iStart = 0 ) const
+ {
+ // nLength is in XCHARs
+ int nLength = this->GetLength();
+ if ( iStart < 0 || iStart >= nLength)
+ return -1;
+
+ // find first single character
+ PCXSTR psz = StringTraits::StringFindChar( this->GetString()+iStart, ch );
+
+ // return -1 if not found and index otherwise
+ return (psz == NULL) ? -1 : int( psz-this->GetString());
+ }
+
+ // look for a specific sub-string
+
+ // Find the first occurrence of string 'pszSub', starting at index 'iStart'
+ int Find( PCXSTR pszSub, int iStart = 0 ) const
+ {
+ // iStart is in XCHARs
+ if(pszSub == NULL)
+ return -1;
+
+ // nLength is in XCHARs
+ int nLength = this->GetLength();
+ if ( iStart < 0 || iStart > nLength )
+ return -1;
+
+ // find first matching substring
+ PCXSTR psz = StringTraits::StringFindString( this->GetString()+iStart, pszSub );
+
+ // return -1 for not found, distance from beginning otherwise
+ return (psz == NULL) ? -1 : int( psz-this->GetString());
+ }
+
+ // Find the first occurrence of any of the characters in string 'pszCharSet'
+ int FindOneOf( PCXSTR pszCharSet ) const
+ {
+ PCXSTR psz = StringTraits::StringScanSet( this->GetString(), pszCharSet );
+ return (psz == NULL) ? -1 : int( psz-this->GetString());
+ }
+
+ // Find the last occurrence of character 'ch'
+ int ReverseFind( XCHAR ch ) const
+ {
+ // find last single character
+ PCXSTR psz = StringTraits::StringFindCharRev( this->GetString(), ch );
+
+ // return -1 if not found, distance from beginning otherwise
+ return (psz == NULL) ? -1 : int( psz-this->GetString());
+ }
+
+ // manipulation
+
+ // Convert the string to uppercase
+ CMStringT& MakeUpper()
+ {
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::StringUppercase( pszBuffer, nLength+1 );
+ this->ReleaseBufferSetLength( nLength );
+
+ return *this;
+ }
+
+ // Convert the string to lowercase
+ CMStringT& MakeLower()
+ {
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::StringLowercase( pszBuffer, nLength+1 );
+ this->ReleaseBufferSetLength( nLength );
+
+ return *this;
+ }
+
+ // Reverse the string
+ CMStringT& MakeReverse()
+ {
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::StringReverse( pszBuffer );
+ this->ReleaseBufferSetLength( nLength );
+
+ return *this;
+ }
+
+ // trimming
+
+ // Remove all trailing whitespace
+ CMStringT& TrimRight()
+ {
+ // find beginning of trailing spaces by starting
+ // at beginning (DBCS aware)
+
+ PCXSTR psz = this->GetString();
+ PCXSTR pszLast = NULL;
+
+ while( *psz != 0 )
+ {
+ if ( StringTraits::IsSpace( *psz ))
+ {
+ if ( pszLast == NULL )
+ pszLast = psz;
+ }
+ else
+ {
+ pszLast = NULL;
+ }
+ psz = StringTraits::CharNext( psz );
+ }
+
+ if ( pszLast != NULL )
+ {
+ // truncate at trailing space start
+ int iLast = int( pszLast-this->GetString());
+
+ this->Truncate( iLast );
+ }
+
+ return *this;
+ }
+
+ // Remove all leading whitespace
+ CMStringT& TrimLeft()
+ {
+ // find first non-space character
+
+ PCXSTR psz = this->GetString();
+
+ while( StringTraits::IsSpace( *psz ))
+ {
+ psz = StringTraits::CharNext( psz );
+ }
+
+ if ( psz != this->GetString())
+ {
+ // fix up data and length
+ int iFirst = int( psz-this->GetString());
+ PXSTR pszBuffer = this->GetBuffer( this->GetLength());
+ psz = pszBuffer+iFirst;
+ int nDataLength = this->GetLength()-iFirst;
+ memmove_s( pszBuffer, (this->GetLength()+1)*sizeof( XCHAR ),
+ psz, (nDataLength+1)*sizeof( XCHAR ));
+ this->ReleaseBufferSetLength( nDataLength );
+ }
+
+ return *this;
+ }
+
+ // Remove all leading and trailing whitespace
+ CMStringT& Trim()
+ {
+ return TrimRight().TrimLeft();
+ }
+
+ // Remove all leading and trailing occurrences of character 'chTarget'
+ CMStringT& Trim( XCHAR chTarget )
+ {
+ return TrimRight( chTarget ).TrimLeft( chTarget );
+ }
+
+ // Remove all leading and trailing occurrences of any of the characters in the string 'pszTargets'
+ CMStringT& Trim( PCXSTR pszTargets )
+ {
+ return TrimRight( pszTargets ).TrimLeft( pszTargets );
+ }
+
+ // trimming anything (either side)
+
+ // Remove all trailing occurrences of character 'chTarget'
+ CMStringT& TrimRight( XCHAR chTarget )
+ {
+ // find beginning of trailing matches
+ // by starting at beginning (DBCS aware)
+
+ PCXSTR psz = this->GetString();
+ PCXSTR pszLast = NULL;
+
+ while( *psz != 0 )
+ {
+ if ( *psz == chTarget )
+ {
+ if ( pszLast == NULL )
+ {
+ pszLast = psz;
+ }
+ }
+ else
+ {
+ pszLast = NULL;
+ }
+ psz = StringTraits::CharNext( psz );
+ }
+
+ if ( pszLast != NULL )
+ {
+ // truncate at left-most matching character
+ int iLast = int( pszLast-this->GetString());
+ this->Truncate( iLast );
+ }
+
+ return *this;
+ }
+
+ // Remove all trailing occurrences of any of the characters in string 'pszTargets'
+ CMStringT& TrimRight( PCXSTR pszTargets )
+ {
+ // if we're not trimming anything, we're not doing any work
+ if ((pszTargets == NULL) || (*pszTargets == 0))
+ {
+ return *this;
+ }
+
+ // find beginning of trailing matches
+ // by starting at beginning (DBCS aware)
+
+ PCXSTR psz = this->GetString();
+ PCXSTR pszLast = NULL;
+
+ while( *psz != 0 )
+ {
+ if ( StringTraits::StringFindChar( pszTargets, *psz ) != NULL )
+ {
+ if ( pszLast == NULL )
+ {
+ pszLast = psz;
+ }
+ }
+ else
+ {
+ pszLast = NULL;
+ }
+ psz = StringTraits::CharNext( psz );
+ }
+
+ if ( pszLast != NULL )
+ {
+ // truncate at left-most matching character
+ int iLast = int( pszLast-this->GetString());
+ this->Truncate( iLast );
+ }
+
+ return *this;
+ }
+
+ // Remove all leading occurrences of character 'chTarget'
+ CMStringT& TrimLeft( XCHAR chTarget )
+ {
+ // find first non-matching character
+ PCXSTR psz = this->GetString();
+
+ while( chTarget == *psz )
+ {
+ psz = StringTraits::CharNext( psz );
+ }
+
+ if ( psz != this->GetString())
+ {
+ // fix up data and length
+ int iFirst = int( psz-this->GetString());
+ PXSTR pszBuffer = this->GetBuffer( this->GetLength());
+ psz = pszBuffer+iFirst;
+ int nDataLength = this->GetLength()-iFirst;
+ memmove_s( pszBuffer, (this->GetLength()+1)*sizeof( XCHAR ),
+ psz, (nDataLength+1)*sizeof( XCHAR ));
+ this->ReleaseBufferSetLength( nDataLength );
+ }
+
+ return *this;
+ }
+
+ // Remove all leading occurrences of any of the characters in string 'pszTargets'
+ CMStringT& TrimLeft( PCXSTR pszTargets )
+ {
+ // if we're not trimming anything, we're not doing any work
+ if ((pszTargets == NULL) || (*pszTargets == 0))
+ {
+ return *this;
+ }
+
+ PCXSTR psz = this->GetString();
+ while((*psz != 0) && (StringTraits::StringFindChar( pszTargets, *psz ) != NULL))
+ {
+ psz = StringTraits::CharNext( psz );
+ }
+
+ if ( psz != this->GetString())
+ {
+ // fix up data and length
+ int iFirst = int( psz-this->GetString());
+ PXSTR pszBuffer = this->GetBuffer( this->GetLength());
+ psz = pszBuffer+iFirst;
+ int nDataLength = this->GetLength()-iFirst;
+ memmove_s( pszBuffer, (this->GetLength()+1)*sizeof( XCHAR ),
+ psz, (nDataLength+1)*sizeof( XCHAR ));
+ this->ReleaseBufferSetLength( nDataLength );
+ }
+
+ return *this;
+ }
+
+ // Convert the string to the OEM character set
+ void AnsiToOem()
+ {
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::ConvertToOem( pszBuffer, nLength+1 );
+ this->ReleaseBufferSetLength( nLength );
+ }
+
+ // Convert the string to the ANSI character set
+ void OemToAnsi()
+ {
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::ConvertToAnsi( pszBuffer, nLength+1 );
+ this->ReleaseBufferSetLength( nLength );
+ }
+
+ // Very simple sub-string extraction
+
+ // Return the substring starting at index 'iFirst'
+ CMStringT Mid( int iFirst ) const
+ {
+ return Mid( iFirst, this->GetLength()-iFirst );
+ }
+
+ // Return the substring starting at index 'iFirst', with length 'nCount'
+ CMStringT Mid( int iFirst, int nCount ) const
+ {
+ // nCount is in XCHARs
+
+ // out-of-bounds requests return sensible things
+ if (iFirst < 0)
+ iFirst = 0;
+ if (nCount < 0)
+ nCount = 0;
+
+ if ((iFirst + nCount) > this->GetLength())
+ nCount = this->GetLength()-iFirst;
+
+ if ( iFirst > this->GetLength())
+ nCount = 0;
+
+ // optimize case of returning entire string
+ if ((iFirst == 0) && ((iFirst+nCount) == this->GetLength()))
+ return *this;
+
+ return CMStringT( this->GetString()+iFirst, nCount );
+ }
+
+ // Return the substring consisting of the rightmost 'nCount' characters
+ CMStringT Right( int nCount ) const
+ {
+ // nCount is in XCHARs
+ if (nCount < 0)
+ nCount = 0;
+
+ int nLength = this->GetLength();
+ if ( nCount >= nLength )
+ {
+ return *this;
+ }
+
+ return CMStringT( this->GetString()+nLength-nCount, nCount );
+ }
+
+ // Return the substring consisting of the leftmost 'nCount' characters
+ CMStringT Left( int nCount ) const
+ {
+ // nCount is in XCHARs
+ if (nCount < 0)
+ nCount = 0;
+
+ int nLength = this->GetLength();
+ if ( nCount >= nLength )
+ return *this;
+
+ return CMStringT( this->GetString(), nCount );
+ }
+
+ // Return the substring consisting of the leftmost characters in the set 'pszCharSet'
+ CMStringT SpanIncluding( PCXSTR pszCharSet ) const
+ {
+ return Left( StringTraits::StringSpanIncluding( this->GetString(), pszCharSet ));
+ }
+
+ // Return the substring consisting of the leftmost characters not in the set 'pszCharSet'
+ CMStringT SpanExcluding( PCXSTR pszCharSet ) const
+ {
+ return Left( StringTraits::StringSpanExcluding( this->GetString(), pszCharSet ));
+ }
+
+ // Format data using format string 'pszFormat'
+ void Format( PCXSTR pszFormat, ... );
+
+ // Append formatted data using format string 'pszFormat'
+ void AppendFormat( PCXSTR pszFormat, ... );
+
+ void AppendFormatV( PCXSTR pszFormat, va_list args )
+ {
+ int nCurrentLength = this->GetLength();
+ int nAppendLength = StringTraits::GetFormattedLength( pszFormat, args );
+ PXSTR pszBuffer = this->GetBuffer( nCurrentLength+nAppendLength );
+ StringTraits::Format( pszBuffer+nCurrentLength,
+ nAppendLength+1, pszFormat, args );
+ this->ReleaseBufferSetLength( nCurrentLength+nAppendLength );
+ }
+
+ void FormatV( PCXSTR pszFormat, va_list args )
+ {
+ int nLength = StringTraits::GetFormattedLength( pszFormat, args );
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::Format( pszBuffer, nLength+1, pszFormat, args );
+ this->ReleaseBufferSetLength( nLength );
+ }
+
+ // OLE BSTR support
+
+ // Allocate a BSTR containing a copy of the string
+ BSTR AllocSysString() const
+ {
+ BSTR bstrResult = StringTraits::AllocSysString( this->GetString(), this->GetLength());
+ return bstrResult;
+ }
+
+ BSTR SetSysString( BSTR* pbstr ) const
+ {
+ StringTraits::ReAllocSysString( this->GetString(), pbstr, this->GetLength());
+ return *pbstr;
+ }
+
+ // Set the string to the value of environment variable 'pszVar'
+ BOOL GetEnvironmentVariable( PCXSTR pszVar )
+ {
+ ULONG nLength = StringTraits::GetEnvironmentVariable( pszVar, NULL, 0 );
+ BOOL bRetVal = FALSE;
+
+ if ( nLength == 0 )
+ {
+ this->Empty();
+ }
+ else
+ {
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::GetEnvironmentVariable( pszVar, pszBuffer, nLength );
+ this->ReleaseBuffer();
+ bRetVal = TRUE;
+ }
+
+ return bRetVal;
+ }
+
+ // Load the string from resource 'nID'
+ BOOL LoadString( UINT nID )
+ {
+ HINSTANCE hInst = StringTraits::FindStringResourceInstance( nID );
+ if ( hInst == NULL )
+ return FALSE;
+
+ return LoadString( hInst, nID );
+ }
+
+ friend CMStringT __stdcall operator+( const CMStringT& str1, const CMStringT& str2 )
+ {
+ CMStringT strResult;
+
+ Concatenate( strResult, str1, str1.GetLength(), str2, str2.GetLength());
+
+ return strResult;
+ }
+
+ friend CMStringT __stdcall operator+( const CMStringT& str1, PCXSTR psz2 )
+ {
+ CMStringT strResult;
+
+ Concatenate( strResult, str1, str1.GetLength(), psz2, StringLength( psz2 ));
+
+ return strResult;
+ }
+
+ friend CMStringT __stdcall operator+( PCXSTR psz1, const CMStringT& str2 )
+ {
+ CMStringT strResult;
+
+ Concatenate( strResult, psz1, StringLength( psz1 ), str2, str2.GetLength());
+
+ return strResult;
+ }
+
+ friend CMStringT __stdcall operator+( const CMStringT& str1, wchar_t ch2 )
+ {
+ CMStringT strResult;
+ XCHAR chTemp = XCHAR( ch2 );
+
+ Concatenate( strResult, str1, str1.GetLength(), &chTemp, 1 );
+
+ return strResult;
+ }
+
+ friend CMStringT __stdcall operator+( const CMStringT& str1, char ch2 )
+ {
+ CMStringT strResult;
+ XCHAR chTemp = XCHAR( ch2 );
+
+ Concatenate( strResult, str1, str1.GetLength(), &chTemp, 1 );
+
+ return strResult;
+ }
+
+ friend CMStringT __stdcall operator+( wchar_t ch1, const CMStringT& str2 )
+ {
+ CMStringT strResult;
+ XCHAR chTemp = XCHAR( ch1 );
+
+ Concatenate( strResult, &chTemp, 1, str2, str2.GetLength());
+
+ return strResult;
+ }
+
+ friend CMStringT __stdcall operator+( char ch1, const CMStringT& str2 )
+ {
+ CMStringT strResult;
+ XCHAR chTemp = XCHAR( ch1 );
+
+ Concatenate( strResult, &chTemp, 1, str2, str2.GetLength());
+
+ return strResult;
+ }
+
+ friend bool __stdcall operator==( const CMStringT& str1, const CMStringT& str2 )
+ {
+ return str1.Compare( str2 ) == 0;
+ }
+
+ friend bool __stdcall operator==( const CMStringT& str1, PCXSTR psz2 )
+ {
+ return str1.Compare( psz2 ) == 0;
+ }
+
+ friend bool __stdcall operator==( PCXSTR psz1, const CMStringT& str2 )
+ {
+ return str2.Compare( psz1 ) == 0;
+ }
+
+ friend bool __stdcall operator==( const CMStringT& str1, PCYSTR psz2 )
+ {
+ CMStringT str2( psz2 );
+
+ return str1 == str2;
+ }
+
+ friend bool __stdcall operator==( PCYSTR psz1, const CMStringT& str2 )
+ {
+ CMStringT str1( psz1 );
+
+ return str1 == str2;
+ }
+
+ friend bool __stdcall operator!=( const CMStringT& str1, const CMStringT& str2 )
+ {
+ return str1.Compare( str2 ) != 0;
+ }
+
+ friend bool __stdcall operator!=( const CMStringT& str1, PCXSTR psz2 )
+ {
+ return str1.Compare( psz2 ) != 0;
+ }
+
+ friend bool __stdcall operator!=( PCXSTR psz1, const CMStringT& str2 )
+ {
+ return str2.Compare( psz1 ) != 0;
+ }
+
+ friend bool __stdcall operator!=( const CMStringT& str1, PCYSTR psz2 )
+ {
+ CMStringT str2( psz2 );
+
+ return str1 != str2;
+ }
+
+ friend bool __stdcall operator!=( PCYSTR psz1, const CMStringT& str2 )
+ {
+ CMStringT str1( psz1 );
+
+ return str1 != str2;
+ }
+
+ friend bool __stdcall operator<( const CMStringT& str1, const CMStringT& str2 )
+ {
+ return str1.Compare( str2 ) < 0;
+ }
+
+ friend bool __stdcall operator<( const CMStringT& str1, PCXSTR psz2 )
+ {
+ return str1.Compare( psz2 ) < 0;
+ }
+
+ friend bool __stdcall operator<( PCXSTR psz1, const CMStringT& str2 )
+ {
+ return str2.Compare( psz1 ) > 0;
+ }
+
+ friend bool __stdcall operator>( const CMStringT& str1, const CMStringT& str2 )
+ {
+ return str1.Compare( str2 ) > 0;
+ }
+
+ friend bool __stdcall operator>( const CMStringT& str1, PCXSTR psz2 )
+ {
+ return str1.Compare( psz2 ) > 0;
+ }
+
+ friend bool __stdcall operator>( PCXSTR psz1, const CMStringT& str2 )
+ {
+ return str2.Compare( psz1 ) < 0;
+ }
+
+ friend bool __stdcall operator<=( const CMStringT& str1, const CMStringT& str2 )
+ {
+ return str1.Compare( str2 ) <= 0;
+ }
+
+ friend bool __stdcall operator<=( const CMStringT& str1, PCXSTR psz2 )
+ {
+ return str1.Compare( psz2 ) <= 0;
+ }
+
+ friend bool __stdcall operator<=( PCXSTR psz1, const CMStringT& str2 )
+ {
+ return str2.Compare( psz1 ) >= 0;
+ }
+
+ friend bool __stdcall operator>=( const CMStringT& str1, const CMStringT& str2 )
+ {
+ return str1.Compare( str2 ) >= 0;
+ }
+
+ friend bool __stdcall operator>=( const CMStringT& str1, PCXSTR psz2 )
+ {
+ return str1.Compare( psz2 ) >= 0;
+ }
+
+ friend bool __stdcall operator>=( PCXSTR psz1, const CMStringT& str2 )
+ {
+ return str2.Compare( psz1 ) <= 0;
+ }
+
+ friend bool __stdcall operator==( XCHAR ch1, const CMStringT& str2 )
+ {
+ return (str2.GetLength() == 1) && (str2[0] == ch1);
+ }
+
+ friend bool __stdcall operator==( const CMStringT& str1, XCHAR ch2 )
+ {
+ return (str1.GetLength() == 1) && (str1[0] == ch2);
+ }
+
+ friend bool __stdcall operator!=( XCHAR ch1, const CMStringT& str2 )
+ {
+ return (str2.GetLength() != 1) || (str2[0] != ch1);
+ }
+
+ friend bool __stdcall operator!=( const CMStringT& str1, XCHAR ch2 )
+ {
+ return (str1.GetLength() != 1) || (str1[0] != ch2);
+ }
+};
+
+template< typename BaseType, class StringTraits >
+inline void CMStringT<BaseType, StringTraits>::Format(PCXSTR pszFormat, ... )
+{
+ va_list argList;
+ va_start( argList, pszFormat );
+ FormatV( pszFormat, argList );
+ va_end( argList );
+}
+
+template< typename BaseType, class StringTraits >
+inline void CMStringT<BaseType, StringTraits>::AppendFormat(PCXSTR pszFormat, ... )
+{
+ va_list argList;
+ va_start( argList, pszFormat );
+ AppendFormatV( pszFormat, argList );
+ va_end( argList );
+}
+
+typedef CMStringT< wchar_t, ChTraitsCRT< wchar_t > > CMStringW;
+typedef CMStringT< char, ChTraitsCRT< char > > CMStringA;
+typedef CMStringT< TCHAR, ChTraitsCRT< TCHAR > > CMString;
diff --git a/plugins/Clist_modern/src/hdr/modern_awaymsg.h b/plugins/Clist_modern/src/hdr/modern_awaymsg.h
new file mode 100644
index 0000000000..ea51c6ddb2
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_awaymsg.h
@@ -0,0 +1,37 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+
+*/
+
+/*
+* Author Artem Shpynov aka FYR
+* Copyright 2000-2008 Artem Shpynov
+*/
+
+#pragma once
+//////////////////////////////////////////////////////////////////////////
+// Module to Request Away Messages
+
+void InitAwayMsgModule();
+void UninitAwayMsgModule();
+void amRequestAwayMsg(HANDLE hContact);
+
diff --git a/plugins/Clist_modern/src/hdr/modern_cache_funcs.h b/plugins/Clist_modern/src/hdr/modern_cache_funcs.h
new file mode 100644
index 0000000000..ba2b59f2c3
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_cache_funcs.h
@@ -0,0 +1,46 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+
+Created by Pescuma
+
+*/
+#pragma once
+
+#ifndef __CACHE_FUNCS_H__
+# define __CACHE_FUNCS_H__
+
+#include "modern_clc.h"
+#include "modern_commonprototypes.h"
+
+void Cache_GetText(struct ClcData *dat, struct ClcContact *contact, BOOL forceRenew);
+void Cache_GetFirstLineText(struct ClcData *dat, struct ClcContact *contact);
+void Cache_GetSecondLineText(struct SHORTDATA *dat, PDNCE pdnce);
+void Cache_GetThirdLineText(struct SHORTDATA *dat, PDNCE pdnce);
+void Cache_GetAvatar(struct ClcData *dat, struct ClcContact *contact);
+void Cache_GetTimezone(struct ClcData *dat, HANDLE hContact);
+int Cache_GetLineText(PDNCE pdnce, int type, LPTSTR text, int text_size, TCHAR *variable_text, BOOL xstatus_has_priority,
+ BOOL show_status_if_no_away, BOOL show_listening_if_no_away, BOOL use_name_and_message_for_xstatus,
+ BOOL pdnce_time_show_only_if_different);
+
+void amRequestAwayMsg(HANDLE hContact);
+
+#endif // __CACHE_FUNCS_H__
diff --git a/plugins/Clist_modern/src/hdr/modern_callproc.h b/plugins/Clist_modern/src/hdr/modern_callproc.h
new file mode 100644
index 0000000000..19cfb883b6
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_callproc.h
@@ -0,0 +1,128 @@
+#ifndef modern_callproc_h__
+#define modern_callproc_h__
+
+namespace call {
+#include <windows.h>
+
+//////////////////////////////////////////////////////////////////////////
+// USE AS
+// ret = call::sync( proc, param1, param2 ... etc)
+//////////////////////////////////////////////////////////////////////////
+// internal realization
+enum ASYNC_T { ASYNC = 0, SYNC };
+int __ProcessCall( class __baseCall * pStorage, ASYNC_T async );
+
+class __baseCall { public: virtual int __DoCallStorageProc() =0; virtual ~__baseCall() {}; };
+template< class R > class _callParams0 : public __baseCall
+{
+public:
+ R(*_proc)();
+ _callParams0( R (*proc)()) : _proc(proc){};
+ int __DoCallStorageProc() { return (int)_proc(); }
+};
+
+template<> class _callParams0<void> : public __baseCall
+{
+public:
+ void(*_proc)();
+ _callParams0( void (*proc)()) : _proc(proc){};
+ int __DoCallStorageProc() { _proc(); return 0; }
+};
+
+template< class R, class A> class _callParams1 : public __baseCall
+{
+public:
+ R(*_proc)(A); A _a;
+ _callParams1( R(*proc)(A), A a) : _proc(proc), _a(a) {};
+ int __DoCallStorageProc() { return (int)_proc(_a); }
+};
+
+template<class A> class _callParams1<void, A> : public __baseCall
+{
+public:
+ void(*_proc)(A); A _a;
+ _callParams1( void(*proc)(A), A a) : _proc(proc), _a(a) {};
+ int __DoCallStorageProc() { _proc(_a); return 0; }
+};
+
+template< class R, class A, class B> class _callParams2 : public __baseCall
+{
+public:
+ R (*_proc)(A, B); A _a; B _b;
+ _callParams2( R (*proc)(A, B), A a, B b) : _proc(proc), _a(a), _b(b) {};
+ int __DoCallStorageProc() { return (int)_proc(_a, _b); }
+};
+
+template< class A, class B> class _callParams2<void, A, B> : public __baseCall
+{
+public:
+ void (*_proc)(A, B); A _a; B _b;
+ _callParams2( void (*proc)(A, B), A a, B b) : _proc(proc), _a(a), _b(b) {};
+ int __DoCallStorageProc() { _proc(_a, _b); return 0; }
+};
+
+template< class R, class A, class B, class C> class _callParams3 : public __baseCall
+{
+public:
+ R (*_proc)(A, B, C); A _a; B _b; C _c;
+ _callParams3( R (*proc)(A, B, C), A a, B b, C c ) : _proc(proc), _a(a), _b(b), _c(c) {};
+ int __DoCallStorageProc() { return (int)_proc(_a,_b,_c); }
+};
+
+template< class A, class B, class C> class _callParams3<void, A, B, C> : public __baseCall
+{
+public:
+ void (*_proc)(A, B, C); A _a; B _b; C _c;
+ _callParams3( void (*proc)(A, B, C), A a, B b, C c ) : _proc(proc), _a(a), _b(b), _c(c) {};
+ int __DoCallStorageProc() { _proc(_a,_b,_c); return 0;}
+};
+
+template < class R > R __DoCall( R(*__proc)(), ASYNC_T sync_mode )
+{
+ typedef _callParams0< R > callClass;
+ callClass * storage = new callClass( __proc );
+ return (R) call::__ProcessCall( storage, sync_mode );
+};
+
+template < class R, class A > R __DoCall( R(*__proc)( A ), A a, ASYNC_T sync_mode )
+{
+ typedef _callParams1< R, A > callClass;
+ callClass * storage = new callClass( __proc, a );
+ return (R)__ProcessCall( storage, sync_mode );
+};
+
+
+template < class R, class A, class B > R __DoCall( R(*__proc)( A, B ), A a, B b, ASYNC_T sync_mode )
+{
+ typedef _callParams2< R, A, B > callClass;
+ callClass * storage = new callClass( __proc, a, b);
+ return (R)__ProcessCall( storage, sync_mode );
+};
+
+
+template < class R, class A, class B, class C > R __DoCall( R(*__proc)( A, B, C ), A a, B b, C c, ASYNC_T sync_mode )
+{
+ typedef _callParams3< R, A, B, C > callClass;
+ callClass * storage = new callClass( __proc, a, b, c);
+ return (R)__ProcessCall( storage, sync_mode );
+};
+
+
+template < class R > R sync( R(*_proc)())
+{ return __DoCall(_proc, SYNC); };
+template < class R, class A > R sync( R(*_proc)( A ), A a )
+{ return __DoCall(_proc, a, SYNC); };
+template < class R, class A, class B > R sync( R(*_proc)( A,B), A a, B b )
+{ return __DoCall(_proc, a, b, SYNC); };
+template < class R, class A, class B, class C > R sync( R(*_proc)( A,B,C ), A a, B b, C c)
+{ return __DoCall(_proc, a, b, c, SYNC); };
+template < class R > int async( R(*_proc)())
+{ return __DoCall(_proc, ASYNC); };
+template < class R, class A > R async( R(*_proc)( A ), A a )
+{ return __DoCall(_proc, a, ASYNC); };
+template < class R, class A, class B > R async( R(*_proc)( A,B), A a, B b )
+{ return __DoCall(_proc, a, b, ASYNC); };
+template < class R, class A, class B, class C > R async( R(*_proc)( A,B,C ), A a, B b, C c)
+{ return __DoCall(_proc, a, b, c, ASYNC); };
+}; // namespace call
+#endif // modern_callproc_h__
diff --git a/plugins/Clist_modern/src/hdr/modern_clc.h b/plugins/Clist_modern/src/hdr/modern_clc.h
new file mode 100644
index 0000000000..56c7a8b4c0
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_clc.h
@@ -0,0 +1,515 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+*/
+
+#pragma once
+
+#ifndef _CLC_H_
+#define _CLC_H_
+#include "modern_image_array.h"
+#include "../m_api/m_xpTheme.h"
+
+#include "modern_defsettings.h"
+#include "modern_clist.h"
+
+#define SETTING_TRAYICON_SINGLE 0
+#define SETTING_TRAYICON_CYCLE 1
+#define SETTING_TRAYICON_MULTI 2
+
+#define NIIF_INTERN_UNICODE 0x00000100
+
+#define SETTING_STATE_HIDDEN 0
+#define SETTING_STATE_MINIMIZED 1
+#define SETTING_STATE_NORMAL 2
+
+#define SETTING_BRINGTOFRONT_DEFAULT 0
+
+#define SETTING_AVATAR_OVERLAY_TYPE_NORMAL 0
+#define SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL 1
+#define SETTING_AVATAR_OVERLAY_TYPE_CONTACT 2
+
+#define HCONTACT_ISGROUP 0x80000000
+#define HCONTACT_ISINFO 0xFFFF0000
+
+#define MAXEXTRACOLUMNS 16
+#define MAXSTATUSMSGLEN 256
+
+#define INTM_NAMECHANGED (WM_USER+10)
+#define INTM_ICONCHANGED (WM_USER+11)
+#define INTM_GROUPCHANGED (WM_USER+12)
+#define INTM_GROUPSCHANGED (WM_USER+13)
+#define INTM_CONTACTADDED (WM_USER+14)
+#define INTM_CONTACTDELETED (WM_USER+15)
+#define INTM_HIDDENCHANGED (WM_USER+16)
+#define INTM_INVALIDATE (WM_USER+17)
+#define INTM_APPARENTMODECHANGED (WM_USER+18)
+#define INTM_SETINFOTIPHOVERTIME (WM_USER+19)
+#define INTM_NOTONLISTCHANGED (WM_USER+20)
+#define INTM_RELOADOPTIONS (WM_USER+21)
+#define INTM_NAMEORDERCHANGED (WM_USER+22)
+#define INTM_IDLECHANGED (WM_USER+23)
+#define INTM_SCROLLBARCHANGED (WM_USER+24)
+#define INTM_PROTOCHANGED (WM_USER+25)
+#define INTM_STATUSMSGCHANGED (WM_USER+26)
+#define INTM_STATUSCHANGED (WM_USER+27)
+#define INTM_AVATARCHANGED (WM_USER+28)
+#define INTM_TIMEZONECHANGED (WM_USER+29)
+
+
+
+#define CLM_SETEXTRACOLUMNSSPACE (CLM_FIRST+73) //wParam=extra space between icons
+
+#define CLBF_TILEVTOROWHEIGHT 0x0100
+
+#define TIMERID_RENAME 10
+#define TIMERID_DRAGAUTOSCROLL 11
+#define TIMERID_INFOTIP 13
+#define TIMERID_REBUILDAFTER 14
+#define TIMERID_DELAYEDRESORTCLC 15
+#define TIMERID_SUBEXPAND 21
+#define TIMERID_INVALIDATE 22
+#define TIMERID_INVALIDATE_FULL 25
+#define TIMERID_RECALCSCROLLBAR 26
+
+#define TIMERID_FIRST TIMERID_RENAME
+#define TIMERID_LAST TIMERID_RECALCSCROLLBAR
+
+void clcSetDelayTimer( UINT_PTR uIDEvent, HWND hwnd, int nDelay = -1);
+
+#define FONTID_CONTACTS 0
+#define FONTID_INVIS 1
+#define FONTID_OFFLINE 2
+#define FONTID_NOTONLIST 3
+#define FONTID_OPENGROUPS 4
+#define FONTID_OPENGROUPCOUNTS 5
+#define FONTID_DIVIDERS 6
+#define FONTID_OFFINVIS 7
+#define FONTID_SECONDLINE 8
+#define FONTID_THIRDLINE 9
+#define FONTID_AWAY 10
+#define FONTID_DND 11
+#define FONTID_NA 12
+#define FONTID_OCCUPIED 13
+#define FONTID_CHAT 14
+#define FONTID_INVISIBLE 15
+#define FONTID_PHONE 16
+#define FONTID_LUNCH 17
+#define FONTID_CONTACT_TIME 18
+#define FONTID_CLOSEDGROUPS 19
+#define FONTID_CLOSEDGROUPCOUNTS 20
+#define FONTID_STATUSBAR_PROTONAME 21
+#define FONTID_EVENTAREA 22
+#define FONTID_VIEMODES 23
+#define FONTID_MODERN_MAX 23
+
+#define DROPTARGET_OUTSIDE 0
+#define DROPTARGET_ONSELF 1
+#define DROPTARGET_ONNOTHING 2
+#define DROPTARGET_ONGROUP 3
+#define DROPTARGET_ONCONTACT 4
+#define DROPTARGET_INSERTION 5
+#define DROPTARGET_ONMETACONTACT 6
+#define DROPTARGET_ONSUBCONTACT 7
+
+struct ClcGroup;
+
+#define CONTACTF_ONLINE 1
+#define CONTACTF_INVISTO 2
+#define CONTACTF_VISTO 4
+#define CONTACTF_NOTONLIST 8
+#define CONTACTF_CHECKED 16
+#define CONTACTF_IDLE 32
+//#define CONTACTF_STATUSMSG 64
+
+#define AVATAR_POS_DONT_HAVE -1
+#define AVATAR_POS_ANIMATED -2
+
+#define TEXT_PIECE_TYPE_TEXT 0
+#define TEXT_PIECE_TYPE_SMILEY 1
+
+#define DRAGSTAGE_NOTMOVED 0
+#define DRAGSTAGE_ACTIVE 1
+#define DRAGSTAGEM_STAGE 0x00FF
+#define DRAGSTAGEF_MAYBERENAME 0x8000
+#define DRAGSTAGEF_OUTSIDE 0x4000
+#define DRAGSTAGEF_SKIPRENAME 0x2000
+
+#define ITEM_AVATAR 0
+#define ITEM_ICON 1
+#define ITEM_TEXT 2
+#define ITEM_EXTRA_ICONS 3
+#define ITEM_CONTACT_TIME 4
+#define NUM_ITEM_TYPE 5
+
+#define TEXT_EMPTY -1
+#define TEXT_STATUS 0
+#define TEXT_NICKNAME 1
+#define TEXT_STATUS_MESSAGE 2
+#define TEXT_TEXT 3
+#define TEXT_CONTACT_TIME 4
+#define TEXT_LISTENING_TO 5
+
+#define TEXT_TEXT_MAX_LENGTH 1024
+
+typedef struct tagClcContactTextPiece
+{
+ int type;
+ int len;
+ union
+ {
+ struct
+ {
+ int start_pos;
+ };
+ struct
+ {
+ HICON smiley;
+ int smiley_width;
+ int smiley_height;
+ };
+ };
+} ClcContactTextPiece;
+
+enum {
+ CIT_PAINT_END=0, //next items are invalids
+ CIT_AVATAR, // 1
+ CIT_ICON, // 2
+ CIT_TEXT, // 3 //the contact name or group name
+ CIT_SUBTEXT1, // 4 //the second line for contact or group counter for groups
+ CIT_SUBTEXT2, // 5
+ CIT_TIME, // 6
+ CIT_CHECKBOX, // 7
+ CIT_SELECTION, // 8
+ CIT_EXTRA=64 //use bit compare for extra icon, the mask &0x3F will return number of extra icon
+};
+
+
+typedef struct _tagContactItems
+{
+ BYTE itemType; //one of above CIT_ definitions
+ RECT itemRect;
+}tContactItems;
+
+struct ClcContact {
+ BYTE type;
+ BYTE flags;
+ union {
+ struct {
+ int iImage;
+ HANDLE hContact;
+ };
+ struct {
+ WORD groupId;
+ struct ClcGroup *group;
+ };
+ };
+ BYTE iExtraImage[MAXEXTRACOLUMNS];
+ TCHAR szText[120 - MAXEXTRACOLUMNS];
+ char * proto; // MS_PROTO_GETBASEPROTO
+
+ struct ClcContact *subcontacts;
+ BYTE SubAllocated;
+ BYTE SubExpanded;
+ BYTE isSubcontact;
+// int status;
+ BOOL image_is_special;
+ int avatar_pos;
+ struct avatarCacheEntry *avatar_data;
+ SIZE avatar_size;
+ CSmileyString ssText;
+
+
+ // For hittest
+ int pos_indent;
+ RECT pos_check;
+ RECT pos_avatar;
+ RECT pos_icon;
+ RECT pos_label;
+ RECT pos_rename_rect;
+ RECT pos_contact_time;
+ RECT pos_extra[MAXEXTRACOLUMNS];
+ DWORD lastPaintCounter;
+ BYTE bContactRate;
+
+ // For extended layout
+ BYTE ext_nItemsNum;
+ BOOL ext_fItemsValid;
+ tContactItems ext_mpItemsDesc[MAXEXTRACOLUMNS+10]; //up to 10 items
+
+ WORD iWideExtraImage[MAXEXTRACOLUMNS];
+
+
+};
+
+
+
+struct ClcModernFontInfo {
+ HFONT hFont;
+ int fontHeight,changed;
+ COLORREF colour;
+ BYTE effect;
+ COLORREF effectColour1;
+ COLORREF effectColour2;
+};
+
+struct ClcData {
+ struct ClcGroup list;
+ int max_row_height;
+
+ int yScroll;
+ int selection;
+ struct ClcFontInfo fontInfo[FONTID_MAX+1];
+ int scrollTime;
+ HIMAGELIST himlHighlight;
+ int groupIndent;
+ TCHAR szQuickSearch[128];
+ int iconXSpace;
+ HWND hwndRenameEdit;
+ COLORREF bkColour,selBkColour,selTextColour,hotTextColour,quickSearchColour;
+ int iDragItem,iInsertionMark;
+ int dragStage;
+ POINT ptDragStart;
+ int dragAutoScrolling;
+ int dragAutoScrollHeight;
+ int leftMargin;
+ int insertionMarkHitHeight;
+ HBITMAP hBmpBackground;
+ int backgroundBmpUse,bkChanged;
+ int iHotTrack;
+ int gammaCorrection;
+ DWORD greyoutFlags; //see m_clc.h
+ DWORD offlineModes;
+ DWORD exStyle;
+ POINT ptInfoTip;
+ int infoTipTimeout;
+ HANDLE hInfoTipItem;
+ HIMAGELIST himlExtraColumns;
+ int extraColumnsCount;
+ int extraColumnSpacing;
+ int checkboxSize;
+ int showSelAlways;
+ int showIdle;
+ int noVScrollbar;
+ int useWindowsColours;
+ int NeedResort;
+ SortedList lCLCContactsCache;
+ BYTE HiLightMode;
+ BYTE doubleClickExpand;
+ int MetaIgnoreEmptyExtra;
+ BYTE expandMeta;
+ BYTE IsMetaContactsEnabled;
+ time_t last_tick_time;
+ BOOL force_in_dialog;
+ int subIndent;
+ int rightMargin;
+ HBITMAP hMenuBackground;
+ DWORD MenuBkColor, MenuBkHiColor, MenuTextColor, MenuTextHiColor;
+ int MenuBmpUse;
+
+ // Row height
+ int *row_heights;
+ int row_heights_size;
+ int row_heights_allocated;
+
+ // Avatar cache
+ int use_avatar_service;
+ IMAGE_ARRAY_DATA avatar_cache;
+
+ // Row
+ int row_min_heigh;
+ int row_border;
+ int row_before_group_space;
+
+ BOOL row_variable_height;
+ BOOL row_align_left_items_to_left;
+ BOOL row_align_right_items_to_right;
+ int row_items[NUM_ITEM_TYPE];
+ BOOL row_hide_group_icon;
+ BYTE row_align_group_mode;
+
+ // Avatar
+ BOOL avatars_show;
+ BOOL avatars_draw_border;
+ COLORREF avatars_border_color;
+ BOOL avatars_round_corners;
+ BOOL avatars_use_custom_corner_size;
+ int avatars_custom_corner_size;
+ BOOL avatars_ignore_size_for_row_height;
+ BOOL avatars_draw_overlay;
+ int avatars_overlay_type;
+
+ int avatars_maxheight_size;
+ int avatars_maxwidth_size;
+
+ // Icon
+ BOOL icon_hide_on_avatar;
+ BOOL icon_draw_on_avatar_space;
+ BOOL icon_ignore_size_for_row_height;
+
+ // Contact time
+ BOOL contact_time_show;
+ BOOL contact_time_show_only_if_different;
+
+ // Text
+ BOOL text_rtl;
+ BOOL text_align_right;
+ BOOL text_replace_smileys;
+ BOOL text_resize_smileys;
+ int text_smiley_height;
+ BOOL text_use_protocol_smileys;
+ BOOL text_ignore_size_for_row_height;
+
+ // First line
+ BOOL first_line_draw_smileys;
+ BOOL first_line_append_nick;
+
+ // Second line
+ BOOL second_line_show;
+ int second_line_top_space;
+ BOOL second_line_draw_smileys;
+ int second_line_type;
+ TCHAR second_line_text[TEXT_TEXT_MAX_LENGTH];
+ BOOL second_line_xstatus_has_priority;
+ BOOL second_line_show_status_if_no_away;
+ BOOL second_line_show_listening_if_no_away;
+ BOOL second_line_use_name_and_message_for_xstatus;
+
+ // Third line
+ BOOL third_line_show;
+ int third_line_top_space;
+ BOOL third_line_draw_smileys;
+ int third_line_type;
+ TCHAR third_line_text[TEXT_TEXT_MAX_LENGTH];
+ BOOL third_line_xstatus_has_priority;
+ BOOL third_line_show_status_if_no_away;
+ BOOL third_line_show_listening_if_no_away;
+ BOOL third_line_use_name_and_message_for_xstatus;
+ struct ClcModernFontInfo fontModernInfo[FONTID_MODERN_MAX+1];
+ HWND hWnd;
+ BYTE menuOwnerType;
+ int menuOwnerID;
+ DWORD m_paintCouter; //range is enoght to 49 days if painting will occure each one millisecond
+ BYTE useMetaIcon;
+ BYTE drawOverlayedStatus;
+ int nInsertionLevel;
+
+ BYTE dbbMetaHideExtra;
+ BYTE dbbBlendInActiveState;
+ BYTE dbbBlend25;
+
+ XPTHANDLE hCheckBoxTheme;
+ BYTE bCompactMode;
+
+ HIMAGELIST himlWideExtraColumns;
+
+};
+
+struct SHORTDATA
+{
+ HWND hWnd;
+ BOOL contact_time_show_only_if_different;
+ int text_smiley_height;
+ BOOL text_replace_smileys;
+ BOOL text_use_protocol_smileys;
+
+ // Second line
+ BOOL second_line_show;
+ BOOL second_line_draw_smileys;
+ int second_line_type;
+ TCHAR second_line_text[TEXT_TEXT_MAX_LENGTH];
+ BOOL second_line_xstatus_has_priority;
+ BOOL second_line_show_status_if_no_away;
+ BOOL second_line_show_listening_if_no_away;
+ BOOL second_line_use_name_and_message_for_xstatus;
+
+ // Third line
+ BOOL third_line_show;
+ BOOL third_line_draw_smileys;
+ int third_line_type;
+ TCHAR third_line_text[TEXT_TEXT_MAX_LENGTH];
+ BOOL third_line_xstatus_has_priority;
+ BOOL third_line_show_status_if_no_away;
+ BOOL third_line_show_listening_if_no_away;
+ BOOL third_line_use_name_and_message_for_xstatus;
+};
+
+
+typedef struct tagOVERLAYICONINFO
+{
+ char *name;
+ char *description;
+ int id;
+ int listID;
+} OVERLAYICONINFO;
+
+//clc.c
+void ClcOptionsChanged(void);
+
+//clcidents.c
+int cliGetRowsPriorTo(struct ClcGroup *group,struct ClcGroup *subgroup,int contactIndex);
+int FindItem(HWND hwnd,struct ClcData *dat,HANDLE hItem,struct ClcContact **contact,struct ClcGroup **subgroup,int *isVisible, BOOL isIgnoreSubcontacts );
+int cliGetRowByIndex(struct ClcData *dat,int testindex,struct ClcContact **contact,struct ClcGroup **subgroup);
+HANDLE ContactToHItem(struct ClcContact *contact);
+HANDLE ContactToItemHandle(struct ClcContact *contact,DWORD *nmFlags);
+void ClearRowByIndexCache();
+
+//clcitems.c
+struct ClcGroup *cli_AddGroup(HWND hwnd,struct ClcData *dat,const TCHAR *szName,DWORD flags,int groupId,int calcTotalMembers);
+void cli_FreeGroup(struct ClcGroup *group);
+int cli_AddInfoItemToGroup(struct ClcGroup *group,int flags,const TCHAR *pszText);
+void cliRebuildEntireList(HWND hwnd,struct ClcData *dat);
+void cli_DeleteItemFromTree(HWND hwnd,HANDLE hItem);
+void cli_AddContactToTree(HWND hwnd,struct ClcData *dat,HANDLE hContact,int updateTotalCount,int checkHideOffline);
+void cli_SortCLC(HWND hwnd,struct ClcData *dat,int useInsertionSort);
+int GetNewSelection(struct ClcGroup *group,int selection, int direction);
+
+//clcmsgs.c
+LRESULT cli_ProcessExternalMessages(HWND hwnd,struct ClcData *dat,UINT msg,WPARAM wParam,LPARAM lParam);
+
+//clcutils.c
+void cliRecalcScrollBar(HWND hwnd,struct ClcData *dat);
+void cliBeginRenameSelection(HWND hwnd,struct ClcData *dat);
+int cliHitTest(HWND hwnd,struct ClcData *dat,int testx,int testy,struct ClcContact **contact,struct ClcGroup **group,DWORD *flags);
+void cliScrollTo(HWND hwnd,struct ClcData *dat,int desty,int noSmooth);
+int GetDropTargetInformation(HWND hwnd,struct ClcData *dat,POINT pt);
+void LoadCLCOptions(HWND hwnd,struct ClcData *dat);
+
+
+//clcpaint.c
+void CLCPaint_cliPaintClc(HWND hwnd,struct ClcData *dat,HDC hdc,RECT *rcPaint);
+
+//clcopts.c
+int ClcOptInit(WPARAM wParam,LPARAM lParam);
+DWORD GetDefaultExStyle(void);
+void GetFontSetting(int i,LOGFONT *lf,COLORREF *colour,BYTE *effect, COLORREF *eColour1,COLORREF *eColour2);
+
+//clistsettings.c
+TCHAR * GetContactDisplayNameW( HANDLE hContact, int mode );
+
+//groups.c
+TCHAR* GetGroupNameTS( int idx, DWORD* pdwFlags );
+int RenameGroupT(WPARAM groupID, LPARAM newName);
+
+int GetContactCachedStatus(HANDLE hContact);
+char *GetContactCachedProtocol(HANDLE hContact);
+
+#endif /* _CLC_H_ */
diff --git a/plugins/Clist_modern/src/hdr/modern_clcpaint.h b/plugins/Clist_modern/src/hdr/modern_clcpaint.h
new file mode 100644
index 0000000000..9c2a2d68d6
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_clcpaint.h
@@ -0,0 +1,191 @@
+#ifndef modern_clcpaint_h__
+#define modern_clcpaint_h__
+
+extern class CLCPaint g_clcPainter;
+class CLCPaint
+{
+
+public:
+ CLCPaint();
+ ~CLCPaint() {};
+
+ CLINTERFACE void cliPaintClc( HWND hwnd, struct ClcData *dat, HDC hdc, RECT *rcPaint );
+ CLINTERFACE tPaintCallbackProc PaintCallbackProc( HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData );
+
+ BOOL IsForegroundWindow( HWND hWnd );
+ HFONT ChangeToFont( HDC hdc, struct ClcData *dat, int id, int *fontHeight );
+ int GetBasicFontID( struct ClcContact * contact );
+ void GetTextSize( SIZE *text_size, HDC hdcMem, RECT free_row_rc, TCHAR *szText, SortedList *plText, UINT uTextFormat, int smiley_height );
+ void AddParam( MODERNMASK * mpModernMask, DWORD dwParamHash, const char* szValue, DWORD dwValueHash );
+ BOOL CheckMiniMode( struct ClcData *dat, BOOL selected, BOOL hot );
+
+private:
+ static const int HORIZONTAL_SPACE;
+ static const int EXTRA_CHECKBOX_SPACE;
+ static const int EXTRA_SPACE;
+ static const int SELECTION_BORDER;
+ static const int MIN_TEXT_WIDTH;
+ static const int BUF2SIZE;
+
+ static const BYTE GIM_SELECTED_AFFECT;
+ static const BYTE GIM_HOT_AFFECT;
+ static const BYTE GIM_TEMP_AFFECT;
+ static const BYTE GIM_IDLE_AFFECT;
+ static const BYTE GIM_EXTRAICON_AFFECT;
+ static const BYTE GIM_STATUSICON_AFFECT;
+ static const BYTE GIM_AVATAR_AFFECT;
+
+ enum tagenumHASHINDEX
+ {
+ hi_Module=0,
+ hi_ID,
+ hi_Type,
+ hi_Open,
+ hi_IsEmpty,
+ hi_SubPos,
+ hi_Protocol,
+ hi_RootGroup,
+ hi_Status,
+ hi_HasAvatar,
+ hi_GroupPos,
+ hi_Selected,
+ hi_Hot,
+ hi_Odd,
+ hi_Indent,
+ hi_Index,
+ hi_Name,
+ hi_Group,
+ hi_True,
+ hi_False,
+ hi_ONLINE,
+ hi_AWAY,
+ hi_DND,
+ hi_NA,
+ hi_OCCUPIED,
+ hi_FREECHAT,
+ hi_INVISIBLE,
+ hi_OUTTOLUNCH,
+ hi_ONTHEPHONE,
+ hi_IDLE,
+ hi_OFFLINE,
+ hi_Row,
+ hi_CL,
+ hi_SubContact,
+ hi_MetaContact,
+ hi_Contact,
+ hi_Divider,
+ hi_Info,
+ hi_First_Single,
+ hi_First,
+ hi_Middle,
+ hi_Mid,
+ hi_Single,
+ hi_Last,
+ hi_Rate,
+ hi_None,
+ hi_Low,
+ hi_Medium,
+ hi_High,
+ hi_State,
+ hi_stActive,
+ hi_stInactive,
+ //ADD new item above here
+ hi_LastItem
+ } enumHASHINDEX;
+ static const char * HASHTEXT[hi_LastItem];
+ static DWORD HASH[hi_LastItem];
+
+
+
+ void _FillQuickHash();
+ void _SetHotTrackColour( HDC hdc, struct ClcData *dat );
+ int _GetStatusOnlineness( int status );
+ int _GetGeneralisedStatus();
+ int _GetRealStatus( struct ClcContact * pContact, int nStatus );
+ RECT _GetRectangle( struct ClcData *dat, RECT *row_rc, RECT *free_row_rc, int *left_pos, int *right_pos, BOOL left, int real_width, int width, int height, int horizontal_space );
+ void _DrawTextSmiley( HDC hdcMem, RECT * free_rc, SIZE * text_size, TCHAR *szText, int len, SortedList *plText, UINT uTextFormat, BOOL ResizeSizeSmiley );
+ void _AddParameter( MODERNMASK * mpModernMask, MASKPARAM * lpParam );
+ void _AddParamShort( MODERNMASK * mpModernMask, DWORD dwParamIndex, DWORD dwValueIndex );
+ void _FillParam( MASKPARAM * lpParam, DWORD dwParamHash, const char* szValue, DWORD dwValueHash );
+ MODERNMASK * _GetCLCContactRowBackModernMask( struct ClcGroup * group, struct ClcContact * Drawing, int indent, int index, BOOL selected, BOOL hottrack, struct ClcData * dat );
+ void _RTLRect( RECT *rect, int width, int offset );
+ void _PaintRowItemsEx( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT row_rc, RECT free_row_rc, int left_pos, int right_pos, int selected, int hottrack, RECT *rcPaint );
+ void _DrawStatusIcon( struct ClcContact * Drawing, struct ClcData *dat, int iImage, HDC hdcMem, int x, int y, int cx, int cy, DWORD colorbg, DWORD colorfg, int mode );
+ BOOL _DrawNonEnginedBackground( HWND hwnd, HDC hdcMem, RECT * rcPaint, RECT clRect, struct ClcData * dat );
+ void _PaintClc( HWND hwnd, struct ClcData *dat, HDC hdc, RECT *rcPaint );
+ void _StoreItemPos( struct ClcContact *contact, int ItemType, RECT * rc );
+ void _CalcItemsPos( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *in_row_rc, RECT *in_free_row_rc, int left_pos, int right_pos, int selected, int hottrack );
+ BOOL __IsVisible( RECT * firtRect, RECT * secondRect );
+ void _GetBlendMode( IN struct ClcData *dat, IN struct ClcContact * Drawing, IN BOOL selected, IN BOOL hottrack, IN BOOL bFlag, OUT COLORREF * OutColourFg, OUT int * OutMode );
+ void _DrawContactItems( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *row_rc, RECT *free_row_rc, int left_pos, int right_pos, int selected, int hottrack, RECT *rcPaint );
+ void _PaintRowItems ( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT row_rc, RECT free_row_rc, int left_pos, int right_pos, int selected, int hottrack, RECT *rcPaint );
+
+ void _DrawContactAvatar ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *row_rc, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem );
+ void _DrawContactIcon ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem );
+ void _DrawContactText ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem, UINT uTextFormat );
+ void _DrawContactSubText ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem, UINT uTextFormat, BYTE itemType );
+ void _DrawContactTime ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem );
+ void _DrawContactExtraIcon ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * rc, int iImage );
+ void _DrawContactSelection ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT *rcPaint, RECT * prcItem );
+ void _DrawContactLine ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *free_row_rc, RECT *rcPaint, RECT& text_rc );
+
+ int _rcWidth( RECT *rc ) { return rc->right-rc->left; }
+ int _rcHeight( RECT *rc ) { return rc->bottom-rc->top; }
+
+private:
+ enum enDrawMode
+ {
+ DM_LAYERED = 1, // Draw normal skin on 32 bit with alpha layer
+ DM_NON_LAYERED = 2, // Draw skinnable, but does not take care about alpha
+ DM_CLASSIC = 4, // Old style draw for classic
+ DM_CONTROL = 8, // Draw as control according to windows color scheme
+ DM_FLOAT = 16, // Float mode
+ DM_GRAY = 32, // Grayed mode
+ DM_GREYALTERNATE = 64, // Gray odd lines
+ DM_DRAW_OFFSCREEN = DM_FLOAT | DM_CONTROL | DM_NON_LAYERED | DM_CLASSIC,
+
+ };
+
+ inline int _DetermineDrawMode( HWND hWnd, struct ClcData *dat );
+
+ struct _PaintContext
+ {
+ enum
+ { release_none = 0,
+ release_hdcmem2 = 1,
+ release_hdcmem = 2
+ };
+ HDC hdcMem;
+ HDC hdcMem2;
+
+ HBITMAP hBmpOsb2;
+ HBITMAP oldbmp2;
+
+ HBITMAP hBmpOsb;
+ HBITMAP oldbmp;
+
+ HBRUSH hBrushAlternateGrey;
+ COLORREF tmpbkcolour;
+ COLORREF tmpforecolour;
+
+ DWORD fRelease;
+ _PaintContext( HDC _hdcMem = NULL) :
+ hdcMem ( _hdcMem ), hdcMem2( NULL ),
+ hBmpOsb2( NULL ), oldbmp2( NULL ),
+ hBmpOsb( NULL ), oldbmp( NULL ),
+ hBrushAlternateGrey ( NULL ),
+ tmpbkcolour( 0 ), tmpforecolour( 0 ),
+ fRelease ( release_none ) {};
+ };
+ inline void _PreparePaintContext( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT& clRect, _PaintContext& pc );
+ inline void _DrawBackground( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT* rcPaint, RECT& clRect, _PaintContext& pc );
+ inline void _DrawLines( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT* rcPaint, RECT& clRect, _PaintContext& pc );
+ inline void _DrawInsertionMark( struct ClcData * dat, RECT& clRect, _PaintContext& pc );
+ inline void _CopyPaintToDest( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT* rcPaint, RECT& clRect, _PaintContext& pc );
+ inline void _FreePaintContext( _PaintContext& pc );
+
+ // void _PaintClcOld( HWND hwnd, struct ClcData *dat, HDC hdc, RECT *rcPaint );
+};
+
+
+#endif // modern_clcpaint_h__
diff --git a/plugins/Clist_modern/src/hdr/modern_clist.h b/plugins/Clist_modern/src/hdr/modern_clist.h
new file mode 100644
index 0000000000..527bf18b64
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_clist.h
@@ -0,0 +1,165 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+*/
+#pragma once
+
+#ifndef _CLIST_H_
+#define _CLIST_H_
+
+void LoadContactTree(void);
+int ExtIconFromStatusMode(HANDLE hContact, const char *szProto,int status);
+HTREEITEM GetTreeItemByHContact(HANDLE hContact);
+void cli_ChangeContactIcon(HANDLE hContact,int iIcon,int add);
+int GetContactInfosForSort(HANDLE hContact,char **Proto,TCHAR **Name,int *Status);
+
+typedef HMONITOR ( WINAPI *pfnMyMonitorFromPoint )(POINT,DWORD);
+extern pfnMyMonitorFromPoint MyMonitorFromPoint;
+
+typedef HMONITOR( WINAPI *pfnMyMonitorFromWindow) (HWND, DWORD);
+extern pfnMyMonitorFromWindow MyMonitorFromWindow;
+
+typedef BOOL(WINAPI *pfnMyGetMonitorInfo) (HMONITOR, LPMONITORINFO);
+extern pfnMyGetMonitorInfo MyGetMonitorInfo;
+
+///////////////////////////////////////////////////////////////////////////////
+
+class CSmileyString
+{
+public:
+ SortedList* plText;
+ int iMaxSmileyHeight;
+
+ CSmileyString() : plText( NULL ), iMaxSmileyHeight( 0 ) {};
+ CSmileyString( const CSmileyString& ssIn )
+ {
+ _CopySmileyList( ssIn.plText );
+ iMaxSmileyHeight = ssIn.iMaxSmileyHeight;
+ }
+
+ CSmileyString& operator= ( const CSmileyString& ssIn )
+ {
+ DestroySmileyList();
+ _CopySmileyList( ssIn.plText );
+ iMaxSmileyHeight = ssIn.iMaxSmileyHeight;
+ return *this;
+ }
+
+ ~CSmileyString()
+ {
+ DestroySmileyList();
+ }
+
+ void ReplaceSmileys(struct SHORTDATA *dat, struct displayNameCacheEntry *pdnce, TCHAR *szText, BOOL replace_smileys);
+
+ /** Destroy smiley list */
+ void DestroySmileyList();
+ /** Copy Smiley List */
+ void _CopySmileyList( SortedList *plInput );
+ void AddListeningToIcon(struct SHORTDATA *dat, struct displayNameCacheEntry *pdnce, TCHAR *szText, BOOL replace_smileys);
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+struct displayNameCacheEntry : public ClcCacheEntryBase
+{
+ int m_cache_nNoHiddenOffline;
+
+ char* m_cache_cszProto;
+ bool m_cache_bProtoNotExists;
+ int m_cache_nStatus;
+ int m_cache_nHiddenSubcontact;
+
+ int i;
+ int ApparentMode;
+ int NotOnList;
+ int IdleTS;
+ void* ClcContact;
+ BYTE IsExpanded;
+ bool isUnknown;
+
+ TCHAR* szSecondLineText;
+ CSmileyString ssSecondLine;
+
+ TCHAR* szThirdLineText;
+ CSmileyString ssThirdLine;
+
+ HANDLE hTimeZone;
+ DWORD dwLastMsgTime;
+
+ void getName(void);
+ void freeName(void);
+};
+
+typedef displayNameCacheEntry *pdisplayNameCacheEntry, *PDNCE;
+
+///////////////////////////////////////////////////////////////////////////////
+
+typedef struct tagEXTRASLOTINFO
+{
+ union
+ {
+ TCHAR * ptszSlotName; // one of this string should be given
+ char * pszSlotName;
+ };
+ char * pszSlotID;
+ BOOL fUnicode;
+ BYTE iSlot; // the slot 10-16 are available, do not use
+} EXTRASLOTINFO;
+
+#define CLVM_FILTER_PROTOS 1
+#define CLVM_FILTER_GROUPS 2
+#define CLVM_FILTER_STATUS 4
+#define CLVM_FILTER_VARIABLES 8
+#define CLVM_STICKY_CONTACTS 16
+#define CLVM_FILTER_STICKYSTATUS 32
+#define CLVM_FILTER_LASTMSG 64
+#define CLVM_FILTER_LASTMSG_OLDERTHAN 128
+#define CLVM_FILTER_LASTMSG_NEWERTHAN 256
+
+#define CLVM_PROTOGROUP_OP 1
+#define CLVM_GROUPSTATUS_OP 2
+#define CLVM_AUTOCLEAR 4
+#define CLVM_INCLUDED_UNGROUPED 8
+#define CLVM_USELASTMSG 16
+
+#define CLVM_USEGROUPS 32
+#define CLVM_DONOTUSEGROUPS 64
+
+//changes the 'use groups' flag and call CLUI v0.8.0.16+
+//wParam=newValue
+//lParam=0
+//returns 0 on success, nonzero on failure
+//newValue is 0 to not use gruops, 1 to use groups
+//or -1 to toggle the value
+#define MS_CLIST_SETUSEGROUPS "CList/SetUseGroups"
+
+
+#if defined(_UNICODE)
+#define CLVM_MODULE "CLVM_W"
+#else
+#define CLVM_MODULE "CLVM"
+#endif
+
+#define GROUPF_SHOWOFFLINE 0x40
+
+#endif \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_clui.h b/plugins/Clist_modern/src/hdr/modern_clui.h
new file mode 100644
index 0000000000..eb353f4609
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_clui.h
@@ -0,0 +1,193 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 modern_clui_h__
+#define modern_clui_h__
+
+#include "windowsX.h"
+#define HANDLE_MESSAGE( _message, _fn) \
+ case (_message): return This->_fn((_message), (wParam), (lParam))
+
+class CLUI
+{
+public:
+ static HWND m_hWnd;
+ static CLUI * m_pCLUI;
+ static BOOL m_fMainMenuInited;
+
+private:
+ CLUI(); // is protected use InitClui to initialize instead
+
+public:
+ ~CLUI();
+
+ static HRESULT InitClui() { m_pCLUI = new CLUI(); return S_OK; };
+ static HWND& ClcWnd() { return pcli->hwndContactTree; }
+ static HWND& CluiWnd() { return pcli->hwndContactList; }
+ static CLUI * GetClui() { return m_pCLUI; }
+ static BOOL IsMainMenuInited() { return CLUI::m_fMainMenuInited; }
+
+ CLINTERFACE void cliOnCreateClc();
+
+ EVENTHOOK( OnEvent_ModulesLoaded );
+ EVENTHOOK( OnEvent_ContactMenuPreBuild );
+ EVENTHOOK( OnEvent_DBSettingChanging );
+ EVENTHOOK( OnEvent_FontReload );
+
+ SERVICE( Service_ShowMainMenu );
+ SERVICE( Service_ShowStatusMenu );
+ SERVICE( Service_Menu_ShowContactAvatar );
+ SERVICE( Service_Menu_HideContactAvatar );
+
+ static LRESULT CALLBACK cli_ContactListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+ {
+ CLUI * This = m_pCLUI;
+ if ( !m_hWnd ) m_hWnd = hwnd;
+
+ BOOL bHandled = FALSE;
+ LRESULT lRes= This->PreProcessWndProc( msg, wParam, lParam, bHandled );
+ if ( bHandled ) return lRes;
+
+ switch ( msg )
+ {
+ HANDLE_MESSAGE( WM_NCCREATE, OnNcCreate );
+ HANDLE_MESSAGE( WM_CREATE, OnCreate );
+ HANDLE_MESSAGE( UM_CREATECLC, OnCreateClc );
+ HANDLE_MESSAGE( UM_SETALLEXTRAICONS, OnSetAllExtraIcons );
+ HANDLE_MESSAGE( WM_INITMENU, OnInitMenu );
+ HANDLE_MESSAGE( WM_SIZE, OnSizingMoving );
+ HANDLE_MESSAGE( WM_SIZING, OnSizingMoving );
+ HANDLE_MESSAGE( WM_MOVE, OnSizingMoving );
+ HANDLE_MESSAGE( WM_EXITSIZEMOVE, OnSizingMoving );
+ HANDLE_MESSAGE( WM_WINDOWPOSCHANGING, OnSizingMoving );
+ HANDLE_MESSAGE( WM_DISPLAYCHANGE, OnSizingMoving );
+ HANDLE_MESSAGE( WM_THEMECHANGED, OnThemeChanged );
+ HANDLE_MESSAGE( WM_DWMCOMPOSITIONCHANGED, OnDwmCompositionChanged );
+ HANDLE_MESSAGE( UM_SYNCCALL, OnSyncCall );
+ HANDLE_MESSAGE( UM_UPDATE, OnUpdate );
+ HANDLE_MESSAGE( WM_NCACTIVATE, OnNcPaint );
+ HANDLE_MESSAGE( WM_PRINT, OnNcPaint );
+ HANDLE_MESSAGE( WM_NCPAINT, OnNcPaint );
+ HANDLE_MESSAGE( WM_ERASEBKGND, OnEraseBkgnd );
+ HANDLE_MESSAGE( WM_PAINT, OnPaint );
+ HANDLE_MESSAGE( WM_LBUTTONDOWN, OnLButtonDown );
+ HANDLE_MESSAGE( WM_PARENTNOTIFY, OnParentNotify );
+ HANDLE_MESSAGE( WM_SETFOCUS, OnSetFocus );
+ HANDLE_MESSAGE( WM_TIMER, OnTimer );
+ HANDLE_MESSAGE( WM_ACTIVATE, OnActivate );
+ HANDLE_MESSAGE( WM_SETCURSOR, OnSetCursor );
+ HANDLE_MESSAGE( WM_MOUSEACTIVATE, OnMouseActivate );
+ HANDLE_MESSAGE( WM_NCLBUTTONDOWN, OnNcLButtonDown );
+ HANDLE_MESSAGE( WM_NCLBUTTONDBLCLK, OnNcLButtonDblClk );
+ HANDLE_MESSAGE( WM_NCHITTEST, OnNcHitTest );
+ HANDLE_MESSAGE( WM_SHOWWINDOW, OnShowWindow );
+ HANDLE_MESSAGE( WM_SYSCOMMAND, OnSysCommand );
+ HANDLE_MESSAGE( WM_KEYDOWN, OnKeyDown );
+ HANDLE_MESSAGE( WM_GETMINMAXINFO, OnGetMinMaxInfo );
+ HANDLE_MESSAGE( WM_MOVING, OnMoving );
+ HANDLE_MESSAGE( WM_NOTIFY, OnNotify );
+ HANDLE_MESSAGE( WM_CONTEXTMENU, OnContextMenu );
+ HANDLE_MESSAGE( WM_MEASUREITEM, OnMeasureItem );
+ HANDLE_MESSAGE( WM_DRAWITEM, OnDrawItem );
+ HANDLE_MESSAGE( WM_DESTROY, OnDestroy );
+ default:
+ return This->DefCluiWndProc( msg, wParam, lParam );
+ }
+ return FALSE;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // METHODS
+ //
+private:
+ HRESULT CreateCLC();
+ HRESULT FillAlphaChannel( HDC hDC, RECT* prcParent, BYTE bAlpha);
+ HRESULT SnappingToEdge( WINDOWPOS * lpWindowPos );
+ HRESULT LoadDllsRuntime();
+ HRESULT RegisterAvatarMenu(); // TODO move to CLC class
+ HRESULT CreateCluiFrames();
+ HRESULT CreateCLCWindow(const HWND parent);
+ HRESULT CreateUIFrames();
+
+ LRESULT DefCluiWndProc( UINT msg, WPARAM wParam, LPARAM lParam )
+ {
+ return corecli.pfnContactListWndProc( m_hWnd, msg, wParam, lParam );
+ }
+
+ // MessageMap
+ LRESULT PreProcessWndProc( UINT msg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
+ LRESULT OnSizingMoving( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnThemeChanged( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnDwmCompositionChanged( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnSyncCall( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnUpdate( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnInitMenu( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnNcPaint( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnEraseBkgnd( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnNcCreate( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnPaint( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnCreate( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnSetAllExtraIcons( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnCreateClc( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnLButtonDown( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnParentNotify( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnSetFocus( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnStatusBarUpdateTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnAutoAlphaTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnSmoothAlphaTransitionTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnDelayedSizingTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnBringOutTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnBringInTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnUpdateBringTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnActivate( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnSetCursor( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnMouseActivate( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnNcLButtonDown( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnNcLButtonDblClk( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnNcHitTest( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnShowWindow( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnSysCommand( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnKeyDown( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnGetMinMaxInfo( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnMoving( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnNotify( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnNewContactNotify( NMCLISTCONTROL * pnmc );
+ LRESULT OnListRebuildNotify( NMCLISTCONTROL * pnmc );
+ LRESULT OnListSizeChangeNotify( NMCLISTCONTROL * pnmc );
+ LRESULT OnClickNotify( NMCLISTCONTROL * pnmc );
+ LRESULT OnContextMenu( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnMeasureItem( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnDrawItem( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnDestroy( UINT msg, WPARAM wParam, LPARAM lParam );
+
+protected:
+ HMODULE m_hDwmapiDll;
+ HMODULE m_hUserDll;
+
+ enum { SNAPTOEDGESENSIVITY = 30 };
+};
+
+#endif // modern_clui_h__ \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_cluiframes.h b/plugins/Clist_modern/src/hdr/modern_cluiframes.h
new file mode 100644
index 0000000000..e2c1aade78
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_cluiframes.h
@@ -0,0 +1,150 @@
+/*
+Miranda ICQ: the free icq client for MS Windows
+Copyright (C) 2000-2 Richard Hughes, Roland Rabien & Tristan Van de Vreede
+
+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.
+*/
+
+#pragma once
+
+#ifndef _CLUIFRAMES_H_
+#define _CLUIFRAMES_H_
+
+#include "../m_api/m_skin_eng.h"
+
+int LoadCLUIFramesModule(void);
+int UnLoadCLUIFramesModule(void);
+int CLUIFramesGetMinHeight();
+int CLUIFramesOnClistResize(WPARAM wParam,LPARAM lParam);
+int CLUIFrames_GetTotalHeight();
+
+typedef struct tagProtocolData {
+ char *RealName;
+ int protopos;
+ boolean show;
+} ProtocolData;
+
+typedef struct
+{
+ int order;
+ int realpos;
+}SortData;
+
+
+
+
+//============
+#define CLUIFRAMESSETALIGN "CLUIFramesSetAlign"
+
+#define CLUIFRAMESSETALIGNALTOP "CLUIFramesSetAlignalTop"
+#define CLUIFRAMESSETALIGNALCLIENT "CLUIFramesSetAlignalClient"
+#define CLUIFRAMESSETALIGNALBOTTOM "CLUIFramesSetAlignalBottom"
+#define CLUIFRAMESSETFLOATING "Set_Floating"
+
+#define CLUIFRAMESMOVEUPDOWN "CLUIFramesMoveUpDown"
+#define CLUIFRAMESMOVEUP "CLUIFramesMoveUp"
+#define CLUIFRAMESMOVEDOWN "CLUIFramesMoveDown"
+
+typedef struct tagMenuHandles
+{
+ HANDLE MainMenuItem;
+ HANDLE MIVisible,MITitle,MITBVisible,MILock,MIColl,MIFloating,MIAlignRoot;
+ HANDLE MIAlignTop,MIAlignClient,MIAlignBottom;
+ HANDLE MIBorder;
+ HANDLE MIPosRoot;
+ HANDLE MIPosUp,MIPosDown;
+} FrameMenuHandles;
+
+typedef struct tagFrameTitleBar{
+ HWND hwnd;
+ HWND TitleBarbutt;
+ HWND hwndTip;
+
+ TCHAR* tbname;
+ TCHAR* tooltip;
+
+ char * sztbname;
+ char * sztooltip;
+
+ HMENU hmenu;
+ HICON hicon;
+
+ BOOLEAN ShowTitleBar;
+ BOOLEAN ShowTitleBarTip;
+ COLORREF BackColour;
+ COLORREF TextColour;
+ int oldstyles;
+ POINT oldpos;
+ RECT wndSize;
+} FrameTitleBar;
+
+typedef struct _DockOpt
+{
+ HWND hwndLeft;
+ HWND hwndRight;
+}
+DockOpt;
+typedef struct _tagFrameWnd{
+ int id;
+ HWND hWnd ;
+ RECT wndSize;
+ TCHAR * Name;
+ char * szName;
+ int align;
+ int height;
+ int dwFlags;
+ BOOLEAN Locked;
+ BOOLEAN visible;
+ BOOLEAN needhide;
+ BOOLEAN collapsed;
+ int prevvisframe;
+ int HeightWhenCollapsed;
+ FrameTitleBar TitleBar;
+ FrameMenuHandles MenuHandles;
+ int oldstyles;
+ BOOLEAN floating;
+ HWND ContainerWnd;
+ POINT FloatingPos;
+ POINT FloatingSize;
+ BOOLEAN minmaxenabled;
+ BOOLEAN UseBorder;
+ int order;
+ DockOpt dockOpt;
+ HWND OwnerWindow;
+ tPaintCallbackProc PaintCallbackProc;
+ sPaintRequest * PaintData;
+ BOOLEAN bQueued;
+ HRGN UpdateRgn;
+
+} FRAMEWND;
+
+#define OFFSET_PROTOPOS 200
+#define OFFSET_VISIBLE 400
+
+#define CLUIFrameSubContainerClassName _T("CLUIFrameSubContainer")
+#define CLUIFrameTitleBarClassName _T("CLUIFrameTitleBar")
+#define CLUIFrameModule "CLUIFrames"
+
+//integrated menu module
+#define MS_INT_MENUMEASUREITEM "CLUIFrames/IntMenuMeasureItem"
+#define MS_INT_MENUDRAWITEM "CLUIFrames/IntMenuDrawItem"
+#define MS_INT_MENUPROCESSCOMMAND "CLUIFrames/IntMenuProcessCommand"
+#define MS_INT_MODIFYMENUITEM "CLUIFrames/IntModifyMenuItem"
+
+#endif
+
+
+
+
diff --git a/plugins/Clist_modern/src/hdr/modern_commonheaders.h b/plugins/Clist_modern/src/hdr/modern_commonheaders.h
new file mode 100644
index 0000000000..922e0b0d90
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_commonheaders.h
@@ -0,0 +1,460 @@
+#ifndef commonheaders_h__
+#define commonheaders_h__
+
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+*/
+
+#pragma once
+#define MIRANDA_VER 0x0A00
+
+#define _WIN32_WINNT 0x0501
+
+#ifndef _WIN32_IE
+#define _WIN32_IE 0x0501
+#endif
+
+#ifndef DB_USEHELPERFUNCTIONS // to supress static inline db helpers
+#define DB_NOHELPERFUNCTIONS
+#endif
+
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS // to suppress secure warnings in VC2005
+#endif
+
+#ifndef _CRT_SECURE_NO_DEPRECATE // to suppress secure deprecate warnings in VC2005
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+#if defined (_DEBUG)
+#define TRACE(str) { log0(str); }
+#else
+ #define TRACE(str)
+#endif
+
+#if defined (_DEBUG)
+ #define TRACEVAR(str,n) { log1(str,n); }
+#else
+ #define TRACEVAR(str,n)
+#endif
+
+#if defined (_DEBUG)
+#define TRACET(str) OutputDebugString(str)
+#else
+#define TRACET(str)
+#endif
+
+#define SERVICE(serviceproc) static INT_PTR serviceproc(WPARAM wParam,LPARAM lParam)
+#define EVENTHOOK(eventhookproc) static int eventhookproc(WPARAM wParam,LPARAM lParam)
+#define CLINTERFACE static
+
+#define PLUGININTERFACE extern "C" __declspec( dllexport )
+#define UPDATER_PATH "http://miranda-im.org/download/details.php?action=viewfile&id=3684"
+
+#include "m_stdhdr.h"
+
+#include <windows.h>
+#include <commctrl.h>
+#include <uxtheme.h>
+#include <vssym32.h>
+#include <stdio.h>
+#include <time.h>
+#include <stddef.h>
+//#include <process.h>
+#include <io.h>
+#include <math.h>
+#include <string.h>
+#include <direct.h>
+#include <win2k.h>
+
+#include "modern_global_structure.h"
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_system_cpp.h>
+#include <m_utils.h>
+
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_button.h>
+#include <m_options.h>
+#include <m_protosvc.h>
+#include <m_clist.h>
+#include <m_clistint.h>
+#include <m_skin.h>
+#include <m_contacts.h>
+#include <m_plugins.h>
+#include <m_avatars.h>
+#include <m_genmenu.h>
+#include <m_clui.h>
+#include <m_clc.h>
+#include <m_icolib.h>
+#include <m_userinfo.h>
+#include <m_addcontact.h>
+#include <m_fontservice.h>
+#include <m_file.h>
+#include <m_timezones.h>
+
+#include "modern_clc.h"
+#include "modern_clist.h"
+#include "modern_cluiframes.h"
+#include "m_cluiframes.h"
+#include "m_metacontacts.h"
+#include "../m_api/m_skin_eng.h"
+
+#include "modern_rowheight_funcs.h"
+#include "modern_cache_funcs.h"
+#include "modern_log.h"
+
+#include "richedit.h"
+#include "m_variables.h"
+
+#include "m_smileyadd.h"
+
+#include "../m_api/m_xpTheme.h"
+#include "../resource.h"
+
+#include "modern_layered_window_engine.h"
+
+// module name of MetaContacts plugin
+extern char *g_szMetaModuleName;
+
+//macros to free data and set it pointer to NULL
+#define mir_free_and_nil(x) {mir_free((void*)x); x=NULL;}
+// shared vars
+
+#define CLUI_FRAME_AUTOHIDENOTIFY 512
+#define CLUI_FRAME_SHOWALWAYS 1024
+
+
+//#define alloc(n) mir_alloc(n)
+
+#define MAX_REGS(_A_) (sizeof(_A_)/sizeof(_A_[0]))
+
+#ifndef CS_DROPSHADOW
+#define CS_DROPSHADOW 0x00020000
+#endif
+
+#define MENU_MIRANDAMENU 0xFFFF1234
+#define MENU_STATUSMENU 0xFFFF1235
+#define MENU_MINIMIZE 0xFFFF1236
+
+#define UM_CREATECLC (WM_USER+1)
+#define UM_SETALLEXTRAICONS (WM_USER+2)
+#define UM_UPDATE (WM_USER+50)
+#define UM_SYNCCALL (WM_USER+654)
+
+// Define constants for CLUI_SizingOnBorder SC_SIZE
+
+#define SCF_NONE 0
+#define SCF_LEFT 1
+#define SCF_RIGHT 2
+#define SCF_TOP 3
+#define SCF_BOTTOM 6
+
+char* __cdecl strstri( char *a, const char *b);
+BOOL __cdecl mir_bool_strcmpi(const char *a, const char *b);
+int __cdecl mir_strcmp (const char *a, const char *b);
+int __cdecl mir_strlen (const char *a);
+int __cdecl mir_strcmpi(const char *a, const char *b);
+int __cdecl mir_tstrcmpi(const TCHAR *a, const TCHAR *b);
+BOOL __cdecl mir_bool_tstrcmpi(const TCHAR *a, const TCHAR *b);
+DWORD exceptFunction(LPEXCEPTION_POINTERS EP);
+
+#ifndef MYCMP
+#define MYCMP 1
+#define strcmp(a,b) mir_strcmp(a,b)
+#define strlen(a) mir_strlen(a)
+#endif
+
+// Register of plugin's user
+//
+// wParam = (WPARAM)szSetting - string that describes a user
+// format: Category/ModuleName,
+// eg: "Contact list background/CLUI",
+// "Status bar background/StatusBar"
+// lParam = (LPARAM)dwFlags
+//
+#define MS_BACKGROUNDCONFIG_REGISTER "ModernBkgrCfg/Register"
+
+//
+// Notification about changed background
+// wParam = ModuleName
+// lParam = 0
+#define ME_BACKGROUNDCONFIG_CHANGED "ModernBkgrCfg/Changed"
+
+
+
+HBITMAP ske_CreateDIB32(int cx, int cy);
+
+extern void InitDisplayNameCache(void);
+extern void FreeDisplayNameCache();
+extern int CLUI_ShowWindowMod(HWND hwnd, int cmd);
+
+#ifdef UNICODE
+ #define GSMDF_TCHAR_MY GSMDF_TCHAR|CNF_UNICODE
+#else
+ #define GSMDF_TCHAR_MY 0
+#endif
+
+#ifndef LWA_COLORKEY
+#define LWA_COLORKEY 0x00000001
+#endif
+
+#ifndef AC_SRC_ALPHA
+#define AC_SRC_ALPHA 0x01
+#endif
+
+//#ifdef _DEBUG
+//#define DeleteObject(a) DebugDeleteObject(a)
+//#endif
+
+#define strsetA(a,b) {if (a) mir_free_and_nill(a); a=mir_strdup(b);}
+#define strsetT(a,b) {if (a) mir_free_and_nill(a); a=mir_tstrdup(b);}
+
+extern void TRACE_ERROR();
+extern BOOL DebugDeleteObject(HGDIOBJ a);
+extern BOOL mod_DeleteDC(HDC hdc);
+extern BOOL ske_ResetTextEffect(HDC hdc);
+extern BOOL ske_SelectTextEffect(HDC hdc, BYTE EffectID, DWORD FirstColor, DWORD SecondColor);
+extern void IvalidateDisplayNameCache(DWORD mode);
+
+typedef BOOL (WINAPI *pfnTryEnterCriticalSection)( LPCRITICAL_SECTION );
+extern pfnTryEnterCriticalSection fnTryEnterCriticalSection;
+
+typedef BOOL (WINAPI *pfnGetScrollBarInfo)( HWND, LONG, PSCROLLBARINFO );
+extern pfnGetScrollBarInfo fnGetScrollBarInfo;
+
+typedef DWORD (WINAPI *pfnMsgWaitForMultipleObjectsEx)( DWORD, CONST HANDLE*, DWORD, DWORD, DWORD );
+extern pfnMsgWaitForMultipleObjectsEx fnMsgWaitForMultipleObjectsEx;
+
+typedef HWND (WINAPI *pfnGetAncestor)( HWND, UINT );
+extern pfnGetAncestor fnGetAncestor;
+HWND WINAPI MyGetAncestor( HWND, UINT );
+
+typedef BOOL (WINAPI *pfnGetMenuBarInfo)( HWND, LONG, LONG, PMENUBARINFO );
+extern pfnGetMenuBarInfo fnGetMenuBarInfo;
+
+void FreeAndNil( void **p );
+
+extern SortedList *clistCache;
+
+HICON LoadSmallIconShared(HINSTANCE hInstance, LPCTSTR lpIconName);
+HICON LoadSmallIcon(HINSTANCE hInstance, LPCTSTR lpIconName);
+BOOL DestroyIcon_protect(HICON icon);
+
+#ifndef ETDT_ENABLETAB
+#define ETDT_DISABLE 0x00000001
+#define ETDT_ENABLE 0x00000002
+#define ETDT_USETABTEXTURE 0x00000004
+#define ETDT_ENABLETAB (ETDT_ENABLE | ETDT_USETABTEXTURE)
+#endif
+
+
+
+#define TreeView_InsertItemA(hwnd, lpis) \
+ (HTREEITEM)SendMessageA((hwnd), TVM_INSERTITEMA, 0, (LPARAM)(LPTV_INSERTSTRUCTA)(lpis))
+
+#define TreeView_GetItemA(hwnd, pitem) \
+ (BOOL)SendMessageA((hwnd), TVM_GETITEMA, 0, (LPARAM)(TV_ITEM *)(pitem))
+
+enum
+{
+ STATE_DLL_LOADING = 0,
+ STATE_CLUI_LOADING,
+ STATE_NORMAL,
+ STATE_PREPEARETOEXIT,
+ STATE_EXITING
+};
+
+#define MirandaLoading() ((g_CluiData.bSTATE<STATE_NORMAL))
+#define MirandaExiting() ((g_CluiData.bSTATE>STATE_NORMAL))
+
+char * strdupn(const char * src, int len);
+
+#define SORTBY_NAME 0
+#define SORTBY_STATUS 1
+#define SORTBY_LASTMSG 2
+#define SORTBY_PROTO 3
+#define SORTBY_RATE 4
+#define SORTBY_NAME_LOCALE 5
+#define SORTBY_NOTHING 10
+
+#define DT_FORCENATIVERENDER 0x10000000
+
+#define _BOOL(a) (a != 0)
+
+/* modern_animated_avatars.c */
+int AniAva_InitModule(); // HAVE TO BE AFTER GDI+ INITIALIZED
+int AniAva_UnloadModule();
+int AniAva_UpdateOptions(); //reload options, //hot enable/disable engine
+
+int AniAva_AddAvatar(HANDLE hContact, TCHAR * szFilename, int width, int heigth); // adds avatars to be displayed
+int AniAva_SetAvatarPos(HANDLE hContact, RECT * rc, int overlayIdx, BYTE bAlpha); // update avatars pos
+int AniAva_InvalidateAvatarPositions(HANDLE hContact); // reset positions of avatars to be drawn (still be painted at same place)
+int AniAva_RemoveInvalidatedAvatars(); // all avatars without validated position will be stop painted and probably removed
+int AniAva_RemoveAvatar(HANDLE hContact); // remove avatar
+int AniAva_RedrawAllAvatars(BOOL updateZOrder); // request to repaint all
+void AniAva_UpdateParent();
+int AniAva_RenderAvatar( HANDLE hContact, HDC hdcMem, RECT * rc );
+
+
+#define CCI_NAME 1
+#define CCI_GROUP (1<<1)
+#define CCI_PROTO (1<<2)
+#define CCI_STATUS (1<<3)
+#define CCI_LINES (1<<4)
+#define CCI_HIDDEN (1<<4)
+#define CCI_NOHIDEOFFLINE (1<<5)
+#define CCI_NOPROTO (1<<6)
+#define CCI_HIDESUBCONTACT (1<<7)
+#define CCI_I (1<<8)
+#define CCI_APPARENT (1<<9)
+#define CCI_NOTONLIST (1<<10)
+#define CCI_IDLETS (1<<11)
+#define CCI_CCONTACT (1<<12)
+#define CCI_EXPAND (1<<13)
+#define CCI_UNKNOWN (1<<14)
+#define CCI_TIME (1<<15)
+#define CCI_OTHER ~( CCI_NAME|CCI_GROUP|CCI_PROTO|CCI_STATUS|CCI_LINES|CCI_TIME )
+#define CCI_ALL (0xFFFFFFFF)
+
+void CListSettings_FreeCacheItemData(pdisplayNameCacheEntry pDst);
+int CLUI_SyncGetPDNCE(WPARAM wParam, LPARAM lParam);
+WORD pdnce___GetStatus(pdisplayNameCacheEntry pdnce);
+void pdnce___SetStatus( pdisplayNameCacheEntry pdnce, WORD wStatus );
+
+/* move to list module */
+typedef void (*ItemDestuctor)(void*);
+
+void li_ListDestruct(SortedList *pList, ItemDestuctor pItemDestructor);
+void li_RemoveDestruct(SortedList *pList, int index, ItemDestuctor pItemDestructor);
+void li_RemovePtrDestruct(SortedList *pList, void * ptr, ItemDestuctor pItemDestructor);
+void li_SortList(SortedList *pList, FSortFunc pSortFunct);
+
+#define mir_safe_free(a) if(a) mir_free(a)
+
+template <class T> class INIT : public T
+{
+public:
+ INIT()
+ {
+ memset(this, 0, sizeof(T));
+ this->cbSize=sizeof(T);
+ }
+};
+
+#ifdef __cplusplus
+const ROWCELL * rowAddCell(ROWCELL* &, int );
+void rowDeleteTree(ROWCELL *cell);
+BOOL rowParse(ROWCELL* &cell, ROWCELL* parent, char *tbuf, int &hbuf, int &sequence, ROWCELL** RowTabAccess );
+void rowSizeWithReposition(ROWCELL* &root, int width);
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+// Specific class for quick implementation of map<string, *> list
+// with some more fast searching it is
+// hash_map alternative - for faked hash search;
+// the items are stored no by char* key but both int(hash),char*.
+// have items sorted in map firstly via hash, secondly via string
+// the method is case insensitive
+// To use this simple define like
+// typedef std::map<HashStringKeyNoCase, _Type > map_Type;
+// map_Type myMap;
+// and access it as usual via simpe char* indexing:
+// myList[ "first" ]=_Type_value;
+// myList[ "second" ]=_Type_value;
+// _Type a = myList[ "second"];
+
+class HashStringKeyNoCase
+{
+public:
+
+ HashStringKeyNoCase( const char* szKey )
+ {
+ _strKey=_strdup( szKey );
+ _CreateHashKey();
+ }
+
+ HashStringKeyNoCase( const HashStringKeyNoCase& hsKey )
+ {
+ _strKey = _strdup( hsKey._strKey );
+ _dwKey = hsKey._dwKey;
+ }
+
+ HashStringKeyNoCase& operator= ( const HashStringKeyNoCase& hsKey )
+ {
+ _strKey = _strdup( hsKey._strKey );
+ _dwKey = hsKey._dwKey;
+ }
+
+#ifdef _UNICODE
+ HashStringKeyNoCase( const wchar_t* szKey )
+ {
+ int codepage=0;
+ int cbLen = WideCharToMultiByte( codepage, 0, szKey, -1, NULL, 0, NULL, NULL );
+ char* result = ( char* )malloc( cbLen+1 );
+ WideCharToMultiByte( codepage, 0, szKey, -1, result, cbLen, NULL, NULL );
+ result[ cbLen ] = 0;
+
+ _strKey=result;
+ _CreateHashKey();
+ }
+#endif
+
+ ~HashStringKeyNoCase()
+ {
+ if (_strKey) free (_strKey);
+ _strKey = NULL;
+ _dwKey=0;
+ }
+
+private:
+ char* _strKey;
+ DWORD _dwKey;
+
+ void _CreateHashKey()
+ {
+ _strKey=_strupr( _strKey );
+ _dwKey = mod_CalcHash( _strKey );
+ }
+
+public:
+ bool operator< ( const HashStringKeyNoCase& second ) const
+ {
+ if ( this->_dwKey != second._dwKey )
+ return ( this->_dwKey < second._dwKey );
+ else
+ return ( strcmp( this->_strKey, second._strKey ) < 0 ); // already maked upper so in any case - will be case insensitive
+ }
+
+ struct HashKeyLess
+ {
+ bool operator() ( const HashStringKeyNoCase& first, const HashStringKeyNoCase& second ) const
+ { return ( first < second ); }
+ };
+};
+
+#define EXTRACOLUMNCOUNT 10
+
+
+#endif // commonheaders_h__
diff --git a/plugins/Clist_modern/src/hdr/modern_commonprototypes.h b/plugins/Clist_modern/src/hdr/modern_commonprototypes.h
new file mode 100644
index 0000000000..d8cb8d33e9
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_commonprototypes.h
@@ -0,0 +1,356 @@
+#pragma once
+
+#ifndef _COMMONPROTOTYPES
+#define _COMMONPROTOTYPES
+
+#ifndef commonheaders_h__
+#error "hdr/modern_commonheaders.h have to be including first"
+#endif
+
+#include "modern_commonheaders.h" //TO DO: Move contents of this file to commonheaders.h
+#include "modern_clist.h"
+#include "modern_cluiframes.h"
+#include "modern_row.h"
+#include "modern_skinengine.h"
+#include "modern_skinselector.h"
+#include "modern_statusbar.h"
+
+#define SKIN "ModernSkin"
+
+extern PLUGININFOEX pluginInfo;
+extern CLIST_INTERFACE * pcli;
+extern CLIST_INTERFACE corecli;
+
+//Global variables
+extern int ON_SETALLEXTRAICON_CYCLE;
+extern BOOL CLM_AUTOREBUILD_WAS_POSTED;
+extern FRAMEWND *g_pfwFrames;
+extern int g_nFramesCount;
+extern RECT g_rcEdgeSizingRect;
+extern FRAMEWND *wndFrameEventArea;
+extern ROWCELL * gl_RowTabAccess[];
+extern ROWCELL * gl_RowRoot;
+extern HIMAGELIST hAvatarOverlays;
+extern int g_nTitleBarHeight;
+extern BOOL g_bTransparentFlag;
+extern HIMAGELIST g_himlCListClc;
+extern HIMAGELIST hCListImages;
+extern BOOL g_mutex_bSizing;
+extern BOOL LOCK_RECALC_SCROLLBAR;
+extern HIMAGELIST g_himlCListClc;
+extern int currentDesiredStatusMode;
+extern BYTE nameOrder[];
+extern SortedList lContactsCache;
+extern BOOL g_flag_bOnModulesLoadedCalled;
+extern HIMAGELIST hCListImages;
+extern SKINOBJECTSLIST g_SkinObjectList;
+extern CURRWNDIMAGEDATA * g_pCachedWindow;
+extern BOOL g_mutex_bLockUpdating;
+extern LISTMODERNMASK *MainModernMaskList;
+extern HIMAGELIST hCListImages;
+extern STATUSBARDATA g_StatusBarData;
+extern SKINOBJECTSLIST g_SkinObjectList;
+extern CURRWNDIMAGEDATA * g_pCachedWindow;
+extern char * g_szConnectingProto;
+extern BOOL g_mutex_bLockUpdating;
+extern BOOL g_mutex_bSetAllExtraIconsCycle;
+extern int g_mutex_nCalcRowHeightLock;
+extern int g_mutex_bOnTrayRightClick;
+extern BOOL g_flag_bPostWasCanceled;
+extern BOOL g_flag_bFullRepaint;
+extern BOOL g_bMultiConnectionMode;
+extern BYTE g_bCalledFromShowHide;
+extern HICON g_hListeningToIcon;
+extern BOOL glOtherSkinWasLoaded;
+extern BYTE glSkinWasModified;
+extern HWND g_hCLUIOptionsWnd;
+extern BOOL g_bTransparentFlag;
+extern HINSTANCE g_hInst;
+extern HIMAGELIST hCListImages;
+extern BOOL g_mutex_bChangingMode;
+extern DWORD g_dwMainThreadID;
+extern DWORD g_dwAwayMsgThreadID;
+extern DWORD g_dwGetTextAsyncThreadID;
+extern DWORD g_dwSmoothAnimationThreadID;
+extern DWORD g_dwFillFontListThreadID;
+extern HWND g_hwndViewModeFrame;
+extern HANDLE hSmileyAddOptionsChangedHook,hAvatarChanged,hIconChangedHook;
+extern BYTE gl_TrimText;
+
+/************************************************************************/
+/* TYPE DEFS */
+/************************************************************************/
+
+typedef INT_PTR (*PSYNCCALLBACKPROC)(WPARAM,LPARAM);
+
+/************************************************************************/
+/* PROTOTYPES */
+/************************************************************************/
+
+
+/* CLCItems */
+BOOL CLCItems_IsShowOfflineGroup(struct ClcGroup* group);
+
+/* CListMod */
+int CListMod_HideWindow(HWND hwndContactList, int mode);
+
+/* CLUI */
+HANDLE RegisterIcolibIconHandle(char * szIcoID, char *szSectionName, char * szDescription, TCHAR * tszDefaultFile, int iDefaultIndex, HINSTANCE hDefaultModule, int iDefaultResource );
+void CLUI_UpdateAeroGlass();
+void CLUI_ChangeWindowMode();
+BOOL CLUI_CheckOwnedByClui(HWND hwnd);
+INT_PTR CLUI_GetConnectingIconService(WPARAM wParam,LPARAM lParam);
+int CLUI_HideBehindEdge();
+int CLUI_IconsChanged(WPARAM,LPARAM);
+int CLUI_IsInMainWindow(HWND hwnd);
+HICON CLUI_LoadIconFromExternalFile (char *filename,int i,BOOL UseLibrary,bool registerit,char *IconName,char *SectName,char *Description,int internalidx, BOOL * needFree);
+int CLUI_OnSkinLoad(WPARAM wParam, LPARAM lParam);
+int CLUI_ReloadCLUIOptions();
+int CLUI_ShowFromBehindEdge();
+int CLUI_SizingGetWindowRect(HWND hwnd,RECT * rc);
+int CLUI_SizingOnBorder(POINT ,int);
+int CLUI_SmoothAlphaTransition(HWND hwnd, BYTE GoalAlpha, BOOL wParam);
+int CLUI_TestCursorOnBorders();
+int CLUI_UpdateTimer(BYTE BringIn);
+void CLUI_UpdateLayeredMode();
+UINT_PTR CLUI_SafeSetTimer(HWND hwnd, int ID, int Timeout, TIMERPROC proc);
+
+/* CLUIServices */
+INT_PTR CLUIServices_ProtocolStatusChanged(WPARAM wParam,LPARAM lParam);
+
+int CLUIUnreadEmailCountChanged(WPARAM wParam,LPARAM lParam);
+
+/* GDIPlus */
+BOOL GDIPlus_AlphaBlend(HDC hdcDest,int nXOriginDest,int nYOriginDest,int nWidthDest,int nHeightDest,HDC hdcSrc,int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc, BLENDFUNCTION * blendFunction);
+HBITMAP GDIPlus_LoadGlyphImage(char *szFileName);
+
+/* EventArea */
+void EventArea_ConfigureEventArea();
+
+/* ExtraImage */
+void ExtraImage_SetAllExtraIcons(HWND hwndList,HANDLE hContact);
+
+/* ModernSkinButton */
+int ModernSkinButton_AddButton(HWND parent,char * ID,char * CommandService,char * StateDefService,char * HandeService, int Left, int Top, int Right, int Bottom, DWORD AlignedTo,TCHAR * Hint,char * DBkey,char * TypeDef,int MinWidth, int MinHeight);
+int ModernSkinButtonLoadModule();
+int ModernSkinButton_ReposButtons(HWND parent, BYTE draw, RECT * r);
+int ModernSkinButtonUnloadModule(WPARAM,LPARAM);
+
+/* RowHeight */
+int RowHeight_CalcRowHeight(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item);
+
+/* SkinEngine */
+BOOL ske_AlphaBlend(HDC hdcDest,int nXOriginDest,int nYOriginDest,int nWidthDest,int nHeightDest,HDC hdcSrc,int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc,BLENDFUNCTION blendFunction);
+void ske_ApplyTransluency(void);
+int ske_BltBackImage (HWND destHWND, HDC destDC, RECT * BltClientRect);
+HBITMAP ske_CreateDIB32(int cx, int cy);
+HBITMAP ske_CreateDIB32Point(int cx, int cy, void ** bits);
+HRGN ske_CreateOpaqueRgn(BYTE Level, bool Opaque);
+HICON ske_CreateJoinedIcon(HICON hBottom, HICON hTop,BYTE alpha);
+int ske_DrawImageAt(HDC hdc, RECT *rc);
+BOOL ske_DrawIconEx(HDC hdc,int xLeft,int yTop,HICON hIcon,int cxWidth,int cyWidth, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags);
+int ske_DrawNonFramedObjects(BOOL Erase,RECT *r);
+BOOL ske_DrawText(HDC hdc, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format);
+BOOL ske_DrawTextA(HDC hdc, char * lpString, int nCount, RECT * lpRect, UINT format);
+LPSKINOBJECTDESCRIPTOR ske_FindObjectByName(const char * szName, BYTE objType, SKINOBJECTSLIST* Skin);
+HBITMAP ske_GetCurrentWindowImage();
+int ske_GetFullFilename(char * buf, char *file, char * skinfolder,BOOL madeAbsolute);
+int ske_GetSkinFolder(char * szFileName, char * t2);
+BOOL ske_ImageList_DrawEx( HIMAGELIST himl,int i,HDC hdcDst,int x,int y,int dx,int dy,COLORREF rgbBk,COLORREF rgbFg,UINT fStyle);
+HICON ske_ImageList_GetIcon(HIMAGELIST himl, int i, UINT fStyle);
+int ske_JustUpdateWindowImageRect(RECT * rty);
+HBITMAP ske_LoadGlyphImage(char * szFileName);
+HRESULT SkinEngineLoadModule();
+void ske_LoadSkinFromDB(void);
+int ske_LoadSkinFromIniFile(TCHAR*, BOOL);
+TCHAR* ske_ParseText(TCHAR *stzText);
+int ske_PrepeareImageButDontUpdateIt(RECT * r);
+int ske_ReCreateBackImage(BOOL Erase,RECT *w);
+int ske_RedrawCompleteWindow();
+BOOL ske_ResetTextEffect(HDC);
+BOOL ske_SelectTextEffect(HDC hdc, BYTE EffectID, DWORD FirstColor, DWORD SecondColor);
+INT_PTR ske_Service_DrawGlyph(WPARAM wParam,LPARAM lParam);
+BOOL ske_SetRectOpaque(HDC memdc,RECT *fr, BOOL force = FALSE );
+BOOL ske_SetRgnOpaque(HDC memdc,HRGN hrgn, BOOL force = FALSE );
+BOOL ske_TextOut(HDC hdc, int x, int y, LPCTSTR lpString, int nCount);
+BOOL ske_TextOutA(HDC hdc, int x, int y, char * lpString, int nCount);
+int ske_UnloadGlyphImage(HBITMAP hbmp);
+int SkinEngineUnloadModule();
+int ske_UpdateWindowImage();
+int ske_UpdateWindowImageRect(RECT * lpRect);
+int ske_ValidateFrameImageProc(RECT * r);
+
+/* CLUIFrames.c PROXIED */
+
+int CLUIFrames_ActivateSubContainers(BOOL wParam);
+int CLUIFrames_OnClistResize_mod(WPARAM wParam,LPARAM lParam);
+int CLUIFrames_OnMoving( HWND, RECT * );
+int CLUIFrames_OnShowHide( HWND hwnd, int mode );
+int CLUIFrames_SetLayeredMode( BOOL fLayeredMode, HWND hwnd );
+int CLUIFrames_SetParentForContainers( HWND parent );
+int CLUIFramesOnClistResize(WPARAM wParam,LPARAM lParam);
+
+FRAMEWND * FindFrameByItsHWND(HWND FrameHwnd); //cluiframes.c
+
+//int callProxied_DrawTitleBar(HDC hdcMem2,RECT * rect,int Frameid);
+int DrawTitleBar(HDC hdcMem2,RECT * rect,int Frameid);
+
+int FindFrameID(HWND FrameHwnd);
+int SetAlpha(BYTE Alpha);
+
+
+/* others TODO: move above */
+int Docking_ProcessWindowMessage(WPARAM wParam,LPARAM lParam);
+void DrawBackGround(HWND hwnd,HDC mhdc, HBITMAP hBmpBackground, COLORREF bkColour, DWORD backgroundBmpUse );
+HRESULT BackgroundsLoadModule();
+int BackgroundsUnloadModule();
+BOOL wildcmp(const char * name, const char * mask, BYTE option); //mod_skin_selector.c
+BOOL wildcmpi(char * name, char * mask); //mod_skin_selector.c
+BOOL wildcmpi(WCHAR* name, WCHAR* mask); //mod_skin_selector.c
+INT_PTR CALLBACK DlgSkinEditorOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); //SkinEditor.c
+INT_PTR CALLBACK DlgTmplEditorOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); //RowTemplate.c
+BOOL FindMenuHanleByGlobalID(HMENU hMenu, int globalID, struct _MenuItemHandles * dat); //GenMenu.c
+BOOL MatchMask(char * name, char * mask); //mod_skin_selector.c
+char* GetContactCachedProtocol(HANDLE hContact); //clistsettings.c
+char* GetParamN(char * string, char * buf, int buflen, BYTE paramN, char Delim, BOOL SkipSpaces); //mod_skin_selector.c
+DWORD CompareContacts2_getLMTime(HANDLE u); //contact.c
+DWORD mod_CalcHash(const char * a); //mod_skin_selector.c
+HICON cliGetIconFromStatusMode(HANDLE hContact, const char *szProto,int status); //clistmod.c
+HICON GetMainStatusOverlay(int STATUS); //clc.c
+int __fastcall CLVM_GetContactHiddenStatus(HANDLE hContact, char *szStatus, struct ClcData *dat); //clcitems.c
+int BgStatusBarChange(WPARAM wParam,LPARAM lParam); //clcopts.c
+int ClcDoProtoAck(HANDLE wParam,ACKDATA * ack); //clc.c
+int ModernSkinButtonDeleteAll(); //modernbutton.c
+int GetAverageMode( void ); //clisttray.c
+int GetContactCachedStatus(HANDLE hContact); //clistsettings.c
+INT_PTR GetContactIcon(WPARAM wParam,LPARAM lParam); //clistmod.c
+int GetContactIconC(pdisplayNameCacheEntry cacheEntry); //clistmod.c
+int GetContactIndex(struct ClcGroup *group,struct ClcContact *contact); //clcidents.c
+int GetStatusForContact(HANDLE hContact,char *szProto); //clistsettings.c
+int InitCustomMenus(void); //clistmenus.c
+int InitFramesMenus(void); //framesmenus.c
+int LoadMoveToGroup(); //movetogroup.c
+int LoadPositionsFromDB(BYTE * OrderPos); //clistopts.c
+int LoadStatusBarData(); //modern_statusbar.c
+int MenuModulesLoaded(WPARAM wParam,LPARAM lParam); //clistmenu.c
+int MenuModulesShutdown(WPARAM wParam,LPARAM lParam); //clistmenu.c
+int MenuProcessCommand(WPARAM wParam,LPARAM lParam); //clistmenu.c
+int ModifyMenuItemProxy(WPARAM wParam,LPARAM lParam); //framesmenu.c
+int OnFrameTitleBarBackgroundChange(WPARAM wParam,LPARAM lParam); //cluiframes.c
+int ProcessCommandProxy(WPARAM wParam,LPARAM lParam); //framesmenu.c
+int QueueAllFramesUpdating (BYTE); //cluiframes.c
+int RecursiveDeleteMenu(HMENU hMenu); //clistmenus.c
+int ModernSkinButtonRedrawAll(HDC hdc); //modern_button.c
+int RegisterButtonByParce(char * ObjectName, char * Params); //mod_skin_selector.c
+int RestoreAllContactData(struct ClcData *dat); //cache_funcs.c
+
+int SkinSelector_DeleteMask(MODERNMASK * mm); //mod_skin_selector.c
+int StoreAllContactData(struct ClcData *dat); //cache_func.c
+INT_PTR ToggleHideOffline(WPARAM wParam,LPARAM lParam); //contact.c
+INT_PTR ToggleGroups(WPARAM wParam,LPARAM lParam); //contact.c
+INT_PTR SetUseGroups(WPARAM wParam,LPARAM lParam); //contact.c
+INT_PTR ToggleSounds(WPARAM wParam,LPARAM lParam); //contact.c
+int UnitFramesMenu(); //framesmenu.c
+void ClcOptionsChanged(); //clc.c
+void Docking_GetMonitorRectFromWindow(HWND hWnd,RECT *rc); //Docking.c
+void DrawAvatarImageWithGDIp(HDC hDestDC,int x, int y, DWORD width, DWORD height, HBITMAP hbmp, int x1, int y1, DWORD width1, DWORD height1,DWORD flag,BYTE alpha); //gdiplus.cpp
+void FreeRowCell(); //RowHeight
+void InitGdiPlus(); //gdiplus.cpp
+void InitTray(); //clisttray.c
+void InvalidateDNCEbyPointer(HANDLE hContact,pdisplayNameCacheEntry pdnce,int SettingType); //clistsettings.c
+void ReAssignExtraIcons(); //extraimage.c
+void ShutdownGdiPlus(); //gdiplus.cpp
+void TextOutWithGDIp(HDC hDestDC, int x, int y, LPCTSTR lpString, int nCount); //gdiplus.cpp
+void UninitCustomMenus(); //clistmenus.c
+void UnloadAvatarOverlayIcon(); //clc.c
+void UnLoadContactListModule(); //clistmod.c
+void UpdateAllAvatars(struct ClcData *dat); //cache_func.c
+ //cluiframes.c
+void gtaRenewText(HANDLE hContact);
+int ExtraImage_ExtraIDToColumnNum(int extra);
+int ExtraImage_ColumnNumToExtraID(int column);
+
+int LoadSkinButtonModule();
+void UninitSkinHotKeys();
+void GetDefaultFontSetting(int i,LOGFONTA *lf,COLORREF *colour);
+int CLUI_OnSkinLoad(WPARAM wParam, LPARAM lParam);
+HRESULT CluiLoadModule();
+HRESULT PreLoadContactListModule();
+HRESULT ClcLoadModule();
+HRESULT ToolbarLoadModule();
+HRESULT ToolbarButtonLoadModule();
+void CustomizeButton(HWND);
+
+// INTERFACES
+
+void cliCheckCacheItem(pdisplayNameCacheEntry pdnce);
+void cliFreeCacheItem( pdisplayNameCacheEntry p );
+void cliRebuildEntireList(HWND hwnd,struct ClcData *dat);
+void cliRecalcScrollBar(HWND hwnd,struct ClcData *dat);
+void CLUI_cliOnCreateClc(void);
+int cli_AddItemToGroup(struct ClcGroup *group, int iAboveItem);
+int cli_AddInfoItemToGroup(struct ClcGroup *group,int flags,const TCHAR *pszText);
+int cliGetGroupContentsCount(struct ClcGroup *group, int visibleOnly);
+int cliFindRowByText(HWND hwnd, struct ClcData *dat, const TCHAR *text, int prefixOk);
+int cliGetRowsPriorTo(struct ClcGroup *group,struct ClcGroup *subgroup,int contactIndex);
+int cli_IconFromStatusMode(const char *szProto,int nStatus, HANDLE hContact);
+int cli_RemoveEvent(HANDLE hContact, HANDLE hDbEvent);
+void cli_AddContactToTree(HWND hwnd,struct ClcData *dat,HANDLE hContact,int updateTotalCount,int checkHideOffline);
+void cli_DeleteItemFromTree(HWND hwnd, HANDLE hItem);
+void cli_FreeContact( struct ClcContact* );
+void cli_FreeGroup( struct ClcGroup* );
+char* cli_GetGroupCountsText(struct ClcData *dat, struct ClcContact *contact);
+void cli_ChangeContactIcon(HANDLE hContact,int iIcon,int add);
+LRESULT cli_ProcessExternalMessages(HWND hwnd,struct ClcData *dat,UINT msg,WPARAM wParam,LPARAM lParam);
+struct CListEvent* cliCreateEvent( void );
+struct CListEvent* cli_AddEvent(CLISTEVENT *cle);
+LRESULT CALLBACK cli_ContactListControlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+int cliShowHide(WPARAM wParam,LPARAM lParam);
+BOOL CLUI__cliInvalidateRect(HWND hWnd, CONST RECT* lpRect,BOOL bErase );
+int cliCompareContacts(const struct ClcContact *contact1,const struct ClcContact *contact2);
+int cliFindItem(HWND hwnd,struct ClcData *dat,HANDLE hItem,struct ClcContact **contact,struct ClcGroup **subgroup,int *isVisible);
+void cliTrayIconUpdateBase(const char *szChangedProto);
+void cliCluiProtocolStatusChanged(int status,const char * proto);
+HMENU cliBuildGroupPopupMenu(struct ClcGroup *group);
+void cliInvalidateDisplayNameCacheEntry(HANDLE hContact);
+void cliCheckCacheItem(pdisplayNameCacheEntry pdnce);
+void cli_SaveStateAndRebuildList(HWND hwnd, struct ClcData *dat);
+void CLUI_cli_LoadCluiGlobalOpts(void);
+INT_PTR cli_TrayIconProcessMessage(WPARAM wParam,LPARAM lParam);
+BOOL CLUI__cliInvalidateRect(HWND hWnd, CONST RECT* lpRect,BOOL bErase );
+
+struct ClcContact* cliCreateClcContact( void );
+ClcCacheEntryBase* cliCreateCacheItem(HANDLE hContact);
+ClcCacheEntryBase* cliGetCacheEntry(HANDLE hContact);
+
+// FUNCTION POINTERS
+extern BOOL (WINAPI *g_proc_UpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD);
+extern BOOL (WINAPI *g_proc_SetLayeredWindowAttributesNew)(HWND,COLORREF,BYTE,DWORD);
+
+#define WM_DWMCOMPOSITIONCHANGED 0x031E
+
+#define DWM_BB_ENABLE 0x00000001
+#define DWM_BB_BLURREGION 0x00000002
+#define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004
+struct DWM_BLURBEHIND
+{
+ DWORD dwFlags;
+ BOOL fEnable;
+ HRGN hRgnBlur;
+ BOOL fTransitionOnMaximized;
+};
+extern HRESULT (WINAPI *g_proc_DWMEnableBlurBehindWindow)(HWND hWnd, DWM_BLURBEHIND *pBlurBehind);
+
+extern tPaintCallbackProc CLCPaint_PaintCallbackProc(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData);
+extern BOOL (WINAPI *MySetProcessWorkingSetSize)(HANDLE,SIZE_T,SIZE_T);
+
+/* SkinEngine.c */
+
+
+BYTE SkinDBGetContactSettingByte(HANDLE hContact, const char* szSection, const char*szKey, BYTE bDefault);
+
+extern OVERLAYICONINFO g_pAvatarOverlayIcons[ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE + 1];
+extern OVERLAYICONINFO g_pStatusOverlayIcons[ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE + 1];
+
+
+#endif
diff --git a/plugins/Clist_modern/src/hdr/modern_defsettings.h b/plugins/Clist_modern/src/hdr/modern_defsettings.h
new file mode 100644
index 0000000000..c84d99840c
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_defsettings.h
@@ -0,0 +1,284 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2007 Artem Shpynov
+Copyright 2000-2008 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.
+*/
+
+/////////////////////////////////////////////////////////////////////////
+/// This file contains default settings value predefinitions
+//////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#undef CLCDEFAULT_GROUPINDENT
+#undef CLCDEFAULT_SHOWIDLE
+#undef CLCDEFAULT_TEXTCOLOUR
+#undef CLCDEFAULT_SELBKCOLOUR
+#undef SETTING_ONTOP_DEFAULT
+#undef SETTING_TRAY1CLICK_DEFAULT
+
+#define SETTING_ENABLESKINEDITOR_DEFAULT 0 //"ModernData", "EnableSkinEditor"
+#define SETTING_TOOLWINDOW_DEFAULT 1 //"CList","ToolWindow"
+#define SETTING_ONTOP_DEFAULT 0 //"CList","OnTop"
+#define SETTING_MIN2TRAY_DEFAULT 1 //"CList","Min2Tray"
+#define SETTING_TRAY1CLICK_DEFAULT 1 //"CList","Tray1Click"
+#define SETTING_HIDEOFFLINE_DEFAULT 0 //"CList", "HideOffline"
+#define SETTING_HIDEEMPTYGROUPS_DEFAULT 0 //"CList","HideEmptyGroups"
+#define SETTING_USEGROUPS_DEFAULT 1 //"CList","UseGroups"
+#define SETTING_PLACEOFFLINETOROOT_DEFAULT 0 //"CList","PlaceOfflineToRoot"
+#define SETTING_ALWAYSPRIMARY_DEFAULT 0 //! "CList","AlwaysPrimary"
+#define SETTING_DISABLETRAYFLASH_DEFAULT 0 //! "CList","DisableTrayFlash"
+#define SETTING_ICONFLASHTIME_DEFAULT 550 //! "CList","IconFlashTime"
+#define SETTING_THINBORDER_DEFAULT 0 //! "CList","ThinBorder"
+#define SETTING_NOBORDER_DEFAULT 0 //! "CList","NoBorder"
+#define SETTING_WINDOWSHADOW_DEFAULT 0 //! "CList","WindowShadow"
+#define SETTING_ONDESKTOP_DEFAULT 0 //! "CList","OnDesktop"
+#define SETTING_DISABLEWORKINGSET_DEFAULT 1 //! "CList","DisableWorkingSet"
+#define SETTING_NOICONBLINF_DEFAULT 0 //! "CList","NoIconBlink"
+#define SETTING_ALWAYSVISICON_DEFAULT 0 //! "CList","AlwaysShowAlwaysVisIcon"
+
+#define SETTING_SHOWMAINMENU_DEFAULT 1 //"CLUI","ShowMainMenu"
+#define SETTING_SHOWCAPTION_DEFAULT 1 //"CLUI","ShowCaption"
+#define SETTING_CLIENTDRAG_DEFAULT 1 //"CLUI","ClientAreaDrag"
+#define SETTING_SHOWSBAR_DEFAULT 1 //! "CLUI","ShowSBar"
+#define SETTING_SBARPERPROTO_DEFAULT 0 //! "CLUI","SBarPerProto"
+#define SETTING_USECONNECTINGICON_DEFAULT 1 //! "CLUI","UseConnectingIcon"
+#define SETTING_SHOWXSTATUS_DEFAULT 6 //! "CLUI","ShowXStatus"
+#define SETTING_SHOWUNREADEMAILS_DEFAULT 0 //! "CLUI","ShowUnreadEmails"
+#define SETTING_SBARSHOW_DEFAULT 3 //! "CLUI","SBarShow"
+#define SETTING_SBARACCOUNTISCUSTOM_DEFAULT 0 //! "CLUI","AccountIsCustom"
+#define SETTING_SBARHIDEACCOUNT_DEFAULT 0 //! "CLUI","HideAccount"
+#define SETTING_SBARRIGHTCLK_DEFAULT 0 //! "CLUI","SBarRightClk"
+#define SETTING_EQUALSECTIONS_DEFAULT 0 //! "CLUI","EqualSections"
+#define SETTING_LEFTOFFSET_DEFAULT 0 //! "CLUI","LeftOffset"
+#define SETTING_RIGHTOFFSET_DEFAULT 0 //! "CLUI","RightOffset
+#define SETTING_TOPOFFSET_DEFAULT 0 //! "CLUI","TopOffset"
+#define SETTING_BOTTOMOFFSET_DEFAULT 0 //! "CLUI","BottomOffset
+#define SETTING_SPACEBETWEEN_DEFAULT 0 //! "CLUI","SpaceBetween"
+#define SETTING_ALIGN_DEFAULT 0 //! "CLUI","Align"
+#define SETTING_VALIGN_DEFAULT 1 //! "CLUI","VAlign"
+#define SETTING_PADDINGLEFT_DEFAULT 0 //! "CLUI","PaddingLeft_*"
+#define SETTING_PADDINGRIGHT_DEFAULT 0 //! "CLUI","PaddingRight_*"
+#define SETTING_DRAGTOSCROLL_DEFAULT 0 //! "CLUI","DragToScroll"
+#define SETTING_AUTOSIZE_DEFAULT 0 //! "CLUI","AutoSize"
+#define SETTING_LOCKSIZE_DEFAULT 0 //! "CLUI","LockSize"
+#define SETTING_MINHEIGTH_DEFAULT 0 //! "CLUI","MinHeight"
+#define SETTING_MINWIDTH_DEFAULT 18 //! "CLUI","MinWidth"
+#define SETTING_MAXSIZEHEIGHT_DEFAULT 75 //! "CLUI","MaxSizeHeight"
+#define SETTING_MINSIZEHEIGHT_DEFAULT 10 //! "CLUI","MinSizeHeight"
+#define SETTING_AUTOSIZEUPWARD_DEFAULT 0 //! "CLUI","AutoSizeUpward"
+#define SETTING_SNAPTOEDGES_DEFAULT 1 //! "CLUI","SnapToEdges"
+#define SETTING_DOCKTOSIDES_DEFAULT 1 //! "CLUI","DockToSides",
+
+#define SETTING_PROTOSPERLINE_DEFAULT 0 //! "CLUI","StatusBarProtosPerLine"
+#define SETTING_TEXTEFFECTID_DEFAULT 0xFF //! "StatusBar","TextEffectID"
+#define SETTING_TEXTEFFECTCOLOR1_DEFAULT 0 //! "StatusBar","TextEffectColor1"
+#define SETTING_TEXTEFFECTCOLOR2_DEFAULT 0 //! "StatusBar","TextEffectColor2"
+#define SETTING_SBHILIGHTMODE_DEFAULT 0 //! "StatusBar","HiLightMode"
+#define SETTING_HIDETOOLTIPTIME_DEFAULT 5000 //! "CLUIFrames","HideToolTipTime"
+
+#define SETTING_EXTRA_ICON_EMAIL_DEFAULT 0 //!
+#define SETTING_EXTRA_ICON_PROTO_DEFAULT 0 //!
+#define SETTING_EXTRA_ICON_SMS_DEFAULT 0 //!
+#define SETTING_EXTRA_ICON_ADV1_DEFAULT 1 //!
+#define SETTING_EXTRA_ICON_ADV2_DEFAULT 1 //!
+#define SETTING_EXTRA_ICON_WEB_DEFAULT 0 //!
+#define SETTING_EXTRA_ICON_CLIENT_DEFAULT 1 //!
+#define SETTING_EXTRA_ICON_VISMODE_DEFAULT 1 //!
+#define SETTING_EXTRA_ICON_ADV3_DEFAULT 1 //!
+#define SETTING_EXTRA_ICON_ADV4_DEFAULT 1 //!
+
+#define SETTING_EXTRACOLUMNSPACE_DEFAULT 18 //! "CLUI","ExtraColumnSpace"
+
+#define SETTING_HIDEBEHIND_DEFAULT 0 //! "ModernData","HideBehind" //(0-none, 1-leftedge, 2-rightedge)
+#define SETTING_BEHINDEDGE_DEFAULT 0 //! "ModernData", "BehindEdge"
+#define SETTING_SHOWDELAY_DEFAULT 3 //! "ModernData","ShowDelay"
+#define SETTING_HIDEDELAY_DEFAULT 3 //! "ModernData","HideDelay"
+#define SETTING_HIDEBEHINDBORDERSIZE_DEFAULT 0 //! "ModernData","HideBehindBorderSize"
+#define SETTING_AEROGLASS_DEFAULT 1 //! "ModernData","AeroGlass"
+
+#define SETTING_ROUNDCORNERS_DEFAULT 0 //! "CLC","RoundCorners"
+#define SETTING_GAPFRAMES_DEFAULT 1 //! "CLUIFrames","GapBetweenFrames"
+#define SETTING_GAPTITLEBAR_DEFAULT 1 //! "CLUIFrames","GapBetweenTitleBar"
+#define SETTING_LEFTCLIENTMARIGN_DEFAULT 0 //! "CLUI","LeftClientMargin"
+#define SETTING_RIGHTCLIENTMARIGN_DEFAULT 0 //! "CLUI","RightClientMargin"
+#define SETTING_TOPCLIENTMARIGN_DEFAULT 0 //! "CLUI","TopClientMargin"
+#define SETTING_BOTTOMCLIENTMARIGN_DEFAULT 0 //! "CLUI","BottomClientMargin"
+#define SETTING_KEYCOLOR_DEFAULT RGB(255,0,255) //! "ModernSettings","KeyColor"
+#define SETTING_LINEUNDERMENU_DEFAULT 0 //! "CLUI","LineUnderMenu"
+#define SETTING_SHOWONSTART_DEFAULT 0 //! "CList","ShowOnStart"
+#define SETTING_AUTOSIZE_DEFAULT 0 //! "CLUI","AutoSize"
+
+#define SETTING_INTERNALAWAYMSGREQUEST_DEFAULT 1 //"ModernData","InternalAwayMsgDiscovery"
+#define SETTING_REMOVEAWAYMSGFOROFFLINE_DEFAULT 1 //"ModernData","RemoveAwayMessageForOffline"
+#define SETTING_METAAVOIDDBLCLICK_DEFAULT 1 //"CLC","MetaDoubleClick"
+#define SETTING_METAIGNOREEMPTYEXTRA_DEFAULT 1 //"CLC","MetaIgnoreEmptyExtra"
+#define SETTING_METAHIDEEXTRA_DEFAULT 0 //"CLC","MetaHideExtra"
+#define SETTING_METAEXPANDING_DEFAULT 1 //"CLC","MetaExpanding"
+#define SETTING_METAAVOIDDBLCLICK_DEFAULT 1 //"CLC","MetaDoubleClick"
+#define SETTING_METAHIDEOFFLINESUB_DEFAULT 1 //"CLC","MetaHideOfflineSub"
+#define SETTING_USEMETAICON_DEFAULT 0 //"CLC","Meta"
+#define SETTING_DRAWOVERLAYEDSTATUS_DEFAULT 3 //todo replace by contstants
+
+
+#define SETTING_SORTBY1_DEFAULT SORTBY_RATE //"CList","SortBy1"
+#define SETTING_SORTBY2_DEFAULT SORTBY_NAME //"CList","SortBy2"
+#define SETTING_SORTBY3_DEFAULT SORTBY_STATUS //"CList","SortBy3"
+
+#define SETTING_PLACEOOFLINETOROOT_DEFAULT 0 //"CList","PlaceOfflineToRoot"
+#define SETTING_NOOFFLINEBOTTOM_DEFAULT 0 //"CList","NoOfflineBottom"
+#define SETTING_HIDEOFFLINEATROOT_DEFAULT 0 //"CLC","HideOfflineRoot"
+#define SETTING_HILIGHTMODE_DEFAULT 0 //todo replace by constant //"CLC","HiLightMode"
+
+#define SETTING_DISABLESKIN_DEFAULT 0 //"ModernData","DisableEngine"
+#define SETTING_ENABLELAYERING_DEFAULT 1 //! "ModernData","EnableLayering"
+#define SETTING_COMPACTMODE_DEFAULT 0 //"CLC","CompactMode"
+
+#define SETTING_EVENTAREAMODE_DEFAULT 1 //autohide todo replace by const //"CLUI","EventArea"
+#define SETTING_SHOWEVENTAREAFRAME_DEFAULT 1 //"CLUI","ShowEventArea"
+
+#define SETTING_TRAYOPTION_DEFAULT 15 //show combined icon
+#define SETTING_FADEIN_DEFAULT 0 //"CLUI","FadeInOut"
+
+//////////////////////////////////////////////////////////////////////////
+// ROW SETTINGS
+#define SETTING_ROWBORDER_DEFAULT 1 //"CList","RowBorder"
+#define SETTING_ROW_ADVANCEDLAYOUT_DEFAULT 0 //"ModernData","UseAdvancedRowLayout"
+#define SETTING_ROW_ROWBORDER_DEFAULT 1 //"CList","RowBorder"
+#define SETTING_VARIABLEROWHEIGHT_DEFAULT 1 //"CList","VariableRowHeight"
+#define SETTING_ALIGNLEFTTOLEFT_DEFAULT 0 //"CList","AlignLeftItemsToLeft"
+#define SETTING_ALIGNRIGHTORIGHT_DEFAULT 1 //"CList","AlignRightItemsToRight"
+#define SETTING_HIDEGROUPSICON_DEFAULT 0 //"CList","HideGroupsIcon"
+#define SETTING_ALIGNGROPCAPTION_DEFAULT 0 //left todo replace by const //"CList","AlignGroupCaptions"
+#define SETTINS_ROWITEMORDER_DEFAULT {ITEM_AVATAR, ITEM_ICON, ITEM_TEXT, ITEM_EXTRA_ICONS, ITEM_CONTACT_TIME}
+
+#define SETTINGS_SHOWAVATARS_DEFAULT 1 //"CList","AvatarsShow"
+#define SETTINGS_AVATARDRAWBORDER_DEFAULT 0 //"CList","AvatarsDrawBorders"
+#define SETTINGS_AVATARBORDERCOLOR_DEFAULT RGB(0,0,0) //"CList","AvatarsBorderColor"
+#define SETTINGS_AVATARROUNDCORNERS_DEFAULT 0 //"CList","AvatarsRoundCorners"
+#define SETTINGS_AVATARUSECUTOMCORNERSIZE_DEFAULT 0 //"CList","AvatarsUseCustomCornerSize"
+#define SETTINGS_AVATARCORNERSIZE_DEFAULT 4 //"CList","AvatarsCustomCornerSize"
+#define SETTINGS_AVATARIGNORESIZEFORROW_DEFAULT 0 //"CList","AvatarsIgnoreSizeForRow"
+#define SETTINGS_AVATARDRAWOVERLAY_DEFAULT 0 //"CList","AvatarsDrawOverlay"
+#define SETTINGS_AVATAROVERLAYTYPE_DEFAULT SETTING_AVATAR_OVERLAY_TYPE_NORMAL
+#define SETTING_AVATARHEIGHT_DEFAULT 24 //"CList","AvatarsSize"
+#define SETTING_AVATARWIDTH_DEFAULT 24 //"CList","AvatarsWidth"
+#define SETTINGS_AVATARINSEPARATE_DEFAULT 0 //"CList","AvatarsInSeparateWnd",
+
+
+
+#define SETTING_HIDEICONONAVATAR_DEFAULT 0 //"CList","IconHideOnAvatar"
+#define SETTING_ICONONAVATARPLACE_DEFAULT 0 //"CList","IconDrawOnAvatarSpace"
+#define SETTING_ICONIGNORESIZE_DEFAULT 0 //"CList","IconIgnoreSizeForRownHeight"
+#define SETTING_SHOWTIME_DEFAULT 0 //"CList","ContactTimeShow"
+#define SETTING_SHOWTIMEIFDIFF_DEFAULT 1 //"CList","ContactTimeShowOnlyIfDifferent"
+
+#define SETTING_TEXT_RTL_DEFAULT 0 //"CList","TextRTL"
+#define SETTING_TEXT_RIGHTALIGN_DEFAULT 0 //"CList","TextAlignToRight"
+#define SETTING_TEXT_SMILEY_DEFAULT 1 //"CList","TextReplaceSmileys"
+#define SETTING_TEXT_RESIZESMILEY_DEFAULT 1 //"CList","TextResizeSmileys"
+#define SETTING_TEXT_PROTOSMILEY_DEFAULT 1 //"CList","TextUseProtocolSmileys"
+#define SETTING_TEXT_IGNORESIZE_DEFAULT 0 //"CList","TextIgnoreSizeForRownHeight"
+
+#define SETTING_FIRSTLINE_SMILEYS_DEFAULT 1 //"CList","FirstLineDrawSmileys"
+#define SETTING_FIRSTLINE_APPENDNICK_DEFAULT 0 //"CList","FirstLineAppendNick"
+#define SETTING_FIRSTLINE_TRIMTEXT_DEFAULT 1 //"CList","TrimText"
+
+#define SETTING_SECONDLINE_SHOW_DEFAULT 1 //"CList","SecondLineShow"
+#define SETTING_SECONDLINE_TOPSPACE_DEFAULT 2 //"CList","SecondLineTopSpace"
+#define SETTING_SECONDLINE_SMILEYS_DEFAULT 1 //"CList","SecondLineDrawSmileys"
+#define SETTING_SECONDLINE_TYPE_DEFAULT TEXT_STATUS_MESSAGE //"CList","SecondLineType"
+#define SETTING_SECONDLINE_XSTATUS_DEFAULT 1 //"CList","SecondLineXStatusHasPriority"
+#define SETTING_SECONDLINE_XSTATUSNAMETEXT_DEFAULT 0 //"CList","SecondLineUseNameAndMessageForXStatus"
+#define SETTING_SECONDLINE_STATUSIFNOAWAY_DEFAULT 1 //"CList","SecondLineShowStatusIfNoAway"
+#define SETTING_SECONDLINE_LISTENINGIFNOAWAY_DEFAULT 1 //"CList","SecondLineShowListeningIfNoAway"
+
+#define SETTING_THIRDLINE_SHOW_DEFAULT 0 //"CList","ThirdLineShow"
+#define SETTING_THIRDLINE_TOPSPACE_DEFAULT 2 //"CList","ThirdLineTopSpace"
+#define SETTING_THIRDLINE_SMILEYS_DEFAULT 0 //"CList","ThirdLineDrawSmileys"
+#define SETTING_THIRDLINE_TYPE_DEFAULT TEXT_STATUS_MESSAGE //"CList","ThirdLineType"
+#define SETTING_THIRDLINE_XSTATUS_DEFAULT 1 //"ThirdLineXStatusHasPriority"
+#define SETTING_THIRDLINE_XSTATUSNAMETEXT_DEFAULT 0 //"ThirdLineUseNameAndMessageForXStatus"
+#define SETTING_THIRDLINE_STATUSIFNOAWAY_DEFAULT 0 //"CList","ThirdLineShowStatusIfNoAway"
+#define SETTING_THIRDLINE_LISTENINGIFNOAWAY_DEFAULT 0 //"ThirdLineShowListeningIfNoAway"
+
+
+#define SETTING_TRANSPARENT_DEFAULT 0 //"CList","Transparent"
+#define SETTING_AUTOALPHA_DEFAULT 150 //"CList","AutoAlpha"
+#define SETTING_CONFIRMDELETE_DEFAULT 1 //"CList","ConfirmDelete"
+#define SETTING_AUTOHIDE_DEFAULT 0 //"CList","AutoHide"
+#define SETTING_HIDETIME_DEFAULT 30 //"CList","HideTime"
+#define SETTING_CYCLETIME_DEFAULT 4 //"CList","CycleTime"
+#define SETTING_TRAYICON_DEFAULT SETTING_TRAYICON_SINGLE //"CList","TrayIcon"
+#define SETTING_ALWAYSSTATUS_DEFAULT 0 //"CList","AlwaysStatus"
+#define SETTING_ALWAYSMULTI_DEFAULT 0 //"CList","AlwaysMulti"
+
+#define SETTING_BLENDINACTIVESTATE_DEFAULT 0 //"CLC","BlendInActiveState"
+#define SETTING_BLEND25_DEFAULT 1 //NOT USED
+
+#define CLCDEFAULT_EXSTYLE (CLS_EX_EDITLABELS|CLS_EX_TRACKSELECT|CLS_EX_SHOWGROUPCOUNTS|CLS_EX_HIDECOUNTSWHENEMPTY|CLS_EX_TRACKSELECT|CLS_EX_NOTRANSLUCENTSEL) //plus CLS_EX_NOSMOOTHSCROLL is got from the system
+#define CLCDEFAULT_SCROLLTIME 150 //"CLC","ScrollTime"
+#define CLCDEFAULT_GROUPINDENT 20 //"CLC","SubIndent"
+#define CLCDEFAULT_BKCOLOUR GetSysColor(COLOR_3DFACE)
+#define CLCDEFAULT_USEBITMAP 0 //"StatusBar","UseBitmap"
+#define CLCDEFAULT_BKBMPUSE CLB_STRETCH //"StatusBar","BkBmpUse"
+#define CLCDEFAULT_OFFLINEMODES MODEF_OFFLINE //"CLC","OfflineModes"
+#define CLCDEFAULT_GREYOUTFLAGS 0 //"CLC","GreyoutFlags"
+#define CLCDEFAULT_FULLGREYOUTFLAGS (MODEF_OFFLINE|PF2_INVISIBLE|GREYF_UNFOCUS)
+#define CLCDEFAULT_SELBKCOLOUR RGB(100,100,100) //GetSysColor(COLOR_HIGHLIGHT)
+
+
+#define CLCDEFAULT_TEXTCOLOUR (g_CluiData.fDisableSkinEngine?GetSysColor(COLOR_WINDOWTEXT):RGB(0,0,0))
+#define CLCDEFAULT_MODERN_SELTEXTCOLOUR (g_CluiData.fDisableSkinEngine?GetSysColor(COLOR_HIGHLIGHTTEXT):RGB(0,0,128))
+#define CLCDEFAULT_MODERN_HOTTEXTCOLOUR (g_CluiData.fDisableSkinEngine?(IsWinVer98Plus()?CLCDEFAULT_MODERN_SELTEXTCOLOUR:GetSysColor(COLOR_HOTLIGHT)):RGB(0,0,255))
+#define CLCDEFAULT_MODERN_QUICKSEARCHCOLOUR RGB(255,255,0)
+#define CLCDEFAULT_LEFTMARGIN 0 //"CLC","LeftMargin"
+#define CLCDEFAULT_RIGHTMARGIN 2 //"CLC","RightMargin"
+#define CLCDEFAULT_GAMMACORRECT 1 //"CLC","GammaCorrect"
+#define CLCDEFAULT_SHOWIDLE 1 //"CLC","ShowIdle"
+#define CLCDEFAULT_NOVSCROLL 0 //"CLC","NoVScrollBar"
+#define CLCDEFAULT_INFOTIPTIME 750 //"! "CLC","InfoTipHoverTime"
+#define CLCDEFAULT_COLLICONTOLEFT 0 //"! "FrameTitleBar","AlignCOLLIconToLeft"
+
+#define SKIN_OFFSET_TOP_DEFAULT 0 //! "ModernSkin","SizeMarginOffset_Top"
+#define SKIN_OFFSET_BOTTOM_DEFAULT 0 //! "ModernSkin","SizeMarginOffset_Bottom"
+#define SKIN_OFFSET_LEFT_DEFAULT 0 //! "ModernSkin","SizeMarginOffset_Left"
+#define SKIN_OFFSET_RIGHT_DEFAULT 0 //! "ModernSkin","SizeMarginOffset_Right"
+#define SKIN_SPACEBEFOREGROUP_DEFAULT 0 //! "ModernSkin","SpaceBeforeGroup"
+
+
+
+
+
+
+
+#define SETTINGS_BARBTNWIDTH_DEFAULT 22 //"ModernToolBar", "option_Bar0_BtnWidth"
+#define SETTINGS_BARBTNHEIGHT_DEFAULT 22 //"ModernToolBar", "option_Bar0_BtnHeight"
+#define SETTINGS_BARBTNSPACE_DEFAULT 0 //"ModernToolBar", "option_Bar0_BtnSpace"
+#define SETTINGS_BARAUTOSIZE_DEFAULT 1 //"ModernToolBar", "option_Bar0_Autosize"
+#define SETTINGS_BARMULTILINE_DEFAULT 1 //"ModernToolBar", "option_Bar0_Multiline"
+
+#define SETTING_ENABLESOUNDS_DEFAULT 1 // !"Skin", "UseSound",
+
+
+
+
diff --git a/plugins/Clist_modern/src/hdr/modern_effectenum.h b/plugins/Clist_modern/src/hdr/modern_effectenum.h
new file mode 100644
index 0000000000..e3c5600dc6
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_effectenum.h
@@ -0,0 +1,93 @@
+#pragma once
+
+typedef signed char sbyte;
+typedef struct _MODERNEFFECTMATRIX
+{
+ sbyte matrix[25];
+ BYTE topEffect;
+ BYTE leftEffect;
+ BYTE rightEffect;
+ BYTE bottomEffect;
+ BYTE cycleCount; //low 7 bits
+}MODERNEFFECTMATRIX;
+
+typedef struct _MODERNEFFECT
+{
+ BYTE EffectID;
+ MODERNEFFECTMATRIX EffectMatrix;
+ DWORD EffectColor1;
+ DWORD EffectColor2;
+}MODERNEFFECT;
+
+#ifdef _EFFECTENUM_FULL_H
+ TCHAR * ModernEffectNames[]=
+#else
+ TCHAR * _ModernEffectNames[]=
+#endif
+{
+ _T("Shadow at left"),
+ _T("Shadow at right"),
+ _T("Outline"),
+ _T("Outline smooth"),
+ _T("Smooth bump"),
+ _T("Contour thin"),
+ _T("Contour heavy"),
+};
+
+#ifdef _EFFECTENUM_FULL_H
+MODERNEFFECTMATRIX ModernEffectsEnum[]={
+ { //Shadow at Left
+ { 0, 0, 0, 0, 0,
+ 0, 4, 16, 4, 4,
+ 0, 16, 64, 32, 16,
+ 0, 4, 32, 32, 16,
+ 0, 4, 16, 16, 16 }, 2,2,2,2,1},
+ { //Shadow at Right
+ { 0, 0, 0, 0, 0,
+ 4, 4, 16, 4, 0,
+ 16, 32, 64, 16, 0,
+ 16, 32, 32, 4, 0,
+ 16, 16, 16, 4, 0 }, 2,2,2,2,1},
+ { //Outline
+ { 0, 0, 0, 0, 0,
+ 0, 16, 16, 16, 0,
+ 0, 16, 32, 16, 0,
+ 0, 16, 16, 16, 0,
+ 0, 0, 0, 0, 0 }, 1,1,1,1,1},
+
+ { //Outline smooth
+ { 4, 4, 4, 4, 4,
+ 4, 8, 8, 8, 4,
+ 4, 8, 32, 8, 4,
+ 4, 8, 8, 8, 4,
+ 4, 4, 4, 4, 4 }, 2,2,2,2,1},
+
+ { //Smooth bump
+ { -2, 2, 2, 2, 2,
+ -2, -16, 16, 16, 2,
+ -2, -16, 48, 16, 2,
+ -2, -16,-16, 16, 2,
+ -2, -2, -2, -2, -2 }, 2,2,2,2,1+0x80},
+ { //Contour thin
+ { 0, 0, 0, 0, 0,
+ 0, 48, 64, 48, 0,
+ 0, 64, 64, 64, 0,
+ 0, 48, 64, 48, 0,
+ 0, 0, 0, 0, 0 }, 1,1,1,1,1},
+ { //Contour heavy
+ { 8, 16, 16, 16, 8,
+ 16, 64, 64, 64, 16,
+ 16, 64, 64, 64, 16,
+ 16, 64, 64, 64, 16,
+ 8, 16, 16, 16, 8 }, 2,2,2,2,1},
+
+};
+#endif
+#ifdef _EFFECTENUM_FULL_H
+ #define MAXPREDEFINEDEFFECTS sizeof(ModernEffectNames)/sizeof(ModernEffectNames[0])
+#else
+ #define MAXPREDEFINEDEFFECTS sizeof(_ModernEffectNames)/sizeof(_ModernEffectNames[0])
+ extern TCHAR * ModernEffectNames[];
+#endif
+extern BOOL SkinEngine_ResetTextEffect(HDC);
+extern BOOL SkinEngine_SelectTextEffect(HDC hdc, BYTE EffectID, DWORD FirstColor, DWORD SecondColor); \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_gettextasync.h b/plugins/Clist_modern/src/hdr/modern_gettextasync.h
new file mode 100644
index 0000000000..881e2b738d
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_gettextasync.h
@@ -0,0 +1,5 @@
+#pragma once
+void InitCacheAsync();
+void UninitCacheAsync();
+void gtaRenewText(HANDLE hContact);
+int gtaAddRequest(struct ClcData *dat,struct ClcContact *contact,HANDLE hContact); \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_global_structure.h b/plugins/Clist_modern/src/hdr/modern_global_structure.h
new file mode 100644
index 0000000000..09036459ec
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_global_structure.h
@@ -0,0 +1,92 @@
+#pragma once
+
+#ifndef modern_global_structure_h__
+#define modern_global_structure_h__
+
+typedef struct tagCLUIDATA
+{
+ /************************************
+ ** Global variables **
+ ************************************/
+
+ /* NotifyArea menu */
+ HMENU hMenuNotify;
+ WORD wNextMenuID;
+ int iIconNotify;
+ BOOL bEventAreaEnabled;
+ BOOL bNotifyActive;
+ DWORD dwFlags;
+ TCHAR * szNoEvents;
+ int hIconNotify;
+ HANDLE hUpdateContact;
+
+ /* Contact List View Mode */
+ TCHAR groupFilter[2048];
+ char protoFilter[2048];
+ char varFilter[2048];
+ DWORD lastMsgFilter;
+ char current_viewmode[256], old_viewmode[256];
+ BYTE boldHideOffline;
+ BYTE bOldUseGroups;
+ DWORD statusMaskFilter;
+ DWORD stickyMaskFilter;
+ DWORD filterFlags;
+ DWORD bFilterEffective;
+ BOOL bMetaAvail;
+ DWORD t_now;
+
+ // Modern Global Variables
+ BOOL fDisableSkinEngine;
+ BOOL fOnDesktop;
+ BOOL fSmoothAnimation;
+ BOOL fLayered;
+ BOOL fDocked;
+ BOOL fGDIPlusFail;
+ BOOL fSortNoOfflineBottom;
+ BOOL fAutoSize;
+ BOOL fAeroGlass;
+ HRGN hAeroGlassRgn;
+
+ BOOL mutexPreventDockMoving;
+ BOOL mutexOnEdgeSizing;
+ BOOL mutexPaintLock;
+
+ BYTE bCurrentAlpha;
+ BYTE bSTATE;
+ BYTE bBehindEdgeSettings;
+ BYTE bSortByOrder[3];
+
+ signed char nBehindEdgeState;
+
+ DWORD dwKeyColor;
+
+ HWND hwndEventFrame;
+
+ int LeftClientMargin;
+ int RightClientMargin;
+ int TopClientMargin;
+ int BottomClientMargin;
+
+ BOOL bInternalAwayMsgDiscovery;
+ BOOL bRemoveAwayMessageForOffline;
+
+ //hEventHandles
+
+ HANDLE hEventExtraImageListRebuilding;
+ HANDLE hEventExtraImageApplying;
+ HANDLE hEventExtraClick;
+ HANDLE hEventBkgrChanged;
+ HANDLE hEventPreBuildTrayMenu;
+ HANDLE hEventPreBuildFrameMenu;
+ HANDLE hEventPreBuildGroupMenu;
+ HANDLE hEventPreBuildSubGroupMenu;
+ HANDLE hEventStatusBarShowToolTip;
+ HANDLE hEventStatusBarHideToolTip;
+ HANDLE hEventSkinServicesCreated;
+
+ int nGapBetweenTitlebar;
+} CLUIDATA;
+
+EXTERN_C CLUIDATA g_CluiData;
+
+#endif // modern_global_structure_h__
diff --git a/plugins/Clist_modern/src/hdr/modern_image_array.h b/plugins/Clist_modern/src/hdr/modern_image_array.h
new file mode 100644
index 0000000000..130c51ce95
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_image_array.h
@@ -0,0 +1,104 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+
+Created by Pescuma
+
+*/
+
+#pragma once
+
+#ifndef __IMAGE_ARRAY_H__
+# define __IMAGE_ARRAY_H__
+
+#include <windows.h>
+
+
+typedef struct _IMAGE_ARRAY_DATA_NODE
+{
+ int width;
+ int height;
+}
+IMAGE_ARRAY_DATA_NODE;
+
+typedef struct _IMAGE_ARRAY_DATA
+{
+ // Configuration
+ BOOL width_based;
+ int grow_step;
+ HDC hdc;
+
+ // Img data
+ HBITMAP img;
+ int width;
+ int height;
+ void * lpBits;
+
+ // CS
+ CRITICAL_SECTION cs;
+
+ // Array
+ IMAGE_ARRAY_DATA_NODE *nodes;
+ int nodes_size;
+ int nodes_allocated_size;
+}
+IMAGE_ARRAY_DATA, *LP_IMAGE_ARRAY_DATA;
+
+
+// Initialize data
+void ImageArray_Initialize(LP_IMAGE_ARRAY_DATA iad, BOOL width_based, int grow_step);
+
+// Free data but keep config
+void ImageArray_Clear(LP_IMAGE_ARRAY_DATA iad);
+
+// Free data
+// If keep_bitmap is TRUE, doesn't delete de bitmap and return its handle. Else, return NULL
+HBITMAP ImageArray_Free(LP_IMAGE_ARRAY_DATA iad, BOOL keep_bitmap);
+
+// Add image to the list (return the index of the image or -1 on error)
+// If pos == -1, add to the end of the list
+int ImageArray_AddImage(LP_IMAGE_ARRAY_DATA iad, HBITMAP hBmp, int pos);
+
+// Change an image in the list (return TRUE on success)
+BOOL ImageArray_ChangeImage(LP_IMAGE_ARRAY_DATA iad, HBITMAP hBmp, int pos);
+
+// Remove an image
+BOOL ImageArray_RemoveImage(LP_IMAGE_ARRAY_DATA iad, int pos);
+
+// Draw an image
+BOOL ImageArray_DrawImage(LP_IMAGE_ARRAY_DATA iad, int pos, HDC hdcDest, int nXDest, int nYDest, BYTE Alpha);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif // __IMAGE_ARRAY_H__
diff --git a/plugins/Clist_modern/src/hdr/modern_layered_window_engine.h b/plugins/Clist_modern/src/hdr/modern_layered_window_engine.h
new file mode 100644
index 0000000000..918bfabf37
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_layered_window_engine.h
@@ -0,0 +1,51 @@
+#pragma once
+#include "../m_api/m_skin_eng.h"
+
+// typedef int (/*__stdcall*/ *tPaintCallbackProc)(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgnUpdate, DWORD dFlags, void * CallBackData);
+
+class CLayeredWindowEngine
+{
+private:
+ /*class CLweInfo
+ {
+ HWND hWnd;
+ HRGN hInvalidRgn;
+ };
+ */
+ //typedef std::map<HWND, CLweInfo> WndInfos;
+
+ enum { state_invalid, state_normal };
+
+ //WndInfos m_infos;
+ DWORD m_hValidatorThread;
+ CRITICAL_SECTION m_cs;
+ int m_state;
+ volatile bool m_invalid;
+
+public:
+ CLayeredWindowEngine(void);
+ ~CLayeredWindowEngine(void);
+
+ void _init();
+ void _deinit();
+
+ void lock() { EnterCriticalSection( &m_cs ); }
+ void unlock() { LeaveCriticalSection( &m_cs ); }
+
+ int get_state();
+
+public:
+ static void __cdecl LweValidatorProc();
+
+ void LweValidatorProcWorker();
+
+ void LweValidatorWorker();
+ int LweInvalidateRect( HWND hWnd, const RECT * rect, BOOL bErase );
+ // int LweValidateWindowRect( HWND hWnd, RECT * rect );
+ // int RegisterWindow( HWND hwnd, tPaintCallbackProc pPaintCallBackProc );
+
+};
+
+extern CLayeredWindowEngine _lwe;
+
+#define _InvalidateRect _lwe.LweInvalidateRect \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_log.h b/plugins/Clist_modern/src/hdr/modern_log.h
new file mode 100644
index 0000000000..0696c280bd
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_log.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#ifndef __LOG_H__
+# define __LOG_H__
+
+#ifdef _DEBUG_LOG
+
+void Log(const char *file,int line,const char *fmt,...);
+#define logg() Log(__FILE__,__LINE__,"")
+#define log0(s) Log(__FILE__,__LINE__,s)
+#define log1(s,a) Log(__FILE__,__LINE__,s,a)
+#define log2(s,a,b) Log(__FILE__,__LINE__,s,a,b)
+#define log3(s,a,b,c) Log(__FILE__,__LINE__,s,a,b,c)
+#define log4(s,a,b,c,d) Log(__FILE__,__LINE__,s,a,b,c,d)
+
+#else
+
+#define logg()
+#define log0(s)
+#define log1(s,a)
+#define log2(s,a,b)
+#define log3(s,a,b,c)
+#define log4(s,a,b,c,d)
+
+#endif
+
+#endif // __LOG_H__ \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_popup.h b/plugins/Clist_modern/src/hdr/modern_popup.h
new file mode 100644
index 0000000000..d333ab1e36
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_popup.h
@@ -0,0 +1,48 @@
+/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+#pragma once
+
+#ifndef __POPUP_H__
+# define __POPUP_H__
+
+#include <m_popup.h>
+
+extern BOOL EnablePopups;
+
+
+#define POPUP_TYPE_NORMAL 0
+#define POPUP_TYPE_TEST 1
+#define POPUP_TYPE_ERROR 2
+
+// Show an popup
+void ShowPopup(const char *title, const char *description, int type);
+
+// Show an error popup
+void ShowErrPopup(const char *title, const char *description);
+
+// Show an trace popup
+void ShowTracePopup(const char *text);
+
+
+
+
+
+
+#endif // __POPUP_H__
diff --git a/plugins/Clist_modern/src/hdr/modern_row.h b/plugins/Clist_modern/src/hdr/modern_row.h
new file mode 100644
index 0000000000..47b9582c29
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_row.h
@@ -0,0 +1,86 @@
+#ifndef modern_row_h__
+#define modern_row_h__
+
+#pragma once
+
+
+// Types of cells
+#define TC_TEXT1 1
+#define TC_TEXT2 2
+#define TC_TEXT3 3
+#define TC_STATUS 4
+#define TC_AVATAR 5
+#define TC_EXTRA 6
+#define TC_EXTRA1 7
+#define TC_EXTRA2 8
+#define TC_EXTRA3 9
+#define TC_EXTRA4 10
+#define TC_EXTRA5 11
+#define TC_EXTRA6 12
+#define TC_EXTRA7 13
+#define TC_EXTRA8 14
+#define TC_EXTRA9 15
+#define TC_TIME 16
+#define TC_SPACE 17
+#define TC_FIXED 18
+
+
+#define TC_ELEMENTSCOUNT 18
+
+// Containers
+#define TC_ROOT 50
+#define TC_ROW 51
+#define TC_COL 52
+#define TC_FLOAT 53
+
+// Alignes
+#define TC_LEFT 0
+#define TC_HCENTER 100
+#define TC_RIGHT 101
+
+#define TC_TOP 0
+#define TC_VCENTER 102
+#define TC_BOTTOM 103
+
+// Sizes
+#define TC_WIDTH 104
+#define TC_HEIGHT 105
+
+
+
+// Ñòðóêòóðà, îïèñûâàþùàÿ êîíòåéíåð ýëåìåíòà êîíòàêòà
+//
+typedef struct tagRowCell
+{
+ int cont; // Òèï êîíòåéíåðà - êîíòàêò, ñòîðîêà, ñòîëáåö
+ int type; // Òèï ýëåìåíòà, ñîäåðæàùåãîñÿ â êîíòåéíåðå, åñëè 0 - ïóñòîé êîíòåéíåð
+ int halign; // Ãîðèçîíòàëüíîå âûðàâíèâàíèå âíóòðè êîíòåéíåðà
+ int valign; // Âåðòèêàëüíîå âûðàâíèâàíèå âíóòðè êîíòåéíåðà
+
+ int w; // Øèðèíà ýëåìåíòà êîíòàêòà, äëÿ òåêñòîâûõ ïîëåé èãíîðèðóåòñÿ
+ int h; // Âûñîòà ýëåìåíòà êîòíàêòà
+
+ BOOL sizing; // Ïàðàìåòð, ïîêàçûâàþùèé íàëè÷èå òåêñòîâûõ ïîëåé â äî÷åðíèõ êîíòåéíåðàõ
+ BOOL layer; // Ïàðàìåòð, ïîêàçûâàþùèé, ÷òî êîíòåéíåð îáðàçóåò íîâûé ñëîé
+
+ BOOL hasfixed; // Ïàðàìåòð ïîêàçûâàþùèé ÷òî åñòü âëîæåííûå ôèêñèðîâàííûå ýëåìåíòû
+ BOOL fitwidth; // Ïàðàìåòð óêàçûâàþùèé ÷òî ïîñëåäíèé ýëåìåíò çàïîëíÿåò âñå îñòàâøååñÿ
+ // Ïðîñòðàíñòâî (ðàññòÿãèâàåò ðîäèòåëÿ.îâåðëåé)
+
+ int fixed_width;
+ int full_width;
+
+ RECT r; // Ïðÿìîóãîëüíèê äëÿ ðèñîâàíèÿ ýëåìåíòà
+ struct tagRowCell * next; // Ïîëå ñâÿçè
+ struct tagRowCell * child; // Ïîëå ñâÿçè ñì. ôàéë îïèñàíèÿ
+} ROWCELL, *pROWCELL;
+
+// Ñòðóêòóðà äëÿ äîñòóïà ê êîíòåéíåðàì ýëåìåíòà êîíòàêòà âíóòðè äåðåâà îïèâàíèÿ
+#ifndef _CPPCODE
+ int cppCalculateRowHeight(ROWCELL *RowRoot);
+ void cppCalculateRowItemsPos(ROWCELL *RowRoot, int width);
+ ROWCELL *cppInitModernRow(ROWCELL ** tabAccess);
+ void cppDeleteTree(ROWCELL * RowRoot);
+#endif
+
+#endif // modern_row_h__ \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_rowheight_funcs.h b/plugins/Clist_modern/src/hdr/modern_rowheight_funcs.h
new file mode 100644
index 0000000000..57223cf3c0
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_rowheight_funcs.h
@@ -0,0 +1,70 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+
+Created by Pescuma
+
+*/
+
+#pragma once
+
+#ifndef __ROWHEIGHT_FUNCS_H__
+# define __ROWHEIGHT_FUNCS_H__
+
+#include "modern_clc.h"
+
+#define ROW_SPACE_BEETWEEN_LINES 2
+#define ICON_HEIGHT 16
+#define ICON_WIDTH 16
+
+
+
+BOOL RowHeights_Initialize(struct ClcData *dat);
+void RowHeights_Free(struct ClcData *dat);
+void RowHeights_Clear(struct ClcData *dat);
+
+BOOL RowHeights_Alloc(struct ClcData *dat, int size);
+
+// Calc and store max row height
+int RowHeights_GetMaxRowHeight(struct ClcData *dat, HWND hwnd);
+
+// Calc and store row height
+int RowHeights_GetRowHeight(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item);
+
+// Calc and store row height for all itens in the list
+void RowHeights_CalcRowHeights(struct ClcData *dat, HWND hwnd);
+
+// Calc item top Y (using stored data)
+int cliGetRowTopY(struct ClcData *dat, int item);
+
+// Calc item bottom Y (using stored data)
+int cliGetRowBottomY(struct ClcData *dat, int item);
+
+// Calc total height of rows (using stored data)
+int cliGetRowTotalHeight(struct ClcData *dat);
+
+// Return the line that pos_y is at or -1 (using stored data). Y start at 0
+int cliRowHitTest(struct ClcData *dat, int pos_y);
+
+// Returns the height of the chosen row
+int cliGetRowHeight(struct ClcData *dat, int item);
+
+#endif // __ROWHEIGHT_FUNCS_H__
diff --git a/plugins/Clist_modern/src/hdr/modern_skinengine.h b/plugins/Clist_modern/src/hdr/modern_skinengine.h
new file mode 100644
index 0000000000..a2b365b2ba
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_skinengine.h
@@ -0,0 +1,148 @@
+#pragma once
+
+#ifndef ske_H_INC
+#define ske_H_INC
+
+#include "modern_skinselector.h"
+#include "modern_commonprototypes.h"
+
+/* Definitions */
+#define GetAValue(argb)((BYTE)((argb)>>24))
+
+#define DEFAULTSKINSECTION "ModernSkin"
+
+
+
+#define MAX_BUFF_SIZE 255*400
+#define MAXSN_BUFF_SIZE 255*1000
+
+/* External variables */
+
+/* Structs */
+
+typedef struct tagSKINOBJECTSLIST
+{
+ DWORD dwObjLPReserved;
+ DWORD dwObjLPAlocated;
+ char * szSkinPlace;
+ LISTMODERNMASK * pMaskList;
+ SKINOBJECTDESCRIPTOR * pObjects;
+ SortedList * pTextList;
+} SKINOBJECTSLIST;
+
+typedef struct tagGLYPHIMAGE
+{
+ char * szFileName;
+ DWORD dwLoadedTimes;
+ HBITMAP hGlyph;
+ BYTE isSemiTransp;
+} GLYPHIMAGE,*LPGLYPHIMAGE;
+
+typedef struct tagCURRWNDIMAGEDATA
+{
+ HDC hImageDC;
+ HDC hBackDC;
+ HDC hScreenDC;
+ HBITMAP hImageDIB, hImageOld;
+ HBITMAP hBackDIB, hBackOld;
+ BYTE * hImageDIBByte;
+ BYTE * hBackDIBByte;
+ int Width,Height;
+
+}CURRWNDIMAGEDATA;
+
+typedef struct tagEFFECTSSTACKITEM
+{
+ HDC hdc;
+ BYTE EffectID;
+ DWORD FirstColor;
+ DWORD SecondColor;
+} EFFECTSSTACKITEM;
+
+#pragma pack(push, 1)
+/* tga header */
+typedef struct
+{
+ BYTE id_lenght; /* size of image id */
+ BYTE colormap_type; /* 1 is has a colormap */
+ BYTE image_type; /* compression type */
+
+ short cm_first_entry; /* colormap origin */
+ short cm_length; /* colormap length */
+ BYTE cm_size; /* colormap size */
+
+ short x_origin; /* bottom left x coord origin */
+ short y_origin; /* bottom left y coord origin */
+
+ short width; /* picture width (in pixels) */
+ short height; /* picture height (in pixels) */
+
+ BYTE pixel_depth; /* bits per pixel: 8, 16, 24 or 32 */
+ BYTE image_descriptor; /* 24 bits = 0x00; 32 bits = 0x80 */
+
+} tga_header_t;
+#pragma pack(pop)
+
+
+class IniParser
+{
+public:
+ enum { FLAG_WITH_SETTINGS = 0,
+ FLAG_ONLY_OBJECTS = 1,
+ };
+
+ enum { IT_UNKNOWN, IT_FILE, IT_RESOURCE };
+
+ typedef HRESULT (*ParserCallback_t)( const char * szSection, const char * szKey, const char * szValue, IniParser * This );
+
+ IniParser( TCHAR * szFileName, BYTE flags = FLAG_WITH_SETTINGS );
+ IniParser( HINSTANCE hInst, const char * resourceName, const char * resourceType, BYTE flags = FLAG_ONLY_OBJECTS );
+ ~IniParser();
+
+ bool CheckOK() { return _isValid; }
+ HRESULT Parse( ParserCallback_t pLineCallBackProc, LPARAM lParam );
+
+ static HRESULT WriteStrToDb( const char * szSection, const char * szKey, const char * szValue, IniParser * This);
+ static int GetSkinFolder( IN const TCHAR * szFileName, OUT TCHAR * pszFolderName );
+
+private:
+
+ // common
+ enum { MAX_LINE_LEN = 512 };
+ int _eType;
+ bool _isValid;
+ char * _szSection;
+ ParserCallback_t _pLineCallBackProc;
+ BOOL _SecCheck;
+ int _nLine;
+
+ void _DoInit();
+ BOOL _DoParseLine( char * szLine );
+
+ // Processing File
+ HRESULT _DoParseFile();
+ FILE * _hFile;
+
+ // Processing resource
+ void _LoadResourceIni( HINSTANCE hInst, const char * resourceName, const char * resourceType );
+ HRESULT _DoParseResource();
+ const char * _RemoveTailings( const char * szLine, size_t& len );
+
+ HGLOBAL _hGlobalRes;
+ DWORD _dwSizeOfRes;
+ char * _pPosition;
+
+ BYTE _Flags;
+
+
+};
+
+
+int ske_UnloadSkin(SKINOBJECTSLIST * Skin);
+int ske_AddDescriptorToSkinObjectList (LPSKINOBJECTDESCRIPTOR lpDescr, SKINOBJECTSLIST* Skin);
+INT_PTR ske_Service_DrawGlyph(WPARAM wParam,LPARAM lParam);
+
+
+
+#endif
+
diff --git a/plugins/Clist_modern/src/hdr/modern_skinned_profile.h b/plugins/Clist_modern/src/hdr/modern_skinned_profile.h
new file mode 100644
index 0000000000..95ab85c606
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_skinned_profile.h
@@ -0,0 +1,245 @@
+#ifndef modern_skinned_profile_h__
+#define modern_skinned_profile_h__
+
+//#include "modern_commonheaders.h"
+//#include "modern_commonprototypes.h"
+
+#include <map>
+#include <string>
+//#include <atlstr.h>
+
+class MString
+{
+private:
+ TCHAR * _buffer;
+public:
+ MString() : _buffer( NULL ) {};
+ MString( const TCHAR * str ) { _buffer = str ? _tcsdup( str ) : NULL; }
+ MString( const MString& str ) { _buffer = str._buffer ? _tcsdup( str._buffer ) : NULL; }
+ MString& operator=( const MString& str )
+ {
+ if ( _buffer ) free( _buffer );
+ _buffer = str._buffer ? _tcsdup( str._buffer ) : NULL;
+ }
+ TCHAR* operator()( const MString& str ) { return _buffer; }
+ ~MString()
+ {
+ if ( _buffer )
+ free( _buffer );
+ _buffer = NULL;
+ }
+
+#ifdef _UNICODE
+ MString( const char * str)
+ {
+ if ( !str )
+ _buffer = NULL;
+ else
+ {
+ int cbLen = MultiByteToWideChar( 0, 0, str, -1, NULL, 0 );
+ wchar_t* _buffer = ( wchar_t* )malloc( sizeof( wchar_t )*(cbLen+1));
+ if ( _buffer == NULL ) return;
+ MultiByteToWideChar( 0, 0, str, -1, _buffer, cbLen );
+ _buffer[ cbLen ] = 0;
+ }
+ }
+#endif
+
+};
+
+class CAutoCriticalSection
+{
+public:
+ CAutoCriticalSection() //Init critical section here
+ : _pLinkedCS( NULL )
+ {
+ InitializeCriticalSection( &_CS );
+ _ifCSOwner = true;
+ _ifLocked = false;
+ }
+ CAutoCriticalSection( CAutoCriticalSection& Locker, bool doLock = true )
+ : _pLinkedCS ( &Locker )
+ {
+ _ifCSOwner = false;
+ _ifLocked = false;
+ if ( doLock )
+ Lock();
+ }
+ ~CAutoCriticalSection() // Leave if auto locker, and destroy if not
+ {
+ if ( _ifLocked )
+ Unlock();
+ if ( _ifCSOwner )
+ DeleteCriticalSection( &_CS );
+ }
+
+ void Lock() // Enter Section
+ {
+ if ( _ifLocked ) return;
+ if ( _ifCSOwner ) EnterCriticalSection( &_CS );
+ else _pLinkedCS->Lock();
+ _ifLocked = true;
+ return;
+ }
+ void Unlock() // Leave Section
+ {
+ if ( !_ifLocked ) return;
+ if ( _ifCSOwner ) LeaveCriticalSection( &_CS );
+ else _pLinkedCS->Unlock();
+ _ifLocked = false;
+ }
+
+private:
+ CRITICAL_SECTION _CS;
+ CAutoCriticalSection * _pLinkedCS;
+ bool _ifCSOwner;
+ bool _ifLocked;
+};
+
+class ValueVariant
+{
+public:
+ ValueVariant() : _type( VVT_EMPTY ) {};
+ ValueVariant( BYTE bValue ) : _type( VVT_BYTE ), _bValue( bValue ) {};
+ ValueVariant( WORD wValue ) : _type( VVT_WORD ), _wValue( wValue ) {};
+ ValueVariant( DWORD dwValue ) : _type( VVT_DWORD ), _dwValue( dwValue ) {};
+ ValueVariant( const MString& strValue ) : _type( VVT_STRING ), _strValue( strValue ) {};
+ ValueVariant( const char * szValue ) : _type( VVT_STRING ), _strValue( szValue ) {};
+#ifdef _UNICODE
+ ValueVariant( const wchar_t * szValue ) : _type( VVT_STRING ), _strValue( szValue ) {};
+#endif
+
+ BYTE GetByte()
+ {
+ switch ( _type )
+ {
+ case VVT_BYTE:
+ return ( BYTE ) _bValue;
+ case VVT_WORD:
+ case VVT_DWORD:
+ DebugBreak();
+ return ( BYTE ) _bValue;
+ default:
+ DebugBreak();
+ }
+ return 0;
+ }
+
+ WORD GetWord()
+ {
+ switch ( _type )
+ {
+ case VVT_WORD:
+ return ( WORD ) _wValue;
+
+ case VVT_BYTE:
+ case VVT_DWORD:
+ DebugBreak();
+ return ( WORD ) _wValue;
+ default:
+ DebugBreak();
+ }
+ return 0;
+ }
+
+ DWORD GetDword()
+ {
+ switch ( _type )
+ {
+ case VVT_DWORD:
+ return ( DWORD ) _dwValue;
+
+ case VVT_BYTE:
+ case VVT_WORD:
+ DebugBreak();
+ return ( DWORD ) _dwValue;
+ default:
+ DebugBreak();
+ }
+ return 0;
+ }
+ MString GetString()
+ {
+ switch ( _type )
+ {
+ case VVT_STRING:
+ return _strValue;
+
+ default:
+ DebugBreak();
+ }
+ return "";
+ }
+ const MString& GetStringStatic()
+ {
+ switch ( _type )
+ {
+ case VVT_STRING:
+ return _strValue;
+
+ default:
+ DebugBreak();
+ }
+ return _strValue;
+ }
+ bool IsEmpty() { return _type==VVT_EMPTY; }
+
+private:
+ enum
+ {
+ VVT_EMPTY = 0,
+ VVT_BYTE,
+ VVT_WORD,
+ VVT_DWORD,
+ VVT_STRING
+ };
+ int _type;
+ union
+ {
+ BYTE _bValue;
+ WORD _wValue;
+ DWORD _dwValue;
+ };
+ MString _strValue;
+
+};
+
+// this is single tone class to represent some profile settings to be skinned
+class CSkinnedProfile
+{
+private:
+ static CSkinnedProfile _me;
+ CSkinnedProfile();
+ ~CSkinnedProfile();
+
+private:
+ // Skinned profile holded attributes
+ MString _strSkinFilename;
+ bool _bLoadedFonts;
+ bool _bLoadedOthers;
+
+ typedef std::map<HashStringKeyNoCase, ValueVariant> ValueList_t;
+ typedef std::map<HashStringKeyNoCase, ValueList_t> KeyList_t;
+
+ KeyList_t SkinnedProfile;
+
+ ValueVariant* _GetValue( const char * szSection, const char * szKey );
+
+ CAutoCriticalSection _Lock; // critical section to matable skinned profile access
+
+public:
+ static CSkinnedProfile* SkinProfile() { return &_me; }
+
+ HRESULT Init();
+ HRESULT Clear();
+
+ static BYTE SpiGetSkinByte ( HANDLE hContact, const char * szSection, const char * szKey, const BYTE defValue );
+ static WORD SpiGetSkinWord ( HANDLE hContact, const char * szSection, const char * szKey, const WORD defValue );
+ static DWORD SpiGetSkinDword( HANDLE hContact, const char * szSection, const char * szKey, const DWORD defValue );
+ static BOOL SpiCheckSkinned( HANDLE hContact, const char * szSection, const char * szKey );
+
+};
+
+
+
+#endif // modern_skinned_profile_h__ \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_skinselector.h b/plugins/Clist_modern/src/hdr/modern_skinselector.h
new file mode 100644
index 0000000000..9509695ad3
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_skinselector.h
@@ -0,0 +1,88 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+*/
+#pragma once
+
+#ifndef M_MOD_SKIN_SELECTOR_H_INC
+#define M_MOD_SKIN_SELECTOR_H_INC
+
+#include "newpluginapi.h"
+#include "modern_commonheaders.h"
+
+#define MAXVALUE 20
+
+#define MPF_EQUAL 1
+#define MPF_DIFF 2
+#define MPF_NOT_EQUAL ( MPF_DIFF|MPF_EQUAL )
+#define MPF_HASHED 4
+
+typedef struct tagMASKPARAM
+{
+ DWORD dwId;
+ BYTE bMaskParamFlag;
+ char* szName;
+ DWORD dwValueHash;
+ char* szValue;
+} MASKPARAM;
+
+
+typedef struct tagMODERNMASK
+{
+ MASKPARAM* pl_Params;
+ DWORD dwParamCnt;
+ union
+ {
+ void* pObject;
+ char* szObjectName;
+ };
+ DWORD dwMaskId;
+ BOOL bObjectFound;
+} MODERNMASK;
+
+typedef struct tagLISTMODERNMASK
+{
+ MODERNMASK* pl_Masks;
+ DWORD dwMaskCnt;
+} LISTMODERNMASK;
+
+/// PROTOTYPES
+int AddModernMaskToList(MODERNMASK * mm, LISTMODERNMASK * mmTemplateList);
+int AddStrModernMaskToList(DWORD maskID, char * szStr, char * objectName, LISTMODERNMASK * mmTemplateList, void * pObjectList);
+int SortMaskList(LISTMODERNMASK * mmList);
+
+int DeleteMaskByItID(DWORD mID,LISTMODERNMASK * mmTemplateList);
+int ClearMaskList(LISTMODERNMASK * mmTemplateList);
+int ExchangeMasksByID(DWORD mID1, DWORD mID2, LISTMODERNMASK * mmTemplateList);
+
+int ParseToModernMask(MODERNMASK * mm, char * szText);
+BOOL CompareModernMask(MODERNMASK * mmValue,MODERNMASK * mmTemplate);
+BOOL CompareStrWithModernMask(char * szValue,MODERNMASK * mmTemplate);
+MODERNMASK * FindMaskByStr(char * szValue,LISTMODERNMASK * mmTemplateList);
+DWORD mod_CalcHash(const char * a);
+char * ModernMaskToString(MODERNMASK * mm, char * buf, UINT bufsize);
+BOOL __inline wildcmp(const char * name, const char * mask, BYTE option);
+int RegisterObjectByParce(char * ObjectName, char * Params);
+SKINOBJECTDESCRIPTOR * skin_FindObjectByRequest(char * szValue,LISTMODERNMASK * mmTemplateList);
+SKINOBJECTDESCRIPTOR * skin_FindObjectByMask (MODERNMASK * mm,LISTMODERNMASK * mmTemplateList);
+TCHAR * GetParamNT(char * string, TCHAR * buf, int buflen, BYTE paramN, char Delim, BOOL SkipSpaces);
+int SkinDrawGlyphMask(HDC hdc, RECT * rcSize, RECT * rcClip, MODERNMASK * ModernMask);
+#endif
diff --git a/plugins/Clist_modern/src/hdr/modern_static_clui.h b/plugins/Clist_modern/src/hdr/modern_static_clui.h
new file mode 100644
index 0000000000..11e492e211
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_static_clui.h
@@ -0,0 +1,246 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+*/
+
+/************************************************************************/
+/** FILE CONTAINS HEADER PART FOR .../modernb/clui.c file **/
+/** **/
+/** !!! DO NOT INCLUDE IN TO OTHER FILES !!! **/
+/************************************************************************/
+
+/* Definitions */
+#pragma once
+
+#define TM_AUTOALPHA 1
+#define TM_DELAYEDSIZING 2
+#define TM_BRINGOUTTIMEOUT 3
+#define TM_BRINGINTIMEOUT 4
+#define TM_UPDATEBRINGTIMER 5
+#define TM_SMOTHALPHATRANSITION 20
+#define TM_WINDOWUPDATE 100
+#define TM_STATUSBARUPDATE 200
+
+
+
+
+#define MS_CLUI_SHOWMAINMENU "CList/ShowMainMenu"
+#define MS_CLUI_SHOWSTATUSMENU "CList/ShowStatusMenu"
+
+#define AC_SRC_NO_PREMULT_ALPHA 0x01
+#define AC_SRC_NO_ALPHA 0x02
+#define AC_DST_NO_PREMULT_ALPHA 0x10
+#define AC_DST_NO_ALPHA 0x20
+
+#define ANIMATION_STEP 40
+
+#define AEROGLASS_MINALPHA 24
+
+/* Declaration of prototypes in other modules */
+
+int ClcUnloadModule();
+int ClcGetShortData(struct ClcData* pData, struct SHORTDATA *pShortData);
+int ClcEnterDragToScroll(HWND hwnd, int Y);
+
+int CListMod_ContactListShutdownProc(WPARAM wParam,LPARAM lParam);
+int CListMod_HideWindow(HWND hwndContactList, int mode);
+
+int CListSettings_GetCopyFromCache(pdisplayNameCacheEntry pDest, DWORD flag);
+int CListSettings_SetToCache(pdisplayNameCacheEntry pSrc, DWORD flag);
+
+int CLUIServices_LoadModule(void);
+INT_PTR CLUIServices_SortList(WPARAM wParam,LPARAM lParam);
+INT_PTR CLUIServices_ProtocolStatusChanged(WPARAM wParam,LPARAM lParam);
+
+void Docking_GetMonitorRectFromWindow(HWND hWnd,RECT *rc);
+
+int EventArea_Create(HWND hCluiWnd);
+
+int ExtraImage_ExtraIDToColumnNum(int extra);
+void ExtraImage_LoadModule();
+void ExtraImage_ReloadExtraIcons();
+void ExtraImage_SetAllExtraIcons(HWND hwndList,HANDLE hContact);
+
+void GroupMenus_Init();
+
+int ModernSkinButtonLoadModule();
+int ModernSkinButton_ReposButtons(HWND parent, BYTE draw,RECT *r);
+
+void ske_ApplyTransluency();
+HBITMAP ske_CreateDIB32(int cx, int cy);
+HBITMAP ske_CreateDIB32Point(int cx, int cy, void ** bits);
+int ske_JustUpdateWindowImage();
+void ske_LoadSkinFromDB(void);
+int ske_RedrawCompleteWindow();
+int ske_UpdateWindowImage();
+int ske_ValidateFrameImageProc(RECT * r);
+
+HWND StatusBar_Create(HWND parent);
+
+void RowHeight_InitModernRow();
+
+int UnhookAll();
+
+
+/* External variables */
+
+
+/* Global variables */
+
+
+DWORD g_dwMainThreadID=0,
+ g_dwAwayMsgThreadID=0,
+ g_dwGetTextAsyncThreadID=0,
+ g_dwSmoothAnimationThreadID=0,
+ g_dwFillFontListThreadID=0;
+
+HMENU g_hMenuMain;
+BOOL g_bTransparentFlag=FALSE;
+
+BOOL g_mutex_bChangingMode=FALSE,
+ g_mutex_bSizing=FALSE;
+
+BOOL g_flag_bOnModulesLoadedCalled=FALSE;
+
+RECT g_rcEdgeSizingRect={0};
+
+BOOL (WINAPI *g_proc_SetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD);
+BOOL (WINAPI *g_proc_SetLayeredWindowAttributesNew)(HWND,COLORREF,BYTE,DWORD);
+BOOL (WINAPI *g_proc_AnimateWindow)(HWND hWnd,DWORD dwTime,DWORD dwFlags);
+
+/* Module function prototypes */
+
+int CLUI_IsInMainWindow(HWND hwnd);
+int CLUI_SizingOnBorder(POINT pt, int size);
+int CLUI_SmoothAlphaTransition(HWND hwnd, BYTE GoalAlpha, BOOL wParam);
+int CLUI_TestCursorOnBorders();
+
+static int CLUI_CreateTimerForConnectingIcon(WPARAM wParam,LPARAM lParam);
+static int CLUI_SmoothAlphaThreadTransition(HWND hwnd);
+
+/* structs */
+
+typedef struct tagPROTOTICKS{
+ int nIconsCount;
+ int nCycleStartTick;
+ char * szProto;
+ int nIndex;
+ BOOL bTimerCreated;
+ BOOL bGlobal;
+ HIMAGELIST himlIconList;
+} PROTOTICKS,*LPPROTOTICKS;
+
+typedef struct tagCHECKFILLING
+{
+ HDC hDC;
+ RECT rcRect;
+} CHECKFILLING;
+
+/* Module global variables */
+
+static BYTE bAlphaEnd;
+static BYTE bOldHideOffline;
+static BYTE bOldUseGroups;
+
+static WORD wBehindEdgeShowDelay,
+ wBehindEdgeHideDelay,
+ wBehindEdgeBorderSize;
+
+static BOOL mutex_bAnimationInProgress=FALSE,
+ mutex_bShowHideCalledFromAnimation=FALSE,
+ mutex_bIgnoreActivation=FALSE,
+ mutex_bDisableAutoUpdate=TRUE,
+ mutex_bDuringSizing=FALSE,
+ mutex_bDelayedSizing=FALSE; //TBC is it need?
+
+static BOOL flag_bFirstTimeCall=FALSE;
+
+static BOOL bTransparentFocus=TRUE,
+ bNeedFixSizingRect=FALSE,
+ bShowEventStarted=FALSE;
+
+static HANDLE hRenameMenuItem,
+ hShowAvatarMenuItem,
+ hHideAvatarMenuItem;
+
+static UINT uMsgGetProfile=0;
+
+static int nLastRequiredHeight=0,
+ nRequiredHeight=0,
+ nMirMenuState=0,
+ nStatusMenuState=0;
+
+static RECT rcNewWindowRect={0},
+ rcOldWindowRect ={0},
+ rcSizingRect={0},
+ rcCorrectSizeRect={0};
+
+static HANDLE hFrameContactTree;
+
+static PROTOTICKS CycleStartTick[64]={0};//max 64 protocols
+
+static int nAnimatedIconStep=100;
+
+
+
+int CheckFramesPos(RECT *wr); //cluiframes.c
+int CLUIFrames_ApplyNewSizes(int mode); //cluiframes.c
+int CLUIFrames_GetTotalHeight(); //cluiframes.c
+int CLUIFrames_RepaintSubContainers(); //cluiframes.c
+int CLUIFramesGetMinHeight(); //cluiframes.c
+
+int SizeFramesByWindowRect(RECT *r, HDWP * PosBatch, int mode); //cluiframes.c
+
+int InitSkinHotKeys();
+BOOL amWakeThread();
+BOOL gtaWakeThread();
+void CreateViewModeFrame();
+
+HIMAGELIST hAvatarOverlays=NULL;
+
+OVERLAYICONINFO g_pAvatarOverlayIcons[ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE + 1] =
+{
+ { "AVATAR_OVERLAY_OFFLINE", LPGEN("Offline"), IDI_AVATAR_OVERLAY_OFFLINE, -1},
+ { "AVATAR_OVERLAY_ONLINE", LPGEN("Online"), IDI_AVATAR_OVERLAY_ONLINE, -1},
+ { "AVATAR_OVERLAY_AWAY", LPGEN("Away"), IDI_AVATAR_OVERLAY_AWAY, -1},
+ { "AVATAR_OVERLAY_DND", LPGEN("DND"), IDI_AVATAR_OVERLAY_DND, -1},
+ { "AVATAR_OVERLAY_NA", LPGEN("NA"), IDI_AVATAR_OVERLAY_NA, -1},
+ { "AVATAR_OVERLAY_OCCUPIED", LPGEN("Occupied"), IDI_AVATAR_OVERLAY_OCCUPIED, -1},
+ { "AVATAR_OVERLAY_CHAT", LPGEN("Free for chat"), IDI_AVATAR_OVERLAY_CHAT, -1},
+ { "AVATAR_OVERLAY_INVISIBLE", LPGEN("Invisible"), IDI_AVATAR_OVERLAY_INVISIBLE, -1},
+ { "AVATAR_OVERLAY_PHONE", LPGEN("On the phone"), IDI_AVATAR_OVERLAY_PHONE, -1},
+ { "AVATAR_OVERLAY_LUNCH", LPGEN("Out to lunch"), IDI_AVATAR_OVERLAY_LUNCH, -1}
+};
+OVERLAYICONINFO g_pStatusOverlayIcons[ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE + 1] =
+{
+ { "STATUS_OVERLAY_OFFLINE", LPGEN("Offline"), IDI_STATUS_OVERLAY_OFFLINE, -1},
+ { "STATUS_OVERLAY_ONLINE", LPGEN("Online"), IDI_STATUS_OVERLAY_ONLINE, -1},
+ { "STATUS_OVERLAY_AWAY", LPGEN("Away"), IDI_STATUS_OVERLAY_AWAY, -1},
+ { "STATUS_OVERLAY_DND", LPGEN("DND"), IDI_STATUS_OVERLAY_DND, -1},
+ { "STATUS_OVERLAY_NA", LPGEN("NA"), IDI_STATUS_OVERLAY_NA, -1},
+ { "STATUS_OVERLAY_OCCUPIED", LPGEN("Occupied"), IDI_STATUS_OVERLAY_OCCUPIED, -1},
+ { "STATUS_OVERLAY_CHAT", LPGEN("Free for chat"), IDI_STATUS_OVERLAY_CHAT, -1},
+ { "STATUS_OVERLAY_INVISIBLE", LPGEN("Invisible"), IDI_STATUS_OVERLAY_INVISIBLE, -1},
+ { "STATUS_OVERLAY_PHONE", LPGEN("On the phone"), IDI_STATUS_OVERLAY_PHONE, -1},
+ { "STATUS_OVERLAY_LUNCH", LPGEN("Out to lunch"), IDI_STATUS_OVERLAY_LUNCH, -1}
+};
diff --git a/plugins/Clist_modern/src/hdr/modern_static_cluiframes_service.h b/plugins/Clist_modern/src/hdr/modern_static_cluiframes_service.h
new file mode 100644
index 0000000000..34403ad8cd
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_static_cluiframes_service.h
@@ -0,0 +1,192 @@
+//////////////////////////////////////////////////////////////////////////
+// WARNING
+//////////////////////////////////////////////////////////////////////////
+// TO BE INCLUDED ONLY TO modern_cluiframes.cpp
+//////////////////////////////////////////////////////////////////////////
+
+static int _us_DoSetFramePaintProc( WPARAM wParam,LPARAM lParam );
+static int _us_DoAddFrame( WPARAM wParam,LPARAM lParam );
+static int _us_DoRemoveFrame( WPARAM wParam,LPARAM lParam );
+static int _us_DoSetFrameOptions( WPARAM wParam,LPARAM lParam );
+static INT_PTR _us_DoGetFrameOptions( WPARAM wParam,LPARAM lParam );
+static int _us_DoUpdateFrame( WPARAM wParam,LPARAM lParam );
+static int _us_DoShowHideFrameTitle( WPARAM wParam,LPARAM lParam );
+static int _us_DoShowTitles( WPARAM wParam,LPARAM lParam );
+static int _us_DoHideTitles( WPARAM wParam,LPARAM lParam );
+static int _us_DoShowHideFrame( WPARAM wParam,LPARAM lParam );
+static int _us_DoShowAllFrames( WPARAM wParam,LPARAM lParam );
+static int _us_DoLockFrame( WPARAM wParam,LPARAM lParam );
+static int _us_DoCollapseFrame( WPARAM wParam,LPARAM lParam );
+static int _us_DoSetFrameBorder( WPARAM wParam,LPARAM lParam );
+static int _us_DoSetFrameAlign( WPARAM wParam,LPARAM lParam );
+static int _us_DoMoveFrame( WPARAM wParam,LPARAM lParam );
+static int _us_DoMoveFrameUp( WPARAM wParam,LPARAM lParam );
+static int _us_DoMoveFrameDown( WPARAM wParam,LPARAM lParam );
+static int _us_DoAlignFrameTop( WPARAM wParam,LPARAM lParam );
+static int _us_DoAlignFrameClient( WPARAM wParam,LPARAM lParam );
+static int _us_DoAlignFrameBottom( WPARAM wParam,LPARAM lParam );
+static int _us_DoSetFrameFloat( WPARAM wParam,LPARAM lParam );
+
+enum {
+ CFM_FIRST_MGS= WM_USER + 0x2FF,
+
+ CFM_SETFRAMEPAINTPROC,
+ CFM_ADDFRAME,
+ CFM_REMOVEFRAME,
+ CFM_SETFRAMEOPTIONS,
+ CFM_GETFRAMEOPTIONS,
+ CFM_UPDATEFRAME,
+ CFM_SHOWHIDEFRAMETITLE,
+ CFM_SHOWTITLES,
+ CFM_HIDETITLES,
+ CFM_SHOWHIDEFRAME,
+ CFM_SHOWALL,
+ CFM_LOCKFRAME,
+ CFM_COLLAPSEFRAME,
+ CFM_SETFRAMEBORDER,
+ CFM_SETFRAMEALIGN,
+ CFM_MOVEFRAME,
+ CFM_MOVEFRAMEUP,
+ CFM_MOVEFRAMEDOWN,
+ CFM_ALIGNFRAMETOP,
+ CFM_ALIGNFRAMEBOTTOM,
+ CFM_ALIGNFRAMECLIENT,
+ CFM_SETFRAMEFLOAT,
+
+ CFM_LAST_MSG
+};
+
+#define CLM_PROCESS( msg, proc ) case msg: result = proc( wParam, lParam); break;
+
+BOOL CALLBACK ProcessCLUIFrameInternalMsg(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT& result )
+{
+ if ( msg <= CFM_FIRST_MGS || msg >= CFM_LAST_MSG ) return FALSE;
+
+ switch ( msg )
+ {
+ CLM_PROCESS( CFM_SETFRAMEPAINTPROC, _us_DoSetFramePaintProc );
+ CLM_PROCESS( CFM_ADDFRAME, _us_DoAddFrame );
+ CLM_PROCESS( CFM_REMOVEFRAME, _us_DoRemoveFrame );
+ CLM_PROCESS( CFM_SETFRAMEOPTIONS, _us_DoSetFrameOptions );
+ CLM_PROCESS( CFM_GETFRAMEOPTIONS, _us_DoGetFrameOptions );
+ CLM_PROCESS( CFM_UPDATEFRAME, _us_DoUpdateFrame );
+ CLM_PROCESS( CFM_SHOWHIDEFRAMETITLE, _us_DoShowHideFrameTitle );
+ CLM_PROCESS( CFM_SHOWTITLES, _us_DoShowTitles );
+ CLM_PROCESS( CFM_HIDETITLES, _us_DoHideTitles );
+ CLM_PROCESS( CFM_SHOWHIDEFRAME, _us_DoShowHideFrame );
+ CLM_PROCESS( CFM_SHOWALL, _us_DoShowAllFrames );
+ CLM_PROCESS( CFM_LOCKFRAME, _us_DoLockFrame );
+ CLM_PROCESS( CFM_COLLAPSEFRAME, _us_DoCollapseFrame );
+ CLM_PROCESS( CFM_SETFRAMEBORDER, _us_DoSetFrameBorder );
+ CLM_PROCESS( CFM_SETFRAMEALIGN, _us_DoSetFrameAlign );
+ CLM_PROCESS( CFM_MOVEFRAME, _us_DoMoveFrame );
+ CLM_PROCESS( CFM_MOVEFRAMEUP, _us_DoMoveFrameUp );
+ CLM_PROCESS( CFM_MOVEFRAMEDOWN, _us_DoMoveFrameDown );
+ CLM_PROCESS( CFM_ALIGNFRAMETOP, _us_DoAlignFrameTop );
+ CLM_PROCESS( CFM_ALIGNFRAMEBOTTOM, _us_DoAlignFrameClient );
+ CLM_PROCESS( CFM_ALIGNFRAMECLIENT, _us_DoAlignFrameBottom );
+ CLM_PROCESS( CFM_SETFRAMEFLOAT, _us_DoSetFrameFloat );
+ default:
+ return FALSE; // Not Handled
+ }
+ return TRUE;
+}
+
+
+static INT_PTR CLUIFrames_SetFramePaintProc( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SETFRAMEPAINTPROC, wParam,lParam ) : 0; }
+
+static INT_PTR CLUIFrames_AddFrame( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_ADDFRAME, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_RemoveFrame( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_REMOVEFRAME, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_SetFrameOptions( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SETFRAMEOPTIONS, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_GetFrameOptions( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_GETFRAMEOPTIONS, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_UpdateFrame( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_UPDATEFRAME, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_ShowHideFrameTitle( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SHOWHIDEFRAMETITLE, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_ShowTitles( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SHOWTITLES, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_HideTitles( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_HIDETITLES, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_ShowHideFrame( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SHOWHIDEFRAME, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_ShowAllFrames( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SHOWALL, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_LockFrame( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_LOCKFRAME, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_CollapseFrame( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_COLLAPSEFRAME, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_SetFrameBorder( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SETFRAMEBORDER, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_SetFrameAlign( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SETFRAMEALIGN, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_MoveFrame( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_MOVEFRAME, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_MoveFrameUp( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_MOVEFRAMEUP, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_MoveFrameDown( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_MOVEFRAMEDOWN, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_AlignFrameTop( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_ALIGNFRAMETOP, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_AlignFrameClient( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_ALIGNFRAMEBOTTOM, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_AlignFrameBottom( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_ALIGNFRAMECLIENT, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_SetFrameFloat( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SETFRAMEFLOAT, wParam, lParam ) : 0; }
+
+static void CreateCluiFramesServices()
+{
+ CreateServiceFunction( MS_SKINENG_REGISTERPAINTSUB, CLUIFrames_SetFramePaintProc );
+ CreateServiceFunction( MS_CLIST_FRAMES_ADDFRAME, CLUIFrames_AddFrame );
+ CreateServiceFunction( MS_CLIST_FRAMES_REMOVEFRAME, CLUIFrames_RemoveFrame );
+
+ CreateServiceFunction( MS_CLIST_FRAMES_SETFRAMEOPTIONS, CLUIFrames_SetFrameOptions );
+ CreateServiceFunction( MS_CLIST_FRAMES_GETFRAMEOPTIONS, CLUIFrames_GetFrameOptions );
+ CreateServiceFunction( MS_CLIST_FRAMES_UPDATEFRAME, CLUIFrames_UpdateFrame );
+
+ CreateServiceFunction( MS_CLIST_FRAMES_SHFRAMETITLEBAR, CLUIFrames_ShowHideFrameTitle );
+ CreateServiceFunction( MS_CLIST_FRAMES_SHOWALLFRAMESTB, CLUIFrames_ShowTitles );
+ CreateServiceFunction( MS_CLIST_FRAMES_HIDEALLFRAMESTB, CLUIFrames_HideTitles );
+ CreateServiceFunction( MS_CLIST_FRAMES_SHFRAME, CLUIFrames_ShowHideFrame );
+ CreateServiceFunction( MS_CLIST_FRAMES_SHOWALLFRAMES, CLUIFrames_ShowAllFrames );
+
+ CreateServiceFunction( MS_CLIST_FRAMES_ULFRAME, CLUIFrames_LockFrame );
+ CreateServiceFunction( MS_CLIST_FRAMES_UCOLLFRAME, CLUIFrames_CollapseFrame );
+ CreateServiceFunction( MS_CLIST_FRAMES_SETUNBORDER, CLUIFrames_SetFrameBorder );
+
+ CreateServiceFunction( CLUIFRAMESSETALIGN, CLUIFrames_SetFrameAlign );
+ CreateServiceFunction( CLUIFRAMESMOVEUPDOWN, CLUIFrames_MoveFrame );
+ CreateServiceFunction( CLUIFRAMESMOVEUP, CLUIFrames_MoveFrameUp );
+ CreateServiceFunction( CLUIFRAMESMOVEDOWN, CLUIFrames_MoveFrameDown );
+
+ CreateServiceFunction( CLUIFRAMESSETALIGNALTOP, CLUIFrames_AlignFrameTop );
+ CreateServiceFunction( CLUIFRAMESSETALIGNALCLIENT, CLUIFrames_AlignFrameClient );
+ CreateServiceFunction( CLUIFRAMESSETALIGNALBOTTOM, CLUIFrames_AlignFrameBottom );
+
+ CreateServiceFunction( CLUIFRAMESSETFLOATING, CLUIFrames_SetFrameFloat );
+} \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_statusbar.h b/plugins/Clist_modern/src/hdr/modern_statusbar.h
new file mode 100644
index 0000000000..65d0ca2e57
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_statusbar.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#ifndef modern_statusbar_h__
+#define modern_statusbar_h__
+
+#include "modern_commonprototypes.h"
+#include "../m_api/m_xpTheme.h"
+
+int ModernDrawStatusBar(HWND hwnd, HDC hDC);
+int ModernDrawStatusBarWorker(HWND hWnd, HDC hDC);
+
+typedef struct tagSTATUSBARDATA
+{
+ BOOL sameWidth;
+ RECT rectBorders;
+ BYTE extraspace;
+ BYTE Align;
+ BYTE VAlign;
+ BYTE showProtoIcon;
+ BYTE showProtoName;
+ BYTE showStatusName;
+ HFONT BarFont;
+ DWORD fontColor;
+ BYTE connectingIcon;
+ BYTE TextEffectID;
+ DWORD TextEffectColor1;
+ DWORD TextEffectColor2;
+ BYTE xStatusMode; // 0-only main, 1-xStatus, 2-main as overlay
+ BYTE nProtosPerLine;
+ BYTE showProtoEmails;
+
+ HBITMAP hBmpBackground;
+ COLORREF bkColour;
+ DWORD backgroundBmpUse;
+ BOOL bkUseWinColors;
+
+ XPTHANDLE hTheme;
+
+ BOOL perProtoConfig;
+ BYTE SBarRightClk;
+
+} STATUSBARDATA;
+
+#endif // modern_statusbar_h__
diff --git a/plugins/Clist_modern/src/hdr/modern_statusmodes.h b/plugins/Clist_modern/src/hdr/modern_statusmodes.h
new file mode 100644
index 0000000000..f69f97abd9
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_statusmodes.h
@@ -0,0 +1,43 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+*/
+//add 1 to ID_STATUS_CONNECTING to mark retries (v0.1.0.1+)
+//eg ID_STATUS_CONNECTING+2 is the third connection attempt, or the second retry
+
+#pragma once
+
+#define ID_STATUS_CONNECTING 1
+//max retries is just a marker so that the clist knows what numbers represent
+//retries. It does not set any kind of limit on the number of retries you can
+//and/or should do.
+#define MAX_CONNECT_RETRIES 10000
+#define ID_STATUS_OFFLINE 40071
+#define ID_STATUS_ONLINE 40072
+#define ID_STATUS_AWAY 40073
+#define ID_STATUS_DND 40074
+#define ID_STATUS_NA 40075
+#define ID_STATUS_OCCUPIED 40076
+#define ID_STATUS_FREECHAT 40077
+#define ID_STATUS_INVISIBLE 40078
+#define ID_STATUS_ONTHEPHONE 40079
+#define ID_STATUS_OUTTOLUNCH 40080
+#define ID_STATUS_IDLE 40081 /* do not use as a m_cache_nStatus */
diff --git a/plugins/Clist_modern/src/hdr/modern_sync.h b/plugins/Clist_modern/src/hdr/modern_sync.h
new file mode 100644
index 0000000000..334d4696a7
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_sync.h
@@ -0,0 +1,98 @@
+#ifndef modern_sync_h__
+#define modern_sync_h__
+
+#include "hdr/modern_commonheaders.h"
+
+
+typedef INT_PTR (*PSYNCCALLBACKPROC)(WPARAM,LPARAM);
+
+int SyncCall(void * vproc, int count, ... );
+int SyncCallProxy( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam, CRITICAL_SECTION * cs = NULL );
+HRESULT SyncCallWinProcProxy( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam, int& nReturn );
+HRESULT SyncCallAPCProxy( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam, int& hReturn );
+
+LRESULT SyncOnWndProcCall( WPARAM wParam );
+
+// Experimental sync caller
+
+int DoCall( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam );
+
+// Have to be here due to MS Visual C++ does not support 'export' keyword
+
+// 3 params
+
+template<class RET, class A, class B, class C> class PARAMS3
+{
+ typedef RET(*proc_t)(A, B, C);
+ proc_t _proc; A _a; B _b; C _c; RET _ret;
+
+public:
+ PARAMS3( proc_t __proc, A __a, B __b, C __c ): _proc( __proc), _a (__a), _b(__b), _c(__c){};
+ static int DoSyncCall( WPARAM wParam, LPARAM lParam )
+ {
+ PARAMS3 * params = (PARAMS3 *) lParam;
+ params->_ret = params->_proc( params->_a, params->_b, params->_c );
+ return 0;
+ };
+ RET GetResult() { return _ret; }
+};
+
+template< class RET, class Ap, class Bp, class Cp, class A, class B, class C> RET Sync( RET(*proc)(Ap, Bp, Cp), A a, B b, C c )
+{
+ PARAMS3<RET, Ap, Bp, Cp> params( proc, a, b, c );
+ DoCall((PSYNCCALLBACKPROC) PARAMS3<RET, Ap, Bp, Cp>::DoSyncCall, 0, (LPARAM) &params );
+ return params.GetResult();
+};
+
+
+// 2 params
+
+template<class RET, class A, class B> class PARAMS2
+{
+ typedef RET(*proc_t)(A, B);
+ proc_t _proc; A _a; B _b; RET _ret;
+
+public:
+ PARAMS2( proc_t __proc, A __a, B __b ): _proc( __proc), _a (__a), _b(__b){};
+ static int DoSyncCall( WPARAM wParam, LPARAM lParam )
+ {
+ PARAMS2 * params = (PARAMS2 *) lParam;
+ params->_ret = params->_proc( params->_a, params->_b );
+ return 0;
+ };
+ RET GetResult() { return _ret; }
+};
+
+template< class RET, class Ap, class Bp, class A, class B> RET Sync( RET(*proc)(Ap, Bp), A a, B b )
+{
+ PARAMS2<RET, Ap, Bp> params( proc, a, b );
+ DoCall((PSYNCCALLBACKPROC) PARAMS2<RET, Ap, Bp>::DoSyncCall, 0, (LPARAM) &params );
+ return params.GetResult();
+};
+
+
+// 1 param
+template<class RET, class A> class PARAMS1
+{
+ typedef RET(*proc_t)(A);
+ proc_t _proc; A _a; RET _ret;
+
+public:
+ PARAMS1( proc_t __proc, A __a): _proc( __proc), _a (__a){};
+ static int DoSyncCall( WPARAM, LPARAM lParam )
+ {
+ PARAMS1 * params = (PARAMS1 *) lParam;
+ params->_ret = params->_proc( params->_a );
+ return 0;
+ };
+ RET GetResult() { return _ret; }
+};
+
+template< class RET, class Ap, class A> RET Sync( RET(*proc)(Ap), A a )
+{
+ PARAMS1<RET, Ap> params( proc, a );
+ DoCall((PSYNCCALLBACKPROC) PARAMS1<RET, Ap>::DoSyncCall, 0, (LPARAM) &params );
+ return params.GetResult();
+};
+
+#endif // modern_sync_h__ \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_tstring.h b/plugins/Clist_modern/src/hdr/modern_tstring.h
new file mode 100644
index 0000000000..17fc9cf50c
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_tstring.h
@@ -0,0 +1,58 @@
+#ifndef UNICODE //FIXME Build without UNICODE flag
+#define _AtlGetConversionACP() CP_THREAD_ACP
+#endif
+
+#include "MString.h"
+
+#ifdef UNICODE
+typedef CMStringA astring;
+typedef CMStringW wstring;
+
+class mbstring : public astring
+{
+ // It is prohibited to initialize by char* outside, use L"xxx"
+private:
+ mbstring( const char * pChar ) : astring( pChar ) {};
+ mbstring& operator=( const char * pChar ) { this->operator =( pChar ); return *this; }
+
+public:
+ mbstring() : astring() {};
+ mbstring( const mbstring& uStr ) : astring( uStr ) {};
+
+
+ mbstring( const wstring& tStr ) { *this = tStr.c_str(); }
+ mbstring& operator=( const wstring& tStr ) { this->operator =( tStr.c_str()); return *this; }
+
+ mbstring( const wchar_t * wChar );
+ mbstring& operator=( const astring& aStr );
+ mbstring& operator=( const wchar_t * wChar );
+ operator wstring();
+ operator astring();
+};
+
+
+class tstring : public wstring
+{
+public:
+ tstring() : wstring() {};
+ tstring(const wchar_t * pwChar) : wstring( pwChar ) {};
+
+
+ tstring(const astring& aStr) { *this = aStr.c_str(); }
+ tstring(const mbstring& utfStr) { *this = utfStr; }
+
+ tstring(const char * pChar);
+ tstring& operator=( const char * pChar );
+ tstring& operator=( const astring& aStr );
+ tstring& operator=( const mbstring& uStr );
+ operator astring();
+ operator mbstring() { return mbstring( this->c_str()); }
+};
+
+#else
+typedef CMStringA astring;
+typedef CMStringA wstring;
+typedef CMStringA tstring;
+typedef CMStringA mbstring;
+
+#endif
diff --git a/plugins/Clist_modern/src/init.cpp b/plugins/Clist_modern/src/init.cpp
new file mode 100644
index 0000000000..3faaa7e1dd
--- /dev/null
+++ b/plugins/Clist_modern/src/init.cpp
@@ -0,0 +1,244 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+//include
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_commonprototypes.h"
+#include "version.h"
+
+#include "hdr/modern_clui.h"
+#include "hdr/modern_clcpaint.h"
+
+//definitions
+
+#define CHECKRES(sub) if (sub != S_OK) return S_FALSE;
+
+HINSTANCE g_hInst = 0;
+CLIST_INTERFACE *pcli = NULL;
+CLIST_INTERFACE corecli = {0};
+CLUIDATA g_CluiData = {0};
+int hLangpack;
+
+TIME_API tmi;
+
+pfnTryEnterCriticalSection fnTryEnterCriticalSection;
+
+pfnGetAncestor fnGetAncestor;
+pfnGetMenuBarInfo fnGetMenuBarInfo;
+pfnGetScrollBarInfo fnGetScrollBarInfo;
+pfnMsgWaitForMultipleObjectsEx fnMsgWaitForMultipleObjectsEx;
+
+static HRESULT SubclassClistInterface();
+static HRESULT CreateHookableEvents();
+int EventArea_UnloadModule();
+
+__forceinline int MakeVer(int a, int b, int c, int d)
+{ return PLUGIN_MAKE_VERSION(a,b,c,d);
+}
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ "Modern Contact List",
+ MakeVer(PRODUCT_VERSION),
+ "Display contacts, event notifications, protocol status with advantage visual modifications. Supported MW modifications, enchanced metacontact cooperation.",
+ "Artem Shpynov, Ricardo Pescuma Domenecci and Anton Senko based on clist_mw by Bethoven",
+ "ashpynov@gmail.com" ,
+ "Copyright 2000-2010 Miranda-IM project",
+ "http://miranda-im.org/development",
+ UNICODE_AWARE,
+ //{043909B6-AAD8-4d82-8EB5-9F64CFE867CD}
+ {0x43909b6, 0xaad8, 0x4d82, { 0x8e, 0xb5, 0x9f, 0x64, 0xcf, 0xe8, 0x67, 0xcd }}
+};
+static const MUUID interfaces[] = {MIID_CLIST, MIID_LAST};
+
+PLUGININTERFACE const MUUID * MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID reserved)
+{
+ g_hInst = hInstDLL;
+ DisableThreadLibraryCalls(g_hInst);
+ return TRUE;
+}
+
+PLUGININTERFACE PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+PLUGININTERFACE int CListInitialise()
+{
+ HMODULE hKernel = GetModuleHandleA( "kernel32.dll" );
+ fnTryEnterCriticalSection = ( pfnTryEnterCriticalSection )GetProcAddress( hKernel, "TryEnterCriticalSection" );
+
+ HMODULE hUser = GetModuleHandleA( "user32.dll" );
+ fnGetMenuBarInfo = ( pfnGetMenuBarInfo )GetProcAddress( hUser, "GetMenuBarInfo" );
+ fnGetScrollBarInfo = ( pfnGetScrollBarInfo )GetProcAddress( hUser, "GetScrollBarInfo" );
+ fnMsgWaitForMultipleObjectsEx = ( pfnMsgWaitForMultipleObjectsEx )GetProcAddress( hUser, "MsgWaitForMultipleObjectsEx" );
+
+ if (( fnGetAncestor = ( pfnGetAncestor )GetProcAddress( hUser, "GetAncestor" )) == NULL )
+ fnGetAncestor = MyGetAncestor;
+
+ g_dwMainThreadID = GetCurrentThreadId();
+ mir_getTMI(&tmi);
+ mir_getLP( &pluginInfo );
+
+ CHECKRES ( PreLoadContactListModule ( ) );
+ CHECKRES ( SubclassClistInterface ( ) );
+ CHECKRES ( CreateHookableEvents ( ) );
+ CHECKRES ( XPThemesLoadModule ( ) );
+ CHECKRES ( SkinEngineLoadModule ( ) );
+ CHECKRES ( BackgroundsLoadModule ( ) );
+ CHECKRES ( CluiLoadModule ( ) );
+ CHECKRES ( ClcLoadModule ( ) );
+ CHECKRES ( ToolbarButtonLoadModule( ) );
+ CHECKRES ( ToolbarLoadModule() );
+
+ TRACE( "CListInitialise Modern Contact List ... Done\r\n" );
+
+ return S_OK;
+}
+
+// never called by a newer plugin loader.
+PLUGININTERFACE int Load(void)
+{
+ MessageBoxA(0,"You Running Old Miranda, use " MINIMAL_COREVERSION_STR " version!","Modern Clist",0);
+ return 1;
+}
+
+PLUGININTERFACE int Unload(void)
+{
+ TRACE("Unloading Clist Modern\r\n");
+
+ if (IsWindow(pcli->hwndContactList)) DestroyWindow(pcli->hwndContactList);
+ pcli->hwndContactList = NULL;
+
+ BackgroundsUnloadModule();
+ SkinEngineUnloadModule();
+ XPThemesUnloadModule();
+
+ UnloadAvatarOverlayIcon();
+ UninitSkinHotKeys();
+ FreeRowCell();
+ EventArea_UnloadModule();
+
+ TRACE("Unloading Clist Modern COMPLETE\r\n");
+ return 0;
+}
+
+
+static HRESULT SubclassClistInterface()
+{
+ // get the contact list interface
+ pcli = ( CLIST_INTERFACE* )CallService(MS_CLIST_RETRIEVE_INTERFACE, 0, (LPARAM)g_hInst);
+ if ((INT_PTR)pcli == CALLSERVICE_NOTFOUND || pcli->version < 6 )
+ {
+ MessageBoxA( NULL, "This version of plugin requires Miranda IM " MINIMAL_COREVERSION_STR " or later", "Fatal error", MB_OK );
+ return TRUE;
+ }
+ // OVERLOAD CLIST INTERFACE FUNCTIONS
+ //
+ // Naming convention is:
+ // 'cli*' - new handler without default core service calling
+ // 'save*' - pointer to stored default parent handle
+ // 'cli_*' - new handler with default core service calling
+
+ corecli = *pcli;
+
+ pcli->bDisplayLocked = TRUE;
+
+ pcli->pfnCheckCacheItem = (void (*)(ClcCacheEntryBase*)) cliCheckCacheItem;
+ pcli->pfnFreeCacheItem = (void(*)(ClcCacheEntryBase*)) cliFreeCacheItem;
+ pcli->pfnInvalidateDisplayNameCacheEntry = cliInvalidateDisplayNameCacheEntry;
+
+ pcli->pfnTrayIconUpdateBase = cliTrayIconUpdateBase;
+ pcli->pfnCluiProtocolStatusChanged = cliCluiProtocolStatusChanged;
+
+ pcli->pfnBeginRenameSelection = cliBeginRenameSelection;
+ pcli->pfnCreateClcContact = cliCreateClcContact;
+ pcli->pfnCreateCacheItem = cliCreateCacheItem;
+ pcli->pfnGetRowBottomY = cliGetRowBottomY;
+ pcli->pfnGetRowHeight = cliGetRowHeight;
+ pcli->pfnGetRowTopY = cliGetRowTopY;
+ pcli->pfnGetRowTotalHeight = cliGetRowTotalHeight;
+ pcli->pfnInvalidateRect = CLUI__cliInvalidateRect;
+ pcli->pfnGetCacheEntry = cliGetCacheEntry;
+ pcli->pfnOnCreateClc = CLUI::cliOnCreateClc;
+ pcli->pfnPaintClc = CLCPaint::cliPaintClc;
+ pcli->pfnRebuildEntireList = cliRebuildEntireList;
+ pcli->pfnRecalcScrollBar = cliRecalcScrollBar;
+ pcli->pfnRowHitTest = cliRowHitTest;
+ pcli->pfnScrollTo = cliScrollTo;
+ pcli->pfnShowHide = cliShowHide;
+ pcli->pfnHitTest = cliHitTest;
+ pcli->pfnCompareContacts = cliCompareContacts;
+ pcli->pfnBuildGroupPopupMenu = cliBuildGroupPopupMenu;
+ pcli->pfnGetIconFromStatusMode = cliGetIconFromStatusMode;
+ pcli->pfnFindItem = cliFindItem;
+ pcli->pfnGetRowByIndex = cliGetRowByIndex;
+ pcli->pfnGetRowsPriorTo = cliGetRowsPriorTo;
+ pcli->pfnGetGroupContentsCount = cliGetGroupContentsCount;
+ pcli->pfnCreateEvent = cliCreateEvent;
+ pcli->pfnFindRowByText = cliFindRowByText;
+
+ //partialy overloaded - call default handlers from inside
+ pcli->pfnIconFromStatusMode = cli_IconFromStatusMode;
+ pcli->pfnLoadCluiGlobalOpts = CLUI_cli_LoadCluiGlobalOpts;
+ pcli->pfnSortCLC = cli_SortCLC;
+ pcli->pfnAddGroup = cli_AddGroup;
+ pcli->pfnGetGroupCountsText = cli_GetGroupCountsText;
+ pcli->pfnAddContactToTree = cli_AddContactToTree;
+ pcli->pfnAddInfoItemToGroup = cli_AddInfoItemToGroup;
+ pcli->pfnAddItemToGroup = cli_AddItemToGroup;
+ pcli->pfnContactListWndProc = CLUI::cli_ContactListWndProc;
+ pcli->pfnDeleteItemFromTree = cli_DeleteItemFromTree;
+ pcli->pfnFreeContact = cli_FreeContact;
+ pcli->pfnFreeGroup = cli_FreeGroup;
+ pcli->pfnChangeContactIcon = cli_ChangeContactIcon;
+ pcli->pfnTrayIconProcessMessage = cli_TrayIconProcessMessage;
+ pcli->pfnSaveStateAndRebuildList = cli_SaveStateAndRebuildList;
+ pcli->pfnContactListControlWndProc = cli_ContactListControlWndProc;
+ pcli->pfnProcessExternalMessages = cli_ProcessExternalMessages;
+ pcli->pfnAddEvent = cli_AddEvent;
+ pcli->pfnRemoveEvent = cli_RemoveEvent;
+ pcli->pfnDocking_ProcessWindowMessage = Docking_ProcessWindowMessage;
+ return S_OK;
+}
+
+static HRESULT CreateHookableEvents()
+{
+ g_CluiData.hEventExtraImageListRebuilding = CreateHookableEvent(ME_CLIST_EXTRA_LIST_REBUILD);
+ g_CluiData.hEventExtraImageApplying = CreateHookableEvent(ME_CLIST_EXTRA_IMAGE_APPLY);
+ g_CluiData.hEventExtraClick = CreateHookableEvent(ME_CLIST_EXTRA_CLICK);
+ g_CluiData.hEventBkgrChanged = CreateHookableEvent(ME_BACKGROUNDCONFIG_CHANGED);
+ g_CluiData.hEventPreBuildTrayMenu = CreateHookableEvent(ME_CLIST_PREBUILDTRAYMENU);
+ g_CluiData.hEventPreBuildFrameMenu = CreateHookableEvent(ME_CLIST_PREBUILDFRAMEMENU);
+ g_CluiData.hEventPreBuildGroupMenu = CreateHookableEvent(ME_CLIST_PREBUILDGROUPMENU);
+ g_CluiData.hEventPreBuildSubGroupMenu = CreateHookableEvent(ME_CLIST_PREBUILDSUBGROUPMENU);
+ g_CluiData.hEventStatusBarShowToolTip = CreateHookableEvent(ME_CLIST_FRAMES_SB_SHOW_TOOLTIP);
+ g_CluiData.hEventStatusBarHideToolTip = CreateHookableEvent(ME_CLIST_FRAMES_SB_HIDE_TOOLTIP);
+ g_CluiData.hEventSkinServicesCreated = CreateHookableEvent(ME_SKIN_SERVICESCREATED);
+ return S_OK;
+}
diff --git a/plugins/Clist_modern/src/m_api/m_skin_eng.h b/plugins/Clist_modern/src/m_api/m_skin_eng.h
new file mode 100644
index 0000000000..78de34e2bb
--- /dev/null
+++ b/plugins/Clist_modern/src/m_api/m_skin_eng.h
@@ -0,0 +1,434 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 M_ske_H_INC
+#define M_ske_H_INC
+
+#include "newpluginapi.h"
+#include "m_clui.h"
+#include "../hdr/modern_commonheaders.h"
+
+
+/*defaults*/
+#define DEFAULT_FIT_MODE FM_STRETCH
+#define DEFAULT_STYLE ST_BRUSH
+#define DEFAULT_BKCOLOUR GetSysColor(COLOR_3DFACE)
+#define DEFAULT_SELBKCOLOUR GetSysColor(COLOR_HIGHLIGHT)
+#define SIZING_MARGIN 3
+
+/* Fit mode */
+#define FM_STRETCH 0
+#define FM_TILE_HORZ 1
+#define FM_TILE_VERT 2
+#define FM_TILE_BOTH 3
+
+/*Object types*/
+#define OT_ANY 0
+#define OT_GLYPHOBJECT 1
+#define OT_FONTOBJECT 2
+
+/*STYLE INDEXEX*/
+#define ST_SKIP 0
+#define ST_PARENT 1
+#define ST_BRUSH 2
+#define ST_IMAGE 3
+#define ST_SOLARIZE 4 //Not used yet.
+#define ST_FRAGMENT 5
+#define ST_GRADIENT 6
+
+//formats:
+#define ADT_TOP 0x00000000
+#define ADT_LEFT 0x00000000
+#define ADT_HCENTER 0x00000001
+#define ADT_RIGHT 0x00000002
+#define ADT_VCENTER 0x00000004
+#define ADT_BOTTOM 0x00000008
+//#define ADT_ECLIPSE 64
+
+
+/*SERVICES*/
+
+//toggle the 'hide offline contacts' flag and call CLUI
+//wParam=0
+//lParam=0
+#define MS_CLIST_TOGGLEHIDEOFFLINE "CList/ToggleHideOffline"
+
+#define MS_CLIST_TOGGLEGROUPS "CList/ToggleGroups"
+
+#define MS_CLIST_TOGGLESOUNDS "CList/ToggleSounds"
+
+// Add new object to skin object list.
+// wParam = pointer to SKINOBJECTDESCRIPTOR structure
+// lParam = 0 ( used for internal purposes: pointer to skin object list)
+#define MS_SKIN_REGISTEROBJECT "ModernList/RegisterObject"
+
+// Add new object to skin object list.
+// wParam = pointer to DEF_SKIN_OBJECT_PARAMS structure
+// lParam = 0 ( used for internal purposes: pointer to skin object list)
+#define MS_SKIN_REGISTERDEFOBJECT "ModernList/RegisterDefObject"
+
+typedef struct s_DEF_SKIN_OBJECT_PARAMS
+{
+ char * szObjectID;
+ BYTE defStyle;
+ DWORD defColor;
+ // SKINOBJECTSLIST * Skin;
+} DEF_SKIN_OBJECT_PARAMS;
+
+
+// Request painting glyph object
+// wParam = pointer to SKINDRAWREQUEST structure
+// lParam = 0
+#define MS_SKIN_DRAWGLYPH "ModernList/DrawGlyph"
+
+
+
+/* EVENTS */
+#define ME_SKIN_SERVICESCREATED "ModernList/ServicesCreated"
+
+/* DRAWGLYPH Request structure */
+typedef struct s_SKINDRAWREQUEST
+{
+ char szObjectID[255]; // Unic Object ID (path) to paint
+ RECT rcDestRect; // Rectangle to fit
+ RECT rcClipRect; // Rectangle to paint in.
+ HDC hDC; // Handler to device context to paint in.
+} SKINDRAWREQUEST,*LPSKINDRAWREQUEST;
+
+/* SKINOBJECTDESCRIPTOR opbject descriptor structure */
+typedef struct tagSKINOBJECTDESCRIPTOR
+{
+ BYTE bType; // One of OT_* values.
+ char* szObjectID; // Unic Object ID (path) [255] max
+ LPVOID Data; // Pointer to GLYPHOBJECT strycture if bType==OT_GLYPHOBJECT
+} SKINOBJECTDESCRIPTOR, *LPSKINOBJECTDESCRIPTOR;
+
+/* SKINOBJECTDESCRIPTOR opbject descriptor structure */
+typedef struct s_GLYPHOBJECT
+{
+ BYTE Style; // One of ST_* values
+ HBITMAP hGlyph; // Bitmap handler (for internal use only)
+ DWORD dwTop, dwLeft, dwBottom, dwRight; // Margins
+ char* szFileName; // FileName of image
+ DWORD dwColor; // Fill color
+ BYTE dwAlpha; // Constant alpha-transparency level
+ BYTE FitMode; // One of FM_* values
+ POINT clipArea; // Object image rect on full image
+ SIZE szclipArea; // Object image rect on full image
+ SortedList * plTextList; // List of GLYPHTEXT
+ LONG bmWidth;
+ LONG bmHeight;
+ BYTE bmBitsPixel;
+} GLYPHOBJECT,*LPGLYPHOBJECT;
+
+/* SKINTEXTDESCRIPTOR opbject descriptor structure */
+typedef struct s_GLYPHTEXT
+{
+ char * szGlyphTextID;
+ TCHAR * stText;
+ TCHAR * stValueText;
+ DWORD dwFlags;
+ DWORD dwColor; // Color (InvAA)(RR)(GG)(BB)
+ DWORD dwShadow; //ToDo: Color2/Shaddow
+ int iLeft,iTop,iRight,iBottom;
+ BYTE RelativeFlags;
+ char * szFontID;
+ HFONT hFont;
+ char * szObjectName;
+}GLYPHTEXT,*LPGLYPHTEXT;
+
+/* SKINTEXTDESCRIPTOR opbject descriptor structure */
+typedef struct s_SKINFONT
+{
+ char * szFontID;
+ HFONT hFont;
+}SKINFONT, *LPSKINFONT;
+
+/* HELPER FUNCTIONS */
+
+//Paint ObjectID as parent background for frame hwndIn
+int __inline SkinDrawWindowBack(HWND hwndIn, HDC hdc, RECT * rcClip, char * objectID);
+//Paint ObjectID
+int __inline SkinDrawGlyph(HDC hdc, RECT * rcSize, RECT * rcClip, char * objectID);
+//Register object with predefined style
+int __inline CreateGlyphedObjectDefStyle(char * ObjID,BYTE defStyle);
+int __inline CreateGlyphedObjectDefColor(char * ObjID,DWORD defColor);
+//Register default object
+int __inline CreateGlyphedObject(char * ObjID);
+
+
+
+//// Creating and registering objects
+//int __inline CreateGlyphedObject(char * ObjID)
+//{
+// DEF_SKIN_OBJECT_PARAMS prm={0};
+// prm.defColor=DEFAULT_BKCOLOUR;
+// prm.defStyle=DEFAULT_STYLE;
+// prm.szObjectID=ObjID;
+// return CallService(MS_SKIN_REGISTERDEFOBJECT,(WPARAM)&prm,0);
+//}
+static BOOL __inline ScreenToClientRect(HWND hWnd, LPRECT lpRect)
+{
+ BOOL ret;
+
+ POINT pt;
+
+ pt.x = lpRect->left;
+ pt.y = lpRect->top;
+
+ ret = ScreenToClient(hWnd, &pt);
+
+ if (!ret) return ret;
+
+ lpRect->left = pt.x;
+ lpRect->top = pt.y;
+
+
+ pt.x = lpRect->right;
+ pt.y = lpRect->bottom;
+
+ ret = ScreenToClient(hWnd, &pt);
+
+ lpRect->right = pt.x;
+ lpRect->bottom = pt.y;
+
+ return ret;
+}
+
+//int __inline CreateGlyphedObjectDefStyle(char * ObjID,BYTE defStyle)
+//{
+// DEF_SKIN_OBJECT_PARAMS prm={0};
+// prm.defColor=DEFAULT_BKCOLOUR;
+// prm.defStyle=defStyle;
+// prm.szObjectID=ObjID;
+// return CallService(MS_SKIN_REGISTERDEFOBJECT,(WPARAM)&prm,0);
+//}
+//int __inline CreateGlyphedObjectDefColor(char * ObjID,DWORD defColor)
+//{
+// DEF_SKIN_OBJECT_PARAMS prm={0};
+// prm.defColor=defColor;
+// prm.defStyle=ST_BRUSH;
+// prm.szObjectID=ObjID;
+// return CallService(MS_SKIN_REGISTERDEFOBJECT,(WPARAM)&prm,0);
+//}
+INT_PTR ske_Service_DrawGlyph(WPARAM wParam,LPARAM lParam);
+int __inline SkinDrawGlyph(HDC hdc, RECT * rcSize, RECT * rcClip, char * objectID)
+{
+ SKINDRAWREQUEST rq;
+ if (!objectID) return 0;
+ rq.hDC=hdc;
+ rq.rcDestRect=*rcSize;
+ rq.rcClipRect=*rcClip;
+ strncpy(rq.szObjectID,objectID,SIZEOF(rq.szObjectID));
+ return ske_Service_DrawGlyph((WPARAM)&rq,0);
+ //return CallService(MS_SKIN_DRAWGLYPH,(WPARAM)&rq,0);
+}
+//#include "../hdr/modern_skin_selector.h"
+
+//////////////////////////////////////////////
+// //
+// New Painting sequence servises //
+// //
+//////////////////////////////////////////////
+
+typedef struct sPAINT_REQUEST
+{
+ DWORD dStructSize; //size of structure
+ HWND hWnd; //called by window
+ HDC hDC; //context to draw on
+ RECT rcUpdate; //rectangle to be painted in (relative to Top-Left corner of Main window)
+ DWORD dwFlags; //drawing flags
+ void * CallbackData; //Data for passing to callback procedure
+ char Reserved[16]; //reserved for farther usage;
+} sPaintRequest;
+
+// Request to register sub for callback painting frame area
+// wParam = hWnd of called frame
+// lParam = pointer to tPaintCallBackProc (or NULL to remove)
+// return 1 - succes, 0 - failure
+#define MS_SKINENG_REGISTERPAINTSUB "SkinEngine/ske_Service_RegisterFramePaintCallbackProcedure"
+
+// Request to repaint frame or change/drop callback data immeadeately
+// wParam = hWnd of called frame
+// lParam = pointer to sPaintRequest (or NULL to redraw all)
+#define MS_SKINENG_UPTATEFRAMEIMAGE "SkinEngine/ske_Service_UpdateFrameImage"
+
+// Request to repaint frame or change/drop callback data
+// wParam = hWnd of called frame
+// lParam = pointer to sPaintRequest (or NULL to redraw all)
+// return 2 - already queued, data updated, 1-have been queued, 0 - failure
+#define MS_SKINENG_INVALIDATEFRAMEIMAGE "SkinEngine/ske_Service_InvalidateFrameImage"
+
+// Callback proc type
+typedef int (/*__stdcall*/ *tPaintCallbackProc)(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgnUpdate, DWORD dFlags, void * CallBackData);
+//tPaintCallbackProc PaintCallbackProc;
+
+// HELPER TO UPDATEIMAGEFRAME
+
+int __inline SkinEngUpdateImageFrame(HWND hwnd, RECT * rcUpdate, DWORD dwFlags, void * CallBackData)
+{
+ sPaintRequest sr={0};
+ sr.dStructSize=sizeof(sPaintRequest);
+ sr.hWnd=hwnd;
+ if (rcUpdate)
+ sr.rcUpdate=*rcUpdate;
+ sr.dwFlags=dwFlags;
+ sr.CallbackData=CallBackData;
+ return CallService(MS_SKINENG_UPTATEFRAMEIMAGE,(WPARAM)hwnd,(LPARAM)&sr);
+}
+
+int __inline SkinEngInvalidateImageFrame(HWND hwnd, CONST RECT * rcUpdate, DWORD dwFlags, void * CallBackData)
+{
+ sPaintRequest sr={0};
+ if (hwnd && (!g_CluiData.fLayered)) return InvalidateRect(hwnd,rcUpdate,dwFlags);
+ sr.dStructSize=sizeof(sPaintRequest);
+ sr.hWnd=hwnd;
+ if (rcUpdate)
+ sr.rcUpdate=*rcUpdate;
+ sr.dwFlags=dwFlags;
+ sr.CallbackData=CallBackData;
+ return CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,(WPARAM)hwnd,(LPARAM)&sr);
+}
+
+
+int __inline SkinInvalidateFrame(HWND hWnd, CONST RECT* lpRect)
+{
+ return SkinEngInvalidateImageFrame(hWnd,lpRect,0,0);
+}
+// Alpha channel GDI replacements/helpers
+
+//
+// Paints text with correct alpha channel
+// wParam - pointer to AlphaTextOutParams
+#define MS_SKINENG_ALPHATEXTOUT "SkinEngine/ske_AlphaTextOut"
+typedef struct _AlphaTextOutParams
+{
+ HDC hDC;
+ LPCTSTR lpString;
+ int nCount;
+ RECT * lpRect;
+ UINT format;
+ DWORD ARGBcolor;
+ char reserv[16];
+}AlphaTextOutParams;
+
+int __inline AlphaText(HDC hDC, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format, DWORD ARGBcolor)
+{
+ AlphaTextOutParams ap={0};
+ ap.hDC=hDC;
+ ap.lpString=lpString;
+ ap.nCount=nCount;
+ ap.lpRect=lpRect;
+ ap.format=format;
+ ap.ARGBcolor=ARGBcolor;
+ return CallService(MS_SKINENG_ALPHATEXTOUT,(WPARAM)&ap,0);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Paints text with correct alpha channel and effect, alternative to DrawText
+// wParam - pointer to DrawTextWithEffectParam
+
+typedef struct MODERNFONTEFFECT_tag
+{
+ BYTE effectIndex;
+ DWORD baseColour; // ARGB
+ DWORD secondaryColour; // ARGB
+}
+MODERNFONTEFFECT;
+
+typedef struct DrawTextWithEffectParam_tag
+{
+ int cbSize;
+ HDC hdc; // handle to DC
+ LPCTSTR lpchText; // text to draw
+ int cchText; // length of text to draw
+ LPRECT lprc; // rectangle coordinates
+ UINT dwDTFormat; // formatting options
+ MODERNFONTEFFECT * pEffect; // effect to be drawn on
+} DrawTextWithEffectParam;
+
+#define MS_DRAW_TEXT_WITH_EFFECTA "Modern/SkinEngine/DrawTextWithEffectA"
+#define MS_DRAW_TEXT_WITH_EFFECTW "Modern/SkinEngine/DrawTextWithEffectW"
+
+#ifdef UNICODE
+ #define MS_DRAW_TEXT_WITH_EFFECT MS_DRAW_TEXT_WITH_EFFECTW
+#else
+ #define MS_DRAW_TEXT_WITH_EFFECT MS_DRAW_TEXT_WITH_EFFECTA
+#endif
+
+// Helper
+int __inline DrawTextWithEffect( HDC hdc, LPCTSTR lpchText, int cchText, RECT * lprc, UINT dwDTFormat, MODERNFONTEFFECT * pEffect )
+{
+ DrawTextWithEffectParam params;
+ static BYTE bIfServiceExists = ServiceExists( MS_DRAW_TEXT_WITH_EFFECT ) ? 1 : 0;
+ if ( bIfServiceExists == 0 ) return DrawText ( hdc, lpchText, cchText, lprc, dwDTFormat );
+
+ // else
+ params.cbSize = sizeof( DrawTextWithEffectParam );
+ params.hdc = hdc;
+ params.lpchText = lpchText;
+ params.cchText = cchText;
+ params.lprc = lprc;
+ params.dwDTFormat = dwDTFormat;
+ params.pEffect = pEffect;
+ return CallService( MS_DRAW_TEXT_WITH_EFFECT, (WPARAM)&params, 0 );
+}
+
+
+typedef struct _ImageListFixParam
+{
+ HIMAGELIST himl;
+ int index;
+ HICON hicon;
+}ImageListFixParam;
+
+typedef struct _DrawIconFixParam
+{
+ HDC hdc;
+ int xLeft;
+ int yTop;
+ HICON hIcon;
+ int cxWidth;
+ int cyWidth;
+ UINT istepIfAniCur;
+ HBRUSH hbrFlickerFreeDraw;
+ UINT diFlags;
+} DrawIconFixParam;
+//wParam - pointer to DrawIconFixParam
+#define MS_SKINENG_DRAWICONEXFIX "SkinEngine/DrawIconEx_Fix"
+
+int __inline mod_DrawIconEx_helper(HDC hdc,int xLeft,int yTop,HICON hIcon,int cxWidth,int cyWidth, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags)
+{
+ DrawIconFixParam p={0};
+ p.hdc=hdc;
+ p.xLeft=xLeft;
+ p.yTop=yTop;
+ p.hIcon=hIcon;
+ p.cxWidth=cxWidth;
+ p.cyWidth=cyWidth;
+ p.istepIfAniCur=istepIfAniCur;
+ p.hbrFlickerFreeDraw=hbrFlickerFreeDraw;
+ p.diFlags=diFlags;
+ return CallService(MS_SKINENG_DRAWICONEXFIX,(WPARAM)&p,0);
+}
+#endif
diff --git a/plugins/Clist_modern/src/m_api/m_skinbutton.h b/plugins/Clist_modern/src/m_api/m_skinbutton.h
new file mode 100644
index 0000000000..43a3167ce3
--- /dev/null
+++ b/plugins/Clist_modern/src/m_api/m_skinbutton.h
@@ -0,0 +1,31 @@
+#include "m_button.h"
+
+#define MBM_UPDATETRANSPARENTFLAG WM_USER+52
+#define MBM_SETICOLIBHANDLE WM_USER+53
+#define MBM_REFRESHICOLIBICON WM_USER+54
+
+#define BUTTONSETID WM_USER+55
+#define BUTTONDRAWINPARENT WM_USER+56
+#define BUTTONSETMARGINS WM_USER+57
+#define BUTTONSETSENDONDOWN WM_USER+58
+
+
+#define SBF_ALIGN_TL_RIGHT 1
+#define SBF_ALIGN_TL_HCENTER 2
+#define SBF_ALIGN_TL_BOTTOM 4
+#define SBF_ALIGN_TL_VCENTER 8
+
+#define SBF_ALIGN_BR_RIGHT 16
+#define SBF_ALIGN_BR_HCENTER 32
+#define SBF_ALIGN_BR_BOTTOM 64
+#define SBF_ALIGN_BR_VCENTER 128
+
+#define SBF_CALL_ON_PRESS 256
+
+// Params for draw flag at Repos function
+#define SBRF_DO_NOT_DRAW 0
+#define SBRF_DO_REDRAW_ALL 1
+#define SBRF_DO_ALT_DRAW 2
+#define SBRF_REDRAW ( SBRF_DO_REDRAW_ALL|SBRF_DO_ALT_DRAW )
+
+#define BUTTONNEEDREDRAW 1256 \ No newline at end of file
diff --git a/plugins/Clist_modern/src/m_api/m_skinned_profile.h b/plugins/Clist_modern/src/m_api/m_skinned_profile.h
new file mode 100644
index 0000000000..0b0932bac6
--- /dev/null
+++ b/plugins/Clist_modern/src/m_api/m_skinned_profile.h
@@ -0,0 +1,44 @@
+#ifdef m_skinned_profile_h__
+#define m_skinned_profile_h__
+
+#define MS_SKINPROFILE_GET_INTERFACE
+
+#ifdef _cplusplus
+extern "C" {
+#endif //_cplusplus
+
+struct SKIN_PROFILE_INTERFACE
+{
+ DWORD cbSize;
+
+ int (*pfnGetByte) ( HANDLE, const char *, const char *, int, const char *szFile, const int nLine);
+ int (*pfnGetWord) ( HANDLE, const char *, const char *, int, const char *szFile, const int nLine);
+ int (*pfnGetDword)( HANDLE, const char *, const char *, int, const char *szFile, const int nLine);
+
+};
+
+#ifdef SPI_DECLARE_INTERFACE_INIT
+#include <m_database.h>
+__forceinline int mir_getSPI( struct SKIN_PROFILE_INTERFACE * pspi)
+{
+ if ( !ServiceExists( MS_SKINPROFILE_GET_INTERFACE ) )
+ {
+ pspi->pfnGetByte = DBGetContactSettingByte_Helper;
+ pspi->pfnGetWord = DBGetContactSettingWord_Helper;
+ pspi->pfnGetDword = DBGetContactSettingDword_Helper;
+ return 0;
+ }
+ else
+ {
+ pspi->cbSize = sizeof( struct SKIN_PROFILE_INTERFACE );
+ return CallService( MS_SKINPROFILE_GET_INTERFACE, 0, (LPARAM) pspi );
+ }
+}
+#endif
+
+#ifdef _cplusplus
+};
+#endif //_cplusplus
+
+
+#endif // m_skinned_profile_h__ \ No newline at end of file
diff --git a/plugins/Clist_modern/src/m_api/m_xpTheme.h b/plugins/Clist_modern/src/m_api/m_xpTheme.h
new file mode 100644
index 0000000000..63f1b0a5d3
--- /dev/null
+++ b/plugins/Clist_modern/src/m_api/m_xpTheme.h
@@ -0,0 +1,35 @@
+/* Wrapper for XP theme */
+typedef void * XPTHANDLE;
+typedef HANDLE HTHEME;
+
+XPTHANDLE xpt_AddThemeHandle(HWND hwnd, LPCWSTR className);
+void xpt_FreeThemeHandle(XPTHANDLE xptHandle);
+void xpt_FreeThemeForWindow(HWND hwnd);
+BOOL xpt_IsValidHandle(XPTHANDLE xptHandle);
+HRESULT xpt_DrawThemeBackground(XPTHANDLE xptHandle, HDC hdc, int type, int state, const RECT * sizeRect, const RECT * clipRect);
+HRESULT xpt_DrawThemeParentBackground(HWND hWnd, HDC hdc, const RECT * sizeRect);
+HRESULT xpt_DrawThemeText(XPTHANDLE xptHandle, HDC hdc, int type, int state, LPCTSTR lpStr, int len, DWORD flag1, DWORD flag2, const RECT * textRect);
+BOOL xpt_IsThemeBackgroundPartiallyTransparent(XPTHANDLE xptHandle, int type, int state);
+HRESULT xpt_DrawTheme(XPTHANDLE xptHandle, HWND hwnd, HDC hdc, int type, int state, const RECT *sizeRect, const RECT * clipRect);
+BOOL xpt_IsThemed(XPTHANDLE xptHandle);
+BOOL xpt_EnableThemeDialogTexture(HWND hwnd, DWORD flags);
+
+// next will be called only from one place
+HRESULT XPThemesLoadModule();
+void XPThemesUnloadModule();
+void xpt_OnWM_THEMECHANGED();
+
+
+//definitions
+
+
+//#include <tmschema.h>
+//TODO: ADD HERE other definitions of part and states from <tmschema.h>
+//WINDOW
+#define WP_CAPTION 1
+#define WP_SMALLCAPTION 2
+#define WP_SMALLMINCAPTION 4
+#define WP_SMALLMAXCAPTION 6
+
+#define CS_ACTIVE 1
+#define CS_INACTIVE 2 \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_aniavatars.cpp b/plugins/Clist_modern/src/modern_aniavatars.cpp
new file mode 100644
index 0000000000..88611fa1d0
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_aniavatars.cpp
@@ -0,0 +1,1300 @@
+/**************************************************************************\
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+
+****************************************************************************
+
+Created: Mar 9, 2007
+
+Author: Artem Shpynov aka FYR: ashpynov@gmail.com
+
+****************************************************************************
+
+File contains implementation of animated avatars in contact list
+
+\**************************************************************************/
+
+#include "hdr/modern_commonheaders.h"
+
+#define IMMEDIATE_DRAW (!AniAva.bSeparateWindow)
+
+void GDIPlus_ExtractAnimatedGIF (TCHAR * szName, int width, int height, HBITMAP * pBmp, int ** pframesDelay, int * pframesCount, SIZE * sizeAvatar);
+BOOL GDIPlus_IsAnimatedGif (TCHAR * szName);
+
+/* Next is module */
+#define ANIAVAWINDOWCLASS _T("MirandaModernAniAvatar")
+#define aacheck if ( !AniAva.bModuleStarted) return
+#define aalock EnterCriticalSection(&AniAva.CS)
+#define aaunlock LeaveCriticalSection(&AniAva.CS)
+
+#define AAO_HAS_BORDER 0x01
+#define AAO_ROUND_CORNERS 0x02
+#define AAO_HAS_OVERLAY 0x04
+#define AAO_OPAQUE 0x08
+//messages
+enum {
+ AAM_FIRST = WM_USER,
+ AAM_SETAVATAR , //sync WPARAM: TCHAR * filename, LPARAM: SIZE * size, RESULT: actual size
+ AAM_SETPOSITION, //async LPARAM: pointer to set pos info - the handler will empty it, RESULT: 0
+ AAM_REDRAW, //async
+ AAM_STOP, //async stops animation, timer, hide window - prepeare for deleting
+ AAM_PAUSE, //sync keep timer and window, but do not process painting -need before graphics change
+ AAM_RESUME, //async remobe previous flag. repaints if required
+ AAM_REMOVEAVATAR, //sync WPARAM: if y more then wParam, LPARAM: shift up to lParam( remove if values is same)
+ AAM_SETPARENT, //async WPARAM: handle of new parent window
+ AAM_SELFDESTROY, //sync
+ AAM_RENDER, //sync
+ AAM_LAST,
+};
+
+typedef struct _tagAniAva_Object
+{
+ HANDLE hContact;
+ HWND hWindow;
+ BOOL bInvalidPos;
+ BOOL bToBeDeleted;
+ DWORD dwAvatarUniqId;
+ SIZE ObjectSize;
+} ANIAVA_OBJECT;
+
+typedef struct _tagAniAva_Info
+{
+ DWORD dwAvatarUniqId;
+ TCHAR * tcsFilename;
+ int nRefCount;
+ int nStripTop;
+ int nFrameCount;
+ int * pFrameDelays;
+ SIZE FrameSize;
+} ANIAVA_INFO;
+
+typedef struct _tagAniAva_WindowInfo
+{
+ HWND hWindow;
+ RECT rcPos;
+ SIZE sizeAvatar;
+ BOOL StopTimer;
+ int TimerId;
+ int nFramesCount;
+ int * delaysInterval;
+ int currentFrame;
+
+ POINT ptFromPoint;
+
+ BOOL bPlaying;
+ int overlayIconIdx;
+ BYTE bAlpha;
+ BOOL bOrderTop;
+
+ BOOL bPaused; // was request do not draw
+ BOOL bPended; // till do not draw - was painting - need to be repaint
+} ANIAVA_WINDOWINFO;
+typedef struct _tagAniAva_PosInfo
+{
+ RECT rcPos;
+ int idxOverlay;
+ BYTE bAlpha;
+} ANIAVA_POSINFO;
+typedef struct _tagAniAvaSyncCallItem
+{
+ WPARAM wParam;
+ LPARAM lParam;
+ INT_PTR nResult;
+ HANDLE hDoneEvent;
+ PSYNCCALLBACKPROC pfnProc;
+} ANIAVA_SYNCCALLITEM;
+typedef struct _tagAniAvatarImageInfo
+{
+ POINT ptImagePos;
+ int nFramesCount;
+ int * pFrameDelays;
+ SIZE szSize;
+} ANIAVATARIMAGEINFO;
+
+//main structure to handle global
+typedef struct _tagAniAva
+{
+ //protection
+ BOOL bModuleStarted;
+ CRITICAL_SECTION CS;
+ //options
+ BYTE bFlags; // 0x1 has border, 0x2 has round corners, 0x4 has overlay, 0x8 background color
+ COLORREF borderColor;
+ BYTE cornerRadius;
+ COLORREF bkgColor;
+ HIMAGELIST overlayIconImageList;
+ //animations
+ HDC hAniAvaDC;
+ HBITMAP hAniAvaBitmap;
+ HBITMAP hAniAvaOldBitmap;
+ int width;
+ int height;
+ SortedList * AniAvatarList;
+ DWORD AnimationThreadID;
+ HANDLE AnimationThreadHandle;
+ HANDLE hExitEvent;
+ //Objects
+ SortedList * Objects;
+ BOOL bSeparateWindow;
+} ANIAVA;
+
+//module static declarations
+static void __AniAva_DebugRenderStrip();
+
+static void _AniAva_DestroyAvatarWindow( HWND hwnd);
+static void _AniAva_Clear_ANIAVA_WINDOWINFO(ANIAVA_WINDOWINFO * pavwi );
+static void _AniAva_RenderAvatar(ANIAVA_WINDOWINFO * dat, HDC hdcParent = NULL, RECT * rcInParent = NULL );
+static void _AniAva_PausePainting();
+static void _AniAva_ResumePainting();
+static void _AniAva_LoadOptions();
+static void _AniAva_ReduceAvatarImages(int startY, int dY, BOOL bDestroyWindow);
+static void _AniAva_AnimationTreadProc(HANDLE hExitEvent);
+static void _AniAva_RemoveAniAvaDC(ANIAVA * pAniAva);
+static void _AniAva_RealRemoveAvatar(DWORD UniqueID);
+static int _AniAva_LoadAvatarFromImage(TCHAR * szFileName, int width, int height, ANIAVATARIMAGEINFO * pRetAII);
+static int _AniAva_SortAvatarInfo(void * first, void * last);
+static BOOL _AniAva_GetAvatarImageInfo(DWORD dwAvatarUniqId, ANIAVATARIMAGEINFO * avii);
+static HWND _AniAva_CreateAvatarWindowSync(TCHAR *szFileName);
+
+static LRESULT CALLBACK _AniAva_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+//module variables
+static ANIAVA AniAva = {0};
+
+/// IMPLEMENTATION
+
+
+int _AniAva_OnModulesUnload(WPARAM wParam,LPARAM lParam)
+{
+ SetEvent(AniAva.hExitEvent);
+ return 0;
+}
+
+
+// Init AniAva module
+int AniAva_InitModule()
+{
+ memset(&AniAva,0,sizeof(AniAva));
+ if (g_CluiData.fGDIPlusFail) return 0;
+ if ( !( db_get_b(NULL,"CList","AvatarsAnimated",(ServiceExists(MS_AV_GETAVATARBITMAP) && !g_CluiData.fGDIPlusFail))
+ && db_get_b(NULL,"CList","AvatarsShow",SETTINGS_SHOWAVATARS_DEFAULT))) return 0;
+ {
+ WNDCLASSEX wc;
+ ZeroMemory(&wc, sizeof(wc));
+ wc.cbSize = sizeof(wc);
+ wc.lpszClassName = ANIAVAWINDOWCLASS;
+ wc.lpfnWndProc = _AniAva_WndProc;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.cbWndExtra = sizeof(ANIAVA_WINDOWINFO*);
+ wc.hbrBackground = 0;
+ wc.style = CS_GLOBALCLASS;
+ RegisterClassEx(&wc);
+ }
+ InitializeCriticalSection(&AniAva.CS);
+ AniAva.Objects = List_Create(0,2);
+ AniAva.AniAvatarList = List_Create(0,1);
+ AniAva.AniAvatarList->sortFunc = _AniAva_SortAvatarInfo;
+ AniAva.bModuleStarted = TRUE;
+ AniAva.hExitEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
+ AniAva.AnimationThreadID = (DWORD)mir_forkthread(_AniAva_AnimationTreadProc, (void*)AniAva.hExitEvent);
+ HookEvent(ME_SYSTEM_PRESHUTDOWN, _AniAva_OnModulesUnload);
+
+ _AniAva_LoadOptions();
+
+ return 1;
+}
+
+// Unload AniAva module
+int AniAva_UnloadModule()
+{
+ aacheck 0;
+ aalock;
+ {
+ int i;
+ AniAva.bModuleStarted = FALSE;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ if (AniAva.Objects->items[i])
+ _AniAva_DestroyAvatarWindow(((ANIAVA_OBJECT*)AniAva.Objects->items[i])->hWindow);
+
+ mir_free(AniAva.Objects->items[i]);
+ }
+ List_Destroy(AniAva.Objects);
+ mir_free(AniAva.Objects);
+
+ for (i=0; i < AniAva.AniAvatarList->realCount; i++)
+ {
+ ANIAVA_INFO * aai = (ANIAVA_INFO *)AniAva.AniAvatarList->items[i];
+ mir_free(aai->tcsFilename);
+ if (aai->pFrameDelays) free(aai->pFrameDelays);
+ mir_free(aai);
+ }
+ List_Destroy(AniAva.AniAvatarList);
+ mir_free(AniAva.AniAvatarList);
+ _AniAva_RemoveAniAvaDC(&AniAva);
+ SetEvent(AniAva.hExitEvent);
+ CloseHandle(AniAva.hExitEvent);
+ }
+ aaunlock;
+ DeleteCriticalSection(&AniAva.CS);
+ return 1;
+}
+// Update options
+int AniAva_UpdateOptions()
+{
+ BOOL bReloadAvatars = FALSE;
+ BOOL bBeEnabled = (!g_CluiData.fGDIPlusFail
+ && db_get_b(NULL,"CList","AvatarsAnimated",(ServiceExists(MS_AV_GETAVATARBITMAP) && !g_CluiData.fGDIPlusFail))
+ && db_get_b(NULL,"CList","AvatarsShow",SETTINGS_SHOWAVATARS_DEFAULT));
+ if (bBeEnabled && !AniAva.bModuleStarted)
+ {
+ AniAva_InitModule();
+ bReloadAvatars = TRUE;
+ }
+ else if ( !bBeEnabled && AniAva.bModuleStarted)
+ {
+ AniAva_UnloadModule();
+ bReloadAvatars = TRUE;
+ }
+ BOOL oldSeparate = AniAva.bSeparateWindow;
+ _AniAva_LoadOptions();
+ if ( oldSeparate != AniAva.bSeparateWindow )
+ {
+ AniAva_InvalidateAvatarPositions(NULL);
+ AniAva_RemoveInvalidatedAvatars();
+ }
+ if ( bReloadAvatars ) PostMessage(pcli->hwndContactTree,INTM_AVATARCHANGED,0,0);
+ else AniAva_RedrawAllAvatars(TRUE);
+ return 0;
+}
+// adds avatars to be displayed
+int AniAva_AddAvatar(HANDLE hContact, TCHAR * szFilename, int width, int heigth)
+{
+ int res = 0;
+ aacheck 0;
+ if ( !GDIPlus_IsAnimatedGif (szFilename))
+ return 0;
+ aalock;
+ {
+ //first try to find window for contact avatar
+ HWND hwnd = NULL;
+ int i;
+ ANIAVA_OBJECT * pavi;
+ ANIAVATARIMAGEINFO avii = {0};
+ SIZE szAva = { width, heigth };
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ pavi = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ if (pavi->hContact == hContact)
+ {
+ if (pavi->ObjectSize.cx == width && pavi->ObjectSize.cy == heigth)
+ {
+ hwnd = pavi->hWindow;
+ break;
+ }
+ else
+ {
+
+ _AniAva_DestroyAvatarWindow(pavi->hWindow);
+ pavi->hWindow = NULL;
+ _AniAva_RealRemoveAvatar(pavi->dwAvatarUniqId);
+ pavi->dwAvatarUniqId = 0;
+ break;
+ }
+ }
+ }
+ if (i == AniAva.Objects->realCount)
+ {
+ pavi = (ANIAVA_OBJECT *) mir_calloc( sizeof(ANIAVA_OBJECT));
+ pavi->hWindow = NULL;
+ pavi->hContact = hContact;
+ pavi->bInvalidPos = 0;
+ List_Insert( AniAva.Objects, pavi, AniAva.Objects->realCount);
+ }
+ //change avatar
+ pavi->bToBeDeleted = FALSE;
+ pavi->bInvalidPos = 0;
+ // now CreateAvatar
+ if (pavi->dwAvatarUniqId)
+ _AniAva_GetAvatarImageInfo(pavi->dwAvatarUniqId,&avii);
+ else
+ pavi->dwAvatarUniqId = _AniAva_LoadAvatarFromImage(szFilename, width, heigth, &avii);
+ if (hwnd)
+ SendMessage(hwnd, AAM_SETAVATAR, (WPARAM)&avii, (LPARAM) 0);
+ pavi->ObjectSize = avii.szSize;
+ res = MAKELONG(avii.szSize.cx, avii.szSize.cy);
+ }
+ aaunlock;
+ return res;
+}
+
+// call windows to set they parent in order to ensure valid zorder
+void AniAva_UpdateParent()
+{
+ aacheck;
+ aalock;
+ {
+ int i;
+ HWND parent = fnGetAncestor(pcli->hwndContactList,GA_PARENT);
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ SendMessage(pai->hWindow, AAM_SETPARENT, (WPARAM)parent,0);
+ }
+ }
+ aaunlock;
+}
+ANIAVA_OBJECT * FindAvatarByContact( HANDLE hContact )
+{
+ for ( int i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = ((ANIAVA_OBJECT *)AniAva.Objects->items[i]);
+ if (pai->hContact == hContact)
+ return pai;
+ }
+ return NULL;
+}
+
+int AniAva_RenderAvatar( HANDLE hContact, HDC hdcMem, RECT * rc )
+{
+ aacheck 0;
+ aalock;
+ ANIAVA_OBJECT * pai = FindAvatarByContact( hContact );
+ if ( pai )
+ SendMessage(pai->hWindow, AAM_RENDER, (WPARAM)hdcMem, (LPARAM) rc);
+ aaunlock;
+ return 0;
+}
+// update avatars pos
+int AniAva_SetAvatarPos(HANDLE hContact, RECT * rc, int overlayIdx, BYTE bAlpha)
+{
+ aacheck 0;
+ aalock;
+ if (AniAva.CS.LockCount>0)
+ {
+ aaunlock;
+ return 0;
+ }
+ {
+ ANIAVA_OBJECT * pai = FindAvatarByContact( hContact );
+ if ( pai )
+ {
+ ANIAVA_POSINFO * api = (ANIAVA_POSINFO *)malloc(sizeof(ANIAVA_POSINFO));
+ if ( !pai->hWindow)
+ {
+ HWND hwnd;
+ HWND parent;
+ ANIAVATARIMAGEINFO avii = {0};
+ //not found -> create window
+ char szName[150] = "AniAvaWnd_";
+ TCHAR * tszName;
+ _itoa((int)hContact,szName+10,16);
+
+ tszName = mir_a2t( szName );
+ hwnd = _AniAva_CreateAvatarWindowSync(tszName);
+ mir_free( tszName );
+ parent = fnGetAncestor(pcli->hwndContactList,GA_PARENT);
+ pai->hWindow = hwnd;
+ SendMessage(hwnd,AAM_SETPARENT,(WPARAM)parent,0);
+ if (_AniAva_GetAvatarImageInfo(pai->dwAvatarUniqId,&avii))
+ SendMessage(pai->hWindow, AAM_SETAVATAR, (WPARAM)&avii, (LPARAM) 0);
+ }
+ api->bAlpha = bAlpha;
+ api->idxOverlay = overlayIdx;
+ api->rcPos = *rc;
+ SendNotifyMessage(pai->hWindow, AAM_SETPOSITION, (WPARAM)0, (LPARAM) api);
+ // the AAM_SETPOSITION is responsible to destroy memory under api
+ pai->bInvalidPos = FALSE;
+ pai->bToBeDeleted = FALSE;
+ }
+ }
+ aaunlock;
+ return 1;
+}
+// remove avatar
+int AniAva_RemoveAvatar(HANDLE hContact)
+{
+ aacheck 0;
+ aalock;
+ {
+ int i;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ if (pai->hContact == hContact)
+ {
+ pai->bToBeDeleted = TRUE;
+ break;
+ }
+ }
+ }
+ aaunlock;
+ return 1;
+}
+// reset positions of avatars to be drawn (still be painted at same place)
+int AniAva_InvalidateAvatarPositions(HANDLE hContact)
+{
+ int i;
+ aacheck 0;
+ aalock;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ if (pai->hContact == hContact || !hContact)
+ {
+ pai->bInvalidPos++;
+ if (hContact) break;
+ }
+ }
+ aaunlock;
+ return 1;
+}
+// all avatars without validated position will be stop painted and probably removed
+int AniAva_RemoveInvalidatedAvatars()
+{
+ BOOL keepAvatar = FALSE;
+ aacheck 0;
+ aalock;
+
+ {
+ int i;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ if (pai->hWindow && (pai->bInvalidPos))
+ {
+ SendMessage(pai->hWindow,AAM_STOP,0,0);
+ if (pai->bInvalidPos)//>3)
+ {
+ //keepAvatar = TRUE;
+ //pai->bToBeDeleted = TRUE;
+ pai->bInvalidPos = 0;
+ _AniAva_DestroyAvatarWindow(pai->hWindow);
+ pai->hWindow = NULL;
+ }
+ }
+ if (pai->bToBeDeleted)
+ {
+ if (pai->hWindow) _AniAva_DestroyAvatarWindow(pai->hWindow);
+ pai->hWindow = NULL;
+ if ( !keepAvatar) _AniAva_RealRemoveAvatar(pai->dwAvatarUniqId);
+ mir_free(pai);
+ List_Remove(AniAva.Objects,i);
+ i--;
+ }
+ }
+ }
+ aaunlock;
+ return 1;
+}
+
+// repaint all avatars at positions (eg on main window movement)
+int AniAva_RedrawAllAvatars(BOOL updateZOrder)
+{
+ int i;
+ aacheck 0;
+ aalock;
+ updateZOrder = 1;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ if (updateZOrder)
+ SendMessage(pai->hWindow,AAM_REDRAW,(WPARAM)updateZOrder,0);
+ else
+ SendNotifyMessage(pai->hWindow,AAM_REDRAW,(WPARAM)updateZOrder,0);
+ }
+ aaunlock;
+ return 1;
+}
+
+//Static procedures
+static void CALLBACK _AniAva_SyncCallerUserAPCProc(DWORD_PTR dwParam)
+{
+ ANIAVA_SYNCCALLITEM* item = (ANIAVA_SYNCCALLITEM*) dwParam;
+ item->nResult = item->pfnProc(item->wParam, item->lParam);
+ SetEvent(item->hDoneEvent);
+}
+static INT_PTR _AniAva_CreateAvatarWindowSync_Worker(WPARAM tszName, LPARAM lParam)
+{
+ HWND hwnd = CreateWindowEx( WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_NOPARENTNOTIFY,ANIAVAWINDOWCLASS,(TCHAR*)tszName,WS_POPUP,
+ 0,0,1,1,pcli->hwndContactList, NULL, pcli->hInst, NULL );
+ return (INT_PTR)hwnd;
+}
+
+static HWND _AniAva_CreateAvatarWindowSync(TCHAR *szFileName)
+{
+ ANIAVA_SYNCCALLITEM item = {0};
+ int res = 0;
+ if ( !AniAva.AnimationThreadHandle) return NULL;
+ if (AniAva.AnimationThreadID == 0) return NULL;
+ item.wParam = (WPARAM) szFileName;
+ item.lParam = 0;
+ item.pfnProc = _AniAva_CreateAvatarWindowSync_Worker;
+ item.hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (GetCurrentThreadId() != AniAva.AnimationThreadID)
+ QueueUserAPC(_AniAva_SyncCallerUserAPCProc, AniAva.AnimationThreadHandle, (DWORD_PTR) &item);
+ else
+ _AniAva_SyncCallerUserAPCProc((DWORD_PTR) &item);
+ WaitForSingleObject(item.hDoneEvent, INFINITE);
+ CloseHandle(item.hDoneEvent);
+ return (HWND)item.nResult;
+}
+
+static void _AniAva_RealRemoveAvatar(DWORD UniqueID)
+{
+ int j,k;
+ for (j = 0; j < AniAva.AniAvatarList->realCount; j++)
+ {
+ ANIAVA_INFO * aai = (ANIAVA_INFO *) AniAva.AniAvatarList->items[j];
+ if (aai->dwAvatarUniqId == UniqueID)
+ {
+ aai->nRefCount--;
+ if (aai->nRefCount == 0)
+ {
+ _AniAva_PausePainting();
+ #ifdef _DEBUG
+ __AniAva_DebugRenderStrip();
+ #endif
+ mir_free(aai->tcsFilename);
+ if (aai->pFrameDelays) free(aai->pFrameDelays);
+ _AniAva_ReduceAvatarImages(aai->nStripTop,aai->FrameSize.cx*aai->nFrameCount, FALSE);
+ for (k = 0; k < AniAva.AniAvatarList->realCount; k++)
+ if (k != j) {
+ ANIAVA_INFO * taai = (ANIAVA_INFO *) AniAva.AniAvatarList->items[k];
+ if (taai->nStripTop>aai->nStripTop)
+ taai->nStripTop -= aai->FrameSize.cx*aai->nFrameCount;
+ }
+ if (AniAva.AniAvatarList->realCount>0)
+ {
+ //lets create hNewDC
+ HDC hNewDC;
+ HBITMAP hNewBmp, hNewOldBmp;
+
+ int newWidth = AniAva.width-aai->FrameSize.cx*aai->nFrameCount;
+ int newHeight = 0;
+ int i;
+ for (i=0; i < AniAva.AniAvatarList->realCount; i++)
+ if (i != j)
+ {
+ newHeight = max(newHeight,((ANIAVA_INFO *) AniAva.AniAvatarList->items[i])->FrameSize.cy);
+ }
+
+ hNewDC = CreateCompatibleDC(NULL);
+ hNewBmp = ske_CreateDIB32(newWidth,newHeight);
+ hNewOldBmp = (HBITMAP)SelectObject(hNewDC,hNewBmp);
+ // copy from old and from new strip
+ if (aai->nStripTop>0)
+ BitBlt(hNewDC,0,0,aai->nStripTop,newHeight,AniAva.hAniAvaDC,0,0, SRCCOPY);
+ if (aai->nStripTop+aai->FrameSize.cx*aai->nFrameCount < AniAva.width)
+ BitBlt(hNewDC,aai->nStripTop,0,AniAva.width-(aai->nStripTop+aai->FrameSize.cx*aai->nFrameCount),newHeight,AniAva.hAniAvaDC,aai->nStripTop+aai->FrameSize.cx*aai->nFrameCount,0, SRCCOPY);
+
+ _AniAva_RemoveAniAvaDC(&AniAva);
+ AniAva.hAniAvaDC = hNewDC;
+ AniAva.hAniAvaBitmap = hNewBmp;
+ AniAva.hAniAvaOldBitmap = hNewOldBmp;
+ AniAva.width = newWidth;
+ AniAva.height = newHeight;
+
+ }
+ else
+ {
+ _AniAva_RemoveAniAvaDC(&AniAva);
+ }
+ #ifdef _DEBUG
+ __AniAva_DebugRenderStrip();
+ #endif
+ List_Remove(AniAva.AniAvatarList, j);
+ mir_free(aai);
+ _AniAva_ResumePainting();
+ break;
+ }
+ }
+ }
+}
+static void _AniAva_RemoveAniAvaDC(ANIAVA * pAniAva)
+{
+ if (pAniAva->hAniAvaDC)
+ {
+ SelectObject(pAniAva->hAniAvaDC, pAniAva->hAniAvaOldBitmap);
+ DeleteObject(pAniAva->hAniAvaBitmap);
+ DeleteDC(pAniAva->hAniAvaDC);
+ pAniAva->hAniAvaDC = NULL;
+ pAniAva->height = 0;
+ pAniAva->width = 0;
+ pAniAva->hAniAvaBitmap = NULL;
+ }
+};
+
+static void _AniAva_DestroyAvatarWindow( HWND hwnd)
+{
+ SendMessage(hwnd,AAM_SELFDESTROY,0,0);
+}
+static int _AniAva_LoadAvatarFromImage(TCHAR * szFileName, int width, int height, ANIAVATARIMAGEINFO * pRetAII)
+{
+ ANIAVA_INFO aai = {0};
+ ANIAVA_INFO * paai = NULL;
+ BOOL fNeedInsertToList = FALSE;
+ int idx = 0;
+ aai.tcsFilename = szFileName;
+ aai.FrameSize.cx = width;
+ aai.FrameSize.cy = height;
+
+ if ( !List_GetIndex(AniAva.AniAvatarList,(void*)&aai,&idx)) idx = -1;
+ if (idx == -1) //item not present in list
+ {
+ HBITMAP hBitmap = NULL;
+ HDC hTempDC;
+ HBITMAP hOldBitmap;
+ HDC hNewDC;
+ HBITMAP hNewBmp;
+ HBITMAP hNewOldBmp;
+ int newWidth;
+ int newHeight;
+
+ paai = (ANIAVA_INFO *)mir_calloc(sizeof(ANIAVA_INFO));
+ paai->tcsFilename = mir_tstrdup(szFileName);
+ paai->dwAvatarUniqId = rand();
+ fNeedInsertToList = TRUE;
+ //get image strip
+ GDIPlus_ExtractAnimatedGIF (szFileName, width, height, &hBitmap, &(paai->pFrameDelays), &(paai->nFrameCount), &(paai->FrameSize));
+
+ //copy image to temp DC
+ hTempDC = CreateCompatibleDC(NULL);
+ hOldBitmap = (HBITMAP)SelectObject(hTempDC,hBitmap);
+
+ //lets create hNewDC
+ /*
+ newWidth = max(paai->FrameSize.cx*paai->nFrameCount,AniAva.width);
+ newHeight = AniAva.height+paai->FrameSize.cy;
+ */
+ newWidth = AniAva.width+paai->FrameSize.cx*paai->nFrameCount;
+ newHeight = max(paai->FrameSize.cy,AniAva.height);
+
+ hNewDC = CreateCompatibleDC(NULL);
+ hNewBmp = ske_CreateDIB32(newWidth,newHeight);
+ hNewOldBmp = (HBITMAP)SelectObject(hNewDC,hNewBmp);
+
+ _AniAva_PausePainting();
+ GdiFlush();
+ // copy from old and from new strip
+ BitBlt(hNewDC,0,0,AniAva.width,AniAva.height,AniAva.hAniAvaDC,0,0, SRCCOPY);
+ BitBlt(hNewDC,AniAva.width,0,paai->FrameSize.cx*paai->nFrameCount,paai->FrameSize.cy,hTempDC,0,0, SRCCOPY);
+
+ paai->nStripTop = AniAva.width;
+
+ GdiFlush();
+ //remove temp DC
+ SelectObject(hTempDC,hOldBitmap);
+ DeleteObject(hNewBmp);
+ DeleteDC(hTempDC);
+ DeleteObject(hBitmap);
+
+
+ //delete old
+ _AniAva_RemoveAniAvaDC(&AniAva);
+ //setNewDC;
+ AniAva.hAniAvaDC = hNewDC;
+ AniAva.hAniAvaBitmap = hNewBmp;
+ AniAva.hAniAvaOldBitmap = hNewOldBmp;
+ AniAva.width = newWidth;
+ AniAva.height = newHeight;
+ GdiFlush();
+ _AniAva_ResumePainting();
+ }
+ else
+ {
+ paai = (ANIAVA_INFO *)AniAva.AniAvatarList->items[idx];
+ }
+ if (paai)
+ {
+ paai->nRefCount++;
+ pRetAII->nFramesCount = paai->nFrameCount;
+ pRetAII->pFrameDelays = paai->pFrameDelays;
+ pRetAII->ptImagePos.x = paai->nStripTop;
+ pRetAII->ptImagePos.y = 0;
+ pRetAII->szSize = paai->FrameSize;
+ if (fNeedInsertToList)
+ {
+ //add to list
+ int idx = AniAva.AniAvatarList->realCount;
+ List_GetIndex(AniAva.AniAvatarList, paai,&idx);
+ List_Insert(AniAva.AniAvatarList, (void*)paai, idx);
+ }
+ return paai->dwAvatarUniqId;
+ }
+ return 0;
+}
+static BOOL _AniAva_GetAvatarImageInfo(DWORD dwAvatarUniqId, ANIAVATARIMAGEINFO * avii)
+{
+ int j;
+ BOOL res = FALSE;
+ for (j = 0; j < AniAva.AniAvatarList->realCount; j++)
+ {
+ ANIAVA_INFO * aai = (ANIAVA_INFO *) AniAva.AniAvatarList->items[j];
+ if (aai->dwAvatarUniqId == dwAvatarUniqId)
+ {
+ avii->nFramesCount = aai->nFrameCount;
+ avii->pFrameDelays = aai->pFrameDelays;
+ avii->ptImagePos.x = aai->nStripTop;
+ avii->ptImagePos.y = 0;
+ avii->szSize = aai->FrameSize;
+ res = TRUE;
+ break;
+ }
+ }
+ return res;
+}
+static void _AniAva_Clear_ANIAVA_WINDOWINFO(ANIAVA_WINDOWINFO * pavwi )
+{
+ pavwi->delaysInterval = NULL;
+ pavwi->nFramesCount = 0;
+ KillTimer(pavwi->hWindow,2);
+ pavwi->bPlaying = FALSE;
+ pavwi->TimerId = 0;
+}
+static void __AniAva_DebugRenderStrip()
+{
+ return;
+ #ifdef _DEBUG
+ {
+ HDC hDC_debug = GetDC(NULL);
+ BitBlt(hDC_debug,0,0,AniAva.width, AniAva.height,AniAva.hAniAvaDC,0,0,SRCCOPY);
+ DeleteDC(hDC_debug);
+ }
+ #endif
+}
+
+static void _AniAva_RenderAvatar(ANIAVA_WINDOWINFO * dat, HDC hdcParent /*= NULL*/, RECT * rcInParent /*= NULL */ )
+{
+ if (dat->bPaused>0) { dat->bPended = TRUE; return; }
+ else dat->bPended = FALSE;
+
+ if ( IMMEDIATE_DRAW && hdcParent == NULL ) return;
+ GdiFlush();
+#ifdef _DEBUG
+ __AniAva_DebugRenderStrip();
+#endif
+ if (dat->bPlaying && IsWindowVisible(dat->hWindow))
+ {
+ POINT ptWnd = {0};
+ SIZE szWnd = {dat->rcPos.right-dat->rcPos.left,dat->rcPos.bottom-dat->rcPos.top};
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0,g_CluiData.bCurrentAlpha*dat->bAlpha/256, AC_SRC_ALPHA };
+ POINT pt_from = {0,0};
+ HDC hDC_animation = GetDC(NULL);
+ HDC copyFromDC;
+ RECT clistRect;
+ HDC tempDC = NULL;
+ HBITMAP hBmp;
+ HBITMAP hOldBmp;
+
+ /*
+ int x = bf.SourceConstantAlpha;
+ x = (49152/(383-x))-129;
+ x = min(x,255); x = max(x,0);
+ bf.SourceConstantAlpha = x;
+ */
+ if ( AniAva.bFlags == 0 ) //simple and fastest method - no borders, round corners and etc. just copy
+ {
+ pt_from.x = dat->ptFromPoint.x+dat->currentFrame*dat->sizeAvatar.cx;
+ pt_from.y = dat->ptFromPoint.y;
+ copyFromDC = AniAva.hAniAvaDC;
+ }
+ else
+ {
+ // ... need to create additional hDC_animation
+ HRGN hRgn = NULL;
+ int cornerRadius = AniAva.cornerRadius;
+ tempDC = CreateCompatibleDC( NULL );
+ hBmp = ske_CreateDIB32( szWnd.cx, szWnd.cy );
+ hOldBmp = (HBITMAP)SelectObject(tempDC,hBmp);
+ if ( AniAva.bFlags & AAO_ROUND_CORNERS )
+ {
+ if ( !cornerRadius) //auto radius
+ cornerRadius = min(szWnd.cx, szWnd.cy )/5;
+ }
+ if ( AniAva.bFlags & AAO_HAS_BORDER )
+ {
+ // if has borders - create region (round corners) and fill it, remember internal as clipping
+ HBRUSH hBrush = CreateSolidBrush( AniAva.borderColor );
+ HBRUSH hOldBrush = (HBRUSH)SelectObject( tempDC, hBrush );
+ HRGN rgnOutside = CreateRoundRectRgn( 0, 0, szWnd.cx+1, szWnd.cy+1, cornerRadius << 1, cornerRadius << 1);
+ hRgn = CreateRoundRectRgn( 1, 1, szWnd.cx, szWnd.cy, cornerRadius << 1, cornerRadius << 1);
+ CombineRgn( rgnOutside,rgnOutside,hRgn,RGN_DIFF);
+ FillRgn( tempDC, rgnOutside, hBrush);
+ ske_SetRgnOpaque( tempDC, rgnOutside, TRUE);
+ SelectObject(tempDC, hOldBrush);
+ DeleteObject(hBrush);
+ DeleteObject(rgnOutside);
+ }
+ else if ( cornerRadius > 0 )
+ {
+ // else create clipping area (round corners)
+ hRgn = CreateRoundRectRgn(0, 0, szWnd.cx+1, szWnd.cy+1, cornerRadius << 1, cornerRadius << 1);
+ }
+ else
+ {
+ hRgn = CreateRectRgn(0, 0, szWnd.cx+1, szWnd.cy+1);
+ }
+ // select clip area
+ if ( hRgn )
+ ExtSelectClipRgn(tempDC, hRgn, RGN_AND);
+
+ if ( AniAva.bFlags & AAO_OPAQUE)
+ {
+ // if back color - fill clipping area
+ HBRUSH hBrush = CreateSolidBrush( AniAva.bkgColor );
+ HBRUSH hOldBrush = (HBRUSH)SelectObject( tempDC, hBrush );
+ FillRgn( tempDC, hRgn, hBrush );
+ ske_SetRgnOpaque( tempDC, hRgn, TRUE );
+ }
+ // draw avatar
+ if ( !(AniAva.bFlags & AAO_OPAQUE))
+ BitBlt(tempDC,0, 0, szWnd.cx, szWnd.cy , AniAva.hAniAvaDC , dat->ptFromPoint.x+dat->sizeAvatar.cx*dat->currentFrame, dat->ptFromPoint.y, SRCCOPY);
+ else
+ {
+ BLENDFUNCTION abf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ ske_AlphaBlend(tempDC,0, 0, szWnd.cx, szWnd.cy , AniAva.hAniAvaDC, dat->ptFromPoint.x+dat->sizeAvatar.cx*dat->currentFrame, dat->ptFromPoint.y, szWnd.cx, szWnd.cy, abf);
+ }
+ // reset clip area
+ if ( hRgn )
+ {
+ DeleteObject(hRgn);
+ hRgn = CreateRectRgn(0, 0, szWnd.cx, szWnd.cy);
+ SelectClipRgn(tempDC, hRgn);
+ DeleteObject(hRgn);
+ }
+
+ if (( AniAva.bFlags & AAO_HAS_OVERLAY )
+ && ( dat->overlayIconIdx != -1 )
+ && ( AniAva.overlayIconImageList ))
+ {
+ // if overlay - draw overlay icon
+ // position - on avatar
+ int x = szWnd.cx-ICON_WIDTH;
+ int y = szWnd.cy-ICON_HEIGHT;
+ ske_ImageList_DrawEx(AniAva.overlayIconImageList,
+ dat->overlayIconIdx&0xFFFF,
+ tempDC, x, y, ICON_WIDTH, ICON_HEIGHT,
+ CLR_NONE, CLR_NONE, ILD_NORMAL);
+ }
+ copyFromDC = tempDC;
+ }
+ // intersect visible area
+ // update layered window
+ GetWindowRect(pcli->hwndContactTree, &clistRect);
+ if (dat->rcPos.top < 0)
+ {
+ pt_from.y += -dat->rcPos.top;
+ szWnd.cy += dat->rcPos.top;
+ }
+ if (dat->rcPos.bottom>clistRect.bottom-clistRect.top)
+ szWnd.cy -= (dat->rcPos.bottom-(clistRect.bottom-clistRect.top));
+
+ ptWnd.x = dat->rcPos.left+clistRect.left;
+ ptWnd.y = (dat->rcPos.top>0 ? dat->rcPos.top :0)+clistRect.top;
+ if (szWnd.cy>0)
+ {
+ if ( hdcParent && rcInParent && IMMEDIATE_DRAW )
+ {
+ if ( AniAva.bFlags & AAO_OPAQUE )
+ BitBlt( hdcParent, rcInParent->left, rcInParent->top, szWnd.cx, szWnd.cy, copyFromDC, pt_from.x, pt_from.y, SRCCOPY);
+ else
+ {
+ BLENDFUNCTION abf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ ske_AlphaBlend( hdcParent, rcInParent->left, rcInParent->top, szWnd.cx, szWnd.cy, copyFromDC, pt_from.x, pt_from.y, szWnd.cx, szWnd.cy, abf);
+ }
+ }
+ else if ( !g_proc_UpdateLayeredWindow(dat->hWindow, hDC_animation, &ptWnd, &szWnd, copyFromDC, &pt_from, RGB(0,0,0), &bf, ULW_ALPHA ))
+ {
+ LONG exStyle;
+ exStyle = GetWindowLongPtr(dat->hWindow,GWL_EXSTYLE);
+ exStyle |= WS_EX_LAYERED;
+ SetWindowLongPtr(dat->hWindow,GWL_EXSTYLE,exStyle);
+ if ( !IMMEDIATE_DRAW )
+ SetWindowPos( pcli->hwndContactTree, dat->hWindow, 0, 0, 0, 0, SWP_ASYNCWINDOWPOS | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSENDCHANGING );
+ g_proc_UpdateLayeredWindow(dat->hWindow, hDC_animation, &ptWnd, &szWnd, copyFromDC, &pt_from, RGB(0,0,0), &bf, ULW_ALPHA );
+ }
+
+ g_CluiData.fAeroGlass = false;
+ CLUI_UpdateAeroGlass();
+ }
+ else
+ {
+ dat->bPlaying = FALSE;
+ }
+ ReleaseDC(NULL,hDC_animation);
+ if (tempDC)
+ {
+ SelectObject(tempDC, hOldBmp);
+ DeleteObject(hBmp);
+ DeleteDC(tempDC);
+ }
+ }
+ if ( !dat->bPlaying)
+ {
+ ShowWindow(dat->hWindow, SW_HIDE);
+ KillTimer(dat->hWindow,2); //stop animation till set pos will be called
+ }
+ GdiFlush();
+}
+static void _AniAva_PausePainting()
+{
+ int i;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ SendMessage(pai->hWindow,AAM_PAUSE,0,0);
+ }
+}
+static void _AniAva_ResumePainting()
+{
+ int i;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ SendNotifyMessage(pai->hWindow,AAM_RESUME,0,0);
+ }
+}
+
+static void _AniAva_ReduceAvatarImages(int startY, int dY, BOOL bDestroyWindow)
+{
+ int i;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ int res = SendMessage(pai->hWindow,AAM_REMOVEAVATAR,(WPARAM)startY,(LPARAM)dY);
+ if (res == 0xDEAD && bDestroyWindow)
+ {
+ _AniAva_DestroyAvatarWindow(pai->hWindow);
+ mir_free(pai);
+ List_Remove(AniAva.Objects,i);
+ i--;
+ }
+ }
+}
+
+
+static void _AniAva_LoadOptions()
+{
+ aacheck;
+ aalock;
+ {
+ AniAva.bFlags = (db_get_b(NULL,"CList","AvatarsDrawBorders",SETTINGS_AVATARDRAWBORDER_DEFAULT)? AAO_HAS_BORDER :0) |
+ (db_get_b(NULL,"CList","AvatarsRoundCorners",SETTINGS_AVATARROUNDCORNERS_DEFAULT)? AAO_ROUND_CORNERS :0) |
+ (db_get_b(NULL,"CList","AvatarsDrawOverlay",SETTINGS_AVATARDRAWOVERLAY_DEFAULT)? AAO_HAS_OVERLAY :0) |
+ ((0) ? AAO_OPAQUE :0);
+
+ if (AniAva.bFlags & AAO_HAS_BORDER)
+ AniAva.borderColor = (COLORREF)db_get_dw(NULL,"CList","AvatarsBorderColor",SETTINGS_AVATARBORDERCOLOR_DEFAULT);;
+ if (AniAva.bFlags & AAO_ROUND_CORNERS)
+ AniAva.cornerRadius = db_get_b(NULL,"CList","AvatarsUseCustomCornerSize",SETTINGS_AVATARUSECUTOMCORNERSIZE_DEFAULT)? db_get_w(NULL,"CList","AvatarsCustomCornerSize",SETTINGS_AVATARCORNERSIZE_DEFAULT) : 0;
+ if (AniAva.bFlags & AAO_HAS_OVERLAY)
+ {
+ //check image list
+ BYTE type = db_get_b(NULL,"CList","AvatarsOverlayType",SETTINGS_AVATAROVERLAYTYPE_DEFAULT);
+ switch(type)
+ {
+ case SETTING_AVATAR_OVERLAY_TYPE_NORMAL:
+ AniAva.overlayIconImageList = hAvatarOverlays;
+ break;
+ case SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL:
+ case SETTING_AVATAR_OVERLAY_TYPE_CONTACT:
+ AniAva.overlayIconImageList = g_himlCListClc;
+ break;
+ default:
+ AniAva.overlayIconImageList = NULL;
+ }
+ }
+ if (AniAva.bFlags & AAO_OPAQUE)
+ AniAva.bkgColor = 0;
+ AniAva.bSeparateWindow = db_get_b(NULL,"CList","AvatarsInSeparateWnd",SETTINGS_AVATARINSEPARATE_DEFAULT);
+
+ }
+ aaunlock;
+}
+static void _AniAva_AnimationTreadProc(HANDLE hExitEvent)
+{
+ //wait forever till hExitEvent signalled
+ DWORD rc;
+ HANDLE hThread = 0;
+ DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),GetCurrentProcess(),&hThread,0,FALSE,DUPLICATE_SAME_ACCESS);
+ AniAva.AnimationThreadHandle = hThread;
+ SetThreadPriority(hThread,THREAD_PRIORITY_LOWEST);
+ for (;;)
+ {
+ if ( fnMsgWaitForMultipleObjectsEx )
+ rc = fnMsgWaitForMultipleObjectsEx(1,&hExitEvent, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
+ else
+ rc = MsgWaitForMultipleObjects(1,&hExitEvent, FALSE, INFINITE, QS_ALLINPUT);
+
+ ResetEvent(hExitEvent);
+ if ( rc == WAIT_OBJECT_0 + 1 )
+ {
+ MSG msg;
+ while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ if ( IsDialogMessage(msg.hwnd, &msg)) continue;
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ else if ( rc == WAIT_OBJECT_0 )
+ {
+ break;
+ }
+ }
+ CloseHandle(AniAva.AnimationThreadHandle);
+ AniAva.AnimationThreadHandle = NULL;
+}
+
+static int _AniAva_SortAvatarInfo(void * first, void * last)
+{
+ int res = 0;
+ ANIAVA_INFO * aai1 = (ANIAVA_INFO *)first;
+ ANIAVA_INFO * aai2 = (ANIAVA_INFO *)last;
+ if (aai1 && aai1->tcsFilename &&
+ aai2 && aai2->tcsFilename)
+ {
+ res = _tcsicmp(aai2->tcsFilename, aai1->tcsFilename);
+ }
+ else
+ {
+ int a1 = (aai1 && aai1->tcsFilename)? 1:0;
+ int a2 = (aai2 && aai2->tcsFilename)? 1:0;
+ res = a1-a2;
+ }
+
+ if (res == 0)
+ {
+ if ( aai1->FrameSize.cx == aai2->FrameSize.cx && aai1->FrameSize.cy == aai2->FrameSize.cy )
+ return 0;
+ else
+ return 1;
+ }
+ else
+ return res;
+}
+
+void _AniAva_InvalidateParent(ANIAVA_WINDOWINFO * dat)
+{
+ if ( !IMMEDIATE_DRAW ) return;
+ HWND hwndParent = pcli->hwndContactTree;
+ RECT rcPos = dat->rcPos;
+ pcli->pfnInvalidateRect( hwndParent, &rcPos, FALSE );
+}
+
+static LRESULT CALLBACK _AniAva_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ ANIAVA_WINDOWINFO * dat = NULL;
+ if (msg == WM_TIMER || msg == WM_DESTROY || (msg>AAM_FIRST && msg < AAM_LAST))
+ dat = (ANIAVA_WINDOWINFO *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ switch (msg)
+ {
+ case AAM_REMOVEAVATAR:
+ if (dat->ptFromPoint.x == (int)wParam) return 0xDEAD; //need to destroy window
+ else if (dat->ptFromPoint.x>(int)wParam) dat->ptFromPoint.x -= (int)lParam;
+ return 0;
+
+ case AAM_PAUSE:
+ dat->bPaused++;
+ return 0;
+
+ case AAM_RESUME:
+ dat->bPaused--;
+ if (dat->bPaused) return 0;
+ if (dat->bPended)
+ {
+ if ( !IMMEDIATE_DRAW )
+ _AniAva_RenderAvatar(dat);
+ }
+ dat->bPended = FALSE;
+ return 0;
+
+ case AAM_STOP:
+ if (dat->bPlaying)
+ {
+ dat->bPlaying = FALSE;
+ KillTimer(hwnd,2);
+ ShowWindow(hwnd, SW_HIDE);
+ }
+ return 0;
+
+ case AAM_SETAVATAR:
+ {
+ ANIAVATARIMAGEINFO *paaii = (ANIAVATARIMAGEINFO*)wParam;
+ _AniAva_Clear_ANIAVA_WINDOWINFO(dat);
+ dat->nFramesCount = paaii->nFramesCount;
+ dat->delaysInterval = paaii->pFrameDelays;
+ dat->sizeAvatar = paaii->szSize;
+ dat->ptFromPoint = paaii->ptImagePos;
+ dat->currentFrame = 0;
+ dat->bPlaying = FALSE;
+ return MAKELONG(dat->sizeAvatar.cx,dat->sizeAvatar.cy);
+ }
+
+ case AAM_SETPOSITION:
+ {
+ ANIAVA_POSINFO * papi = (ANIAVA_POSINFO *)lParam;
+ if ( !dat->delaysInterval) return 0;
+ if ( !papi) return 0;
+ dat->rcPos = papi->rcPos;
+ dat->overlayIconIdx = papi->idxOverlay;
+ dat->bAlpha = papi->bAlpha;
+ free(papi);
+ if ( !dat->bPlaying)
+ {
+ dat->bPlaying = TRUE;
+ ShowWindow(hwnd,SW_SHOWNA);
+ dat->currentFrame = 0;
+ KillTimer(hwnd,2);
+ SetTimer(hwnd,2,dat->delaysInterval[0],NULL);
+ }
+ if ( !IMMEDIATE_DRAW )
+ _AniAva_RenderAvatar(dat);
+ return 0;
+ }
+ case AAM_SETPARENT:
+ if ( IMMEDIATE_DRAW ) return 0;
+ dat->bOrderTop = ((HWND)wParam != GetDesktopWindow());
+ SetParent(hwnd,(HWND)wParam);
+ if (dat->bOrderTop)
+ {
+ SetWindowPos(hwnd,HWND_TOP,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_ASYNCWINDOWPOS);
+ }
+ else
+ {
+ LONG exStyle;
+ exStyle = GetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE);
+ SetWindowPos(pcli->hwndContactList,hwnd,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE/*|SWP_ASYNCWINDOWPOS*/);
+ if ( !(exStyle&WS_EX_TOPMOST))
+ SetWindowPos(pcli->hwndContactList,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE/*|SWP_ASYNCWINDOWPOS*/);
+ }
+ return 0;
+
+ case AAM_REDRAW:
+ if ( IMMEDIATE_DRAW )
+ return 0;
+ if ( wParam )
+ {
+ if (dat->bOrderTop)
+ {
+ SetWindowPos(hwnd,HWND_TOP,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_ASYNCWINDOWPOS);
+ }
+ else
+ {
+ LONG exStyle;
+ exStyle = GetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE);
+ SetWindowPos(pcli->hwndContactList,hwnd,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE/*|SWP_ASYNCWINDOWPOS*/);
+ if ( !(exStyle&WS_EX_TOPMOST))
+ SetWindowPos(pcli->hwndContactList,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE/*|SWP_ASYNCWINDOWPOS*/);
+ }
+ }
+
+ _AniAva_RenderAvatar( dat );
+ return 0;
+
+
+ case AAM_RENDER:
+ {
+ HDC hdc = ( HDC )wParam;
+ RECT* rect = ( RECT* )lParam;
+ _AniAva_RenderAvatar( dat, hdc, rect );
+ }
+ return 0;
+
+ case AAM_SELFDESTROY:
+ return DestroyWindow(hwnd);
+
+ case WM_CREATE:
+ {
+ LONG exStyle;
+ ANIAVA_WINDOWINFO * dat = (ANIAVA_WINDOWINFO *) mir_calloc(sizeof (ANIAVA_WINDOWINFO));
+ SetWindowLongPtr(hwnd,GWLP_USERDATA,(LONG_PTR)dat);
+ dat->hWindow = hwnd;
+ //ShowWindow(dat->hWindow,SW_SHOW);
+ //change layered mode
+ exStyle = GetWindowLongPtr(dat->hWindow,GWL_EXSTYLE);
+ exStyle |= WS_EX_LAYERED;
+ SetWindowLongPtr(dat->hWindow,GWL_EXSTYLE,exStyle);
+ exStyle = GetWindowLongPtr(dat->hWindow,GWL_STYLE);
+ exStyle &= ~WS_POPUP;
+ exStyle |= WS_CHILD;
+ SetWindowLongPtr(dat->hWindow,GWL_STYLE,exStyle);
+ break;
+ }
+ case WM_TIMER:
+ {
+ if ( !IsWindowVisible(hwnd))
+ {
+ DestroyWindow(hwnd);
+ return 0;
+ }
+ dat->currentFrame++;
+ if (dat->currentFrame >= dat->nFramesCount)
+ dat->currentFrame = 0;
+
+ if ( !IMMEDIATE_DRAW )
+ _AniAva_RenderAvatar( dat );
+ else
+ _AniAva_InvalidateParent( dat );
+
+ KillTimer(hwnd,2);
+ SetTimer(hwnd,2,dat->delaysInterval[dat->currentFrame]+1,NULL);
+ return 0;
+ }
+ case WM_DESTROY:
+ {
+ _AniAva_Clear_ANIAVA_WINDOWINFO(dat);
+ mir_free(dat);
+ SetWindowLongPtr(hwnd,GWLP_USERDATA,(LONG_PTR)NULL);
+ break;
+ }
+
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+#undef aacheck
+#undef aalock
+#undef aaunlock
+
+/////////////////////////////////////////////////////////////////
+// some stub
+
+HWND WINAPI MyGetAncestor( HWND hWnd, UINT option )
+{
+ if ( option == GA_PARENT )
+ return GetParent( hWnd );
+
+ if ( option == GA_ROOTOWNER ) {
+ HWND result = hWnd;
+ while( true ) {
+ HWND hParent = GetParent( result );
+ if ( !hParent )
+ return result;
+
+ result = hParent;
+ }
+ }
+
+ return NULL;
+}
diff --git a/plugins/Clist_modern/src/modern_awaymsg.cpp b/plugins/Clist_modern/src/modern_awaymsg.cpp
new file mode 100644
index 0000000000..342b3eefad
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_awaymsg.cpp
@@ -0,0 +1,232 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+
+*/
+
+/*
+* Author Artem Shpynov aka FYR
+* Copyright 2000-2008 Artem Shpynov
+*/
+
+//////////////////////////////////////////////////////////////////////////
+// Module to Request Away Messages
+
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_awaymsg.h"
+#include "newpluginapi.h"
+#include "hdr/modern_sync.h"
+
+#define AMASKPERIOD 3000
+#define amlock EnterCriticalSection(&amLockChain)
+#define amunlock LeaveCriticalSection(&amLockChain)
+
+typedef struct _tag_amChainItem {
+ HANDLE hContact;
+ _tag_amChainItem *Next;
+} AMCHAINITEM;
+
+static AMCHAINITEM * amFirstChainItem = NULL;
+static AMCHAINITEM * amLastChainItem = NULL;
+static CRITICAL_SECTION amLockChain;
+static HANDLE hamProcessEvent = NULL;
+static DWORD amRequestTick = 0;
+
+
+static int amAddHandleToChain(HANDLE hContact);
+static HANDLE amGetCurrentChain();
+static int amThreadProc(HWND hwnd);
+
+/*
+* Add contact handle to requests queue
+*/
+static int amAddHandleToChain(HANDLE hContact)
+{
+ AMCHAINITEM * workChain;
+ amlock;
+ {
+ //check that handle is present
+ AMCHAINITEM * wChain;
+ wChain = amFirstChainItem;
+ if (wChain)
+ do {
+ if (wChain->hContact == hContact)
+ {
+ amunlock;
+ return 0;
+ }
+ } while(wChain = (AMCHAINITEM *)wChain->Next);
+ }
+ if ( !amFirstChainItem)
+ {
+ amFirstChainItem = (AMCHAINITEM*)malloc(sizeof(AMCHAINITEM));
+ workChain = amFirstChainItem;
+ }
+ else
+ {
+ amLastChainItem->Next = (AMCHAINITEM*)malloc(sizeof(AMCHAINITEM));
+ workChain = (AMCHAINITEM *)amLastChainItem->Next;
+ }
+ amLastChainItem = workChain;
+ workChain->Next = NULL;
+ workChain->hContact = hContact;
+ amunlock;
+ SetEvent(hamProcessEvent);
+ return 1;
+}
+
+
+/*
+* Gets handle from queue for request
+*/
+static HANDLE amGetCurrentChain()
+{
+ AMCHAINITEM * workChain;
+ HANDLE res = NULL;
+ amlock;
+ if (amFirstChainItem)
+ {
+ res = amFirstChainItem->hContact;
+ workChain = amFirstChainItem->Next;
+ free(amFirstChainItem);
+ amFirstChainItem = (AMCHAINITEM *)workChain;
+ }
+ amunlock;
+ return res;
+}
+
+/*
+* Tread sub to ask protocol to retrieve away message
+*/
+static int amThreadProc(HWND hwnd)
+{
+ DWORD time;
+ HANDLE hContact;
+ HANDLE ACK = 0;
+ displayNameCacheEntry dnce;
+ memset( &dnce, 0, sizeof(dnce));
+
+ while (!MirandaExiting())
+ {
+ hContact = amGetCurrentChain();
+ while (hContact)
+ {
+ time = GetTickCount();
+ if ((time-amRequestTick) < AMASKPERIOD)
+ {
+ SleepEx(AMASKPERIOD-(time-amRequestTick)+10,TRUE);
+ if (MirandaExiting())
+ {
+ g_dwAwayMsgThreadID = 0;
+ return 0;
+ }
+ }
+ CListSettings_FreeCacheItemData(&dnce);
+ dnce.hContact = (HANDLE)hContact;
+ Sync(CLUI_SyncGetPDNCE, (WPARAM) 0,(LPARAM)&dnce);
+ if (dnce.ApparentMode != ID_STATUS_OFFLINE) //don't ask if contact is always invisible (should be done with protocol)
+ ACK = (HANDLE)CallContactService(hContact,PSS_GETAWAYMSG,0,0);
+ if ( !ACK)
+ {
+ ACKDATA ack;
+ ack.hContact = hContact;
+ ack.type = ACKTYPE_AWAYMSG;
+ ack.result = ACKRESULT_FAILED;
+ if (dnce.m_cache_cszProto)
+ ack.szModule = dnce.m_cache_cszProto;
+ else
+ ack.szModule = NULL;
+ ClcDoProtoAck(hContact, &ack);
+ }
+ CListSettings_FreeCacheItemData(&dnce);
+ amRequestTick = time;
+ hContact = amGetCurrentChain();
+ if (hContact)
+ {
+ DWORD i=0;
+ do
+ {
+ i++;
+ SleepEx(50,TRUE);
+ } while (i < AMASKPERIOD/50 && !MirandaExiting());
+ }
+ else break;
+ if (MirandaExiting())
+ {
+ g_dwAwayMsgThreadID = 0;
+ return 0;
+ }
+ }
+ WaitForSingleObjectEx(hamProcessEvent, INFINITE, TRUE);
+ ResetEvent(hamProcessEvent);
+ if (MirandaExiting())
+ {
+ g_dwAwayMsgThreadID = 0;
+ return 0;
+ }
+ }
+ g_dwAwayMsgThreadID = 0;
+ return 1;
+}
+
+BOOL amWakeThread()
+{
+ if (hamProcessEvent && g_dwAwayMsgThreadID)
+ {
+ SetEvent(hamProcessEvent);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+* Sub to be called outside on status changing to retrieve away message
+*/
+void amRequestAwayMsg(HANDLE hContact)
+{
+ char *szProto;
+ if ( !g_CluiData.bInternalAwayMsgDiscovery || !hContact)
+ return;
+ //Do not re-ask for chat rooms
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (szProto == NULL || db_get_b(hContact, szProto, "ChatRoom", 0) != 0)
+ return;
+ amAddHandleToChain(hContact);
+}
+
+void InitAwayMsgModule()
+{
+ InitializeCriticalSection(&amLockChain);
+ hamProcessEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
+ g_dwAwayMsgThreadID = (DWORD)mir_forkthread((pThreadFunc)amThreadProc,0);
+}
+
+void UninitAwayMsgModule()
+{
+ SetEvent(hamProcessEvent);
+ CloseHandle(hamProcessEvent);
+ amlock;
+ while (amGetCurrentChain());
+ amunlock;
+ DeleteCriticalSection(&amLockChain);
+}
diff --git a/plugins/Clist_modern/src/modern_cachefuncs.cpp b/plugins/Clist_modern/src/modern_cachefuncs.cpp
new file mode 100644
index 0000000000..2a14c77224
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_cachefuncs.cpp
@@ -0,0 +1,968 @@
+/* CODE STYLE */
+
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+
+Created by Pescuma
+Modified by FYR
+
+*/
+
+/************************************************************************/
+/* Module for working with lines text and avatars */
+/************************************************************************/
+
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_cache_funcs.h"
+#include "newpluginapi.h"
+#include "./hdr/modern_gettextasync.h"
+#include "hdr/modern_sync.h"
+
+typedef BOOL (* ExecuteOnAllContactsFuncPtr) (struct ClcContact *contact, BOOL subcontact, void *param);
+
+
+/***********************************/
+/** Module static declarations **/
+/***********************************/
+
+/* Module Static Prototypes */
+
+static int CopySkipUnprintableChars(TCHAR *to, TCHAR * buf, DWORD size);
+
+static BOOL ExecuteOnAllContacts(struct ClcData *dat, ExecuteOnAllContactsFuncPtr func, void *param);
+static BOOL ExecuteOnAllContactsOfGroup(struct ClcGroup *group, ExecuteOnAllContactsFuncPtr func, void *param);
+int CLUI_SyncGetShortData(WPARAM wParam, LPARAM lParam);
+void CListSettings_FreeCacheItemData(pdisplayNameCacheEntry pDst);
+void CListSettings_FreeCacheItemDataOption( pdisplayNameCacheEntry pDst, DWORD flag );
+/*
+* Get time zone for contact
+*/
+void Cache_GetTimezone(struct ClcData *dat, HANDLE hContact)
+{
+ PDNCE pdnce = (PDNCE)pcli->pfnGetCacheEntry(hContact);
+ if (dat == NULL && pcli->hwndContactTree)
+ dat = (struct ClcData *)GetWindowLongPtr(pcli->hwndContactTree,0);
+
+ if (dat && dat->hWnd == pcli->hwndContactTree) {
+ DWORD flags = dat->contact_time_show_only_if_different ? TZF_DIFONLY : 0;
+ pdnce->hTimeZone = tmi.createByContact ? tmi.createByContact(hContact, flags) : 0;
+ }
+}
+
+/*
+* Get all lines of text
+*/
+
+void Cache_GetText(struct ClcData *dat, struct ClcContact *contact, BOOL forceRenew)
+{
+ Cache_GetFirstLineText(dat, contact);
+ if ( !dat->force_in_dialog) {
+ PDNCE pdnce = (PDNCE)pcli->pfnGetCacheEntry(contact->hContact);
+
+ if ((dat->second_line_show && (forceRenew || pdnce->szSecondLineText == NULL)) || (dat->third_line_show && (forceRenew || pdnce->szThirdLineText == NULL)))
+ gtaAddRequest(dat,contact, contact->hContact);
+ }
+}
+
+void CSmileyString::AddListeningToIcon(struct SHORTDATA *dat, pdisplayNameCacheEntry pdnce, TCHAR *szText, BOOL replace_smileys)
+{
+ iMaxSmileyHeight = 0;
+ DestroySmileyList();
+
+ if (szText == NULL) return;
+
+ int text_size = (int)_tcslen( szText );
+
+ plText = List_Create( 0, 1 );
+
+ // Add Icon
+ {
+ BITMAP bm;
+
+ ICONINFO icon;
+ ClcContactTextPiece *piece = (ClcContactTextPiece *) mir_alloc(sizeof(ClcContactTextPiece));
+
+ piece->type = TEXT_PIECE_TYPE_SMILEY;
+ piece->len = 0;
+ piece->smiley = g_hListeningToIcon;
+
+ piece->smiley_width = 16;
+ piece->smiley_height = 16;
+ if (GetIconInfo(piece->smiley, &icon)) {
+ if (GetObject(icon.hbmColor,sizeof(BITMAP),&bm)) {
+ piece->smiley_width = bm.bmWidth;
+ piece->smiley_height = bm.bmHeight;
+ }
+
+ DeleteObject(icon.hbmMask);
+ DeleteObject(icon.hbmColor);
+ }
+
+ dat->text_smiley_height = max(piece->smiley_height, dat->text_smiley_height);
+ iMaxSmileyHeight = max(piece->smiley_height, iMaxSmileyHeight);
+
+ List_Insert( plText, piece, plText->realCount);
+ }
+
+ // Add text
+ {
+ ClcContactTextPiece *piece = (ClcContactTextPiece *) mir_alloc(sizeof(ClcContactTextPiece));
+
+ piece->type = TEXT_PIECE_TYPE_TEXT;
+ piece->start_pos = 0;
+ piece->len = text_size;
+ List_Insert( plText, piece, plText->realCount);
+ }
+}
+
+void CSmileyString::_CopySmileyList( SortedList *plInput )
+{
+ // ASSERT( plText == NULL );
+
+ if ( !plInput || plInput->realCount == 0 ) return;
+ plText = List_Create( 0, 1 );
+ for ( int i=0; i < plInput->realCount; i++ )
+ {
+ ClcContactTextPiece *pieceFrom = (ClcContactTextPiece *) plInput->items[i];
+ if ( pieceFrom != NULL )
+ {
+ ClcContactTextPiece *piece = (ClcContactTextPiece *) mir_alloc( sizeof(ClcContactTextPiece));
+ *piece = *pieceFrom;
+ if ( pieceFrom->type == TEXT_PIECE_TYPE_SMILEY)
+ piece->smiley = CopyIcon( pieceFrom->smiley );
+ List_Insert( plText, piece, plText->realCount );
+ }
+ }
+}
+
+void CSmileyString::DestroySmileyList()
+{
+ //ASSERT( plText == NULL );
+
+ if ( plText == NULL ) return;
+
+ if ( IsBadReadPtr( plText, sizeof(SortedList))) {
+ plText = NULL;
+ return;
+ }
+
+ if ( plText->realCount != 0 ) {
+ for ( int i=0 ; i < plText->realCount ; i++ ) {
+ if ( plText->items[i] != NULL ) {
+ ClcContactTextPiece *piece = (ClcContactTextPiece *) plText->items[i];
+
+ if ( !IsBadWritePtr(piece, sizeof(ClcContactTextPiece))) {
+ if (piece->type == TEXT_PIECE_TYPE_SMILEY && piece->smiley != g_hListeningToIcon)
+ DestroyIcon_protect(piece->smiley);
+ mir_free(piece);
+ }
+ }
+ }
+ List_Destroy( plText );
+ }
+ mir_free(plText);
+
+ plText = NULL;
+}
+
+/*
+* Parsing of text for smiley
+*/
+
+void CSmileyString::ReplaceSmileys(struct SHORTDATA *dat, PDNCE pdnce, TCHAR * szText, BOOL replace_smileys)
+{
+ SMADD_BATCHPARSE2 sp = {0};
+ SMADD_BATCHPARSERES *spr;
+
+ int last_pos = 0;
+ iMaxSmileyHeight = 0;
+
+ DestroySmileyList();
+
+ if ( !dat->text_replace_smileys || !replace_smileys || szText == NULL)
+ return;
+
+ int text_size = (int)_tcslen( szText );
+
+ // Call service for the first time to see if needs to be used...
+ sp.cbSize = sizeof(sp);
+
+ if (dat->text_use_protocol_smileys) {
+ sp.Protocolname = pdnce->m_cache_cszProto;
+
+ if (db_get_b(NULL,"CLC","Meta",SETTING_USEMETAICON_DEFAULT) != 1 && pdnce->m_cache_cszProto != NULL && g_szMetaModuleName && strcmp(pdnce->m_cache_cszProto, g_szMetaModuleName) == 0) {
+ HANDLE hContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (LPARAM)pdnce->hContact, 0);
+ if (hContact != 0)
+ sp.Protocolname = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (LPARAM)hContact, 0);
+ }
+ }
+ else sp.Protocolname = "clist";
+
+ sp.str = szText;
+ sp.flag = SAFL_TCHAR;
+
+ spr = (SMADD_BATCHPARSERES*)CallService(MS_SMILEYADD_BATCHPARSE, 0, (LPARAM)&sp);
+
+ // Did not find a simley
+ if (spr == NULL || (INT_PTR)spr == CALLSERVICE_NOTFOUND)
+ return;
+
+ // Lets add smileys
+ plText = List_Create( 0, 1 );
+
+ for (unsigned i=0; i < sp.numSmileys; ++i) {
+ if (spr[i].hIcon != NULL) { // For deffective smileypacks
+ // Add text
+ if (spr[i].startChar - last_pos > 0) {
+ ClcContactTextPiece *piece = (ClcContactTextPiece *) mir_alloc(sizeof(ClcContactTextPiece));
+
+ piece->type = TEXT_PIECE_TYPE_TEXT;
+ piece->start_pos = last_pos ;//sp.str - text;
+ piece->len = spr[i].startChar - last_pos;
+ List_Insert(plText, piece, plText->realCount);
+ }
+
+ // Add smiley
+ {
+ BITMAP bm;
+ ICONINFO icon;
+ ClcContactTextPiece *piece = (ClcContactTextPiece *) mir_alloc(sizeof(ClcContactTextPiece));
+
+ piece->type = TEXT_PIECE_TYPE_SMILEY;
+ piece->len = spr[i].size;
+ piece->smiley = spr[i].hIcon;
+
+ piece->smiley_width = 16;
+ piece->smiley_height = 16;
+ if (GetIconInfo(piece->smiley, &icon)) {
+ if (GetObject(icon.hbmColor,sizeof(BITMAP),&bm)) {
+ piece->smiley_width = bm.bmWidth;
+ piece->smiley_height = bm.bmHeight;
+ }
+
+ DeleteObject(icon.hbmMask);
+ DeleteObject(icon.hbmColor);
+ }
+
+ dat->text_smiley_height = max( piece->smiley_height, dat->text_smiley_height );
+ iMaxSmileyHeight = max( piece->smiley_height, iMaxSmileyHeight );
+
+ List_Insert(plText, piece, plText->realCount);
+ }
+ }
+ // Get next
+ last_pos = spr[i].startChar + spr[i].size;
+ }
+ CallService(MS_SMILEYADD_BATCHFREE, 0, (LPARAM)spr);
+
+ // Add rest of text
+ if (last_pos < text_size) {
+ ClcContactTextPiece *piece = (ClcContactTextPiece *) mir_alloc(sizeof(ClcContactTextPiece));
+
+ piece->type = TEXT_PIECE_TYPE_TEXT;
+ piece->start_pos = last_pos;
+ piece->len = text_size-last_pos;
+
+ List_Insert(plText, piece, plText->realCount);
+ }
+}
+
+/*
+* Getting Status name
+* -1 for XStatus, 1 for Status
+*/
+int GetStatusName(TCHAR *text, int text_size, PDNCE pdnce, BOOL xstatus_has_priority)
+{
+ BOOL noAwayMsg = FALSE;
+ BOOL noXstatus = FALSE;
+ // Hide status text if Offline /// no offline
+ WORD nStatus = pdnce___GetStatus( pdnce );
+ if ((nStatus == ID_STATUS_OFFLINE || nStatus == 0) && g_CluiData.bRemoveAwayMessageForOffline) noAwayMsg = TRUE;
+ if (nStatus == ID_STATUS_OFFLINE || nStatus == 0) noXstatus = TRUE;
+ text[0] = '\0';
+ // Get XStatusName
+ if ( !noAwayMsg && !noXstatus && xstatus_has_priority && pdnce->hContact && pdnce->m_cache_cszProto) {
+ DBVARIANT dbv = {0};
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusName", &dbv)) {
+ //lstrcpyn(text, dbv.pszVal, text_size);
+ CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1);
+ db_free(&dbv);
+
+ if (text[0] != '\0')
+ return -1;
+ }
+ }
+
+ // Get Status name
+ {
+ TCHAR *tmp = (TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)nStatus, GSMDF_TCHAR_MY);
+ lstrcpyn(text, tmp, text_size);
+ //CopySkipUnprintableChars(text, dbv.pszVal, text_size-1);
+ if (text[0] != '\0')
+ return 1;
+ }
+
+ // Get XStatusName
+ if ( !noAwayMsg && !noXstatus && !xstatus_has_priority && pdnce->hContact && pdnce->m_cache_cszProto) {
+ DBVARIANT dbv = {0};
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusName", &dbv)) {
+ //lstrcpyn(text, dbv.pszVal, text_size);
+ CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1);
+ db_free(&dbv);
+
+ if (text[0] != '\0')
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+/*
+* Get Listening to information
+*/
+
+void GetListeningTo(TCHAR *text, int text_size, PDNCE pdnce)
+{
+ DBVARIANT dbv = {0};
+ WORD wStatus = pdnce___GetStatus( pdnce );
+ text[0] = _T('\0');
+
+ if (wStatus == ID_STATUS_OFFLINE || wStatus == 0)
+ return;
+
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "ListeningTo", &dbv)) {
+ CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1);
+ db_free(&dbv);
+ }
+}
+
+/*
+* Getting Status message (Away message)
+* -1 for XStatus, 1 for Status
+*/
+
+int GetStatusMessage(TCHAR *text, int text_size, PDNCE pdnce, BOOL xstatus_has_priority)
+{
+ DBVARIANT dbv = {0};
+ BOOL noAwayMsg = FALSE;
+ WORD wStatus = pdnce___GetStatus( pdnce );
+ text[0] = '\0';
+ // Hide status text if Offline /// no offline
+
+ if (wStatus == ID_STATUS_OFFLINE || wStatus == 0) noAwayMsg = TRUE;
+ // Get XStatusMsg
+ if ( !noAwayMsg && xstatus_has_priority && pdnce->hContact && pdnce->m_cache_cszProto) {
+ // Try to get XStatusMsg
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusMsg", &dbv)) {
+ //lstrcpyn(text, dbv.pszVal, text_size);
+ CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1);
+ db_free(&dbv);
+
+ if (text[0] != '\0')
+ return -1;
+ }
+ }
+
+ // Get StatusMsg
+ if (pdnce->hContact && text[0] == '\0') {
+ if ( !DBGetContactSettingTString(pdnce->hContact, "CList", "StatusMsg", &dbv)) {
+ //lstrcpyn(text, dbv.pszVal, text_size);
+ CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1);
+ db_free(&dbv);
+
+ if (text[0] != '\0')
+ return 1;
+ }
+ }
+
+ // Get XStatusMsg
+ if ( !noAwayMsg && !xstatus_has_priority && pdnce->hContact && pdnce->m_cache_cszProto && text[0] == '\0') {
+ // Try to get XStatusMsg
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusMsg", &dbv)) {
+ //lstrcpyn(text, dbv.pszVal, text_size);
+ CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1);
+ db_free(&dbv);
+
+ if (text[0] != '\0')
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+
+/*
+* Get the text for specified lines
+*/
+int Cache_GetLineText(PDNCE pdnce, int type, LPTSTR text, int text_size, TCHAR *variable_text, BOOL xstatus_has_priority,
+ BOOL show_status_if_no_away, BOOL show_listening_if_no_away, BOOL use_name_and_message_for_xstatus,
+ BOOL pdnce_time_show_only_if_different)
+{
+ text[0] = '\0';
+ switch(type) {
+ case TEXT_STATUS:
+ if (GetStatusName(text, text_size, pdnce, xstatus_has_priority) == -1 && use_name_and_message_for_xstatus) {
+ DBVARIANT dbv = {0};
+
+ // Try to get XStatusMsg
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusMsg", &dbv)) {
+ if (dbv.ptszVal != NULL && dbv.ptszVal[0] != 0) {
+ TCHAR *tmp = NEWTSTR_ALLOCA(text);
+ mir_sntprintf(text, text_size, _T("%s: %s"), tmp, dbv.ptszVal);
+ CopySkipUnprintableChars(text, text, text_size-1);
+ }
+ db_free(&dbv);
+ }
+ }
+
+ return TEXT_STATUS;
+
+ case TEXT_NICKNAME:
+ if (pdnce->hContact && pdnce->m_cache_cszProto) {
+ DBVARIANT dbv = {0};
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "Nick", &dbv)) {
+ lstrcpyn(text, dbv.ptszVal, text_size);
+ db_free(&dbv);
+ CopySkipUnprintableChars(text, text, text_size-1);
+ }
+ }
+
+ return TEXT_NICKNAME;
+
+ case TEXT_STATUS_MESSAGE:
+ if (GetStatusMessage(text, text_size, pdnce, xstatus_has_priority) == -1 && use_name_and_message_for_xstatus) {
+ DBVARIANT dbv = {0};
+
+ // Try to get XStatusName
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusName", &dbv)) {
+ if (dbv.pszVal != NULL && dbv.pszVal[0] != 0) {
+ TCHAR *tmp = NEWTSTR_ALLOCA(text);
+ mir_sntprintf(text, text_size, _T("%s: %s"), dbv.pszVal, tmp);
+ }
+ CopySkipUnprintableChars(text, text, text_size-1);
+ db_free(&dbv);
+ }
+ }
+ else if (use_name_and_message_for_xstatus && xstatus_has_priority) {
+ DBVARIANT dbv = {0};
+ // Try to get XStatusName
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusName", &dbv)) {
+ if (dbv.pszVal != NULL && dbv.pszVal[0] != 0)
+ mir_sntprintf(text, text_size, _T("%s"), dbv.pszVal);
+ CopySkipUnprintableChars(text, text, text_size-1);
+ db_free(&dbv);
+ }
+ }
+
+ if (text[0] == '\0') {
+ if (show_listening_if_no_away) {
+ Cache_GetLineText(pdnce, TEXT_LISTENING_TO, text, text_size, variable_text, xstatus_has_priority, 0, 0, use_name_and_message_for_xstatus, pdnce_time_show_only_if_different);
+ if (text[0] != '\0')
+ return TEXT_LISTENING_TO;
+ }
+
+ if (show_status_if_no_away) {
+ //re-request status if no away
+ return Cache_GetLineText(pdnce, TEXT_STATUS, text, text_size, variable_text, xstatus_has_priority, 0, 0, use_name_and_message_for_xstatus, pdnce_time_show_only_if_different);
+ }
+ }
+ return TEXT_STATUS_MESSAGE;
+
+ case TEXT_LISTENING_TO:
+ GetListeningTo(text, text_size, pdnce);
+ return TEXT_LISTENING_TO;
+
+ case TEXT_TEXT:
+ {
+ TCHAR *tmp = variables_parsedup(variable_text, pdnce->tszName, pdnce->hContact);
+ lstrcpyn(text, tmp, text_size);
+ mir_free(tmp);
+ CopySkipUnprintableChars(text, text, text_size-1);
+ }
+ return TEXT_TEXT;
+
+ case TEXT_CONTACT_TIME:
+ if (pdnce->hTimeZone) {
+ // Get pdnce time
+ text[0] = 0;
+ tmi.printDateTime( pdnce->hTimeZone, _T("t"), text, text_size, 0);
+ }
+
+ return TEXT_CONTACT_TIME;
+ }
+
+ return TEXT_EMPTY;
+}
+
+/*
+* Get the text for First Line
+*/
+void Cache_GetFirstLineText(struct ClcData *dat, struct ClcContact *contact)
+{
+ if (GetCurrentThreadId() != g_dwMainThreadID)
+ return;
+
+ PDNCE pdnce = (PDNCE)pcli->pfnGetCacheEntry(contact->hContact);
+ TCHAR *name = pcli->pfnGetContactDisplayName(contact->hContact,0);
+ if (dat->first_line_append_nick && (!dat->force_in_dialog)) {
+ DBVARIANT dbv = {0};
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "Nick", &dbv)) {
+ TCHAR nick[SIZEOF(contact->szText)];
+ lstrcpyn(nick, dbv.ptszVal, SIZEOF(contact->szText));
+ db_free(&dbv);
+
+ // They are the same -> use the name to keep the case
+ if (_tcsicmp(name, nick) == 0)
+ lstrcpyn(contact->szText, name, SIZEOF(contact->szText));
+ else
+ // Append then
+ mir_sntprintf(contact->szText, SIZEOF(contact->szText), _T("%s - %s"), name, nick);
+ }
+ else lstrcpyn(contact->szText, name, SIZEOF(contact->szText));
+ }
+ else lstrcpyn(contact->szText, name, SIZEOF(contact->szText));
+
+ if ( !dat->force_in_dialog) {
+ struct SHORTDATA data = {0};
+ Sync(CLUI_SyncGetShortData,(WPARAM)pcli->hwndContactTree,(LPARAM)&data);
+ contact->ssText.ReplaceSmileys(&data, pdnce, contact->szText, dat->first_line_draw_smileys);
+ }
+}
+
+/*
+* Get the text for Second Line
+*/
+
+void Cache_GetSecondLineText(struct SHORTDATA *dat, PDNCE pdnce)
+{
+ TCHAR Text[240-MAXEXTRACOLUMNS] = {0};
+ int type = TEXT_EMPTY;
+
+ if (dat->second_line_show)
+ type = Cache_GetLineText(pdnce, dat->second_line_type, (TCHAR*)Text, SIZEOF(Text), dat->second_line_text,
+ dat->second_line_xstatus_has_priority,dat->second_line_show_status_if_no_away,dat->second_line_show_listening_if_no_away,
+ dat->second_line_use_name_and_message_for_xstatus, dat->contact_time_show_only_if_different);
+ Text[SIZEOF(Text)-1] = 0; //to be sure that it is null terminated string
+
+ mir_free(pdnce->szSecondLineText);
+
+ if (dat->second_line_show)// Text[0] != '\0')
+ pdnce->szSecondLineText = mir_tstrdup((TCHAR*)Text);
+ else
+ pdnce->szSecondLineText = NULL;
+
+ if (pdnce->szSecondLineText) {
+ if (type == TEXT_LISTENING_TO && pdnce->szSecondLineText[0] != _T('\0'))
+ pdnce->ssSecondLine.AddListeningToIcon(dat, pdnce, pdnce->szSecondLineText, dat->second_line_draw_smileys);
+ else
+ pdnce->ssSecondLine.ReplaceSmileys(dat, pdnce, pdnce->szSecondLineText, dat->second_line_draw_smileys);
+ }
+}
+
+/*
+* Get the text for Third Line
+*/
+void Cache_GetThirdLineText(struct SHORTDATA *dat, PDNCE pdnce)
+{
+ TCHAR Text[240-MAXEXTRACOLUMNS] = {0};
+ int type = TEXT_EMPTY;
+ if (dat->third_line_show)
+ type = Cache_GetLineText(pdnce, dat->third_line_type,(TCHAR*)Text, SIZEOF(Text), dat->third_line_text,
+ dat->third_line_xstatus_has_priority,dat->third_line_show_status_if_no_away,dat->third_line_show_listening_if_no_away,
+ dat->third_line_use_name_and_message_for_xstatus, dat->contact_time_show_only_if_different);
+
+ Text[SIZEOF(Text)-1] = 0; //to be sure that it is null terminated string
+
+ mir_free(pdnce->szThirdLineText);
+
+ if (dat->third_line_show)//Text[0] != '\0')
+ pdnce->szThirdLineText = mir_tstrdup((TCHAR*)Text);
+ else
+ pdnce->szThirdLineText = NULL;
+
+ if (pdnce->szThirdLineText) {
+ if (type == TEXT_LISTENING_TO && pdnce->szThirdLineText[0] != _T('\0'))
+ pdnce->ssThirdLine.AddListeningToIcon(dat, pdnce, pdnce->szThirdLineText, dat->third_line_draw_smileys);
+ else
+ pdnce->ssThirdLine.ReplaceSmileys(dat, pdnce, pdnce->szThirdLineText, dat->third_line_draw_smileys);
+ }
+}
+
+void RemoveTag(TCHAR *to, TCHAR *tag)
+{
+ TCHAR * st = to;
+ int len = (int)_tcslen(tag);
+ int lastsize = (int)_tcslen(to)+1;
+ while (st = _tcsstr(st,tag)) {
+ lastsize -= len;
+ memmove((void*)st,(void*)(st+len),(lastsize)*sizeof(TCHAR));
+ }
+}
+
+/*
+* Copy string with removing Escape chars from text
+* And BBcodes
+*/
+static int CopySkipUnprintableChars(TCHAR *to, TCHAR * buf, DWORD size)
+{
+ DWORD i;
+ BOOL keep = 0;
+ TCHAR * cp = to;
+ if ( !to) return 0;
+ if ( !buf) {
+ to[0] = '\0';
+ return 0;
+ }
+
+ for (i=0; i < size; i++) {
+ if (buf[i] == 0) break;
+ if (buf[i] > 0 && buf[i] < ' ') {
+ *cp = ' ';
+ if ( !keep) cp++;
+ keep = 1;
+ }
+ else {
+ keep = 0;
+ *cp = buf[i];
+ cp++;
+ }
+ }
+ *cp = 0;
+
+ //remove bbcodes: [b] [i] [u] <b> <i> <u>
+ RemoveTag(to,_T("[b]")); RemoveTag(to,_T("[/b]"));
+ RemoveTag(to,_T("[u]")); RemoveTag(to,_T("[/u]"));
+ RemoveTag(to,_T("[i]")); RemoveTag(to,_T("[/i]"));
+
+ RemoveTag(to,_T("<b>")); RemoveTag(to,_T("</b>"));
+ RemoveTag(to,_T("<u>")); RemoveTag(to,_T("</u>"));
+ RemoveTag(to,_T("<i>")); RemoveTag(to,_T("</i>"));
+
+ RemoveTag(to,_T("[B]")); RemoveTag(to,_T("[/b]"));
+ RemoveTag(to,_T("[U]")); RemoveTag(to,_T("[/u]"));
+ RemoveTag(to,_T("[I]")); RemoveTag(to,_T("[/i]"));
+
+ RemoveTag(to,_T("<B>")); RemoveTag(to,_T("</B>"));
+ RemoveTag(to,_T("<U>")); RemoveTag(to,_T("</U>"));
+ RemoveTag(to,_T("<I>")); RemoveTag(to,_T("</I>"));
+ return i;
+}
+
+// If ExecuteOnAllContactsFuncPtr returns FALSE, stop loop
+// Return TRUE if finished, FALSE if was stoped
+static BOOL ExecuteOnAllContacts(struct ClcData *dat, ExecuteOnAllContactsFuncPtr func, void *param)
+{
+ BOOL res;
+ res = ExecuteOnAllContactsOfGroup(&dat->list, func, param);
+ return res;
+}
+
+static BOOL ExecuteOnAllContactsOfGroup(struct ClcGroup *group, ExecuteOnAllContactsFuncPtr func, void *param)
+{
+ if ( !group)
+ return TRUE;
+
+ for (int scanIndex = 0 ; scanIndex < group->cl.count ; scanIndex++) {
+ if (group->cl.items[scanIndex]->type == CLCIT_CONTACT) {
+ if ( !func(group->cl.items[scanIndex], FALSE, param))
+ return FALSE;
+
+ if (group->cl.items[scanIndex]->SubAllocated > 0) {
+ for (int i=0 ; i < group->cl.items[scanIndex]->SubAllocated ; i++)
+ if ( !func(&group->cl.items[scanIndex]->subcontacts[i], TRUE, param))
+ return FALSE;
+ }
+ }
+ else if (group->cl.items[scanIndex]->type == CLCIT_GROUP)
+ if ( !ExecuteOnAllContactsOfGroup(group->cl.items[scanIndex]->group, func, param))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+* Avatar working routines
+*/
+BOOL UpdateAllAvatarsProxy(struct ClcContact *contact, BOOL subcontact, void *param)
+{
+ Cache_GetAvatar((struct ClcData *)param, contact);
+ return TRUE;
+}
+
+void UpdateAllAvatars(struct ClcData *dat)
+{
+ ExecuteOnAllContacts(dat,UpdateAllAvatarsProxy,dat);
+}
+
+BOOL ReduceAvatarPosition(struct ClcContact *contact, BOOL subcontact, void *param)
+{
+ if (contact->avatar_pos >= *((int *)param))
+ contact->avatar_pos--;
+
+ return TRUE;
+}
+
+void Cache_ProceedAvatarInList(struct ClcData *dat, struct ClcContact *contact)
+{
+ struct avatarCacheEntry * ace = contact->avatar_data;
+ int old_pos = contact->avatar_pos;
+
+ if (ace == NULL || ace->dwFlags == AVS_BITMAP_EXPIRED || ace->hbmPic == NULL) {
+ //Avatar was not ready or removed - need to remove it from cache
+ if (old_pos >= 0) {
+ ImageArray_RemoveImage(&dat->avatar_cache, old_pos);
+ // Update all items
+ ExecuteOnAllContacts(dat, ReduceAvatarPosition, (void *)&old_pos);
+ contact->avatar_pos = AVATAR_POS_DONT_HAVE;
+ return;
+ }
+ }
+ else if (contact->avatar_data->hbmPic != NULL) //Lets Add it
+ {
+ // Make bounds -> keep aspect radio
+ LONG width_clip;
+ LONG height_clip;
+ RECT rc = {0};
+
+ // Clipping width and height
+ width_clip = dat->avatars_maxwidth_size?dat->avatars_maxwidth_size:dat->avatars_maxheight_size;
+ height_clip = dat->avatars_maxheight_size;
+
+ if (height_clip * ace->bmWidth / ace->bmHeight <= width_clip)
+ width_clip = height_clip * ace->bmWidth / ace->bmHeight;
+ else
+ height_clip = width_clip * ace->bmHeight / ace->bmWidth;
+
+ if (wildcmpi(contact->avatar_data->szFilename,_T("*.gif"))) {
+ if (old_pos == AVATAR_POS_ANIMATED)
+ AniAva_RemoveAvatar(contact->hContact);
+
+ int res = AniAva_AddAvatar(contact->hContact, contact->avatar_data->szFilename, width_clip, height_clip);
+ if (res) {
+ contact->avatar_pos = AVATAR_POS_ANIMATED;
+ contact->avatar_size.cy = HIWORD(res);
+ contact->avatar_size.cx = LOWORD(res);
+ return;
+ }
+ }
+
+ // Create objs
+ void * pt;
+ HDC hdc = CreateCompatibleDC(dat->avatar_cache.hdc);
+ HBITMAP hDrawBmp = ske_CreateDIB32Point(width_clip, height_clip,&pt);
+ HBITMAP oldBmp = (HBITMAP)SelectObject(hdc, hDrawBmp);
+ //need to draw avatar bitmap here
+ {
+ RECT real_rc = {0,0,width_clip, height_clip};
+
+ int w = width_clip;
+ int h = height_clip;
+ if ( !g_CluiData.fGDIPlusFail) //Use gdi+ engine
+ DrawAvatarImageWithGDIp(hdc, 0, 0, w, h,ace->hbmPic,0,0,ace->bmWidth,ace->bmHeight,ace->dwFlags,255);
+ else {
+ if ( !(ace->dwFlags & AVS_PREMULTIPLIED)) {
+ HDC hdcTmp = CreateCompatibleDC(hdc);
+ RECT r = {0,0,w,h};
+ HDC hdcTmp2 = CreateCompatibleDC(hdc);
+ HBITMAP bmo = (HBITMAP)SelectObject(hdcTmp,ace->hbmPic);
+ HBITMAP b2 = ske_CreateDIB32(w,h);
+ HBITMAP bmo2 = (HBITMAP)SelectObject(hdcTmp2,b2);
+ SetStretchBltMode(hdcTmp, HALFTONE);
+ SetStretchBltMode(hdcTmp2, HALFTONE);
+ StretchBlt(hdcTmp2, 0, 0, w, h,
+ hdcTmp, 0, 0, ace->bmWidth, ace->bmHeight,
+ SRCCOPY);
+
+ ske_SetRectOpaque(hdcTmp2,&r);
+ BitBlt(hdc, rc.left, rc.top, w, h,hdcTmp2,0,0,SRCCOPY);
+ SelectObject(hdcTmp2,bmo2);
+ SelectObject(hdcTmp,bmo);
+ mod_DeleteDC(hdcTmp);
+ mod_DeleteDC(hdcTmp2);
+ DeleteObject(b2);
+ }
+ else {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0,255, AC_SRC_ALPHA };
+ HDC hdcTempAv = CreateCompatibleDC(hdc);
+ HBITMAP hbmTempAvOld;
+ hbmTempAvOld = (HBITMAP)SelectObject(hdcTempAv,ace->hbmPic);
+ ske_AlphaBlend(hdc, rc.left, rc.top, w, h, hdcTempAv, 0, 0,ace->bmWidth,ace->bmHeight, bf);
+ SelectObject(hdcTempAv, hbmTempAvOld);
+ mod_DeleteDC(hdcTempAv);
+ }
+ }
+ }
+ SelectObject(hdc,oldBmp);
+ DeleteDC(hdc);
+ // Add to list
+ if (old_pos >= 0) {
+ ImageArray_ChangeImage(&dat->avatar_cache, hDrawBmp, old_pos);
+ contact->avatar_pos = old_pos;
+ }
+ else contact->avatar_pos = ImageArray_AddImage(&dat->avatar_cache, hDrawBmp, -1);
+
+ if (old_pos == AVATAR_POS_ANIMATED && contact->avatar_pos != AVATAR_POS_ANIMATED)
+ AniAva_RemoveAvatar(contact->hContact);
+
+ DeleteObject(hDrawBmp);
+ }
+}
+
+void Cache_GetAvatar(struct ClcData *dat, struct ClcContact *contact)
+{
+ int old_pos = contact->avatar_pos;
+ if (g_CluiData.bSTATE != STATE_NORMAL
+ || (dat->use_avatar_service && !ServiceExists(MS_AV_GETAVATARBITMAP))) // workaround for avatar service and other wich destroys service on OK_TOEXIT
+ {
+ contact->avatar_pos = AVATAR_POS_DONT_HAVE;
+ contact->avatar_data = NULL;
+ return;
+ }
+ if (dat->use_avatar_service && ServiceExists(MS_AV_GETAVATARBITMAP))
+ {
+ if (dat->avatars_show && !db_get_b(contact->hContact, "CList", "HideContactAvatar", 0))
+ {
+ contact->avatar_data = (struct avatarCacheEntry *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)contact->hContact, 0);
+ if (contact->avatar_data == NULL || contact->avatar_data->cbSize != sizeof(struct avatarCacheEntry)
+ || contact->avatar_data->dwFlags == AVS_BITMAP_EXPIRED)
+ {
+ contact->avatar_data = NULL;
+ }
+
+ if (contact->avatar_data != NULL)
+ {
+ contact->avatar_data->t_lastAccess = (DWORD)time(NULL);
+ }
+ }
+ else
+ {
+ contact->avatar_data = NULL;
+ }
+ Cache_ProceedAvatarInList(dat, contact);
+ }
+ else
+ {
+ contact->avatar_pos = AVATAR_POS_DONT_HAVE;
+ if (dat->avatars_show && !db_get_b(contact->hContact, "CList", "HideContactAvatar", 0))
+ {
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingTString(contact->hContact, "ContactPhoto", "File", &dbv))
+ {
+ HBITMAP hBmp = (HBITMAP) CallService(MS_UTILS_LOADBITMAPT, 0, (LPARAM)dbv.ptszVal);
+ if (hBmp != NULL)
+ {
+ // Make bounds
+ BITMAP bm;
+ if (GetObject(hBmp,sizeof(BITMAP),&bm))
+ {
+ // Create data...
+ HDC hdc;
+ HBITMAP hDrawBmp,oldBmp;
+
+ // Make bounds -> keep aspect radio
+ LONG width_clip;
+ LONG height_clip;
+ RECT rc = {0};
+
+ // Clipping width and height
+ width_clip = dat->avatars_maxheight_size;
+ height_clip = dat->avatars_maxheight_size;
+
+ if (height_clip * bm.bmWidth / bm.bmHeight <= width_clip)
+ {
+ width_clip = height_clip * bm.bmWidth / bm.bmHeight;
+ }
+ else
+ {
+ height_clip = width_clip * bm.bmHeight / bm.bmWidth;
+ }
+
+ // Create objs
+ hdc = CreateCompatibleDC(dat->avatar_cache.hdc);
+ hDrawBmp = ske_CreateDIB32(width_clip, height_clip);
+ oldBmp = (HBITMAP)SelectObject(hdc, hDrawBmp);
+ SetBkMode(hdc,TRANSPARENT);
+ {
+ POINT org;
+ GetBrushOrgEx(hdc, &org);
+ SetStretchBltMode(hdc, HALFTONE);
+ SetBrushOrgEx(hdc, org.x, org.y, NULL);
+ }
+
+ rc.right = width_clip - 1;
+ rc.bottom = height_clip - 1;
+
+ // Draw bitmap 8//8
+ {
+ HDC dcMem = CreateCompatibleDC(hdc);
+ HBITMAP obmp = (HBITMAP)SelectObject(dcMem, hBmp);
+ StretchBlt(hdc, 0, 0, width_clip, height_clip,dcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
+ SelectObject(dcMem,obmp);
+ mod_DeleteDC(dcMem);
+ }
+ {
+ RECT rtr = {0};
+ rtr.right = width_clip+1;
+ rtr.bottom = height_clip+1;
+ ske_SetRectOpaque(hdc,&rtr);
+ }
+
+ hDrawBmp = (HBITMAP)GetCurrentObject(hdc, OBJ_BITMAP);
+ SelectObject(hdc,oldBmp);
+ mod_DeleteDC(hdc);
+
+ // Add to list
+ if (old_pos >= 0)
+ {
+ ImageArray_ChangeImage(&dat->avatar_cache, hDrawBmp, old_pos);
+ contact->avatar_pos = old_pos;
+ }
+ else
+ {
+ contact->avatar_pos = ImageArray_AddImage(&dat->avatar_cache, hDrawBmp, -1);
+ }
+
+ DeleteObject(hDrawBmp);
+ } // if (GetObject(hBmp,sizeof(BITMAP),&bm))
+ DeleteObject(hBmp);
+ } //if (hBmp != NULL)
+ }
+ db_free(&dbv);
+ }
+
+ // Remove avatar if needed
+ if (old_pos >= 0 && contact->avatar_pos == AVATAR_POS_DONT_HAVE)
+ {
+ ImageArray_RemoveImage(&dat->avatar_cache, old_pos);
+ // Update all items
+ ExecuteOnAllContacts(dat, ReduceAvatarPosition, (void *)&old_pos);
+ }
+ if (old_pos == AVATAR_POS_ANIMATED && contact->avatar_pos != AVATAR_POS_ANIMATED)
+ {
+ AniAva_RemoveAvatar( contact->hContact );
+ }
+ }
+}
diff --git a/plugins/Clist_modern/src/modern_callproc.cpp b/plugins/Clist_modern/src/modern_callproc.cpp
new file mode 100644
index 0000000000..ab26eb03eb
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_callproc.cpp
@@ -0,0 +1,20 @@
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_callproc.h"
+
+//////////////////////////////////////////////////////////////////////////
+// standard callback proc
+int CALLBACK __DoCallBack( LPARAM pvStorage)
+{
+ call::__baseCall * storage = (call::__baseCall *) pvStorage;
+ int res=storage->__DoCallStorageProc();
+ delete storage;
+ return res;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// To do: Replace __ProcessCall to switching threads etc
+// and specify _DoCallback as callback
+int call::__ProcessCall( __baseCall * pStorage, ASYNC_T async )
+{
+ return __DoCallBack( (LPARAM)pStorage);
+}
diff --git a/plugins/Clist_modern/src/modern_clc.cpp b/plugins/Clist_modern/src/modern_clc.cpp
new file mode 100644
index 0000000000..57d4da274b
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clc.cpp
@@ -0,0 +1,2107 @@
+// refactored step 1.
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+*/
+
+/************************************************************************/
+/* Module responsible for working with contact list control */
+/************************************************************************/
+
+#include "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "m_skin.h"
+#include "hdr/modern_commonprototypes.h"
+
+#include "hdr/modern_clc.h"
+#include "hdr/modern_clist.h"
+#include "hdr/modern_clcpaint.h"
+
+#include "m_modernopt.h"
+
+int ModernOptInit(WPARAM wParam,LPARAM lParam);
+int ModernSkinOptInit(WPARAM wParam,LPARAM lParam);
+
+/*
+* Private module variables
+*/
+static HANDLE hShowInfoTipEvent;
+static POINT HitPoint;
+static BOOL fMouseUpped;
+static BYTE IsDragToScrollMode = 0;
+static int StartDragPos = 0;
+static int StartScrollPos = 0;
+HANDLE hSmileyAddOptionsChangedHook = NULL;
+HANDLE hIconChangedHook = NULL;
+HANDLE hAckHook = NULL;
+HANDLE hAvatarChanged = NULL;
+static BOOL g_bSortTimerIsSet = FALSE;
+static struct ClcContact * hitcontact = NULL;
+
+
+static int clcHookSmileyAddOptionsChanged(WPARAM wParam,LPARAM lParam);
+static int clcHookIconsChanged(WPARAM wParam, LPARAM lParam);
+static int clcHookBkgndConfigChanged(WPARAM wParam,LPARAM lParam);
+static int clcProceedDragToScroll(HWND hwnd, int Y);
+static int clcExitDragToScroll();
+
+
+static int clcHookModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ if (MirandaExiting())
+ return 0;
+
+ HookEvent(ME_MODERNOPT_INITIALIZE,ModernOptInit);
+ HookEvent(ME_MODERNOPT_INITIALIZE,ModernSkinOptInit);
+
+ if (ServiceExists(MS_MC_DISABLEHIDDENGROUP))
+ CallService(MS_MC_DISABLEHIDDENGROUP, (WPARAM)TRUE, (LPARAM)0);
+ if (ServiceExists(MS_MC_GETPROTOCOLNAME))
+ g_szMetaModuleName = (char *)CallService(MS_MC_GETPROTOCOLNAME, 0, 0);
+
+ // Get icons
+ int i;
+
+ TCHAR szMyPath[MAX_PATH];
+ GetModuleFileName(g_hInst, szMyPath, SIZEOF(szMyPath));
+
+ SKINICONDESC sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.cx = 16;
+ sid.cy = 16;
+ sid.ptszDefaultFile = szMyPath;
+ sid.flags = SIDF_PATH_TCHAR;
+
+ sid.pszSection = LPGEN("Contact List");
+ sid.pszDescription = LPGEN("Listening to");
+ sid.pszName = "LISTENING_TO_ICON";
+ sid.iDefaultIndex = - IDI_LISTENING_TO;
+ Skin_AddIcon(&sid);
+
+ sid.pszSection = LPGEN("Contact List/Avatar Overlay");
+ for (i=0; i < MAX_REGS(g_pAvatarOverlayIcons) ; i++) {
+ sid.pszDescription = g_pAvatarOverlayIcons[i].description;
+ sid.pszName = g_pAvatarOverlayIcons[i].name;
+ sid.iDefaultIndex = - g_pAvatarOverlayIcons[i].id;
+ Skin_AddIcon(&sid);
+ }
+
+ sid.pszSection = LPGEN("Contact List/Status Overlay");
+ for (i=0; i < MAX_REGS(g_pStatusOverlayIcons); i++) {
+ sid.pszDescription = g_pStatusOverlayIcons[i].description;
+ sid.pszName = g_pStatusOverlayIcons[i].name;
+ sid.iDefaultIndex = - g_pStatusOverlayIcons[i].id;
+ Skin_AddIcon(&sid);
+ }
+
+ clcHookIconsChanged(0,0);
+
+ hIconChangedHook = HookEvent(ME_SKIN2_ICONSCHANGED, clcHookIconsChanged);
+
+ // Register smiley category
+ if (ServiceExists(MS_SMILEYADD_REGISTERCATEGORY)) {
+ SMADD_REGCAT rc;
+
+ rc.cbSize = sizeof(rc);
+ rc.name = "clist";
+ rc.dispname = Translate("Contact List smileys");
+
+ CallService(MS_SMILEYADD_REGISTERCATEGORY, 0, (LPARAM)&rc);
+
+ hSmileyAddOptionsChangedHook = HookEvent(ME_SMILEYADD_OPTIONSCHANGED,clcHookSmileyAddOptionsChanged);
+ }
+
+ CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"List Background/CLC",0);
+ CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"Menu Background/Menu",0);
+ CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"StatusBar Background/StatusBar",0);
+ CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"Frames TitleBar BackGround/FrameTitleBar",0);
+
+ HookEvent(ME_BACKGROUNDCONFIG_CHANGED,clcHookBkgndConfigChanged);
+ HookEvent(ME_BACKGROUNDCONFIG_CHANGED,BgStatusBarChange);
+ HookEvent(ME_BACKGROUNDCONFIG_CHANGED,OnFrameTitleBarBackgroundChange);
+ HookEvent(ME_COLOUR_RELOAD, OnFrameTitleBarBackgroundChange);
+
+ AniAva_UpdateOptions();
+ return 0;
+}
+
+static int clcHookSmileyAddOptionsChanged(WPARAM wParam,LPARAM lParam)
+{
+ if (MirandaExiting()) return 0;
+ pcli->pfnClcBroadcast( CLM_AUTOREBUILD,0,0);
+ pcli->pfnClcBroadcast( INTM_INVALIDATE,0,0);
+ return 0;
+}
+
+static int clcHookProtoAck(WPARAM wParam,LPARAM lParam)
+{
+ return ClcDoProtoAck((HANDLE) wParam,(ACKDATA*) lParam);
+}
+static int clcHookIconsChanged(WPARAM wParam, LPARAM lParam)
+{
+ int i;
+ if (MirandaExiting()) return 0;
+ for (i=0 ; i < MAX_REGS(g_pAvatarOverlayIcons) ; i++)
+ {
+ g_pAvatarOverlayIcons[i].listID = -1;
+ g_pStatusOverlayIcons[i].listID = -1;
+ }
+ if (hAvatarOverlays) ImageList_Destroy(hAvatarOverlays);
+ hAvatarOverlays = ImageList_Create(16,16,ILC_MASK|ILC_COLOR32,MAX_REGS(g_pAvatarOverlayIcons)*2,1);
+ for (i=0 ; i < MAX_REGS(g_pAvatarOverlayIcons) ; i++)
+ {
+ HICON hIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)g_pAvatarOverlayIcons[i].name);
+ g_pAvatarOverlayIcons[i].listID = ImageList_AddIcon(hAvatarOverlays,hIcon);
+ CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)g_pAvatarOverlayIcons[i].name);
+
+ hIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)g_pStatusOverlayIcons[i].name);
+ g_pStatusOverlayIcons[i].listID = ImageList_AddIcon(hAvatarOverlays,hIcon);
+ CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)g_pStatusOverlayIcons[i].name);
+ }
+
+ g_hListeningToIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"LISTENING_TO_ICON");
+
+ pcli->pfnClcBroadcast( INTM_INVALIDATE,0,0);
+ AniAva_UpdateOptions();
+ return 0;
+}
+
+static int clcHookSettingChanged(WPARAM wParam,LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam;
+ if (MirandaExiting()) return 0;
+ if ((HANDLE)wParam == NULL)
+ {
+ if (g_szMetaModuleName && !mir_strcmp(cws->szModule, g_szMetaModuleName))
+ {
+ if ( !mir_strcmp(cws->szSetting, "Enabled"))
+ pcli->pfnClcBroadcast( INTM_RELOADOPTIONS, wParam, lParam);
+ }
+ else if ( !mir_strcmp(cws->szModule, "CListGroups"))
+ {
+ pcli->pfnClcBroadcast( INTM_GROUPSCHANGED,wParam,lParam);
+ }
+ else if ( !strcmp(cws->szSetting,"XStatusId") || !strcmp(cws->szSetting,"XStatusName"))
+ {
+ CLUIServices_ProtocolStatusChanged(0,(LPARAM)cws->szModule);
+ }
+ }
+ else // (HANDLE)wParam != NULL
+ {
+ if ( !strcmp(cws->szSetting,"TickTS"))
+ {
+ pcli->pfnClcBroadcast( INTM_STATUSCHANGED,wParam,0);
+ }
+ else if (g_szMetaModuleName && !strcmp(cws->szModule,g_szMetaModuleName))
+ {
+ if ( !strcmp(cws->szSetting,"Handle"))
+ {
+ pcli->pfnClcBroadcast( INTM_NAMEORDERCHANGED,0,0);
+ }
+ else if ( !strcmp(cws->szSetting,"Default"))
+ {
+ pcli->pfnClcBroadcast( INTM_NAMEORDERCHANGED,0,0);
+ }
+ }
+ else if ( !strcmp(cws->szModule,"UserInfo"))
+ {
+ if ( !strcmp(cws->szSetting,"Timezone"))
+ pcli->pfnClcBroadcast( INTM_TIMEZONECHANGED,wParam,0);
+ }
+ else if ( !strcmp(cws->szModule,"CList"))
+ {
+ if ( !strcmp(cws->szSetting,"StatusMsg"))
+ pcli->pfnClcBroadcast( INTM_STATUSMSGCHANGED,wParam,0);
+
+ }
+ else if ( !strcmp(cws->szModule,"ContactPhoto"))
+ {
+ if ( !strcmp(cws->szSetting,"File"))
+ pcli->pfnClcBroadcast( INTM_AVATARCHANGED,wParam,0);
+ }
+ else
+ {
+ if ((!strcmp(cws->szSetting,"XStatusName") || !strcmp(cws->szSetting,"XStatusMsg")))
+ pcli->pfnClcBroadcast( INTM_STATUSMSGCHANGED,wParam,0);
+ else if ( !strcmp(cws->szSetting,"XStatusId"))
+ pcli->pfnClcBroadcast( INTM_STATUSCHANGED,wParam,0);
+ else if ( !strcmp(cws->szSetting,"Timezone"))
+ pcli->pfnClcBroadcast( INTM_TIMEZONECHANGED,wParam,0);
+ else if ( !strcmp(cws->szSetting,"ListeningTo"))
+ pcli->pfnClcBroadcast( INTM_STATUSMSGCHANGED,wParam,0);
+ else if ( !strcmp(cws->szSetting,"Transport") || !strcmp(cws->szSetting,"IsTransported")) {
+ pcli->pfnInvalidateDisplayNameCacheEntry((HANDLE)wParam);
+ pcli->pfnClcBroadcast( CLM_AUTOREBUILD,wParam,0);
+ }
+ }
+ }
+ return 0;
+}
+
+static int clcHookDbEventAdded(WPARAM wParam,LPARAM lParam)
+{
+ DBEVENTINFO dbei = {0};
+ g_CluiData.t_now = time(NULL);
+ if (wParam && lParam)
+ {
+ dbei.cbSize = sizeof(dbei);
+ dbei.pBlob = 0;
+ dbei.cbBlob = 0;
+ CallService(MS_DB_EVENT_GET, (WPARAM)lParam, (LPARAM)&dbei);
+ if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT))
+ {
+ PDNCE pdnce = (PDNCE)pcli->pfnGetCacheEntry((HANDLE)wParam);
+ db_set_dw((HANDLE)wParam, "CList", "mf_lastmsg", dbei.timestamp);
+ if (pdnce)
+ pdnce->dwLastMsgTime = dbei.timestamp;
+ }
+ }
+ return 0;
+}
+
+static int clcHookBkgndConfigChanged(WPARAM wParam,LPARAM lParam)
+{
+ pcli->pfnClcOptionsChanged();
+ return 0;
+}
+
+static int clcHookAvatarChanged(WPARAM wParam, LPARAM lParam)
+{
+ if (MirandaExiting()) return 0;
+ pcli->pfnClcBroadcast(INTM_AVATARCHANGED, wParam, lParam);
+ return 0;
+}
+
+static int clcExitDragToScroll()
+{
+ if ( !IsDragToScrollMode) return 0;
+ IsDragToScrollMode = 0;
+ ReleaseCapture();
+ return 1;
+}
+
+static int clcProceedDragToScroll(HWND hwnd, int Y)
+{
+ int pos,dy;
+ if ( !IsDragToScrollMode) return 0;
+ if (GetCapture() != hwnd) clcExitDragToScroll();
+ dy = StartDragPos-Y;
+ pos = StartScrollPos+dy;
+ if (pos < 0)
+ pos = 0;
+ SendMessage(hwnd, WM_VSCROLL,MAKEWPARAM(SB_THUMBTRACK,pos),0);
+ return 1;
+}
+
+
+
+static int clcSearchNextContact(HWND hwnd, struct ClcData *dat, int index, const TCHAR *text, int prefixOk, BOOL fSearchUp)
+{
+ struct ClcGroup *group = &dat->list;
+ int testlen = lstrlen(text);
+ BOOL fReturnAsFound = FALSE;
+ int nLastFound = -1;
+ if (index == -1) fReturnAsFound = TRUE;
+ group->scanIndex = 0;
+ for (;;)
+ {
+ if (group->scanIndex == group->cl.count)
+ {
+ group = group->parent;
+ if (group == NULL)
+ break;
+ group->scanIndex++;
+ continue;
+ }
+ if (group->cl.items[group->scanIndex]->type != CLCIT_DIVIDER)
+ {
+ if ((prefixOk && CSTR_EQUAL == CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, text, -1, group->cl.items[group->scanIndex]->szText, testlen)) ||
+ (!prefixOk && !lstrcmpi(text, group->cl.items[group->scanIndex]->szText)))
+ {
+ struct ClcGroup *contactGroup = group;
+ int contactScanIndex = group->scanIndex;
+ int foundindex;
+ for (; group; group = group->parent)
+ pcli->pfnSetGroupExpand(hwnd, dat, group, 1);
+ foundindex = pcli->pfnGetRowsPriorTo(&dat->list, contactGroup, contactScanIndex);
+ if (fReturnAsFound)
+ return foundindex;
+ else if (nLastFound != -1 && fSearchUp && foundindex == index)
+ return nLastFound;
+ else if ( !fSearchUp && foundindex == index)
+ fReturnAsFound = TRUE;
+ else
+ nLastFound = foundindex;
+ group = contactGroup;
+ group->scanIndex = contactScanIndex;
+ }
+ if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP)
+ {
+ if ( !(dat->exStyle & CLS_EX_QUICKSEARCHVISONLY) || group->cl.items[group->scanIndex]->group->expanded)
+ {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ continue;
+ }
+ }
+ }
+ group->scanIndex++;
+ }
+ return -1;
+}
+
+static BOOL clcItemNotHiddenOffline(struct ClcData * dat, struct ClcGroup* group, struct ClcContact * contact)
+{
+ PDNCE pdnce;
+
+ if ( !group) return FALSE;
+ if ( !contact) return FALSE;
+ if (group->hideOffline) return FALSE;
+ if (g_CluiData.bFilterEffective) return FALSE;
+
+ if (CLCItems_IsShowOfflineGroup(group)) return TRUE;
+
+ pdnce = (PDNCE)pcli->pfnGetCacheEntry( contact->hContact);
+ if ( !pdnce) return FALSE;
+ if (pdnce->m_cache_nNoHiddenOffline) return TRUE;
+
+ return FALSE;
+
+}
+static LRESULT clcOnCreate(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ dat = (struct ClcData*)mir_calloc(sizeof(struct ClcData));
+ SetWindowLongPtr(hwnd,0,(LONG_PTR)dat);
+ dat->hCheckBoxTheme = xpt_AddThemeHandle(hwnd, L"BUTTON");
+ dat->m_paintCouter = 0;
+ dat->hWnd = hwnd;
+ dat->use_avatar_service = ServiceExists(MS_AV_GETAVATARBITMAP);
+ if (dat->use_avatar_service)
+ {
+ if ( !hAvatarChanged)
+ hAvatarChanged = HookEvent(ME_AV_AVATARCHANGED, clcHookAvatarChanged);
+ }
+ //else
+ //{
+ ImageArray_Initialize(&dat->avatar_cache, FALSE, 20); //this array will be used to keep small avatars too
+ //}
+
+ RowHeights_Initialize(dat);
+
+ dat->NeedResort = 1;
+ dat->MetaIgnoreEmptyExtra = db_get_b(NULL,"CLC","MetaIgnoreEmptyExtra",SETTING_METAIGNOREEMPTYEXTRA_DEFAULT);
+
+ dat->IsMetaContactsEnabled = (!(GetWindowLongPtr(hwnd,GWL_STYLE)&CLS_MANUALUPDATE)) &&
+ g_szMetaModuleName && db_get_b(NULL,g_szMetaModuleName,"Enabled",1) && ServiceExists(MS_MC_GETDEFAULTCONTACT);
+
+ dat->expandMeta = db_get_b(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT);
+ dat->useMetaIcon = db_get_b(NULL,"CLC","Meta",SETTING_USEMETAICON_DEFAULT);
+ dat->drawOverlayedStatus = db_get_b(NULL,"CLC","DrawOverlayedStatus",SETTING_DRAWOVERLAYEDSTATUS_DEFAULT);
+ g_CluiData.bSortByOrder[0] = db_get_b(NULL,"CList","SortBy1",SETTING_SORTBY1_DEFAULT);
+ g_CluiData.bSortByOrder[1] = db_get_b(NULL,"CList","SortBy2",SETTING_SORTBY2_DEFAULT);
+ g_CluiData.bSortByOrder[2] = db_get_b(NULL,"CList","SortBy3",SETTING_SORTBY3_DEFAULT);
+ g_CluiData.fSortNoOfflineBottom = db_get_b(NULL,"CList","NoOfflineBottom",SETTING_NOOFFLINEBOTTOM_DEFAULT);
+ dat->menuOwnerID = -1;
+ dat->menuOwnerType = CLCIT_INVALID;
+ //InitDisplayNameCache(&dat->lCLCContactsCache);
+ //LoadCLCOptions(hwnd,dat);
+ corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ LoadCLCOptions(hwnd,dat);
+ if ( dat->contact_time_show || dat->second_line_type == TEXT_CONTACT_TIME || dat->third_line_type == TEXT_CONTACT_TIME )
+ CLUI_SafeSetTimer( hwnd, TIMERID_INVALIDATE, 5000, NULL );
+ else
+ KillTimer( hwnd, TIMERID_INVALIDATE );
+ //if (dat->force_in_dialog)
+ // pcli->pfnRebuildEntireList(hwnd,dat);
+ TRACE("Create New ClistControl TO END\r\n");
+ return 0;
+}
+
+
+
+static LRESULT clcOnHitTest(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ return DefWindowProc(hwnd,WM_NCHITTEST,wParam,lParam);
+}
+static LRESULT clcOnCommand(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct ClcContact *contact;
+ int hit = pcli->pfnGetRowByIndex(dat, dat->selection, &contact, NULL);
+ if (hit == -1) return 0;
+ if ( contact->type == CLCIT_CONTACT && CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM) contact->hContact)) return 0;
+
+ switch (LOWORD(wParam))
+ {
+ case POPUP_NEWSUBGROUP:
+ if (contact->type != CLCIT_GROUP)
+ return 0;
+ SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) & ~CLS_HIDEEMPTYGROUPS);
+ SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) | CLS_USEGROUPS);
+ CallService(MS_CLIST_GROUPCREATE, contact->groupId, 0);
+ return 0;
+ case POPUP_RENAMEGROUP:
+ pcli->pfnBeginRenameSelection(hwnd, dat);
+ return 0;
+ case POPUP_DELETEGROUP:
+ if (contact->type != CLCIT_GROUP)
+ return 0;
+ CallService(MS_CLIST_GROUPDELETE, contact->groupId, 0);
+ return 0;
+ case POPUP_GROUPSHOWOFFLINE:
+ if (contact->type != CLCIT_GROUP)
+ return 0;
+ CallService(MS_CLIST_GROUPSETFLAGS, contact->groupId,
+ MAKELPARAM(CLCItems_IsShowOfflineGroup(contact->group) ? 0 : GROUPF_SHOWOFFLINE, GROUPF_SHOWOFFLINE));
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD,0, 0);
+ return 0;
+ case POPUP_GROUPHIDEOFFLINE:
+ if (contact->type != CLCIT_GROUP)
+ return 0;
+ CallService(MS_CLIST_GROUPSETFLAGS, contact->groupId,
+ MAKELPARAM(contact->group->hideOffline ? 0 : GROUPF_HIDEOFFLINE, GROUPF_HIDEOFFLINE));
+ return 0;
+ }
+ if (contact->type == CLCIT_GROUP)
+ if (CallService(MO_PROCESSCOMMANDBYMENUIDENT,LOWORD(wParam),(LPARAM)hwnd))
+ return 0;
+ return 0;
+}
+
+static LRESULT clcOnSize(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+
+ pcli->pfnEndRename(hwnd,dat,1);
+ KillTimer(hwnd,TIMERID_INFOTIP);
+ KillTimer(hwnd,TIMERID_RENAME);
+ cliRecalcScrollBar(hwnd,dat);
+ if ( g_CluiData.fDisableSkinEngine || dat->force_in_dialog )
+ {
+ HBITMAP hBmp, hBmpMask, hoBmp, hoMaskBmp;
+ HDC hdc,hdcMem;
+ RECT rc = {0};
+ int depth;
+ HBRUSH hBrush;
+
+ GetClientRect(hwnd, &rc);
+ if (rc.right == 0)
+ return corecli.pfnContactListControlWndProc(hwnd,msg,wParam,lParam);;
+
+ rc.bottom = max ( dat->row_min_heigh, 1 );
+ //rc.bottom = 8;
+ //rc.right = 8;
+ hdc = GetDC(hwnd);
+ depth = GetDeviceCaps(hdc, BITSPIXEL);
+ if (depth < 16)
+ depth = 16;
+ hBmp = CreateBitmap(rc.right, rc.bottom, 1, depth, NULL);
+ hBmpMask = CreateBitmap(rc.right, rc.bottom, 1, 1, NULL);
+ hdcMem = CreateCompatibleDC(hdc);
+ hoBmp = (HBITMAP) SelectObject(hdcMem, hBmp);
+ hBrush = CreateSolidBrush(( dat->useWindowsColours || dat->force_in_dialog ) ? GetSysColor(COLOR_HIGHLIGHT) : dat->selBkColour);
+ FillRect(hdcMem, &rc, hBrush);
+ DeleteObject(hBrush);
+
+ hoMaskBmp = (HBITMAP)SelectObject(hdcMem, hBmpMask);
+ FillRect(hdcMem, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
+ SelectObject(hdcMem, hoMaskBmp);
+ SelectObject(hdcMem, hoBmp);
+ DeleteDC(hdcMem);
+ ReleaseDC(hwnd, hdc);
+ if (dat->himlHighlight)
+ ImageList_Destroy(dat->himlHighlight);
+ dat->himlHighlight = ImageList_Create(rc.right, rc.bottom, (IsWinVerXPPlus()? ILC_COLOR32 : ILC_COLOR16) | ILC_MASK, 1, 1);
+ ImageList_Add(dat->himlHighlight, hBmp, hBmpMask);
+ DeleteObject(hBmpMask);
+ DeleteObject(hBmp);
+ }
+ else if (dat->himlHighlight)
+ {
+ ImageList_Destroy(dat->himlHighlight);
+ dat->himlHighlight = NULL;
+ }
+ return 0;
+}
+
+static LRESULT clcOnChar(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (wParam == 27 && dat->szQuickSearch[0] == '\0') //escape and not quick search
+ {
+ // minimize clist
+ CListMod_HideWindow(pcli->hwndContactList, SW_HIDE);
+ }
+ return corecli.pfnContactListControlWndProc(hwnd,msg,wParam,lParam);
+}
+static LRESULT clcOnPaint(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HDC hdc;
+ PAINTSTRUCT ps;
+ if (IsWindowVisible(hwnd))
+ {
+ if ( !g_CluiData.fLayered || GetParent(hwnd) != pcli->hwndContactList)
+ {
+ hdc = BeginPaint(hwnd,&ps);
+ g_clcPainter.cliPaintClc(hwnd,dat,hdc,&ps.rcPaint);
+ EndPaint(hwnd,&ps);
+ }
+ else CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,(WPARAM)hwnd,0);
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+static LRESULT clcOnEraseBkGround(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ return 1;
+}
+
+static LRESULT clcOnKeyDown(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int selMoved = 0;
+ int changeGroupExpand = 0;
+ int pageSize;
+ if (wParam == VK_CONTROL)
+ return 0;
+ pcli->pfnHideInfoTip(hwnd,dat);
+
+ KillTimer(hwnd,TIMERID_INFOTIP);
+ KillTimer(hwnd,TIMERID_RENAME);
+
+ if (CallService(MS_CLIST_MENUPROCESSHOTKEY,wParam,MPCF_CONTACTMENU))
+ return 0;
+
+ {
+ RECT clRect;
+ GetClientRect(hwnd,&clRect);
+ if (dat->max_row_height) pageSize = clRect.bottom/dat->max_row_height;
+ else pageSize = 0;
+ }
+
+ switch(wParam)
+ {
+ case VK_DOWN:
+ case VK_UP:
+ {
+ if (dat->szQuickSearch[0] != '\0' && dat->selection != -1) //get next contact
+ {
+ //get next contact
+ int index = clcSearchNextContact(hwnd,dat,dat->selection,dat->szQuickSearch,1,(wParam == VK_UP));
+ if (index == -1)
+ {
+ MessageBeep(MB_OK);
+ return 0;
+ }
+ else
+ {
+ dat->selection = index;
+ pcli->pfnInvalidateRect(hwnd, NULL, FALSE);
+ pcli->pfnEnsureVisible(hwnd, dat, dat->selection, 0);
+ return 0;
+ }
+
+ }
+ else
+ {
+ if (wParam == VK_DOWN) dat->selection++;
+ if (wParam == VK_UP) dat->selection--;
+ selMoved = 1; break;
+ }
+ }
+ case VK_PRIOR: dat->selection -= pageSize; selMoved = 1; break;
+ case VK_NEXT: dat->selection += pageSize; selMoved = 1; break;
+ case VK_HOME: dat->selection = 0; selMoved = 1; break;
+ case VK_END: dat->selection = pcli->pfnGetGroupContentsCount(&dat->list,1)-1; selMoved = 1; break;
+ case VK_LEFT: changeGroupExpand = 1; break;
+ case VK_RIGHT: changeGroupExpand = 2; break;
+ case VK_RETURN: pcli->pfnDoSelectionDefaultAction(hwnd,dat); SetCapture(hwnd); return 0;
+ case VK_F2: cliBeginRenameSelection(hwnd,dat); /*SetCapture(hwnd);*/ return 0;
+ case VK_DELETE: pcli->pfnDeleteFromContactList(hwnd,dat); SetCapture(hwnd);return 0;
+ case VK_ESCAPE:
+ {
+ if ((dat->dragStage&DRAGSTAGEM_STAGE) == DRAGSTAGE_ACTIVE)
+ {
+ dat->iDragItem = -1;
+ dat->iInsertionMark = -1;
+ dat->dragStage = 0;
+ ReleaseCapture();
+ }
+ return 0;
+ }
+ default:
+ {
+ NMKEY nmkey;
+ nmkey.hdr.hwndFrom = hwnd;
+ nmkey.hdr.idFrom = GetDlgCtrlID(hwnd);
+ nmkey.hdr.code = NM_KEYDOWN;
+ nmkey.nVKey = wParam;
+ nmkey.uFlags = HIWORD(lParam);
+
+ if (SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nmkey))
+ {
+ SetCapture(hwnd);
+ return 0;
+ }
+ }
+ }
+ if (changeGroupExpand)
+ {
+ int hit;
+ struct ClcContact *contact;
+ struct ClcGroup *group;
+ dat->szQuickSearch[0] = 0;
+ hit = cliGetRowByIndex(dat,dat->selection,&contact,&group);
+ if (hit != -1)
+ {
+ if (contact->type == CLCIT_CONTACT && (contact->isSubcontact || contact->SubAllocated>0))
+ {
+ if (contact->isSubcontact && changeGroupExpand == 1)
+ {
+ dat->selection -= contact->isSubcontact;
+ selMoved = 1;
+ }
+ else if ( !contact->isSubcontact && contact->SubAllocated>0)
+ {
+ if (changeGroupExpand == 1 && !contact->SubExpanded)
+ {
+ dat->selection = cliGetRowsPriorTo(&dat->list,group,-1);
+ selMoved = 1;
+ }
+ else if (changeGroupExpand == 1 && contact->SubExpanded)
+ {
+ //Contract
+ struct ClcContact * ht = NULL;
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ contact->SubExpanded = 0;
+ db_set_b(contact->hContact,"CList","Expanded",0);
+ ht = contact;
+ dat->NeedResort = 1;
+ pcli->pfnSortCLC(hwnd,dat,1);
+ cliRecalcScrollBar(hwnd,dat);
+ hitcontact = NULL;
+ }
+ else if (changeGroupExpand == 2 && contact->SubExpanded)
+ {
+ dat->selection++;
+ selMoved = 1;
+ }
+ else if (changeGroupExpand == 2 && !contact->SubExpanded && dat->expandMeta)
+ {
+ struct ClcContact * ht = NULL;
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ contact->SubExpanded = 1;
+ db_set_b(contact->hContact,"CList","Expanded",1);
+ ht = contact;
+ dat->NeedResort = 1;
+ pcli->pfnSortCLC(hwnd,dat,1);
+ cliRecalcScrollBar(hwnd,dat);
+ if (ht)
+ {
+ int i=0;
+ struct ClcContact *contact2;
+ struct ClcGroup *group2;
+ if (FindItem(hwnd,dat,contact->hContact,&contact2,&group2,NULL,FALSE))
+ {
+ i = cliGetRowsPriorTo(&dat->list,group2,GetContactIndex(group2,contact2));
+ pcli->pfnEnsureVisible(hwnd,dat,i+contact->SubAllocated,0);
+ }
+ }
+ hitcontact = NULL;
+ }
+ }
+ }
+
+ else
+ {
+ if (changeGroupExpand == 1 && contact->type == CLCIT_CONTACT) {
+ if (group == &dat->list) {SetCapture(hwnd); return 0;}
+ dat->selection = cliGetRowsPriorTo(&dat->list,group,-1);
+ selMoved = 1;
+ }
+ else {
+ if (contact->type == CLCIT_GROUP)
+ {
+ if (changeGroupExpand == 1)
+ {
+ if ( !contact->group->expanded)
+ {
+ dat->selection--;
+ selMoved = 1;
+ }
+ else
+ {
+ pcli->pfnSetGroupExpand(hwnd,dat,contact->group,0);
+ }
+ }
+ else if (changeGroupExpand == 2)
+ {
+ pcli->pfnSetGroupExpand(hwnd,dat,contact->group,1);
+ dat->selection++;
+ selMoved = 1;
+ }
+ else {SetCapture(hwnd);return 0;}
+ }//
+ //
+ }
+
+ }
+ }
+ else {SetCapture(hwnd);return 0; }
+ }
+ if (selMoved)
+ {
+ dat->szQuickSearch[0] = 0;
+ if (dat->selection >= pcli->pfnGetGroupContentsCount(&dat->list,1))
+ dat->selection = pcli->pfnGetGroupContentsCount(&dat->list,1)-1;
+ if (dat->selection < 0) dat->selection = 0;
+ if (dat->bCompactMode)
+ SendMessage(hwnd,WM_SIZE,0,0);
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ pcli->pfnEnsureVisible(hwnd,dat,dat->selection,0);
+ UpdateWindow(hwnd);
+ SetCapture(hwnd);
+ return 0;
+ }
+ SetCapture(hwnd);
+ return 0;
+
+}
+
+void clcSetDelayTimer( UINT_PTR uIDEvent, HWND hwnd, int nDelay)
+{
+ KillTimer( hwnd, uIDEvent );
+ int delay = nDelay;
+ if ( delay == -1)
+ {
+ switch ( uIDEvent )
+ {
+ case TIMERID_DELAYEDRESORTCLC: delay = 10; break;
+ case TIMERID_RECALCSCROLLBAR: delay = 10; break;
+ case TIMERID_REBUILDAFTER: delay = 50; break;
+ default: delay = 100; break;
+ }
+ }
+ CLUI_SafeSetTimer( hwnd, uIDEvent, delay, NULL );
+}
+
+static LRESULT clcOnTimer(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(wParam) {
+ case TIMERID_INVALIDATE_FULL:
+ KillTimer(hwnd,TIMERID_INVALIDATE_FULL);
+ pcli->pfnRecalcScrollBar(hwnd,dat);
+ pcli->pfnInvalidateRect(hwnd,NULL,0);
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+
+ case TIMERID_INVALIDATE:
+ {
+ time_t cur_time = (time(NULL)/60);
+ if (cur_time != dat->last_tick_time)
+ {
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ dat->last_tick_time = cur_time;
+ }
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ }
+ case TIMERID_SUBEXPAND:
+ {
+ struct ClcContact * ht = NULL;
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ if (hitcontact && dat->expandMeta)
+ {
+ if (hitcontact->SubExpanded) hitcontact->SubExpanded = 0; else hitcontact->SubExpanded = 1;
+ db_set_b(hitcontact->hContact,"CList","Expanded",hitcontact->SubExpanded);
+ if (hitcontact->SubExpanded)
+ ht = &(hitcontact->subcontacts[hitcontact->SubAllocated-1]);
+ }
+
+ dat->NeedResort = 1;
+ pcli->pfnSortCLC(hwnd,dat,1);
+ cliRecalcScrollBar(hwnd,dat);
+ if (ht) {
+ int i=0;
+ struct ClcContact *contact;
+ struct ClcGroup *group;
+ if (FindItem(hwnd,dat,hitcontact->hContact,&contact,&group,NULL,FALSE))
+ {
+ i = cliGetRowsPriorTo(&dat->list,group,GetContactIndex(group,contact));
+ pcli->pfnEnsureVisible(hwnd,dat,i+hitcontact->SubAllocated,0);
+ }
+ }
+ hitcontact = NULL;
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ }
+ case TIMERID_DELAYEDRESORTCLC:
+ TRACE("Do sort on Timer\n");
+ KillTimer(hwnd,TIMERID_DELAYEDRESORTCLC);
+ pcli->pfnSortCLC(hwnd,dat,1);
+ pcli->pfnInvalidateRect(hwnd,NULL,FALSE);
+ return 0;
+
+ case TIMERID_RECALCSCROLLBAR:
+ KillTimer(hwnd,TIMERID_RECALCSCROLLBAR);
+ pcli->pfnRecalcScrollBar(hwnd,dat);
+ return 0;
+
+ default:
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ }
+ return 0;
+}
+
+
+static LRESULT clcOnActivate(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TRACE ("clcOnActivate\n");
+ if (dat->bCompactMode)
+ {
+ cliRecalcScrollBar(hwnd,dat);
+ if ( dat->hwndRenameEdit == NULL )
+ PostMessage( hwnd, WM_SIZE, 0, 0);
+ }
+ dat->dragStage |= DRAGSTAGEF_SKIPRENAME;
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+}
+static LRESULT clcOnSetCursor(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int lResult;
+
+ if ( !CLUI_IsInMainWindow(hwnd))
+ return DefWindowProc(hwnd,msg,wParam,lParam);
+
+ if (g_CluiData.nBehindEdgeState>0)
+ CLUI_ShowFromBehindEdge();
+
+ if (g_CluiData.bBehindEdgeSettings)
+ CLUI_UpdateTimer(0);
+
+ lResult = CLUI_TestCursorOnBorders();
+ return lResult ? lResult : DefWindowProc(hwnd,msg,wParam,lParam);
+}
+static LRESULT clcOnLButtonDown(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ {
+ POINT pt;
+ int k = 0;
+ pt.x = LOWORD(lParam);
+ pt.y = HIWORD(lParam);
+ ClientToScreen(hwnd,&pt);
+ k = CLUI_SizingOnBorder(pt,0);
+ if (k)
+ {
+ int io = dat->iHotTrack;
+ dat->iHotTrack = 0;
+ if (dat->exStyle&CLS_EX_TRACKSELECT)
+ {
+ pcli->pfnInvalidateItem(hwnd,dat,io);
+ }
+ if (k && GetCapture() == hwnd)
+ {
+ SendMessage(GetParent(hwnd),WM_PARENTNOTIFY,WM_LBUTTONDOWN,lParam);
+ }
+ return FALSE;
+ }
+ }
+ {
+ struct ClcContact *contact;
+ struct ClcGroup *group;
+ int hit;
+ DWORD hitFlags;
+ fMouseUpped = FALSE;
+ pcli->pfnHideInfoTip(hwnd,dat);
+ KillTimer(hwnd,TIMERID_INFOTIP);
+ KillTimer(hwnd,TIMERID_RENAME);
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+
+ pcli->pfnEndRename(hwnd,dat,1);
+ dat->ptDragStart.x = (short)LOWORD(lParam);
+ dat->ptDragStart.y = (short)HIWORD(lParam);
+ dat->szQuickSearch[0] = 0;
+ hit = cliHitTest(hwnd,dat,(short)LOWORD(lParam),(short)HIWORD(lParam),&contact,&group,&hitFlags);
+ if (GetFocus() != hwnd) SetFocus(hwnd);
+ if (hit != -1 && !(hitFlags&CLCHT_NOWHERE))
+ {
+ if ( hit == dat->selection && hitFlags&CLCHT_ONITEMLABEL && dat->exStyle&CLS_EX_EDITLABELS)
+ {
+ if ( !(dat->dragStage&DRAGSTAGEF_SKIPRENAME))
+ {
+ SetCapture(hwnd);
+ dat->iDragItem = dat->selection;
+ dat->dragStage = DRAGSTAGE_NOTMOVED|DRAGSTAGEF_MAYBERENAME;
+ dat->dragAutoScrolling = 0;
+ return TRUE;
+ }
+ else
+ {
+ dat->dragStage &= ~DRAGSTAGEF_SKIPRENAME;
+ return TRUE;
+ }
+
+ }
+ }
+ if (hit != -1 && !(hitFlags&CLCHT_NOWHERE) && contact->type == CLCIT_CONTACT && contact->SubAllocated && !contact->isSubcontact)
+ if (hitFlags&CLCHT_ONITEMICON && dat->expandMeta)
+ {
+ BYTE doubleClickExpand = db_get_b(NULL,"CLC","MetaDoubleClick",SETTING_METAAVOIDDBLCLICK_DEFAULT);
+
+ hitcontact = contact;
+ HitPoint.x = (short)LOWORD(lParam);
+ HitPoint.y = (short)HIWORD(lParam);
+ fMouseUpped = FALSE;
+ if ((GetKeyState(VK_SHIFT)&0x8000) || (GetKeyState(VK_CONTROL)&0x8000) || (GetKeyState(VK_MENU)&0x8000))
+ {
+ fMouseUpped = TRUE;
+ hitcontact = contact;
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ CLUI_SafeSetTimer(hwnd,TIMERID_SUBEXPAND,0,NULL);
+ }
+ }
+ else
+ hitcontact = NULL;
+
+ if (hit != -1 && !(hitFlags&CLCHT_NOWHERE) && contact->type == CLCIT_GROUP)
+ if (hitFlags&CLCHT_ONITEMICON)
+ {
+ struct ClcGroup *selgroup;
+ struct ClcContact *selcontact;
+ dat->selection = cliGetRowByIndex(dat,dat->selection,&selcontact,&selgroup);
+ pcli->pfnSetGroupExpand(hwnd,dat,contact->group,-1);
+ if (dat->selection != -1)
+ {
+ dat->selection = cliGetRowsPriorTo(&dat->list,selgroup,GetContactIndex(selgroup,selcontact));
+ if (dat->selection == -1) dat->selection = cliGetRowsPriorTo(&dat->list,contact->group,-1);
+ }
+ if (dat->bCompactMode)
+ {
+ SendMessage(hwnd,WM_SIZE,0,0);
+ }
+ else
+ {
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ UpdateWindow(hwnd);
+ }
+ return TRUE;
+ }
+ if (hit != -1 && !(hitFlags&CLCHT_NOWHERE) && hitFlags&CLCHT_ONITEMCHECK)
+ {
+ NMCLISTCONTROL nm;
+ contact->flags ^= CONTACTF_CHECKED;
+ if (contact->type == CLCIT_GROUP) pcli->pfnSetGroupChildCheckboxes(contact->group,contact->flags&CONTACTF_CHECKED);
+ pcli->pfnRecalculateGroupCheckboxes(hwnd,dat);
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ nm.hdr.code = CLN_CHECKCHANGED;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ nm.flags = 0;
+ nm.hItem = ContactToItemHandle(contact,&nm.flags);
+ SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm);
+ }
+ if ( !(hitFlags&(CLCHT_ONITEMICON|CLCHT_ONITEMLABEL|CLCHT_ONITEMCHECK)))
+ {
+ NMCLISTCONTROL nm;
+ nm.hdr.code = NM_CLICK;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ nm.flags = 0;
+ if (hit == -1 || hitFlags&CLCHT_NOWHERE) nm.hItem = NULL;
+ else nm.hItem = ContactToItemHandle(contact,&nm.flags);
+ nm.iColumn = hitFlags&CLCHT_ONITEMEXTRA?HIBYTE(HIWORD(hitFlags)):-1;
+ nm.pt = dat->ptDragStart;
+ SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm);
+ }
+ if (hitFlags&(CLCHT_ONITEMCHECK|CLCHT_ONITEMEXTRA))
+ return FALSE;
+
+ dat->selection = (hitFlags&CLCHT_NOWHERE)?-1:hit;
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+
+ UpdateWindow(hwnd);
+ if (dat->selection != -1 && (contact->type == CLCIT_CONTACT || contact->type == CLCIT_GROUP) && !(hitFlags&(CLCHT_ONITEMEXTRA|CLCHT_ONITEMCHECK|CLCHT_NOWHERE)))
+ {
+ SetCapture(hwnd);
+ dat->iDragItem = dat->selection;
+ dat->dragStage = DRAGSTAGE_NOTMOVED;
+ dat->dragAutoScrolling = 0;
+ }
+ if (dat->bCompactMode)
+ {
+ SendMessage(hwnd,WM_SIZE,0,0);
+ }
+ if (dat->selection != -1) pcli->pfnEnsureVisible(hwnd,dat,hit,0);
+ return TRUE;
+ }
+}
+
+
+
+static LRESULT clcOnCaptureChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if ((HWND)lParam != hwnd)
+ {
+ if (dat->iHotTrack != -1)
+ {
+ int i;
+ i = dat->iHotTrack;
+ dat->iHotTrack = -1;
+ pcli->pfnInvalidateItem(hwnd,dat,i);
+ pcli->pfnHideInfoTip(hwnd,dat);
+ }
+ }
+ return 0;
+}
+
+static LRESULT clcOnMouseMove(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ BOOL isOutside = FALSE;
+ if (CLUI_IsInMainWindow(hwnd))
+ {
+ if (g_CluiData.bBehindEdgeSettings) CLUI_UpdateTimer(0);
+ CLUI_TestCursorOnBorders();
+ }
+ if (clcProceedDragToScroll(hwnd, (short)HIWORD(lParam)))
+ return 0;
+
+ if ( dat->dragStage&DRAGSTAGEF_MAYBERENAME )
+ {
+ POINT pt;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ if ( abs(pt.x-dat->ptDragStart.x)>GetSystemMetrics(SM_CXDOUBLECLK)
+ || abs(pt.y-dat->ptDragStart.y)>GetSystemMetrics(SM_CYDOUBLECLK))
+ {
+ KillTimer( hwnd, TIMERID_RENAME );
+ dat->dragStage &= (~DRAGSTAGEF_MAYBERENAME);
+ }
+ }
+
+ if (dat->iDragItem == -1)
+ {
+ POINT pt;
+ HWND window;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ ClientToScreen(hwnd,&pt);
+ window = WindowFromPoint(pt);
+ if (window != hwnd) isOutside = TRUE;
+ }
+
+ if (hitcontact != NULL) {
+ int x = (short)LOWORD(lParam);
+ int y = (short)HIWORD(lParam);
+ int xm = GetSystemMetrics(SM_CXDOUBLECLK);
+ int ym = GetSystemMetrics(SM_CYDOUBLECLK);
+ if ( abs(HitPoint.x-x) > xm || abs(HitPoint.y-y) > ym) {
+ if (fMouseUpped) {
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ CLUI_SafeSetTimer(hwnd,TIMERID_SUBEXPAND,0,NULL);
+ fMouseUpped = FALSE;
+ }
+ else {
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ hitcontact = NULL;
+ fMouseUpped = FALSE;
+ }
+ }
+ }
+
+ if (dat->iDragItem == -1) {
+ DWORD flag = 0;
+ int iOldHotTrack = dat->iHotTrack;
+
+ if (dat->hwndRenameEdit != NULL || GetKeyState(VK_MENU)&0x8000 || GetKeyState(VK_F10)&0x8000)
+ return 0;
+
+ dat->iHotTrack = isOutside ? -1 : cliHitTest(hwnd,dat,(short)LOWORD(lParam),(short)HIWORD(lParam),NULL,NULL,&flag);
+
+ if (flag&CLCHT_NOWHERE)
+ dat->iHotTrack = -1;
+
+ if (iOldHotTrack != dat->iHotTrack || isOutside) {
+ if (iOldHotTrack == -1 && !isOutside)
+ SetCapture(hwnd);
+
+ if (dat->iHotTrack == -1 || isOutside)
+ ReleaseCapture();
+
+ if (dat->exStyle&CLS_EX_TRACKSELECT)
+ {
+ pcli->pfnInvalidateItem(hwnd,dat,iOldHotTrack);
+ pcli->pfnInvalidateItem(hwnd,dat,dat->iHotTrack);
+ }
+
+ pcli->pfnHideInfoTip(hwnd,dat);
+ }
+
+ KillTimer(hwnd,TIMERID_INFOTIP);
+
+ if (wParam == 0 && dat->hInfoTipItem == NULL)
+ {
+ dat->ptInfoTip.x = (short)LOWORD(lParam);
+ dat->ptInfoTip.y = (short)HIWORD(lParam);
+ CLUI_SafeSetTimer(hwnd,TIMERID_INFOTIP,dat->infoTipTimeout,NULL);
+ }
+ return 0;
+ }
+
+ if ((dat->dragStage&DRAGSTAGEM_STAGE) == DRAGSTAGE_NOTMOVED && !(dat->exStyle&CLS_EX_DISABLEDRAGDROP))
+ if (abs((short)LOWORD(lParam)-dat->ptDragStart.x) >= GetSystemMetrics(SM_CXDRAG) || abs((short)HIWORD(lParam)-dat->ptDragStart.y) >= GetSystemMetrics(SM_CYDRAG))
+ dat->dragStage = (dat->dragStage&~DRAGSTAGEM_STAGE)|DRAGSTAGE_ACTIVE;
+
+ if ((dat->dragStage&DRAGSTAGEM_STAGE) == DRAGSTAGE_ACTIVE) {
+ RECT clRect;
+ GetClientRect(hwnd,&clRect);
+
+ POINT pt;
+ pt.x = (short)LOWORD(lParam); pt.y = (short)HIWORD(lParam);
+ HCURSOR hNewCursor = LoadCursor(NULL, IDC_NO);
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ if (dat->dragAutoScrolling)
+ {KillTimer(hwnd,TIMERID_DRAGAUTOSCROLL); dat->dragAutoScrolling = 0;}
+ int target = GetDropTargetInformation(hwnd,dat,pt);
+ if (dat->dragStage&DRAGSTAGEF_OUTSIDE && target != DROPTARGET_OUTSIDE) {
+ NMCLISTCONTROL nm;
+ struct ClcContact *contact;
+ cliGetRowByIndex(dat,dat->iDragItem,&contact,NULL);
+ nm.hdr.code = CLN_DRAGSTOP;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ nm.flags = 0;
+ nm.hItem = ContactToItemHandle(contact,&nm.flags);
+ SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm);
+ dat->dragStage &= ~DRAGSTAGEF_OUTSIDE;
+ }
+
+ switch(target) {
+ case DROPTARGET_ONSELF:
+ break;
+
+ case DROPTARGET_ONCONTACT:
+ if (ServiceExists(MS_MC_ADDTOMETA))
+ {
+ struct ClcContact *contSour;
+ cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL);
+ if (contSour->type == CLCIT_CONTACT && g_szMetaModuleName && mir_strcmp(contSour->proto,g_szMetaModuleName))
+ {
+ if ( !contSour->isSubcontact)
+ hNewCursor = LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROPUSER)); /// Add to meta
+ else
+ hNewCursor = LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_DROPMETA));
+ }
+
+ }
+ break;
+
+ case DROPTARGET_ONMETACONTACT:
+ if (ServiceExists(MS_MC_ADDTOMETA))
+ {
+ struct ClcContact *contSour,*contDest;
+ cliGetRowByIndex(dat,dat->selection,&contDest,NULL);
+ cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL);
+ if (contSour->type == CLCIT_CONTACT && g_szMetaModuleName && mir_strcmp(contSour->proto,g_szMetaModuleName))
+ {
+ if ( !contSour->isSubcontact)
+ hNewCursor = LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROPUSER)); /// Add to meta
+ else
+ if (contSour->subcontacts == contDest)
+ hNewCursor = LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_DEFAULTSUB)); ///MakeDefault
+ else
+ hNewCursor = LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_REGROUP));
+ }
+ }
+ break;
+ case DROPTARGET_ONSUBCONTACT:
+ if (ServiceExists(MS_MC_ADDTOMETA))
+ {
+ struct ClcContact *contSour,*contDest;
+ cliGetRowByIndex(dat,dat->selection,&contDest,NULL);
+ cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL);
+ if (contSour->type == CLCIT_CONTACT && g_szMetaModuleName && mir_strcmp(contSour->proto,g_szMetaModuleName))
+ {
+ if ( !contSour->isSubcontact)
+ hNewCursor = LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROPUSER)); /// Add to meta
+ else
+ if (contDest->subcontacts == contSour->subcontacts)
+ break;
+ else
+ hNewCursor = LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_REGROUP));
+ }
+ }
+ break;
+
+ case DROPTARGET_ONGROUP:
+ hNewCursor = LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROPUSER));
+ break;
+
+ case DROPTARGET_INSERTION:
+ hNewCursor = LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROP));
+ break;
+
+ case DROPTARGET_OUTSIDE:
+ {
+ NMCLISTCONTROL nm;
+ struct ClcContact *contact;
+
+ if (pt.x >= 0 && pt.x < clRect.right && ((pt.y < 0 && pt.y>-dat->dragAutoScrollHeight) || (pt.y >= clRect.bottom && pt.y < clRect.bottom+dat->dragAutoScrollHeight)))
+ {
+ if ( !dat->dragAutoScrolling)
+ {
+ if (pt.y < 0) dat->dragAutoScrolling = -1;
+ else dat->dragAutoScrolling = 1;
+ CLUI_SafeSetTimer(hwnd,TIMERID_DRAGAUTOSCROLL,dat->scrollTime,NULL);
+ }
+ SendMessage(hwnd,WM_TIMER,TIMERID_DRAGAUTOSCROLL,0);
+ }
+
+ dat->dragStage |= DRAGSTAGEF_OUTSIDE;
+ cliGetRowByIndex(dat,dat->iDragItem,&contact,NULL);
+ nm.hdr.code = CLN_DRAGGING;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ nm.flags = 0;
+ nm.hItem = ContactToItemHandle(contact,&nm.flags);
+ nm.pt = pt;
+ if (SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm))
+ return 0;
+ break;
+ }
+ default:
+ {
+ struct ClcGroup *group = NULL;
+ cliGetRowByIndex(dat,dat->iDragItem,NULL,&group);
+ if (group && group->parent)
+ {
+ struct ClcContact *contSour;
+ cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL);
+ if ( !contSour->isSubcontact)
+ hNewCursor = LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROPUSER));
+ }
+ break;
+ }
+ }
+ SetCursor(hNewCursor);
+ }
+ return 0;
+}
+
+static LRESULT clcOnLButtonUp(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (clcExitDragToScroll())
+ return 0;
+
+ fMouseUpped = TRUE;
+
+ if (hitcontact != NULL && dat->expandMeta) {
+ BYTE doubleClickExpand = db_get_b(NULL,"CLC","MetaDoubleClick",SETTING_METAAVOIDDBLCLICK_DEFAULT);
+ CLUI_SafeSetTimer(hwnd,TIMERID_SUBEXPAND,GetDoubleClickTime()*doubleClickExpand,NULL);
+ }
+ else if (dat->iHotTrack == -1 && dat->iDragItem == -1)
+ ReleaseCapture();
+ if (dat->iDragItem == -1) return 0;
+ SetCursor((HCURSOR)GetClassLongPtr(hwnd,GCLP_HCURSOR));
+ if (dat->exStyle & CLS_EX_TRACKSELECT)
+ {
+ DWORD flags;
+ dat->iHotTrack = cliHitTest(hwnd,dat,(short)LOWORD(lParam),(short)HIWORD(lParam),NULL,NULL,&flags);
+ if (dat->iHotTrack == -1)
+ ReleaseCapture();
+ }
+ else if (hitcontact == NULL)
+ ReleaseCapture();
+ KillTimer(hwnd,TIMERID_DRAGAUTOSCROLL);
+ if (dat->dragStage == (DRAGSTAGE_NOTMOVED|DRAGSTAGEF_MAYBERENAME))
+ CLUI_SafeSetTimer(hwnd,TIMERID_RENAME,GetDoubleClickTime(),NULL);
+ else if ((dat->dragStage&DRAGSTAGEM_STAGE) == DRAGSTAGE_ACTIVE)
+ {
+ POINT pt;
+ int target;
+ TCHAR Wording[500];
+ int res = 0;
+ pt.x = (short)LOWORD(lParam); pt.y = (short)HIWORD(lParam);
+ target = GetDropTargetInformation(hwnd,dat,pt);
+ switch(target)
+ {
+ case DROPTARGET_ONSELF:
+ break;
+ case DROPTARGET_ONCONTACT:
+ if (ServiceExists(MS_MC_ADDTOMETA))
+ {
+ struct ClcContact *contDest, *contSour;
+ int res;
+ HANDLE handle,hcontact;
+
+ cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL);
+ cliGetRowByIndex(dat,dat->selection,&contDest,NULL);
+ hcontact = contSour->hContact;
+ if (contSour->type == CLCIT_CONTACT)
+ {
+
+ if (g_szMetaModuleName && mir_strcmp(contSour->proto,g_szMetaModuleName))
+ {
+ if ( !contSour->isSubcontact)
+ {
+ HANDLE hDest = contDest->hContact;
+ mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be converted to MetaContact and '%s' be added to it?"),contDest->szText, contSour->szText);
+ res = MessageBox(hwnd,Wording,TranslateT("Converting to MetaContact"),MB_OKCANCEL|MB_ICONQUESTION);
+ if (res == 1)
+ {
+ handle = (HANDLE)CallService(MS_MC_CONVERTTOMETA,(WPARAM)hDest,0);
+ if ( !handle) return 0;
+ CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle);
+ }
+ }
+ else
+ {
+ HANDLE handle,hcontact,hfrom,hdest;
+ hcontact = contSour->hContact;
+ hfrom = contSour->subcontacts->hContact;
+ hdest = contDest->hContact;
+ mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be converted to MetaContact and '%s' be added to it (remove it from '%s')?"), contDest->szText,contSour->szText,contSour->subcontacts->szText);
+ res = MessageBox(hwnd,Wording,TranslateT("Converting to MetaContact (Moving)"),MB_OKCANCEL|MB_ICONQUESTION);
+ if (res == 1)
+ {
+
+ handle = (HANDLE)CallService(MS_MC_CONVERTTOMETA,(WPARAM)hdest,0);
+ if ( !handle) return 0;
+
+ CallService(MS_MC_REMOVEFROMMETA,(WPARAM)0,(LPARAM)hcontact);
+ CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle);
+ }
+ }
+ }
+
+ }
+ }
+ break;
+ case DROPTARGET_ONMETACONTACT:
+ {
+ struct ClcContact *contDest, *contSour;
+ int res;
+ cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL);
+ cliGetRowByIndex(dat,dat->selection,&contDest,NULL);
+ if (contSour->type == CLCIT_CONTACT)
+ {
+
+ if (g_szMetaModuleName && strcmp(contSour->proto,g_szMetaModuleName))
+ {
+ if ( !contSour->isSubcontact)
+ {
+ HANDLE handle,hcontact;
+ hcontact = contSour->hContact;
+ handle = contDest->hContact;
+ mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do you want to contact '%s' be added to metacontact '%s'?"),contSour->szText, contDest->szText);
+ res = MessageBox(hwnd,Wording,TranslateT("Adding contact to MetaContact"),MB_OKCANCEL|MB_ICONQUESTION);
+ if (res == 1)
+ {
+
+ if ( !handle) return 0;
+ CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle);
+ }
+ }
+ else
+ {
+ if (contSour->subcontacts == contDest)
+ {
+ HANDLE hsour;
+ hsour = contSour->hContact;
+ mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be default ?"),contSour->szText);
+ res = MessageBox(hwnd,Wording,TranslateT("Set default contact"),MB_OKCANCEL|MB_ICONQUESTION);
+
+ if (res == 1)
+ {
+ CallService(MS_MC_SETDEFAULTCONTACT,(WPARAM)contDest->hContact,(LPARAM)hsour);
+ }
+ }
+ else
+ {
+ HANDLE handle,hcontact,hfrom;
+ hcontact = contSour->hContact;
+ hfrom = contSour->subcontacts->hContact;
+ handle = contDest->hContact;
+ mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be removed from MetaContact '%s' and added to '%s'?"), contSour->szText,contSour->subcontacts->szText,contDest->szText);
+ res = MessageBox(hwnd,Wording,TranslateT("Changing MetaContacts (Moving)"),MB_OKCANCEL|MB_ICONQUESTION);
+ if (res == 1)
+ {
+
+ if ( !handle) return 0;
+
+ CallService(MS_MC_REMOVEFROMMETA,(WPARAM)0,(LPARAM)hcontact);
+ CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case DROPTARGET_ONSUBCONTACT:
+ {
+ struct ClcContact *contDest, *contSour;
+ int res;
+ cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL);
+ cliGetRowByIndex(dat,dat->selection,&contDest,NULL);
+ if (contSour->type == CLCIT_CONTACT)
+ {
+ if (g_szMetaModuleName && strcmp(contSour->proto,g_szMetaModuleName))
+ {
+ if ( !contSour->isSubcontact)
+ {
+ HANDLE handle,hcontact;
+ hcontact = contSour->hContact;
+ handle = contDest->subcontacts->hContact;
+ mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be added to MetaContact '%s'?"), contSour->szText,contDest->subcontacts->szText);
+ res = MessageBox(hwnd,Wording,TranslateT("Changing MetaContacts (Moving)"),MB_OKCANCEL|MB_ICONQUESTION);
+ if (res == 1)
+ {
+
+ if ( !handle) return 0;
+ CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle);
+ }
+ }
+ else
+ {
+ if (contSour->subcontacts != contDest->subcontacts)
+ {
+ HANDLE handle,hcontact,hfrom;
+ hcontact = contSour->hContact;
+ hfrom = contSour->subcontacts->hContact;
+ handle = contDest->subcontacts->hContact;
+ mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be removed from MetaContact '%s' and added to '%s'?"), contSour->szText,contSour->subcontacts->szText,contDest->subcontacts->szText);
+ res = MessageBox(hwnd,Wording,TranslateT("Changing MetaContacts (Moving)"),MB_OKCANCEL|MB_ICONQUESTION);
+ if (res == 1)
+ {
+
+ if ( !handle) return 0;
+
+ CallService(MS_MC_REMOVEFROMMETA,(WPARAM)0,(LPARAM)hcontact);
+ CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case DROPTARGET_ONGROUP:
+ corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ break;
+ case DROPTARGET_INSERTION:
+ {
+ struct ClcContact *contact, *destcontact;
+ struct ClcGroup *group, *destgroup;
+ BOOL NeedRename = FALSE;
+ TCHAR newName[128] = {0};
+ int newIndex,i;
+ pcli->pfnGetRowByIndex(dat, dat->iDragItem, &contact, &group);
+ i = pcli->pfnGetRowByIndex(dat, dat->iInsertionMark, &destcontact, &destgroup);
+ if (i != -1 && group->groupId != destgroup->groupId)
+ {
+ TCHAR * groupName = mir_tstrdup(pcli->pfnGetGroupName(contact->groupId,0));
+ TCHAR * shortGroup = NULL;
+ TCHAR * sourceGrName = mir_tstrdup(pcli->pfnGetGroupName(destgroup->groupId,0));
+ if (groupName) {
+ int len = (int)_tcslen(groupName);
+ do {len--;}while(len >= 0 && groupName[len] != '\\');
+ if (len >= 0) shortGroup = groupName+len+1;
+ else shortGroup = groupName;
+ }
+ if (shortGroup)
+ {
+ NeedRename = TRUE;
+ if (sourceGrName)
+ mir_sntprintf(newName,SIZEOF(newName),_T("%s\\%s"),sourceGrName,shortGroup);
+ else
+ mir_sntprintf(newName,SIZEOF(newName),_T("%s"),shortGroup);
+ }
+ mir_free(groupName);
+ mir_free(sourceGrName);
+ }
+ newIndex = CallService(MS_CLIST_GROUPMOVEBEFORE, contact->groupId, (destcontact && i != -1)?destcontact->groupId:0);
+ newIndex = newIndex?newIndex:contact->groupId;
+ if (NeedRename) pcli->pfnRenameGroup(newIndex,newName);
+ break;
+ }
+ case DROPTARGET_OUTSIDE:
+ corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ break;
+ default:
+ corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ break;
+
+ }
+ }
+
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ dat->iDragItem = -1;
+ dat->iInsertionMark = -1;
+ return 0;
+}
+static LRESULT clcOnLButtonDblClick(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ hitcontact = NULL;
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+}
+static LRESULT clcOnDestroy(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int i=0;
+
+ for (i=0;i <= FONTID_MODERN_MAX;i++)
+ {
+ if (dat->fontModernInfo[i].hFont) DeleteObject(dat->fontModernInfo[i].hFont);
+ dat->fontModernInfo[i].hFont = NULL;
+ }
+ if (dat->hMenuBackground)
+ {
+ DeleteObject(dat->hMenuBackground);
+ dat->hMenuBackground = NULL;
+ }
+ if ( !dat->bkChanged && dat->hBmpBackground)
+ {
+ DeleteObject(dat->hBmpBackground);
+ dat->hBmpBackground = NULL;
+ }
+
+ ImageArray_Clear(&dat->avatar_cache);
+ mod_DeleteDC(dat->avatar_cache.hdc);
+ ImageArray_Free(&dat->avatar_cache, FALSE);
+ if (dat->himlHighlight)
+ ImageList_Destroy(dat->himlHighlight);
+
+ RowHeights_Free(dat);
+ corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ xpt_FreeThemeForWindow(hwnd);
+ return 0;
+}
+static LRESULT clcOnIntmGroupChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct ClcContact *contact;
+ BYTE iExtraImage[MAXEXTRACOLUMNS];
+ WORD iWideExtraImage[MAXEXTRACOLUMNS];
+ BYTE flags = 0;
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ {
+ memset(iExtraImage, 0xFF, SIZEOF(iExtraImage));
+ memset((void*)iWideExtraImage, 0xFF, sizeof(iWideExtraImage));
+ }
+ else {
+ CopyMemory(iExtraImage, contact->iExtraImage, SIZEOF(iExtraImage));
+ CopyMemory((void*)iWideExtraImage, (void*)contact->iWideExtraImage, sizeof(iWideExtraImage));
+ flags = contact->flags;
+ }
+ pcli->pfnDeleteItemFromTree(hwnd, (HANDLE) wParam);
+ if (GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_SHOWHIDDEN || !db_get_b((HANDLE) wParam, "CList", "Hidden", 0)) {
+ NMCLISTCONTROL nm;
+ pcli->pfnAddContactToTree(hwnd, dat, (HANDLE) wParam, 1, 1);
+ if (pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) {
+ CopyMemory(contact->iExtraImage, iExtraImage, SIZEOF(iExtraImage));
+ CopyMemory((void*)contact->iWideExtraImage, (void*)iWideExtraImage, sizeof(iWideExtraImage));
+ if (flags & CONTACTF_CHECKED)
+ contact->flags |= CONTACTF_CHECKED;
+ }
+ nm.hdr.code = CLN_CONTACTMOVED;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ nm.flags = 0;
+ nm.hItem = (HANDLE) wParam;
+ SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM) & nm);
+ dat->NeedResort = 1;
+ }
+ SetTimer(hwnd,TIMERID_REBUILDAFTER,1,NULL);
+ return 0;
+}
+
+static LRESULT clcOnIntmIconChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct ClcContact *contact = NULL;
+ struct ClcGroup *group = NULL;
+ int recalcScrollBar = 0, shouldShow;
+ BOOL needRepaint = FALSE;
+ WORD status;
+ char *szProto;
+ int nHiddenStatus = 0;
+ BOOL image_is_special = FALSE;
+ RECT iconRect = {0};
+ int contacticon = CallService(MS_CLIST_GETCONTACTICON, wParam, 1);
+ HANDLE hSelItem = NULL;
+ struct ClcContact *selcontact = NULL;
+
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);
+ if (szProto == NULL)
+ status = ID_STATUS_OFFLINE;
+ else
+ status = GetContactCachedStatus((HANDLE) wParam);
+ image_is_special = (LOWORD(contacticon) != (LOWORD(lParam))); //check only base icons
+
+ nHiddenStatus = CLVM_GetContactHiddenStatus((HANDLE)wParam, szProto, dat);
+
+ DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE);
+ bool isVisiblebyFilter = (( ( style & CLS_SHOWHIDDEN ) && nHiddenStatus != -1 ) || !nHiddenStatus );
+ bool ifVisibleByClui = !pcli->pfnIsHiddenMode( dat, status );
+ bool isVisible = g_CluiData.bFilterEffective&CLVM_FILTER_STATUS ? TRUE : ifVisibleByClui;
+ bool isIconChanged = CallService(MS_CLIST_GETCONTACTICON, wParam, 0) != LOWORD(lParam);
+
+ shouldShow = isVisiblebyFilter && ( isVisible || isIconChanged ) ;
+
+ // XXX CLVM changed - this means an offline msg is flashing, so the contact should be shown
+
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, &group, NULL))
+ {
+ if (shouldShow && CallService(MS_DB_CONTACT_IS, wParam, 0))
+ {
+ if (dat->selection >= 0 && pcli->pfnGetRowByIndex(dat, dat->selection, &selcontact, NULL) != -1)
+ hSelItem = pcli->pfnContactToHItem(selcontact);
+ pcli->pfnAddContactToTree(hwnd, dat, (HANDLE) wParam, (style & CLS_CONTACTLIST) == 0, 0);
+ recalcScrollBar = 1;
+ needRepaint = TRUE;
+ pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL);
+ if (contact)
+ {
+ contact->iImage = lParam;
+ contact->image_is_special = image_is_special;
+ pcli->pfnNotifyNewContact(hwnd, (HANDLE) wParam);
+ dat->NeedResort = 1;
+ }
+ }
+ }
+ else
+ {
+ //item in list already
+ if (contact->iImage == lParam)
+ return 0;
+ if ( !shouldShow && !(style & CLS_NOHIDEOFFLINE) && (style & CLS_HIDEOFFLINE) && clcItemNotHiddenOffline(dat, group, contact))
+ {
+ shouldShow = TRUE;
+ }
+ if ( !shouldShow && !(style & CLS_NOHIDEOFFLINE) && ((style & CLS_HIDEOFFLINE) || group->hideOffline || g_CluiData.bFilterEffective)) // CLVM changed
+ {
+ if (dat->selection >= 0 && pcli->pfnGetRowByIndex(dat, dat->selection, &selcontact, NULL) != -1)
+ hSelItem = pcli->pfnContactToHItem(selcontact);
+ pcli->pfnRemoveItemFromGroup(hwnd, group, contact, (style & CLS_CONTACTLIST) == 0);
+ needRepaint = TRUE;
+ recalcScrollBar = 1;
+ dat->NeedResort = 1;
+ }
+ else if (contact)
+ {
+ contact->iImage = lParam;
+ if ( !pcli->pfnIsHiddenMode(dat, status))
+ contact->flags |= CONTACTF_ONLINE;
+ else
+ contact->flags &= ~CONTACTF_ONLINE;
+ contact->image_is_special = image_is_special;
+ if ( !image_is_special) //Only if it is status changing
+ {
+ dat->NeedResort = 1;
+ needRepaint = TRUE;
+ }
+ else if (dat->m_paintCouter == contact->lastPaintCounter) //if contacts is visible
+ {
+ needRepaint = TRUE;
+ }
+ }
+
+ }
+ if (hSelItem) {
+ struct ClcGroup *selgroup;
+ if (pcli->pfnFindItem(hwnd, dat, hSelItem, &selcontact, &selgroup, NULL))
+ dat->selection = pcli->pfnGetRowsPriorTo(&dat->list, selgroup, List_IndexOf(( SortedList* )&selgroup->cl, selcontact));
+ else
+ dat->selection = -1;
+ }
+ // dat->NeedResort = 1;
+ // SortClcByTimer(hwnd);
+ if (dat->NeedResort)
+ {
+ TRACE("Sort required\n");
+ clcSetDelayTimer( TIMERID_DELAYEDRESORTCLC, hwnd );
+ }
+ else if (needRepaint)
+ {
+ if (contact && contact->pos_icon.bottom != 0 && contact->pos_icon.right != 0)
+ CLUI__cliInvalidateRect(hwnd,&(contact->pos_icon),FALSE);
+ else
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ //try only needed rectangle
+ }
+
+ return 0;
+}
+
+static LRESULT clcOnIntmAvatarChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct ClcContact *contact;
+ if (FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL,FALSE))
+ {
+ Cache_GetAvatar(dat, contact);
+ }
+ else if (dat->use_avatar_service && !wParam)
+ {
+ UpdateAllAvatars(dat);
+ }
+ CLUI__cliInvalidateRect(hwnd, NULL, FALSE);
+ return 0;
+}
+
+static LRESULT clcOnIntmTimeZoneChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct ClcContact *contact;
+ if ( !FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL,FALSE))
+ return corecli.pfnContactListControlWndProc(hwnd,msg,wParam,lParam);
+
+ if (contact) //!IsBadWritePtr(contact, sizeof(struct ClcContact)))
+ {
+ Cache_GetTimezone(dat,contact->hContact);
+ Cache_GetText(dat, contact,1);
+ cliRecalcScrollBar(hwnd,dat);
+ }
+ return 0;
+}
+static LRESULT clcOnIntmNameChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct ClcContact *contact;
+ int ret = corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+
+ pcli->pfnInvalidateDisplayNameCacheEntry((HANDLE)wParam);
+ if ( !FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL,FALSE))
+ return ret;
+
+ lstrcpyn(contact->szText, pcli->pfnGetContactDisplayName((HANDLE)wParam,0),SIZEOF(contact->szText));
+ if (contact)//!IsBadWritePtr(contact, sizeof(struct ClcContact)))
+ {
+ Cache_GetText(dat,contact,1);
+ cliRecalcScrollBar(hwnd,dat);
+ }
+ dat->NeedResort = 1;
+ pcli->pfnSortContacts();
+
+ return ret;
+}
+
+static LRESULT clcOnIntmApparentModeChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int lResult = corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ if ( !ServiceExists("ExtraIcon/Register"))
+ ExtraImage_SetAllExtraIcons(pcli->hwndContactTree,(HANDLE)wParam);
+ return lResult;
+}
+
+static LRESULT clcOnIntmStatusMsgChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct ClcContact *contact;
+ HANDLE hContact = (HANDLE)wParam;
+ if (hContact == NULL || IsHContactInfo(hContact) || IsHContactGroup(hContact))
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ if ( !FindItem(hwnd,dat,hContact,&contact,NULL,NULL,FALSE))
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ if (contact)//!IsBadWritePtr(contact, sizeof(struct ClcContact)))
+ {
+ Cache_GetText(dat,contact,1);
+ cliRecalcScrollBar(hwnd,dat);
+ PostMessage(hwnd,INTM_INVALIDATE,0,0);
+ }
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+}
+
+static LRESULT clcOnIntmNotOnListChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *dbcws = (DBCONTACTWRITESETTING*)lParam;
+ struct ClcContact *contact;
+
+ if ( !FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL,TRUE))
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+
+ if (contact->type != CLCIT_CONTACT)
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+
+ if (dbcws->value.type == DBVT_DELETED || dbcws->value.bVal == 0)
+ contact->flags &= ~CONTACTF_NOTONLIST;
+ else
+ contact->flags |= CONTACTF_NOTONLIST;
+
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+}
+
+static LRESULT clcOnIntmScrollBarChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_CONTACTLIST)
+ {
+ if (dat->noVScrollbar) ShowScrollBar(hwnd, SB_VERT, FALSE);
+ else pcli->pfnRecalcScrollBar(hwnd, dat);
+ }
+ return 0;
+}
+
+static LRESULT clcOnIntmStatusChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int ret = corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ if (wParam != 0)
+ {
+ pdisplayNameCacheEntry pdnce = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry((HANDLE)wParam);
+ if (pdnce && pdnce->m_cache_cszProto)
+ {
+ struct ClcContact *contact = NULL;
+ pdnce___SetStatus( pdnce, GetStatusForContact(pdnce->hContact,pdnce->m_cache_cszProto));
+ if ( !dat->force_in_dialog && (
+ (dat->second_line_show)// && dat->second_line_type == TEXT_STATUS)
+ || (dat->third_line_show)// && dat->third_line_type == TEXT_STATUS)
+ ))
+ gtaRenewText(pdnce->hContact);
+ SendMessage(hwnd,INTM_ICONCHANGED, wParam, (LPARAM) CallService(MS_CLIST_GETCONTACTICON, wParam, 1));
+ if (FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL,TRUE))
+ {
+ if (contact && contact->type == CLCIT_CONTACT)
+ {
+ if ( !contact->image_is_special && pdnce___GetStatus( pdnce )>ID_STATUS_OFFLINE)
+ contact->iImage = CallService(MS_CLIST_GETCONTACTICON, wParam, 1);
+ if (contact->isSubcontact
+ && contact->subcontacts
+ && contact->subcontacts->type == CLCIT_CONTACT)
+ pcli->pfnClcBroadcast( INTM_STATUSCHANGED,(WPARAM)contact->subcontacts->hContact,0); //forward status changing to host meta contact
+ }
+ }
+ }
+#ifdef _DEBUG
+ else
+ {
+ DebugBreak();
+ }
+#endif
+
+
+ }
+ if (db_get_b(NULL,"CList","PlaceOfflineToRoot",SETTING_PLACEOOFLINETOROOT_DEFAULT))
+ {
+ SendMessage(hwnd,CLM_AUTOREBUILD,0,0);
+ }
+ else
+ {
+ pcli->pfnSortContacts();
+ PostMessage(hwnd,INTM_INVALIDATE,0,0);
+ }
+ return ret;
+}
+
+
+
+static LRESULT clcOnIntmReloadOptions(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ pcli->pfnLoadClcOptions(hwnd,dat);
+ LoadCLCOptions(hwnd,dat);
+ pcli->pfnSaveStateAndRebuildList(hwnd,dat);
+ pcli->pfnSortCLC(hwnd,dat,1);
+ if (IsWindowVisible(hwnd))
+ pcli->pfnInvalidateRect(GetParent(hwnd), NULL, FALSE);
+ return TRUE;
+}
+
+
+HRESULT ClcLoadModule()
+{
+ g_himlCListClc = (HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST,0,0);
+
+ HookEvent(ME_DB_CONTACT_SETTINGCHANGED, clcHookSettingChanged);
+ HookEvent(ME_OPT_INITIALISE, ClcOptInit);
+ hAckHook = (HANDLE)HookEvent(ME_PROTO_ACK, clcHookProtoAck);
+ HookEvent(ME_SYSTEM_MODULESLOADED, clcHookModulesLoaded);
+ HookEvent(ME_DB_EVENT_ADDED, clcHookDbEventAdded);
+ return S_OK;
+}
+
+int ClcUnloadModule()
+{
+ if ( g_CluiData.bOldUseGroups != (BYTE)-1 )
+ db_set_b(NULL,"CList","UseGroups",(BYTE)g_CluiData.bOldUseGroups );
+ if ( g_CluiData.boldHideOffline != (BYTE)-1 )
+ db_set_b(NULL,"CList","HideOffline",(BYTE)g_CluiData.boldHideOffline );
+
+ return 0;
+}
+
+int ClcDoProtoAck(HANDLE wParam,ACKDATA * ack)
+{
+ if (MirandaExiting()) return 0;
+ if (ack->type == ACKTYPE_STATUS)
+ {
+ int i;
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ for (i=0; i < pcli->hClcProtoCount; i++)
+ {
+ if ( !lstrcmpA(pcli->clcProto[i].szProto, ack->szModule))
+ {
+ pcli->clcProto[i].dwStatus = (WORD) ack->lParam;
+ if (pcli->clcProto[i].dwStatus >= ID_STATUS_OFFLINE)
+ pcli->pfnTrayIconUpdateBase(pcli->clcProto[i].szProto);
+ if ( !ServiceExists("ExtraIcon/Register"))
+ if (ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_VISMODE) != -1)
+ ExtraImage_SetAllExtraIcons(pcli->hwndContactTree,(HANDLE)NULL);
+ return 0;
+ }
+ }
+ }
+ }
+ else if (ack->type == ACKTYPE_AWAYMSG)
+ {
+ if (ack->result == ACKRESULT_SUCCESS && ack->lParam) {
+ {//Do not change DB if it is IRC protocol
+ if (ack->szModule != NULL)
+ if (db_get_b(ack->hContact, ack->szModule, "ChatRoom", 0) != 0) return 0;
+ }
+
+ db_set_ws(ack->hContact,"CList","StatusMsg",(const TCHAR *)ack->lParam);
+ gtaRenewText(ack->hContact);
+ }
+ else
+ {
+ //DBDeleteContactSetting(ack->hContact,"CList","StatusMsg");
+ //char a = '\0';
+ {//Do not change DB if it is IRC protocol
+ if (ack->szModule != NULL)
+ if (db_get_b(ack->hContact, ack->szModule, "ChatRoom", 0) != 0) return 0;
+ }
+ if (ack->hContact)
+ {
+ char * val = db_get_sa(ack->hContact,"CList","StatusMsg");
+ if (val) {
+ if ( !mir_bool_strcmpi(val,""))
+ db_set_s(ack->hContact,"CList","StatusMsg","");
+ else
+ gtaRenewText(ack->hContact);
+ mir_free(val);
+ }
+ }
+ //pcli->pfnClcBroadcast( INTM_STATUSMSGCHANGED,(WPARAM)ack->hContact,&a);
+ }
+ }
+ else if (ack->type == ACKTYPE_AVATAR)
+ {
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ PROTO_AVATAR_INFORMATIONT *pai = (PROTO_AVATAR_INFORMATIONT*)ack->hProcess;
+ if (pai != NULL && pai->hContact != NULL)
+ pcli->pfnClcBroadcast( INTM_AVATARCHANGED,(WPARAM)pai->hContact,0);
+ }
+ }
+ else if (ack->type == ACKTYPE_EMAIL) {
+ CLUIUnreadEmailCountChanged(0,0);
+ }
+ return 0;
+}
+
+
+int ClcGetShortData(struct ClcData* pData, struct SHORTDATA *pShortData)
+{
+ if ( !pData || !pShortData) return -1;
+ pShortData->hWnd = pData->hWnd;
+ pShortData->text_replace_smileys = pData->text_replace_smileys;
+ pShortData->text_smiley_height = pData->text_smiley_height;
+ pShortData->text_use_protocol_smileys = pData->text_use_protocol_smileys;
+ pShortData->contact_time_show_only_if_different = pData->contact_time_show_only_if_different;
+ // Second line
+ pShortData->second_line_show = pData->second_line_show;
+ pShortData->second_line_draw_smileys = pData->second_line_draw_smileys;
+ pShortData->second_line_type = pData->second_line_type;
+
+ _tcsncpy(pShortData->second_line_text,pData->second_line_text,TEXT_TEXT_MAX_LENGTH);
+
+ pShortData->second_line_xstatus_has_priority = pData->second_line_xstatus_has_priority;
+ pShortData->second_line_show_status_if_no_away = pData->second_line_show_status_if_no_away;
+ pShortData->second_line_show_listening_if_no_away = pData->second_line_show_listening_if_no_away;
+ pShortData->second_line_use_name_and_message_for_xstatus = pData->second_line_use_name_and_message_for_xstatus;
+
+ pShortData->third_line_show = pData->third_line_show;
+ pShortData->third_line_draw_smileys = pData->third_line_draw_smileys;
+ pShortData->third_line_type = pData->third_line_type;
+
+ _tcsncpy(pShortData->third_line_text,pData->third_line_text,TEXT_TEXT_MAX_LENGTH);
+
+ pShortData->third_line_xstatus_has_priority = pData->third_line_xstatus_has_priority;
+ pShortData->third_line_show_status_if_no_away = pData->third_line_show_status_if_no_away;
+ pShortData->third_line_show_listening_if_no_away = pData->third_line_show_listening_if_no_away;
+ pShortData->third_line_use_name_and_message_for_xstatus = pData->third_line_use_name_and_message_for_xstatus;
+
+ return 0;
+}
+
+
+
+int ClcEnterDragToScroll(HWND hwnd, int Y)
+{
+ struct ClcData * dat;
+ if (IsDragToScrollMode) return 0;
+ dat = (struct ClcData*)GetWindowLongPtr(hwnd,0);
+ if ( !dat) return 0;
+ StartDragPos = Y;
+ StartScrollPos = dat->yScroll;
+ IsDragToScrollMode = 1;
+ SetCapture(hwnd);
+ return 1;
+}
+
+
+/*
+* Contact list control window procedure
+*/
+LRESULT CALLBACK cli_ContactListControlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+
+#define CASE_MSG_RET(msg, handler) case msg: return handler(dat, hwnd, msg, wParam, lParam);
+
+ struct ClcData *dat = (struct ClcData*)GetWindowLongPtr(hwnd,0);
+
+ if (msg >= CLM_FIRST && msg < CLM_LAST)
+ return cli_ProcessExternalMessages(hwnd,dat,msg,wParam,lParam);
+
+ switch (msg) {
+ CASE_MSG_RET( INTM_GROUPCHANGED, clcOnIntmGroupChanged );
+ CASE_MSG_RET( INTM_ICONCHANGED, clcOnIntmIconChanged );
+ CASE_MSG_RET( INTM_AVATARCHANGED, clcOnIntmAvatarChanged );
+ CASE_MSG_RET( INTM_TIMEZONECHANGED, clcOnIntmTimeZoneChanged );
+ CASE_MSG_RET( INTM_NAMECHANGED, clcOnIntmNameChanged );
+ CASE_MSG_RET( INTM_APPARENTMODECHANGED, clcOnIntmApparentModeChanged );
+ CASE_MSG_RET( INTM_STATUSMSGCHANGED, clcOnIntmStatusMsgChanged );
+ CASE_MSG_RET( INTM_NOTONLISTCHANGED, clcOnIntmNotOnListChanged );
+ CASE_MSG_RET( INTM_SCROLLBARCHANGED, clcOnIntmScrollBarChanged );
+ CASE_MSG_RET( INTM_STATUSCHANGED, clcOnIntmStatusChanged );
+ CASE_MSG_RET( INTM_RELOADOPTIONS, clcOnIntmReloadOptions );
+
+ CASE_MSG_RET( WM_CREATE, clcOnCreate );
+ CASE_MSG_RET( WM_NCHITTEST, clcOnHitTest );
+ CASE_MSG_RET( WM_COMMAND, clcOnCommand );
+ CASE_MSG_RET( WM_SIZE, clcOnSize );
+ CASE_MSG_RET( WM_CHAR, clcOnChar );
+ CASE_MSG_RET( WM_PAINT, clcOnPaint );
+ CASE_MSG_RET( WM_ERASEBKGND, clcOnEraseBkGround );
+ CASE_MSG_RET( WM_KEYDOWN, clcOnKeyDown );
+ CASE_MSG_RET( WM_TIMER, clcOnTimer );
+ CASE_MSG_RET( WM_ACTIVATE, clcOnActivate );
+ CASE_MSG_RET( WM_SETCURSOR, clcOnSetCursor );
+ CASE_MSG_RET( WM_LBUTTONDOWN, clcOnLButtonDown );
+ CASE_MSG_RET( WM_CAPTURECHANGED,clcOnCaptureChanged );
+ CASE_MSG_RET( WM_MOUSEMOVE, clcOnMouseMove );
+ CASE_MSG_RET( WM_LBUTTONUP, clcOnLButtonUp );
+ CASE_MSG_RET( WM_LBUTTONDBLCLK, clcOnLButtonDblClick );
+ CASE_MSG_RET( WM_DESTROY, clcOnDestroy );
+
+ default:
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ }
+ return TRUE;
+}
diff --git a/plugins/Clist_modern/src/modern_clcidents.cpp b/plugins/Clist_modern/src/modern_clcidents.cpp
new file mode 100644
index 0000000000..903844eb9c
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clcidents.cpp
@@ -0,0 +1,299 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_commonprototypes.h"
+
+#define CacheArrSize 255
+struct ClcGroup *CacheIndex[CacheArrSize] = {NULL};
+bool CacheIndexClear = TRUE;
+
+/* the CLC uses 3 different ways to identify elements in its list, this file
+contains routines to convert between them.
+
+1) struct ClcContact/struct ClcGroup pair. Only ever used within the duration
+of a single operation, but used at some point in nearly everything
+2) index integer. The 0-based number of the item from the top. Only visible
+items are counted (ie not closed groups). Used for saving selection and drag
+highlight
+3) hItem handle. Either the hContact or (hGroup|HCONTACT_ISGROUP). Used
+exclusively externally
+
+1->2: cliGetRowsPriorTo()
+1->3: ContactToHItem()
+3->1: FindItem()
+2->1: GetRowByIndex()
+*/
+
+int GetContactIndex(struct ClcGroup *group,struct ClcContact *contact)
+{
+ for (int i=0; i < group->cl.count; i++)
+ if (group->cl.items[i]->hContact == contact->hContact) return i;
+ return -1;
+}
+
+int cliGetRowsPriorTo(struct ClcGroup *group,struct ClcGroup *subgroup,int contactIndex)
+{
+ int count = 0;
+ BYTE k;
+ int subcontactscount = 0;
+ k = db_get_b(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT);
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL) break;
+ group->scanIndex++;
+ continue;
+ }
+ if (group == subgroup && contactIndex-subcontactscount == group->scanIndex) return count;
+ count++;
+
+ /* if ((group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) && (group->cl.items[group->scanIndex].flags & CONTACTF_STATUSMSG)) {
+ count++;
+ }
+ */
+ if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) {
+ if (group->cl.items[group->scanIndex]->group == subgroup && contactIndex == -1)
+ return count-1;
+ if (group->cl.items[group->scanIndex]->group->expanded) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ subcontactscount = 0;
+ continue;
+ }
+ }
+ if (group == subgroup)
+ {
+ if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->SubAllocated)
+ {
+ int rows = (group->cl.items[group->scanIndex]->SubAllocated*group->cl.items[group->scanIndex]->SubExpanded*k);
+ if (group->scanIndex+rows >= contactIndex)
+ return count+(contactIndex-group->scanIndex)-1;
+ }
+ }
+ if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT)
+ {
+ count += (group->cl.items[group->scanIndex]->SubAllocated*group->cl.items[group->scanIndex]->SubExpanded*k);
+ subcontactscount += (group->cl.items[group->scanIndex]->SubAllocated*group->cl.items[group->scanIndex]->SubExpanded*k);
+ }
+ group->scanIndex++;
+ }
+ return -1;
+}
+
+int cliFindItem(HWND hwnd,struct ClcData *dat,HANDLE hItem,struct ClcContact **contact,struct ClcGroup **subgroup,int *isVisible)
+{
+ return FindItem(hwnd,dat, hItem,contact,subgroup,isVisible,FALSE);
+}
+
+int FindItem(HWND hwnd,struct ClcData *dat,HANDLE hItem,struct ClcContact **contact,struct ClcGroup **subgroup,int *isVisible, BOOL isIgnoreSubcontacts)
+{
+ int index = 0, i;
+ int nowVisible = 1;
+ struct ClcGroup *group;
+
+ group = &dat->list;
+
+ group->scanIndex = 0;
+ group = &dat->list;
+
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ struct ClcGroup *tgroup;
+ group = group->parent;
+ if (group == NULL) break;
+ nowVisible = 1;
+ for (tgroup = group;tgroup;tgroup = tgroup->parent)
+ {
+ if ( !tgroup->expanded)
+ {
+ nowVisible = 0;
+ break;
+ }
+ }
+ group->scanIndex++;
+ continue;
+ }
+ if (nowVisible) index++;
+ if ((IsHContactGroup(hItem) && group->cl.items[group->scanIndex]->type == CLCIT_GROUP && ((UINT_PTR)hItem&~HCONTACT_ISGROUP) == group->cl.items[group->scanIndex]->groupId) ||
+ (IsHContactContact(hItem) && group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->hContact == hItem) ||
+ (IsHContactInfo(hItem) && group->cl.items[group->scanIndex]->type == CLCIT_INFO && group->cl.items[group->scanIndex]->hContact == (HANDLE)((UINT_PTR)hItem&~HCONTACT_ISINFO)))
+ {
+ if (isVisible) {
+ if ( !nowVisible) *isVisible = 0;
+ else {
+ int posy = cliGetRowTopY(dat,index+1);
+ if (posy < dat->yScroll)
+ *isVisible = 0;
+ else {
+ RECT clRect;
+ GetClientRect(hwnd,&clRect);
+ if (posy >= dat->yScroll+clRect.bottom) *isVisible = 0;
+ else *isVisible = 1;
+ }
+ }
+ }
+ if (contact) *contact = group->cl.items[group->scanIndex];
+ if (subgroup) *subgroup = group;
+
+ return 1;
+ }
+ if ( !isIgnoreSubcontacts &&
+ IsHContactContact(hItem) &&
+ group->cl.items[group->scanIndex]->type == CLCIT_CONTACT &&
+ group->cl.items[group->scanIndex]->SubAllocated > 0)
+ {
+ for (i=0; i < group->cl.items[group->scanIndex]->SubAllocated; i++)
+ {
+ if (group->cl.items[group->scanIndex]->subcontacts[i].hContact == hItem)
+ {
+#ifdef _DEBUG
+ if (IsBadWritePtr(&group->cl.items[group->scanIndex]->subcontacts[i], sizeof(struct ClcContact)))
+ {
+ log1("FindIltem->IsBadWritePtr | 2o [%08x]", &group->cl.items[group->scanIndex]->subcontacts[i]);
+ PostMessage(hwnd,CLM_AUTOREBUILD,0,0);
+
+ return 0;
+ }
+#endif
+ if (contact) *contact = &group->cl.items[group->scanIndex]->subcontacts[i];
+ if (subgroup) *subgroup = group;
+
+ return 1;
+ }
+ }
+ }
+
+ if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ nowVisible &= group->expanded;
+ continue;
+ }
+ group->scanIndex++;
+ }
+
+ return 0;
+}
+
+void ClearRowByIndexCache()
+{
+ if ( !CacheIndexClear)
+ {
+ memset(CacheIndex,0,sizeof(CacheIndex));
+ CacheIndexClear = TRUE;
+ };
+}
+int cliGetRowByIndex(struct ClcData *dat,int testindex,struct ClcContact **contact,struct ClcGroup **subgroup)
+{
+ int index = 0,i;
+ struct ClcGroup *group = &dat->list;
+
+ if (testindex < 0) return (-1);
+ {
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL) break;
+ group->scanIndex++;
+ continue;
+ }
+ if ((index>0) && (index < CacheArrSize))
+ {
+ CacheIndex[index] = group;
+ CacheIndexClear = FALSE;
+ };
+
+ if (testindex == index) {
+ if (contact) *contact = group->cl.items[group->scanIndex];
+ if (subgroup) *subgroup = group;
+ return index;
+ }
+
+ if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT)
+ if (group->cl.items[group->scanIndex]->SubAllocated)
+ if (group->cl.items[group->scanIndex]->SubExpanded && dat->expandMeta)
+ {
+ for (i=0;i < group->cl.items[group->scanIndex]->SubAllocated;i++)
+ {
+ if ((index>0) && (index < CacheArrSize))
+ {
+ CacheIndex[index] = group;
+ CacheIndexClear = FALSE;
+ };
+ index++;
+ if (testindex == index) {
+ if (contact)
+ {
+ *contact = &group->cl.items[group->scanIndex]->subcontacts[i];
+ (*contact)->subcontacts = group->cl.items[group->scanIndex];
+ }
+
+ if (subgroup) *subgroup = group;
+ return index;
+ }
+ }
+
+ }
+ index++;
+ if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP && group->cl.items[group->scanIndex]->group->expanded) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ continue;
+ }
+ group->scanIndex++;
+ }
+ };
+ return -1;
+}
+
+HANDLE ContactToHItem(struct ClcContact *contact)
+{
+ switch(contact->type) {
+case CLCIT_CONTACT:
+ return contact->hContact;
+case CLCIT_GROUP:
+ return (HANDLE)(contact->groupId|HCONTACT_ISGROUP);
+case CLCIT_INFO:
+ return (HANDLE)((DWORD_PTR)contact->hContact|HCONTACT_ISINFO);
+ }
+ return NULL;
+}
+
+HANDLE ContactToItemHandle(struct ClcContact *contact,DWORD *nmFlags)
+{
+ switch(contact->type) {
+case CLCIT_CONTACT:
+ return contact->hContact;
+case CLCIT_GROUP:
+ if (nmFlags) *nmFlags |= CLNF_ISGROUP;
+ return (HANDLE)contact->groupId;
+case CLCIT_INFO:
+ if (nmFlags) *nmFlags |= CLNF_ISINFO;
+ return (HANDLE)((DWORD_PTR)contact->hContact|HCONTACT_ISINFO);
+ }
+ return NULL;
+} \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_clcitems.cpp b/plugins/Clist_modern/src/modern_clcitems.cpp
new file mode 100644
index 0000000000..7a29b5e82a
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clcitems.cpp
@@ -0,0 +1,819 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_clist.h"
+#include "m_metacontacts.h"
+#include "hdr/modern_commonprototypes.h"
+
+void AddSubcontacts(struct ClcData *dat, struct ClcContact * cont, BOOL showOfflineHereGroup)
+{
+ int subcount,i,j;
+ HANDLE hsub;
+ pdisplayNameCacheEntry cacheEntry;
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(cont->hContact);
+ cont->SubExpanded = (db_get_b(cont->hContact,"CList","Expanded",0) && (db_get_b(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT)));
+ subcount = (int)CallService(MS_MC_GETNUMCONTACTS,(WPARAM)cont->hContact,0);
+
+ if (subcount <= 0) {
+ cont->isSubcontact = 0;
+ cont->subcontacts = NULL;
+ cont->SubAllocated = 0;
+ return;
+ }
+
+ cont->isSubcontact = 0;
+ mir_free(cont->subcontacts);
+ cont->subcontacts = (struct ClcContact *) mir_calloc(sizeof(struct ClcContact)*subcount);
+ cont->SubAllocated = subcount;
+ i=0;
+ for (j = 0; j < subcount; j++) {
+ WORD wStatus;
+
+ hsub = (HANDLE)CallService(MS_MC_GETSUBCONTACT,(WPARAM)cont->hContact,j);
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hsub);
+ wStatus = pdnce___GetStatus( cacheEntry );
+ if (showOfflineHereGroup || (!(db_get_b(NULL,"CLC","MetaHideOfflineSub",SETTING_METAHIDEOFFLINESUB_DEFAULT) && db_get_b(NULL,"CList","HideOffline",SETTING_HIDEOFFLINE_DEFAULT)) ||
+ wStatus != ID_STATUS_OFFLINE )
+ // &&
+ //(!cacheEntry->Hidden || style&CLS_SHOWHIDDEN)
+ )
+
+ {
+ cont->subcontacts[i].hContact = cacheEntry->hContact;
+
+ cont->subcontacts[i].avatar_pos = AVATAR_POS_DONT_HAVE;
+ Cache_GetAvatar(dat, &cont->subcontacts[i]);
+
+ cont->subcontacts[i].iImage = CallService(MS_CLIST_GETCONTACTICON,(WPARAM)cacheEntry->hContact,1);
+ memset(cont->subcontacts[i].iExtraImage,0xFF,sizeof(cont->subcontacts[i].iExtraImage));
+ memset((void*)cont->subcontacts[i].iWideExtraImage,0xFF,sizeof(cont->subcontacts[i].iWideExtraImage));
+ cont->subcontacts[i].proto = cacheEntry->m_cache_cszProto;
+ cont->subcontacts[i].type = CLCIT_CONTACT;
+ cont->subcontacts[i].flags = 0;//CONTACTF_ONLINE;
+ cont->subcontacts[i].isSubcontact = i+1;
+ cont->subcontacts[i].lastPaintCounter = 0;
+ cont->subcontacts[i].subcontacts = cont;
+ cont->subcontacts[i].image_is_special = FALSE;
+ //cont->subcontacts[i].status = cacheEntry->status;
+ Cache_GetTimezone(dat, (&cont->subcontacts[i])->hContact);
+ Cache_GetText(dat, &cont->subcontacts[i],1);
+
+ {
+ int apparentMode;
+ char *szProto;
+ int idleMode;
+ szProto = cacheEntry->m_cache_cszProto;
+ if (szProto != NULL && !pcli->pfnIsHiddenMode(dat,wStatus))
+ cont->subcontacts[i].flags |= CONTACTF_ONLINE;
+ apparentMode = szProto != NULL?cacheEntry->ApparentMode:0;
+ apparentMode = szProto != NULL?cacheEntry->ApparentMode:0;
+ if (apparentMode == ID_STATUS_OFFLINE) cont->subcontacts[i].flags |= CONTACTF_INVISTO;
+ else if (apparentMode == ID_STATUS_ONLINE) cont->subcontacts[i].flags |= CONTACTF_VISTO;
+ else if (apparentMode) cont->subcontacts[i].flags |= CONTACTF_VISTO|CONTACTF_INVISTO;
+ if (cacheEntry->NotOnList) cont->subcontacts[i].flags |= CONTACTF_NOTONLIST;
+ idleMode = szProto != NULL?cacheEntry->IdleTS:0;
+ if (idleMode) cont->subcontacts[i].flags |= CONTACTF_IDLE;
+ }
+ i++;
+ } }
+
+ cont->SubAllocated = i;
+ if ( !i && cont->subcontacts != NULL)
+ mir_free_and_nil(cont->subcontacts);
+}
+
+int cli_AddItemToGroup(struct ClcGroup *group,int iAboveItem)
+{
+ if ( group == NULL ) return 0;
+
+ iAboveItem = corecli.pfnAddItemToGroup( group, iAboveItem );
+ ClearRowByIndexCache();
+ return iAboveItem;
+}
+
+struct ClcGroup *cli_AddGroup(HWND hwnd,struct ClcData *dat,const TCHAR *szName,DWORD flags,int groupId,int calcTotalMembers)
+{
+ struct ClcGroup* result;
+ ClearRowByIndexCache();
+ if ( !dat->force_in_dialog && !(GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_SHOWHIDDEN))
+ if ( !lstrcmp(_T("-@-HIDDEN-GROUP-@-"),szName)) //group is hidden
+ {
+ ClearRowByIndexCache();
+ return NULL;
+ }
+ result = corecli.pfnAddGroup( hwnd, dat, szName, flags, groupId, calcTotalMembers);
+ /* ToDo: fix some times valid contact with valid group are placed to root
+ if ( result == NULL )
+ {
+ result = &dat->list;
+ }
+ */
+ ClearRowByIndexCache();
+ return result;
+}
+
+void cli_FreeContact(struct ClcContact *p)
+{
+ if ( p->SubAllocated) {
+ if ( p->subcontacts && !p->isSubcontact) {
+ int i;
+ for ( i=0 ; i < p->SubAllocated ; i++ ) {
+ p->subcontacts[i].ssText.DestroySmileyList();
+ if ( p->subcontacts[i].avatar_pos == AVATAR_POS_ANIMATED )
+ AniAva_RemoveAvatar( p->subcontacts[i].hContact );
+ p->subcontacts[i].avatar_pos = AVATAR_POS_DONT_HAVE;
+ }
+ mir_free_and_nil(p->subcontacts);
+ } }
+
+ p->ssText.DestroySmileyList();
+ if ( p->avatar_pos == AVATAR_POS_ANIMATED )
+ AniAva_RemoveAvatar( p->hContact );
+ p->avatar_pos = AVATAR_POS_DONT_HAVE;
+ corecli.pfnFreeContact( p );
+}
+
+void cli_FreeGroup( struct ClcGroup* group )
+{
+ corecli.pfnFreeGroup( group );
+ ClearRowByIndexCache();
+}
+
+int cli_AddInfoItemToGroup(struct ClcGroup *group,int flags,const TCHAR *pszText)
+{
+ int i = corecli.pfnAddInfoItemToGroup( group, flags, pszText );
+ ClearRowByIndexCache();
+ return i;
+}
+
+static void _LoadDataToContact(struct ClcContact * cont, struct ClcGroup *group, struct ClcData *dat, HANDLE hContact)
+{
+ pdisplayNameCacheEntry cacheEntry = NULL;
+ WORD apparentMode;
+ DWORD idleMode;
+ char * szProto;
+
+ if ( !cont) return;
+ cont->type = CLCIT_CONTACT;
+ cont->SubAllocated = 0;
+ cont->isSubcontact = 0;
+ cont->subcontacts = NULL;
+ cont->szText[0] = 0;
+ cont->lastPaintCounter = 0;
+ cont->image_is_special = FALSE;
+ cont->hContact = hContact;
+
+ pcli->pfnInvalidateDisplayNameCacheEntry(hContact);
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+
+ szProto = cacheEntry->m_cache_cszProto;
+ cont->proto = szProto;
+
+ if (szProto != NULL && !pcli->pfnIsHiddenMode(dat,pdnce___GetStatus( cacheEntry )))
+ cont->flags |= CONTACTF_ONLINE;
+
+ apparentMode = szProto != NULL?cacheEntry->ApparentMode:0;
+
+ if (apparentMode)
+ switch (apparentMode)
+ {
+ case ID_STATUS_OFFLINE:
+ cont->flags |= CONTACTF_INVISTO;
+ break;
+ case ID_STATUS_ONLINE:
+ cont->flags |= CONTACTF_VISTO;
+ break;
+ default:
+ cont->flags |= CONTACTF_VISTO|CONTACTF_INVISTO;
+ }
+
+ if (cacheEntry->NotOnList)
+ cont->flags |= CONTACTF_NOTONLIST;
+ idleMode = szProto != NULL?cacheEntry->IdleTS:0;
+
+ if (idleMode)
+ cont->flags |= CONTACTF_IDLE;
+
+
+ //Add subcontacts
+ if (szProto)
+ {
+ if ( g_szMetaModuleName && dat->IsMetaContactsEnabled && mir_strcmp(cont->proto,g_szMetaModuleName) == 0)
+ AddSubcontacts(dat,cont,CLCItems_IsShowOfflineGroup(group));
+ }
+ cont->lastPaintCounter = 0;
+ cont->avatar_pos = AVATAR_POS_DONT_HAVE;
+ Cache_GetAvatar(dat,cont);
+ Cache_GetText(dat,cont,1);
+ Cache_GetTimezone(dat,cont->hContact);
+ cont->iImage = CallService(MS_CLIST_GETCONTACTICON,(WPARAM)hContact,1);
+ cont->bContactRate = db_get_b(hContact, "CList", "Rate",0);
+}
+
+static struct ClcContact * AddContactToGroup(struct ClcData *dat,struct ClcGroup *group, pdisplayNameCacheEntry cacheEntry)
+{
+ HANDLE hContact;
+ int i;
+ if (cacheEntry == NULL) return NULL;
+ if (group == NULL) return NULL;
+ if (dat == NULL) return NULL;
+ hContact = cacheEntry->hContact;
+ dat->NeedResort = 1;
+ for (i = group->cl.count-1;i >= 0;i--)
+ if (group->cl.items[i]->type != CLCIT_INFO || !(group->cl.items[i]->flags&CLCIIF_BELOWCONTACTS)) break;
+ i = cli_AddItemToGroup(group,i+1);
+
+ _LoadDataToContact(group->cl.items[i], group, dat, hContact);
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ ClearRowByIndexCache();
+ return group->cl.items[i];
+}
+
+void * AddTempGroup(HWND hwnd,struct ClcData *dat,const TCHAR *szName,DWORD flags,int groupId,int calcTotalMembers)
+{
+ int i=0;
+ int f = 0;
+ TCHAR * szGroupName;
+ DWORD groupFlags;
+
+ if ( wildcmp( _T2A(szName), "-@-HIDDEN-GROUP-@-",0))
+ return NULL;
+
+ for (i = 1;;i++) {
+ szGroupName = pcli->pfnGetGroupName(i,&groupFlags);
+ if (szGroupName == NULL) break;
+ if ( !mir_tstrcmpi(szGroupName,szName)) f = 1;
+ }
+ if ( !f)
+ {
+ char buf[20];
+ TCHAR b2[255];
+ void * res = NULL;
+ mir_snprintf(buf,SIZEOF(buf),"%d",(i-1));
+ mir_sntprintf(b2,SIZEOF(b2),_T("#%s"),szName);
+ b2[0] = 1|GROUPF_EXPANDED;
+ db_set_ws(NULL,"CListGroups",buf,b2);
+ pcli->pfnGetGroupName(i,&groupFlags);
+ res = cli_AddGroup(hwnd,dat,szName,groupFlags,i,0);
+ return res;
+ }
+ return NULL;
+}
+
+void cli_AddContactToTree(HWND hwnd,struct ClcData *dat,HANDLE hContact,int updateTotalCount,int checkHideOffline)
+{
+ struct ClcGroup *group;
+ struct ClcContact * cont;
+ pdisplayNameCacheEntry cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ if (dat->IsMetaContactsEnabled && cacheEntry && cacheEntry->m_cache_nHiddenSubcontact) return; //contact should not be added
+ if ( !dat->IsMetaContactsEnabled && cacheEntry && g_szMetaModuleName && !mir_strcmp(cacheEntry->m_cache_cszProto,g_szMetaModuleName)) return;
+ corecli.pfnAddContactToTree(hwnd,dat,hContact,updateTotalCount,checkHideOffline);
+ if (FindItem(hwnd,dat,hContact,&cont,&group,NULL,FALSE))
+ _LoadDataToContact(cont, group, dat, hContact);
+ return;
+}
+
+void cli_DeleteItemFromTree(HWND hwnd,HANDLE hItem)
+{
+ struct ClcData *dat = (struct ClcData *) GetWindowLongPtr(hwnd, 0);
+ ClearRowByIndexCache();
+ corecli.pfnDeleteItemFromTree(hwnd, hItem);
+
+ //check here contacts are not resorting
+ if (hwnd == pcli->hwndContactTree)
+ pcli->pfnFreeCacheItem(pcli->pfnGetCacheEntry(hItem));
+ dat->NeedResort = 1;
+ ClearRowByIndexCache();
+}
+
+
+__inline BOOL CLCItems_IsShowOfflineGroup(struct ClcGroup* group)
+{
+ DWORD groupFlags = 0;
+ if ( !group) return FALSE;
+ if (group->hideOffline) return FALSE;
+ pcli->pfnGetGroupName(group->groupId,&groupFlags);
+ return (groupFlags&GROUPF_SHOWOFFLINE) != 0;
+}
+
+HANDLE SaveSelection( struct ClcData *dat )
+{
+ ClcContact * selcontact = NULL;
+
+ if ( pcli->pfnGetRowByIndex( dat, dat->selection, &selcontact, NULL ) == -1 )
+ return NULL;
+ else
+ return pcli->pfnContactToHItem( selcontact );
+}
+
+int RestoreSelection( struct ClcData *dat, HANDLE hSelected )
+{
+ ClcContact * selcontact = NULL;
+ ClcGroup * selgroup = NULL;
+
+ if ( !hSelected || !pcli->pfnFindItem( dat->hWnd, dat, hSelected, &selcontact, &selgroup, NULL))
+ {
+ dat->selection = -1;
+ return dat->selection;
+ }
+
+ if ( !selcontact->isSubcontact )
+ {
+ dat->selection = pcli->pfnGetRowsPriorTo( &dat->list, selgroup, List_IndexOf((SortedList*)&selgroup->cl, selcontact ));
+ }
+ else
+ {
+ dat->selection = pcli->pfnGetRowsPriorTo(&dat->list, selgroup, List_IndexOf((SortedList*)&selgroup->cl, selcontact->subcontacts ));
+
+ if (dat->selection != -1 )
+ dat->selection += selcontact->isSubcontact;
+ }
+ return dat->selection;
+
+}
+
+void cliRebuildEntireList(HWND hwnd,struct ClcData *dat)
+{
+ DWORD style = GetWindowLongPtr(hwnd,GWL_STYLE);
+ HANDLE hContact;
+ struct ClcContact * cont;
+ struct ClcGroup *group;
+ static int rebuildCounter = 0;
+
+ BOOL PlaceOfflineToRoot = db_get_b(NULL,"CList","PlaceOfflineToRoot",SETTING_PLACEOFFLINETOROOT_DEFAULT);
+ KillTimer(hwnd,TIMERID_REBUILDAFTER);
+
+ ClearRowByIndexCache();
+ ImageArray_Clear(&dat->avatar_cache);
+ RowHeights_Clear(dat);
+ RowHeights_GetMaxRowHeight(dat, hwnd);
+ TRACEVAR("Rebuild Entire List %d times\n",++rebuildCounter);
+
+ dat->list.expanded = 1;
+ dat->list.hideOffline = db_get_b(NULL,"CLC","HideOfflineRoot",SETTING_HIDEOFFLINEATROOT_DEFAULT) && style&CLS_USEGROUPS;
+ dat->list.cl.count = dat->list.cl.limit = 0;
+ dat->list.cl.increment = 50;
+ dat->NeedResort = 1;
+
+ HANDLE hSelected = SaveSelection( dat );
+ dat->selection = -1;
+ dat->HiLightMode = db_get_b(NULL,"CLC","HiLightMode",SETTING_HILIGHTMODE_DEFAULT);
+ {
+ int i;
+ TCHAR *szGroupName;
+ DWORD groupFlags;
+
+ for (i = 1;;i++) {
+ szGroupName = pcli->pfnGetGroupName(i,&groupFlags); //UNICODE
+ if (szGroupName == NULL) break;
+ cli_AddGroup(hwnd,dat,szGroupName,groupFlags,i,0);
+ }
+ }
+
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ while(hContact)
+ {
+ pdisplayNameCacheEntry cacheEntry = NULL;
+ int nHiddenStatus;
+ cont = NULL;
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+
+ nHiddenStatus = CLVM_GetContactHiddenStatus(hContact, NULL, dat);
+ if ((style&CLS_SHOWHIDDEN && nHiddenStatus != -1) || !nHiddenStatus)
+ {
+
+ if (lstrlen(cacheEntry->tszGroup) == 0)
+ group = &dat->list;
+ else {
+ group = cli_AddGroup(hwnd,dat,cacheEntry->tszGroup,(DWORD)-1,0,0);
+ }
+ if (group != NULL)
+ {
+ WORD wStatus = pdnce___GetStatus( cacheEntry );
+ if (wStatus == ID_STATUS_OFFLINE)
+ if (PlaceOfflineToRoot)
+ group = &dat->list;
+ group->totalMembers++;
+
+ if ( !(style&CLS_NOHIDEOFFLINE) && (style&CLS_HIDEOFFLINE || group->hideOffline))
+ {
+ if (cacheEntry->m_cache_cszProto == NULL) {
+ if ( !pcli->pfnIsHiddenMode(dat,ID_STATUS_OFFLINE) || cacheEntry->m_cache_nNoHiddenOffline || CLCItems_IsShowOfflineGroup(group))
+ cont = AddContactToGroup(dat,group,cacheEntry);
+ }
+ else
+ if ( !pcli->pfnIsHiddenMode(dat,wStatus) || cacheEntry->m_cache_nNoHiddenOffline || CLCItems_IsShowOfflineGroup(group))
+ cont = AddContactToGroup(dat,group,cacheEntry);
+ }
+ else cont = AddContactToGroup(dat,group,cacheEntry);
+ }
+ }
+ if (cont)
+ {
+ cont->SubAllocated = 0;
+ if (cont->proto && g_szMetaModuleName && dat->IsMetaContactsEnabled && strcmp(cont->proto,g_szMetaModuleName) == 0)
+ AddSubcontacts(dat,cont,CLCItems_IsShowOfflineGroup(group));
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0);
+ }
+
+ if (style&CLS_HIDEEMPTYGROUPS) {
+ group = &dat->list;
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL) break;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) {
+ if (group->cl.items[group->scanIndex]->group->cl.count == 0) {
+ group = pcli->pfnRemoveItemFromGroup(hwnd,group,group->cl.items[group->scanIndex],0);
+ }
+ else {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ }
+ continue;
+ }
+ group->scanIndex++;
+ }
+ }
+
+ pcli->pfnSortCLC(hwnd,dat,0);
+
+ RestoreSelection( dat, hSelected );
+
+}
+
+void cli_SortCLC( HWND hwnd, struct ClcData *dat, int useInsertionSort )
+{
+ HANDLE hSelected = SaveSelection( dat );
+
+ corecli.pfnSortCLC(hwnd,dat,useInsertionSort);
+
+ RestoreSelection( dat, hSelected );
+}
+
+int GetNewSelection(struct ClcGroup *group, int selection, int direction)
+{
+ int lastcount = 0, count = 0;//group->cl.count;
+ if (selection < 0) {
+ return 0;
+ }
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL) break;
+ group->scanIndex++;
+ continue;
+ }
+ if (count >= selection) return count;
+ lastcount = count;
+ count++;
+ if ( !direction) {
+ if (count>selection) return lastcount;
+ }
+ if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP && (group->cl.items[group->scanIndex]->group->expanded)) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ continue;
+ }
+ group->scanIndex++;
+ }
+ return lastcount;
+}
+
+struct SavedContactState_t {
+ HANDLE hContact;
+ BYTE iExtraImage[MAXEXTRACOLUMNS];
+ WORD iWideExtraImage[MAXEXTRACOLUMNS];
+ int checked;
+};
+
+struct SavedGroupState_t {
+ int groupId,expanded;
+};
+
+struct SavedInfoState_t {
+ int parentId;
+ struct ClcContact contact;
+};
+
+BOOL LOCK_RECALC_SCROLLBAR = FALSE;
+void cli_SaveStateAndRebuildList(HWND hwnd, struct ClcData *dat)
+{
+ LOCK_RECALC_SCROLLBAR = TRUE;
+
+ NMCLISTCONTROL nm;
+ int i, j;
+ OBJLIST<SavedGroupState_t> savedGroup( 4 );
+ OBJLIST<SavedContactState_t> savedContact( 4 );
+ OBJLIST<SavedInfoState_t> savedInfo( 4 );
+
+ struct ClcGroup *group;
+ struct ClcContact *contact;
+
+ pcli->pfnHideInfoTip(hwnd, dat);
+ KillTimer(hwnd, TIMERID_INFOTIP);
+ KillTimer(hwnd, TIMERID_RENAME);
+ pcli->pfnEndRename(hwnd, dat, 1);
+
+ dat->NeedResort = 1;
+ group = &dat->list;
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL)
+ break;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+
+ SavedGroupState_t* p = new SavedGroupState_t;
+ p->groupId = group->groupId;
+ p->expanded = group->expanded;
+ savedGroup.insert( p );
+ continue;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) {
+ SavedContactState_t* p = new SavedContactState_t;
+ p->hContact = group->cl.items[group->scanIndex]->hContact;
+ CopyMemory(p->iExtraImage, group->cl.items[group->scanIndex]->iExtraImage,
+ sizeof(group->cl.items[group->scanIndex]->iExtraImage));
+
+ CopyMemory((void*)p->iWideExtraImage, (void*)group->cl.items[group->scanIndex]->iWideExtraImage,
+ sizeof(group->cl.items[group->scanIndex]->iWideExtraImage));
+
+ p->checked = group->cl.items[group->scanIndex]->flags & CONTACTF_CHECKED;
+ savedContact.insert( p );
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_INFO) {
+ SavedInfoState_t* p = new SavedInfoState_t;
+ memset( p, 0, sizeof( SavedInfoState_t ));
+ if (group->parent == NULL)
+ p->parentId = -1;
+ else
+ p->parentId = group->groupId;
+ p->contact = *group->cl.items[group->scanIndex];
+ savedInfo.insert( p );
+ }
+ group->scanIndex++;
+ }
+
+ pcli->pfnFreeGroup(&dat->list);
+ pcli->pfnRebuildEntireList(hwnd, dat);
+
+ group = &dat->list;
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL)
+ break;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ for (i=0; i < savedGroup.getCount(); i++)
+ if (savedGroup[i].groupId == group->groupId) {
+ group->expanded = savedGroup[i].expanded;
+ break;
+ }
+ continue;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) {
+ for (i=0; i < savedContact.getCount(); i++)
+ if (savedContact[i].hContact == group->cl.items[group->scanIndex]->hContact) {
+ CopyMemory(group->cl.items[group->scanIndex]->iExtraImage, savedContact[i].iExtraImage,
+ sizeof(group->cl.items[group->scanIndex]->iExtraImage));
+
+ CopyMemory((void*)group->cl.items[group->scanIndex]->iWideExtraImage, (void*)savedContact[i].iWideExtraImage,
+ sizeof(group->cl.items[group->scanIndex]->iWideExtraImage));
+
+ if (savedContact[i].checked)
+ group->cl.items[group->scanIndex]->flags |= CONTACTF_CHECKED;
+ break;
+ }
+ }
+ group->scanIndex++;
+ }
+ savedGroup.destroy();
+ savedContact.destroy();
+
+ for (i=0; i < savedInfo.getCount(); i++) {
+ if (savedInfo[i].parentId == -1)
+ group = &dat->list;
+ else {
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) (savedInfo[i].parentId | HCONTACT_ISGROUP), &contact, NULL, NULL))
+ continue;
+ group = contact->group;
+ }
+ j = pcli->pfnAddInfoItemToGroup(group, savedInfo[i].contact.flags, _T(""));
+ *group->cl.items[j] = savedInfo[i].contact;
+ }
+ savedInfo.destroy();
+
+ LOCK_RECALC_SCROLLBAR = FALSE;
+ pcli->pfnRecalculateGroupCheckboxes(hwnd, dat);
+
+ pcli->pfnRecalcScrollBar(hwnd, dat);
+ nm.hdr.code = CLN_LISTREBUILT;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM) & nm);
+}
+
+
+WORD pdnce___GetStatus(pdisplayNameCacheEntry pdnce)
+{
+ if ( !pdnce)
+ return ID_STATUS_OFFLINE;
+ else
+ return pdnce->m_cache_nStatus;
+ /*
+ // this stub will replace direct usage of m_cache_nStatus and will be substituted by getting info from DB directrly
+ if ( !pdnce) return ID_STATUS_OFFLINE;
+ if ( !pdnce->m_cache_cszProto) return ID_STATUS_OFFLINE;
+ if ( !pdnce->hContact) return ID_STATUS_OFFLINE;
+ return DBGetContactSettingWord( pdnce->hContact, pdnce->m_cache_cszProto, "Status" , ID_STATUS_OFFLINE );
+ */
+}
+
+
+void pdnce___SetStatus( pdisplayNameCacheEntry pdnce, WORD wStatus )
+{
+ if (pdnce) pdnce->m_cache_nStatus = wStatus;
+}
+struct ClcContact* cliCreateClcContact( void )
+{
+ struct ClcContact* contact = (struct ClcContact*)mir_calloc(sizeof( struct ClcContact ));
+ memset((void*)contact->iWideExtraImage,0xFF,sizeof(contact->iWideExtraImage));
+ return contact;
+}
+
+ClcCacheEntryBase* cliCreateCacheItem( HANDLE hContact )
+{
+ pdisplayNameCacheEntry p = (pdisplayNameCacheEntry)mir_calloc(sizeof( displayNameCacheEntry ));
+ if ( p )
+ {
+ memset(p,0,sizeof( displayNameCacheEntry ));
+ p->hContact = hContact;
+ InvalidateDNCEbyPointer(hContact,p,0);
+ p->szSecondLineText = NULL;
+ p->szThirdLineText = NULL;
+ p->ssSecondLine.plText = NULL;
+ p->ssThirdLine.plText = NULL;
+ }
+ return (ClcCacheEntryBase*)p;
+}
+
+
+
+void cliInvalidateDisplayNameCacheEntry(HANDLE hContact)
+{
+ pdisplayNameCacheEntry p;
+ p = (pdisplayNameCacheEntry) pcli->pfnGetCacheEntry(hContact);
+ if (p) InvalidateDNCEbyPointer(hContact,p,0);
+ return;
+}
+
+char* cli_GetGroupCountsText(struct ClcData *dat, struct ClcContact *contact)
+{
+ char * res;
+
+ res = corecli.pfnGetGroupCountsText(dat, contact);
+
+ return res;
+}
+
+int cliGetGroupContentsCount(struct ClcGroup *group, int visibleOnly)
+{
+ int count = group->cl.count;
+ struct ClcGroup *topgroup = group;
+
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ if (group == topgroup)
+ break;
+ group = group->parent;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP && (!(visibleOnly&0x01) || group->cl.items[group->scanIndex]->group->expanded)) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ count += group->cl.count;
+ continue;
+ }
+ else if ((group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) &&
+ (group->cl.items[group->scanIndex]->subcontacts != NULL) &&
+ ((group->cl.items[group->scanIndex]->SubExpanded || (!visibleOnly))))
+ {
+ count += group->cl.items[group->scanIndex]->SubAllocated;
+ }
+ group->scanIndex++;
+ }
+ return count;
+}
+
+/*
+* checks the currently active view mode filter and returns true, if the contact should be hidden
+* if no view mode is active, it returns the CList/Hidden setting
+* also cares about sub contacts (if meta is active)
+*/
+
+int __fastcall CLVM_GetContactHiddenStatus(HANDLE hContact, char *szProto, struct ClcData *dat)
+{
+ int dbHidden = db_get_b(hContact, "CList", "Hidden", 0); // default hidden state, always respect it.
+ int filterResult = 1;
+ DBVARIANT dbv = {0};
+ char szTemp[64];
+ TCHAR szGroupMask[256];
+ DWORD dwLocalMask;
+ PDNCE pdnce = (PDNCE)pcli->pfnGetCacheEntry(hContact);
+ BOOL fEmbedded = dat->force_in_dialog;
+ // always hide subcontacts (but show them on embedded contact lists)
+
+ if (g_CluiData.bMetaAvail && dat != NULL && dat->IsMetaContactsEnabled && g_szMetaModuleName && db_get_b(hContact, g_szMetaModuleName, "IsSubcontact", 0))
+ return -1; //subcontact
+ if (pdnce && pdnce->isUnknown && !fEmbedded)
+ return 1; //'Unknown Contact'
+ if (pdnce && g_CluiData.bFilterEffective && !fEmbedded)
+ {
+ if (szProto == NULL)
+ szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ // check stickies first (priority), only if we really have stickies defined (CLVM_STICKY_CONTACTS is set).
+ if (g_CluiData.bFilterEffective & CLVM_STICKY_CONTACTS)
+ {
+ if ((dwLocalMask = db_get_dw(hContact, CLVM_MODULE, g_CluiData.current_viewmode, 0)) != 0) {
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_STICKYSTATUS)
+ {
+ WORD wStatus = db_get_w(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ return !((1 << (wStatus - ID_STATUS_OFFLINE)) & HIWORD(dwLocalMask));
+ }
+ return 0;
+ }
+ }
+ // check the proto, use it as a base filter result for all further checks
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_PROTOS) {
+ mir_snprintf(szTemp, SIZEOF(szTemp), "%s|", szProto);
+ filterResult = strstr(g_CluiData.protoFilter, szTemp) ? 1 : 0;
+ }
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_GROUPS) {
+ if ( !DBGetContactSettingTString(hContact, "CList", "Group", &dbv)) {
+ mir_sntprintf(szGroupMask, SIZEOF(szGroupMask), _T("%s|"), &dbv.ptszVal[0]);
+ filterResult = (g_CluiData.filterFlags & CLVM_PROTOGROUP_OP) ? (filterResult | (_tcsstr(g_CluiData.groupFilter, szGroupMask) ? 1 : 0)) : (filterResult & (_tcsstr(g_CluiData.groupFilter, szGroupMask) ? 1 : 0));
+ mir_free(dbv.ptszVal);
+ }
+ else if (g_CluiData.filterFlags & CLVM_INCLUDED_UNGROUPED)
+ filterResult = (g_CluiData.filterFlags & CLVM_PROTOGROUP_OP) ? filterResult : filterResult & 1;
+ else
+ filterResult = (g_CluiData.filterFlags & CLVM_PROTOGROUP_OP) ? filterResult : filterResult & 0;
+ }
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_STATUS) {
+ WORD wStatus = db_get_w(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ filterResult = (g_CluiData.filterFlags & CLVM_GROUPSTATUS_OP) ? ((filterResult | ((1 << (wStatus - ID_STATUS_OFFLINE)) & g_CluiData.statusMaskFilter ? 1 : 0))) : (filterResult & ((1 << (wStatus - ID_STATUS_OFFLINE)) & g_CluiData.statusMaskFilter ? 1 : 0));
+ }
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_LASTMSG)
+ {
+ DWORD now;
+ PDNCE pdnce = (PDNCE)pcli->pfnGetCacheEntry(hContact);
+ if (pdnce)
+ {
+ now = g_CluiData.t_now;
+ now -= g_CluiData.lastMsgFilter;
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_LASTMSG_OLDERTHAN)
+ filterResult = filterResult & (pdnce->dwLastMsgTime < now);
+ else if (g_CluiData.bFilterEffective & CLVM_FILTER_LASTMSG_NEWERTHAN)
+ filterResult = filterResult & (pdnce->dwLastMsgTime > now);
+ }
+ }
+ return (dbHidden | !filterResult);
+ }
+ else
+ return dbHidden;
+}
diff --git a/plugins/Clist_modern/src/modern_clcmsgs.cpp b/plugins/Clist_modern/src/modern_clcmsgs.cpp
new file mode 100644
index 0000000000..cef111c793
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clcmsgs.cpp
@@ -0,0 +1,262 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_commonprototypes.h"
+
+
+//processing of all the CLM_ messages incoming
+
+LRESULT cli_ProcessExternalMessages(HWND hwnd,struct ClcData *dat,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ ClcContact *contact;
+ ClcGroup *group;
+
+ switch(msg) {
+ case CLM_DELETEITEM:
+ pcli->pfnDeleteItemFromTree(hwnd, (HANDLE) wParam);
+ clcSetDelayTimer( TIMERID_DELAYEDRESORTCLC, hwnd, 1 ); //pcli->pfnSortCLC(hwnd, dat, 1);
+ clcSetDelayTimer( TIMERID_RECALCSCROLLBAR, hwnd, 2 ); //pcli->pfnRecalcScrollBar(hwnd, dat);
+ return 0;
+
+ case CLM_AUTOREBUILD:
+ if (dat->force_in_dialog)
+ pcli->pfnSaveStateAndRebuildList(hwnd, dat);
+ else {
+ clcSetDelayTimer( TIMERID_REBUILDAFTER, hwnd );
+ CLM_AUTOREBUILD_WAS_POSTED = FALSE;
+ }
+ return 0;
+
+ case CLM_SETEXTRACOLUMNSSPACE:
+ dat->extraColumnSpacing = (int)wParam;
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ return 0;
+
+ case CLM_SETFONT:
+ if (HIWORD(lParam) < 0 || HIWORD(lParam)>FONTID_MODERN_MAX) return 0;
+
+ dat->fontModernInfo[HIWORD(lParam)].hFont = (HFONT)wParam;
+ dat->fontModernInfo[HIWORD(lParam)].changed = 1;
+
+ RowHeights_GetMaxRowHeight(dat, hwnd);
+
+ if (LOWORD(lParam))
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ return 0;
+
+ case CLM_SETHIDEEMPTYGROUPS:
+ {
+ BOOL old = ((GetWindowLongPtr(hwnd,GWL_STYLE)&CLS_HIDEEMPTYGROUPS) != 0);
+ BOOL newval = old;
+ if (wParam) SetWindowLongPtr(hwnd,GWL_STYLE,GetWindowLongPtr(hwnd,GWL_STYLE)|CLS_HIDEEMPTYGROUPS);
+ else SetWindowLongPtr(hwnd,GWL_STYLE,GetWindowLongPtr(hwnd,GWL_STYLE)&~CLS_HIDEEMPTYGROUPS);
+ newval = ((GetWindowLongPtr(hwnd,GWL_STYLE)&CLS_HIDEEMPTYGROUPS) != 0);
+ if (newval != old)
+ SendMessage(hwnd,CLM_AUTOREBUILD,0,0);
+ }
+ return 0;
+
+ case CLM_SETTEXTCOLOR:
+ if (wParam < 0 || wParam>FONTID_MODERN_MAX) break;
+
+ dat->fontModernInfo[wParam].colour = lParam;
+ dat->force_in_dialog = TRUE;
+ // Issue 40: option knows nothing about moderns colors
+ // others who know have to set colors from lowest to highest
+ switch ( wParam ) {
+ case FONTID_CONTACTS:
+ dat->fontModernInfo[FONTID_SECONDLINE].colour = lParam;
+ dat->fontModernInfo[FONTID_THIRDLINE].colour = lParam;
+ dat->fontModernInfo[FONTID_AWAY].colour = lParam;
+ dat->fontModernInfo[FONTID_DND].colour = lParam;
+ dat->fontModernInfo[FONTID_NA].colour = lParam;
+ dat->fontModernInfo[FONTID_OCCUPIED].colour = lParam;
+ dat->fontModernInfo[FONTID_CHAT].colour = lParam;
+ dat->fontModernInfo[FONTID_INVISIBLE].colour = lParam;
+ dat->fontModernInfo[FONTID_PHONE].colour = lParam;
+ dat->fontModernInfo[FONTID_LUNCH].colour = lParam;
+ dat->fontModernInfo[FONTID_CONTACT_TIME].colour = lParam;
+ break;
+ case FONTID_OPENGROUPS:
+ dat->fontModernInfo[FONTID_CLOSEDGROUPS].colour = lParam;
+ break;
+ case FONTID_OPENGROUPCOUNTS:
+ dat->fontModernInfo[FONTID_CLOSEDGROUPCOUNTS].colour = lParam;
+ break;
+ }
+ return 0;
+
+ case CLM_GETNEXTITEM:
+ {
+ int i;
+ if (wParam != CLGN_ROOT) {
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) lParam, &contact, &group, NULL))
+ return (LRESULT) (HANDLE) NULL;
+ i = List_IndexOf((SortedList*)&group->cl,contact);
+ if (i < 0) return 0;
+ }
+ switch (wParam) {
+ case CLGN_ROOT:
+ if (dat->list.cl.count)
+ return (LRESULT) pcli->pfnContactToHItem(dat->list.cl.items[0]);
+ else
+ return (LRESULT) (HANDLE) NULL;
+ case CLGN_CHILD:
+ if (contact->type != CLCIT_GROUP)
+ return (LRESULT) (HANDLE) NULL;
+ group = contact->group;
+ if (group->cl.count == 0)
+ return (LRESULT) (HANDLE) NULL;
+ return (LRESULT) pcli->pfnContactToHItem(group->cl.items[0]);
+ case CLGN_PARENT:
+ return group->groupId | HCONTACT_ISGROUP;
+ case CLGN_NEXT:
+ do {
+ if (++i >= group->cl.count)
+ return NULL;
+ }
+ while (group->cl.items[i]->type == CLCIT_DIVIDER);
+ return (LRESULT) pcli->pfnContactToHItem(group->cl.items[i]);
+ case CLGN_PREVIOUS:
+ do {
+ if (--i < 0)
+ return NULL;
+ }
+ while (group->cl.items[i]->type == CLCIT_DIVIDER);
+ return (LRESULT) pcli->pfnContactToHItem(group->cl.items[i]);
+ case CLGN_NEXTCONTACT:
+ for (i++; i < group->cl.count; i++)
+ if (group->cl.items[i]->type == CLCIT_CONTACT)
+ break;
+ if (i >= group->cl.count)
+ return (LRESULT) (HANDLE) NULL;
+ return (LRESULT) pcli->pfnContactToHItem(group->cl.items[i]);
+ case CLGN_PREVIOUSCONTACT:
+ if (i >= group->cl.count)
+ return (LRESULT) (HANDLE) NULL;
+ for (i--; i >= 0; i--)
+ if (group->cl.items[i]->type == CLCIT_CONTACT)
+ break;
+ if (i < 0)
+ return (LRESULT) (HANDLE) NULL;
+ return (LRESULT) pcli->pfnContactToHItem(group->cl.items[i]);
+ case CLGN_NEXTGROUP:
+ for (i++; i < group->cl.count; i++)
+ if (group->cl.items[i]->type == CLCIT_GROUP)
+ break;
+ if (i >= group->cl.count)
+ return (LRESULT) (HANDLE) NULL;
+ return (LRESULT) pcli->pfnContactToHItem(group->cl.items[i]);
+ case CLGN_PREVIOUSGROUP:
+ if (i >= group->cl.count)
+ return (LRESULT) (HANDLE) NULL;
+ for (i--; i >= 0; i--)
+ if (group->cl.items[i]->type == CLCIT_GROUP)
+ break;
+ if (i < 0)
+ return (LRESULT) (HANDLE) NULL;
+ return (LRESULT) pcli->pfnContactToHItem(group->cl.items[i]);
+ }
+ return (LRESULT) (HANDLE) NULL;
+ }
+ return 0;
+ case CLM_SELECTITEM:
+ {
+ struct ClcGroup *tgroup;
+ int index = -1;
+ int mainindex = -1;
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, &group, NULL))
+ break;
+ for (tgroup = group; tgroup; tgroup = tgroup->parent)
+ pcli->pfnSetGroupExpand(hwnd, dat, tgroup, 1);
+
+ if ( !contact->isSubcontact)
+ {
+ index = List_IndexOf((SortedList*)&group->cl,contact);
+ mainindex = index;
+ }
+ else
+ {
+ index = List_IndexOf((SortedList*)&group->cl,contact->subcontacts);
+ mainindex = index;
+ index += contact->isSubcontact;
+ }
+
+ BYTE k = db_get_b(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT);
+ if (k) {
+ for (int i=0; i < mainindex; i++)
+ {
+ struct ClcContact *tempCont = group->cl.items[i];
+ if (tempCont->type == CLCIT_CONTACT && tempCont->SubAllocated && tempCont->SubExpanded)
+ index += tempCont->SubAllocated;
+ }
+ }
+
+ dat->selection = pcli->pfnGetRowsPriorTo(&dat->list, group, index);
+ pcli->pfnEnsureVisible(hwnd, dat, dat->selection, 0);
+ }
+ return 0;
+
+ case CLM_SETEXTRAIMAGE:
+ if (LOWORD(lParam) >= dat->extraColumnsCount)
+ return 0;
+
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ return 0;
+
+ contact->iExtraImage[LOWORD(lParam)] = (BYTE) HIWORD(lParam); //set oldstyle icon
+ contact->iWideExtraImage[LOWORD(lParam)] = (WORD) 0xFFFF; //reset wide icon
+ pcli->pfnInvalidateRect(hwnd, NULL, FALSE);
+ return 0;
+
+ case CLM_SETWIDEEXTRAIMAGE:
+ if (LOWORD(lParam) >= dat->extraColumnsCount)
+ return 0;
+
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ return 0;
+
+ contact->iExtraImage[LOWORD(lParam)] = (BYTE) 0xFF; //reset oldstyle icon
+ contact->iWideExtraImage[LOWORD(lParam)] = (WORD) HIWORD(lParam); //set wide icon
+ pcli->pfnInvalidateRect(hwnd, NULL, FALSE);
+ return 0;
+
+ case CLM_SETEXTRAIMAGELIST:
+ dat->himlExtraColumns = (HIMAGELIST) lParam;
+ dat->himlWideExtraColumns = (HIMAGELIST) wParam;
+ pcli->pfnInvalidateRect(hwnd, NULL, FALSE);
+ return 0;
+
+ case CLM_GETWIDEEXTRAIMAGE:
+ if (LOWORD(lParam) >= dat->extraColumnsCount)
+ return 0xFFFF;
+
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ return 0xFFFF;
+
+ return contact->iWideExtraImage[LOWORD(lParam)];
+ }
+ return corecli.pfnProcessExternalMessages(hwnd, dat, msg, wParam, lParam);
+}
diff --git a/plugins/Clist_modern/src/modern_clcopts.cpp b/plugins/Clist_modern/src/modern_clcopts.cpp
new file mode 100644
index 0000000000..2cce5a111c
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clcopts.cpp
@@ -0,0 +1,2068 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_defsettings.h"
+#include "hdr/modern_effectenum.h"
+#include "hdr/modern_sync.h"
+#include <m_modernopt.h>
+#include "m_fontservice.h"
+
+#define FONTF_NORMAL 0
+#define FONTF_BOLD 1
+#define FONTF_ITALIC 2
+#define FONTF_UNDERLINE 4
+
+struct FontOptionsList
+{
+ DWORD dwFlags;
+ int fontID;
+ TCHAR* szGroup;
+ TCHAR* szDescr;
+ COLORREF defColour;
+ TCHAR* szDefFace;
+ BYTE defCharset, defStyle;
+ char defSize;
+ FONTEFFECT defeffect;
+
+ COLORREF colour;
+ TCHAR szFace[LF_FACESIZE];
+ BYTE charset, style;
+ char size;
+};
+
+#define CLCGROUP LPGENT("Contact List/Contact names")
+#define CLCLINESGROUP LPGENT("Contact List/Row Items")
+#define CLCFRAMESGROUP LPGENT("Contact List/Frame texts")
+#define CLCCOLOURSGROUP LPGENT("Contact List/Special colours")
+
+#define DEFAULT_COLOUR RGB(0, 0, 0)
+#define DEFAULT_GREYCOLOUR RGB(128, 128, 128)
+#define DEFAULT_BACKCOLOUR RGB(255, 255, 255)
+
+#define DEFAULT_FAMILY _T("Arial")
+#define DEFAULT_EFFECT { 0, 0x00000000, 0x00000000 }
+
+#define DEFAULT_SIZE -11
+#define DEFAULT_SMALLSIZE -8
+
+static struct FontOptionsList fontOptionsList[] = {
+ { FIDF_CLASSGENERAL, FONTID_CONTACTS, CLCGROUP, LPGENT( "Standard contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_AWAY, CLCGROUP, LPGENT( "Away contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_DND, CLCGROUP, LPGENT( "DND contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_NA, CLCGROUP, LPGENT( "NA contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_OCCUPIED, CLCGROUP, LPGENT( "Occupied contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_CHAT, CLCGROUP, LPGENT( "Free for chat contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_INVISIBLE, CLCGROUP, LPGENT( "Invisible contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_PHONE, CLCGROUP, LPGENT( "On the phone contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_LUNCH, CLCGROUP, LPGENT( "Out to lunch contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_OFFLINE, CLCGROUP, LPGENT( "Offline contacts"), DEFAULT_GREYCOLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_INVIS, CLCGROUP, LPGENT( "Online contacts to whom you have a different visibility"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_OFFINVIS, CLCGROUP, LPGENT( "Offline contacts to whom you have a different visibility"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_NOTONLIST, CLCGROUP, LPGENT( "Contacts who are 'not on list'"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSHEADER, FONTID_OPENGROUPS, CLCGROUP, LPGENT( "Open groups"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_BOLD, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSHEADER, FONTID_OPENGROUPCOUNTS, CLCGROUP, LPGENT( "Open group member counts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSHEADER, FONTID_CLOSEDGROUPS, CLCGROUP, LPGENT( "Closed groups"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_BOLD, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSHEADER, FONTID_CLOSEDGROUPCOUNTS, CLCGROUP, LPGENT( "Closed group member counts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSSMALL, FONTID_DIVIDERS, CLCGROUP, LPGENT( "Dividers"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+
+ { FIDF_CLASSSMALL, FONTID_SECONDLINE, CLCLINESGROUP, LPGENT( "Second line"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SMALLSIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSSMALL, FONTID_THIRDLINE, CLCLINESGROUP, LPGENT( "Third line"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SMALLSIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSSMALL, FONTID_CONTACT_TIME, CLCLINESGROUP, LPGENT( "Contact time"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SMALLSIZE, DEFAULT_EFFECT },
+
+ { FIDF_CLASSGENERAL, FONTID_STATUSBAR_PROTONAME, CLCFRAMESGROUP, LPGENT( "Status bar text"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_EVENTAREA, CLCFRAMESGROUP, LPGENT( "Event area text"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_VIEMODES, CLCFRAMESGROUP, LPGENT( "Current view mode text"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+};
+
+struct ColourOptionsList
+{
+ char * chGroup;
+ char * chName;
+ TCHAR* szGroup;
+ TCHAR* szDescr;
+ COLORREF defColour;
+};
+
+static struct ColourOptionsList colourOptionsList[] = {
+
+ { "CLC", "BkColour", CLCGROUP, LPGENT( "Background"), DEFAULT_BACKCOLOUR },
+ { "CLC", "Rows_BkColour", CLCLINESGROUP, LPGENT( "Background"), DEFAULT_BACKCOLOUR },
+ { "CLC", "Frames_BkColour", CLCFRAMESGROUP, LPGENT( "Background"), DEFAULT_BACKCOLOUR},
+
+ { "CLC", "HotTextColour", CLCCOLOURSGROUP, LPGENT( "Hot text"), CLCDEFAULT_MODERN_HOTTEXTCOLOUR },
+ { "CLC", "SelTextColour", CLCCOLOURSGROUP, LPGENT( "Selected text"), CLCDEFAULT_MODERN_SELTEXTCOLOUR },
+ { "CLC", "QuickSearchColour", CLCCOLOURSGROUP, LPGENT( "Quick search text"), CLCDEFAULT_MODERN_QUICKSEARCHCOLOUR},
+
+ { "Menu", "TextColour", CLCCOLOURSGROUP, LPGENT( "Menu text"), CLCDEFAULT_TEXTCOLOUR},
+ { "Menu", "SelTextColour", CLCCOLOURSGROUP, LPGENT( "Selected menu text"), CLCDEFAULT_MODERN_SELTEXTCOLOUR},
+ { "FrameTitleBar", "TextColour", CLCCOLOURSGROUP, LPGENT( "Frame title text"), CLCDEFAULT_TEXTCOLOUR },
+ { "StatusBar", "TextColour", CLCCOLOURSGROUP, LPGENT( "Statusbar text"), CLCDEFAULT_TEXTCOLOUR},
+ { "ModernSettings", "KeyColor", CLCCOLOURSGROUP, LPGENT( "3rd party frames transparent back colour"), SETTING_KEYCOLOR_DEFAULT},
+
+};
+
+void RegisterCLUIFonts( void )
+{
+ static bool registered = false;
+ if ( registered )
+ return;
+
+ FontIDT fontid = {0};
+ EffectIDT effectid = {0};
+ char idstr[10];
+ int i, index = 0;
+
+ fontid.cbSize = sizeof(fontid);
+ strncpy(fontid.dbSettingsGroup, "CLC", SIZEOF(fontid.dbSettingsGroup));
+
+ effectid.cbSize = sizeof(effectid);
+ strncpy(effectid.dbSettingsGroup, "CLC", SIZEOF(effectid.dbSettingsGroup));
+
+ for ( i=0; i < SIZEOF(fontOptionsList); i++, index++ ) {
+ fontid.flags = FIDF_DEFAULTVALID | FIDF_APPENDNAME | FIDF_SAVEPOINTSIZE | FIDF_ALLOWEFFECTS | FIDF_ALLOWREREGISTER | FIDF_NOAS;
+ fontid.flags |= fontOptionsList[i].dwFlags;
+
+ _tcsncpy(fontid.group, fontOptionsList[i].szGroup, SIZEOF(fontid.group));
+ _tcsncpy(fontid.name, fontOptionsList[i].szDescr, SIZEOF(fontid.name));
+ sprintf(idstr, "Font%d", fontOptionsList[i].fontID);
+ strncpy(fontid.prefix, idstr, SIZEOF(fontid.prefix));
+ fontid.order = i+1;
+
+ 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));
+
+ FontRegisterT(&fontid);
+
+ _tcsncpy(effectid.group, fontOptionsList[i].szGroup, SIZEOF(effectid.group));
+ _tcsncpy(effectid.name, fontOptionsList[i].szDescr, SIZEOF(effectid.name));
+ sprintf(idstr, "Font%d", fontOptionsList[i].fontID);
+ strncpy(effectid.setting, idstr, SIZEOF(effectid.setting));
+ effectid.order = i + 1;
+
+ effectid.defeffect.effectIndex = fontOptionsList[i].defeffect.effectIndex;
+ effectid.defeffect.baseColour = fontOptionsList[i].defeffect.baseColour;
+ effectid.defeffect.secondaryColour = fontOptionsList[i].defeffect.secondaryColour;
+
+ EffectRegisterT(&effectid);
+ }
+
+ ColourIDT colourid = {0};
+ colourid.cbSize = sizeof(colourid);
+
+ for ( i=0; i < SIZEOF( colourOptionsList); i++ ) {
+ _tcsncpy(colourid.group, colourOptionsList[i].szGroup, SIZEOF(colourid.group));
+ _tcsncpy(colourid.name, colourOptionsList[i].szDescr, SIZEOF(colourid.group));
+ strncpy(colourid.setting, colourOptionsList[i].chName, SIZEOF(colourid.setting));
+ strncpy(colourid.dbSettingsGroup, colourOptionsList[i].chGroup, SIZEOF(colourid.dbSettingsGroup));
+ colourid.defcolour = colourOptionsList[i].defColour;
+ colourid.order = i + 1;
+ ColourRegisterT(&colourid);
+ }
+ registered = true;
+}
+
+static INT_PTR CALLBACK DlgProcClistListOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcClistAdditionalOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcClcBkgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcStatusBarBkgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+DWORD GetDefaultExStyle(void)
+{
+ BOOL param;
+ DWORD ret = CLCDEFAULT_EXSTYLE;
+ if (SystemParametersInfo(SPI_GETLISTBOXSMOOTHSCROLLING,0,&param,FALSE) && !param)
+ ret |= CLS_EX_NOSMOOTHSCROLLING;
+ if (SystemParametersInfo(SPI_GETHOTTRACKING,0,&param,FALSE) && !param)
+ ret &= ~CLS_EX_TRACKSELECT;
+ return ret;
+}
+
+void GetFontSetting(int i,LOGFONT *lf,COLORREF *colour,BYTE *effect, COLORREF *eColour1,COLORREF *eColour2)
+{
+ DBVARIANT dbv = {0};
+ char idstr[32];
+
+ int index = 0;
+ for ( index = 0; index < SIZEOF(fontOptionsList); index++ )
+ if ( fontOptionsList[index].fontID == i )
+ break;
+
+ if ( index == SIZEOF(fontOptionsList))
+ return;
+
+ FontIDT fontid = {0};
+ fontid.cbSize = sizeof(fontid);
+ _tcsncpy( fontid.group, fontOptionsList[index].szGroup, SIZEOF( fontid.group ));
+ _tcsncpy( fontid.name, fontOptionsList[index].szDescr, SIZEOF( fontid.name ));
+
+ COLORREF col = CallService( MS_FONT_GETT, (WPARAM)&fontid, (LPARAM)lf );
+
+ if ( colour )
+ *colour = col;
+
+ if (effect) {
+ mir_snprintf(idstr,SIZEOF(idstr),"Font%dEffect",i);
+ *effect = db_get_b(NULL,"CLC",idstr,0);
+ mir_snprintf(idstr,SIZEOF(idstr),"Font%dEffectCol1",i);
+ *eColour1 = db_get_dw(NULL,"CLC",idstr,0);
+ mir_snprintf(idstr,SIZEOF(idstr),"Font%dEffectCol2",i);
+ *eColour2 = db_get_dw(NULL,"CLC",idstr,0);
+ }
+}
+
+
+static INT_PTR CALLBACK DlgProcClistOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcTrayOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcClistWindowOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcClistBehaviourOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK DlgProcSBarOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+static UINT StatusBarExpertControls[] = {IDC_STATUSBAR_PER_PROTO, IDC_STATUSBAR_PROTO_LIST, IDC_SBAR_USE_ACCOUNT_SETTINGS, IDC_SBAR_HIDE_ACCOUNT_COMPLETELY};
+
+struct
+{
+ char *name; // Tab name
+ int id; // Dialog id
+ DLGPROC wnd_proc; // Dialog function
+ UINT* expertControls; // Expert Controls
+ int nExpertControls;
+ DWORD flag; // Expertonly
+}
+static clist_opt_items[] =
+{
+ { LPGEN("General"), IDD_OPT_CLIST, DlgProcClistOpts, NULL, 0, 0},
+ { LPGEN("Tray"), IDD_OPT_TRAY, DlgProcTrayOpts, NULL, 0, 0 },
+ { LPGEN("List"), IDD_OPT_CLC, DlgProcClistListOpts, NULL, 0, 0 },
+ { LPGEN("Window"), IDD_OPT_CLUI, DlgProcClistWindowOpts, NULL, 0, 0 },
+ { LPGEN("Behaviour"), IDD_OPT_CLUI_2, DlgProcClistBehaviourOpts, NULL, 0, 0 },
+ { LPGEN("Status Bar"), IDD_OPT_SBAR, DlgProcSBarOpts, StatusBarExpertControls, SIZEOF(StatusBarExpertControls), 0},
+ { LPGEN("Additional stuff"), IDD_OPT_META_CLC, DlgProcClistAdditionalOpts, NULL, 0, 0 }
+};
+
+int ClcOptInit(WPARAM wParam,LPARAM lParam)
+{
+ if (MirandaExiting())
+ return 0;
+
+ OPTIONSDIALOGPAGE odp = { 0 };
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = g_hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CLC);
+ odp.pszTitle = LPGEN("Contact List");
+ odp.pfnDlgProc = DlgProcClistListOpts;
+ odp.flags = ODPF_BOLDGROUPS;
+
+ for (int i=0; i < SIZEOF(clist_opt_items); i++) {
+ odp.pszTemplate = MAKEINTRESOURCEA(clist_opt_items[i].id);
+ odp.pszTab = clist_opt_items[i].name;
+ odp.pfnDlgProc = clist_opt_items[i].wnd_proc;
+ odp.flags = ODPF_BOLDGROUPS | clist_opt_items[i].flag;
+ odp.expertOnlyControls = clist_opt_items[i].expertControls;
+ odp.nExpertOnlyControls = clist_opt_items[i].nExpertControls;
+ Options_AddPage(wParam, &odp);
+ }
+
+ if (g_CluiData.fDisableSkinEngine) {
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CLIST_LISTBKG);
+ odp.pszGroup = LPGEN("Skins");
+ odp.pszTitle = LPGEN("Contact List");
+ odp.pszTab = LPGEN("List Background");
+ odp.pfnDlgProc = DlgProcClcBkgOpts;
+ odp.flags = ODPF_BOLDGROUPS;
+ Options_AddPage(wParam, &odp);
+ }
+
+ return 0;
+}
+
+struct CheckBoxToStyleEx_t
+{
+ int id;
+ DWORD flag;
+ int neg;
+};
+static const struct CheckBoxToStyleEx_t 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|TVIF_IMAGE;
+ 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);
+ tvis.item.iImage = tvis.item.iSelectedImage = (style&tvis.item.lParam) != 0?1:0;
+ TreeView_InsertItem(hwndTree,&tvis);
+ }
+}
+
+static DWORD MakeCheckBoxTreeFlags(HWND hwndTree)
+{
+ DWORD flags = 0;
+ TVITEMA tvi;
+
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM|TVIF_IMAGE;
+ tvi.hItem = TreeView_GetRoot(hwndTree);
+ while(tvi.hItem) {
+ TreeView_GetItem(hwndTree,&tvi);
+ if (tvi.iImage) flags |= tvi.lParam;
+ tvi.hItem = TreeView_GetNextSibling(hwndTree,tvi.hItem);
+ }
+ return flags;
+}
+
+static INT_PTR CALLBACK DlgProcClistAdditionalOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ LPNMHDR t;
+ t = ((LPNMHDR)lParam);
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_META, db_get_b(NULL,"CLC","Meta",SETTING_USEMETAICON_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+ CheckDlgButton(hwndDlg, IDC_METADBLCLK, db_get_b(NULL,"CLC","MetaDoubleClick",SETTING_METAAVOIDDBLCLICK_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+ CheckDlgButton(hwndDlg, IDC_METASUBEXTRA, db_get_b(NULL,"CLC","MetaHideExtra",SETTING_METAHIDEEXTRA_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+ CheckDlgButton(hwndDlg, IDC_METASUBEXTRA_IGN, db_get_b(NULL,"CLC","MetaIgnoreEmptyExtra",SETTING_METAAVOIDDBLCLICK_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+ CheckDlgButton(hwndDlg, IDC_METASUB_HIDEOFFLINE, db_get_b(NULL,"CLC","MetaHideOfflineSub",SETTING_METAHIDEOFFLINESUB_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+ CheckDlgButton(hwndDlg, IDC_METAEXPAND, db_get_b(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+ CheckDlgButton(hwndDlg, IDC_DISCOVER_AWAYMSG, db_get_b(NULL,"ModernData","InternalAwayMsgDiscovery",SETTING_INTERNALAWAYMSGREQUEST_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+ CheckDlgButton(hwndDlg, IDC_REMOVE_OFFLINE_AWAYMSG, db_get_b(NULL,"ModernData","RemoveAwayMessageForOffline",SETTING_REMOVEAWAYMSGFOROFFLINE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+
+ SendDlgItemMessage(hwndDlg,IDC_SUBINDENTSPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_SUBINDENT),0);
+ SendDlgItemMessage(hwndDlg,IDC_SUBINDENTSPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_SUBINDENTSPIN,UDM_SETPOS,0,MAKELONG(db_get_b(NULL,"CLC","SubIndent",CLCDEFAULT_GROUPINDENT),0));
+
+ {
+ BYTE t = IsDlgButtonChecked(hwndDlg,IDC_METAEXPAND);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_METADBLCLK),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_METASUBEXTRA),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_METASUB_HIDEOFFLINE),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SUBINDENTSPIN),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SUBINDENT),t);
+
+ t = ServiceExists(MS_MC_GETMOSTONLINECONTACT);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_META),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_METADBLCLK),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_METASUB_HIDEOFFLINE),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_METAEXPAND),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_METASUBEXTRA),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_FRAME_META),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_FRAME_META_CAPT),!t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_SUBINDENTSPIN),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_SUBINDENT),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_SUBIDENTCAPT),t);
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_METAEXPAND) {
+ BYTE t = IsDlgButtonChecked(hwndDlg,IDC_METAEXPAND);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_METADBLCLK),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_METASUBEXTRA),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_METASUB_HIDEOFFLINE),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SUBINDENTSPIN),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SUBINDENT),t);
+ }
+ if ((LOWORD(wParam) == IDC_SUBINDENT) && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ return TRUE;
+
+ case WM_NOTIFY:
+ switch(t->idFrom) {
+ case 0:
+ switch (t->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CLC","Meta",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_META)); // by FYR
+ db_set_b(NULL,"CLC","MetaDoubleClick",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_METADBLCLK)); // by FYR
+ db_set_b(NULL,"CLC","MetaHideExtra",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_METASUBEXTRA)); // by FYR
+ db_set_b(NULL,"CLC","MetaIgnoreEmptyExtra",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_METASUBEXTRA_IGN)); // by FYR
+ db_set_b(NULL,"CLC","MetaHideOfflineSub",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_METASUB_HIDEOFFLINE)); // by FYR
+ db_set_b(NULL,"CLC","MetaExpanding",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_METAEXPAND));
+ db_set_b(NULL,"ModernData","InternalAwayMsgDiscovery",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DISCOVER_AWAYMSG));
+ db_set_b(NULL,"ModernData","RemoveAwayMessageForOffline",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_REMOVE_OFFLINE_AWAYMSG));
+
+ db_set_b(NULL,"CLC","SubIndent",(BYTE)SendDlgItemMessage(hwndDlg,IDC_SUBINDENTSPIN,UDM_GETPOS,0,0));
+ ClcOptionsChanged();
+ CLUI_ReloadCLUIOptions();
+ PostMessage(pcli->hwndContactList,WM_SIZE,0,0);
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK DlgProcClistListOpts(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);
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_HIDEOFFLINEOPTS),GWL_STYLE,GetWindowLongPtr(GetDlgItem(hwndDlg,IDC_HIDEOFFLINEOPTS),GWL_STYLE)|TVS_NOHSCROLL);
+ {
+ HIMAGELIST himlCheckBoxes;
+ himlCheckBoxes = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_COLOR32|ILC_MASK,2,2);
+ ImageList_AddIcon(himlCheckBoxes,LoadSmallIconShared(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_NOTICK)));
+ ImageList_AddIcon(himlCheckBoxes,LoadSmallIconShared(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_TICK)));
+ TreeView_SetImageList(GetDlgItem(hwndDlg,IDC_GREYOUTOPTS),himlCheckBoxes,TVSIL_NORMAL);
+ TreeView_SetImageList(GetDlgItem(hwndDlg,IDC_HIDEOFFLINEOPTS),himlCheckBoxes,TVSIL_NORMAL);
+
+ DWORD exStyle = db_get_dw(NULL,"CLC","ExStyle",GetDefaultExStyle());
+ for (int i=0;i < SIZEOF(checkBoxToStyleEx);i++)
+ CheckDlgButton(hwndDlg,checkBoxToStyleEx[i].id,(exStyle&checkBoxToStyleEx[i].flag)^(checkBoxToStyleEx[i].flag*checkBoxToStyleEx[i].neg)?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(db_get_w(NULL,"CLC","ScrollTime",CLCDEFAULT_SCROLLTIME),0));
+ }
+ CheckDlgButton(hwndDlg,IDC_IDLE,db_get_b(NULL,"CLC","ShowIdle",CLCDEFAULT_SHOWIDLE)?BST_CHECKED:BST_UNCHECKED);
+
+ SendDlgItemMessage(hwndDlg,IDC_GROUPINDENTSPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_GROUPINDENTSPIN,UDM_SETPOS,0,MAKELONG(db_get_b(NULL,"CLC","GroupIndent",CLCDEFAULT_GROUPINDENT),0));
+ CheckDlgButton(hwndDlg,IDC_GREYOUT,db_get_dw(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),db_get_dw(NULL,"CLC","FullGreyoutFlags",CLCDEFAULT_FULLGREYOUTFLAGS));
+ FillCheckBoxTree(GetDlgItem(hwndDlg,IDC_HIDEOFFLINEOPTS),offlineValues,SIZEOF(offlineValues),db_get_dw(NULL,"CLC","OfflineModes",CLCDEFAULT_OFFLINEMODES));
+ CheckDlgButton(hwndDlg,IDC_NOSCROLLBAR,db_get_b(NULL,"CLC","NoVScrollBar",CLCDEFAULT_NOVSCROLL)?BST_CHECKED:BST_UNCHECKED);
+ return TRUE;
+
+ case WM_VSCROLL:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 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) && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 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_ONITEMICON) {
+ TVITEMA 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 = !tvi.iImage;
+ //tvi.state = tvi.iImage?2:1;
+ TreeView_SetItem(((LPNMHDR)lParam)->hwndFrom,&tvi);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ }
+ }
+ break;
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ {
+ DWORD exStyle = 0;
+ for (int i=0;i < SIZEOF(checkBoxToStyleEx);i++)
+ if ((IsDlgButtonChecked(hwndDlg,checkBoxToStyleEx[i].id) == 0) == checkBoxToStyleEx[i].neg)
+ exStyle |= checkBoxToStyleEx[i].flag;
+ db_set_dw(NULL,"CLC","ExStyle",exStyle);
+ }
+ {
+ DWORD fullGreyoutFlags = MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg,IDC_GREYOUTOPTS));
+ db_set_dw(NULL,"CLC","FullGreyoutFlags",fullGreyoutFlags);
+ if (IsDlgButtonChecked(hwndDlg,IDC_GREYOUT))
+ db_set_dw(NULL,"CLC","GreyoutFlags",fullGreyoutFlags);
+ else
+ db_set_dw(NULL,"CLC","GreyoutFlags",0);
+ }
+
+ db_set_b(NULL,"CLC","ShowIdle",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_IDLE)?1:0));
+ db_set_dw(NULL,"CLC","OfflineModes",MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg,IDC_HIDEOFFLINEOPTS)));
+ db_set_w(NULL,"CLC","ScrollTime",(WORD)SendDlgItemMessage(hwndDlg,IDC_SMOOTHTIMESPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CLC","GroupIndent",(BYTE)SendDlgItemMessage(hwndDlg,IDC_GROUPINDENTSPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CLC","NoVScrollBar",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_NOSCROLLBAR)?1:0));
+
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+ ImageList_Destroy(TreeView_GetImageList(GetDlgItem(hwndDlg,IDC_GREYOUTOPTS),TVSIL_NORMAL));
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK DlgProcStatusBarBkgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg,IDC_BITMAP,db_get_b(NULL,"StatusBar","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,"StatusBar","BkColour",CLCDEFAULT_BKCOLOUR));
+ SendDlgItemMessage(hwndDlg,IDC_SELCOLOUR,CPM_SETDEFAULTCOLOUR,0,CLCDEFAULT_SELBKCOLOUR);
+ SendDlgItemMessage(hwndDlg,IDC_SELCOLOUR,CPM_SETCOLOUR,0,db_get_dw(NULL,"StatusBar","SelBkColour",CLCDEFAULT_SELBKCOLOUR));
+ {
+ DBVARIANT dbv = {0};
+ if ( !DBGetContactSettingString(NULL,"StatusBar","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);
+ }
+ db_free(&dbv);
+ }
+ }
+
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE,db_get_b(NULL,"StatusBar","HiLightMode",SETTING_SBHILIGHTMODE_DEFAULT) == 0?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE1,db_get_b(NULL,"StatusBar","HiLightMode",SETTING_SBHILIGHTMODE_DEFAULT) == 1?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE2,db_get_b(NULL,"StatusBar","HiLightMode",SETTING_SBHILIGHTMODE_DEFAULT) == 2?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE3,db_get_b(NULL,"StatusBar","HiLightMode",SETTING_SBHILIGHTMODE_DEFAULT) == 3?BST_CHECKED:BST_UNCHECKED);
+ {
+ WORD bmpUse = db_get_w(NULL,"StatusBar","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);
+ CheckDlgButton(hwndDlg,IDC_TILEVROWH,bmpUse&CLBF_TILEVTOROWHEIGHT?BST_CHECKED:BST_UNCHECKED);
+
+ HRESULT (STDAPICALLTYPE *MySHAutoComplete)(HWND,DWORD);
+ MySHAutoComplete = (HRESULT (STDAPICALLTYPE*)(HWND,DWORD))GetProcAddress(GetModuleHandle(_T("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));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TILEVROWH),IsDlgButtonChecked(hwndDlg,IDC_BITMAP));
+ 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_FILENAME && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"StatusBar","UseBitmap",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_BITMAP));
+ {
+ COLORREF col;
+ col = SendDlgItemMessage(hwndDlg,IDC_BKGCOLOUR,CPM_GETCOLOUR,0,0);
+ if (col == CLCDEFAULT_BKCOLOUR) db_unset(NULL,"StatusBar","BkColour");
+ else db_set_dw(NULL,"StatusBar","BkColour",col);
+ col = SendDlgItemMessage(hwndDlg,IDC_SELCOLOUR,CPM_GETCOLOUR,0,0);
+ if (col == CLCDEFAULT_SELBKCOLOUR) db_unset(NULL,"StatusBar","SelBkColour");
+ else db_set_dw(NULL,"StatusBar","SelBkColour",col);
+ }
+ {
+ 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))
+ db_set_s(NULL,"StatusBar","BkBitmap",strrel);
+ else db_set_s(NULL,"StatusBar","BkBitmap",str);
+ }
+ else db_set_s(NULL,"StatusBar","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;
+ if (IsDlgButtonChecked(hwndDlg,IDC_TILEVROWH)) flags |= CLBF_TILEVTOROWHEIGHT;
+
+ db_set_w(NULL,"StatusBar","BkBmpUse",flags);
+ }
+ {
+ int hil = 0;
+ if (IsDlgButtonChecked(hwndDlg,IDC_HILIGHTMODE1)) hil = 1;
+ if (IsDlgButtonChecked(hwndDlg,IDC_HILIGHTMODE2)) hil = 2;
+ if (IsDlgButtonChecked(hwndDlg,IDC_HILIGHTMODE3)) hil = 3;
+
+ db_set_b(NULL,"StatusBar","HiLightMode",(BYTE)hil);
+ }
+
+ ClcOptionsChanged();
+ //OnStatusBarBackgroundChange();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static int _GetNetVisibleProtoCount()
+{
+ int i,count,netProtoCount;
+ PROTOACCOUNT **accs;
+ ProtoEnumAccounts( &count, &accs );
+ for (i=0,netProtoCount = 0;i < count;i++)
+ {
+ if ( pcli->pfnGetProtocolVisibility(accs[i]->szModuleName) == 0 )
+ continue;
+ netProtoCount++;
+ }
+ return netProtoCount;
+}
+
+TCHAR *sortby[] = {_T("Name"), _T("Name (use locale settings)") , _T("Status"), _T("Last message time"), _T("Account Name"), _T("Rate"), _T("-Nothing-")};
+int sortbyValue[] = { SORTBY_NAME, SORTBY_NAME_LOCALE, SORTBY_STATUS, SORTBY_LASTMSG, SORTBY_PROTO ,SORTBY_RATE , SORTBY_NOTHING };
+static INT_PTR CALLBACK DlgProcClistOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)HookEventMessage(ME_DB_CONTACT_SETTINGCHANGED,hwndDlg,WM_USER+1));
+
+ CheckDlgButton(hwndDlg, IDC_HIDEOFFLINE, db_get_b(NULL,"CList","HideOffline",SETTING_HIDEOFFLINE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_HIDEEMPTYGROUPS, db_get_b(NULL,"CList","HideEmptyGroups",SETTING_HIDEEMPTYGROUPS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DISABLEGROUPS, db_get_b(NULL,"CList","UseGroups",SETTING_USEGROUPS_DEFAULT) ? BST_UNCHECKED : BST_CHECKED);
+ CheckDlgButton(hwndDlg, IDC_CONFIRMDELETE, db_get_b(NULL,"CList","ConfirmDelete",SETTING_CONFIRMDELETE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg,IDC_GAMMACORRECT,db_get_b(NULL,"CLC","GammaCorrect",CLCDEFAULT_GAMMACORRECT)?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE,db_get_b(NULL,"CLC","HiLightMode",SETTING_HILIGHTMODE_DEFAULT) == 0?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE1,db_get_b(NULL,"CLC","HiLightMode",SETTING_HILIGHTMODE_DEFAULT) == 1?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE2,db_get_b(NULL,"CLC","HiLightMode",SETTING_HILIGHTMODE_DEFAULT) == 2?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE3,db_get_b(NULL,"CLC","HiLightMode",SETTING_HILIGHTMODE_DEFAULT) == 3?BST_CHECKED:BST_UNCHECKED);
+
+ int i, item;
+ int s1, s2, s3;
+ for (i=0; i < SIZEOF(sortby); i++)
+ {
+ item = SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_ADDSTRING,0,(LPARAM)TranslateTS(sortby[i]));
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_SETITEMDATA,item,(LPARAM)0);
+ item = SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_ADDSTRING,0,(LPARAM)TranslateTS(sortby[i]));
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_SETITEMDATA,item,(LPARAM)0);
+ item = SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_ADDSTRING,0,(LPARAM)TranslateTS(sortby[i]));
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_SETITEMDATA,item,(LPARAM)0);
+
+ }
+ s1 = db_get_b(NULL,"CList","SortBy1",SETTING_SORTBY1_DEFAULT);
+ s2 = db_get_b(NULL,"CList","SortBy2",SETTING_SORTBY2_DEFAULT);
+ s3 = db_get_b(NULL,"CList","SortBy3",SETTING_SORTBY3_DEFAULT);
+
+ for (i=0; i < SIZEOF(sortby); i++)
+ {
+ if (s1 == sortbyValue[i])
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_SETCURSEL,i,0);
+ if (s2 == sortbyValue[i])
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_SETCURSEL,i,0);
+ if (s3 == sortbyValue[i])
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_SETCURSEL,i,0);
+ }
+
+ CheckDlgButton(hwndDlg, IDC_NOOFFLINEMOVE, db_get_b(NULL,"CList","NoOfflineBottom",SETTING_NOOFFLINEBOTTOM_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_OFFLINETOROOT, db_get_b(NULL,"CList","PlaceOfflineToRoot",SETTING_PLACEOFFLINETOROOT_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ }
+ return TRUE;
+ case WM_COMMAND:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CList","HideOffline",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_HIDEOFFLINE));
+ db_set_b(NULL,"CList","HideEmptyGroups",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_HIDEEMPTYGROUPS));
+ db_set_b(NULL,"CList","UseGroups",(BYTE)!IsDlgButtonChecked(hwndDlg,IDC_DISABLEGROUPS));
+ db_set_b(NULL,"CList","ConfirmDelete",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_CONFIRMDELETE));
+
+ db_set_b(NULL,"CLC","GammaCorrect",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_GAMMACORRECT));
+ int hil = 0;
+ if (IsDlgButtonChecked(hwndDlg,IDC_HILIGHTMODE1)) hil = 1;
+ if (IsDlgButtonChecked(hwndDlg,IDC_HILIGHTMODE2)) hil = 2;
+ if (IsDlgButtonChecked(hwndDlg,IDC_HILIGHTMODE3)) hil = 3;
+ db_set_b(NULL,"CLC","HiLightMode",(BYTE)hil);
+
+ int s1 = SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_GETCURSEL,0,0);
+ int s2 = SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_GETCURSEL,0,0);
+ int s3 = SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_GETCURSEL,0,0);
+ if (s1 >= 0) s1 = sortbyValue[s1];
+ if (s2 >= 0) s2 = sortbyValue[s2];
+ if (s3 >= 0) s3 = sortbyValue[s3];
+ db_set_b(NULL,"CList","SortBy1",(BYTE)s1);
+ db_set_b(NULL,"CList","SortBy2",(BYTE)s2);
+ db_set_b(NULL,"CList","SortBy3",(BYTE)s3);
+
+ db_set_b(NULL,"CList","NoOfflineBottom",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_NOOFFLINEMOVE));
+ db_set_b(NULL,"CList","PlaceOfflineToRoot",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_OFFLINETOROOT));
+
+ pcli->pfnLoadContactTree(); /* this won't do job properly since it only really works when changes happen */
+ SendMessage(pcli->hwndContactTree,CLM_AUTOREBUILD,0,0); /* force reshuffle */
+ ClcOptionsChanged(); // Used to force loading avatar an list height related options
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK DlgProcTrayOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_NOOFFLINEMOVE, db_get_b( NULL,"CList", "NoOfflineBottom", SETTING_NOOFFLINEBOTTOM_DEFAULT ) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_OFFLINETOROOT, db_get_b( NULL,"CList", "PlaceOfflineToRoot", SETTING_PLACEOFFLINETOROOT_DEFAULT ) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_ONECLK, db_get_b( NULL,"CList", "Tray1Click", SETTING_TRAY1CLICK_DEFAULT ) ? BST_CHECKED : BST_UNCHECKED);
+ {
+ BYTE trayOption = db_get_b(NULL,"CLUI","XStatusTray",SETTING_TRAYOPTION_DEFAULT);
+ CheckDlgButton(hwndDlg, IDC_SHOWXSTATUS, (trayOption&3) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWNORMAL, (trayOption&2) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_TRANSPARENTOVERLAY, (trayOption&4) ? BST_CHECKED : BST_UNCHECKED);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWNORMAL),IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSPARENTOVERLAY),IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL));
+ }
+ CheckDlgButton(hwndDlg, IDC_ALWAYSSTATUS, db_get_b(NULL,"CList","AlwaysStatus",SETTING_ALWAYSSTATUS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_ALWAYSPRIMARY, !db_get_b(NULL,"CList","AlwaysPrimary",SETTING_ALWAYSPRIMARY_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_ALWAYSMULTI, !db_get_b(NULL,"CList","AlwaysMulti",SETTING_ALWAYSMULTI_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DONTCYCLE, db_get_b(NULL,"CList","TrayIcon",SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_SINGLE ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CYCLE, db_get_b(NULL,"CList","TrayIcon",SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_CYCLE ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_MULTITRAY, db_get_b(NULL,"CList","TrayIcon",SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_MULTI ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DISABLEBLINK, db_get_b(NULL,"CList","DisableTrayFlash",SETTING_DISABLETRAYFLASH_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOW_AVATARS, db_get_b(NULL,"CList","AvatarsShow",SETTINGS_SHOWAVATARS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_SHOW_ANIAVATARS, db_get_b(NULL,"CList","AvatarsAnimated",(ServiceExists(MS_AV_GETAVATARBITMAP) && !g_CluiData.fGDIPlusFail)) == 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);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ALWAYSPRIMARY),FALSE);
+ }
+ if (IsDlgButtonChecked(hwndDlg,IDC_MULTITRAY)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIMESPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIME),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PRIMARYSTATUS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ALWAYSPRIMARY),FALSE);
+ }
+ SendDlgItemMessage(hwndDlg,IDC_CYCLETIMESPIN,UDM_SETRANGE,0,MAKELONG(120,1));
+ SendDlgItemMessage(hwndDlg,IDC_CYCLETIMESPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","CycleTime",SETTING_CYCLETIME_DEFAULT),0));
+ {
+ int i,count,item;
+ PROTOACCOUNT **accs;
+ DBVARIANT dbv = {DBVT_DELETED};
+ db_get(NULL,"CList","PrimaryStatus",&dbv);
+ ProtoEnumAccounts( &count, &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 || dbv.type == DBVT_UTF8) && !strcmp(dbv.pszVal,accs[i]->szModuleName))
+ SendDlgItemMessage(hwndDlg,IDC_PRIMARYSTATUS,CB_SETCURSEL,item,0);
+ }
+ db_free(&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(db_get_w(NULL,"CList","IconFlashTime",SETTING_ICONFLASHTIME_DEFAULT),0));
+ {
+ int i = _GetNetVisibleProtoCount();
+ if (i < 2)
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PRIMARYSTATUS),TRUE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIMESPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIME),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ALWAYSPRIMARY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ALWAYSPRIMARY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTITRAY),FALSE);
+ CheckDlgButton(hwndDlg,IDC_DONTCYCLE,TRUE);
+ }
+ }
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_SHOWXSTATUS || LOWORD(wParam) == IDC_SHOWNORMAL)
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWNORMAL),IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSPARENTOVERLAY),IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL));
+ }
+ 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));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ALWAYSPRIMARY),IsDlgButtonChecked(hwndDlg,IDC_DONTCYCLE));
+ }
+ if (LOWORD(wParam) == IDC_PRIMARYSTATUS && HIWORD(wParam) != CBN_SELCHANGE) break;
+ 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, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CList","Tray1Click",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_ONECLK));
+ db_set_b(NULL,"CList","AlwaysStatus",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_ALWAYSSTATUS));
+
+ db_set_b(NULL,"CList","AlwaysMulti",(BYTE)!IsDlgButtonChecked(hwndDlg,IDC_ALWAYSMULTI));
+ db_set_b(NULL,"CList","AlwaysPrimary",(BYTE)!IsDlgButtonChecked(hwndDlg,IDC_ALWAYSPRIMARY));
+
+ db_set_w(NULL,"CList","CycleTime",(WORD)SendDlgItemMessage(hwndDlg,IDC_CYCLETIMESPIN,UDM_GETPOS,0,0));
+ db_set_w(NULL,"CList","IconFlashTime",(WORD)SendDlgItemMessage(hwndDlg,IDC_BLINKSPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CList","DisableTrayFlash",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DISABLEBLINK));
+
+ if (_GetNetVisibleProtoCount()>1)
+ db_set_b(NULL,"CList","TrayIcon",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_DONTCYCLE)?SETTING_TRAYICON_SINGLE:(IsDlgButtonChecked(hwndDlg,IDC_CYCLE)?SETTING_TRAYICON_CYCLE:SETTING_TRAYICON_MULTI)));
+
+ {
+ BYTE xOptions = 0;
+ xOptions = IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS)?1:0;
+ xOptions |= (xOptions && IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL))?2:0;
+ xOptions |= (xOptions && IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENTOVERLAY))?4:0;
+ db_set_b(NULL,"CLUI","XStatusTray",xOptions);
+
+ int cursel = SendDlgItemMessage(hwndDlg,IDC_PRIMARYSTATUS,CB_GETCURSEL,0,0);
+ PROTOACCOUNT* pa = (PROTOACCOUNT*)SendDlgItemMessage(hwndDlg,IDC_PRIMARYSTATUS,CB_GETITEMDATA,cursel,0);
+ if ( !pa )
+ db_unset(NULL, "CList","PrimaryStatus");
+ else
+ db_set_s(NULL,"CList","PrimaryStatus", pa->szModuleName);
+ }
+ pcli->pfnTrayIconIconsChanged();
+ pcli->pfnLoadContactTree(); /* this won't do job properly since it only really works when changes happen */
+ SendMessage(pcli->hwndContactTree,CLM_AUTOREBUILD,0,0); /* force reshuffle */
+ ClcOptionsChanged(); // Used to force loading avatar an list height related options
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+void ClcOptionsChanged(void)
+{
+ pcli->pfnClcBroadcast( INTM_RELOADOPTIONS,0,0);
+ pcli->pfnClcBroadcast( INTM_INVALIDATE,0,0);
+}
+
+HWND g_hCLUIOptionsWnd = NULL;
+
+static INT_PTR CALLBACK DlgProcClistBehaviourOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_CLIENTDRAG, db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DRAGTOSCROLL, (db_get_b(NULL,"CLUI","DragToScroll",SETTING_DRAGTOSCROLL_DEFAULT) && !db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_AUTOSIZE, g_CluiData.fAutoSize ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_LOCKSIZING, db_get_b(NULL,"CLUI","LockSize",SETTING_LOCKSIZE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_BRINGTOFRONT, db_get_b(NULL,"CList","BringToFront",SETTING_BRINGTOFRONT_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+
+ SendDlgItemMessage(hwndDlg,IDC_MAXSIZESPIN,UDM_SETRANGE,0,MAKELONG(100,0));
+ SendDlgItemMessage(hwndDlg,IDC_MAXSIZESPIN,UDM_SETPOS,0,db_get_b(NULL,"CLUI","MaxSizeHeight",SETTING_MAXSIZEHEIGHT_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_MINSIZESPIN,UDM_SETRANGE,0,MAKELONG(100,0));
+ SendDlgItemMessage(hwndDlg,IDC_MINSIZESPIN,UDM_SETPOS,0,db_get_b(NULL,"CLUI","MinSizeHeight",SETTING_MINSIZEHEIGHT_DEFAULT));
+ CheckDlgButton(hwndDlg, IDC_AUTOSIZEUPWARD, db_get_b(NULL,"CLUI","AutoSizeUpward",SETTING_AUTOSIZEUPWARD_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SNAPTOEDGES, db_get_b(NULL,"CLUI","SnapToEdges",SETTING_SNAPTOEDGES_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DOCKTOSIDES, db_get_b(NULL,"CLUI","DockToSides",SETTING_DOCKTOSIDES_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_EVENTAREA_NONE, db_get_b(NULL,"CLUI","EventArea",SETTING_EVENTAREAMODE_DEFAULT) == 0 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_EVENTAREA, db_get_b(NULL,"CLUI","EventArea",SETTING_EVENTAREAMODE_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_EVENTAREA_ALWAYS, db_get_b(NULL,"CLUI","EventArea",SETTING_EVENTAREAMODE_DEFAULT) == 2 ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_AUTOHIDE, db_get_b(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(db_get_w(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));
+ {
+ int i, item;
+ TCHAR *hidemode[] = {TranslateT("Hide to tray"), TranslateT("Behind left edge"), TranslateT("Behind right edge")};
+ for (i=0; i < SIZEOF(hidemode); i++) {
+ item = SendDlgItemMessage(hwndDlg,IDC_HIDEMETHOD,CB_ADDSTRING,0,(LPARAM)(hidemode[i]));
+ SendDlgItemMessage(hwndDlg,IDC_HIDEMETHOD,CB_SETITEMDATA,item,(LPARAM)0);
+ SendDlgItemMessage(hwndDlg,IDC_HIDEMETHOD,CB_SETCURSEL,db_get_b(NULL,"ModernData","HideBehind",SETTING_HIDEBEHIND_DEFAULT),0);
+ }
+ }
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN2,UDM_SETRANGE,0,MAKELONG(600,0));
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN2,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"ModernData","ShowDelay",SETTING_SHOWDELAY_DEFAULT),0));
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN3,UDM_SETRANGE,0,MAKELONG(600,0));
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN3,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"ModernData","HideDelay",SETTING_HIDEDELAY_DEFAULT),0));
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN4,UDM_SETRANGE,0,MAKELONG(50,1));
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN4,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"ModernData","HideBehindBorderSize",SETTING_HIDEBEHINDBORDERSIZE_DEFAULT),0));
+ {
+ int mode = SendDlgItemMessage(hwndDlg,IDC_HIDEMETHOD,CB_GETCURSEL,0,0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWDELAY),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDEDELAY),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN2),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN3),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN4),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDEDELAY2),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC5),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC6),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC7),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC8),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC10),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC13),mode != 0);
+ }
+
+ 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_MINSIZEHEIGHT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MINSIZESPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AUTOSIZEUPWARD),FALSE);
+ }
+ 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_DRAGTOSCROLL && IsDlgButtonChecked(hwndDlg,IDC_CLIENTDRAG)) {
+ CheckDlgButton(hwndDlg,IDC_CLIENTDRAG,FALSE);
+ }
+ else if (LOWORD(wParam) == IDC_CLIENTDRAG && IsDlgButtonChecked(hwndDlg,IDC_DRAGTOSCROLL)) {
+ CheckDlgButton(hwndDlg,IDC_DRAGTOSCROLL,FALSE);
+ }
+ 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_MINSIZEHEIGHT),IsDlgButtonChecked(hwndDlg,IDC_AUTOSIZE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MINSIZESPIN),IsDlgButtonChecked(hwndDlg,IDC_AUTOSIZE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AUTOSIZEUPWARD),IsDlgButtonChecked(hwndDlg,IDC_AUTOSIZE));
+ }
+ else if (LOWORD(wParam) == IDC_HIDEMETHOD)
+ {
+ int mode = SendDlgItemMessage(hwndDlg,IDC_HIDEMETHOD,CB_GETCURSEL,0,0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWDELAY),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDEDELAY),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN2),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN3),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN4),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDEDELAY2),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC5),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC6),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC7),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC8),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC10),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC13),mode != 0);
+ }
+ if ((LOWORD(wParam) == IDC_HIDETIME || LOWORD(wParam) == IDC_HIDEDELAY2 || LOWORD(wParam) == IDC_HIDEDELAY || LOWORD(wParam) == IDC_SHOWDELAY || LOWORD(wParam) == IDC_MAXSIZEHEIGHT || LOWORD(wParam) == IDC_MINSIZEHEIGHT) &&
+ (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()))
+ return 0;
+
+ // Enable apply button
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"ModernData","HideBehind",(BYTE)SendDlgItemMessage(hwndDlg,IDC_HIDEMETHOD,CB_GETCURSEL,0,0));
+ db_set_w(NULL,"ModernData","ShowDelay",(WORD)SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN2,UDM_GETPOS,0,0));
+ db_set_w(NULL,"ModernData","HideDelay",(WORD)SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN3,UDM_GETPOS,0,0));
+ db_set_w(NULL,"ModernData","HideBehindBorderSize",(WORD)SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN4,UDM_GETPOS,0,0));
+
+ db_set_b(NULL,"CLUI","DragToScroll",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DRAGTOSCROLL));
+ db_set_b(NULL,"CList","BringToFront",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_BRINGTOFRONT));
+ g_mutex_bChangingMode = TRUE;
+ db_set_b(NULL,"CLUI","ClientAreaDrag",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_CLIENTDRAG));
+ db_set_b(NULL,"CLUI","AutoSize",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_AUTOSIZE));
+ db_set_b(NULL,"CLUI","LockSize",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_LOCKSIZING));
+ db_set_b(NULL,"CLUI","MaxSizeHeight",(BYTE)GetDlgItemInt(hwndDlg,IDC_MAXSIZEHEIGHT,NULL,FALSE));
+ db_set_b(NULL,"CLUI","MinSizeHeight",(BYTE)GetDlgItemInt(hwndDlg,IDC_MINSIZEHEIGHT,NULL,FALSE));
+ db_set_b(NULL,"CLUI","AutoSizeUpward",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_AUTOSIZEUPWARD));
+ db_set_b(NULL,"CLUI","SnapToEdges",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_SNAPTOEDGES));
+
+ db_set_b(NULL,"CLUI","DockToSides",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DOCKTOSIDES));
+
+ db_set_b(NULL,"CLUI","EventArea",
+ (BYTE)(IsDlgButtonChecked(hwndDlg,IDC_EVENTAREA_ALWAYS)?2:(BYTE)IsDlgButtonChecked(hwndDlg,IDC_EVENTAREA)?1:0));
+
+ db_set_b(NULL,"CList","AutoHide",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ db_set_w(NULL,"CList","HideTime",(WORD)SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN,UDM_GETPOS,0,0));
+ CLUI_ChangeWindowMode();
+ SendMessage(pcli->hwndContactTree,WM_SIZE,0,0); //forces it to send a cln_listsizechanged
+ CLUI_ReloadCLUIOptions();
+ EventArea_ConfigureEventArea();
+ cliShowHide(0,1);
+ g_mutex_bChangingMode = FALSE;
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK DlgProcClistWindowOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ BOOL fEnabled = FALSE;
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ g_hCLUIOptionsWnd = hwndDlg;
+ CheckDlgButton(hwndDlg, IDC_ONTOP, db_get_b(NULL,"CList","OnTop",SETTING_ONTOP_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ {
+ //====== Activate/Deactivate Non-Layered items =======
+ fEnabled = !g_CluiData.fLayered || g_CluiData.fDisableSkinEngine;
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOOLWND),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MIN2TRAY),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BORDER),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_NOBORDERWND),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWCAPTION),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWMAINMENU),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TITLETEXT),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DROPSHADOW),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AEROGLASS),!fEnabled && (g_proc_DWMEnableBlurBehindWindow != NULL));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TITLEBAR_STATIC),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ROUNDCORNERS),fEnabled);
+ }
+ {
+ //====== Non-Layered Mode =====
+ CheckDlgButton(hwndDlg, IDC_TOOLWND, db_get_b(NULL,"CList","ToolWindow",SETTING_TOOLWINDOW_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_MIN2TRAY, db_get_b(NULL,"CList","Min2Tray",SETTING_MIN2TRAY_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_BORDER, db_get_b(NULL,"CList","ThinBorder",SETTING_THINBORDER_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_NOBORDERWND, db_get_b(NULL,"CList","NoBorder",SETTING_NOBORDER_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ if (IsDlgButtonChecked(hwndDlg,IDC_TOOLWND))
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MIN2TRAY),FALSE);
+ CheckDlgButton(hwndDlg, IDC_SHOWCAPTION, db_get_b(NULL,"CLUI","ShowCaption",SETTING_SHOWCAPTION_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWMAINMENU, db_get_b(NULL,"CLUI","ShowMainMenu",SETTING_SHOWMAINMENU_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);
+ }
+ if (IsDlgButtonChecked(hwndDlg,IDC_BORDER) || IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MIN2TRAY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOOLWND),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TITLETEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWCAPTION),FALSE);
+ }
+ CheckDlgButton(hwndDlg, IDC_DROPSHADOW, db_get_b(NULL,"CList","WindowShadow",SETTING_WINDOWSHADOW_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_ROUNDCORNERS, db_get_b(NULL,"CLC","RoundCorners",SETTING_ROUNDCORNERS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ } //====== End of Non-Layered Mode =====
+
+ CheckDlgButton(hwndDlg, IDC_FADEINOUT, db_get_b(NULL,"CLUI","FadeInOut",SETTING_FADEIN_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_ONDESKTOP, db_get_b(NULL,"CList","OnDesktop", SETTING_ONDESKTOP_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ SendDlgItemMessage(hwndDlg,IDC_FRAMESSPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_CAPTIONSSPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_FRAMESSPIN,UDM_SETPOS,0,db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_CAPTIONSSPIN,UDM_SETPOS,0,db_get_dw(NULL,"CLUIFrames","GapBetweenTitleBar",SETTING_GAPTITLEBAR_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_LEFTMARGINSPIN,UDM_SETRANGE,0,MAKELONG(250,0));
+ SendDlgItemMessage(hwndDlg,IDC_RIGHTMARGINSPIN,UDM_SETRANGE,0,MAKELONG(250,0));
+ SendDlgItemMessage(hwndDlg,IDC_TOPMARGINSPIN,UDM_SETRANGE,0,MAKELONG(250,0));
+ SendDlgItemMessage(hwndDlg,IDC_BOTTOMMARGINSPIN,UDM_SETRANGE,0,MAKELONG(250,0));
+ SendDlgItemMessage(hwndDlg,IDC_LEFTMARGINSPIN,UDM_SETPOS,0,db_get_b(NULL,"CLUI","LeftClientMargin",SETTING_LEFTCLIENTMARIGN_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_RIGHTMARGINSPIN,UDM_SETPOS,0,db_get_b(NULL,"CLUI","RightClientMargin",SETTING_RIGHTCLIENTMARIGN_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_TOPMARGINSPIN,UDM_SETPOS,0,db_get_b(NULL,"CLUI","TopClientMargin",SETTING_TOPCLIENTMARIGN_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_BOTTOMMARGINSPIN,UDM_SETPOS,0,db_get_b(NULL,"CLUI","BottomClientMargin",SETTING_BOTTOMCLIENTMARIGN_DEFAULT));
+
+ CheckDlgButton(hwndDlg, IDC_DISABLEENGINE, db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_AEROGLASS, db_get_b(NULL,"ModernData","AeroGlass",SETTING_AEROGLASS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_LAYERENGINE),(g_proc_UpdateLayeredWindow != NULL && !db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT))?TRUE:FALSE);
+ CheckDlgButton(hwndDlg, IDC_LAYERENGINE, ((db_get_b(NULL,"ModernData","EnableLayering",SETTING_ENABLELAYERING_DEFAULT) && g_proc_UpdateLayeredWindow != NULL) && !db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT)) ? BST_UNCHECKED:BST_CHECKED);
+
+ {
+ DBVARIANT dbv = {0};
+ TCHAR *s;
+ if ( !DBGetContactSettingTString(NULL,"CList","TitleText",&dbv))
+ s = dbv.ptszVal;
+ else
+ s = _T(MIRANDANAME);
+ SetDlgItemText(hwndDlg, IDC_TITLETEXT, s);
+ db_free(&dbv);
+
+ SendDlgItemMessage(hwndDlg,IDC_TITLETEXT,CB_ADDSTRING,0,(LPARAM)MIRANDANAME);
+
+ char szUin[20];
+ sprintf(szUin,"%u",db_get_dw(NULL,"ICQ","UIN",0));
+ SendDlgItemMessage(hwndDlg,IDC_TITLETEXT,CB_ADDSTRING,0,(LPARAM)szUin);
+
+ if ( !DBGetContactSettingString(NULL,"ICQ","Nick",&dbv)) {
+ SendDlgItemMessage(hwndDlg,IDC_TITLETEXT,CB_ADDSTRING,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ dbv.pszVal = NULL;
+ }
+ if ( !DBGetContactSettingString(NULL,"ICQ","FirstName",&dbv)) {
+ SendDlgItemMessage(hwndDlg,IDC_TITLETEXT,CB_ADDSTRING,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ dbv.pszVal = NULL;
+ }
+ if ( !DBGetContactSettingString(NULL,"ICQ","e-mail",&dbv)) {
+ SendDlgItemMessage(hwndDlg,IDC_TITLETEXT,CB_ADDSTRING,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ dbv.pszVal = NULL;
+ }
+ }
+ 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,db_get_b(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,db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_TRANSINACTIVE,TBM_SETPOS,TRUE,db_get_b(NULL,"CList","AutoAlpha",SETTING_AUTOALPHA_DEFAULT));
+ SendMessage(hwndDlg,WM_HSCROLL,0x12345678,0);
+ return TRUE;
+
+ case WM_COMMAND:
+ 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_LAYERENGINE || LOWORD(wParam) == IDC_DISABLEENGINE)
+ { //====== Activate/Deactivate Non-Layered items =======
+ fEnabled = !(IsWindowEnabled(GetDlgItem(hwndDlg,IDC_LAYERENGINE)) && !IsDlgButtonChecked(hwndDlg,IDC_LAYERENGINE) && !IsDlgButtonChecked(hwndDlg,IDC_DISABLEENGINE));
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOOLWND),fEnabled && (IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION)) && !(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MIN2TRAY),fEnabled && (IsDlgButtonChecked(hwndDlg,IDC_TOOLWND) && IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION)) && !(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TITLETEXT),fEnabled && (IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION)) && !(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWCAPTION),fEnabled && !(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BORDER),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_NOBORDERWND),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWMAINMENU),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DROPSHADOW),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AEROGLASS),!fEnabled && (g_proc_DWMEnableBlurBehindWindow != NULL));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TITLEBAR_STATIC),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ROUNDCORNERS),fEnabled);
+ if (LOWORD(wParam) == IDC_DISABLEENGINE)
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_LAYERENGINE),!IsDlgButtonChecked(hwndDlg,IDC_DISABLEENGINE) && g_proc_UpdateLayeredWindow != NULL);
+ if (IsDlgButtonChecked(hwndDlg,IDC_DISABLEENGINE))
+ CheckDlgButton(hwndDlg,IDC_LAYERENGINE,BST_CHECKED);
+ }
+
+ }
+ else if (LOWORD(wParam) == IDC_ONDESKTOP && IsDlgButtonChecked(hwndDlg,IDC_ONDESKTOP)) {
+ CheckDlgButton(hwndDlg, IDC_ONTOP, BST_UNCHECKED);
+ }
+ else if (LOWORD(wParam) == IDC_ONTOP && IsDlgButtonChecked(hwndDlg,IDC_ONTOP)) {
+ CheckDlgButton(hwndDlg, IDC_ONDESKTOP, BST_UNCHECKED);
+ }
+ 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));
+ }
+ else if (LOWORD(wParam) == IDC_NOBORDERWND || LOWORD(wParam) == IDC_BORDER)
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOOLWND),(IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION)) && !(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MIN2TRAY),(IsDlgButtonChecked(hwndDlg,IDC_TOOLWND) && IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION)) && !(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TITLETEXT),(IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION)) && !(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWCAPTION),!(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ if (LOWORD(wParam) == IDC_BORDER) CheckDlgButton(hwndDlg, IDC_NOBORDERWND,BST_UNCHECKED);
+ else CheckDlgButton(hwndDlg, IDC_BORDER,BST_UNCHECKED);
+
+ }
+ if ((LOWORD(wParam) == IDC_TITLETEXT || LOWORD(wParam) == IDC_MAXSIZEHEIGHT || LOWORD(wParam) == IDC_MINSIZEHEIGHT || LOWORD(wParam) == IDC_FRAMESGAP || LOWORD(wParam) == IDC_CAPTIONSGAP ||
+ LOWORD(wParam) == IDC_LEFTMARGIN || LOWORD(wParam) == IDC_RIGHTMARGIN || LOWORD(wParam) == IDC_TOPMARGIN || LOWORD(wParam) == IDC_BOTTOMMARGIN)
+ && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()))
+ return 0;
+ // Enable apply button
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_HSCROLL:
+ { char str[10];
+ sprintf(str,"%d%%",100*SendDlgItemMessage(hwndDlg,IDC_TRANSINACTIVE,TBM_GETPOS,0,0)/255);
+ SetDlgItemTextA(hwndDlg,IDC_INACTIVEPERC,str);
+ sprintf(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, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CLUI","LeftClientMargin",(BYTE)SendDlgItemMessage(hwndDlg,IDC_LEFTMARGINSPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CLUI","RightClientMargin",(BYTE)SendDlgItemMessage(hwndDlg,IDC_RIGHTMARGINSPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CLUI","TopClientMargin",(BYTE)SendDlgItemMessage(hwndDlg,IDC_TOPMARGINSPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CLUI","BottomClientMargin",(BYTE)SendDlgItemMessage(hwndDlg,IDC_BOTTOMMARGINSPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"ModernData","DisableEngine",IsDlgButtonChecked(hwndDlg,IDC_DISABLEENGINE));
+ db_set_b(NULL,"ModernData","AeroGlass",IsDlgButtonChecked(hwndDlg,IDC_AEROGLASS));
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_DISABLEENGINE))
+ {
+ if (g_proc_UpdateLayeredWindow != NULL && IsDlgButtonChecked(hwndDlg,IDC_LAYERENGINE))
+ db_set_b(NULL,"ModernData","EnableLayering",0);
+ else
+ db_unset(NULL,"ModernData","EnableLayering");
+ }
+ g_CluiData.dwKeyColor = db_get_dw(NULL,"ModernSettings","KeyColor",(DWORD)SETTING_KEYCOLOR_DEFAULT);
+ db_set_b(NULL,"CList","OnDesktop",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_ONDESKTOP));
+ db_set_b(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 |SWP_NOACTIVATE);
+ db_set_b(NULL,"CLUI","DragToScroll",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DRAGTOSCROLL));
+
+ { //====== Non-Layered Mode ======
+ db_set_b(NULL,"CList","ToolWindow",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_TOOLWND));
+ db_set_b(NULL,"CLUI","ShowCaption",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION));
+ db_set_b(NULL,"CLUI","ShowMainMenu",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOWMAINMENU));
+ db_set_b(NULL,"CList","ThinBorder",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_BORDER));
+ db_set_b(NULL,"CList","NoBorder",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND));
+ {
+ TCHAR title[256];
+ GetDlgItemText(hwndDlg,IDC_TITLETEXT,title,SIZEOF(title));
+ db_set_ws(NULL,"CList","TitleText",title);
+ }
+ db_set_b(NULL,"CList","Min2Tray",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_MIN2TRAY));
+ db_set_b(NULL,"CList","WindowShadow",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DROPSHADOW));
+ db_set_b(NULL,"CLC","RoundCorners",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_ROUNDCORNERS));
+ } //====== End of Non-Layered Mode ======
+ g_mutex_bChangingMode = TRUE;
+
+ if (IsDlgButtonChecked(hwndDlg,IDC_ONDESKTOP))
+ {
+ HWND hProgMan = FindWindow(_T("Progman"),NULL);
+ if (IsWindow(hProgMan))
+ {
+ SetParent(pcli->hwndContactList,hProgMan);
+ Sync( CLUIFrames_SetParentForContainers, (HWND)hProgMan );
+ g_CluiData.fOnDesktop = 1;
+ }
+ }
+ else
+ {
+ if (GetParent(pcli->hwndContactList))
+ {
+ SetParent(pcli->hwndContactList,NULL);
+ Sync( CLUIFrames_SetParentForContainers, (HWND)NULL );
+ }
+ g_CluiData.fOnDesktop = 0;
+ }
+ AniAva_UpdateParent();
+ db_set_b(NULL,"CLUI","FadeInOut",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_FADEINOUT));
+ g_CluiData.fSmoothAnimation = IsWinVer2000Plus() && (BYTE)IsDlgButtonChecked(hwndDlg,IDC_FADEINOUT);
+ {
+ int i1 = SendDlgItemMessage(hwndDlg,IDC_FRAMESSPIN,UDM_GETPOS,0,0);
+ int i2 = SendDlgItemMessage(hwndDlg,IDC_CAPTIONSSPIN,UDM_GETPOS,0,0);
+
+ db_set_dw(NULL,"CLUIFrames","GapBetweenFrames",(DWORD)i1);
+ db_set_dw(NULL,"CLUIFrames","GapBetweenTitleBar",(DWORD)i2);
+ Sync(CLUIFramesOnClistResize, (WPARAM)pcli->hwndContactList,(LPARAM)0);
+ }
+ db_set_b(NULL,"CList","Transparent",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT));
+ db_set_b(NULL,"CList","Alpha",(BYTE)SendDlgItemMessage(hwndDlg,IDC_TRANSACTIVE,TBM_GETPOS,0,0));
+ db_set_b(NULL,"CList","AutoAlpha",(BYTE)SendDlgItemMessage(hwndDlg,IDC_TRANSINACTIVE,TBM_GETPOS,0,0));
+ db_set_b(NULL,"CList","OnDesktop",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_ONDESKTOP));
+
+ ske_LoadSkinFromDB();
+ CLUI_UpdateLayeredMode();
+ CLUI_ChangeWindowMode();
+ SendMessage(pcli->hwndContactTree,WM_SIZE,0,0); //forces it to send a cln_listsizechanged
+ CLUI_ReloadCLUIOptions();
+ cliShowHide(0,1);
+ g_mutex_bChangingMode = FALSE;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+#include "hdr/modern_commonheaders.h"
+
+#define CLBF_TILEVTOROWHEIGHT 0x0100
+
+
+#define DEFAULT_BKCOLOUR GetSysColor(COLOR_3DFACE)
+#define DEFAULT_USEBITMAP 0
+#define DEFAULT_BKBMPUSE CLB_STRETCH
+#define DEFAULT_SELBKCOLOUR GetSysColor(COLOR_HIGHLIGHT)
+
+extern HINSTANCE g_hInst;
+
+char **bkgrList = NULL;
+int bkgrCount = 0;
+
+#define M_BKGR_UPDATE (WM_USER+10)
+#define M_BKGR_SETSTATE (WM_USER+11)
+#define M_BKGR_GETSTATE (WM_USER+12)
+
+#define M_BKGR_BACKCOLOR 0x01
+#define M_BKGR_SELECTCOLOR 0x02
+#define M_BKGR_ALLOWBITMAPS 0x04
+#define M_BKGR_STRETCH 0x08
+#define M_BKGR_TILE 0x10
+
+static int bitmapRelatedControls[] = {
+ IDC_FILENAME,IDC_BROWSE,IDC_STRETCHH,IDC_STRETCHV,IDC_TILEH,IDC_TILEV,
+ IDC_SCROLL,IDC_PROPORTIONAL,IDC_TILEVROWH
+};
+struct BkgrItem
+{
+ BYTE changed;
+ BYTE useBitmap;
+ COLORREF bkColor, selColor;
+ char filename[MAX_PATH];
+ WORD flags;
+ BYTE useWinColours;
+};
+struct BkgrData
+{
+ struct BkgrItem *item;
+ int indx;
+ int count;
+};
+
+static INT_PTR CALLBACK DlgProcClcBkgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct BkgrData *dat = (struct BkgrData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ int indx;
+ HWND hList = GetDlgItem(hwndDlg, IDC_BKGRLIST);
+ TranslateDialogDefault(hwndDlg);
+
+ dat = (struct BkgrData*)mir_alloc(sizeof(struct BkgrData));
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
+ dat->count = bkgrCount;
+ dat->item = (struct BkgrItem*)mir_alloc(sizeof(struct BkgrItem)*dat->count);
+ dat->indx = CB_ERR;
+ for (indx = 0; indx < dat->count; indx++)
+ {
+ char *module = bkgrList[indx] + strlen(bkgrList[indx]) + 1;
+ int jndx;
+
+ dat->item[indx].changed = FALSE;
+ dat->item[indx].useBitmap = db_get_b(NULL,module, "UseBitmap", DEFAULT_USEBITMAP);
+ dat->item[indx].bkColor = db_get_dw(NULL,module, "BkColour", DEFAULT_BKCOLOUR);
+ dat->item[indx].selColor = db_get_dw(NULL,module, "SelBkColour", DEFAULT_SELBKCOLOUR);
+ dat->item[indx].useWinColours = db_get_b(NULL,module, "UseWinColours", CLCDEFAULT_USEWINDOWSCOLOURS);
+ {
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingString(NULL,module,"BkBitmap",&dbv))
+ {
+ int retval = CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)dbv.pszVal, (LPARAM)dat->item[indx].filename);
+ if ( !retval || retval == CALLSERVICE_NOTFOUND)
+ lstrcpynA(dat->item[indx].filename, dbv.pszVal, MAX_PATH);
+ mir_free(dbv.pszVal);
+ }
+ else
+ *dat->item[indx].filename = 0;
+ }
+ dat->item[indx].flags = db_get_w(NULL,module,"BkBmpUse", DEFAULT_BKBMPUSE);
+ jndx = SendMessageA(hList, CB_ADDSTRING, 0, (LPARAM)Translate(bkgrList[indx]));
+ SendMessage(hList, CB_SETITEMDATA, jndx, indx);
+ }
+ SendMessage(hList, CB_SETCURSEL, 0, 0);
+ PostMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_BKGRLIST, CBN_SELCHANGE), 0);
+ {
+ 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_DESTROY:
+ if (dat) {
+ mir_free(dat->item);
+ mir_free(dat);
+ }
+
+ return TRUE;
+
+ case M_BKGR_GETSTATE:
+ {
+ int indx = wParam;
+ if (indx == CB_ERR || indx >= dat->count) break;
+ indx = SendDlgItemMessage(hwndDlg, IDC_BKGRLIST, CB_GETITEMDATA, indx, 0);
+
+ dat->item[indx].useBitmap = IsDlgButtonChecked(hwndDlg,IDC_BITMAP);
+ dat->item[indx].useWinColours = IsDlgButtonChecked(hwndDlg,IDC_USEWINCOL);
+ dat->item[indx].bkColor = SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR,0,0);
+ dat->item[indx].selColor = SendDlgItemMessage(hwndDlg, IDC_SELCOLOUR, CPM_GETCOLOUR,0,0);
+
+ GetDlgItemTextA(hwndDlg, IDC_FILENAME, dat->item[indx].filename, SIZEOF(dat->item[indx].filename));
+ {
+ 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;
+ if (IsDlgButtonChecked(hwndDlg,IDC_TILEVROWH)) flags |= CLBF_TILEVTOROWHEIGHT;
+ dat->item[indx].flags = flags;
+ }
+ break;
+ }
+ case M_BKGR_SETSTATE:
+ {
+ int flags;
+ int indx = wParam;
+ if (indx == -1) break;
+ flags = dat->item[indx].flags;
+ if (indx == CB_ERR || indx >= dat->count) break;
+ indx = SendDlgItemMessage(hwndDlg, IDC_BKGRLIST, CB_GETITEMDATA, indx, 0);
+
+ CheckDlgButton(hwndDlg, IDC_BITMAP, dat->item[indx].useBitmap?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_USEWINCOL, dat->item[indx].useWinColours?BST_CHECKED:BST_UNCHECKED);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BKGCOLOUR), !dat->item[indx].useWinColours);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SELCOLOUR), !dat->item[indx].useWinColours);
+
+ SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETDEFAULTCOLOUR, 0, DEFAULT_BKCOLOUR);
+ SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETCOLOUR, 0, dat->item[indx].bkColor);
+ SendDlgItemMessage(hwndDlg, IDC_SELCOLOUR, CPM_SETDEFAULTCOLOUR, 0, DEFAULT_SELBKCOLOUR);
+ SendDlgItemMessage(hwndDlg, IDC_SELCOLOUR, CPM_SETCOLOUR, 0, dat->item[indx].selColor);
+ SetDlgItemTextA(hwndDlg, IDC_FILENAME, dat->item[indx].filename);
+
+ CheckDlgButton(hwndDlg,IDC_STRETCHH, flags&CLB_STRETCHH?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_STRETCHV,flags&CLB_STRETCHV?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_TILEH,flags&CLBF_TILEH?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_TILEV,flags&CLBF_TILEV?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_SCROLL,flags&CLBF_SCROLL?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_PROPORTIONAL,flags&CLBF_PROPORTIONAL?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_TILEVROWH,flags&CLBF_TILEVTOROWHEIGHT?BST_CHECKED:BST_UNCHECKED);
+
+ SendMessage(hwndDlg, M_BKGR_UPDATE, 0,0);
+ break;
+ }
+ case M_BKGR_UPDATE:
+ {
+ int isChecked = IsDlgButtonChecked(hwndDlg,IDC_BITMAP);
+ int indx;
+ for (indx = 0; indx < SIZEOF(bitmapRelatedControls); indx++)
+ EnableWindow(GetDlgItem(hwndDlg, bitmapRelatedControls[indx]),isChecked);
+ 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, M_BKGR_UPDATE, 0,0);
+ if (LOWORD(wParam) == IDC_FILENAME && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()))
+ return 0;
+ if (LOWORD(wParam) == IDC_BKGRLIST)
+ {
+ if (HIWORD(wParam) == CBN_SELCHANGE)
+ {
+ SendMessage(hwndDlg, M_BKGR_GETSTATE, dat->indx, 0);
+ SendMessage(hwndDlg, M_BKGR_SETSTATE, dat->indx = SendDlgItemMessage(hwndDlg, IDC_BKGRLIST, CB_GETCURSEL, 0,0), 0);
+ }
+ return 0;
+ }
+ {
+ int indx = SendDlgItemMessage(hwndDlg, IDC_BKGRLIST, CB_GETCURSEL, 0,0);
+ if (indx != CB_ERR && indx < dat->count)
+ {
+ indx = SendDlgItemMessage(hwndDlg, IDC_BKGRLIST, CB_GETITEMDATA, indx, 0);
+ dat->item[indx].changed = TRUE;
+
+ }
+ {
+ BOOL EnableColours = !IsDlgButtonChecked(hwndDlg,IDC_USEWINCOL);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BKGCOLOUR), EnableColours);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SELCOLOUR), EnableColours);
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0,0);
+ }
+ break;
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ SendMessage(hwndDlg, M_BKGR_GETSTATE, SendDlgItemMessage(hwndDlg, IDC_BKGRLIST, CB_GETCURSEL, 0,0), 0);
+ {
+ for (int indx = 0; indx < dat->count; indx++)
+ if (dat->item[indx].changed)
+ {
+ char *module = bkgrList[indx] + strlen(bkgrList[indx]) + 1;
+ db_set_b(NULL, module, "UseBitmap", (BYTE)dat->item[indx].useBitmap);
+
+ COLORREF col;
+ if ((col = dat->item[indx].bkColor) == DEFAULT_BKCOLOUR)
+ db_unset(NULL, module, "BkColour");
+ else
+ db_set_dw(NULL, module, "BkColour", col);
+
+ if ((col = dat->item[indx].selColor) == DEFAULT_SELBKCOLOUR)
+ db_unset(NULL, module, "SelBkColour");
+ else
+ db_set_dw(NULL, module, "SelBkColour", col);
+
+ db_set_b(NULL, module, "UseWinColours", (BYTE)dat->item[indx].useWinColours);
+
+ char str[MAX_PATH];
+ int retval = CallService(MS_UTILS_PATHTOABSOLUTE,
+ (WPARAM)dat->item[indx].filename,
+ (LPARAM)str);
+ if ( !retval || retval == CALLSERVICE_NOTFOUND)
+ db_set_s(NULL, module, "BkBitmap", dat->item[indx].filename);
+ else
+ db_set_s(NULL, module, "BkBitmap", str);
+
+ db_set_w(NULL, module, "BkBmpUse", dat->item[indx].flags);
+ dat->item[indx].changed = FALSE;
+ NotifyEventHooks(g_CluiData.hEventBkgrChanged, (WPARAM)module, 0);
+ }
+ return TRUE;
+ }
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR BkgrCfg_Register(WPARAM wParam,LPARAM lParam)
+{
+ char *szSetting = (char *)wParam;
+ char *value, *tok;
+ int len = strlen(szSetting) + 1;
+
+ value = (char *)mir_alloc(len + 4); // add room for flags (DWORD)
+ memcpy(value, szSetting, len);
+ tok = strchr(value, '/');
+ if (tok == NULL) {
+ mir_free(value);
+ return 1;
+ }
+ *tok = 0;
+ *(DWORD*)(value + len) = lParam;
+
+ bkgrList = (char **)mir_realloc(bkgrList, sizeof(char*)*(bkgrCount+1));
+ bkgrList[bkgrCount] = value;
+ bkgrCount++;
+ return 0;
+}
+
+HRESULT BackgroundsLoadModule()
+{
+ CreateServiceFunction(MS_BACKGROUNDCONFIG_REGISTER, BkgrCfg_Register);
+ return S_OK;
+}
+
+int BackgroundsUnloadModule(void)
+{
+ if (bkgrList != NULL) {
+ for (int indx = 0; indx < bkgrCount; indx++)
+ if (bkgrList[indx] != NULL)
+ mir_free(bkgrList[indx]);
+ mir_free(bkgrList);
+ }
+ DestroyHookableEvent(g_CluiData.hEventBkgrChanged);
+ g_CluiData.hEventBkgrChanged = NULL;
+
+ return 0;
+}
+
+
+
+
+
+enum
+{
+ CBVT_NONE,
+ CBVT_CHAR,
+ CBVT_INT,
+ CBVT_BYTE,
+ CBVT_DWORD,
+ CBVT_BOOL,
+};
+
+struct OptCheckBox
+{
+ UINT idc;
+
+ DWORD defValue; // should be full combined value for masked items!
+ DWORD dwBit;
+
+ BYTE dbType;
+ char *dbModule;
+ char *dbSetting;
+
+ BYTE valueType;
+ union
+ {
+ void *pValue;
+
+ char *charValue;
+ int *intValue;
+ BYTE *byteValue;
+ DWORD *dwordValue;
+ BOOL *boolValue;
+ };
+};
+
+DWORD OptCheckBox_LoadValue(struct OptCheckBox *cb)
+{
+ switch (cb->valueType)
+ {
+ case CBVT_NONE:
+ switch (cb->dbType)
+ {
+ case DBVT_BYTE:
+ return db_get_b(NULL, cb->dbModule, cb->dbSetting, cb->defValue);
+ case DBVT_WORD:
+ return db_get_w(NULL, cb->dbModule, cb->dbSetting, cb->defValue);
+ case DBVT_DWORD:
+ return db_get_dw(NULL, cb->dbModule, cb->dbSetting, cb->defValue);
+ }
+ break;
+
+ case CBVT_CHAR:
+ return *cb->charValue;
+ case CBVT_INT:
+ return *cb->intValue;
+ case CBVT_BYTE:
+ return *cb->byteValue;
+ case CBVT_DWORD:
+ return *cb->dwordValue;
+ case CBVT_BOOL:
+ return *cb->boolValue;
+ }
+
+ return cb->defValue;
+}
+
+void OptCheckBox_Load(HWND hwnd, struct OptCheckBox *cb)
+{
+ DWORD value = OptCheckBox_LoadValue(cb);
+ if (cb->dwBit) value &= cb->dwBit;
+ CheckDlgButton(hwnd, cb->idc, value ? BST_CHECKED : BST_UNCHECKED);
+}
+
+void OptCheckBox_Save(HWND hwnd, struct OptCheckBox *cb)
+{
+ DWORD value = IsDlgButtonChecked(hwnd, cb->idc) == BST_CHECKED;
+
+ if (cb->dwBit)
+ {
+ DWORD curValue = OptCheckBox_LoadValue(cb);
+ value = value ? (curValue | cb->dwBit) : (curValue & ~cb->dwBit);
+ }
+
+ switch (cb->dbType)
+ {
+ case DBVT_BYTE:
+ db_set_b(NULL, cb->dbModule, cb->dbSetting, (BYTE)value);
+ break;
+ case DBVT_WORD:
+ db_set_w(NULL, cb->dbModule, cb->dbSetting, (WORD)value);
+ break;
+ case DBVT_DWORD:
+ db_set_dw(NULL, cb->dbModule, cb->dbSetting, (DWORD)value);
+ break;
+ }
+
+ switch (cb->valueType)
+ {
+ case CBVT_CHAR:
+ *cb->charValue = (char)value;
+ break;
+ case CBVT_INT:
+ *cb->intValue = (int)value;
+ break;
+ case CBVT_BYTE:
+ *cb->byteValue = (BYTE)value;
+ break;
+ case CBVT_DWORD:
+ *cb->dwordValue = (DWORD)value;
+ break;
+ case CBVT_BOOL:
+ *cb->boolValue = (BOOL)value;
+ break;
+ }
+}
+
+static INT_PTR CALLBACK DlgProcModernOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct OptCheckBox opts[] =
+ {
+ //{IDC_, def, bit, dbtype, dbmodule, dbsetting, valtype, pval},
+ {IDC_ONTOP, SETTING_ONTOP_DEFAULT, 0, DBVT_BYTE, "CList", "OnTop"},
+ {IDC_AUTOHIDE, SETTING_AUTOHIDE_DEFAULT, 0, DBVT_BYTE, "CList", "AutoHide"},
+ {IDC_FADEINOUT, SETTING_FADEIN_DEFAULT, 0, DBVT_BYTE, "CLUI", "FadeInOut"},
+ {IDC_TRANSPARENT, SETTING_TRANSPARENT_DEFAULT, 0, DBVT_BYTE, "CList", "Transparent"},
+ {IDC_SHOWGROUPCOUNTS, GetDefaultExStyle(), CLS_EX_SHOWGROUPCOUNTS, DBVT_DWORD, "CLC", "ExStyle"},
+ {IDC_HIDECOUNTSWHENEMPTY, GetDefaultExStyle(), CLS_EX_HIDECOUNTSWHENEMPTY, DBVT_DWORD, "CLC", "ExStyle"},
+ {IDC_MINIMODE, SETTING_COMPACTMODE_DEFAULT, 0, DBVT_BYTE, "CLC", "CompactMode"},
+ {IDC_SHOW_AVATARS, SETTINGS_SHOWAVATARS_DEFAULT, 0, DBVT_BYTE, "CList","AvatarsShow"},
+ {IDC_SHOW_ANIAVATARS, FALSE, 0, DBVT_BYTE, "CList","AvatarsAnimated"},
+ {IDC_SHOW, SETTING_SHOWTIME_DEFAULT, 0, DBVT_BYTE, "CList", "ContactTimeShow"},
+ };
+
+ static bool bInit = true;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ bInit = true;
+
+ int i=0;
+ int item;
+ int s1, s2, s3;
+
+ TranslateDialogDefault(hwndDlg);
+ for (i=0; i < SIZEOF(opts); ++i)
+ OptCheckBox_Load(hwndDlg, opts+i);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIME),IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN),IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN,UDM_SETRANGE,0,MAKELONG(900,1));
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","HideTime",SETTING_HIDETIME_DEFAULT),0));
+
+ if ( !IsWinVer2000Plus())
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_FADEINOUT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSPARENT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DROPSHADOW),FALSE);
+ }
+
+ 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,db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_TRANSINACTIVE,TBM_SETPOS,TRUE,db_get_b(NULL,"CList","AutoAlpha",SETTING_AUTOALPHA_DEFAULT));
+ SendMessage(hwndDlg,WM_HSCROLL,0x12345678,0);
+
+
+ for (i=0; i < SIZEOF(sortby); i++)
+ {
+ item = SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_ADDSTRING,0,(LPARAM)TranslateTS(sortby[i]));
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_SETITEMDATA,item,(LPARAM)0);
+ item = SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_ADDSTRING,0,(LPARAM)TranslateTS(sortby[i]));
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_SETITEMDATA,item,(LPARAM)0);
+ item = SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_ADDSTRING,0,(LPARAM)TranslateTS(sortby[i]));
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_SETITEMDATA,item,(LPARAM)0);
+
+ }
+ s1 = db_get_b(NULL,"CList","SortBy1",SETTING_SORTBY1_DEFAULT);
+ s2 = db_get_b(NULL,"CList","SortBy2",SETTING_SORTBY2_DEFAULT);
+ s3 = db_get_b(NULL,"CList","SortBy3",SETTING_SORTBY3_DEFAULT);
+
+ for (i=0; i < SIZEOF(sortby); i++)
+ {
+ if (s1 == sortbyValue[i])
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_SETCURSEL,i,0);
+ if (s2 == sortbyValue[i])
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_SETCURSEL,i,0);
+ if (s3 == sortbyValue[i])
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_SETCURSEL,i,0);
+ }
+
+ bInit = false;
+ return TRUE;
+ }
+
+ case WM_DESTROY:
+ bInit = true;
+ break;
+
+ case WM_HSCROLL:
+ { char str[10];
+ sprintf(str,"%d%%",100*SendDlgItemMessage(hwndDlg,IDC_TRANSINACTIVE,TBM_GETPOS,0,0)/255);
+ SetDlgItemTextA(hwndDlg,IDC_INACTIVEPERC,str);
+ sprintf(str,"%d%%",100*SendDlgItemMessage(hwndDlg,IDC_TRANSACTIVE,TBM_GETPOS,0,0)/255);
+ SetDlgItemTextA(hwndDlg,IDC_ACTIVEPERC,str);
+ if (wParam != 0x12345678)
+ if ( !bInit) SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+ }
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_AUTOHIDE:
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIME),IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN),IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ break;
+ case 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));
+ break;
+ }
+ if ( !bInit) SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR) lParam)->idFrom)
+ {
+ case 0:
+ switch (((LPNMHDR) lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ int i;
+
+ g_mutex_bChangingMode = TRUE;
+
+ for (i=0; i < SIZEOF(opts); ++i)
+ OptCheckBox_Save(hwndDlg, opts+i);
+
+ SetWindowPos(pcli->hwndContactList, IsDlgButtonChecked(hwndDlg,IDC_ONTOP)?HWND_TOPMOST:HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ db_set_w(NULL,"CList","HideTime",(WORD)SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN,UDM_GETPOS,0,0));
+
+ db_set_b(NULL,"CList","Alpha",(BYTE)SendDlgItemMessage(hwndDlg,IDC_TRANSACTIVE,TBM_GETPOS,0,0));
+ db_set_b(NULL,"CList","AutoAlpha",(BYTE)SendDlgItemMessage(hwndDlg,IDC_TRANSINACTIVE,TBM_GETPOS,0,0));
+
+ {
+ int s1 = SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_GETCURSEL,0,0);
+ int s2 = SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_GETCURSEL,0,0);
+ int s3 = SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_GETCURSEL,0,0);
+ if (s1 >= 0) s1 = sortbyValue[s1];
+ if (s2 >= 0) s2 = sortbyValue[s2];
+ if (s3 >= 0) s3 = sortbyValue[s3];
+ db_set_b(NULL,"CList","SortBy1",(BYTE)s1);
+ db_set_b(NULL,"CList","SortBy2",(BYTE)s2);
+ db_set_b(NULL,"CList","SortBy3",(BYTE)s3);
+ }
+
+ ClcOptionsChanged();
+ AniAva_UpdateOptions();
+ ske_LoadSkinFromDB();
+ CLUI_UpdateLayeredMode();
+ CLUI_ChangeWindowMode();
+ SendMessage(pcli->hwndContactTree,WM_SIZE,0,0); //forces it to send a cln_listsizechanged
+ CLUI_ReloadCLUIOptions();
+ cliShowHide(0,1);
+ g_mutex_bChangingMode = FALSE;
+ return TRUE;
+ }
+ }
+ break;
+ }
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+int ModernOptInit(WPARAM wParam,LPARAM lParam)
+{
+ static int iBoldControls[] =
+ {
+ IDC_TXT_TITLE1, IDC_TXT_TITLE2,
+ IDC_TXT_TITLE3, IDC_TXT_TITLE4,
+ IDC_TXT_TITLE5,
+ 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.lptzSubsection = _T("Fonts");
+ obj.lpzClassicGroup = NULL;
+ obj.lpzClassicPage = "Contact List";
+ obj.lpzHelpUrl = "http://wiki.miranda-im.org/";
+
+ obj.lpzTemplate = MAKEINTRESOURCEA(IDD_MODERNOPTS);
+ obj.pfnDlgProc = DlgProcModernOptions;
+ CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj);
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_clcpaint.cpp b/plugins/Clist_modern/src/modern_clcpaint.cpp
new file mode 100644
index 0000000000..20839cb12c
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clcpaint.cpp
@@ -0,0 +1,3385 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+
+#include "m_clc.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_skinengine.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_row.h"
+#include "hdr/modern_clcpaint.h"
+
+CLCPaint g_clcPainter;
+
+DWORD CLCPaint::HASH[hi_LastItem] = {0};
+const char* CLCPaint::HASHTEXT[hi_LastItem] = {
+ "Module",
+ "ID",
+ "Type",
+ "Open",
+ "IsEmpty",
+ "SubPos",
+ "Protocol",
+ "RootGroup",
+ "Status",
+ "HasAvatar",
+ "GroupPos",
+ "Selected",
+ "Hot",
+ "Odd",
+ "Indent",
+ "Index",
+ "Name",
+ "Group",
+ "True",
+ "False",
+ "ONLINE",
+ "AWAY",
+ "DND",
+ "NA",
+ "OCCUPIED",
+ "FREECHAT",
+ "INVISIBLE",
+ "OUTTOLUNCH",
+ "ONTHEPHONE",
+ "IDLE",
+ "OFFLINE",
+ "Row",
+ "CL",
+ "SubContact",
+ "MetaContact",
+ "Contact",
+ "Divider",
+ "Info",
+ "First-Single",
+ "First",
+ "Middle",
+ "Mid",
+ "Single",
+ "Last",
+ "Rate",
+ "None",
+ "Low",
+ "Medium",
+ "High",
+ "State",
+ "Active",
+ "Inactive"
+ //ADD item here
+};
+const int CLCPaint::HORIZONTAL_SPACE = 2;
+const int CLCPaint::EXTRA_CHECKBOX_SPACE = 2;
+const int CLCPaint::EXTRA_SPACE = 2;
+const int CLCPaint::SELECTION_BORDER = 6;
+const int CLCPaint::MIN_TEXT_WIDTH = 20;
+const int CLCPaint::BUF2SIZE = 7;
+
+const BYTE CLCPaint::GIM_SELECTED_AFFECT = 1;
+const BYTE CLCPaint::GIM_HOT_AFFECT = 2;
+const BYTE CLCPaint::GIM_TEMP_AFFECT = 4;
+const BYTE CLCPaint::GIM_IDLE_AFFECT = 8;
+const BYTE CLCPaint::GIM_EXTRAICON_AFFECT = CLCPaint::GIM_SELECTED_AFFECT | CLCPaint::GIM_HOT_AFFECT | CLCPaint::GIM_IDLE_AFFECT | CLCPaint::GIM_TEMP_AFFECT;
+const BYTE CLCPaint::GIM_STATUSICON_AFFECT = CLCPaint::GIM_IDLE_AFFECT | CLCPaint::GIM_TEMP_AFFECT;
+const BYTE CLCPaint::GIM_AVATAR_AFFECT = CLCPaint::GIM_IDLE_AFFECT | CLCPaint::GIM_TEMP_AFFECT;
+
+CLCPaint::CLCPaint()
+{
+ _FillQuickHash();
+};
+
+void CLCPaint::cliPaintClc( HWND hwnd, struct ClcData *dat, HDC hdc, RECT *rcPaint )
+{
+ if ( MirandaExiting()) return;
+ g_CluiData.mutexPaintLock++;
+ g_clcPainter._PaintClc( hwnd, dat, hdc, rcPaint );
+ g_CluiData.mutexPaintLock--;
+}
+
+BOOL CLCPaint::IsForegroundWindow( HWND hWnd )
+{
+ HWND hWindow;
+ hWindow = hWnd;
+ while ( hWindow ) {
+ if ( GetForegroundWindow() == hWindow ) return TRUE;
+ hWindow = GetParent( hWindow );
+ }
+ return FALSE;
+}
+
+HFONT CLCPaint::ChangeToFont( HDC hdc, struct ClcData *dat, int id, int *fontHeight )
+{
+ if ( !dat )
+ dat = ( struct ClcData* )GetWindowLongPtr( pcli->hwndContactTree, 0 );
+
+ if ( !dat )
+ return NULL;
+
+ HFONT res = ( HFONT )SelectObject( hdc, dat->fontModernInfo[id].hFont );
+ SetTextColor( hdc, dat->fontModernInfo[id].colour );
+
+ if ( fontHeight )
+ *fontHeight = dat->fontModernInfo[id].fontHeight;
+ ske_ResetTextEffect( hdc );
+
+ if ( dat->hWnd == pcli->hwndContactTree && dat->fontModernInfo[id].effect != 0 )
+ ske_SelectTextEffect( hdc, dat->fontModernInfo[id].effect-1, dat->fontModernInfo[id].effectColour1, dat->fontModernInfo[id].effectColour2 );
+ else
+ ske_ResetTextEffect( hdc );
+
+ return res;
+}
+
+int CLCPaint::GetBasicFontID( struct ClcContact * contact )
+{
+ PDNCE pdnce = NULL;
+ if ( contact->type == CLCIT_CONTACT )
+ pdnce = ( PDNCE )pcli->pfnGetCacheEntry( contact->hContact );
+
+ switch ( contact->type )
+ {
+ case CLCIT_GROUP:
+ if ( contact->group->expanded )
+ return FONTID_OPENGROUPS;
+ else
+ return FONTID_CLOSEDGROUPS;
+ break;
+ case CLCIT_INFO:
+ if ( contact->flags & CLCIIF_GROUPFONT )
+ return FONTID_OPENGROUPS;
+ else
+ return FONTID_CONTACTS;
+ break;
+ case CLCIT_DIVIDER:
+ return FONTID_DIVIDERS;
+ break;
+ case CLCIT_CONTACT:
+ if ( contact->flags & CONTACTF_NOTONLIST )
+ return FONTID_NOTONLIST;
+ else if (( contact->flags&CONTACTF_INVISTO
+ && _GetRealStatus( contact, ID_STATUS_OFFLINE ) != ID_STATUS_INVISIBLE )
+ ||
+ ( contact->flags&CONTACTF_VISTO
+ && _GetRealStatus( contact, ID_STATUS_OFFLINE ) == 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
+ return contact->flags & CONTACTF_ONLINE ? FONTID_INVIS : FONTID_OFFINVIS;
+ }
+ else
+ {
+ switch( pdnce___GetStatus( pdnce ))
+ {
+ case ID_STATUS_OFFLINE: return FONTID_OFFLINE;
+ case ID_STATUS_AWAY: return FONTID_AWAY;
+ case ID_STATUS_DND: return FONTID_DND;
+ case ID_STATUS_NA: return FONTID_NA;
+ case ID_STATUS_OCCUPIED: return FONTID_OCCUPIED;
+ case ID_STATUS_FREECHAT: return FONTID_CHAT;
+ case ID_STATUS_INVISIBLE: return FONTID_INVISIBLE;
+ case ID_STATUS_ONTHEPHONE: return FONTID_PHONE;
+ case ID_STATUS_OUTTOLUNCH: return FONTID_LUNCH;
+ default: return FONTID_CONTACTS;
+ }
+ }
+ break;
+ default:
+ return FONTID_CONTACTS;
+ }
+}
+
+void CLCPaint::GetTextSize( SIZE *text_size, HDC hdcMem, RECT free_row_rc, TCHAR *szText, SortedList *plText, UINT uTextFormat, int smiley_height )
+{
+ if ( szText == NULL || !szText[0] )
+ {
+ text_size->cy = 0;
+ text_size->cx = 0;
+ }
+ else
+ {
+ RECT text_rc = free_row_rc;
+ int free_width;
+ int free_height;
+
+ free_width = text_rc.right - text_rc.left;
+ free_height = text_rc.bottom - text_rc.top;
+
+ // Always need cy...
+ text_size->cy = ske_DrawText( hdcMem, szText, lstrlen( szText ), &text_rc, DT_CALCRECT | uTextFormat );
+ text_size->cy = min( text_size->cy, free_height );
+ if ( plText == NULL )
+ {
+ text_size->cx = min( text_rc.right - text_rc.left + 2, free_width );
+ }
+ else
+ {
+ // See each item of list
+ int i;
+
+ text_size->cy = min( max( text_size->cy, smiley_height ), free_height );
+
+ text_size->cx = 0;
+
+ for ( i=0; i < plText->realCount && text_size->cx < free_width; i++ )
+ {
+ ClcContactTextPiece *piece = ( ClcContactTextPiece * ) plText->items[i];
+
+ if ( piece->type == TEXT_PIECE_TYPE_TEXT )
+ {
+ text_rc = free_row_rc;
+
+ ske_DrawText( hdcMem, &szText[piece->start_pos], piece->len, &text_rc, DT_CALCRECT | uTextFormat );
+ text_size->cx = min( text_size->cx + text_rc.right - text_rc.left + 2, free_width );
+ }
+ else
+ {
+ double factor;
+
+ if ( piece->smiley_height > text_size->cy )
+ {
+ factor = text_size->cy / ( double ) piece->smiley_height;
+ }
+ else
+ {
+ factor = 1;
+ }
+
+ text_size->cx = min( text_size->cx + ( long )( factor * piece->smiley_width ), free_width );
+ }
+ }
+ }
+ }
+}
+
+void CLCPaint::AddParam( MODERNMASK * mpModernMask, DWORD dwParamHash, const char* const szValue, DWORD dwValueHash )
+{
+ static MASKPARAM param = {0}; //AddParameter will clear it so it can be static to avoid initializations
+ _FillParam( &param, dwParamHash, szValue, dwValueHash );
+ _AddParameter( mpModernMask, &param );
+}
+BOOL CLCPaint::CheckMiniMode( struct ClcData *dat, BOOL selected, BOOL hot )
+{
+ if (( !dat->bCompactMode /* not mini*/ )
+ || (( dat->bCompactMode&0x01 ) && selected /*mini on selected*/ )
+ /* || ( TRUE && hot )*/ ) return FALSE;
+ return TRUE;
+}
+
+tPaintCallbackProc CLCPaint::PaintCallbackProc( HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData )
+{
+ struct ClcData* dat = ( struct ClcData* )GetWindowLongPtr( hWnd, 0 );
+ if ( !dat ) return 0;
+ cliPaintClc( hWnd, dat, hDC, rcPaint );
+ return NULL;
+}
+
+void CLCPaint::_FillQuickHash()
+{
+ int i;
+ for ( i=0;i < hi_LastItem;i++ )
+ HASH[i] = mod_CalcHash( HASHTEXT[i] );
+}
+
+void CLCPaint::_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 );
+}
+
+int CLCPaint::_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;
+}
+
+int CLCPaint::_GetGeneralisedStatus()
+{
+ int status = ID_STATUS_OFFLINE;
+ int statusOnlineness = 0;
+
+ for ( int i=0; i < pcli->hClcProtoCount; i++ )
+ {
+ int thisStatus = pcli->clcProto[i].dwStatus;
+ if ( thisStatus == ID_STATUS_INVISIBLE )
+ return ID_STATUS_INVISIBLE;
+
+ int thisOnlineness = _GetStatusOnlineness( thisStatus );
+ if ( thisOnlineness > statusOnlineness )
+ {
+ status = thisStatus;
+ statusOnlineness = thisOnlineness;
+ }
+ }
+ return status;
+}
+
+int CLCPaint::_GetRealStatus( struct ClcContact * pContact, int nStatus )
+{
+ if ( !pContact->proto )
+ return nStatus;
+
+ for ( int i=0; i < pcli->hClcProtoCount; i++ )
+ {
+ if ( !lstrcmpA( pcli->clcProto[i].szProto, pContact->proto ))
+ return pcli->clcProto[i].dwStatus;
+ }
+ return nStatus;
+}
+
+
+RECT CLCPaint::_GetRectangle( struct ClcData *dat, RECT *row_rc, RECT *free_row_rc, int *left_pos, int *right_pos, BOOL left, int real_width, int width, int height, int horizontal_space )
+{
+ RECT rc = *free_row_rc;
+ int width_tmp = width;
+ if ( left )
+ {
+ if ( dat->row_align_left_items_to_left )
+ width_tmp = real_width;
+
+ rc.left += ( width_tmp - real_width ) >> 1;
+ rc.right = rc.left + real_width;
+ rc.top += ( rc.bottom - rc.top - height ) >> 1;
+ rc.bottom = rc.top + height;
+ *left_pos += width_tmp + horizontal_space;
+ free_row_rc->left = row_rc->left + *left_pos;
+ }
+ else // if ( !left )
+ {
+ if ( dat->row_align_right_items_to_right )
+ width_tmp = real_width;
+
+ if ( width_tmp > rc.right - rc.left )
+ {
+ rc.left = rc.right + 1;
+ }
+ else
+ {
+ rc.left = max( rc.left + horizontal_space, rc.right - width_tmp ) + (( width_tmp - real_width ) >> 1 );
+ rc.right = min( rc.left + real_width, rc.right );
+ rc.top += max( 0, ( rc.bottom - rc.top - height ) >> 1 );
+ rc.bottom = min( rc.top + height, rc.bottom );
+
+ *right_pos += min( width_tmp + horizontal_space, free_row_rc->right - free_row_rc->left );
+ free_row_rc->right = row_rc->right - *right_pos;
+ }
+ }
+
+ return rc;
+}
+
+
+
+void CLCPaint::_DrawTextSmiley( HDC hdcMem, RECT * free_rc, SIZE * text_size, TCHAR *szText, int len, SortedList *plText, UINT uTextFormat, BOOL ResizeSizeSmiley )
+{
+ if ( szText == NULL )return;
+ uTextFormat &= ~DT_RIGHT;
+ if ( plText == NULL )
+ ske_DrawText( hdcMem, szText, len, free_rc, uTextFormat );
+ else
+ {
+ // Draw list
+ int i;
+ int pos_x = 0;
+ int row_height;
+ RECT tmp_rc = *free_rc;
+ if ( len == -1 ) len = (int)_tcslen( szText );
+ if ( uTextFormat & DT_RTLREADING )
+ i = plText->realCount - 1;
+ else
+ i=0;
+
+ // Get real height of the line
+ row_height = ske_DrawText( hdcMem, _T( "A" ), 1, &tmp_rc, DT_CALCRECT | uTextFormat );
+
+ // Just draw ellipsis
+ if ( free_rc->right <= free_rc->left )
+ {
+ if ( gl_TrimText ) ske_DrawText( hdcMem, _T( "..." ), 3, free_rc, uTextFormat & ~DT_END_ELLIPSIS );
+ }
+ else
+ {
+ // Draw text and smileys
+ for ( ; i < plText->realCount && i >= 0 && pos_x < text_size->cx && len > 0; i += ( uTextFormat & DT_RTLREADING ? -1 : 1 ))
+ {
+ ClcContactTextPiece *piece = ( ClcContactTextPiece * ) plText->items[i];
+ RECT text_rc = *free_rc;
+
+ if ( uTextFormat & DT_RTLREADING )
+ text_rc.right -= pos_x;
+ else
+ text_rc.left += pos_x;
+
+ if ( piece->type == TEXT_PIECE_TYPE_TEXT )
+ {
+ tmp_rc = text_rc;
+ tmp_rc.right += 50;
+ ske_DrawText( hdcMem, &szText[piece->start_pos], min( len, piece->len ), &tmp_rc, DT_CALCRECT | ( uTextFormat & ~DT_END_ELLIPSIS ));
+ pos_x += tmp_rc.right - tmp_rc.left + 2;
+
+ if ( uTextFormat & DT_RTLREADING )
+ text_rc.left = max( text_rc.left, text_rc.right - ( tmp_rc.right - tmp_rc.left ));
+
+ ske_DrawText( hdcMem, &szText[piece->start_pos], min( len, piece->len ), &text_rc, uTextFormat );
+ len -= piece->len;
+ }
+ else
+ {
+ float factor = 0;
+
+ if ( len < piece->len )
+ {
+ len = 0;
+ }
+ else
+ {
+ LONG fac_width, fac_height;
+ len -= piece->len;
+
+ if ( piece->smiley_height > row_height && ResizeSizeSmiley )
+ {
+ factor = row_height / ( float ) piece->smiley_height;
+ }
+ else
+ {
+ factor = 1;
+ }
+
+ fac_width = ( LONG )( piece->smiley_width * factor );
+ fac_height = ( LONG )( piece->smiley_height * factor );
+
+ if ( uTextFormat & DT_RTLREADING )
+ text_rc.left = max( text_rc.right - fac_width, text_rc.left );
+
+ if ( fac_width <= text_rc.right - text_rc.left )
+ {
+ text_rc.top += ( row_height - fac_height ) >> 1;
+
+ ske_DrawIconEx( hdcMem, text_rc.left, text_rc.top, piece->smiley,
+ fac_width, fac_height, 0, NULL, DI_NORMAL|(( factor < 1 )?128:0 )); //TO DO enchance drawing quality
+ }
+ else
+ {
+ ske_DrawText( hdcMem, _T( "..." ), 3, &text_rc, uTextFormat );
+ }
+
+ pos_x += fac_width;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void CLCPaint::_AddParameter( MODERNMASK * mpModernMask, MASKPARAM * lpParam )
+{
+ mpModernMask->pl_Params = ( MASKPARAM * )realloc( mpModernMask->pl_Params, ( mpModernMask->dwParamCnt+1 )*sizeof( MASKPARAM ));
+ memmove( &( mpModernMask->pl_Params[mpModernMask->dwParamCnt] ), lpParam, sizeof( MASKPARAM ));
+ mpModernMask->dwParamCnt++;
+ memset( lpParam, 0, sizeof( MASKPARAM ));
+}
+
+void CLCPaint::_FillParam( MASKPARAM * lpParam, DWORD dwParamHash, const char* const szValue, DWORD dwValueHash )
+{
+ lpParam->bMaskParamFlag = MPF_EQUAL|MPF_HASHED;
+ lpParam->dwId = dwParamHash;
+ if ( !dwValueHash && szValue && szValue[0] ) lpParam->dwValueHash = mod_CalcHash( szValue );
+ else lpParam->dwValueHash = dwValueHash;
+ if ( szValue ) lpParam->szValue = strdupn( szValue, strlen( szValue ));
+ else lpParam->szValue = NULL;
+}
+
+void CLCPaint::_AddParamShort( MODERNMASK * mpModernMask, DWORD dwParamIndex, DWORD dwValueIndex )
+{
+ AddParam( mpModernMask, HASH[dwParamIndex], HASHTEXT[dwValueIndex], HASH[dwValueIndex] );
+}
+
+
+MODERNMASK * CLCPaint::_GetCLCContactRowBackModernMask( struct ClcGroup * group, struct ClcContact * Drawing, int indent, int index, BOOL selected, BOOL hottrack, struct ClcData * dat )
+{
+ MODERNMASK * mpModernMask = NULL;
+ char buf[BUF2SIZE] = {0};
+ mpModernMask = ( MODERNMASK* )mir_calloc( sizeof( MODERNMASK ));
+
+ _AddParamShort( mpModernMask, hi_Module, hi_CL );
+ _AddParamShort( mpModernMask, hi_ID, hi_Row );
+ switch ( Drawing->type )
+ {
+ case CLCIT_GROUP:
+ {
+ _AddParamShort( mpModernMask, hi_Type, hi_Group );
+ _AddParamShort( mpModernMask, hi_Open, ( Drawing && Drawing->group && Drawing->group->expanded )?hi_True:hi_False );
+ _AddParamShort( mpModernMask, hi_IsEmpty, ( Drawing->group->cl.count == 0 )?hi_True:hi_False );
+ }
+ break;
+ case CLCIT_CONTACT:
+ {
+ struct ClcContact * mCont = Drawing;
+ if ( Drawing->isSubcontact )
+ {
+ _AddParamShort( mpModernMask, hi_Type, hi_SubContact );
+ if ( Drawing->isSubcontact == 1 && Drawing->subcontacts->SubAllocated == 1 )
+ _AddParamShort( mpModernMask, hi_SubPos, hi_First_Single );
+ else if ( Drawing->isSubcontact == 1 )
+ _AddParamShort( mpModernMask, hi_SubPos, hi_First );
+ else if ( Drawing->isSubcontact == Drawing->subcontacts->SubAllocated )
+ _AddParamShort( mpModernMask, hi_SubPos, hi_Last );
+ else
+ _AddParamShort( mpModernMask, hi_SubPos, hi_Middle );
+ mCont = Drawing->subcontacts;
+ }
+ else if ( Drawing->SubAllocated )
+ {
+ _AddParamShort( mpModernMask, hi_Type, hi_MetaContact );
+ _AddParamShort( mpModernMask, hi_Open, ( Drawing->SubExpanded )?hi_True:hi_False );
+ }
+ else
+ _AddParamShort( mpModernMask, hi_Type, hi_Contact );
+ AddParam( mpModernMask, HASH[hi_Protocol], Drawing->proto, 0 );
+ _AddParamShort( mpModernMask, hi_RootGroup, ( group && group->parent == NULL )?hi_True:hi_False );
+ switch( GetContactCachedStatus( Drawing->hContact ))
+ {
+ // case ID_STATUS_CONNECTING: AppendChar( buf, BUFSIZE, "CONNECTING" ); break;
+ case ID_STATUS_ONLINE: _AddParamShort( mpModernMask, hi_Status, hi_ONLINE ); break;
+ case ID_STATUS_AWAY: _AddParamShort( mpModernMask, hi_Status, hi_AWAY ); break;
+ case ID_STATUS_DND: _AddParamShort( mpModernMask, hi_Status, hi_DND ); break;
+ case ID_STATUS_NA: _AddParamShort( mpModernMask, hi_Status, hi_NA ); break;
+ case ID_STATUS_OCCUPIED: _AddParamShort( mpModernMask, hi_Status, hi_OCCUPIED ); break;
+ case ID_STATUS_FREECHAT: _AddParamShort( mpModernMask, hi_Status, hi_FREECHAT ); break;
+ case ID_STATUS_INVISIBLE: _AddParamShort( mpModernMask, hi_Status, hi_INVISIBLE ); break;
+ case ID_STATUS_OUTTOLUNCH: _AddParamShort( mpModernMask, hi_Status, hi_OUTTOLUNCH );break;
+ case ID_STATUS_ONTHEPHONE: _AddParamShort( mpModernMask, hi_Status, hi_ONTHEPHONE );break;
+ case ID_STATUS_IDLE: _AddParamShort( mpModernMask, hi_Status, hi_IDLE ); break;
+ default: _AddParamShort( mpModernMask, hi_Status, hi_OFFLINE );
+ }
+ _AddParamShort( mpModernMask, hi_HasAvatar, ( dat->avatars_show && Drawing->avatar_data != NULL )?hi_True:hi_False );
+ _AddParamShort( mpModernMask, hi_Rate, hi_None + Drawing->bContactRate );
+ break;
+ }
+ case CLCIT_DIVIDER:
+ {
+ _AddParamShort( mpModernMask, hi_Type, hi_Divider );
+ }
+ break;
+ case CLCIT_INFO:
+ {
+ _AddParamShort( mpModernMask, hi_Type, hi_Info );
+ }
+ break;
+ }
+ if ( group->scanIndex == 0 && group->cl.count == 1 )
+ _AddParamShort( mpModernMask, hi_GroupPos, hi_First_Single );
+ else if ( group->scanIndex == 0 )
+ _AddParamShort( mpModernMask, hi_GroupPos, hi_First );
+ else if ( group->scanIndex+1 == group->cl.count )
+ _AddParamShort( mpModernMask, hi_GroupPos, hi_Last );
+ else
+ _AddParamShort( mpModernMask, hi_GroupPos, hi_Mid );
+
+ _AddParamShort( mpModernMask, hi_Selected, ( selected )?hi_True:hi_False );
+ _AddParamShort( mpModernMask, hi_Hot, ( hottrack )?hi_True:hi_False );
+ _AddParamShort( mpModernMask, hi_Odd, ( index&1 )?hi_True:hi_False );
+
+ _itoa( indent, buf, BUF2SIZE );
+ AddParam( mpModernMask, HASH[hi_Indent], buf, 0 );
+ _itoa( index, buf, BUF2SIZE );
+ AddParam( mpModernMask, HASH[hi_Index], buf, 0 );
+ {
+ TCHAR * b2 = mir_tstrdup( Drawing->szText );
+ int i, m;
+ m = lstrlen( b2 );
+ for ( i=0; i < m;i++ )
+ if ( b2[i] == _T( ',' )) b2[i] = _T( '.' );
+ {
+ char* b3 = mir_utf8encodeT( b2 );
+ AddParam( mpModernMask, HASH[hi_Name], b3, 0 );
+ mir_free( b3 );
+ }
+
+ mir_free( b2 );
+ }
+ if ( group->parent )
+ {
+ TCHAR * b2 = mir_tstrdup( group->parent->cl.items[0]->szText );
+ int i, m;
+ m = lstrlen( b2 );
+ for ( i=0; i < m;i++ )
+ if ( b2[i] == _T( ',' )) b2[i] = _T( '.' );
+ {
+ char * b3 = mir_utf8encodeT( b2 );
+ AddParam( mpModernMask, HASH[hi_Group], b3, 0 );
+ mir_free( b3 );
+ }
+
+ mir_free( b2 );
+ }
+ return mpModernMask;
+}
+
+
+void CLCPaint::_RTLRect( RECT *rect, int width, int offset )
+{
+ int left, right;
+ if ( !rect ) return;
+ left = ( width )-rect->right;
+ right = ( width )-rect->left;
+ rect->left = left;//-offset;
+ rect->right = right;//-offset;
+ return;
+}
+
+void CLCPaint::_PaintRowItemsEx( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT row_rc, RECT free_row_rc, int left_pos, int right_pos, int selected, int hottrack, RECT *rcPaint )
+{
+ int i=0;
+ int dx = free_row_rc.left;
+ int dy = row_rc.top+dat->row_border;
+ int dg = 0;
+
+
+ // Let calc placeholder
+ int minheight = dat->row_min_heigh;
+ int mode2 = -1;
+ COLORREF colourFg = RGB( 0, 0, 0 );
+ BOOL InClistWindow = ( dat->hWnd == pcli->hwndContactTree );
+ PDNCE pdnce = NULL;
+ int height = RowHeight_CalcRowHeight( dat, hwnd, Drawing, -1 );
+
+ // TO DO DEPRECATE OLD ROW LAYOUT
+
+ if ( Drawing->type == CLCIT_CONTACT )
+ pdnce = ( PDNCE )pcli->pfnGetCacheEntry( Drawing->hContact );
+
+ if ( Drawing->type == CLCIT_GROUP &&
+ Drawing->group->parent->groupId == 0 &&
+ Drawing->group->parent->cl.items[0] != Drawing )
+ {
+ dg = dat->row_before_group_space;
+ free_row_rc.top += dg;
+ height -= dg;
+ }
+ if ( !InClistWindow || !gl_RowRoot || Drawing->type == CLCIT_GROUP )
+ {
+ // to do paint simple
+ RECT fr_rc = free_row_rc;
+
+ //1 draw icon
+ if ( !( Drawing->type == CLCIT_GROUP && InClistWindow && dat->row_hide_group_icon ))
+ {
+ int iImage = -1;
+ // Get image
+ if ( Drawing->type == CLCIT_GROUP )
+ {
+ iImage = Drawing->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT )
+ iImage = Drawing->iImage;
+ if ( iImage != -1 )
+ {
+ COLORREF colourFg;
+ int mode;
+ RECT p_rect = {0};
+ p_rect.top = fr_rc.top+(( fr_rc.bottom-fr_rc.top-ICON_HEIGHT )>>1 );
+ p_rect.left = fr_rc.left;
+ p_rect.right = p_rect.left+ICON_HEIGHT;
+ p_rect.bottom = p_rect.top+ICON_HEIGHT;
+ // Store pos
+ if ( dat->text_rtl != 0 ) _RTLRect( &p_rect, free_row_rc.right, dx );
+ Drawing->pos_icon = p_rect;
+ if ( hottrack )
+ {
+ colourFg = dat->hotTextColour;
+ mode = ILD_NORMAL;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
+ {
+ colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
+ mode = ILD_BLEND50;
+ }
+ else
+ {
+ colourFg = dat->selBkColour;
+ mode = ILD_NORMAL;
+ }
+
+ if ( Drawing->type == CLCIT_CONTACT && dat->showIdle && ( Drawing->flags&CONTACTF_IDLE ) &&
+ _GetRealStatus( Drawing, ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE )
+ {
+ mode = ILD_SELECTED;
+ }
+ _DrawStatusIcon( Drawing, dat, iImage, hdcMem, p_rect.left, p_rect.top, 0, 0, CLR_NONE, colourFg, mode );
+
+ }
+ fr_rc.left += ICON_HEIGHT+2;
+ }
+ //2 draw extra
+ {
+ RECT p_rect = {0};
+ p_rect.top = fr_rc.top+(( fr_rc.bottom-fr_rc.top-ICON_HEIGHT )>>1 );
+ //p_rect.left = fr_rc.left;
+ //p_rect.right = p_rect.left+ICON_HEIGHT;
+ p_rect.bottom = p_rect.top+ICON_HEIGHT;
+
+ if (( Drawing->type == CLCIT_GROUP || Drawing->type == CLCIT_CONTACT || Drawing->type == CLCIT_INFO )
+ && dat->extraColumnsCount > 0 && ( !InClistWindow || Drawing->type == CLCIT_CONTACT ))
+ {
+ int BlendedInActiveState = dat->dbbBlendInActiveState;
+ int BlendValue = dat->dbbBlend25 ? ILD_BLEND25 : ILD_BLEND50;
+ int iImage;
+ int count = 0;
+ RECT rc;
+ int x = 0;
+ for ( iImage = dat->extraColumnsCount-1; iImage >= 0 ; iImage-- )
+ {
+ COLORREF colourFg = dat->selBkColour;
+ int mode = BlendedInActiveState?BlendValue:ILD_NORMAL;
+ if ( Drawing->iExtraImage[iImage] == 0xFF && Drawing->iWideExtraImage[iImage] == 0xFFFF )
+ {
+ {
+ x += ( x>0 )?dat->extraColumnSpacing:ICON_HEIGHT;
+ SetRect( &rc, fr_rc.right-x, p_rect.top, fr_rc.right-x+ICON_HEIGHT, p_rect.bottom );
+ if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, 0 );
+ Drawing->pos_extra[iImage] = rc;
+ count++;
+ }
+ continue;
+ }
+
+ if ( selected ) mode = BlendedInActiveState?ILD_NORMAL:ILD_SELECTED;
+ else if ( hottrack )
+ {
+ mode = BlendedInActiveState?ILD_NORMAL:ILD_FOCUS;
+ colourFg = dat->hotTextColour;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
+ {
+ colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
+ mode = BlendValue;
+ }
+
+ x += ( x>0 )?dat->extraColumnSpacing:ICON_HEIGHT;
+ SetRect( &rc, fr_rc.right-x, p_rect.top, fr_rc.right-x+ICON_HEIGHT, p_rect.bottom );
+ if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, dx );
+ Drawing->pos_extra[iImage] = rc;
+ Drawing->pos_extra[iImage] = rc;
+ if ( Drawing->iExtraImage[iImage] != 0xFF )
+ ske_ImageList_DrawEx( dat->himlExtraColumns, Drawing->iExtraImage[iImage], hdcMem,
+ rc.left, rc.top, 0, 0, CLR_NONE, colourFg, mode );
+ else if ( Drawing->iWideExtraImage[iImage] != 0xFFFF )
+ ske_ImageList_DrawEx( dat->himlWideExtraColumns, Drawing->iWideExtraImage[iImage], hdcMem,
+ rc.left, rc.top, 0, 0, CLR_NONE, colourFg, mode );
+
+ }
+ fr_rc.right -= x;
+ }
+ }
+ //3 draw text
+ {
+ SIZE text_size = {0};
+ char * szCounts = NULL;
+ RECT text_rect = fr_rc;
+ RECT counts_rc = {0};
+ UINT uTextFormat = DT_LEFT|DT_VCENTER|( gl_TrimText?DT_END_ELLIPSIS:0 )|DT_SINGLELINE;
+ uTextFormat |= dat->text_rtl?DT_RTLREADING:0;
+ // Select font
+ ChangeToFont( hdcMem, dat, GetBasicFontID( Drawing ), NULL );
+
+ // Get text size
+ GetTextSize( &text_size, hdcMem, fr_rc, Drawing->szText, Drawing->ssText.plText, uTextFormat,
+ dat->text_resize_smileys ? 0 : Drawing->ssText.iMaxSmileyHeight );
+ // counters
+ if ( Drawing->type == CLCIT_GROUP && InClistWindow )
+ {
+ RECT nameRect = fr_rc;
+ RECT countRect = {0};
+ RECT count_rc = {0};
+ SIZE count_size = {0};
+ int space_width = 0;
+ char * szCounts = pcli->pfnGetGroupCountsText( dat, Drawing );
+ // Has to draw the count?
+ if ( szCounts && strlen( szCounts )>0 )
+ {
+ // calc width and height
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ ske_DrawText( hdcMem, _T( " " ), 1, &count_rc, DT_CALCRECT | DT_NOPREFIX );
+ count_size.cx = count_rc.right-count_rc.left;
+ space_width = count_size.cx;
+ count_rc.right = 0;
+ count_rc.left = 0;
+ ske_DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &count_rc, DT_CALCRECT );
+ count_size.cx += count_rc.right-count_rc.left;
+ count_size.cy = count_rc.bottom-count_rc.top;
+ }
+ // modify text rect
+ //if ( !RTL )
+ {
+ SIZE text_size = {0};
+ int wid = fr_rc.right-fr_rc.left;
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPS:FONTID_CLOSEDGROUPS, NULL );
+ GetTextSize( &text_size, hdcMem, fr_rc, Drawing->szText, Drawing->ssText.plText, 0, dat->text_resize_smileys ? 0 : Drawing->ssText.iMaxSmileyHeight );
+
+ if ( wid-count_size.cx > text_size.cx )
+ {
+
+ if ( dat->row_align_group_mode != 2 ) //center or left
+ {
+ int x = ( dat->row_align_group_mode == 1 )?( wid-( text_size.cx+count_size.cx ))>>1:0;
+ nameRect.left += x;
+ nameRect.right = nameRect.left+text_size.cx;
+ countRect.left = nameRect.right+space_width;
+ countRect.right = countRect.left+count_size.cx-space_width;
+ }
+ else
+ {
+ countRect.right = nameRect.right;
+ countRect.left = countRect.right-(( count_size.cx>0 )?( count_size.cx-space_width ):0 );
+ nameRect.right = countRect.left-(( count_size.cx>0 )?space_width:0 );
+ nameRect.left = nameRect.right-text_size.cx;
+ }
+
+ }
+
+ else
+ {
+ countRect.right = nameRect.right;
+ nameRect.right -= count_size.cx;
+ countRect.left = nameRect.right+space_width;
+ }
+ countRect.bottom = nameRect.bottom;
+ countRect.top = nameRect.top;
+ }
+
+
+
+ //if ( !( szCounts && strlen( szCounts )>0 ))
+ //uTextFormat |= ( dat->row_align_group_mode == 2 )?DT_RIGHT:( dat->row_align_group_mode == 1 )?DT_CENTER:DT_LEFT;
+
+ uTextFormat |= DT_VCENTER;
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPS:FONTID_CLOSEDGROUPS, NULL );
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ if ( dat->text_rtl != 0 ) _RTLRect( &nameRect, free_row_rc.right, dx );
+ _DrawTextSmiley( hdcMem, &nameRect, &text_size, Drawing->szText, lstrlen( Drawing->szText ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ if ( selected && dat->szQuickSearch[0] != '\0' )
+ {
+ SetTextColor( hdcMem, dat->quickSearchColour );
+ _DrawTextSmiley( hdcMem, &nameRect, &text_size, Drawing->szText, lstrlen( dat->szQuickSearch ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ }
+ if ( szCounts && strlen( szCounts )>0 )
+ {
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ if ( dat->text_rtl != 0 ) _RTLRect( &countRect, free_row_rc.right, dx );
+ ske_DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &countRect, uTextFormat );
+ }
+ {
+ RECT rc = fr_rc;
+ if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, dx );
+ Drawing->pos_rename_rect = rc;
+ }
+ Drawing->pos_label = nameRect;
+ return;
+ }
+ else if ( Drawing->type == CLCIT_GROUP )
+ {
+
+ szCounts = pcli->pfnGetGroupCountsText( dat, Drawing );
+ // Has to draw the count?
+ if ( szCounts && szCounts[0] )
+ {
+ RECT space_rc = fr_rc;
+
+ int text_width = 0;
+ SIZE space_size = {0};
+ SIZE counts_size = {0};
+ // Get widths
+ counts_rc = fr_rc;
+ DrawText( hdcMem, _T( " " ), 1, &space_rc, DT_CALCRECT | DT_NOPREFIX );
+
+ space_size.cx = space_rc.right - space_rc.left;
+ space_size.cy = min( space_rc.bottom - space_rc.top, fr_rc.bottom-fr_rc.top );
+
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &counts_rc, DT_CALCRECT );
+
+ counts_size.cx = counts_rc.right - counts_rc.left;
+ counts_size.cy = min( counts_rc.bottom - counts_rc.top, fr_rc.bottom-fr_rc.top );
+
+ text_width = fr_rc.right - fr_rc.left - space_size.cx - counts_size.cx;
+
+ if ( text_width > 4 )
+ {
+ text_size.cx = min( text_width, text_size.cx );
+ text_width = text_size.cx + space_size.cx + counts_size.cx;
+ }
+ else
+ {
+ text_width = text_size.cx;
+ space_size.cx = 0;
+ counts_size.cx = 0;
+ }
+ text_rect.right = text_rect.left+text_size.cx;
+ counts_rc = text_rect;
+ counts_rc.left = text_rect.right+space_size.cx;
+ counts_rc.right = counts_rc.left+counts_size.cx;
+ }
+ }
+ ChangeToFont( hdcMem, dat, GetBasicFontID( Drawing ), NULL );
+
+ // Set color
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ if ( dat->text_rtl != 0 ) _RTLRect( &text_rect, free_row_rc.right, dx );
+ _DrawTextSmiley( hdcMem, &text_rect, &text_size, Drawing->szText, lstrlen( Drawing->szText ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ if ( selected && dat->szQuickSearch[0] != '\0' )
+ {
+ SetTextColor( hdcMem, dat->quickSearchColour );
+ _DrawTextSmiley( hdcMem, &text_rect, &text_size, Drawing->szText, lstrlen( dat->szQuickSearch ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ }
+ if ( Drawing->type == CLCIT_GROUP && szCounts && szCounts[0] && counts_rc.right-counts_rc.left>0 )
+ {
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ if ( dat->text_rtl != 0 ) _RTLRect( &counts_rc, free_row_rc.right, dx );
+ if ( InClistWindow && g_CluiData.fLayered )
+ ske_DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &counts_rc, uTextFormat );
+ else
+ //88
+ ske_DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &counts_rc, uTextFormat );
+ if ( dat->text_rtl == 0 )
+ text_rect.right = counts_rc.right;
+ else
+ text_rect.left = counts_rc.left;
+ }
+ Drawing->pos_label = text_rect;
+ {
+ RECT rc = fr_rc;
+ if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, dx );
+ Drawing->pos_rename_rect = rc;
+ }
+
+ if (( !InClistWindow || !g_CluiData.fLayered ) && (( Drawing->type == CLCIT_DIVIDER ) || ( Drawing->type == CLCIT_GROUP && dat->exStyle&CLS_EX_LINEWITHGROUPS )))
+ {
+ //???
+ RECT rc = fr_rc;
+ if ( dat->text_rtl != 0 )
+ {
+ rc.left = Drawing->pos_rename_rect.left;
+ rc.right = text_rect.left-3;
+ }
+ else
+ rc.left = text_rect.right+3;
+ if ( rc.right-rc.left>4 )
+ {
+ rc.top += (( rc.bottom-rc.top )>>1 )-1;
+ rc.bottom = rc.top+2;
+ DrawEdge( hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT );
+ ske_SetRectOpaque( hdcMem, &rc );
+ }
+ }
+
+ }
+ return;
+ }
+ minheight = max( minheight, height );
+ dy += ( minheight>height )?(( minheight-height )>>1 ):0;
+ // Call Placement
+ cppCalculateRowItemsPos( gl_RowRoot, free_row_rc.right-free_row_rc.left );
+ // Now paint
+ while (( gl_RowTabAccess[i] != NULL || ( i < 2 && Drawing->type == CLCIT_GROUP )) && !( i >= 2 && Drawing->type == CLCIT_GROUP ))
+ {
+
+ if ( gl_RowTabAccess[i]->r.right-gl_RowTabAccess[i]->r.left>0
+ && gl_RowTabAccess[i]->r.bottom-gl_RowTabAccess[i]->r.top>0 )
+ {
+ RECT p_rect = gl_RowTabAccess[i]->r;
+ OffsetRect( &p_rect, dx, dy );
+ if ( dat->text_rtl != 0 && gl_RowTabAccess[i]->type != TC_EXTRA /*each extra icon modified separately*/ ) _RTLRect( &p_rect, free_row_rc.right, 0 );
+ switch ( gl_RowTabAccess[i]->type )
+ {
+ case TC_TEXT1:
+ {
+ //paint text 1
+ SIZE text_size;
+ UINT uTextFormat = ( dat->text_rtl ? DT_RTLREADING : 0 ) ;
+ text_size.cx = p_rect.right-p_rect.left;
+ text_size.cy = p_rect.bottom-p_rect.top;
+ ChangeToFont( hdcMem, dat, GetBasicFontID( Drawing ), NULL );
+
+ uTextFormat |= ( gl_RowTabAccess[i]->valign == TC_VCENTER )?DT_VCENTER:( gl_RowTabAccess[i]->valign == TC_BOTTOM )?DT_BOTTOM:0;
+ uTextFormat |= ( gl_RowTabAccess[i]->halign == TC_HCENTER )?DT_CENTER:( gl_RowTabAccess[i]->halign == TC_RIGHT )?DT_RIGHT:0;
+
+ uTextFormat = uTextFormat | ( gl_TrimText?DT_END_ELLIPSIS:0 )|DT_SINGLELINE;
+ if ( Drawing->type == CLCIT_CONTACT )
+ {
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ _DrawTextSmiley( hdcMem, &p_rect, &text_size, Drawing->szText, lstrlen( Drawing->szText ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ if ( selected && dat->szQuickSearch[0] != '\0' )
+ {
+ SetTextColor( hdcMem, dat->quickSearchColour );
+ _DrawTextSmiley( hdcMem, &p_rect, &text_size, Drawing->szText, lstrlen( dat->szQuickSearch ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ }
+ Drawing->pos_rename_rect = p_rect;
+ {
+ SIZE size;
+ GetTextSize( &size, hdcMem, p_rect, Drawing->szText, Drawing->ssText.plText, 0, dat->text_resize_smileys ? 0 : Drawing->ssText.iMaxSmileyHeight );
+ Drawing->pos_label = p_rect;
+ Drawing->pos_label.right = min( Drawing->pos_label.right, Drawing->pos_label.left+size.cx );
+ }
+
+ }
+ else if ( Drawing->type == CLCIT_GROUP )
+ {
+ RECT nameRect = p_rect;
+ RECT countRect = {0};
+ RECT count_rc = {0};
+ SIZE count_size = {0};
+ int space_width = 0;
+ char * szCounts = pcli->pfnGetGroupCountsText( dat, Drawing );
+ // Has to draw the count?
+ if ( szCounts && strlen( szCounts )>0 )
+ {
+
+
+ // calc width and height
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ ske_DrawText( hdcMem, _T( " " ), 1, &count_rc, DT_CALCRECT | DT_NOPREFIX );
+ count_size.cx = count_rc.right-count_rc.left;
+ space_width = count_size.cx;
+ count_rc.right = 0;
+ count_rc.left = 0;
+ ske_DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &count_rc, DT_CALCRECT );
+ count_size.cx += count_rc.right-count_rc.left;
+ count_size.cy = count_rc.bottom-count_rc.top;
+ }
+ // modify text rect
+ //if ( !RTL )
+ {
+ SIZE text_size = {0};
+ int wid = p_rect.right-p_rect.left;
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPS:FONTID_CLOSEDGROUPS, NULL );
+ GetTextSize( &text_size, hdcMem, p_rect, Drawing->szText, Drawing->ssText.plText, 0, dat->text_resize_smileys ? 0 : Drawing->ssText.iMaxSmileyHeight );
+
+ if ( wid-count_size.cx > text_size.cx )
+ {
+
+ if ( dat->row_align_group_mode != 2 ) //center or left
+ {
+ int x = ( dat->row_align_group_mode == 1 )?( wid-( text_size.cx+count_size.cx ))>>1:0;
+ nameRect.left += x;
+ nameRect.right = nameRect.left+text_size.cx;
+ countRect.left = nameRect.right+space_width;
+ countRect.right = countRect.left+count_size.cx-space_width;
+ }
+ else
+ {
+ countRect.right = nameRect.right;
+ countRect.left = countRect.right-(( count_size.cx>0 )?( count_size.cx-space_width ):0 );
+ nameRect.right = countRect.left-(( count_size.cx>0 )?space_width:0 );
+ nameRect.left = nameRect.right-text_size.cx;
+ }
+
+ }
+
+ else
+ {
+ countRect.right = nameRect.right;
+ nameRect.right -= count_size.cx;
+ countRect.left = nameRect.right+space_width;
+ }
+ countRect.bottom = nameRect.bottom;
+ countRect.top = nameRect.top;
+ }
+
+
+
+ //if ( !( szCounts && strlen( szCounts )>0 ))
+ //uTextFormat |= ( dat->row_align_group_mode == 2 )?DT_RIGHT:( dat->row_align_group_mode == 1 )?DT_CENTER:DT_LEFT;
+
+ uTextFormat |= DT_VCENTER;
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPS:FONTID_CLOSEDGROUPS, NULL );
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ _DrawTextSmiley( hdcMem, &nameRect, &text_size, Drawing->szText, lstrlen( Drawing->szText ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ if ( selected && dat->szQuickSearch[0] != '\0' )
+ {
+ SetTextColor( hdcMem, dat->quickSearchColour );
+ _DrawTextSmiley( hdcMem, &nameRect, &text_size, Drawing->szText, lstrlen( dat->szQuickSearch ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ }
+ if ( szCounts && strlen( szCounts )>0 )
+ {
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ ske_DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &countRect, uTextFormat );
+ }
+ Drawing->pos_rename_rect = p_rect;
+ Drawing->pos_label = nameRect;
+ }
+ break;
+ }
+ case TC_TEXT2:
+ {
+ // paint text 2
+ //
+ // Select font
+ SIZE text_size;
+ UINT uTextFormat = ( dat->text_rtl ? DT_RTLREADING : 0 ) ;
+ {
+ if ( dat->second_line_show && dat->second_line_type == TEXT_CONTACT_TIME && pdnce->hTimeZone )
+ {
+ // Get contact time
+ TCHAR buf[70] = _T("");
+ mir_free_and_nil( pdnce->szSecondLineText );
+
+ tmi.printDateTime(pdnce->hTimeZone, _T("t"), buf, SIZEOF(buf), 0);
+ pdnce->szSecondLineText = mir_tstrdup( buf );
+ }
+ }
+ uTextFormat |= ( gl_RowTabAccess[i]->valign == TC_VCENTER )?DT_VCENTER:( gl_RowTabAccess[i]->valign == TC_BOTTOM )?DT_BOTTOM:0;
+ uTextFormat |= ( gl_RowTabAccess[i]->halign == TC_HCENTER )?DT_CENTER:( gl_RowTabAccess[i]->halign == TC_RIGHT )?DT_RIGHT:0;
+
+ text_size.cx = p_rect.right-p_rect.left;
+ text_size.cy = p_rect.bottom-p_rect.top;
+
+ ChangeToFont( hdcMem, dat, FONTID_SECONDLINE, NULL );
+ uTextFormat = uTextFormat | ( gl_TrimText?DT_END_ELLIPSIS:0 )|DT_SINGLELINE;
+ if ( Drawing->type == CLCIT_CONTACT )
+ _DrawTextSmiley( hdcMem, &p_rect, &text_size, pdnce->szSecondLineText, lstrlen( pdnce->szSecondLineText ), pdnce->ssSecondLine.plText, uTextFormat, dat->text_resize_smileys );
+ break;
+ }
+ case TC_TEXT3:
+ {
+ //paint text 3
+ // Select font
+ SIZE text_size;
+ UINT uTextFormat = ( dat->text_rtl ? DT_RTLREADING : 0 ) ;
+ {
+ if ( dat->third_line_show && dat->third_line_type == TEXT_CONTACT_TIME && pdnce->hTimeZone )
+ {
+ // Get contact time
+ TCHAR buf[70] = _T("");
+ mir_free( pdnce->szThirdLineText );
+
+ tmi.printDateTime(pdnce->hTimeZone, _T("t"), buf, SIZEOF(buf), 0);
+ pdnce->szThirdLineText = mir_tstrdup( buf );
+ }
+ }
+ uTextFormat |= ( gl_RowTabAccess[i]->valign == TC_VCENTER )?DT_VCENTER:( gl_RowTabAccess[i]->valign == TC_BOTTOM )?DT_BOTTOM:0;
+ uTextFormat |= ( gl_RowTabAccess[i]->halign == TC_HCENTER )?DT_CENTER:( gl_RowTabAccess[i]->halign == TC_RIGHT )?DT_RIGHT:0;
+
+ text_size.cx = p_rect.right-p_rect.left;
+ text_size.cy = p_rect.bottom-p_rect.top;
+
+ ChangeToFont( hdcMem, dat, FONTID_THIRDLINE, NULL );
+ uTextFormat = uTextFormat | ( gl_TrimText?DT_END_ELLIPSIS:0 )|DT_SINGLELINE;
+ if ( Drawing->type == CLCIT_CONTACT )
+ _DrawTextSmiley( hdcMem, &p_rect, &text_size, pdnce->szThirdLineText, lstrlen( pdnce->szThirdLineText ), pdnce->ssThirdLine.plText, uTextFormat, dat->text_resize_smileys );
+ break;
+ }
+ case TC_STATUS:
+ {
+
+ if (( Drawing->type == CLCIT_GROUP && !dat->row_hide_group_icon )
+ || ( Drawing->type == CLCIT_CONTACT && Drawing->iImage != -1
+ && !( dat->icon_hide_on_avatar && dat->avatars_show
+ && (( dat->use_avatar_service && Drawing->avatar_data != NULL ) ||
+ ( !dat->use_avatar_service && Drawing->avatar_pos != AVATAR_POS_DONT_HAVE )
+ )
+ && !Drawing->image_is_special )))
+ {
+ int iImage = -1;
+ // Get image
+ if ( Drawing->type == CLCIT_GROUP )
+ {
+ if ( !dat->row_hide_group_icon ) iImage = Drawing->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT;
+ else iImage = -1;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT )
+ iImage = Drawing->iImage;
+ if ( iImage != -1 )
+ {
+ COLORREF colourFg;
+ int mode;
+ // Store pos
+ Drawing->pos_icon = p_rect;
+ if ( hottrack )
+ {
+ colourFg = dat->hotTextColour;
+ mode = ILD_NORMAL;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
+ {
+ colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
+ mode = ILD_BLEND50;
+ }
+ else
+ {
+ colourFg = dat->selBkColour;
+ mode = ILD_NORMAL;
+ }
+
+ if ( Drawing->type == CLCIT_CONTACT && dat->showIdle && ( Drawing->flags&CONTACTF_IDLE ) &&
+ _GetRealStatus( Drawing, ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE )
+ {
+ mode = ILD_SELECTED;
+ }
+
+ _DrawStatusIcon( Drawing, dat, iImage, hdcMem, p_rect.left, p_rect.top, 0, 0, CLR_NONE, colourFg, mode );
+
+ }
+ }
+
+ break;
+ }
+ case TC_AVATAR:
+ {
+ BOOL hasAvatar = ( dat->use_avatar_service && Drawing->avatar_data != NULL ) || ( !dat->use_avatar_service && Drawing->avatar_pos != AVATAR_POS_DONT_HAVE );
+ BYTE blendmode = 255;
+ if ( hottrack )
+ blendmode = 255;
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
+ blendmode = 128;
+ if ( Drawing->type == CLCIT_CONTACT && dat->showIdle && ( Drawing->flags&CONTACTF_IDLE ) &&
+ _GetRealStatus( Drawing, ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE )
+ blendmode = 128;
+ if ( !hasAvatar ) //if no avatar then paint icon image
+ {
+ int iImage = Drawing->iImage;
+ if ( iImage != -1 )
+ {
+ COLORREF colourFg;
+ int mode;
+ // Store pos
+ Drawing->pos_icon = p_rect;
+ if ( hottrack )
+ {
+ colourFg = dat->hotTextColour;
+ mode = ILD_NORMAL;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
+ {
+ colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
+ mode = ILD_BLEND50;
+ }
+ else
+ {
+ colourFg = dat->selBkColour;
+ mode = ILD_NORMAL;
+ }
+
+ if ( Drawing->type == CLCIT_CONTACT && dat->showIdle && ( Drawing->flags&CONTACTF_IDLE ) &&
+ _GetRealStatus( Drawing, ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE )
+ {
+ mode = ILD_SELECTED;
+ }
+
+ _DrawStatusIcon( Drawing, dat, iImage, hdcMem, p_rect.left, p_rect.top, 0, 0, CLR_NONE, colourFg, mode );
+
+ }
+ }
+ else
+ {
+ HRGN rgn = NULL;
+ HRGN oldrgn;
+ int round_radius = 0;
+ int width = p_rect.right-p_rect.left;
+ int height = p_rect.bottom-p_rect.top;
+ // Store pos
+ Drawing->pos_avatar = p_rect;
+ oldrgn = CreateRectRgn( 0, 0, 0, 0 );
+ GetClipRgn( hdcMem, oldrgn );
+
+ // Round corners
+ if ( dat->avatars_round_corners )
+ {
+ if ( dat->avatars_use_custom_corner_size )
+ round_radius = dat->avatars_custom_corner_size;
+ else
+ round_radius = min( width, height ) / 5;
+ }
+ else
+ {
+ round_radius = 0;
+ }
+ if ( dat->avatars_draw_border )
+ {
+ HBRUSH hBrush = CreateSolidBrush( dat->avatars_border_color );
+ HBRUSH hOldBrush = ( HBRUSH )SelectObject( hdcMem, hBrush );
+ HRGN rgn2;
+ rgn = CreateRoundRectRgn( p_rect.left, p_rect.top, p_rect.right+1, p_rect.bottom+1, round_radius << 1, round_radius << 1 );
+ rgn2 = CreateRoundRectRgn( p_rect.left+1, p_rect.top+1, p_rect.right, p_rect.bottom, round_radius << 1, round_radius << 1 );
+ CombineRgn( rgn2, rgn, rgn2, RGN_DIFF );
+ // FrameRgn( hdcMem, rgn, hBrush, 1, 1 );
+ FillRgn( hdcMem, rgn2, hBrush );
+ ske_SetRgnOpaque( hdcMem, rgn2 );
+ SelectObject( hdcMem, hOldBrush );
+ DeleteObject( hBrush );
+ DeleteObject( rgn );
+ DeleteObject( rgn2 );
+ }
+ if ( dat->avatars_round_corners || dat->avatars_draw_border )
+ {
+ int k = dat->avatars_draw_border?1:0;
+ rgn = CreateRoundRectRgn( p_rect.left+k, p_rect.top+k, p_rect.right+1-k, p_rect.bottom+1-k, round_radius * 2, round_radius * 2 );
+ ExtSelectClipRgn( hdcMem, rgn, RGN_AND );
+ }
+
+ // Draw avatar
+ if ( dat->use_avatar_service )
+ /*if ( ServiceExists( MS_AV_BLENDDRAWAVATAR ))
+ {
+ AVATARDRAWREQUEST adr;
+
+ adr.cbSize = sizeof( AVATARDRAWREQUEST );
+ adr.hContact = Drawing->hContact;
+ adr.hTargetDC = hdcMem;
+ adr.rcDraw = p_rect;
+ adr.dwFlags = ( dat->avatars_draw_border ? AVDRQ_DRAWBORDER : 0 ) |
+ ( dat->avatars_round_corners ? AVDRQ_ROUNDEDCORNER : 0 ) |
+ AVDRQ_HIDEBORDERONTRANSPARENCY;
+ adr.clrBorder = dat->avatars_border_color;
+ adr.radius = round_radius;
+ adr.alpha = blendmode;
+
+ CallService( MS_AV_DRAWAVATAR, 0, ( LPARAM ) &adr );
+ }
+ else
+ */
+ {
+ int w = width;
+ int h = height;
+ if ( !g_CluiData.fGDIPlusFail ) //Use gdi+ engine
+ {
+ DrawAvatarImageWithGDIp( hdcMem, p_rect.left, p_rect.top, w, h, Drawing->avatar_data->hbmPic, 0, 0, Drawing->avatar_data->bmWidth, Drawing->avatar_data->bmHeight, Drawing->avatar_data->dwFlags, blendmode );
+ }
+ else
+ {
+ if ( !( Drawing->avatar_data->dwFlags&AVS_PREMULTIPLIED ))
+ {
+ HDC hdcTmp = CreateCompatibleDC( hdcMem );
+ RECT r = {0, 0, w, h};
+ HDC hdcTmp2 = CreateCompatibleDC( hdcMem );
+ HBITMAP bmo = ( HBITMAP )SelectObject( hdcTmp, Drawing->avatar_data->hbmPic );
+ HBITMAP b2 = ske_CreateDIB32( w, h );
+ HBITMAP bmo2 = ( HBITMAP )SelectObject( hdcTmp2, b2 );
+ SetStretchBltMode( hdcTmp, HALFTONE );
+ SetStretchBltMode( hdcTmp2, HALFTONE );
+ StretchBlt( hdcTmp2, 0, 0, w, h,
+ hdcTmp, 0, 0, Drawing->avatar_data->bmWidth, Drawing->avatar_data->bmHeight,
+ SRCCOPY );
+
+ ske_SetRectOpaque( hdcTmp2, &r );
+ BitBlt( hdcMem, p_rect.left, p_rect.top, w, h, hdcTmp2, 0, 0, SRCCOPY );
+ SelectObject( hdcTmp2, bmo2 );
+ SelectObject( hdcTmp, bmo );
+ mod_DeleteDC( hdcTmp );
+ mod_DeleteDC( hdcTmp2 );
+ DeleteObject( b2 );
+ }
+ else {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, blendmode, AC_SRC_ALPHA };
+ HDC hdcTempAv = CreateCompatibleDC( hdcMem );
+ HBITMAP hbmTempAvOld;
+ hbmTempAvOld = ( HBITMAP )SelectObject( hdcTempAv, Drawing->avatar_data->hbmPic );
+ ske_AlphaBlend( hdcMem, p_rect.left, p_rect.top, w, h, hdcTempAv, 0, 0, Drawing->avatar_data->bmWidth, Drawing->avatar_data->bmHeight, bf );
+ SelectObject( hdcTempAv, hbmTempAvOld );
+ mod_DeleteDC( hdcTempAv );
+ }
+ }
+ }
+ else
+ {
+ ImageArray_DrawImage( &dat->avatar_cache, Drawing->avatar_pos, hdcMem, p_rect.left, p_rect.top, 255 );
+ }
+ // Restore region
+ if ( dat->avatars_round_corners || dat->avatars_draw_border )
+ {
+ DeleteObject( rgn );
+ }
+ SelectClipRgn( hdcMem, oldrgn );
+ DeleteObject( oldrgn );
+
+
+ // Draw borders
+
+ //TODO fix overlays
+ // Draw overlay
+ if ( dat->avatars_draw_overlay && dat->avatars_maxheight_size >= ICON_HEIGHT + ( dat->avatars_draw_border ? 2 : 0 )
+ && GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE < MAX_REGS( g_pAvatarOverlayIcons ))
+ {
+ p_rect.top = p_rect.bottom - ICON_HEIGHT;
+ p_rect.left = p_rect.right - ICON_HEIGHT;
+
+ if ( dat->avatars_draw_border )
+ {
+ p_rect.top--;
+ p_rect.left--;
+ }
+
+ switch( dat->avatars_overlay_type )
+ {
+ case SETTING_AVATAR_OVERLAY_TYPE_NORMAL:
+ {
+ UINT a = blendmode;
+ a = ( a << 24 );
+ ske_ImageList_DrawEx( hAvatarOverlays, g_pAvatarOverlayIcons[GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE].listID,
+ hdcMem,
+ p_rect.left, p_rect.top, ICON_HEIGHT, ICON_HEIGHT,
+ CLR_NONE, CLR_NONE,
+ ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
+
+ //ske_DrawIconEx( hdcMem, p_rect.left, p_rect.top, g_pAvatarOverlayIcons[GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE].icon,
+ // ICON_HEIGHT, ICON_HEIGHT, 0, NULL, DI_NORMAL|a );
+ break;
+ }
+ case SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL:
+ {
+ int item;
+
+ item = ExtIconFromStatusMode( Drawing->hContact, Drawing->proto,
+ Drawing->proto == NULL ? ID_STATUS_OFFLINE : GetContactCachedStatus( Drawing->hContact ));
+ if ( item != -1 )
+ _DrawStatusIcon( Drawing, dat, item, hdcMem,
+ p_rect.left, p_rect.top, ICON_HEIGHT, ICON_HEIGHT,
+ CLR_NONE, CLR_NONE, ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
+ break;
+ }
+ case SETTING_AVATAR_OVERLAY_TYPE_CONTACT:
+ {
+ if ( Drawing->iImage != -1 )
+ _DrawStatusIcon( Drawing, dat, Drawing->iImage, hdcMem,
+ p_rect.left, p_rect.top, ICON_HEIGHT, ICON_HEIGHT,
+ CLR_NONE, CLR_NONE, ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
+ break;
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ case TC_EXTRA:
+ {
+
+ if ( Drawing->type == CLCIT_CONTACT &&
+ ( !Drawing->isSubcontact || dat->dbbMetaHideExtra == 0 && dat->extraColumnsCount > 0 ))
+ {
+ int BlendedInActiveState = dat->dbbBlendInActiveState;
+ int BlendValue = dat->dbbBlend25 ? ILD_BLEND25 : ILD_BLEND50;
+ int iImage;
+ int count = 0;
+ RECT rc;
+ int x = 0;
+ for ( iImage = 0; iImage < dat->extraColumnsCount ; iImage++ )
+ {
+ COLORREF colourFg = dat->selBkColour;
+ int mode = BlendedInActiveState?BlendValue:ILD_NORMAL;
+ if ( Drawing->iExtraImage[iImage] == 0xFF && Drawing->iWideExtraImage[iImage] == 0xFFFF )
+ {
+ if ( !dat->MetaIgnoreEmptyExtra )
+ {
+ SetRect( &rc, p_rect.left+x, p_rect.top, p_rect.left+x+ICON_HEIGHT, p_rect.bottom );
+ x += dat->extraColumnSpacing;
+ if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, 0 );
+ Drawing->pos_extra[iImage] = rc;
+ count++;
+ }
+ continue;
+ }
+
+ if ( selected ) mode = BlendedInActiveState?ILD_NORMAL:ILD_SELECTED;
+ else if ( hottrack )
+ {
+ mode = BlendedInActiveState?ILD_NORMAL:ILD_FOCUS;
+ colourFg = dat->hotTextColour;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
+ {
+ colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
+ mode = BlendValue;
+ }
+
+ SetRect( &rc, p_rect.left+x, p_rect.top, p_rect.left+x+ICON_HEIGHT, p_rect.bottom );
+ x += dat->extraColumnSpacing;
+ count++;
+ if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, 0 );
+ Drawing->pos_extra[iImage] = rc;
+ if ( Drawing->iExtraImage[iImage] != 0xFF )
+ ske_ImageList_DrawEx( dat->himlExtraColumns, Drawing->iExtraImage[iImage], hdcMem,
+ rc.left, rc.top, 0, 0, CLR_NONE, colourFg, mode );
+ else if ( Drawing->iWideExtraImage[iImage] != 0xFFFF )
+ ske_ImageList_DrawEx( dat->himlWideExtraColumns, Drawing->iWideExtraImage[iImage], hdcMem,
+ rc.left, rc.top, 0, 0, CLR_NONE, colourFg, mode );
+ }
+ }
+ break;
+ }
+ case TC_EXTRA1:
+ case TC_EXTRA2:
+ case TC_EXTRA3:
+ case TC_EXTRA4:
+ case TC_EXTRA5:
+ case TC_EXTRA6:
+ case TC_EXTRA7:
+ case TC_EXTRA8:
+ case TC_EXTRA9:
+ {
+ if ( Drawing->type == CLCIT_CONTACT &&
+ ( !Drawing->isSubcontact || dat->dbbMetaHideExtra == 0 && dat->extraColumnsCount > 0 ))
+ {
+ int eNum = gl_RowTabAccess[i]->type-TC_EXTRA1;
+ if ( eNum < dat->extraColumnsCount )
+ if ( Drawing->iExtraImage[eNum] != 0xFF || Drawing->iWideExtraImage[eNum] != 0xFFFF )
+ {
+ int mode = 0;
+ int BlendedInActiveState = dat->dbbBlendInActiveState;
+ int BlendValue = dat->dbbBlend25 ? ILD_BLEND25 : ILD_BLEND50;
+ if ( mode2 != -1 ) mode = mode2;
+ else
+ {
+ if ( selected ) mode = BlendedInActiveState?ILD_NORMAL:ILD_SELECTED;
+ else if ( hottrack )
+ {
+ mode = BlendedInActiveState?ILD_NORMAL:ILD_FOCUS;
+ colourFg = dat->hotTextColour;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
+ {
+ colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
+ mode = BlendValue;
+ }
+ mode2 = mode;
+ }
+ if ( dat->text_rtl != 0 ) _RTLRect( &p_rect, free_row_rc.right, 0 );
+ Drawing->pos_extra[eNum] = p_rect;
+ if ( Drawing->iExtraImage[eNum] != 0xFF )
+ ske_ImageList_DrawEx( dat->himlExtraColumns, Drawing->iExtraImage[eNum], hdcMem,
+ p_rect.left, p_rect.top, 0, 0, CLR_NONE, colourFg, mode );
+ else if ( Drawing->iWideExtraImage[eNum] != 0xFFFF )
+ ske_ImageList_DrawEx( dat->himlWideExtraColumns, Drawing->iWideExtraImage[eNum], hdcMem,
+ p_rect.left, p_rect.top, 0, 0, CLR_NONE, colourFg, mode );
+ }
+ }
+ }
+ case TC_TIME:
+ {
+ TCHAR szResult[80];
+
+ if ( !tmi.printDateTime(pdnce->hTimeZone, _T("t"), szResult, SIZEOF(szResult), 0))
+ {
+ // Select font
+ ChangeToFont( hdcMem, dat, FONTID_CONTACT_TIME, NULL );
+ ske_DrawText( hdcMem, szResult, lstrlen( szResult ), &p_rect, DT_NOPREFIX | DT_SINGLELINE|( dat->text_rtl ? DT_RTLREADING : 0 ));
+ }
+ break;
+ }
+ }
+ }
+ i++;
+ }
+ return;
+}
+
+
+
+
+void CLCPaint::_DrawStatusIcon( struct ClcContact * Drawing, struct ClcData *dat, int iImage, HDC hdcMem, int x, int y, int cx, int cy, DWORD colorbg, DWORD colorfg, int mode )
+{
+ if ( Drawing->type != CLCIT_CONTACT )
+ {
+ ske_ImageList_DrawEx( g_himlCListClc, LOWORD( iImage ), hdcMem,
+ x, y, cx, cy, colorbg, colorfg, mode );
+ }
+ else if ( Drawing->image_is_special )
+ {
+ ske_ImageList_DrawEx( g_himlCListClc, LOWORD( iImage ), hdcMem,
+ x, y, cx, cy, colorbg, colorfg, mode );
+ }
+ else if ( iImage != -1 && HIWORD( iImage ) && dat->drawOverlayedStatus )
+ {
+ int status = GetContactCachedStatus( Drawing->hContact );
+ if ( status < ID_STATUS_OFFLINE ) status = ID_STATUS_OFFLINE;
+ else if ( status>ID_STATUS_OUTTOLUNCH ) status = ID_STATUS_ONLINE;
+ ske_ImageList_DrawEx( g_himlCListClc, HIWORD( iImage ), hdcMem,
+ x, y, cx, cy, colorbg, colorfg, mode );
+ if ( dat->drawOverlayedStatus&2 ) //draw overlay
+ ske_ImageList_DrawEx( hAvatarOverlays, g_pStatusOverlayIcons[status-ID_STATUS_OFFLINE].listID, hdcMem,
+ x, y, cx, cy, colorbg, colorfg, mode );
+ }
+ else
+ {
+ ske_ImageList_DrawEx( g_himlCListClc, LOWORD( iImage ), hdcMem,
+ x, y, cx, cy, colorbg, colorfg, mode );
+ }
+}
+
+BOOL CLCPaint::_DrawNonEnginedBackground( HWND hwnd, HDC hdcMem, RECT * rcPaint, RECT clRect, struct ClcData * dat )
+{
+ if ( dat->hBmpBackground )
+ {
+ BITMAP bmp;
+ HBITMAP oldbm;
+ 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 );
+ oldbm = ( HBITMAP )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;
+ if ( dat->backgroundBmpUse&CLBF_TILEVTOROWHEIGHT )
+ {
+ desth = dat->row_min_heigh;
+ }
+
+ }
+ 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;
+ if ( dat->backgroundBmpUse&CLBF_TILEVTOROWHEIGHT )
+ {
+ desth = dat->row_min_heigh;
+ }
+ 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 );
+ }
+ SelectObject( hdcBmp, oldbm );
+ DeleteDC( hdcBmp );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int CLCPaint::_DetermineDrawMode( HWND hWnd, struct ClcData *dat )
+{
+ int paintMode = DM_LAYERED; // by default
+
+ if ( dat->force_in_dialog )
+ paintMode = DM_CONTROL;
+ else if ( g_CluiData.fDisableSkinEngine )
+ paintMode = DM_CLASSIC;
+ else if ( !g_CluiData.fLayered )
+ paintMode = DM_NON_LAYERED;
+
+ if ( !(paintMode&DM_CONTROL) && !CLUI_IsInMainWindow( hWnd ))
+ paintMode |= DM_FLOAT;
+
+ LONG lStyle = GetWindowLongPtr( hWnd, GWL_STYLE );
+ int nStatus = _GetGeneralisedStatus();
+ if (( lStyle & WS_DISABLED )
+ || ( dat->greyoutFlags & pcli->pfnClcStatusToPf2( nStatus ))
+ || (( dat->greyoutFlags & GREYF_UNFOCUS) && ( GetFocus() != hWnd )))
+ paintMode |= DM_GRAY;
+
+ if ( lStyle&CLS_GREYALTERNATE )
+ paintMode |= DM_GREYALTERNATE;
+
+ return paintMode;
+}
+
+void CLCPaint::_PreparePaintContext( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT& clRect, _PaintContext& pc )
+{
+ if ( paintMode&DM_GRAY && !(paintMode&DM_LAYERED))
+ {
+ pc.hdcMem2 = CreateCompatibleDC( hdc );
+ if ( paintMode&DM_CLASSIC )
+ pc.hBmpOsb2 = CreateBitmap( clRect.right, clRect.bottom, 1, GetDeviceCaps( hdc, BITSPIXEL ), NULL );
+ else
+ pc.hBmpOsb2 = ske_CreateDIB32( clRect.right, clRect.bottom );
+ pc.oldbmp2 = (HBITMAP) SelectObject( pc.hdcMem2, pc.hBmpOsb2 );
+ pc.fRelease |= _PaintContext::release_hdcmem2;
+ }
+
+ if ( paintMode&( DM_DRAW_OFFSCREEN | DM_GRAY ) )
+ {
+ pc.hdcMem = CreateCompatibleDC( hdc );
+ pc.fRelease |= _PaintContext::release_hdcmem;
+ pc.hBmpOsb = ske_CreateDIB32( clRect.right, clRect.bottom );
+ pc.oldbmp = ( HBITMAP ) SelectObject( pc.hdcMem, pc.hBmpOsb );
+ }
+
+ if ( paintMode&DM_CONTROL && !dat->bkChanged )
+ {
+ pc.tmpbkcolour = GetSysColor( COLOR_3DFACE );
+ pc.tmpforecolour = GetSysColor( COLOR_BTNTEXT );
+ }
+ else
+ {
+ pc.tmpbkcolour = (!(paintMode&DM_CONTROL) && dat->bkChanged ) ? dat->bkColour : ( !dat->useWindowsColours ? dat->bkColour : GetSysColor( COLOR_3DFACE ));
+ pc.tmpforecolour = /*(paintMode&DM_CONTROL) ? */dat->fontModernInfo[FONTID_CONTACTS].colour;
+ }
+
+ if ( paintMode&DM_GREYALTERNATE )
+ {
+ int rDelta = ( GetRValue( pc.tmpbkcolour ) > GetRValue( pc.tmpforecolour )) ? -10 : 10;
+ int gDelta = ( GetGValue( pc.tmpbkcolour ) > GetGValue( pc.tmpforecolour )) ? -10 : 10;
+ int bDelta = ( GetBValue( pc.tmpbkcolour ) > GetBValue( pc.tmpforecolour )) ? -10 : 10;
+ int rValue = GetRValue( pc.tmpbkcolour ) + rDelta;
+ int gValue = GetRValue( pc.tmpbkcolour ) + gDelta;
+ int bValue = GetRValue( pc.tmpbkcolour ) + bDelta;
+
+ BYTE brValue = ( rValue >255) ? 255 : rValue < 0 ? 0 : (BYTE)rValue;
+ BYTE bgValue = ( gValue >255) ? 255 : gValue < 0 ? 0 : (BYTE)gValue;
+ BYTE bbValue = ( bValue >255) ? 255 : bValue < 0 ? 0 : (BYTE)bValue;
+
+ pc.hBrushAlternateGrey = CreateSolidBrush( GetNearestColor( pc.hdcMem, RGB( brValue, bgValue, bbValue )));
+ }
+
+ // Set some draw states
+ SetBkMode( pc.hdcMem, TRANSPARENT );
+ SetStretchBltMode( pc.hdcMem, HALFTONE );
+
+ POINT org;
+ GetBrushOrgEx( pc.hdcMem, &org );
+ SetBrushOrgEx( pc.hdcMem, org.x, org.y, NULL );
+}
+
+void CLCPaint::_DrawBackground( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT * rcPaint, RECT& clRect, _PaintContext& pc )
+{
+ if (paintMode & (DM_FLOAT | DM_CONTROL)) {
+ HBRUSH hBrush = CreateSolidBrush( pc.tmpbkcolour );
+ FillRect( pc.hdcMem, rcPaint, hBrush );
+ DeleteObject( hBrush );
+ ske_SetRectOpaque( pc.hdcMem, rcPaint );
+ if ( !( paintMode & DM_GREYALTERNATE))
+ SkinDrawGlyph( pc.hdcMem, &clRect, rcPaint, "CL,ID=Background,Type=Control" );
+ }
+ else if ( paintMode&DM_CLASSIC) {
+ if ( !_DrawNonEnginedBackground( hWnd, pc.hdcMem, rcPaint, clRect, dat )) {
+ HBRUSH hBrush = CreateSolidBrush( pc.tmpbkcolour );
+ FillRect( pc.hdcMem, rcPaint, hBrush );
+ DeleteObject( hBrush );
+ }
+ }
+ else {
+ if ( paintMode&DM_NON_LAYERED )
+ ske_BltBackImage( hWnd, (paintMode&DM_GRAY) ? pc.hdcMem2 : pc.hdcMem, rcPaint );
+
+ SkinDrawGlyph(pc.hdcMem, &clRect, rcPaint, "CL,ID=Background");
+ }
+}
+
+void CLCPaint::_DrawLines( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT* rcPaint, RECT& clRect, _PaintContext& pc )
+{
+ struct ClcContact *Drawing;
+ struct ClcGroup *group = &dat->list;
+ group->scanIndex = 0;
+ int indent = 0;
+ int subident = 0;
+ int subindex = -1;
+ int line_num = -1;
+ int y = -dat->yScroll;
+ BOOL is_foreground = IsForegroundWindow( hWnd );
+ LONG lStyle = GetWindowLongPtr( hWnd, GWL_STYLE );
+
+ while( y < rcPaint->bottom )
+ {
+ if ( subindex == -1 )
+ {
+ if ( group->scanIndex >= group->cl.count )
+ {
+ group = group->parent;
+ indent--;
+ if ( group == NULL ) break; // Finished list
+ group->scanIndex++;
+ continue;
+ }
+ }
+
+ line_num++;
+
+ // Draw line, if needed
+ if ( y > rcPaint->top - dat->row_heights[line_num] )
+ {
+ int selected;
+ int hottrack;
+ int left_pos;
+ int right_pos;
+ int free_row_height;
+ RECT row_rc;
+ RECT free_row_rc;
+ MODERNMASK * mpRequest = NULL;
+ RECT rc;
+
+ // Get item to draw
+ if ( group->scanIndex < group->cl.count )
+ {
+ if ( subindex == -1 ) {
+ Drawing = group->cl.items[group->scanIndex];
+ subident = 0;
+ }
+ else {
+ Drawing = &( group->cl.items[group->scanIndex]->subcontacts[subindex] );
+ subident = dat->subIndent;
+ }
+ }
+ else Drawing = NULL;
+
+ // Something to draw?
+ if ( Drawing ) {
+
+ // Calc row height
+ if ( !gl_RowRoot )
+ RowHeights_GetRowHeight( dat, hWnd, Drawing, line_num );
+ else
+ RowHeight_CalcRowHeight( dat, hWnd, Drawing, line_num );
+
+ // Init settings
+ selected = (( line_num == dat->selection ) && ( dat->hwndRenameEdit != NULL || dat->showSelAlways || dat->exStyle&CLS_EX_SHOWSELALWAYS || is_foreground ) && Drawing->type != CLCIT_DIVIDER );
+ hottrack = dat->exStyle&CLS_EX_TRACKSELECT && Drawing->type != CLCIT_DIVIDER && dat->iHotTrack == line_num;
+ left_pos = clRect.left + dat->leftMargin + indent * dat->groupIndent + subident;
+ right_pos = dat->rightMargin; // Border
+
+ SetRect( &row_rc, clRect.left, y, clRect.right, y + dat->row_heights[line_num] );
+ free_row_rc = row_rc;
+ free_row_rc.left += left_pos;
+ free_row_rc.right -= right_pos;
+ free_row_rc.top += dat->row_border;
+ free_row_rc.bottom -= dat->row_border;
+ free_row_height = free_row_rc.bottom - free_row_rc.top;
+
+ {
+ HRGN rgn = CreateRectRgn( row_rc.left, row_rc.top, row_rc.right, row_rc.bottom );
+ SelectClipRgn( pc.hdcMem, rgn );
+ DeleteObject( rgn );
+ }
+
+ // Store pos
+ Drawing->pos_indent = free_row_rc.left;
+ ZeroMemory( &Drawing->pos_check, sizeof( Drawing->pos_check ));
+ ZeroMemory( &Drawing->pos_avatar, sizeof( Drawing->pos_avatar ));
+ ZeroMemory( &Drawing->pos_icon, sizeof( Drawing->pos_icon ));
+ ZeroMemory( &Drawing->pos_label, sizeof( Drawing->pos_label ));
+ ZeroMemory( &Drawing->pos_rename_rect, sizeof( Drawing->pos_rename_rect ));
+ ZeroMemory( &Drawing->pos_extra, sizeof( Drawing->pos_extra ));
+
+
+ //**** Draw Background
+
+ // Alternating grey
+ if ( paintMode&DM_GREYALTERNATE && line_num&1 )
+ {
+ if ( paintMode&DM_CONTROL || dat->bkChanged )
+ {
+ FillRect( pc.hdcMem, &row_rc, pc.hBrushAlternateGrey );
+ }
+ else
+ SkinDrawGlyph( pc.hdcMem, &row_rc, rcPaint, "CL,ID=GreyAlternate" );
+ }
+ if ( ! (paintMode&(DM_CLASSIC|DM_CONTROL)))
+ {
+ // Row background
+ if ( !(paintMode&DM_CONTROL))
+ { //Build mpRequest string
+ mpRequest = _GetCLCContactRowBackModernMask( group, Drawing, indent, line_num, selected, hottrack, dat );
+ {
+ RECT mrc = row_rc;
+ if ( group->parent == 0
+ && group->scanIndex != 0
+ && group->scanIndex < group->cl.count
+ && group->cl.items[group->scanIndex]->type == CLCIT_GROUP )
+ {
+ mrc.top += dat->row_before_group_space;
+ }
+ SkinDrawGlyphMask( pc.hdcMem, &mrc, rcPaint, mpRequest );
+ }
+ }
+ if ( selected || hottrack )
+ {
+ RECT mrc = row_rc;
+ if ( Drawing->type == CLCIT_GROUP &&
+ Drawing->group->parent->groupId == 0 &&
+ Drawing->group->parent->cl.items[0] != Drawing )
+ {
+ mrc.top += dat->row_before_group_space;
+ }
+ // Selection background ( only if hole line - full/less )
+ if ( dat->HiLightMode == 1 ) // Full or default
+ {
+ if ( selected )
+ SkinDrawGlyph( pc.hdcMem, &mrc, rcPaint, "CL,ID=Selection" );
+ if ( hottrack )
+ SkinDrawGlyph( pc.hdcMem, &mrc, rcPaint, "CL,ID=HotTracking" );
+ }
+ else if ( dat->HiLightMode == 2 ) // Less
+ {
+ if ( selected )
+ SkinDrawGlyph( pc.hdcMem, &mrc, rcPaint, "CL,ID=Selection" ); //instead of free_row_rc
+ if ( hottrack )
+ SkinDrawGlyph( pc.hdcMem, &mrc, rcPaint, "CL,ID=HotTracking" );
+ }
+ }
+
+ }
+ else
+ {
+ int checkboxWidth;
+ if (( lStyle&CLS_CHECKBOXES && Drawing->type == CLCIT_CONTACT ) ||
+ ( lStyle&CLS_GROUPCHECKBOXES && Drawing->type == CLCIT_GROUP ) ||
+ ( Drawing->type == CLCIT_INFO && Drawing->flags&CLCIIF_CHECKBOX ))
+ checkboxWidth = dat->checkboxSize+2;
+ else checkboxWidth = 0;
+ //background
+ if ( selected ) {
+ switch ( dat->HiLightMode )
+ {
+ case 0:
+ case 1:
+ {
+ int i = y;
+ int row_height = row_rc.bottom-row_rc.top;
+ for ( i = y; i < y+row_height; i += max( dat->row_min_heigh, 1 ))
+ {
+ ImageList_DrawEx( dat->himlHighlight, 0, pc.hdcMem, 0, i, clRect.right,
+ min( y+row_height-i, max( dat->row_min_heigh, 1 )), CLR_NONE, CLR_NONE,
+ dat->exStyle&CLS_EX_NOTRANSLUCENTSEL?ILD_NORMAL:ILD_BLEND25 );
+ }
+ SetTextColor( pc.hdcMem, paintMode&DM_CONTROL ? GetSysColor( COLOR_HIGHLIGHTTEXT ) : dat->selTextColour );
+ break;
+ }
+
+ case 2:
+ {
+ int i;
+ int row_height = row_rc.bottom-row_rc.top-1;
+ for ( i = y+1; i < y+row_height; i += max( dat->row_min_heigh, 1 ))
+ {
+ ImageList_DrawEx( dat->himlHighlight, 0, pc.hdcMem, 1, i, clRect.right-2,
+ min( y+row_height-i, max( dat->row_min_heigh, 1 )), CLR_NONE, CLR_NONE,
+ dat->exStyle&CLS_EX_NOTRANSLUCENTSEL?ILD_NORMAL:ILD_BLEND25 );
+ }
+ SetTextColor( pc.hdcMem, paintMode&DM_CONTROL ? GetSysColor( COLOR_HIGHLIGHTTEXT ) : dat->selTextColour );
+ break;
+ }
+ }
+ }
+
+ }
+ //**** Checkboxes
+ if (( lStyle&CLS_CHECKBOXES && Drawing->type == CLCIT_CONTACT ) ||
+ ( lStyle&CLS_GROUPCHECKBOXES && Drawing->type == CLCIT_GROUP ) ||
+ ( Drawing->type == CLCIT_INFO && Drawing->flags&CLCIIF_CHECKBOX ))
+ {
+ //RECT rc;
+ rc = free_row_rc;
+ rc.right = rc.left + dat->checkboxSize;
+ rc.top += ( rc.bottom - rc.top - dat->checkboxSize ) >> 1;
+ rc.bottom = rc.top + dat->checkboxSize;
+
+ if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, 0 );
+
+ if ( xpt_IsThemed( dat->hCheckBoxTheme )) {
+ xpt_DrawThemeBackground( dat->hCheckBoxTheme, pc.hdcMem, BP_CHECKBOX, Drawing->flags&CONTACTF_CHECKED?( hottrack?CBS_CHECKEDHOT:CBS_CHECKEDNORMAL ):( hottrack?CBS_UNCHECKEDHOT:CBS_UNCHECKEDNORMAL ), &rc, &rc );
+ }
+ else DrawFrameControl( pc.hdcMem, &rc, DFC_BUTTON, DFCS_BUTTONCHECK|DFCS_FLAT|( Drawing->flags&CONTACTF_CHECKED?DFCS_CHECKED:0 )|( hottrack?DFCS_HOT:0 ));
+
+ left_pos += dat->checkboxSize + EXTRA_CHECKBOX_SPACE + HORIZONTAL_SPACE;
+ free_row_rc.left = row_rc.left + left_pos;
+
+ // Store pos
+ Drawing->pos_check = rc;
+ }
+ _PaintRowItems( hWnd, pc.hdcMem, dat, Drawing, row_rc, free_row_rc, left_pos, right_pos, selected, hottrack, rcPaint );
+ if ( mpRequest && !dat->force_in_dialog )
+ {
+ if ( mpRequest->pl_Params[1].szValue )
+ free( mpRequest->pl_Params[1].szValue );
+ mpRequest->pl_Params[1].szValue = strdupn( "Ovl", 3 );
+ mpRequest->pl_Params[1].dwValueHash = mod_CalcHash( "Ovl" );
+ {
+ RECT mrc = row_rc;
+ if ( Drawing->type == CLCIT_GROUP &&
+ Drawing->group->parent->groupId == 0 &&
+ Drawing->group->parent->cl.items[0] != Drawing )
+ {
+ mrc.top += dat->row_before_group_space;
+ }
+ SkinDrawGlyphMask( pc.hdcMem, &mrc, rcPaint, mpRequest );
+ }
+ SkinSelector_DeleteMask( mpRequest );
+ mir_free( mpRequest );
+ }
+ }
+ }
+ y += dat->row_heights[line_num];
+ //increment by subcontacts
+ if (( group->cl.items && group->scanIndex < group->cl.count && group->cl.items[group->scanIndex]->subcontacts != NULL && group->cl.items[group->scanIndex]->type != CLCIT_GROUP )
+ && ( group->cl.items[group->scanIndex]->SubExpanded && dat->expandMeta ))
+ {
+ if ( subindex < group->cl.items[group->scanIndex]->SubAllocated-1 )
+ subindex++;
+ else
+ subindex = -1;
+ }
+
+ if ( subindex == -1 && group->scanIndex < group->cl.count )
+ {
+ 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;
+ subindex = -1;
+ continue;
+ }
+ group->scanIndex++;
+ }
+ else if ( group->scanIndex >= group->cl.count )
+ {
+ subindex = -1;
+ }
+ }
+ SelectClipRgn( pc.hdcMem, NULL );
+}
+
+
+void CLCPaint::_DrawInsertionMark( struct ClcData * dat, RECT& clRect, _PaintContext& pc )
+{
+ HBRUSH hBrush, hoBrush;
+ POINT pts[8];
+ HRGN hRgn;
+ int identation = dat->nInsertionLevel*dat->groupIndent;
+ int yt = cliGetRowTopY( dat, dat->iInsertionMark );
+
+ pts[0].y = yt - dat->yScroll - 4;
+ if ( pts[0].y < -3 ) pts[0].y = -3;
+ pts[0].x = 1+identation*( dat->text_rtl?0:1 );
+
+ pts[1].x = pts[0].x+2;
+ pts[1].y = pts[0].y+3;
+
+ pts[2].x = clRect.right-identation*( dat->text_rtl?1:0 )-4;
+ pts[2].y = pts[1].y;
+
+ pts[3].x = clRect.right-1-identation*( dat->text_rtl?1:0 );
+ 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 )/sizeof( pts[0] ), ALTERNATE );
+ hBrush = CreateSolidBrush( dat->fontModernInfo[FONTID_CONTACTS].colour );
+ hoBrush = ( HBRUSH )SelectObject( pc.hdcMem, hBrush );
+ FillRgn( pc.hdcMem, hRgn, hBrush );
+ ske_SetRgnOpaque( pc.hdcMem, hRgn );
+ SelectObject( pc.hdcMem, hoBrush );
+ DeleteObject( hBrush );
+}
+
+void CLCPaint::_CopyPaintToDest( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT* rcPaint, RECT& clRect, _PaintContext& pc )
+{
+ if ( !( paintMode&DM_GRAY ) && ( paintMode & DM_DRAW_OFFSCREEN ))
+ {
+ BitBlt( hdc, rcPaint->left, rcPaint->top, rcPaint->right-rcPaint->left, rcPaint->bottom-rcPaint->top, pc.hdcMem, rcPaint->left, rcPaint->top, SRCCOPY );
+ }
+
+ if (( paintMode&DM_GRAY ) && hdc && hdc != pc.hdcMem )
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 80, AC_SRC_ALPHA };
+ BOOL a = (( paintMode&DM_GRAY ) && (( paintMode&DM_NON_LAYERED)));
+ ske_AlphaBlend( a ? pc.hdcMem2 : hdc, rcPaint->left, rcPaint->top, rcPaint->right-rcPaint->left, rcPaint->bottom-rcPaint->top, pc.hdcMem, rcPaint->left, rcPaint->top, rcPaint->right-rcPaint->left, rcPaint->bottom-rcPaint->top, bf );
+ if ( a )
+ BitBlt( hdc, rcPaint->left, rcPaint->top, rcPaint->right-rcPaint->left, rcPaint->bottom-rcPaint->top, pc.hdcMem2, rcPaint->left, rcPaint->top, SRCCOPY );
+ }
+}
+void CLCPaint::_FreePaintContext( _PaintContext& pc )
+{
+ if ( pc.hBrushAlternateGrey ) DeleteObject( pc.hBrushAlternateGrey );
+ SelectObject( pc.hdcMem, (HFONT) GetStockObject( DEFAULT_GUI_FONT ));
+ if ( pc.fRelease&_PaintContext::release_hdcmem )
+ {
+ SelectObject( pc.hdcMem, pc.oldbmp );
+ DeleteObject( pc.hBmpOsb );
+ DeleteDC( pc.hdcMem );
+ }
+ if ( pc.fRelease&_PaintContext::release_hdcmem2)
+ {
+ SelectObject( pc.hdcMem2, pc.oldbmp2 );
+ DeleteObject( pc.hBmpOsb2 );
+ DeleteDC( pc.hdcMem2 );
+ }
+}
+void CLCPaint::_PaintClc( HWND hwnd, struct ClcData *dat, HDC hdc, RECT *_rcPaint )
+{
+ g_CluiData.t_now = time( NULL );
+
+ if ( _rcPaint && IsRectEmpty( _rcPaint )) return; // check if draw area is not empty
+ if ( !IsWindowVisible( hwnd )) return; // and window is visible
+
+ RECT clRect;
+ GetClientRect( hwnd, &clRect );
+
+ RECT * rcPaint = _rcPaint ? _rcPaint : &clRect; // if null is transmitted - use whole client area
+
+ // Invalidate ani avatars, avatars have to be validated in row paint routine below
+ if ( rcPaint->top == 0 && rcPaint->bottom == clRect.bottom && dat->avatars_show )
+ AniAva_InvalidateAvatarPositions( NULL );
+
+ // Now determine paint mode
+ int paintMode = _DetermineDrawMode( hwnd, dat );
+
+ // Preparing drawing contexts
+ _PaintContext pc( hdc );
+ _PreparePaintContext( hwnd, dat, hdc, paintMode, clRect, pc );
+
+ // Draw background
+ _DrawBackground( hwnd, dat, hdc, paintMode, rcPaint, clRect, pc );
+ // Draw lines
+ if ( dat->row_heights )
+ _DrawLines( hwnd, dat, hdc, paintMode, rcPaint, clRect, pc );
+
+ //insertion mark
+ if ( dat->iInsertionMark != -1 )
+ _DrawInsertionMark( dat, clRect, pc );
+
+ // BitBlt from memory to destination
+ _CopyPaintToDest( hwnd, dat, hdc, paintMode, rcPaint, clRect, pc );
+
+ // Free
+ _FreePaintContext( pc );
+
+ // all still non-validated animated avatars have to be removed
+ AniAva_RemoveInvalidatedAvatars();
+
+}
+
+void CLCPaint::_StoreItemPos( struct ClcContact *contact, int ItemType, RECT * rc )
+{
+ contact->ext_mpItemsDesc[contact->ext_nItemsNum].itemType = ItemType;
+ contact->ext_mpItemsDesc[contact->ext_nItemsNum].itemRect = *rc;
+ contact->ext_nItemsNum++;
+ switch ( ItemType )
+ {
+ case CIT_AVATAR:
+ contact->pos_avatar = *rc;
+ break;
+ case CIT_ICON:
+ contact->pos_icon = *rc;
+ break;
+ case CIT_TIME:
+ contact->pos_contact_time = *rc;
+ break;
+ case CIT_TEXT:
+ // RECT pos_label;//TODO label ( CIT_TEXT??? )
+ // RECT pos_rename; //TODO ( CIT_TEXT??? )
+ break;
+ case CIT_CHECKBOX:
+ break;
+ default:
+ if (( ItemType&CIT_EXTRA ) == CIT_EXTRA )
+ {
+ int iImage = ItemType&0x3F;
+ contact->pos_extra[iImage] = *rc;
+ }
+ break;
+ }
+}
+
+
+void CLCPaint::_CalcItemsPos( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *in_row_rc, RECT *in_free_row_rc, int left_pos, int right_pos, int selected, int hottrack )
+{
+ int item_iterator, item, item_text, text_left_pos;
+ BOOL left = TRUE; //TODO remove
+ RECT free_row_rc = *in_free_row_rc;
+ RECT row_rc = *in_row_rc;
+ Drawing->ext_nItemsNum = 0;
+ text_left_pos = row_rc.right;
+ // Now let's check what we have to draw
+ for ( item_iterator = 0 ; item_iterator < NUM_ITEM_TYPE && free_row_rc.left < free_row_rc.right ; item_iterator++ )
+ {
+ if ( Drawing->ext_nItemsNum >= SIZEOF( Drawing->ext_mpItemsDesc )) break;
+ if ( left )
+ item = item_iterator;
+ else
+ item = NUM_ITEM_TYPE - ( item_iterator - item_text );
+
+ switch( dat->row_items[item] )
+ {
+ case ITEM_AVATAR: ///////////////////////////////////////////////////////////////////////////////////////////////////
+ {
+ RECT rc;
+ int max_width;
+ int width;
+ int height;
+ BOOL miniMode;
+ if ( !dat->avatars_show || Drawing->type != CLCIT_CONTACT )
+ break;
+ miniMode = CheckMiniMode( dat, selected, hottrack );
+ AniAva_InvalidateAvatarPositions( Drawing->hContact );
+ if ( dat->icon_hide_on_avatar && dat->icon_draw_on_avatar_space )
+ max_width = max( dat->iconXSpace, dat->avatars_maxheight_size );
+ else
+ max_width = dat->avatars_maxheight_size;
+
+ // Has to draw?
+ if (( dat->use_avatar_service && Drawing->avatar_data == NULL )
+ || ( !dat->use_avatar_service && Drawing->avatar_pos == AVATAR_POS_DONT_HAVE )
+ || miniMode )
+ {
+ // Don't have to draw avatar
+
+ // Has to draw icon instead?
+ if ( dat->icon_hide_on_avatar && dat->icon_draw_on_avatar_space && Drawing->iImage != -1 )
+ {
+ RECT rc;
+
+ // Make rectangle
+ rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
+ left, dat->iconXSpace, max_width, ICON_HEIGHT, HORIZONTAL_SPACE );
+
+ if ( rc.left < rc.right )
+ {
+ /* center icon in avatar place */
+ if ( rc.right-rc.left>16 ) rc.left += (( ( rc.right-rc.left )-16 )>>1 );
+ if ( rc.bottom-rc.top>16 ) rc.top += (( ( rc.bottom-rc.top )-16 )>>1 );
+
+ // Store position
+ _StoreItemPos( Drawing, CIT_ICON, &rc );
+ }
+ }
+ else
+ {
+ // Has to keep the empty space??
+ if (( left && !dat->row_align_left_items_to_left ) || ( !left && !dat->row_align_right_items_to_right ))
+ {
+ // Make rectangle
+ rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
+ left, max_width, max_width, dat->avatars_maxheight_size, HORIZONTAL_SPACE );
+
+ // Store position
+ //StoreItemPos( Drawing, CIT_AVATAR, &rc );
+ //Drawing->pos_avatar = rc;
+ }
+ }
+ break;
+ }
+
+ // Has to draw avatar
+ if ( dat->avatar_cache.nodes && Drawing->avatar_pos > AVATAR_POS_DONT_HAVE ) {
+ width = dat->avatar_cache.nodes[Drawing->avatar_pos].width;
+ height = dat->avatar_cache.nodes[Drawing->avatar_pos].height;
+ }else if ( Drawing->avatar_pos == AVATAR_POS_ANIMATED ) {
+ width = Drawing->avatar_size.cx;
+ height = Drawing->avatar_size.cy;
+ }else {
+ width = 0;
+ height = 0;
+ }
+
+ // Make rectangle
+ rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
+ left, width, max_width, height, HORIZONTAL_SPACE );
+
+ rc.top = max( free_row_rc.top, rc.top );
+ rc.bottom = min( free_row_rc.bottom, rc.bottom );
+
+ if ( rc.left < rc.right ) {
+ // Store position
+ _StoreItemPos( Drawing, CIT_AVATAR, &rc );
+ }
+ //TO DO: CALC avatar overlays
+ break;
+ }
+ case ITEM_ICON: /////////////////////////////////////////////////////////////////////////////////////////////////////
+ {
+ RECT rc;
+ int iImage = -1;
+ BOOL has_avatar = (( dat->use_avatar_service && Drawing->avatar_data != NULL ) ||
+ ( !dat->use_avatar_service && Drawing->avatar_pos != AVATAR_POS_DONT_HAVE ))
+ && !( CheckMiniMode( dat, selected, hottrack ));
+
+ if ( Drawing->type == CLCIT_CONTACT
+ && dat->icon_hide_on_avatar
+ && !dat->icon_draw_on_avatar_space
+ && has_avatar
+ && !Drawing->image_is_special )
+ {
+ // Don't have to draw, but has to keep the empty space?
+ if (( left && !dat->row_align_left_items_to_left ) || ( !left && !dat->row_align_right_items_to_right ))
+ {
+ rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
+ left, dat->iconXSpace, dat->iconXSpace, ICON_HEIGHT, HORIZONTAL_SPACE );
+
+ if ( rc.left < rc.right ) {
+ // Store position
+ _StoreItemPos( Drawing, CIT_ICON, &rc );
+ }
+ }
+ break;
+ }
+ if ( Drawing->type == CLCIT_CONTACT
+ && dat->icon_hide_on_avatar
+ && dat->icon_draw_on_avatar_space
+ && ( !Drawing->image_is_special || !has_avatar ||
+ (
+ dat->avatars_draw_overlay
+ && dat->avatars_maxheight_size >= ICON_HEIGHT + ( dat->avatars_draw_border ? 2 : 0 )
+ && GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE < MAX_REGS( g_pAvatarOverlayIcons )
+ && dat->avatars_overlay_type == SETTING_AVATAR_OVERLAY_TYPE_CONTACT
+ )))
+ {
+ // Don't have to draw and don't have to keep the empty space
+ break;
+ }
+
+ // Get image
+ iImage = -1;
+ if ( Drawing->type == CLCIT_GROUP && !dat->row_hide_group_icon )
+ iImage = Drawing->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT;
+ else if ( Drawing->type == CLCIT_CONTACT )
+ iImage = Drawing->iImage;
+
+ // Has image to draw?
+ if ( iImage != -1 )
+ {
+ // Make rectangle
+ rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
+ left, dat->iconXSpace, dat->iconXSpace, ICON_HEIGHT, HORIZONTAL_SPACE );
+
+ if ( rc.left < rc.right )
+ {
+ // Store position
+ _StoreItemPos( Drawing, CIT_ICON, &rc );
+ }
+ }
+ break;
+ }
+ case ITEM_CONTACT_TIME: /////////////////////////////////////////////////////////////////////////////////////////////////////
+ {
+ PDNCE pdnce = ( PDNCE )(( Drawing->type == CLCIT_CONTACT )?pcli->pfnGetCacheEntry( Drawing->hContact ):NULL );
+ if ( Drawing->type == CLCIT_CONTACT && dat->contact_time_show && pdnce->hTimeZone )
+ {
+ TCHAR szResult[80];
+
+ if ( !tmi.printDateTime(pdnce->hTimeZone, _T("t"), szResult, SIZEOF(szResult), 0))
+ {
+ SIZE text_size;
+ RECT rc;
+
+ // Select font
+ ChangeToFont( hdcMem, dat, FONTID_CONTACT_TIME, NULL );
+
+ // Get text size
+ text_size.cy = ske_DrawText( hdcMem, szResult, lstrlen( szResult ), &rc, DT_CALCRECT | DT_NOPREFIX | DT_SINGLELINE );
+ text_size.cy = min( text_size.cy, free_row_rc.bottom - free_row_rc.top );
+ text_size.cx = rc.right - rc.left;
+
+ // Get rc
+ rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos, left,
+ text_size.cx, text_size.cx, text_size.cy, HORIZONTAL_SPACE );
+
+ if ( rc.left < rc.right )
+ {
+ // Store pos
+ Drawing->pos_contact_time = rc;
+ _StoreItemPos( Drawing, CIT_TIME, &rc );
+ }
+ }
+ }
+ break;
+ }
+ case ITEM_TEXT: /////////////////////////////////////////////////////////////////////////////////////////////////////
+ {
+ // Store init text position:
+ text_left_pos = left_pos;
+
+ left_pos += MIN_TEXT_WIDTH;
+ free_row_rc.left = row_rc.left + left_pos;
+
+ item_text = item;
+ left = FALSE;
+ break;
+ }
+ case ITEM_EXTRA_ICONS: //////////////////////////////////////////////////////////////////////////////////////////////
+ {
+ // Draw extra icons
+ if ( !Drawing->isSubcontact || dat->dbbMetaHideExtra == 0 && dat->extraColumnsCount > 0 )
+ {
+ int iImage;
+ int count = 0;
+ RECT rc;
+
+ for ( iImage = dat->extraColumnsCount-1 ; iImage >= 0 ; iImage -- )
+ {
+ if ( Drawing->iExtraImage[iImage] != 0xFF || Drawing->iWideExtraImage[iImage] != 0xFFFF || !dat->MetaIgnoreEmptyExtra )
+ {
+ rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
+ left, dat->extraColumnSpacing, dat->extraColumnSpacing, ICON_HEIGHT, 0 );
+ if ( rc.left < rc.right )
+ {
+ // Store position
+ _StoreItemPos( Drawing, CIT_EXTRA|( iImage&0x3F ), &rc );
+ //Drawing->pos_extra[iImage] = rc;
+ count++;
+ }
+ }
+ }
+ // Add extra space
+ if ( count )
+ {
+ _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
+ left, HORIZONTAL_SPACE, HORIZONTAL_SPACE, ICON_HEIGHT, 0 );
+ }
+ }
+ break;
+ }
+ }
+ }
+ if ( text_left_pos < free_row_rc.right )
+ {
+ // Draw text
+ RECT text_rc;
+ RECT selection_text_rc;
+ SIZE text_size = {0};
+ SIZE second_line_text_size = {0};
+ SIZE third_line_text_size = {0};
+ SIZE space_size = {0};
+ SIZE counts_size = {0};
+ char *szCounts = NULL;//mir_tstrdup( _T( "" ));
+ int free_width;
+ int free_height;
+ int max_bottom_selection_border = SELECTION_BORDER;
+ UINT uTextFormat = DT_NOPREFIX| /*DT_VCENTER |*/ DT_SINGLELINE | ( dat->text_rtl ? DT_RTLREADING : 0 ) | ( dat->text_align_right ? DT_RIGHT : 0 );
+
+ free_row_rc.left = text_left_pos;
+ free_width = free_row_rc.right - free_row_rc.left;
+ free_height = free_row_rc.bottom - free_row_rc.top;
+
+ // Select font
+ ChangeToFont( hdcMem, dat, GetBasicFontID( Drawing ), NULL );
+
+ // Get text size
+ GetTextSize( &text_size, hdcMem, free_row_rc, Drawing->szText, Drawing->ssText.plText, uTextFormat,
+ dat->text_resize_smileys ? 0 : Drawing->ssText.iMaxSmileyHeight );
+
+ // Get rect
+ text_rc = free_row_rc;
+
+ free_height -= text_size.cy;
+ text_rc.top += free_height >> 1;
+ text_rc.bottom = text_rc.top + text_size.cy;
+
+ if ( dat->text_align_right )
+ text_rc.left = max( free_row_rc.left, free_row_rc.right - text_size.cx );
+ else
+ text_rc.right = min( free_row_rc.right, free_row_rc.left + text_size.cx );
+
+ selection_text_rc = text_rc;
+
+ // If group, can have the size of count
+ if ( Drawing->type == CLCIT_GROUP )
+ {
+ int full_text_width = text_size.cx;
+ // Group conts?
+ szCounts = pcli->pfnGetGroupCountsText( dat, Drawing );
+
+ // Has to draw the count?
+ if ( szCounts && szCounts[0] )
+ {
+ RECT space_rc = free_row_rc;
+ RECT counts_rc = free_row_rc;
+ int text_width;
+
+ free_height = free_row_rc.bottom - free_row_rc.top;
+
+ // Get widths
+ ske_DrawText( hdcMem, _T( " " ), 1, &space_rc, DT_CALCRECT | DT_NOPREFIX );
+ space_size.cx = space_rc.right - space_rc.left;
+ space_size.cy = min( space_rc.bottom - space_rc.top, free_height );
+
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &counts_rc, DT_CALCRECT );
+
+ //Store position
+ //StoreItemPos( Drawing, CIT_SUBTEXT1, &counts_rc ); // Or not to comment?
+
+ counts_size.cx = counts_rc.right - counts_rc.left;
+ counts_size.cy = min( counts_rc.bottom - counts_rc.top, free_height );
+
+ text_width = free_row_rc.right - free_row_rc.left - space_size.cx - counts_size.cx;
+
+ if ( text_width > 4 )
+ {
+ text_size.cx = min( text_width, text_size.cx );
+ text_width = text_size.cx + space_size.cx + counts_size.cx;
+ }
+ else
+ {
+ text_width = text_size.cx;
+ space_size.cx = 0;
+ space_size.cy = 0;
+ counts_size.cx = 0;
+ counts_size.cy = 0;
+ }
+
+ // Get rect
+ free_height -= max( text_size.cy, counts_size.cy );
+ text_rc.top = free_row_rc.top + ( free_height >> 1 );
+ text_rc.bottom = text_rc.top + max( text_size.cy, counts_size.cy );
+
+ if ( dat->text_align_right )
+ text_rc.left = free_row_rc.right - text_width;
+ else
+ text_rc.right = free_row_rc.left + text_width;
+
+ selection_text_rc = text_rc;
+ full_text_width = text_width;
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPS:FONTID_CLOSEDGROUPS, NULL );
+ }
+
+ if ( dat->row_align_group_mode == 1 ) //center
+ {
+ int x;
+ x = free_row_rc.left+(( free_row_rc.right-free_row_rc.left-full_text_width )>>1 );
+ //int l = dat->leftMargin;
+ //int r = dat->rightMargin;
+ //x = l+row_rc.left+(( row_rc.right-row_rc.left-full_text_width-l-r )>>1 );
+ text_rc.left = x;
+ text_rc.right = x+full_text_width;
+ }
+ else if ( dat->row_align_group_mode == 2 ) //right
+ {
+ text_rc.left = free_row_rc.right-full_text_width;
+ text_rc.right = free_row_rc.right;
+ }
+ else //left
+ {
+ text_rc.left = free_row_rc.left;
+ text_rc.right = free_row_rc.left+full_text_width;
+ }
+
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && !CheckMiniMode( dat, selected, hottrack ))
+ {
+ int tmp;
+ PDNCE pdnce = ( PDNCE )(( Drawing->type == CLCIT_CONTACT )?pcli->pfnGetCacheEntry( Drawing->hContact ):NULL );
+ if ( dat->second_line_show && dat->second_line_type == TEXT_CONTACT_TIME && pdnce->hTimeZone)
+ {
+ // Get contact time
+ TCHAR buf[70] = _T("");
+ tmi.printDateTime(pdnce->hTimeZone, _T("t"), buf, SIZEOF(buf), 0);
+ mir_free( pdnce->szThirdLineText );
+ pdnce->szSecondLineText = mir_tstrdup( buf );
+ }
+
+ if ( dat->second_line_show && pdnce->szSecondLineText && pdnce->szSecondLineText[0]
+ && free_height > dat->second_line_top_space )
+ {
+ //RECT rc_tmp = free_row_rc;
+
+ ChangeToFont( hdcMem, dat, FONTID_SECONDLINE, NULL );
+
+ // Get sizes
+ GetTextSize( &second_line_text_size, hdcMem, free_row_rc, pdnce->szSecondLineText, pdnce->ssSecondLine.plText,
+ uTextFormat, dat->text_resize_smileys ? 0 : pdnce->ssSecondLine.iMaxSmileyHeight );
+
+ // Get rect
+ tmp = min( free_height, dat->second_line_top_space + second_line_text_size.cy );
+
+ free_height -= tmp;
+ text_rc.top = free_row_rc.top + ( free_height >> 1 );
+ text_rc.bottom = text_rc.top + free_row_rc.bottom - free_row_rc.top - free_height;
+
+ if ( dat->text_align_right )
+ text_rc.left = max( free_row_rc.left, min( text_rc.left, free_row_rc.right - second_line_text_size.cx ));
+ else
+ text_rc.right = min( free_row_rc.right, max( text_rc.right, free_row_rc.left + second_line_text_size.cx ));
+
+ selection_text_rc.top = text_rc.top;
+ selection_text_rc.bottom = min( selection_text_rc.bottom, selection_text_rc.top + text_size.cy );
+
+ max_bottom_selection_border = min( max_bottom_selection_border, dat->second_line_top_space / 2 );
+ }
+ if ( dat->third_line_show && dat->third_line_type == TEXT_CONTACT_TIME && pdnce->hTimeZone )
+ {
+ // Get contact time
+ TCHAR buf[70] = _T("");
+ tmi.printDateTime(pdnce->hTimeZone, _T("t"), buf, SIZEOF(buf), 0);
+ mir_free( pdnce->szThirdLineText );
+ pdnce->szThirdLineText = mir_tstrdup( buf );
+ }
+ if ( dat->third_line_show && pdnce->szThirdLineText != NULL && pdnce->szThirdLineText[0]
+ && free_height > dat->third_line_top_space )
+ {
+ //RECT rc_tmp = free_row_rc;
+
+ ChangeToFont( hdcMem, dat, FONTID_THIRDLINE, NULL );
+
+ // Get sizes
+ GetTextSize( &third_line_text_size, hdcMem, free_row_rc, pdnce->szThirdLineText, pdnce->ssThirdLine.plText,
+ uTextFormat, dat->text_resize_smileys ? 0 : pdnce->ssThirdLine.iMaxSmileyHeight );
+
+ // Get rect
+ tmp = min( free_height, dat->third_line_top_space + third_line_text_size.cy );
+
+ free_height -= tmp;
+ text_rc.top = free_row_rc.top + ( free_height >> 1 );
+ text_rc.bottom = text_rc.top + free_row_rc.bottom - free_row_rc.top - free_height;
+
+ if ( dat->text_align_right )
+ text_rc.left = max( free_row_rc.left, min( text_rc.left, free_row_rc.right - third_line_text_size.cx ));
+ else
+ text_rc.right = min( free_row_rc.right, max( text_rc.right, free_row_rc.left + third_line_text_size.cx ));
+
+ selection_text_rc.top = text_rc.top;
+ selection_text_rc.bottom = min( selection_text_rc.bottom, selection_text_rc.top + text_size.cy );
+
+ max_bottom_selection_border = min( max_bottom_selection_border, dat->third_line_top_space / 2 );
+ }
+
+ ChangeToFont( hdcMem, dat, GetBasicFontID( Drawing ), NULL );
+ }
+
+
+ selection_text_rc.left = text_rc.left;
+ selection_text_rc.right = text_rc.right;
+
+ Drawing->pos_label = text_rc;
+
+ selection_text_rc.top = max( selection_text_rc.top - SELECTION_BORDER, row_rc.top );
+ selection_text_rc.bottom = min( selection_text_rc.bottom + max_bottom_selection_border, row_rc.bottom );
+
+ if ( dat->text_align_right )
+ selection_text_rc.left = max( selection_text_rc.left - SELECTION_BORDER, free_row_rc.left );
+ else
+ selection_text_rc.right = min( selection_text_rc.right + SELECTION_BORDER, free_row_rc.right );
+ _StoreItemPos( Drawing, CIT_SELECTION, &selection_text_rc );
+
+ Drawing->pos_rename_rect = free_row_rc;
+
+ {
+ // Draw text
+ uTextFormat = uTextFormat | ( gl_TrimText?DT_END_ELLIPSIS:0 );
+
+ switch ( Drawing->type )
+ {
+ case CLCIT_DIVIDER:
+ {
+ //devider
+ RECT trc = free_row_rc;
+ RECT rc = free_row_rc;
+ rc.top += ( rc.bottom - rc.top ) >> 1;
+ rc.bottom = rc.top + 2;
+ rc.right = rc.left + (( rc.right - rc.left - text_size.cx )>>1 ) - 3;
+ trc.left = rc.right + 3;
+ trc.right = trc.left + text_size.cx + 6;
+ if ( text_size.cy < trc.bottom - trc.top )
+ {
+ trc.top += ( trc.bottom - trc.top - text_size.cy ) >> 1;
+ trc.bottom = trc.top + text_size.cy;
+ }
+ _StoreItemPos( Drawing, CIT_TEXT, &trc );
+ rc.left = rc.right + 6 + text_size.cx;
+ rc.right = free_row_rc.right;
+ break;
+ }
+ case CLCIT_GROUP:
+ {
+ RECT rc = text_rc;
+
+ // Get text rectangle
+ if ( dat->text_align_right )
+ rc.left = rc.right - text_size.cx;
+ else
+ rc.right = rc.left + text_size.cx;
+
+
+ if ( text_size.cy < rc.bottom - rc.top )
+ {
+ rc.top += ( rc.bottom - rc.top - text_size.cy ) >> 1;
+ rc.bottom = rc.top + text_size.cy;
+ }
+
+ // Draw text
+ _StoreItemPos( Drawing, CIT_TEXT, &rc );
+
+ // Has to draw the count?
+ if ( counts_size.cx > 0 )
+ {
+ RECT counts_rc = text_rc;
+ //counts_size.cx;
+ if ( dat->text_align_right )
+ counts_rc.right = text_rc.left + counts_size.cx;
+ else
+ counts_rc.left = text_rc.right - counts_size.cx;
+
+ if ( counts_size.cy < counts_rc.bottom - counts_rc.top )
+ {
+ counts_rc.top += ( counts_rc.bottom - counts_rc.top - counts_size.cy + 1 ) >> 1;
+ counts_rc.bottom = counts_rc.top + counts_size.cy;
+ }
+ // Draw counts
+ _StoreItemPos( Drawing, CIT_SUBTEXT1, &counts_rc );
+ }
+ break;
+ }
+ case CLCIT_CONTACT:
+ {
+
+ RECT free_rc = text_rc;
+ PDNCE pdnce = ( PDNCE )pcli->pfnGetCacheEntry( Drawing->hContact );
+ if ( text_size.cx > 0 && free_rc.bottom > free_rc.top )
+ {
+ RECT rc = free_rc;
+ rc.bottom = min( rc.bottom, rc.top + text_size.cy );
+
+ if ( text_size.cx < rc.right - rc.left )
+ {
+ if ( dat->text_align_right )
+ rc.left = rc.right - text_size.cx;
+ else
+ rc.right = rc.left + text_size.cx;
+ }
+ uTextFormat |= DT_VCENTER;
+ _StoreItemPos( Drawing, CIT_TEXT, &rc );
+ free_rc.top = rc.bottom;
+ }
+ uTextFormat &= ~DT_VCENTER;
+ if ( second_line_text_size.cx > 0 && free_rc.bottom > free_rc.top )
+ {
+ free_rc.top += dat->second_line_top_space;
+
+ if ( free_rc.bottom > free_rc.top )
+ {
+ RECT rc = free_rc;
+ rc.bottom = min( rc.bottom, rc.top + second_line_text_size.cy );
+
+ if ( second_line_text_size.cx < rc.right - rc.left )
+ {
+ if ( dat->text_align_right )
+ rc.left = rc.right - second_line_text_size.cx;
+ else
+ rc.right = rc.left + second_line_text_size.cx;
+ }
+ _StoreItemPos( Drawing, CIT_SUBTEXT1, &rc );
+ free_rc.top = rc.bottom;
+ }
+ }
+
+ if ( third_line_text_size.cx > 0 && free_rc.bottom > free_rc.top )
+ {
+ free_rc.top += dat->third_line_top_space;
+
+ if ( free_rc.bottom > free_rc.top )
+ {
+ RECT rc = free_rc;
+ rc.bottom = min( rc.bottom, rc.top + third_line_text_size.cy );
+
+ if ( third_line_text_size.cx < rc.right - rc.left )
+ {
+ if ( dat->text_align_right )
+ rc.left = rc.right - third_line_text_size.cx;
+ else
+ rc.right = rc.left + third_line_text_size.cx;
+ }
+ _StoreItemPos( Drawing, CIT_SUBTEXT2, &rc );
+ free_rc.top = rc.bottom;
+ }
+ }
+ break;
+ }
+ default: // CLCIT_INFO
+ {
+ _StoreItemPos( Drawing, CIT_TEXT, &text_rc );
+ }
+ }
+ }
+ }
+
+ *in_free_row_rc = free_row_rc;
+ *in_row_rc = row_rc;
+ Drawing->ext_fItemsValid = FALSE; /*TO DO: correctly implement placement recalculation*/
+}
+BOOL CLCPaint::__IsVisible( RECT * firtRect, RECT * secondRect )
+{
+ RECT res;
+ IntersectRect( &res, firtRect, secondRect );
+ return !IsRectEmpty( &res );
+}
+
+
+void CLCPaint::_GetBlendMode( IN struct ClcData *dat, IN struct ClcContact * Drawing, IN BOOL selected, IN BOOL hottrack, IN BOOL bFlag, OUT COLORREF * OutColourFg, OUT int * OutMode )
+{
+ COLORREF colourFg;
+ int mode;
+ int BlendedInActiveState = ( dat->dbbBlendInActiveState );
+ int BlendValue = dat->dbbBlend25 ? ILD_BLEND25 : ILD_BLEND50;
+ if ( selected && ( bFlag&GIM_SELECTED_AFFECT ))
+ {
+ colourFg = dat->selBkColour;
+ mode = BlendedInActiveState?ILD_NORMAL:ILD_SELECTED;
+ }
+ else if ( hottrack && ( bFlag&GIM_HOT_AFFECT ))
+ {
+ mode = BlendedInActiveState?ILD_NORMAL:ILD_FOCUS;
+ colourFg = dat->hotTextColour;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST && ( bFlag&GIM_TEMP_AFFECT ))
+ {
+ colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
+ mode = BlendValue;
+ }
+ else
+ {
+ colourFg = dat->selBkColour;
+ mode = ILD_NORMAL;
+ }
+ if ( Drawing->type == CLCIT_CONTACT && dat->showIdle && ( Drawing->flags&CONTACTF_IDLE ) &&
+ _GetRealStatus( Drawing, ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE &&
+ ( bFlag&GIM_IDLE_AFFECT )
+ )
+ mode = ILD_SELECTED;
+ if ( OutColourFg ) *OutColourFg = colourFg;
+ if ( OutMode )
+ {
+ if ( OutColourFg ) *OutMode = mode; //return ILD_MODE if color requested
+ else *OutMode =
+ ( mode == ILD_BLEND50 )?128 :
+ ( mode == ILD_BLEND25 )?64 :
+ 255; //return alpha otherwise
+ }
+}
+
+void CLCPaint::_DrawContactAvatar( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *row_rc, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem )
+{
+ if ( Drawing->avatar_pos == AVATAR_POS_ANIMATED )
+ {
+ int overlayIdx = -1;
+ int blendmode = 255;
+ if ( dat->avatars_draw_overlay && dat->avatars_maxheight_size >= ICON_HEIGHT + ( dat->avatars_draw_border ? 2 : 0 )
+ && GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE < MAX_REGS( g_pAvatarOverlayIcons ))
+ {
+ switch( dat->avatars_overlay_type )
+ {
+ case SETTING_AVATAR_OVERLAY_TYPE_NORMAL:
+ overlayIdx = g_pAvatarOverlayIcons[GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE].listID;
+ break;
+ case SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL:
+ overlayIdx = ExtIconFromStatusMode( Drawing->hContact, Drawing->proto,
+ Drawing->proto == NULL ? ID_STATUS_OFFLINE : GetContactCachedStatus( Drawing->hContact ));
+ break;
+ case SETTING_AVATAR_OVERLAY_TYPE_CONTACT:
+ overlayIdx = Drawing->iImage;
+ break;
+ }
+ }
+ _GetBlendMode( dat, Drawing, selected, hottrack, GIM_AVATAR_AFFECT, NULL, &blendmode );
+ AniAva_SetAvatarPos( Drawing->hContact, prcItem, overlayIdx, blendmode );
+ AniAva_RenderAvatar( Drawing->hContact, hdcMem, prcItem );
+ }
+ else if ( Drawing->avatar_pos>AVATAR_POS_DONT_HAVE )
+ {
+ int round_radius = 0;
+ HRGN rgn;
+ int blendmode = 255;
+
+ _GetBlendMode( dat, Drawing, selected, hottrack, GIM_AVATAR_AFFECT, NULL, &blendmode );
+
+ //get round corner radius
+ if ( dat->avatars_round_corners )
+ {
+ if ( dat->avatars_use_custom_corner_size )
+ round_radius = dat->avatars_custom_corner_size;
+ else
+ round_radius = min( _rcWidth( prcItem ), _rcHeight( prcItem )) / 5;
+ }
+ // draw borders
+ if ( dat->avatars_draw_border )
+ {
+ HBRUSH hBrush = CreateSolidBrush( dat->avatars_border_color );
+ HBRUSH hOldBrush = ( HBRUSH )SelectObject( hdcMem, hBrush );
+ HRGN rgnOutside = CreateRoundRectRgn( prcItem->left, prcItem->top, prcItem->right+1, prcItem->bottom+1, round_radius << 1, round_radius << 1 );
+ HRGN rgnInside = CreateRoundRectRgn( prcItem->left+1, prcItem->top+1, prcItem->right, prcItem->bottom, round_radius << 1, round_radius << 1 );
+ CombineRgn( rgnOutside, rgnOutside, rgnInside, RGN_DIFF );
+ FillRgn( hdcMem, rgnOutside, hBrush );
+ ske_SetRgnOpaque( hdcMem, rgnOutside );
+ SelectObject( hdcMem, hOldBrush );
+ DeleteObject( hBrush );
+ DeleteObject( rgnInside );
+ DeleteObject( rgnOutside );
+ }
+
+ //set clip area to clip avatars within borders
+ if ( dat->avatars_round_corners || dat->avatars_draw_border )
+ {
+ int k = dat->avatars_draw_border?1:0;
+ rgn = CreateRoundRectRgn( prcItem->left+k, prcItem->top+k, prcItem->right+1-k, prcItem->bottom+1-k, round_radius * 2, round_radius * 2 );
+
+ }
+ else
+ rgn = CreateRectRgn( prcItem->left, prcItem->top, prcItem->right, prcItem->bottom );
+ ExtSelectClipRgn( hdcMem, rgn, RGN_AND );
+ // Draw avatar
+ ImageArray_DrawImage( &dat->avatar_cache, Drawing->avatar_pos, hdcMem, prcItem->left, prcItem->top, blendmode );
+
+ // Restore region
+ DeleteObject( rgn );
+ rgn = CreateRectRgn( row_rc->left, row_rc->top, row_rc->right, row_rc->bottom );
+ SelectClipRgn( hdcMem, rgn );
+ DeleteObject( rgn );
+ // Draw overlays
+ if ( dat->avatars_draw_overlay && dat->avatars_maxheight_size >= ICON_HEIGHT + ( dat->avatars_draw_border ? 2 : 0 )
+ && GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE < MAX_REGS( g_pAvatarOverlayIcons ))
+ {
+ POINT ptOverlay = { prcItem->right-ICON_HEIGHT, prcItem->bottom-ICON_HEIGHT };
+ if ( dat->avatars_draw_border )
+ {
+ ptOverlay.x--;
+ ptOverlay.y--;
+ }
+ switch( dat->avatars_overlay_type )
+ {
+ case SETTING_AVATAR_OVERLAY_TYPE_NORMAL:
+ {
+ ske_ImageList_DrawEx( hAvatarOverlays, g_pAvatarOverlayIcons[GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE].listID,
+ hdcMem,
+ ptOverlay.x, ptOverlay.y, ICON_HEIGHT, ICON_HEIGHT,
+ CLR_NONE, CLR_NONE,
+ ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
+ break;
+ }
+ case SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL:
+ {
+ int item;
+
+ item = ExtIconFromStatusMode( Drawing->hContact, Drawing->proto,
+ Drawing->proto == NULL ? ID_STATUS_OFFLINE : GetContactCachedStatus( Drawing->hContact ));
+ if ( item != -1 )
+ _DrawStatusIcon( Drawing, dat, item, hdcMem,
+ ptOverlay.x, ptOverlay.y, ICON_HEIGHT, ICON_HEIGHT,
+ CLR_NONE, CLR_NONE, ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
+ break;
+ }
+ case SETTING_AVATAR_OVERLAY_TYPE_CONTACT:
+ {
+ if ( Drawing->iImage != -1 )
+ _DrawStatusIcon( Drawing, dat, Drawing->iImage, hdcMem,
+ ptOverlay.x, ptOverlay.y, ICON_HEIGHT, ICON_HEIGHT,
+ CLR_NONE, CLR_NONE, ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
+ break;
+ }
+ }
+ }
+ }
+}
+
+void CLCPaint::_DrawContactIcon( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem )
+{
+ //Draw Icon
+ int iImage = -1;
+ // Get image
+ if ( Drawing->type == CLCIT_GROUP )
+ {
+ if ( !dat->row_hide_group_icon ) iImage = Drawing->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT;
+ else iImage = -1;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT )
+ iImage = Drawing->iImage;
+
+ // Has image to draw?
+ if ( iImage != -1 )
+ {
+ COLORREF colourFg;
+ int mode;
+ _GetBlendMode( dat, Drawing, selected, hottrack, GIM_STATUSICON_AFFECT, &colourFg, &mode );
+ _DrawStatusIcon( Drawing, dat, iImage, hdcMem,
+ prcItem->left, prcItem->top,
+ 0, 0, CLR_NONE, colourFg, mode );
+ }
+}
+
+void CLCPaint::_DrawContactText( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem, UINT uTextFormat )
+{
+ ChangeToFont( hdcMem, dat, GetBasicFontID( Drawing ), NULL );
+ if ( selected )
+ SetTextColor( hdcMem, dat->force_in_dialog ? GetSysColor( COLOR_HIGHLIGHTTEXT ) : dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+
+ if ( Drawing->type == CLCIT_GROUP )
+ {
+ ske_DrawText( hdcMem, Drawing->szText, -1, prcItem, uTextFormat );
+ if ( selected && dat->szQuickSearch[0] != '\0' )
+ {
+ SetTextColor( hdcMem, dat->quickSearchColour );
+ ske_DrawText( hdcMem, Drawing->szText, lstrlen( dat->szQuickSearch ), prcItem, uTextFormat );
+ }
+ }
+ else if ( Drawing->type == CLCIT_CONTACT )
+ {
+ SIZE text_size;
+ text_size.cx = _rcWidth( prcItem );
+ text_size.cy = _rcHeight( prcItem );
+ uTextFormat |= DT_VCENTER;
+ //get font
+ _DrawTextSmiley( hdcMem, prcItem, &text_size, Drawing->szText, -1, Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ if ( selected && dat->szQuickSearch[0] != '\0' )
+ {
+ SetTextColor( hdcMem, dat->quickSearchColour );
+ _DrawTextSmiley( hdcMem, prcItem, &text_size, Drawing->szText, lstrlen( dat->szQuickSearch ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ }
+ }
+ else
+ {
+ ske_DrawText( hdcMem, Drawing->szText, -1, prcItem, uTextFormat );
+ }
+ text_rc.right = max( text_rc.right, prcItem->right );
+ text_rc.left = min( text_rc.left, prcItem->left );
+}
+void CLCPaint::_DrawContactSubText( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem, UINT uTextFormat, BYTE itemType )
+{
+ if ( Drawing->type == CLCIT_GROUP )
+ {
+ char * szCounts = pcli->pfnGetGroupCountsText( dat, Drawing );
+
+ // Has to draw the count?
+ if ( szCounts && szCounts[0] )
+ {
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ ske_DrawTextA( hdcMem, szCounts, -1, prcItem, uTextFormat );
+ ske_ResetTextEffect( hdcMem );
+ }
+ }
+ else if ( Drawing->type == CLCIT_CONTACT )
+ {
+ SIZE text_size = { _rcWidth( prcItem ), _rcHeight( prcItem ) };
+ PDNCE pdnce = ( PDNCE )(( Drawing->type == CLCIT_CONTACT )?pcli->pfnGetCacheEntry( Drawing->hContact ):NULL );
+ if ( pdnce )
+ {
+ ChangeToFont( hdcMem, dat, itemType == CIT_SUBTEXT1 ? FONTID_SECONDLINE : FONTID_THIRDLINE, NULL );
+ //draw second and third line
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ uTextFormat |= DT_VCENTER;
+ if ( itemType == CIT_SUBTEXT1 )
+ _DrawTextSmiley( hdcMem, prcItem, &text_size, pdnce->szSecondLineText, -1, pdnce->ssSecondLine.plText, uTextFormat, dat->text_resize_smileys );
+ else
+ _DrawTextSmiley( hdcMem, prcItem, &text_size, pdnce->szThirdLineText, -1, pdnce->ssThirdLine.plText, uTextFormat, dat->text_resize_smileys );
+ }
+ }
+ text_rc.right = max( text_rc.right, prcItem->right );
+ text_rc.left = min( text_rc.left, prcItem->left );
+}
+void CLCPaint::_DrawContactTime( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem )
+{
+ TCHAR szResult[80];
+ PDNCE pdnce = ( PDNCE )(( Drawing->type == CLCIT_CONTACT )?pcli->pfnGetCacheEntry( Drawing->hContact ):NULL );
+
+ if ( !pdnce ) return;
+
+ if ( !tmi.printDateTime(pdnce->hTimeZone, _T("t"), szResult, SIZEOF(szResult), 0))
+ {
+ // Select font
+ ChangeToFont( hdcMem, dat, FONTID_CONTACT_TIME, NULL );
+ ske_DrawText( hdcMem, szResult, lstrlen( szResult ), prcItem, DT_NOPREFIX | DT_SINGLELINE );
+ }
+}
+
+void CLCPaint::_DrawContactSelection( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT *rcPaint, RECT * prcItem )
+{
+ // Selection background
+ if (( selected || hottrack ) && dat->HiLightMode == 0) {
+ if ( selected )
+ SkinDrawGlyph( hdcMem, prcItem, rcPaint, "Contact List/Selection" );
+ else if ( hottrack )
+ SkinDrawGlyph( hdcMem, prcItem, rcPaint, "Contact List/HotTracking" );
+ }
+}
+
+void CLCPaint::_DrawContactExtraIcon( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * rc, int iImage )
+{
+ //Draw extra icon
+ COLORREF colourFg;
+ int mode;
+ if ( iImage != -1 )
+ {
+ _GetBlendMode( dat, Drawing, selected, hottrack, GIM_EXTRAICON_AFFECT, &colourFg, &mode );
+ if ( Drawing->iExtraImage[iImage] != 0xFF )
+ ske_ImageList_DrawEx( dat->himlExtraColumns, Drawing->iExtraImage[iImage], hdcMem,
+ rc->left, rc->top, 0, 0, CLR_NONE, colourFg, mode );
+ else if ( Drawing->iWideExtraImage[iImage] != 0xFFFF )
+ ske_ImageList_DrawEx( dat->himlWideExtraColumns, Drawing->iWideExtraImage[iImage], hdcMem,
+ rc->left, rc->top, 0, 0, CLR_NONE, colourFg, mode );
+ }
+}
+
+void CLCPaint::_DrawContactLine( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *free_row_rc, RECT *rcPaint, RECT& text_rc )
+{ //draw line
+ RECT rc1 = *free_row_rc;
+ RECT rc2 = *free_row_rc;
+ rc1.right = text_rc.left-3;
+ rc2.left = text_rc.right+3;
+ rc1.top += ( rc1.bottom - rc1.top ) >> 1;
+ rc1.bottom = rc1.top + 2;
+ rc2.top += ( rc2.bottom - rc2.top ) >> 1;
+ rc2.bottom = rc2.top + 2;
+ {
+ RECT rcTemp = rc1;
+ IntersectRect( &rc1, &rcTemp, rcPaint );
+ }
+
+ { //Subtract icon rect from left and right.
+ RECT rcTemp;
+ IntersectRect( &rcTemp, &Drawing->pos_icon, &rc1 );
+ if ( !IsRectEmpty( &rcTemp )) rc1.right = rcTemp.left;
+ IntersectRect( &rcTemp, &Drawing->pos_icon, &rc2 );
+ if ( !IsRectEmpty( &rcTemp )) rc2.left = rcTemp.right;
+ }
+
+ if ( rc1.right-rc1.left >= 6 && !IsRectEmpty( &rc1 ))
+ {
+ DrawEdge( hdcMem, &rc1, BDR_SUNKENOUTER, BF_RECT );
+ ske_SetRectOpaque( hdcMem, &rc1 );
+ }
+ {
+ RECT rcTemp = rc2;
+ IntersectRect( &rc2, &rcTemp, rcPaint );
+ }
+ if ( rc2.right-rc2.left >= 6 && !IsRectEmpty( &rc2 ))
+ {
+ DrawEdge( hdcMem, &rc2, BDR_SUNKENOUTER, BF_RECT );
+ ske_SetRectOpaque( hdcMem, &rc2 );
+ }
+}
+
+void CLCPaint::_DrawContactItems( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *row_rc, RECT *free_row_rc, int left_pos, int right_pos, int selected, int hottrack, RECT *rcPaint )
+{
+ int i;
+ RECT text_rc = {0};
+ UINT uTextFormat = DT_NOPREFIX |
+ /*DT_VCENTER |*/
+ DT_SINGLELINE |
+ ( dat->text_rtl ? DT_RTLREADING : 0 ) |
+ ( dat->text_align_right ? DT_RIGHT : 0 )|
+ ( gl_TrimText?DT_END_ELLIPSIS:0 )|
+ (( dat->force_in_dialog || dat->bkChanged ) ? DT_FORCENATIVERENDER:0 );
+
+ text_rc = *row_rc;
+
+ text_rc.right = row_rc->left;
+ text_rc.left = row_rc->right;
+
+ for ( i=0; i < Drawing->ext_nItemsNum; i++ )
+ {
+ RECT * prcItem = &( Drawing->ext_mpItemsDesc[i].itemRect );
+ if ( __IsVisible( rcPaint, prcItem ) || ( Drawing->ext_mpItemsDesc[i].itemType == CIT_AVATAR && Drawing->avatar_pos == AVATAR_POS_ANIMATED ))
+ {
+ switch( Drawing->ext_mpItemsDesc[i].itemType )
+ {
+ case CIT_AVATAR:
+ _DrawContactAvatar( hdcMem, dat, Drawing, row_rc, selected, hottrack, text_rc, prcItem );
+ break;
+ case CIT_ICON:
+ _DrawContactIcon( hdcMem, dat, Drawing, selected, hottrack, text_rc, prcItem );
+ break;
+ case CIT_TEXT:
+ _DrawContactText( hdcMem, dat, Drawing, selected, hottrack, text_rc, prcItem, uTextFormat );
+ break;
+ case CIT_SUBTEXT1:
+ case CIT_SUBTEXT2:
+ _DrawContactSubText( hdcMem, dat, Drawing, selected, hottrack, text_rc, prcItem, uTextFormat, Drawing->ext_mpItemsDesc[i].itemType );
+ break;
+ case CIT_TIME:
+ _DrawContactTime( hdcMem, dat, Drawing, selected, hottrack, text_rc, prcItem );
+ break;
+ case CIT_CHECKBOX:
+ //_DrawNothing no check boxes in skinned mode
+ break;
+ //other here
+ case CIT_SELECTION:
+ _DrawContactSelection( hdcMem, dat, Drawing, selected, hottrack, rcPaint, prcItem );
+ break;
+ default:
+ if ( Drawing->ext_mpItemsDesc[i].itemType&CIT_EXTRA )
+ _DrawContactExtraIcon( hdcMem, dat, Drawing, selected, hottrack, text_rc, prcItem, Drawing->ext_mpItemsDesc[i].itemType&0x3F );
+ break;
+ }
+ }
+ }
+ if (( Drawing->type == CLCIT_GROUP && dat->exStyle&CLS_EX_LINEWITHGROUPS )
+ || ( Drawing->type == CLCIT_DIVIDER ))
+ _DrawContactLine( hdcMem, dat, Drawing, free_row_rc, rcPaint, text_rc );
+}
+void CLCPaint::_PaintRowItems ( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT row_rc, RECT free_row_rc, int left_pos, int right_pos, int selected, int hottrack, RECT *rcPaint )
+{
+ //Extended LAYOUT
+ if ( gl_RowRoot && ( dat->hWnd == pcli->hwndContactTree ))
+ {
+ _PaintRowItemsEx( hwnd, hdcMem, dat, Drawing, row_rc, free_row_rc, left_pos, right_pos, selected, hottrack, rcPaint );
+ ske_ResetTextEffect( hdcMem );
+ return;
+ }
+ //END OFF Extended LAYOUT
+ if ( !Drawing->ext_fItemsValid ) _CalcItemsPos( hwnd, hdcMem, dat, Drawing, &row_rc, &free_row_rc, left_pos, right_pos, selected, hottrack );
+ _DrawContactItems( hwnd, hdcMem, dat, Drawing, &row_rc, &free_row_rc, left_pos, right_pos, selected, hottrack, rcPaint );
+ ske_ResetTextEffect( hdcMem );
+}
+
+/* TODO Render items
+
+V avatar
+V avatars overlays
+V avatar clipping if ignore avatar height for row height calculation is set
+V icon
+V text
+V time
+V extra icons
+V selection/hot
+V groups and divider lines
+
+Milestones to implement Extended row layout
+
+- 1. Implement separate Row item position calculation and drawing
+V a. Separation of painting and positions calculation
+V b. Use Items rect array for hit test
+. c. Calculate row height via appropriate function
+. d. Invalidate row items only when needed
+
+. 2. Implement extended row item layout
+. a. layout template parsing
+. b. calculate positions according to template
+. c. GUI to modify template
+. d. skin defined template
+*/
diff --git a/plugins/Clist_modern/src/modern_clcutils.cpp b/plugins/Clist_modern/src/modern_clcutils.cpp
new file mode 100644
index 0000000000..9e6066c13a
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clcutils.cpp
@@ -0,0 +1,870 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_defsettings.h"
+
+//loads of stuff that didn't really fit anywhere else
+
+BOOL RectHitTest(RECT *rc, int testx, int testy)
+{
+ return testx >= rc->left && testx < rc->right && testy >= rc->top && testy < rc->bottom;
+}
+
+int cliHitTest(HWND hwnd,struct ClcData *dat,int testx,int testy,struct ClcContact **contact,struct ClcGroup **group,DWORD *flags)
+{
+ struct ClcContact *hitcontact = NULL;
+ struct ClcGroup *hitgroup = NULL;
+ int hit = -1;
+ RECT clRect;
+ if (CLUI_TestCursorOnBorders() != 0)
+ {
+ if (flags) *flags = CLCHT_NOWHERE;
+ return -1;
+ }
+ if (flags) *flags = 0;
+ GetClientRect(hwnd,&clRect);
+ if (testx < 0 || testy < 0 || testy >= clRect.bottom || testx >= clRect.right) {
+ if (flags) {
+ if (testx < 0) *flags |= CLCHT_TOLEFT;
+ else if (testx >= clRect.right) *flags |= CLCHT_TORIGHT;
+ if (testy < 0) *flags |= CLCHT_ABOVE;
+ else if (testy >= clRect.bottom) *flags |= CLCHT_BELOW;
+ }
+ return -1;
+ }
+ if (testx < dat->leftMargin) {
+ if (flags) *flags |= CLCHT_INLEFTMARGIN|CLCHT_NOWHERE;
+ return -1;
+ }
+
+ // Get hit item
+ hit = cliRowHitTest(dat, dat->yScroll + testy);
+
+ if (hit != -1)
+ hit = cliGetRowByIndex(dat, hit, &hitcontact, &hitgroup);
+
+ if (hit == -1) {
+ if (flags) *flags |= CLCHT_NOWHERE|CLCHT_BELOWITEMS;
+ return -1;
+ }
+ if (contact) *contact = hitcontact;
+ if (group) *group = hitgroup;
+ /////////
+
+ if (((testx < hitcontact->pos_indent) && !dat->text_rtl) ||
+ ((testx>clRect.right-hitcontact->pos_indent) && dat->text_rtl))
+ {
+ if (flags) *flags |= CLCHT_ONITEMINDENT;
+ return hit;
+ }
+
+ if (RectHitTest(&hitcontact->pos_check, testx, testy))
+ {
+ if (flags) *flags |= CLCHT_ONITEMCHECK;
+ return hit;
+ }
+
+ if (RectHitTest(&hitcontact->pos_avatar, testx, testy))
+ {
+ if (flags) *flags |= CLCHT_ONITEMICON;
+ return hit;
+ }
+
+ if (RectHitTest(&hitcontact->pos_icon, testx, testy))
+ {
+ if (flags) *flags |= CLCHT_ONITEMICON;
+ return hit;
+ }
+
+ // if (testx>hitcontact->pos_extra) {
+ // if (flags)
+ {
+ // int c = -1;
+ int i;
+ for (i=0; i < dat->extraColumnsCount; i++)
+ {
+ if (RectHitTest(&hitcontact->pos_extra[i], testx, testy))
+ {
+ if (flags) *flags |= CLCHT_ONITEMEXTRA|(i << 24);
+ return hit;
+ }
+ }
+ }
+
+ if (dat->HiLightMode == 1)
+ {
+ if (flags) *flags |= CLCHT_ONITEMLABEL;
+ return hit;
+ }
+
+ if (RectHitTest(&hitcontact->pos_label, testx, testy))
+ {
+ if (flags) *flags |= CLCHT_ONITEMLABEL;
+ return hit;
+ }
+
+ if (flags) *flags |= CLCHT_NOWHERE;
+ return hit;
+}
+
+void cliScrollTo(HWND hwnd,struct ClcData *dat,int desty,int noSmooth)
+{
+ DWORD startTick,nowTick;
+ int oldy = dat->yScroll;
+ RECT clRect,rcInvalidate;
+ int maxy,previousy;
+
+ if (dat->iHotTrack != -1 && dat->yScroll != desty) {
+ pcli->pfnInvalidateItem(hwnd,dat,dat->iHotTrack);
+ dat->iHotTrack = -1;
+ ReleaseCapture();
+ }
+ GetClientRect(hwnd,&clRect);
+ rcInvalidate = clRect;
+ //maxy = dat->rowHeight*GetGroupContentsCount(&dat->list,2)-clRect.bottom;
+ maxy = cliGetRowTotalHeight(dat)-clRect.bottom;
+ if (desty>maxy) desty = maxy;
+ if (desty < 0) desty = 0;
+ if (abs(desty-dat->yScroll) < 4) noSmooth = 1;
+ if ( !noSmooth && dat->exStyle&CLS_EX_NOSMOOTHSCROLLING) noSmooth = 1;
+ previousy = dat->yScroll;
+
+ BOOL keyDown = ( ( GetKeyState( VK_UP )
+ | GetKeyState( VK_DOWN )
+ | GetKeyState( VK_LEFT )
+ | GetKeyState( VK_RIGHT )
+ | GetKeyState( VK_PRIOR )
+ | GetKeyState( VK_NEXT )
+ | GetKeyState( VK_HOME )
+ | GetKeyState( VK_END )) & 0x8000 );
+
+ if ( !noSmooth && !keyDown)
+ {
+ startTick = GetTickCount();
+ for (;;) {
+ nowTick = GetTickCount();
+ if (nowTick >= startTick+dat->scrollTime) break;
+ dat->yScroll = oldy+(desty-oldy)*(int)(nowTick-startTick)/dat->scrollTime;
+ if (/*dat->backgroundBmpUse&CLBF_SCROLL || dat->hBmpBackground == NULL && */FALSE)
+ ScrollWindowEx(hwnd,0,previousy-dat->yScroll,NULL,NULL,NULL,NULL,SW_INVALIDATE);
+ else
+ {
+ CallService(MS_SKINENG_UPTATEFRAMEIMAGE,(WPARAM) hwnd, (LPARAM) 0);
+ //InvalidateRectZ(hwnd,NULL,FALSE);
+ }
+ previousy = dat->yScroll;
+ SetScrollPos(hwnd,SB_VERT,dat->yScroll,TRUE);
+ CallService(MS_SKINENG_UPTATEFRAMEIMAGE,(WPARAM) hwnd, (LPARAM) 0);
+ UpdateWindow(hwnd);
+ }
+ }
+ dat->yScroll = desty;
+ if ((dat->backgroundBmpUse&CLBF_SCROLL || dat->hBmpBackground == NULL) && FALSE)
+ ScrollWindowEx(hwnd,0,previousy-dat->yScroll,NULL,NULL,NULL,NULL,SW_INVALIDATE);
+ else
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ SetScrollPos(hwnd,SB_VERT,dat->yScroll,TRUE);
+}
+
+
+void cliRecalcScrollBar(HWND hwnd,struct ClcData *dat)
+{
+ SCROLLINFO si = {0};
+ RECT clRect;
+ NMCLISTCONTROL nm;
+ if (LOCK_RECALC_SCROLLBAR) return;
+
+ RowHeights_CalcRowHeights(dat, hwnd);
+
+ GetClientRect(hwnd,&clRect);
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ si.nMin = 0;
+ si.nMax = cliGetRowTotalHeight(dat)-1;
+ si.nPage = clRect.bottom;
+ si.nPos = dat->yScroll;
+
+ nm.hdr.code = CLN_LISTSIZECHANGE;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = 0;//GetDlgCtrlID(hwnd);
+ nm.pt.y = si.nMax;
+
+ SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm); //post
+
+ GetClientRect(hwnd,&clRect);
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ si.nMin = 0;
+ si.nMax = cliGetRowTotalHeight(dat)-1;
+ si.nPage = clRect.bottom;
+ si.nPos = dat->yScroll;
+
+ if ( GetWindowLongPtr(hwnd,GWL_STYLE)&CLS_CONTACTLIST ) {
+ if ( dat->noVScrollbar == 0 ) SetScrollInfo(hwnd,SB_VERT,&si,TRUE);
+ //else SetScrollInfo(hwnd,SB_VERT,&si,FALSE);
+ }
+ else
+ SetScrollInfo(hwnd,SB_VERT,&si,TRUE);
+ g_mutex_bSizing = 1;
+ cliScrollTo(hwnd,dat,dat->yScroll,1);
+ g_mutex_bSizing = 0;
+}
+
+
+static WNDPROC OldRenameEditWndProc;
+static LRESULT CALLBACK RenameEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg)
+ {
+ case WM_KEYDOWN:
+ switch(wParam)
+ {
+ case VK_RETURN:
+ pcli->pfnEndRename(GetParent(hwnd),(struct ClcData*)GetWindowLongPtr(hwnd,GWLP_USERDATA),1);
+ return 0;
+ case VK_ESCAPE:
+ pcli->pfnEndRename(GetParent(hwnd),(struct ClcData*)GetWindowLongPtr(hwnd,GWLP_USERDATA),0);
+ return 0;
+ }
+ break;
+ case WM_GETDLGCODE:
+ if (lParam)
+ {
+ MSG *msg = (MSG*)lParam;
+ if (msg->message == WM_KEYDOWN && msg->wParam == VK_TAB) return 0;
+ if (msg->message == WM_CHAR && msg->wParam == '\t') return 0;
+ }
+ return DLGC_WANTMESSAGE;
+ case WM_KILLFOCUS:
+ pcli->pfnEndRename(GetParent(hwnd),(struct ClcData*)GetWindowLongPtr(hwnd,GWLP_USERDATA),1);
+ SendMessage(pcli->hwndContactTree,WM_SIZE,0,0);
+ return 0;
+ }
+ return CallWindowProc(OldRenameEditWndProc,hwnd,msg,wParam,lParam);
+}
+
+void cliBeginRenameSelection(HWND hwnd,struct ClcData *dat)
+{
+ struct ClcContact *contact;
+ struct ClcGroup *group;
+ int indent,x,y,subident, h,w;
+ RECT clRect;
+ RECT r;
+
+
+ KillTimer(hwnd,TIMERID_RENAME);
+ ReleaseCapture();
+ dat->iHotTrack = -1;
+ dat->selection = cliGetRowByIndex(dat,dat->selection,&contact,&group);
+ if (dat->selection == -1) return;
+ if (contact->type != CLCIT_CONTACT && contact->type != CLCIT_GROUP) return;
+
+ if (contact->type == CLCIT_CONTACT && contact->isSubcontact)
+ subident = dat->subIndent;
+ else
+ subident = 0;
+
+ for (indent = 0;group->parent;indent++,group = group->parent);
+ GetClientRect(hwnd,&clRect);
+ x = indent*dat->groupIndent+dat->iconXSpace-2+subident;
+ w = clRect.right-x;
+ y = cliGetRowTopY(dat, dat->selection)-dat->yScroll;
+ h = dat->row_heights[dat->selection];
+ {
+ int i;
+ for (i=0; i <= FONTID_MODERN_MAX; i++)
+ if (h < dat->fontModernInfo[i].fontHeight+4) h = dat->fontModernInfo[i].fontHeight+4;
+ }
+ //TODO contact->pos_label
+
+
+ {
+
+ RECT rectW;
+ int h2;
+ GetWindowRect(hwnd,&rectW);
+ // w = contact->pos_full_first_row.right-contact->pos_full_first_row.left;
+ // h = contact->pos_full_first_row.bottom-contact->pos_full_first_row.top;
+ //w = clRect.right-x;
+ //w = clRect.right-x;
+ //x += rectW.left;//+contact->pos_full_first_row.left;
+ //y += rectW.top;//+contact->pos_full_first_row.top;
+ x = contact->pos_rename_rect.left+rectW.left;
+ y = contact->pos_label.top+rectW.top;
+ w = contact->pos_rename_rect.right-contact->pos_rename_rect.left;
+ h2 = contact->pos_label.bottom-contact->pos_label.top+4;
+ h = h2;//max(h,h2);
+
+ }
+
+ {
+ int a = 0;
+ if (contact->type == CLCIT_GROUP)
+ {
+ if (dat->row_align_group_mode == 1) a |= ES_CENTER;
+ else if (dat->row_align_group_mode == 2) a |= ES_RIGHT;
+ }
+ if (dat->text_rtl) a |= EN_ALIGN_RTL_EC;
+ if (contact->type == CLCIT_GROUP)
+ dat->hwndRenameEdit = CreateWindow(_T("EDIT"),contact->szText,WS_POPUP|WS_BORDER|ES_AUTOHSCROLL|a,x,y,w,h,hwnd,NULL,g_hInst,NULL);
+ else
+ dat->hwndRenameEdit = CreateWindow(_T("EDIT"),pcli->pfnGetContactDisplayName(contact->hContact,0),WS_POPUP|WS_BORDER|ES_AUTOHSCROLL|a,x,y,w,h,hwnd,NULL,g_hInst,NULL);
+ }
+ SetWindowLongPtr(dat->hwndRenameEdit,GWL_STYLE,GetWindowLongPtr(dat->hwndRenameEdit,GWL_STYLE)&(~WS_CAPTION)|WS_BORDER);
+ SetWindowLongPtr(dat->hwndRenameEdit,GWLP_USERDATA,(LONG_PTR)dat);
+ OldRenameEditWndProc = (WNDPROC)SetWindowLongPtr(dat->hwndRenameEdit,GWLP_WNDPROC,(LONG_PTR)RenameEditSubclassProc);
+ SendMessage(dat->hwndRenameEdit,WM_SETFONT,(WPARAM)(contact->type == CLCIT_GROUP?dat->fontModernInfo[FONTID_OPENGROUPS].hFont:dat->fontModernInfo[FONTID_CONTACTS].hFont),0);
+ SendMessage(dat->hwndRenameEdit,EM_SETMARGINS,EC_LEFTMARGIN|EC_RIGHTMARGIN|EC_USEFONTINFO,0);
+ SendMessage(dat->hwndRenameEdit,EM_SETSEL,0,(LPARAM)(-1));
+ // SetWindowLongPtr(dat->hwndRenameEdit,GWLP_USERDATA,(LONG_PTR)hwnd);
+ r.top = 1;
+ r.bottom = h-1;
+ r.left = 0;
+ r.right = w;
+
+ //ES_MULTILINE
+
+ SendMessage(dat->hwndRenameEdit,EM_SETRECT,0,(LPARAM)(&r));
+
+ CLUI_ShowWindowMod(dat->hwndRenameEdit,SW_SHOW);
+ SetWindowPos(dat->hwndRenameEdit,HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
+ SetFocus(dat->hwndRenameEdit);
+}
+
+int GetDropTargetInformation(HWND hwnd,struct ClcData *dat,POINT pt)
+{
+ RECT clRect;
+ int hit;
+ struct ClcContact *contact = NULL,*movecontact = NULL;
+ struct ClcGroup *group,*movegroup;
+ DWORD hitFlags;
+ int nSetSelection = -1;
+
+ GetClientRect(hwnd,&clRect);
+ dat->selection = dat->iDragItem;
+ dat->iInsertionMark = -1;
+ dat->nInsertionLevel = 0;
+ if ( !PtInRect(&clRect,pt)) return DROPTARGET_OUTSIDE;
+
+ hit = cliHitTest(hwnd,dat,pt.x,pt.y,&contact,&group,&hitFlags);
+ cliGetRowByIndex(dat,dat->iDragItem,&movecontact,&movegroup);
+ if (hit == dat->iDragItem) return DROPTARGET_ONSELF;
+ if (hit == -1 || hitFlags&CLCHT_ONITEMEXTRA || !movecontact) return DROPTARGET_ONNOTHING;
+
+ if (movecontact->type == CLCIT_GROUP) {
+ struct ClcContact *bottomcontact = NULL,*topcontact = NULL;
+ struct ClcGroup *topgroup = NULL, *bottomgroup = NULL;
+ int topItem = -1,bottomItem = -1;
+ int ok = 0;
+ if (pt.y+dat->yScroll < cliGetRowTopY(dat,hit)+dat->insertionMarkHitHeight || contact->type != CLCIT_GROUP) {
+ //could be insertion mark (above)
+ topItem = hit-1; bottomItem = hit;
+ bottomcontact = contact;
+ bottomgroup = group;
+ topItem = cliGetRowByIndex(dat,topItem,&topcontact,&topgroup);
+ ok = 1;
+ } else if ((pt.y+dat->yScroll >= cliGetRowTopY(dat,hit+1)-dat->insertionMarkHitHeight)
+ || (contact->type == CLCIT_GROUP && contact->group->expanded && contact->group->cl.count>0))
+ {
+ //could be insertion mark (below)
+ topItem = hit; bottomItem = hit+1;
+ topcontact = contact; topgroup = group;
+ bottomItem = cliGetRowByIndex(dat,bottomItem,&bottomcontact,&bottomgroup);
+ ok = 1;
+ }
+ if (ok)
+ {
+ if (bottomItem == -1 && contact->type == CLCIT_GROUP)
+ {
+ bottomItem = topItem+1;
+ }
+ else
+ {
+ if (bottomItem == -1 && contact->type != CLCIT_GROUP && contact->groupId == 0)
+ {
+ if (contact->type != CLCIT_GROUP && contact->groupId == 0)
+ {
+ bottomItem = topItem;
+ cliGetRowByIndex(dat,bottomItem,&bottomcontact,&bottomgroup);
+ }
+ }
+ if (bottomItem != -1 && bottomcontact->type != CLCIT_GROUP)
+ {
+ struct ClcGroup * gr = bottomgroup;
+ do
+ {
+ bottomItem = cliGetRowByIndex(dat,bottomItem-1,&bottomcontact,&bottomgroup);}
+ while (bottomItem >= 0 && bottomcontact->type != CLCIT_GROUP && bottomgroup == gr);
+ nSetSelection = bottomItem;
+ bottomItem = cliGetRowByIndex(dat,bottomItem+1,&bottomcontact,&bottomgroup);
+ }
+ }
+
+ if (bottomItem == -1) bottomItem = topItem+1;
+ {
+ int bi = cliGetRowByIndex(dat,bottomItem,&bottomcontact,&bottomgroup);
+ if (bi != -1)
+ {
+ group = bottomgroup;
+ if (bottomcontact == movecontact || group == movecontact->group) return DROPTARGET_ONSELF;
+ dat->nInsertionLevel = -1; // decreasing here
+ for (;group;group = group->parent)
+ {
+ dat->nInsertionLevel++;
+ if (group == movecontact->group) return DROPTARGET_ONSELF;
+ }
+ }
+ }
+ dat->iInsertionMark = bottomItem;
+ dat->selection = nSetSelection;
+ return DROPTARGET_INSERTION;
+ }
+ }
+ if (contact->type == CLCIT_GROUP)
+ {
+ if (dat->iInsertionMark == -1)
+ {
+ if (movecontact->type == CLCIT_GROUP)
+ { //check not moving onto its own subgroup
+ dat->iInsertionMark = hit+1;
+ for (;group;group = group->parent)
+ {
+ dat->nInsertionLevel++;
+ if (group == movecontact->group) return DROPTARGET_ONSELF;
+ }
+ }
+ dat->selection = hit;
+ return DROPTARGET_ONGROUP;
+ }
+ }
+ dat->selection = hit;
+
+ if (g_szMetaModuleName && !mir_strcmp(contact->proto,g_szMetaModuleName) && (ServiceExists(MS_MC_ADDTOMETA))) return DROPTARGET_ONMETACONTACT;
+ if (contact->isSubcontact && (ServiceExists(MS_MC_ADDTOMETA))) return DROPTARGET_ONSUBCONTACT;
+ return DROPTARGET_ONCONTACT;
+}
+COLORREF sttGetColor(char * module, char * color, COLORREF defColor)
+{
+ BOOL useWinColor = db_get_b(NULL, module, "UseWinColours",CLCDEFAULT_USEWINDOWSCOLOURS);
+ if (useWinColor) return defColor;
+ else return db_get_dw(NULL, module, color, defColor);
+}
+void RegisterCLUIFonts( void );
+void LoadCLCFonts( HWND hwnd, struct ClcData *dat )
+{
+ RegisterCLUIFonts();
+
+ HDC hdc = GetDC(hwnd);
+ HFONT holdfont = (HFONT)GetCurrentObject( hdc, OBJ_FONT );
+
+ for ( int i=0 ; i <= FONTID_MODERN_MAX; i++ )
+ {
+ if ( !dat->fontModernInfo[i].changed && dat->fontModernInfo[i].hFont )
+ {
+ DeleteObject(dat->fontModernInfo[i].hFont);
+ }
+ LOGFONT lf;
+
+ // Issue 40: Do not reload font colors for embedded clists
+ // Parent window is responsible to re-set fonts colors if needed
+ GetFontSetting( i, &lf, dat->force_in_dialog ? NULL: &dat->fontModernInfo[i].colour, &dat->fontModernInfo[i].effect, &dat->fontModernInfo[i].effectColour1, &dat->fontModernInfo[i].effectColour2 );
+ dat->fontModernInfo[i].hFont = CreateFontIndirect( &lf );
+ dat->fontModernInfo[i].changed = 0;
+
+ SelectObject( hdc, dat->fontModernInfo[i].hFont );
+ SIZE fontSize;
+ GetTextExtentPoint32A( hdc, "x", 1, &fontSize );
+ dat->fontModernInfo[i].fontHeight = fontSize.cy;
+ }
+ SelectObject( hdc, holdfont );
+ ReleaseDC( hwnd, hdc );
+}
+
+void LoadCLCOptions(HWND hwnd, struct ClcData *dat )
+{
+ int i;
+
+ g_CluiData.fDisableSkinEngine = db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT);
+
+ LoadCLCFonts( hwnd, dat );
+
+ g_CluiData.bSortByOrder[0] = db_get_b(NULL,"CList","SortBy1",SETTING_SORTBY1_DEFAULT);
+ g_CluiData.bSortByOrder[1] = db_get_b(NULL,"CList","SortBy2",SETTING_SORTBY2_DEFAULT);
+ g_CluiData.bSortByOrder[2] = db_get_b(NULL,"CList","SortBy3",SETTING_SORTBY3_DEFAULT);
+ g_CluiData.fSortNoOfflineBottom = db_get_b(NULL,"CList","NoOfflineBottom",SETTING_NOOFFLINEBOTTOM_DEFAULT);
+
+ // Row
+ dat->row_min_heigh = db_get_w(NULL,"CList","MinRowHeight",CLCDEFAULT_ROWHEIGHT);
+ dat->row_border = db_get_w(NULL,"CList","RowBorder",SETTING_ROWBORDER_DEFAULT);
+ dat->row_before_group_space = ((hwnd != pcli->hwndContactTree && pcli->hwndContactTree != NULL)
+ || !db_get_b(NULL,"ModernData","UseAdvancedRowLayout",SETTING_ROW_ADVANCEDLAYOUT_DEFAULT))?0:db_get_w(NULL,"ModernSkin","SpaceBeforeGroup",SKIN_SPACEBEFOREGROUP_DEFAULT);
+ dat->row_variable_height = db_get_b(NULL,"CList","VariableRowHeight",SETTING_VARIABLEROWHEIGHT_DEFAULT);
+ dat->row_align_left_items_to_left = db_get_b(NULL,"CList","AlignLeftItemsToLeft",SETTING_ALIGNLEFTTOLEFT_DEFAULT);
+ dat->row_hide_group_icon = db_get_b(NULL,"CList","HideGroupsIcon",SETTING_HIDEGROUPSICON_DEFAULT);
+ dat->row_align_right_items_to_right = db_get_b(NULL,"CList","AlignRightItemsToRight",SETTING_ALIGNRIGHTORIGHT_DEFAULT);
+ //TODO: Add to settings
+ dat->row_align_group_mode = db_get_b(NULL,"CList","AlignGroupCaptions",SETTING_ALIGNGROPCAPTION_DEFAULT);
+ if (pcli->hwndContactTree == NULL || dat->hWnd == pcli->hwndContactTree)
+ {
+
+ int defItemsOrder[NUM_ITEM_TYPE] = SETTINS_ROWITEMORDER_DEFAULT;
+ for (i=0 ; i < NUM_ITEM_TYPE ; i++)
+ {
+ char tmp[128];
+ mir_snprintf(tmp, SIZEOF(tmp), "RowPos%d", i);
+ dat->row_items[i] = db_get_w(NULL, "CList", tmp, defItemsOrder[i]);
+ }
+ }
+ else
+ {
+ int defItems[] = {ITEM_ICON, ITEM_TEXT, ITEM_EXTRA_ICONS,};
+ for (i=0 ; i < NUM_ITEM_TYPE; i++)
+ dat->row_items[i] = (i < SIZEOF(defItems)) ? defItems[i] : -1;
+ }
+
+ // Avatar
+ if (pcli->hwndContactTree == hwnd || pcli->hwndContactTree == NULL)
+ {
+ dat->avatars_show = db_get_b(NULL,"CList","AvatarsShow",SETTINGS_SHOWAVATARS_DEFAULT);
+ dat->avatars_draw_border = db_get_b(NULL,"CList","AvatarsDrawBorders",SETTINGS_AVATARDRAWBORDER_DEFAULT);
+ dat->avatars_border_color = (COLORREF)db_get_dw(NULL,"CList","AvatarsBorderColor",SETTINGS_AVATARBORDERCOLOR_DEFAULT);
+ dat->avatars_round_corners = db_get_b(NULL,"CList","AvatarsRoundCorners",SETTINGS_AVATARROUNDCORNERS_DEFAULT);
+ dat->avatars_use_custom_corner_size = db_get_b(NULL,"CList","AvatarsUseCustomCornerSize",SETTINGS_AVATARUSECUTOMCORNERSIZE_DEFAULT);
+ dat->avatars_custom_corner_size = db_get_w(NULL,"CList","AvatarsCustomCornerSize",SETTINGS_AVATARCORNERSIZE_DEFAULT);
+ dat->avatars_ignore_size_for_row_height = db_get_b(NULL,"CList","AvatarsIgnoreSizeForRow",SETTINGS_AVATARIGNORESIZEFORROW_DEFAULT);
+ dat->avatars_draw_overlay = db_get_b(NULL,"CList","AvatarsDrawOverlay",SETTINGS_AVATARDRAWOVERLAY_DEFAULT);
+ dat->avatars_overlay_type = db_get_b(NULL,"CList","AvatarsOverlayType",SETTINGS_AVATAROVERLAYTYPE_DEFAULT);
+ dat->avatars_maxheight_size = db_get_w(NULL,"CList","AvatarsSize",SETTING_AVATARHEIGHT_DEFAULT);
+ dat->avatars_maxwidth_size = db_get_w(NULL,"CList","AvatarsWidth",SETTING_AVATARWIDTH_DEFAULT);
+ }
+ else
+ {
+ dat->avatars_show = 0;
+ dat->avatars_draw_border = 0;
+ dat->avatars_border_color = 0;
+ dat->avatars_round_corners = 0;
+ dat->avatars_use_custom_corner_size = 0;
+ dat->avatars_custom_corner_size = 4;
+ dat->avatars_ignore_size_for_row_height = 0;
+ dat->avatars_draw_overlay = 0;
+ dat->avatars_overlay_type = SETTING_AVATAR_OVERLAY_TYPE_NORMAL;
+ dat->avatars_maxheight_size = 30;
+ dat->avatars_maxwidth_size = 0;
+ }
+
+ // Icon
+ if (pcli->hwndContactTree == hwnd || pcli->hwndContactTree == NULL)
+ {
+ dat->icon_hide_on_avatar = db_get_b(NULL,"CList","IconHideOnAvatar",SETTING_HIDEICONONAVATAR_DEFAULT);
+ dat->icon_draw_on_avatar_space = db_get_b(NULL,"CList","IconDrawOnAvatarSpace",SETTING_ICONONAVATARPLACE_DEFAULT);
+ dat->icon_ignore_size_for_row_height = db_get_b(NULL,"CList","IconIgnoreSizeForRownHeight",SETTING_ICONIGNORESIZE_DEFAULT);
+ }
+ else
+ {
+ dat->icon_hide_on_avatar = 0;
+ dat->icon_draw_on_avatar_space = 0;
+ dat->icon_ignore_size_for_row_height = 0;
+ }
+
+ // Contact time
+ if (pcli->hwndContactTree == hwnd || pcli->hwndContactTree == NULL)
+ {
+ dat->contact_time_show = db_get_b(NULL,"CList","ContactTimeShow",SETTING_SHOWTIME_DEFAULT);
+ dat->contact_time_show_only_if_different = db_get_b(NULL,"CList","ContactTimeShowOnlyIfDifferent",SETTING_SHOWTIMEIFDIFF_DEFAULT);
+ }
+ else
+ {
+ dat->contact_time_show = 0;
+ dat->contact_time_show_only_if_different = 0;
+ }
+
+ // Text
+ dat->text_rtl = db_get_b(NULL,"CList","TextRTL",SETTING_TEXT_RTL_DEFAULT);
+ dat->text_align_right = db_get_b(NULL,"CList","TextAlignToRight",SETTING_TEXT_RIGHTALIGN_DEFAULT);
+ dat->text_replace_smileys = db_get_b(NULL,"CList","TextReplaceSmileys",SETTING_TEXT_SMILEY_DEFAULT);
+ dat->text_resize_smileys = db_get_b(NULL,"CList","TextResizeSmileys",SETTING_TEXT_RESIZESMILEY_DEFAULT);
+ dat->text_smiley_height = 0;
+ dat->text_use_protocol_smileys = db_get_b(NULL,"CList","TextUseProtocolSmileys",SETTING_TEXT_PROTOSMILEY_DEFAULT);
+
+ if (pcli->hwndContactTree == hwnd || pcli->hwndContactTree == NULL)
+ {
+ dat->text_ignore_size_for_row_height = db_get_b(NULL,"CList","TextIgnoreSizeForRownHeight",SETTING_TEXT_IGNORESIZE_DEFAULT);
+ }
+ else
+ {
+ dat->text_ignore_size_for_row_height = 0;
+ }
+
+ // First line
+ dat->first_line_draw_smileys = db_get_b(NULL,"CList","FirstLineDrawSmileys",SETTING_FIRSTLINE_SMILEYS_DEFAULT);
+ dat->first_line_append_nick = db_get_b(NULL,"CList","FirstLineAppendNick",SETTING_FIRSTLINE_APPENDNICK_DEFAULT);
+ gl_TrimText = db_get_b(NULL,"CList","TrimText",SETTING_FIRSTLINE_TRIMTEXT_DEFAULT);
+
+ // Second line
+ if (pcli->hwndContactTree == hwnd || pcli->hwndContactTree == NULL)
+ {
+ dat->second_line_show = db_get_b(NULL,"CList","SecondLineShow",SETTING_SECONDLINE_SHOW_DEFAULT);
+ dat->second_line_top_space = db_get_w(NULL,"CList","SecondLineTopSpace",SETTING_SECONDLINE_TOPSPACE_DEFAULT);
+ dat->second_line_draw_smileys = db_get_b(NULL,"CList","SecondLineDrawSmileys",SETTING_SECONDLINE_SMILEYS_DEFAULT);
+ dat->second_line_type = db_get_w(NULL,"CList","SecondLineType",SETTING_SECONDLINE_TYPE_DEFAULT);
+ {
+ DBVARIANT dbv = {0};
+
+ if ( !DBGetContactSettingTString(NULL, "CList","SecondLineText", &dbv))
+ {
+ lstrcpyn(dat->second_line_text, dbv.ptszVal, SIZEOF(dat->second_line_text)-1);
+ dat->second_line_text[SIZEOF(dat->second_line_text)-1] = _T('\0');
+ db_free(&dbv);
+ }
+ else
+ {
+ dat->second_line_text[0] = _T('\0');
+ }
+ }
+ dat->second_line_xstatus_has_priority = db_get_b(NULL,"CList","SecondLineXStatusHasPriority",SETTING_SECONDLINE_XSTATUS_DEFAULT);
+ dat->second_line_show_status_if_no_away = db_get_b(NULL,"CList","SecondLineShowStatusIfNoAway",SETTING_SECONDLINE_STATUSIFNOAWAY_DEFAULT);
+ dat->second_line_show_listening_if_no_away = db_get_b(NULL,"CList","SecondLineShowListeningIfNoAway",SETTING_SECONDLINE_LISTENINGIFNOAWAY_DEFAULT);
+ dat->second_line_use_name_and_message_for_xstatus = db_get_b(NULL,"CList","SecondLineUseNameAndMessageForXStatus",SETTING_SECONDLINE_XSTATUSNAMETEXT_DEFAULT);
+ }
+ else
+ {
+ dat->second_line_show = 0;
+ dat->second_line_top_space = 0;
+ dat->second_line_draw_smileys = 0;
+ dat->second_line_type = 0;
+ dat->second_line_text[0] = _T('\0');
+ dat->second_line_xstatus_has_priority = 0;
+ dat->second_line_use_name_and_message_for_xstatus = 0;
+ }
+
+
+ // Third line
+ if (pcli->hwndContactTree == hwnd || pcli->hwndContactTree == NULL)
+ {
+ dat->third_line_show = db_get_b(NULL,"CList","ThirdLineShow",SETTING_THIRDLINE_SHOW_DEFAULT);
+ dat->third_line_top_space = db_get_w(NULL,"CList","ThirdLineTopSpace",SETTING_THIRDLINE_TOPSPACE_DEFAULT);
+ dat->third_line_draw_smileys = db_get_b(NULL,"CList","ThirdLineDrawSmileys",SETTING_THIRDLINE_SMILEYS_DEFAULT);
+ dat->third_line_type = db_get_w(NULL,"CList","ThirdLineType",SETTING_THIRDLINE_TYPE_DEFAULT);
+ {
+ DBVARIANT dbv = {0};
+
+ if ( !DBGetContactSettingTString(NULL, "CList","ThirdLineText", &dbv))
+ {
+ lstrcpyn(dat->third_line_text, dbv.ptszVal, SIZEOF(dat->third_line_text)-1);
+ dat->third_line_text[SIZEOF(dat->third_line_text)-1] = _T('\0');
+ db_free(&dbv);
+ }
+ else
+ {
+ dat->third_line_text[0] = _T('\0');
+ }
+ }
+ dat->third_line_xstatus_has_priority = db_get_b(NULL,"CList","ThirdLineXStatusHasPriority",SETTING_THIRDLINE_XSTATUS_DEFAULT);
+ dat->third_line_show_status_if_no_away = db_get_b(NULL,"CList","ThirdLineShowStatusIfNoAway",SETTING_THIRDLINE_STATUSIFNOAWAY_DEFAULT);
+ dat->third_line_show_listening_if_no_away = db_get_b(NULL,"CList","ThirdLineShowListeningIfNoAway",SETTING_THIRDLINE_LISTENINGIFNOAWAY_DEFAULT);
+ dat->third_line_use_name_and_message_for_xstatus = db_get_b(NULL,"CList","ThirdLineUseNameAndMessageForXStatus",SETTING_THIRDLINE_XSTATUSNAMETEXT_DEFAULT);
+ }
+ else
+ {
+ dat->third_line_show = 0;
+ dat->third_line_top_space = 0;
+ dat->third_line_draw_smileys = 0;
+ dat->third_line_type = TEXT_STATUS_MESSAGE;
+ dat->third_line_text[0] = _T('\0');
+ dat->third_line_xstatus_has_priority = 1;
+ dat->third_line_use_name_and_message_for_xstatus = 0;
+ }
+
+ dat->leftMargin = db_get_b(NULL,"CLC","LeftMargin",CLCDEFAULT_LEFTMARGIN);
+ dat->rightMargin = db_get_b(NULL,"CLC","RightMargin",CLCDEFAULT_RIGHTMARGIN);
+ dat->exStyle = db_get_dw(NULL,"CLC","ExStyle",GetDefaultExStyle());
+ dat->scrollTime = db_get_w(NULL,"CLC","ScrollTime",CLCDEFAULT_SCROLLTIME);
+ dat->force_in_dialog = (pcli->hwndContactTree)?(hwnd != pcli->hwndContactTree):0;
+ dat->groupIndent = db_get_b(NULL,"CLC","GroupIndent",CLCDEFAULT_GROUPINDENT);
+ dat->subIndent = db_get_b(NULL,"CLC","SubIndent",CLCDEFAULT_GROUPINDENT);
+ dat->gammaCorrection = db_get_b(NULL,"CLC","GammaCorrect",CLCDEFAULT_GAMMACORRECT);
+ dat->showIdle = db_get_b(NULL,"CLC","ShowIdle",CLCDEFAULT_SHOWIDLE);
+ dat->noVScrollbar = db_get_b(NULL,"CLC","NoVScrollBar",CLCDEFAULT_NOVSCROLL);
+ SendMessage(hwnd,INTM_SCROLLBARCHANGED,0,0);
+
+ if (dat->hBmpBackground) {DeleteObject(dat->hBmpBackground); dat->hBmpBackground = NULL;}
+ if (dat->hMenuBackground) {DeleteObject(dat->hMenuBackground); dat->hMenuBackground = NULL;}
+
+ dat->useWindowsColours = db_get_b(NULL, "CLC", "UseWinColours", CLCDEFAULT_USEWINDOWSCOLOURS);
+
+ if (g_CluiData.fDisableSkinEngine)
+ {
+ DBVARIANT dbv;
+ if ( !dat->bkChanged)
+ {
+ dat->bkColour = sttGetColor("CLC","BkColour",GetSysColor(COLOR_3DFACE));
+ {
+ if (db_get_b(NULL,"CLC","UseBitmap",CLCDEFAULT_USEBITMAP))
+ {
+ if ( !DBGetContactSettingString(NULL,"CLC","BkBitmap",&dbv))
+ {
+ dat->hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ }
+ }
+ dat->backgroundBmpUse = db_get_w(NULL,"CLC","BkBmpUse",CLCDEFAULT_BKBMPUSE);
+ }
+ dat->MenuBkColor = sttGetColor("Menu","BkColour",CLCDEFAULT_BKCOLOUR);
+ dat->MenuBkHiColor = sttGetColor("Menu","SelBkColour",CLCDEFAULT_SELBKCOLOUR);
+
+ dat->MenuTextColor = sttGetColor("Menu","TextColour",CLCDEFAULT_TEXTCOLOUR);
+ dat->MenuTextHiColor = sttGetColor("Menu","SelTextColour",CLCDEFAULT_MODERN_SELTEXTCOLOUR);
+
+ if (db_get_b(NULL,"Menu","UseBitmap",CLCDEFAULT_USEBITMAP)) {
+ if ( !DBGetContactSettingString(NULL,"Menu","BkBitmap",&dbv)) {
+ dat->hMenuBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ }
+ dat->MenuBmpUse = db_get_w(NULL,"Menu","BkBmpUse",CLCDEFAULT_BKBMPUSE);
+ }
+
+ dat->greyoutFlags = db_get_dw(NULL,"CLC","GreyoutFlags",CLCDEFAULT_GREYOUTFLAGS);
+ dat->offlineModes = db_get_dw(NULL,"CLC","OfflineModes",CLCDEFAULT_OFFLINEMODES);
+ dat->selBkColour = sttGetColor("CLC","SelBkColour",CLCDEFAULT_SELBKCOLOUR);
+ dat->selTextColour = db_get_dw(NULL,"CLC","SelTextColour",CLCDEFAULT_MODERN_SELTEXTCOLOUR);
+ dat->hotTextColour = db_get_dw(NULL,"CLC","HotTextColour",CLCDEFAULT_MODERN_HOTTEXTCOLOUR);
+ dat->quickSearchColour = db_get_dw(NULL,"CLC","QuickSearchColour",CLCDEFAULT_MODERN_QUICKSEARCHCOLOUR);
+ if ( !g_szMetaModuleName && ServiceExists(MS_MC_GETPROTOCOLNAME)) g_szMetaModuleName = (char *)CallService(MS_MC_GETPROTOCOLNAME, 0, 0);
+ dat->IsMetaContactsEnabled = (!(GetWindowLongPtr(hwnd,GWL_STYLE)&CLS_MANUALUPDATE)) &&
+ g_szMetaModuleName && db_get_b(NULL,g_szMetaModuleName,"Enabled",1) && ServiceExists(MS_MC_GETDEFAULTCONTACT);
+
+ if (pcli->hwndContactTree == NULL || dat->hWnd == pcli->hwndContactTree)
+ dat->MetaIgnoreEmptyExtra = db_get_b(NULL,"CLC","MetaIgnoreEmptyExtra",SETTING_METAIGNOREEMPTYEXTRA_DEFAULT);
+ else
+ dat->MetaIgnoreEmptyExtra = FALSE;
+
+ dat->expandMeta = db_get_b(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT);
+ dat->useMetaIcon = db_get_b(NULL,"CLC","Meta",SETTING_USEMETAICON_DEFAULT);
+
+ dat->drawOverlayedStatus = db_get_b(NULL,"CLC","DrawOverlayedStatus",SETTING_DRAWOVERLAYEDSTATUS_DEFAULT);
+
+ dat->dbbMetaHideExtra = db_get_b(NULL,"CLC","MetaHideExtra",SETTING_METAHIDEEXTRA_DEFAULT);
+ dat->dbbBlendInActiveState = db_get_b(NULL,"CLC","BlendInActiveState",SETTING_BLENDINACTIVESTATE_DEFAULT);
+ dat->dbbBlend25 = db_get_b(NULL,"CLC","Blend25%",SETTING_BLENDINACTIVESTATE_DEFAULT);
+ dat->bCompactMode = db_get_b(NULL,"CLC","CompactMode",SETTING_COMPACTMODE_DEFAULT);
+ if ((pcli->hwndContactTree == hwnd || pcli->hwndContactTree == NULL))
+ {
+ IvalidateDisplayNameCache(16);
+
+ }
+
+ {
+ NMHDR hdr;
+ hdr.code = CLN_OPTIONSCHANGED;
+ hdr.hwndFrom = hwnd;
+ hdr.idFrom = 0;//GetDlgCtrlID(hwnd);
+ SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&hdr);
+ }
+ SendMessage(hwnd,WM_SIZE,0,0);
+
+}
+
+int ExpandMetaContact(HWND hwnd, struct ClcContact * contact, struct ClcData * dat, BOOL bExpand)
+{
+ struct ClcContact * ht = NULL;
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ if (contact->type != CLCIT_CONTACT || contact->SubAllocated == 0 || contact->SubExpanded == bExpand || !db_get_b(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT)) return 0;
+ contact->SubExpanded = bExpand;
+ db_set_b(contact->hContact,"CList","Expanded",contact->SubExpanded);
+ dat->NeedResort = 1;
+ pcli->pfnSortCLC(hwnd,dat,1);
+ cliRecalcScrollBar(hwnd,dat);
+ return contact->SubExpanded;
+}
+
+int cliFindRowByText(HWND hwnd, struct ClcData *dat, const TCHAR *text, int prefixOk)
+{
+ struct ClcGroup *group = &dat->list;
+ int testlen = lstrlen(text);
+ struct ClcContact *contact = NULL;
+ int SubCount = 0;
+
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL)
+ break;
+ group->scanIndex++;
+ continue;
+ }
+ contact = group->cl.items[group->scanIndex];
+ if (contact->type != CLCIT_DIVIDER)
+ {
+ if ((prefixOk && !_tcsnicmp(text, contact->szText, testlen)) ||
+ (!prefixOk && !lstrcmpi(text, contact->szText)))
+ {
+ struct ClcGroup *contactGroup = group;
+ int contactScanIndex = group->scanIndex;
+ for (; group; group = group->parent)
+ pcli->pfnSetGroupExpand(hwnd, dat, group, 1);
+ return pcli->pfnGetRowsPriorTo(&dat->list, contactGroup, contactScanIndex+SubCount);
+ }
+ if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP)
+ {
+ if ( !(dat->exStyle & CLS_EX_QUICKSEARCHVISONLY) || group->cl.items[group->scanIndex]->group->expanded) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ SubCount = 0;
+ continue;
+ }
+ }
+ }
+ if (contact->type == CLCIT_CONTACT && contact->SubAllocated)
+ {
+ if ( !(dat->exStyle & CLS_EX_QUICKSEARCHVISONLY) || contact->SubExpanded )
+ {
+ int i=0;
+ for (i=0; i < contact->SubAllocated; i++)
+ {
+ struct ClcContact * subcontact = &(contact->subcontacts[i]);
+ if ((prefixOk && !_tcsnicmp(text, subcontact->szText, testlen)) ||
+ (!prefixOk && !lstrcmpi(text, subcontact->szText)))
+ {
+ struct ClcGroup *contactGroup = group;
+ int contactScanIndex = group->scanIndex;
+ for (; group; group = group->parent)
+ pcli->pfnSetGroupExpand(hwnd, dat, group, 1);
+ if ( !contact->SubExpanded)
+ ExpandMetaContact(hwnd, contact, dat, 1 );
+ return pcli->pfnGetRowsPriorTo(&dat->list, contactGroup, contactScanIndex+SubCount+i+1);
+ }
+ }
+ }
+ }
+ if (contact->type == CLCIT_CONTACT && contact->SubAllocated && contact->SubExpanded)
+ SubCount += contact->SubAllocated;
+ group->scanIndex++;
+ }
+ return -1;
+} \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_clistevents.cpp b/plugins/Clist_modern/src/modern_clistevents.cpp
new file mode 100644
index 0000000000..4453329c66
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clistevents.cpp
@@ -0,0 +1,624 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2003 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 "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "./hdr/modern_cluiframes.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_clcpaint.h"
+
+/**************************************************/
+/* Notify Event Area Frame implementation */
+/**************************************************/
+
+/* Declarations */
+static HANDLE hNotifyFrame = NULL;
+static int EventArea_PaintCallbackProc(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData);
+static int EventArea_Draw(HWND hwnd, HDC hDC);
+static int EventArea_DrawWorker(HWND hwnd, HDC hDC);
+static void EventArea_HideShowNotifyFrame();
+static LRESULT CALLBACK EventArea_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+int EventArea_Create(HWND hCluiWnd);
+int EventArea_UnloadModule();
+void EventArea_ConfigureEventArea();
+
+/**************************************************/
+
+HWND g_hwndEventArea = 0;
+
+struct CListEvent {
+ int imlIconIndex;
+ int flashesDone;
+ CLISTEVENT cle;
+
+ int menuId;
+ int imlIconOverlayIndex;
+};
+
+static struct CListEvent *event;
+static int eventCount;
+static int disableTrayFlash;
+static int disableIconFlash;
+
+
+struct CListImlIcon {
+ int index;
+ HICON hIcon;
+};
+
+static struct CListImlIcon *imlIcon;
+static int imlIconCount;
+static UINT flashTimerId;
+static int iconsOn;
+
+
+struct NotifyMenuItemExData {
+ HANDLE hContact;
+ int iIcon; // icon index in the image list
+ HICON hIcon; // corresponding icon handle
+ HANDLE hDbEvent;
+};
+
+static CLISTEVENT* MyGetEvent(int iSelection)
+{
+ int i;
+
+ for (i=0; i < pcli->events.count; i++) {
+ struct CListEvent* p = pcli->events.items[i];
+ if (p->menuId == iSelection)
+ return &p->cle;
+ }
+ return NULL;
+}
+
+
+CListEvent* cliCreateEvent( void )
+{
+ CListEvent *p = (CListEvent *)mir_calloc(sizeof(CListEvent));
+ return p;
+}
+
+struct CListEvent* cli_AddEvent(CLISTEVENT *cle)
+{
+ struct CListEvent* p = corecli.pfnAddEvent(cle);
+ if ( p == NULL )
+ return NULL;
+
+ if (1) {
+ if (p->cle.hContact != 0 && p->cle.hDbEvent != (HANDLE) 1 && !(p->cle.flags & CLEF_ONLYAFEW)) {
+ int j;
+ struct NotifyMenuItemExData *nmi = 0;
+ char *szProto;
+ TCHAR *szName;
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA | MIIM_BITMAP | MIIM_ID;
+ if (p->cle.pszService && ( !strncmp("SRMsg/ReadMessage", p->cle.pszService, SIZEOF("SRMsg/ReadMessage"))
+ || !strncmp("GChat/DblClickEvent", p->cle.pszService, SIZEOF("GChat/DblClickEvent"))))
+
+ {
+ // dup check only for msg events
+ for (j = 0; j < GetMenuItemCount(g_CluiData.hMenuNotify); j++) {
+ if (GetMenuItemInfo(g_CluiData.hMenuNotify, j, TRUE, &mii) != 0) {
+ nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
+ if (nmi != 0 && (HANDLE) nmi->hContact == (HANDLE) p->cle.hContact && nmi->iIcon == p->imlIconIndex)
+ return p;
+ } } }
+
+ szProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) p->cle.hContact, 0);
+ szName = pcli->pfnGetContactDisplayName(p->cle.hContact, 0);
+ if (szProto && szName) {
+ nmi = (struct NotifyMenuItemExData *) malloc(sizeof(struct NotifyMenuItemExData));
+ if (nmi) {
+ TCHAR szBuffer[128];
+ TCHAR* szStatus = pcli->pfnGetStatusModeDescription(db_get_w(p->cle.hContact, szProto, "Status", ID_STATUS_OFFLINE), 0);
+ TCHAR szwProto[64];
+ MultiByteToWideChar(CP_ACP, 0, szProto, -1, szwProto, 64);
+ szwProto[63] = 0;
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s: %s (%s)"), szwProto, szName, szStatus);
+ szBuffer[127] = 0;
+ AppendMenu(g_CluiData.hMenuNotify, MF_BYCOMMAND | MF_STRING, g_CluiData.wNextMenuID, szBuffer);
+ mii.hbmpItem = HBMMENU_CALLBACK;
+ nmi->hContact = p->cle.hContact;
+ nmi->iIcon = p->imlIconIndex;
+ nmi->hIcon = p->cle.hIcon;
+ nmi->hDbEvent = p->cle.hDbEvent;
+ mii.dwItemData = (ULONG_PTR) nmi;
+ mii.wID = g_CluiData.wNextMenuID;
+ SetMenuItemInfo(g_CluiData.hMenuNotify, g_CluiData.wNextMenuID, FALSE, &mii);
+ p-> menuId = g_CluiData.wNextMenuID;
+ g_CluiData.wNextMenuID++;
+ if (g_CluiData.wNextMenuID > 0x7fff)
+ g_CluiData.wNextMenuID = 1;
+ g_CluiData.iIconNotify = p->imlIconIndex;
+ }
+ }
+ }
+
+ else if (p->cle.hContact != 0 && (p->cle.flags & CLEF_ONLYAFEW))
+ {
+ g_CluiData.iIconNotify = p->imlIconIndex;
+ g_CluiData.hUpdateContact = p->cle.hContact;
+ }
+ if (pcli->events.count > 0) {
+ g_CluiData.bEventAreaEnabled = TRUE;
+ if (g_CluiData.bNotifyActive == FALSE) {
+ g_CluiData.bNotifyActive = TRUE;
+ EventArea_HideShowNotifyFrame();
+ }
+ }
+ CLUI__cliInvalidateRect(g_CluiData.hwndEventFrame, NULL, FALSE);
+ }
+
+ return p;
+}
+
+
+int cli_RemoveEvent(HANDLE hContact, HANDLE hDbEvent)
+{
+ int i;
+ int res = 0;
+
+ // Find the event that should be removed
+ for (i=0; i < pcli->events.count; i++)
+ {
+ if ((pcli->events.items[i]->cle.hContact == hContact) && (pcli->events.items[i]->cle.hDbEvent == hDbEvent))
+ {
+ break;
+ }
+ }
+
+ // Event was not found
+ if (i == pcli->events.count)
+ return 1;
+
+ // remove event from the notify menu
+ if (1)
+ {
+ if (pcli->events.items[i]->menuId > 0)
+ {
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA;
+ if (GetMenuItemInfo(g_CluiData.hMenuNotify, pcli->events.items[i]->menuId, FALSE, &mii) != 0)
+ {
+ struct NotifyMenuItemExData *nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
+ if (nmi && nmi->hContact == hContact && nmi->hDbEvent == hDbEvent)
+ {
+ free(nmi);
+ DeleteMenu(g_CluiData.hMenuNotify, pcli->events.items[i]->menuId, MF_BYCOMMAND);
+ }
+ }
+ }
+ }
+
+ res = corecli.pfnRemoveEvent(hContact, hDbEvent);
+
+ if (pcli->events.count == 0)
+ {
+ g_CluiData.bNotifyActive = FALSE;
+ EventArea_HideShowNotifyFrame();
+ }
+
+ if (hContact == g_CluiData.hUpdateContact || (INT_PTR)hDbEvent == 1)
+ g_CluiData.hUpdateContact = 0;
+ CLUI__cliInvalidateRect(g_CluiData.hwndEventFrame, NULL, FALSE);
+ return res;
+}
+
+
+/* Implementations */
+
+struct event_area_t
+{
+ HBITMAP hBmpBackground;
+ COLORREF bkColour;
+ int useWinColors;
+ int backgroundBmpUse;
+
+ event_area_t():
+ hBmpBackground( NULL),
+ bkColour( CLCDEFAULT_BKCOLOUR ),
+ useWinColors( CLCDEFAULT_USEWINDOWSCOLOURS ),
+ backgroundBmpUse( CLCDEFAULT_USEBITMAP )
+ {}
+};
+
+static event_area_t event_area;
+
+static BOOL sttDrawEventAreaBackground(HWND hwnd, HDC hdc, RECT * rect)
+{
+ BOOL bFloat = (GetParent(hwnd) != pcli->hwndContactList);
+ if (g_CluiData.fDisableSkinEngine || !g_CluiData.fLayered || bFloat)
+ {
+ RECT rc;
+
+ if (rect) rc = *rect;
+ else GetClientRect(hwnd,&rc);
+
+ if ( !event_area.hBmpBackground && !event_area.useWinColors)
+ {
+ HBRUSH hbr = CreateSolidBrush(event_area.bkColour);
+ FillRect(hdc, &rc, hbr);
+ DeleteObject(hbr);
+ }
+ else
+ {
+ DrawBackGround(hwnd,hdc,event_area.hBmpBackground,event_area.bkColour,event_area.backgroundBmpUse);
+ }
+ }
+ return TRUE;
+}
+
+COLORREF sttGetColor(char * module, char * color, COLORREF defColor); //clcutils
+
+static int ehhEventAreaBackgroundSettingsChanged(WPARAM wParam, LPARAM lParam)
+{
+ if (event_area.hBmpBackground)
+ {
+ DeleteObject(event_area.hBmpBackground);
+ event_area.hBmpBackground = NULL;
+ }
+ if (g_CluiData.fDisableSkinEngine)
+ {
+ DBVARIANT dbv;
+ event_area.bkColour = sttGetColor("EventArea","BkColour",CLCDEFAULT_BKCOLOUR);
+ if (db_get_b(NULL,"EventArea","UseBitmap",CLCDEFAULT_USEBITMAP)) {
+ if ( !DBGetContactSettingString(NULL,"EventArea","BkBitmap",&dbv)) {
+ event_area.hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ }
+ event_area.useWinColors = db_get_b(NULL, "EventArea", "UseWinColours", CLCDEFAULT_USEWINDOWSCOLOURS);
+ event_area.backgroundBmpUse = db_get_w(NULL, "EventArea", "BkBmpUse", CLCDEFAULT_BKBMPUSE);
+ }
+ PostMessage(pcli->hwndContactList,WM_SIZE,0,0);
+ return 0;
+}
+
+void EventArea_ConfigureEventArea()
+{
+ int iCount = pcli->events.count;
+
+ g_CluiData.dwFlags &= ~(CLUI_FRAME_AUTOHIDENOTIFY|CLUI_FRAME_SHOWALWAYS);
+ if (db_get_b(NULL,"CLUI","EventArea",SETTING_EVENTAREAMODE_DEFAULT) == 1) g_CluiData.dwFlags |= CLUI_FRAME_AUTOHIDENOTIFY;
+ if (db_get_b(NULL,"CLUI","EventArea",SETTING_EVENTAREAMODE_DEFAULT) == 2) g_CluiData.dwFlags |= CLUI_FRAME_SHOWALWAYS;
+
+ if (g_CluiData.dwFlags & CLUI_FRAME_SHOWALWAYS)
+ g_CluiData.bNotifyActive = 1;
+ else if (g_CluiData.dwFlags & CLUI_FRAME_AUTOHIDENOTIFY)
+ g_CluiData.bNotifyActive = iCount > 0 ? 1 : 0;
+ else
+ g_CluiData.bNotifyActive = 0;
+
+ EventArea_HideShowNotifyFrame();
+}
+
+
+static int EventArea_PaintCallbackProc(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData)
+{
+ return EventArea_Draw(hWnd,hDC);
+}
+
+static int EventArea_Draw(HWND hwnd, HDC hDC)
+{
+ if (hwnd == (HWND)-1) return 0;
+ if (GetParent(hwnd) == pcli->hwndContactList)
+ return EventArea_DrawWorker(hwnd,hDC);
+ else
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ return 0;
+}
+
+static int EventArea_DrawWorker(HWND hWnd, HDC hDC)
+{
+ RECT rc;
+ HFONT hOldFont;
+ GetClientRect(hWnd,&rc);
+ if ( g_CluiData.fDisableSkinEngine )
+ {
+ sttDrawEventAreaBackground( hWnd, hDC, &rc );
+ }
+ else
+ {
+ SkinDrawGlyph(hDC,&rc,&rc,"Main,ID=EventArea");
+ }
+ hOldFont = g_clcPainter.ChangeToFont(hDC,NULL,FONTID_EVENTAREA,NULL);
+ SetBkMode(hDC,TRANSPARENT);
+ //ske_DrawText(hDC,_T("DEBUG"),lstrlen(_T("DEBUG")),&rc,0);
+ {
+ int iCount = GetMenuItemCount(g_CluiData.hMenuNotify);
+ rc.left += 26;
+ if (g_CluiData.hUpdateContact != 0)
+ {
+ TCHAR *szName = pcli->pfnGetContactDisplayName(g_CluiData.hUpdateContact, 0);
+ int iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) g_CluiData.hUpdateContact, 0);
+
+ ske_ImageList_DrawEx(g_himlCListClc, iIcon, hDC, rc.left, (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL);
+ rc.left += 18;
+ ske_DrawText(hDC, szName, -1, &rc, DT_VCENTER | DT_SINGLELINE);
+ ske_ImageList_DrawEx(g_himlCListClc, (int)g_CluiData.iIconNotify, hDC, 4, (rc.bottom + rc.top - 16) / 2, 16, 16, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ }
+ else if (iCount > 0)
+ {
+ MENUITEMINFO mii = {0};
+ struct NotifyMenuItemExData *nmi;
+ TCHAR *szName;
+ int iIcon;
+
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA;
+ GetMenuItemInfo(g_CluiData.hMenuNotify, iCount - 1, TRUE, &mii);
+ nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
+ szName = pcli->pfnGetContactDisplayName(nmi->hContact, 0);
+ iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) nmi->hContact, 0);
+ ske_ImageList_DrawEx(g_himlCListClc, iIcon, hDC, rc.left, (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL);
+ rc.left += 18;
+ ske_ImageList_DrawEx(g_himlCListClc, nmi->iIcon, hDC, 4, (rc.bottom + rc.top) / 2 - 8, 16, 16, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ ske_DrawText(hDC, szName, -1, &rc, DT_VCENTER | DT_SINGLELINE);
+ }
+ else
+ {
+ HICON hIcon = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_BLANK), IMAGE_ICON, 16, 16, 0);
+ ske_DrawText(hDC, g_CluiData.szNoEvents, lstrlen(g_CluiData.szNoEvents), &rc, DT_VCENTER | DT_SINGLELINE);
+ ske_DrawIconEx(hDC, 4, (rc.bottom + rc.top - 16) / 2, hIcon, 16, 16, 0, 0, DI_NORMAL | DI_COMPAT);
+ DestroyIcon(hIcon);
+ }
+ }
+ ske_ResetTextEffect(hDC);
+ SelectObject(hDC,hOldFont);
+ return 0;
+}
+
+static void EventArea_HideShowNotifyFrame()
+{
+ int dwVisible = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, hNotifyFrame), 0) & F_VISIBLE;
+ int desired;
+
+ if (g_CluiData.dwFlags & CLUI_FRAME_SHOWALWAYS)
+ desired = TRUE;
+ else if (g_CluiData.dwFlags & CLUI_FRAME_AUTOHIDENOTIFY)
+ desired = g_CluiData.bNotifyActive ? TRUE : FALSE;
+ else
+ desired = FALSE;
+
+ if (desired)
+ {
+ if ( !dwVisible)
+ CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)hNotifyFrame, 0);
+ }
+ else
+ {
+ if (dwVisible)
+ CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)hNotifyFrame, 0);
+ }
+}
+
+
+int EventArea_Create(HWND hCluiWnd)
+{
+
+ CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"Event Area Background/EventArea",0);
+ HookEvent(ME_BACKGROUNDCONFIG_CHANGED,ehhEventAreaBackgroundSettingsChanged);
+ ehhEventAreaBackgroundSettingsChanged(0,0);
+
+ WNDCLASS wndclass = {0};
+ TCHAR pluginname[] = _T("EventArea");
+ int h = GetSystemMetrics(SM_CYSMICON)+2;
+ if (GetClassInfo(g_hInst,pluginname,&wndclass) == 0)
+ {
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = EventArea_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = pluginname;
+ RegisterClass(&wndclass);
+ }
+ g_CluiData.hwndEventFrame = CreateWindow(pluginname,pluginname,WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN,
+ 0,0,0,h,hCluiWnd,NULL,g_hInst,NULL);
+ // register frame
+
+ {
+ CLISTFrame Frame;
+ memset(&Frame,0,sizeof(Frame));
+ Frame.cbSize = sizeof(CLISTFrame);
+ Frame.hWnd = g_CluiData.hwndEventFrame;
+ Frame.align = alBottom;
+ Frame.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ Frame.Flags = (db_get_b(NULL,"CLUI","ShowEventArea",SETTING_SHOWEVENTAREAFRAME_DEFAULT)?F_VISIBLE:0)|F_LOCKED|F_NOBORDER|F_NO_SUBCONTAINER|F_TCHAR;
+ Frame.height = h;
+ Frame.tname = _T("EventArea"); //do not translate
+ Frame.TBtname = TranslateT("Event Area");
+ hNotifyFrame = (HANDLE)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&Frame,(LPARAM)0);
+ CallService(MS_SKINENG_REGISTERPAINTSUB,(WPARAM)Frame.hWnd,(LPARAM)EventArea_PaintCallbackProc); //$$$$$ register sub for frame
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME,-1,0);
+ EventArea_HideShowNotifyFrame();
+ }
+ g_CluiData.szNoEvents = TranslateT("No Events");
+ g_CluiData.hMenuNotify = CreatePopupMenu();
+ g_CluiData.wNextMenuID = 1;
+ EventArea_ConfigureEventArea();
+ return 0;
+}
+
+int EventArea_UnloadModule()
+{
+ // remove frame window
+ // remove all events data from menu
+ DestroyMenu( g_CluiData.hMenuNotify );
+ return 0;
+}
+
+#define IDC_NOTIFYBUTTON 1900
+static LRESULT CALLBACK EventArea_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg)
+ {
+ case WM_MEASUREITEM:
+ {
+ MEASUREITEMSTRUCT *lpi = (LPMEASUREITEMSTRUCT) lParam;
+ MENUITEMINFOA mii = {0};
+
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA | MIIM_ID;
+ if (GetMenuItemInfoA(g_CluiData.hMenuNotify, lpi->itemID, FALSE, &mii) != 0) {
+ if (mii.dwItemData == lpi->itemData)
+ {
+ lpi->itemWidth = 8 + 16;
+ lpi->itemHeight = 0;
+ return TRUE;
+ }
+ }
+ break;
+ }
+ case WM_DRAWITEM:
+ {
+ LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam;
+ if (dis->hwndItem == (HWND) g_CluiData.hMenuNotify)
+ {
+ MENUITEMINFOA mii = {0};
+
+ struct NotifyMenuItemExData *nmi = 0;
+ int iIcon;
+
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA;
+ if (GetMenuItemInfoA(g_CluiData.hMenuNotify, (UINT) dis->itemID, FALSE, &mii) != 0)
+ {
+ nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
+ if (nmi)
+ {
+ iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) nmi->hContact, 0);
+ ske_ImageList_DrawEx(g_himlCListClc, nmi->iIcon, dis->hDC, 2, (dis->rcItem.bottom + dis->rcItem.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL);
+ ske_ImageList_DrawEx(g_himlCListClc, iIcon, dis->hDC, 2+GetSystemMetrics(SM_CXSMICON)+2, (dis->rcItem.bottom + dis->rcItem.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL);
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+ case WM_LBUTTONUP:
+ if (g_CluiData.bEventAreaEnabled)
+ SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_NOTIFYBUTTON, 0), 0);
+ break;
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_NOTIFYBUTTON) {
+ int iSelection;
+ MENUITEMINFO mii = {0};
+ POINT pt;
+ struct NotifyMenuItemExData *nmi = 0;
+ int iCount = GetMenuItemCount(g_CluiData.hMenuNotify);
+ BOOL result;
+
+ GetCursorPos(&pt);
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA;
+ if (iCount > 1)
+ iSelection = TrackPopupMenu(g_CluiData.hMenuNotify, TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL);
+ else
+ iSelection = GetMenuItemID(g_CluiData.hMenuNotify, 0);
+ result = GetMenuItemInfo(g_CluiData.hMenuNotify, (UINT) iSelection, FALSE, &mii);
+ if (result != 0) {
+ nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
+ if (nmi) {
+ CLISTEVENT *cle = MyGetEvent(iSelection);
+ if (cle) {
+ CLISTEVENT *cle1 = NULL;
+ CallService(cle->pszService, (WPARAM) NULL, (LPARAM) cle);
+ // re-obtain the pointer, it may already be invalid/point to another event if the
+ // event we're interested in was removed by the service (nasty one...)
+ cle1 = MyGetEvent(iSelection);
+ if (cle1 != NULL)
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM) cle->hContact, (LPARAM) cle->hDbEvent);
+ }
+ }
+ }
+ break;
+ }
+ break;
+ case WM_SIZE:
+ if ( !g_CluiData.fLayered)InvalidateRect(hwnd,NULL,FALSE);
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ case WM_ERASEBKGND:
+ return 1;
+ case WM_PAINT:
+ {
+ if (GetParent(hwnd) == pcli->hwndContactList && g_CluiData.fLayered)
+ CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,(WPARAM)hwnd,0);
+ else if (GetParent(hwnd) == pcli->hwndContactList && !g_CluiData.fLayered)
+ {
+ HDC hdc, hdc2;
+ HBITMAP hbmp,hbmpo;
+ RECT rc = {0};
+ GetClientRect(hwnd,&rc);
+ rc.right++;
+ rc.bottom++;
+ hdc = GetDC(hwnd);
+ hdc2 = CreateCompatibleDC(hdc);
+ hbmp = ske_CreateDIB32(rc.right,rc.bottom);
+ hbmpo = (HBITMAP)SelectObject(hdc2,hbmp);
+ ske_BltBackImage(hwnd,hdc2,&rc);
+ EventArea_DrawWorker(hwnd,hdc2);
+ BitBlt(hdc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,
+ hdc2,rc.left,rc.top,SRCCOPY);
+ SelectObject(hdc2,hbmpo);
+ DeleteObject(hbmp);
+ mod_DeleteDC(hdc2);
+ SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
+ ReleaseDC(hwnd,hdc);
+ ValidateRect(hwnd,NULL);
+ }
+ else
+ {
+ HDC hdc, hdc2;
+ HBITMAP hbmp, hbmpo;
+ RECT rc;
+ PAINTSTRUCT ps;
+ HBRUSH br = GetSysColorBrush(COLOR_3DFACE);
+ GetClientRect(hwnd,&rc);
+ hdc = BeginPaint(hwnd,&ps);
+ hdc2 = CreateCompatibleDC(hdc);
+ hbmp = ske_CreateDIB32(rc.right,rc.bottom);
+ hbmpo = (HBITMAP)SelectObject(hdc2,hbmp);
+ FillRect(hdc2,&ps.rcPaint,br);
+ EventArea_DrawWorker(hwnd,hdc2);
+ BitBlt(hdc,ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right-ps.rcPaint.left,ps.rcPaint.bottom-ps.rcPaint.top,
+ hdc2,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY);
+ SelectObject(hdc2,hbmpo);
+ DeleteObject(hbmp);
+ mod_DeleteDC(hdc2);
+ ps.fErase = FALSE;
+ EndPaint(hwnd,&ps);
+ }
+ }
+ default:
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return TRUE;
+}
diff --git a/plugins/Clist_modern/src/modern_clistmenus.cpp b/plugins/Clist_modern/src/modern_clistmenus.cpp
new file mode 100644
index 0000000000..1cb178028d
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clistmenus.cpp
@@ -0,0 +1,217 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "hdr/modern_clist.h"
+#include "m_genmenu.h"
+#include "m_clui.h"
+#include "hdr/modern_commonprototypes.h"
+
+int LoadFavoriteContactMenu();
+int UnloadFavoriteContactMenu();
+
+#pragma hdrstop
+
+INT_PTR CloseAction(WPARAM wParam,LPARAM lParam)
+{
+ int k;
+ g_CluiData.bSTATE = STATE_PREPEARETOEXIT; // workaround for avatar service and other wich destroys service on OK_TOEXIT
+ do
+ { k = CallService(MS_SYSTEM_OKTOEXIT,(WPARAM)0,(LPARAM)0);
+ }
+ while (!k);
+
+ if ( k ) {
+ DestroyWindow(pcli->hwndContactList);
+ }
+
+ return 0;
+}
+
+int InitCustomMenus(void)
+{
+ CreateServiceFunction( "CloseAction", CloseAction );
+ LoadFavoriteContactMenu();
+ return 0;
+}
+
+void UninitCustomMenus(void)
+{
+ UnloadFavoriteContactMenu();
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// FAVORITE CONTACT SYSTEM
+//
+//////////////////////////////////////////////////////////////////////////
+
+#define CLUI_FAVSETRATE "CLUI/SetContactRate" //LParam is rate, Wparam is contact handle
+#define CLUI_FAVTOGGLESHOWOFFLINE "CLUI/ToggleContactShowOffline"
+
+static HANDLE hFavoriteContactMenu = NULL;
+static HANDLE *hFavoriteContactMenuItems = NULL;
+static HANDLE hShowIfOflineItem = NULL;
+static HANDLE hOnContactMenuBuild_FAV = NULL;
+
+
+
+static int FAV_OnContactMenuBuild(WPARAM wParam,LPARAM lParam)
+{
+ CLISTMENUITEM mi;
+ BOOL NeedFree = FALSE;
+ BYTE bContactRate = db_get_b((HANDLE)wParam, "CList", "Rate",0);
+ //if (hFavoriteContactMenu)
+
+ static TCHAR * FAVMENUROOTNAME = _T("&Contact rate");
+
+ TCHAR *rates[] = {
+ _T( "None" ),
+ _T( "Low" ),
+ _T( "Medium" ),
+ _T( "High" )
+ };
+
+ char* iconsName[] = {
+ LPGEN( "Contact rate None" ),
+ LPGEN( "Contact rate Low" ),
+ LPGEN( "Contact rate Medium" ),
+ LPGEN( "Contact rate High" )
+ };
+
+ if ( bContactRate >SIZEOF( rates ) - 1 )
+ bContactRate = SIZEOF( rates ) - 1;
+
+ BOOL bModifyMenu = FALSE;
+ int i;
+ TCHAR * name = NULL;
+
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.hIcon = CLUI_LoadIconFromExternalFile("clisticons.dll",8,TRUE,TRUE,iconsName[bContactRate],"Contact List",Translate(iconsName[bContactRate]),-IDI_FAVORITE_0 - bContactRate, &NeedFree);
+ mi.pszPopupName = (char *)-1;
+ mi.position = 0;
+ if ( !bContactRate)
+ mi.ptszName = FAVMENUROOTNAME;
+ else
+ {
+ int bufsize = (lstrlen(FAVMENUROOTNAME)+lstrlen(rates[bContactRate])+15)*sizeof(TCHAR);
+ name = (TCHAR*)_alloca(bufsize);
+ mir_sntprintf(name,bufsize/sizeof(TCHAR),_T("%s (%s)"),FAVMENUROOTNAME,rates[bContactRate]);
+ mi.ptszName = name;
+ }
+ mi.flags = CMIF_ROOTPOPUP|CMIF_TCHAR;
+ if ( !hFavoriteContactMenu)
+ hFavoriteContactMenu = Menu_AddContactMenuItem(&mi);
+ else
+ {
+ mi.flags |= CMIM_FLAGS|CMIM_ICON|CMIM_NAME;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hFavoriteContactMenu, (LPARAM)&mi);
+ bModifyMenu = TRUE;
+ }
+ {
+ OptParam op;
+ op.Handle = hFavoriteContactMenu;
+ op.Setting = OPT_MENUITEMSETUNIQNAME;
+ op.Value = (INT_PTR)"ModernClistMenu_ContactRate";
+ CallService(MO_SETOPTIONSMENUITEM,(WPARAM)0,(LPARAM)&op);
+ }
+
+ CallService(MS_SKIN2_RELEASEICON,(WPARAM)mi.hIcon,0);
+ if (mi.hIcon && NeedFree) DestroyIcon(mi.hIcon);
+
+ mi.pszPopupName = (char*)hFavoriteContactMenu;
+ if ( !hFavoriteContactMenuItems) {
+ hFavoriteContactMenuItems = (HANDLE*)malloc(sizeof(HANDLE)*SIZEOF(rates));
+ memset(hFavoriteContactMenuItems,0,sizeof(HANDLE)*SIZEOF(rates));
+ }
+
+ for (i=0; i < SIZEOF(rates); i++) {
+ mi.hIcon = mi.hIcon = CLUI_LoadIconFromExternalFile("clisticons.dll",8+i,TRUE,TRUE,iconsName[i],"Contact List",Translate(iconsName[i]),-IDI_FAVORITE_0 - i, &NeedFree);
+ mi.ptszName = rates[i];
+ mi.flags = CMIF_CHILDPOPUP|CMIF_TCHAR|((bContactRate == i)?CMIF_CHECKED:0);
+ mi.pszService = CLUI_FAVSETRATE;
+ mi.popupPosition = i;
+ if (bModifyMenu && hFavoriteContactMenuItems[i]) {
+ mi.flags |= CMIM_FLAGS|CMIM_ICON;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hFavoriteContactMenuItems[i], (LPARAM)&mi);
+ }
+ else hFavoriteContactMenuItems[i] = Menu_AddContactMenuItem(&mi);
+ CallService(MS_SKIN2_RELEASEICON,(WPARAM)mi.hIcon,0);
+ if (mi.hIcon && NeedFree) DestroyIcon(mi.hIcon);
+ }
+
+ mi.hIcon = NULL;
+ mi.ptszName = _T("Show even if offline");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_TCHAR|(db_get_b((HANDLE)wParam,"CList","noOffline",0)?CMIF_CHECKED:0);
+ mi.pszService = CLUI_FAVTOGGLESHOWOFFLINE;
+ mi.popupPosition = i+100000000;
+ mi.position = -100000000;
+ if (bModifyMenu && hShowIfOflineItem) {
+ mi.flags |= CMIM_FLAGS|CMIM_ICON;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hShowIfOflineItem, (LPARAM)&mi);
+ }
+ else hShowIfOflineItem = Menu_AddContactMenuItem(&mi);
+
+ return 0;
+}
+
+INT_PTR FAV_SetRate(WPARAM hContact, LPARAM nRate)
+{
+ if (hContact)
+ {
+ db_set_b((HANDLE)hContact, "CList", "Rate",(BYTE)nRate);
+ }
+ return 0;
+}
+
+INT_PTR FAV_ToggleShowOffline(WPARAM hContact,LPARAM lParam)
+{
+ if (hContact)
+ {
+ db_set_b((HANDLE)hContact,"CList","noOffline",
+ db_get_b((HANDLE)hContact,"CList","noOffline",0)?0:1);
+ }
+ return 0;
+}
+
+int LoadFavoriteContactMenu()
+{
+ CreateServiceFunction(CLUI_FAVSETRATE,FAV_SetRate);
+ CreateServiceFunction(CLUI_FAVTOGGLESHOWOFFLINE,FAV_ToggleShowOffline);
+ hOnContactMenuBuild_FAV = HookEvent(ME_CLIST_PREBUILDCONTACTMENU,FAV_OnContactMenuBuild);
+ return 0;
+}
+
+int UnloadFavoriteContactMenu()
+{
+ if (hFavoriteContactMenuItems)
+ free (hFavoriteContactMenuItems);
+ hFavoriteContactMenuItems = NULL;
+
+ if (hFavoriteContactMenu)
+ CallService(MO_REMOVEMENUITEM,(WPARAM)hFavoriteContactMenu,0);
+ hFavoriteContactMenu = NULL;
+
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_clistmod.cpp b/plugins/Clist_modern/src/modern_clistmod.cpp
new file mode 100644
index 0000000000..fb182af5ec
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clistmod.cpp
@@ -0,0 +1,567 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include <m_file.h>
+#include <m_addcontact.h>
+#include "hdr/modern_clist.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_sync.h"
+#include "hdr/modern_clui.h"
+#include <m_modernopt.h>
+pfnMyMonitorFromPoint MyMonitorFromPoint = NULL;
+pfnMyMonitorFromWindow MyMonitorFromWindow = NULL;
+pfnMyGetMonitorInfo MyGetMonitorInfo = NULL;
+
+static HANDLE hookSystemShutdown_CListMod = NULL;
+HANDLE hookOptInitialise_CList = NULL,
+ hookOptInitialise_Skin = NULL,
+ hookContactAdded_CListSettings = NULL;
+
+
+int CListMod_HideWindow(HWND hwndContactList, int mode);
+
+void GroupMenus_Init(void);
+int AddMainMenuItem(WPARAM wParam,LPARAM lParam);
+int AddContactMenuItem(WPARAM wParam,LPARAM lParam);
+void UninitCListEvents(void);
+int ContactAdded(WPARAM wParam,LPARAM lParam);
+int GetContactDisplayName(WPARAM wParam,LPARAM lParam);
+int CListOptInit(WPARAM wParam,LPARAM lParam);
+int SkinOptInit(WPARAM wParam,LPARAM lParam);
+int ModernSkinOptInit(WPARAM wParam,LPARAM lParam);
+int EventsProcessContactDoubleClick(HANDLE hContact);
+
+INT_PTR TrayIconPauseAutoHide(WPARAM wParam,LPARAM lParam);
+INT_PTR ContactChangeGroup(WPARAM wParam,LPARAM lParam);
+
+void InitTrayMenus(void);
+void UninitTrayMenu();
+
+HIMAGELIST hCListImages = NULL;
+
+BOOL (WINAPI *MySetProcessWorkingSetSize)(HANDLE,SIZE_T,SIZE_T);
+
+//returns normal icon or combined with status overlay. Needs to be destroyed.
+HICON cliGetIconFromStatusMode(HANDLE hContact, const char *szProto,int status)
+{
+ HICON hIcon = NULL;
+ HICON hXIcon = NULL;
+ // check if options is turned on
+ BYTE trayOption = db_get_b(NULL,"CLUI","XStatusTray",SETTING_TRAYOPTION_DEFAULT);
+ if (trayOption&3 && szProto != NULL)
+ {
+ // check service exists
+ char str[MAXMODULELABELLENGTH];
+ strcpy(str,szProto);
+ strcat(str,"/GetXStatusIcon");
+ if (ServiceExists(str))
+ {
+ // check status is online
+ if (status>ID_STATUS_OFFLINE)
+ {
+ // get xicon
+ hXIcon = (HICON)CallService(str,0,0);
+ if (hXIcon)
+ {
+ // check overlay mode
+ if (trayOption&2)
+ {
+ // get overlay
+ HICON MainOverlay = (HICON)GetMainStatusOverlay(status);
+ hIcon = ske_CreateJoinedIcon(hXIcon,MainOverlay,(trayOption&4)?192:0);
+ DestroyIcon_protect(hXIcon);
+ DestroyIcon_protect(MainOverlay);
+ }
+ else
+ {
+ // paint it
+ hIcon = hXIcon;
+ }
+ }
+ }
+ }
+ }
+ if ( !hIcon)
+ {
+ hIcon = ske_ImageList_GetIcon(g_himlCListClc,ExtIconFromStatusMode(hContact,szProto,status),ILD_NORMAL);
+ }
+ // if not ready take normal icon
+ return hIcon;
+}
+////////// By FYR/////////////
+int ExtIconFromStatusMode(HANDLE hContact, const char *szProto,int status)
+{
+ /*pdisplayNameCacheEntry cacheEntry;
+ if ((DBGetContactSettingByte(NULL,"CLC","Meta",0) != 1) && szProto != NULL)
+ {
+ if (meta_module && mir_strcmp(szProto,meta_module) == 0)
+ {
+ hContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT,(UINT)hContact,0);
+ if (hContact != 0)
+ {
+ szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(UINT)hContact,0);
+ status = DBGetContactSettingWord(hContact,szProto,"Status",ID_STATUS_OFFLINE);
+ }
+ }
+ }
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ if (cacheEntry->isTransport>0) return GetTrasportStatusIconIndex(cacheEntry->isTransport-1,status);
+ */
+ return pcli->pfnIconFromStatusMode(szProto,status,hContact);
+}
+/////////// End by FYR ////////
+int cli_IconFromStatusMode(const char *szProto,int nStatus, HANDLE hContact)
+{
+ int result = -1;
+ if (hContact && szProto)
+ {
+ char * szActProto = (char*)szProto;
+ char AdvancedService[255] = {0};
+ int nActStatus = nStatus;
+ HANDLE hActContact = hContact;
+ if ( !db_get_b(NULL,"CLC","Meta",SETTING_USEMETAICON_DEFAULT) && g_szMetaModuleName && !mir_strcmp(szActProto,g_szMetaModuleName))
+ {
+ // substitute params by mostonline contact datas
+ HANDLE hMostOnlineContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT,(WPARAM)hActContact,0);
+ if (hMostOnlineContact)
+ {
+ pdisplayNameCacheEntry cacheEntry;
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hMostOnlineContact);
+ if (cacheEntry && cacheEntry->m_cache_cszProto)
+ {
+ szActProto = cacheEntry->m_cache_cszProto;
+ nActStatus = pdnce___GetStatus( cacheEntry );
+ hActContact = hMostOnlineContact;
+ }
+ }
+ }
+ mir_snprintf(AdvancedService,SIZEOF(AdvancedService),"%s%s",szActProto,"/GetAdvancedStatusIcon");
+
+ if (ServiceExists(AdvancedService))
+ result = CallService(AdvancedService,(WPARAM)hActContact, (LPARAM)0);
+
+ if (result == -1 || !(LOWORD(result)))
+ {
+ //Get normal Icon
+ int basicIcon = corecli.pfnIconFromStatusMode(szActProto,nActStatus,NULL);
+ if (result != -1 && basicIcon != 1) result |= basicIcon;
+ else result = basicIcon;
+ }
+ }
+ else
+ {
+ result = corecli.pfnIconFromStatusMode(szProto,nStatus,NULL);
+ }
+ return result;
+}
+
+
+int GetContactIconC(pdisplayNameCacheEntry cacheEntry)
+{
+ return ExtIconFromStatusMode(cacheEntry->hContact,cacheEntry->m_cache_cszProto,cacheEntry->m_cache_cszProto == NULL ? ID_STATUS_OFFLINE : pdnce___GetStatus( cacheEntry ));
+}
+
+//lParam
+// 0 - default - return icon id in order: transport status icon, protostatus icon, meta is affected
+
+
+INT_PTR GetContactIcon(WPARAM wParam,LPARAM lParam)
+{
+ char *szProto;
+ int status;
+ int res;
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);
+ if (szProto == NULL)
+ status = ID_STATUS_OFFLINE;
+ else
+ status = db_get_w((HANDLE) wParam, szProto, "Status", ID_STATUS_OFFLINE);
+ res = ExtIconFromStatusMode((HANDLE)wParam,szProto,szProto == NULL?ID_STATUS_OFFLINE:status); //by FYR
+ if (lParam == 0 && res != -1) res &= 0xFFFF;
+ return res;
+}
+
+void UnLoadContactListModule() //unhooks noncritical events
+{
+ UninitTrayMenu();
+ UninitCustomMenus();
+}
+
+int CListMod_ContactListShutdownProc(WPARAM wParam,LPARAM lParam)
+{
+ FreeDisplayNameCache();
+ return 0;
+}
+
+INT_PTR CLUIGetCapsService(WPARAM wParam,LPARAM lParam)
+{
+ if (lParam)
+ {
+ switch (lParam)
+ {
+ case 0:
+ return 0;
+ case CLUIF2_PLUGININFO:
+ return (INT_PTR)&pluginInfo;
+ case CLUIF2_CLISTTYPE:
+ return 0x0107;
+ case CLUIF2_EXTRACOLUMNCOUNT:
+ return EXTRA_ICON_COUNT;
+ case CLUIF2_USEREXTRASTART:
+ return EXTRA_ICON_ADV3;
+ }
+ return 0;
+ }
+ else
+ {
+ switch (wParam)
+ {
+ case CLUICAPS_FLAGS1:
+ return CLUIF_HIDEEMPTYGROUPS|CLUIF_DISABLEGROUPS|CLUIF_HASONTOPOPTION|CLUIF_HASAUTOHIDEOPTION;
+ case CLUICAPS_FLAGS2:
+ return MAKELONG(EXTRACOLUMNCOUNT,1);
+ }
+ }
+ return 0;
+}
+HRESULT PreLoadContactListModule()
+{
+ /* Global data initialization */
+ {
+ g_CluiData.fOnDesktop = FALSE;
+ g_CluiData.dwKeyColor = RGB(255,0,255);
+ g_CluiData.bCurrentAlpha = 255;
+ }
+
+ //initialize firstly hooks
+ //clist interface is empty yet so handles should check
+ CreateServiceFunction(MS_CLIST_GETCONTACTICON, GetContactIcon);
+ return S_OK;
+}
+
+INT_PTR SvcActiveSkin(WPARAM wParam, LPARAM lParam);
+INT_PTR SvcPreviewSkin(WPARAM wParam, LPARAM lParam);
+INT_PTR SvcApplySkin(WPARAM wParam, LPARAM lParam);
+
+HRESULT CluiLoadModule()
+{
+ CreateServiceFunction(MS_CLUI_GETCAPS,CLUIGetCapsService);
+
+ InitDisplayNameCache();
+ hookSystemShutdown_CListMod = HookEvent(ME_SYSTEM_SHUTDOWN,CListMod_ContactListShutdownProc);
+ hookOptInitialise_CList = HookEvent(ME_OPT_INITIALISE,CListOptInit);
+ hookOptInitialise_Skin = HookEvent(ME_OPT_INITIALISE,SkinOptInit);
+
+ CreateServiceFunction("ModernSkinSel/Active", SvcActiveSkin);
+ CreateServiceFunction("ModernSkinSel/Preview", SvcPreviewSkin);
+ CreateServiceFunction("ModernSkinSel/Apply", SvcApplySkin);
+
+ hookContactAdded_CListSettings = HookEvent(ME_DB_CONTACT_ADDED,ContactAdded);
+ CreateServiceFunction(MS_CLIST_TRAYICONPROCESSMESSAGE,cli_TrayIconProcessMessage);
+ CreateServiceFunction(MS_CLIST_PAUSEAUTOHIDE,TrayIconPauseAutoHide);
+ CreateServiceFunction(MS_CLIST_CONTACTCHANGEGROUP,ContactChangeGroup);
+ CreateServiceFunction(MS_CLIST_TOGGLEHIDEOFFLINE,ToggleHideOffline);
+
+ CreateServiceFunction(MS_CLIST_TOGGLEGROUPS,ToggleGroups);
+ CreateServiceFunction(MS_CLIST_TOGGLESOUNDS,ToggleSounds);
+ CreateServiceFunction(MS_CLIST_SETUSEGROUPS,SetUseGroups);
+
+
+ CreateServiceFunction(MS_CLIST_GETCONTACTICON,GetContactIcon);
+
+ MySetProcessWorkingSetSize = (BOOL (WINAPI*)(HANDLE,SIZE_T,SIZE_T))GetProcAddress(GetModuleHandle(_T("kernel32")),"SetProcessWorkingSetSize");
+ hCListImages = ImageList_Create(16, 16, ILC_MASK|ILC_COLOR32, 32, 0);
+ InitCustomMenus();
+ InitTray();
+ {
+ HINSTANCE hUser = GetModuleHandleA("USER32");
+ MyMonitorFromPoint = ( pfnMyMonitorFromPoint )GetProcAddress( hUser,"MonitorFromPoint" );
+ MyMonitorFromWindow = ( pfnMyMonitorFromWindow )GetProcAddress( hUser, "MonitorFromWindow" );
+ MyGetMonitorInfo = ( pfnMyGetMonitorInfo )GetProcAddress( hUser, "GetMonitorInfoW");
+ }
+ CLUI::InitClui();
+
+ return S_OK;
+}
+
+/*
+Begin of Hrk's code for bug
+*/
+#define GWVS_HIDDEN 1
+#define GWVS_VISIBLE 2
+#define GWVS_COVERED 3
+#define GWVS_PARTIALLY_COVERED 4
+
+int GetWindowVisibleState(HWND, int, int);
+__inline DWORD GetDIBPixelColor(int X, int Y, int Width, int Height, int ByteWidth, BYTE * ptr)
+{
+ DWORD res = 0;
+ if (X >= 0 && X < Width && Y >= 0 && Y < Height && ptr)
+ res = *((DWORD*)(ptr+ByteWidth*(Height-Y-1)+X*4));
+ return res;
+}
+
+int GetWindowVisibleState(HWND hWnd, int iStepX, int iStepY) {
+ RECT rc = { 0 };
+ POINT pt = { 0 };
+ register int i=0,
+ j = 0,
+ width = 0,
+ height = 0,
+ iCountedDots = 0,
+ iNotCoveredDots = 0;
+ HWND hAux = 0;
+
+ if (hWnd == NULL) {
+ SetLastError(0x00000006); //Wrong handle
+ return -1;
+ }
+ //Some defaults now. The routine is designed for thin and tall windows.
+ if (iStepX <= 0) iStepX = 8;
+ if (iStepY <= 0) iStepY = 16;
+
+ HWND hwndFocused = GetFocus();
+
+ if (IsIconic(hWnd) || !IsWindowVisible(hWnd))
+ return GWVS_HIDDEN;
+ else if ( db_get_b(NULL,"CList","OnDesktop",SETTING_ONDESKTOP_DEFAULT) || !db_get_b(NULL, "CList", "BringToFront", SETTING_BRINGTOFRONT_DEFAULT))
+ return GWVS_VISIBLE;
+ else if ( hwndFocused == pcli->hwndContactList || GetParent(hwndFocused) == pcli->hwndContactList )
+ return GWVS_VISIBLE;
+ else
+ {
+ int hstep,vstep;
+ BITMAP bmp;
+ HBITMAP WindowImage;
+ int maxx = 0;
+ int maxy = 0;
+ int wx = 0;
+ int dx,dy;
+ BYTE *ptr = NULL;
+ HRGN rgn = NULL;
+ WindowImage = g_CluiData.fLayered?ske_GetCurrentWindowImage():0;
+ if (WindowImage && g_CluiData.fLayered)
+ {
+ GetObject(WindowImage,sizeof(BITMAP),&bmp);
+ ptr = (BYTE*)bmp.bmBits;
+ maxx = bmp.bmWidth;
+ maxy = bmp.bmHeight;
+ wx = bmp.bmWidthBytes;
+ }
+ else
+ {
+ RECT rc;
+ int i=0;
+ rgn = CreateRectRgn(0,0,1,1);
+ GetWindowRect(hWnd,&rc);
+ GetWindowRgn(hWnd,rgn);
+ OffsetRgn(rgn,rc.left,rc.top);
+ GetRgnBox(rgn,&rc);
+ i = i;
+ //maxx = rc.right;
+ //maxy = rc.bottom;
+ }
+ GetWindowRect(hWnd, &rc);
+ {
+ RECT rcMonitor = {0};
+ Docking_GetMonitorRectFromWindow(hWnd,&rcMonitor);
+ rc.top = rc.top < rcMonitor.top?rcMonitor.top:rc.top;
+ rc.left = rc.left < rcMonitor.left?rcMonitor.left:rc.left;
+ rc.bottom = rc.bottom>rcMonitor.bottom?rcMonitor.bottom:rc.bottom;
+ rc.right = rc.right>rcMonitor.right?rcMonitor.right:rc.right;
+ }
+ width = rc.right - rc.left;
+ height = rc.bottom- rc.top;
+ dx = -rc.left;
+ dy = -rc.top;
+ hstep = width/iStepX;
+ vstep = height/iStepY;
+ hstep = hstep>0?hstep:1;
+ vstep = vstep>0?vstep:1;
+
+ for (i = rc.top; i < rc.bottom; i += vstep) {
+ pt.y = i;
+ for (j = rc.left; j < rc.right; j += hstep) {
+ BOOL po = FALSE;
+ pt.x = j;
+ if (rgn)
+ po = PtInRegion(rgn,j,i);
+ else
+ {
+ DWORD a = (GetDIBPixelColor(j+dx,i+dy,maxx,maxy,wx,ptr)&0xFF000000)>>24;
+ a = ((a*g_CluiData.bCurrentAlpha)>>8);
+ po = (a>16);
+ }
+ if (po || (!rgn && ptr == 0))
+ {
+ BOOL hWndFound = FALSE;
+ HWND hAuxOld = NULL;
+ hAux = WindowFromPoint(pt);
+ do
+ {
+ if (hAux == hWnd)
+ {
+ hWndFound = TRUE;
+ break;
+ }
+ //hAux = GetParent(hAux);
+ hAuxOld = hAux;
+ hAux = fnGetAncestor(hAux,GA_ROOTOWNER);
+ if (hAuxOld == hAux)
+ {
+ TCHAR buf[255];
+ GetClassName(hAux,buf,SIZEOF(buf));
+ if ( !lstrcmp(buf,CLUIFrameSubContainerClassName))
+ {
+ hWndFound = TRUE;
+ break;
+ }
+ }
+ }while(hAux != NULL && hAuxOld != hAux);
+
+ if (hWndFound) //There's window!
+ iNotCoveredDots++; //Let's count the not covered dots.
+ iCountedDots++; //Let's keep track of how many dots we checked.
+ }
+ }
+ }
+ if (rgn) DeleteObject(rgn);
+ if ( iCountedDots - iNotCoveredDots < 2) //Every dot was not covered: the window is visible.
+ return GWVS_VISIBLE;
+ else if (iNotCoveredDots == 0) //They're all covered!
+ return GWVS_COVERED;
+ else //There are dots which are visible, but they are not as many as the ones we counted: it's partially covered.
+ return GWVS_PARTIALLY_COVERED;
+ }
+}
+BYTE g_bCalledFromShowHide = 0;
+int cliShowHide(WPARAM wParam,LPARAM lParam)
+{
+ BOOL bShow = FALSE;
+
+ int iVisibleState = GetWindowVisibleState(pcli->hwndContactList,0,0);
+ int method;
+ method = db_get_b(NULL, "ModernData", "HideBehind", SETTING_HIDEBEHIND_DEFAULT);; //(0-none, 1-leftedge, 2-rightedge);
+ if (method)
+ {
+ if (db_get_b(NULL, "ModernData", "BehindEdge", SETTING_BEHINDEDGE_DEFAULT) == 0 && lParam != 1)
+ {
+ //hide
+ CLUI_HideBehindEdge();
+ }
+ else
+ {
+ CLUI_ShowFromBehindEdge();
+ }
+ bShow = TRUE;
+ iVisibleState = GWVS_HIDDEN;
+ }
+
+ if ( !method && db_get_b(NULL, "ModernData", "BehindEdge", SETTING_BEHINDEDGE_DEFAULT)>0)
+ {
+ g_CluiData.bBehindEdgeSettings = db_get_b(NULL, "ModernData", "BehindEdge", SETTING_BEHINDEDGE_DEFAULT);
+ CLUI_ShowFromBehindEdge();
+ g_CluiData.bBehindEdgeSettings = 0;
+ g_CluiData.nBehindEdgeState = 0;
+ db_unset(NULL, "ModernData", "BehindEdge");
+ }
+
+ //bShow is FALSE when we enter the switch if no hide behind edge.
+ switch (iVisibleState) {
+ case GWVS_PARTIALLY_COVERED:
+ bShow = TRUE; break;
+ case GWVS_COVERED: //Fall through (and we're already falling)
+ bShow = TRUE; break;
+ case GWVS_HIDDEN:
+ bShow = TRUE; break;
+ case GWVS_VISIBLE: //This is not needed, but goes for readability.
+ bShow = FALSE; break;
+ case -1: //We can't get here, both pcli->hwndContactList and iStepX and iStepY are right.
+ return 0;
+ }
+
+ if ((bShow == TRUE || lParam == 1))
+ {
+ Sync( CLUIFrames_ActivateSubContainers, TRUE );
+ CLUI_ShowWindowMod(pcli->hwndContactList, SW_RESTORE);
+
+ if ( !db_get_b(NULL,"CList","OnDesktop",SETTING_ONDESKTOP_DEFAULT))
+ {
+ Sync(CLUIFrames_OnShowHide, pcli->hwndContactList,1); //TO BE PROXIED
+ SetWindowPos(pcli->hwndContactList, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |SWP_NOACTIVATE);
+ g_bCalledFromShowHide = 1;
+ if ( !db_get_b(NULL,"CList","OnTop",SETTING_ONTOP_DEFAULT))
+ SetWindowPos(pcli->hwndContactList, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
+ g_bCalledFromShowHide = 0;
+ }
+ else
+ {
+ SetWindowPos(pcli->hwndContactList, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
+ Sync(CLUIFrames_OnShowHide, pcli->hwndContactList,1);
+ SetForegroundWindow(pcli->hwndContactList);
+ }
+ db_set_b(NULL,"CList","State",SETTING_STATE_NORMAL);
+
+ RECT rcWindow;
+ GetWindowRect(pcli->hwndContactList,&rcWindow);
+ if (Utils_AssertInsideScreen(&rcWindow) == 1)
+ {
+ MoveWindow(pcli->hwndContactList, rcWindow.left, rcWindow.top,
+ rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
+ }
+
+ //if (DBGetContactSettingByte(NULL,"CList","OnDesktop",SETTING_ONDESKTOP_DEFAULT))
+ // SetWindowPos(pcli->hwndContactList, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ }
+ else { //It needs to be hidden
+ if (GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)
+ {
+ CListMod_HideWindow(pcli->hwndContactList, SW_HIDE);
+ db_set_b(NULL,"CList","State",SETTING_STATE_HIDDEN);
+ }
+ else
+ {
+ if (db_get_b(NULL,"CList","Min2Tray",SETTING_MIN2TRAY_DEFAULT)) {
+ CLUI_ShowWindowMod(pcli->hwndContactList, SW_HIDE);
+ db_set_b(NULL,"CList","State",SETTING_STATE_HIDDEN);
+ }
+ else
+ {
+ CLUI_ShowWindowMod(pcli->hwndContactList, SW_MINIMIZE);
+ db_set_b(NULL,"CList","State",SETTING_STATE_MINIMIZED);
+ }
+ }
+
+ if (MySetProcessWorkingSetSize != NULL)
+ MySetProcessWorkingSetSize(GetCurrentProcess(),-1,-1);
+ }
+ return 0;
+}
+
+int CListMod_HideWindow(HWND hwndContactList, int mode)
+{
+ KillTimer(pcli->hwndContactList,1/*TM_AUTOALPHA*/);
+ if ( !CLUI_HideBehindEdge()) return CLUI_SmoothAlphaTransition(pcli->hwndContactList, 0, 1);
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_clistopts.cpp b/plugins/Clist_modern/src/modern_clistopts.cpp
new file mode 100644
index 0000000000..d5d46dc1cb
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clistopts.cpp
@@ -0,0 +1,1282 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "m_clc.h"
+#include "hdr/modern_commonprototypes.h"
+
+static UINT expertOnlyControls[] = {IDC_ALWAYSSTATUS};
+
+static INT_PTR CALLBACK DlgProcItemRowOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ SendDlgItemMessage(hwndDlg,IDC_MIN_ROW_HEIGHT_SPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_MIN_ROW_HEIGHT),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_MIN_ROW_HEIGHT_SPIN,UDM_SETRANGE,0,MAKELONG(255,0));
+ SendDlgItemMessage(hwndDlg,IDC_MIN_ROW_HEIGHT_SPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","MinRowHeight",CLCDEFAULT_ROWHEIGHT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_ROW_BORDER_SPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_ROW_BORDER),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_ROW_BORDER_SPIN,UDM_SETRANGE,0,MAKELONG(255,0));
+ SendDlgItemMessage(hwndDlg,IDC_ROW_BORDER_SPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","RowBorder",SETTING_ROWBORDER_DEFAULT),0));
+
+ CheckDlgButton(hwndDlg, IDC_VARIABLE_ROW_HEIGHT, db_get_b(NULL,"CList","VariableRowHeight",SETTING_VARIABLEROWHEIGHT_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_ALIGN_TO_LEFT, db_get_b(NULL,"CList","AlignLeftItemsToLeft",SETTING_ALIGNLEFTTOLEFT_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_ALIGN_TO_RIGHT, db_get_b(NULL,"CList","AlignRightItemsToRight",SETTING_ALIGNRIGHTORIGHT_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+
+ CheckDlgButton(hwndDlg, IDC_MINIMODE, db_get_b(NULL,"CLC","CompactMode",SETTING_COMPACTMODE_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+
+ SendDlgItemMessage(hwndDlg,IDC_LEFTMARGINSPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_LEFTMARGIN),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_LEFTMARGINSPIN,UDM_SETRANGE,0,MAKELONG(64,0));
+ SendDlgItemMessage(hwndDlg,IDC_LEFTMARGINSPIN,UDM_SETPOS,0,MAKELONG(db_get_b(NULL,"CLC","LeftMargin",CLCDEFAULT_LEFTMARGIN),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_RIGHTMARGINSPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_RIGHTMARGIN),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_RIGHTMARGINSPIN,UDM_SETRANGE,0,MAKELONG(64,0));
+ SendDlgItemMessage(hwndDlg,IDC_RIGHTMARGINSPIN,UDM_SETPOS,0,MAKELONG(db_get_b(NULL,"CLC","RightMargin",CLCDEFAULT_RIGHTMARGIN),0));
+
+ // Listbox
+ {
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_LIST_ORDER);
+ for (int i=0 ; i < NUM_ITEM_TYPE ; i++) {
+ char tmp[128];
+ int type;
+ int pos = 0;
+
+ mir_snprintf(tmp, SIZEOF(tmp), "RowPos%d", i);
+ type = db_get_w(NULL, "CList", tmp, i);
+
+ switch(type) {
+ case ITEM_AVATAR:
+ pos = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM) TranslateT("Avatar"));
+ break;
+ case ITEM_ICON:
+ pos = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM) TranslateT("Icon"));
+ break;
+ case ITEM_TEXT:
+ pos = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM) TranslateT("Text"));
+ break;
+ case ITEM_EXTRA_ICONS:
+ pos = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM) TranslateT("Extra icons"));
+ break;
+ case ITEM_CONTACT_TIME:
+ pos = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM) TranslateT("Contact time"));
+ break;
+ }
+ SendMessage(hwndList, LB_SETITEMDATA, pos, type);
+ }
+
+ // Buttons
+ switch(SendMessage(hwndList, LB_GETCURSEL, 0, 0)) {
+ case LB_ERR:
+ EnableWindow(GetDlgItem(hwndDlg,IDC_UP),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DOWN),FALSE);
+ break;
+ case 0:
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DOWN),FALSE);
+ break;
+ case 3:
+ EnableWindow(GetDlgItem(hwndDlg,IDC_UP),FALSE);
+ break;
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_UP) {
+ if (HIWORD(wParam) != BN_CLICKED)
+ return 0;
+
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_LIST_ORDER);
+ int pos = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
+ if (pos == LB_ERR)
+ return 0;
+ int type = SendMessage(hwndList, LB_GETITEMDATA, pos, 0);
+
+ // Switch items
+ SendMessage(hwndList, LB_DELETESTRING, pos, 0);
+
+ switch(type) {
+ case ITEM_AVATAR:
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos-1, (LPARAM) TranslateT("Avatar"));
+ break;
+ case ITEM_ICON:
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos-1, (LPARAM) TranslateT("Icon"));
+ break;
+ case ITEM_TEXT:
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos-1, (LPARAM) TranslateT("Text"));
+ break;
+ case ITEM_EXTRA_ICONS:
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos-1, (LPARAM) TranslateT("Extra icons"));
+ break;
+ case ITEM_CONTACT_TIME:
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos-1, (LPARAM) TranslateT("Contact time"));
+ break;
+ }
+ SendMessage(hwndList, LB_SETITEMDATA, pos, type);
+ SendMessage(hwndList, LB_SETCURSEL, pos, 0);
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ }
+
+ if (LOWORD(wParam) == IDC_DOWN)
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_LIST_ORDER);
+ int pos = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
+
+ if (pos != LB_ERR)
+ {
+ int type = SendMessage(hwndList, LB_GETITEMDATA, pos, 0);
+
+ // Switch items
+ SendMessage(hwndList, LB_DELETESTRING, pos, 0);
+
+ switch(type)
+ {
+ case ITEM_AVATAR:
+ {
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos+1, (LPARAM) TranslateT("Avatar"));
+ break;
+ }
+ case ITEM_ICON:
+ {
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos+1, (LPARAM) TranslateT("Icon"));
+ break;
+ }
+ case ITEM_TEXT:
+ {
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos+1, (LPARAM) TranslateT("Text"));
+ break;
+ }
+ case ITEM_EXTRA_ICONS:
+ {
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos+1, (LPARAM) TranslateT("Extra icons"));
+ break;
+ }
+ case ITEM_CONTACT_TIME:
+ {
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos+1, (LPARAM) TranslateT("Contact time"));
+ break;
+ }
+ }
+ SendMessage(hwndList, LB_SETITEMDATA, pos, type);
+ SendMessage(hwndList, LB_SETCURSEL, pos, 0);
+
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ }
+ else return 0;
+ }
+ else return 0;
+ }
+
+ if (LOWORD(wParam) == IDC_LIST_ORDER || LOWORD(wParam) == IDC_UP || LOWORD(wParam) == IDC_DOWN) {
+ int pos = SendMessage(GetDlgItem(hwndDlg, IDC_LIST_ORDER), LB_GETCURSEL, 0, 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_UP),pos != LB_ERR && pos > 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DOWN),pos != LB_ERR && pos < 4);
+ }
+
+ if (LOWORD(wParam) == IDC_LIST_ORDER) return 0;
+ if (LOWORD(wParam) == IDC_MIN_ROW_HEIGHT && HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())
+ return 0; // dont make apply enabled during buddy set crap
+ if ((LOWORD(wParam) == IDC_LEFTMARGIN || LOWORD(wParam) == IDC_RIGHTMARGIN || LOWORD(wParam) == IDC_ROW_BORDER) && 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:
+ db_set_w(NULL,"CList","MinRowHeight",(WORD)SendDlgItemMessage(hwndDlg,IDC_MIN_ROW_HEIGHT_SPIN,UDM_GETPOS,0,0));
+ db_set_w(NULL,"CList","RowBorder",(WORD)SendDlgItemMessage(hwndDlg,IDC_ROW_BORDER_SPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CList","VariableRowHeight", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_VARIABLE_ROW_HEIGHT));
+ db_set_b(NULL,"CList","AlignLeftItemsToLeft", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_ALIGN_TO_LEFT));
+ db_set_b(NULL,"CList","AlignRightItemsToRight", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_ALIGN_TO_RIGHT));
+ db_set_b(NULL,"CLC","CompactMode", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_MINIMODE));
+ db_set_b(NULL,"CLC","LeftMargin",(BYTE)SendDlgItemMessage(hwndDlg,IDC_LEFTMARGINSPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CLC","RightMargin",(BYTE)SendDlgItemMessage(hwndDlg,IDC_RIGHTMARGINSPIN,UDM_GETPOS,0,0));
+ {
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_LIST_ORDER);
+ for (int i=0 ; i < NUM_ITEM_TYPE ; i++) {
+ char tmp[128];
+ mir_snprintf(tmp, SIZEOF(tmp), "RowPos%d", i);
+ db_set_w(NULL,"CList",tmp,(WORD)SendMessage(hwndList, LB_GETITEMDATA, i, 0));
+ }
+ }
+
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static INT_PTR CALLBACK DlgProcItemAvatarOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_SHOW_AVATARS, db_get_b(NULL,"CList","AvatarsShow",SETTINGS_SHOWAVATARS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_SHOW_ANIAVATARS, db_get_b(NULL,"CList","AvatarsAnimated",(ServiceExists(MS_AV_GETAVATARBITMAP) && !g_CluiData.fGDIPlusFail)) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_AVATAR_FASTDRAW, db_get_b(NULL,"CList","AvatarsInSeparateWnd",SETTINGS_AVATARINSEPARATE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_AVATAR_DRAW_BORDER, db_get_b(NULL,"CList","AvatarsDrawBorders",SETTINGS_AVATARDRAWBORDER_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_AVATAR_ROUND_CORNERS, db_get_b(NULL,"CList","AvatarsRoundCorners",SETTINGS_AVATARROUNDCORNERS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK, db_get_b(NULL,"CList","AvatarsUseCustomCornerSize",SETTINGS_AVATARUSECUTOMCORNERSIZE_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_AVATAR_IGNORE_SIZE, db_get_b(NULL,"CList","AvatarsIgnoreSizeForRow",SETTINGS_AVATARIGNORESIZEFORROW_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_AVATAR_OVERLAY_ICONS, db_get_b(NULL,"CList","AvatarsDrawOverlay",SETTINGS_AVATARDRAWOVERLAY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+
+ switch(db_get_b(NULL,"CList","AvatarsOverlayType",SETTINGS_AVATAROVERLAYTYPE_DEFAULT)) {
+ case SETTING_AVATAR_OVERLAY_TYPE_NORMAL:
+ CheckDlgButton(hwndDlg, IDC_AVATAR_OVERLAY_ICON_NORMAL, BST_CHECKED);
+ break;
+ case SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL:
+ CheckDlgButton(hwndDlg, IDC_AVATAR_OVERLAY_ICON_PROTOCOL, BST_CHECKED);
+ break;
+ case SETTING_AVATAR_OVERLAY_TYPE_CONTACT:
+ CheckDlgButton(hwndDlg, IDC_AVATAR_OVERLAY_ICON_CONTACT, BST_CHECKED);
+ break;
+ }
+
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_SIZE_SPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_AVATAR_SIZE),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_SIZE_SPIN,UDM_SETRANGE,0,MAKELONG(255,1));
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_SIZE_SPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","AvatarsSize",SETTING_AVATARHEIGHT_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_WIDTH_SPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_AVATAR_WIDTH),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_WIDTH_SPIN,UDM_SETRANGE,0,MAKELONG(255,0));
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_WIDTH_SPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","AvatarsWidth",SETTING_AVATARWIDTH_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN,UDM_SETRANGE,0,MAKELONG(255,1));
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","AvatarsCustomCornerSize",SETTINGS_AVATARCORNERSIZE_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg, IDC_AVATAR_BORDER_COLOR, CPM_SETCOLOUR, 0, (COLORREF)db_get_dw(NULL,"CList","AvatarsBorderColor",SETTINGS_AVATARBORDERCOLOR_DEFAULT));
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_SHOW_AVATARS)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_DRAW_BORDER),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR_L),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_ROUND_CORNERS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_IGNORE_SIZE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICONS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_NORMAL),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_PROTOCOL),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_CONTACT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_L),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_SPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_PIXELS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_WIDTH),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_WIDTH_SPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_PIXELS2),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_ANIAVATARS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_PIXELS3),FALSE);
+ EnableWindow( GetDlgItem( hwndDlg, IDC_AVATAR_FASTDRAW), FALSE );
+ }
+
+ if ( !IsDlgButtonChecked( hwndDlg, IDC_SHOW_ANIAVATARS ))
+ EnableWindow( GetDlgItem( hwndDlg, IDC_AVATAR_FASTDRAW), FALSE );
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_AVATAR_DRAW_BORDER)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR_L),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR),FALSE);
+ }
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_AVATAR_ROUND_CORNERS)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN),FALSE);
+ }
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN),FALSE);
+ }
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICONS)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_NORMAL),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_PROTOCOL),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_CONTACT),FALSE);
+ }
+
+ if ( !ServiceExists(MS_AV_GETAVATARBITMAP) || g_CluiData.fGDIPlusFail) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_ANIAVATARS),FALSE);
+ SetDlgItemText(hwndDlg, IDC_SHOW_ANIAVATARS, TranslateT("Animate Avatars (GDI+ and Avatar Service module (avs.dll) are required)"));
+ }
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_SHOW_AVATARS) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_SHOW_AVATARS);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_DRAW_BORDER),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR_L),enabled && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_DRAW_BORDER));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR),enabled && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_DRAW_BORDER));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_ROUND_CORNERS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_IGNORE_SIZE),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICONS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_NORMAL),enabled && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICONS));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_PROTOCOL),enabled && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICONS));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_CONTACT),enabled && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICONS));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_L),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_SPIN),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_PIXELS2),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_PIXELS3),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_ANIAVATARS),enabled && (ServiceExists(MS_AV_GETAVATARBITMAP) && !g_CluiData.fGDIPlusFail));
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_WIDTH),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_WIDTH_SPIN),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_PIXELS),enabled);
+
+ EnableWindow( GetDlgItem( hwndDlg, IDC_AVATAR_FASTDRAW), enabled && IsDlgButtonChecked( hwndDlg, IDC_SHOW_ANIAVATARS ));
+ }
+ else if (LOWORD(wParam) == IDC_SHOW_ANIAVATARS)
+ EnableWindow( GetDlgItem( hwndDlg, IDC_AVATAR_FASTDRAW), IsDlgButtonChecked( hwndDlg, IDC_SHOW_ANIAVATARS ));
+
+ else if (LOWORD(wParam) == IDC_AVATAR_DRAW_BORDER) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_SHOW_AVATARS) && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_DRAW_BORDER);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR_L),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR),enabled);
+ }
+
+ else if (LOWORD(wParam) == IDC_AVATAR_ROUND_CORNERS) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_SHOW_AVATARS) && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_ROUND_CORNERS);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN),enabled);
+ }
+
+ else if (LOWORD(wParam) == IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_AVATAR_ROUND_CORNERS);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE),enabled && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN),enabled && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK));
+ }
+
+ else if (LOWORD(wParam) == IDC_AVATAR_OVERLAY_ICONS) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_SHOW_AVATARS) && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICONS);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_NORMAL),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_PROTOCOL),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_CONTACT),enabled);
+ }
+ else if (LOWORD(wParam) == IDC_AVATAR_SIZE && HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())
+ return 0; // dont make apply enabled during buddy set crap
+ else if (LOWORD(wParam) == IDC_AVATAR_CUSTOM_CORNER_SIZE && 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:
+ db_set_b(NULL,"CList","AvatarsShow", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW_AVATARS));
+ db_set_b(NULL,"CList","AvatarsAnimated", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW_ANIAVATARS));
+ db_set_b(NULL,"CList","AvatarsInSeparateWnd", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_AVATAR_FASTDRAW));
+
+ db_set_b(NULL,"CList","AvatarsDrawBorders", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_AVATAR_DRAW_BORDER));
+ db_set_dw(NULL,"CList","AvatarsBorderColor", (DWORD)SendDlgItemMessage(hwndDlg, IDC_AVATAR_BORDER_COLOR, CPM_GETCOLOUR, 0, 0));
+ db_set_b(NULL,"CList","AvatarsRoundCorners", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_AVATAR_ROUND_CORNERS));
+ db_set_b(NULL,"CList","AvatarsIgnoreSizeForRow", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_AVATAR_IGNORE_SIZE));
+ db_set_b(NULL,"CList","AvatarsUseCustomCornerSize", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK));
+ db_set_w(NULL,"CList","AvatarsCustomCornerSize",(WORD)SendDlgItemMessage(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CList","AvatarsDrawOverlay", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICONS));
+ db_set_w(NULL,"CList","AvatarsSize",(WORD)SendDlgItemMessage(hwndDlg,IDC_AVATAR_SIZE_SPIN,UDM_GETPOS,0,0));
+ db_set_w(NULL,"CList","AvatarsWidth",(WORD)SendDlgItemMessage(hwndDlg,IDC_AVATAR_WIDTH_SPIN,UDM_GETPOS,0,0));
+
+ if (IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICON_NORMAL))
+ db_set_b(NULL,"CList","AvatarsOverlayType",SETTING_AVATAR_OVERLAY_TYPE_NORMAL);
+ else if (IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICON_PROTOCOL))
+ db_set_b(NULL,"CList","AvatarsOverlayType",SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL);
+ else if (IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICON_CONTACT))
+ db_set_b(NULL,"CList","AvatarsOverlayType",SETTING_AVATAR_OVERLAY_TYPE_CONTACT);
+ ClcOptionsChanged();
+ AniAva_UpdateOptions();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+static INT_PTR CALLBACK DlgProcItemIconOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_HIDE_ICON_ON_AVATAR, db_get_b(NULL,"CList","IconHideOnAvatar",SETTING_HIDEICONONAVATAR_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_DRAW_ON_AVATAR_SPACE, db_get_b(NULL,"CList","IconDrawOnAvatarSpace",SETTING_ICONONAVATARPLACE_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_ICONBLINK, db_get_b(NULL,"CList","NoIconBlink",SETTING_NOICONBLINF_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_HIDE_GROUPSICON, db_get_b(NULL,"CList","HideGroupsIcon",SETTING_HIDEGROUPSICON_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_NOTCHECKICONSIZE, db_get_b(NULL,"CList","IconIgnoreSizeForRownHeight",SETTING_ICONIGNORESIZE_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_ALWAYS_VISIBLEICON, db_get_b(NULL,"CList","AlwaysShowAlwaysVisIcon",SETTING_ALWAYSVISICON_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_USEXSTATUS, (db_get_b(NULL,"CLC","DrawOverlayedStatus",SETTING_DRAWOVERLAYEDSTATUS_DEFAULT)&1) ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_DRAWSTATUSOVERLAY, (db_get_b(NULL,"CLC","DrawOverlayedStatus",SETTING_DRAWOVERLAYEDSTATUS_DEFAULT)&2) ? BST_CHECKED : BST_UNCHECKED );
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAWSTATUSOVERLAY),IsDlgButtonChecked(hwndDlg,IDC_USEXSTATUS));
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_HIDE_ICON_ON_AVATAR))
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAW_ON_AVATAR_SPACE),FALSE);
+
+ if (ServiceExists("ExtraIcon/Register"))
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ALWAYS_VISIBLEICON), SW_HIDE);
+
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_HIDE_ICON_ON_AVATAR) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_HIDE_ICON_ON_AVATAR);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAW_ON_AVATAR_SPACE),enabled);
+ }
+ else if (LOWORD(wParam) == IDC_USEXSTATUS)
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAWSTATUSOVERLAY),IsDlgButtonChecked(hwndDlg,IDC_USEXSTATUS));
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CList","IconHideOnAvatar", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_HIDE_ICON_ON_AVATAR));
+ db_set_b(NULL,"CList","IconDrawOnAvatarSpace", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_DRAW_ON_AVATAR_SPACE));
+ db_set_b(NULL,"CList","HideGroupsIcon", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_HIDE_GROUPSICON));
+ db_set_b(NULL,"CList","NoIconBlink", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_ICONBLINK));
+ db_set_b(NULL,"CList","IconIgnoreSizeForRownHeight", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_NOTCHECKICONSIZE));
+ db_set_b(NULL,"CList","AlwaysShowAlwaysVisIcon", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_ALWAYS_VISIBLEICON));
+ {
+ BYTE ovr = IsDlgButtonChecked(hwndDlg,IDC_USEXSTATUS)?1:0;
+ if (ovr) ovr += IsDlgButtonChecked(hwndDlg,IDC_DRAWSTATUSOVERLAY)?2:0;
+ db_set_b(NULL,"CLC","DrawOverlayedStatus", ovr );
+ }
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+static INT_PTR CALLBACK DlgProcItemContactTimeOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_SHOW, db_get_b(NULL,"CList","ContactTimeShow",SETTING_SHOWTIME_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_SHOW_ONLY_IF_DIFFERENT, db_get_b(NULL,"CList","ContactTimeShowOnlyIfDifferent",SETTING_SHOWTIMEIFDIFF_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ break;
+
+ case WM_COMMAND:
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CList","ContactTimeShow", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW));
+ db_set_b(NULL,"CList","ContactTimeShowOnlyIfDifferent", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW_ONLY_IF_DIFFERENT));
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+static INT_PTR CALLBACK DlgProcItemTextOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_RTL, db_get_b(NULL,"CList","TextRTL",SETTING_TEXT_RTL_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ //TODO: init IDC_ALIGNGROUPCOMBO from DBGetContactSettingByte(NULL,"CList","AlignGroupCaptions",SETTING_ALIGNGROPCAPTION_DEFAULT);
+ {
+ int item;
+ TCHAR *align[] = {_T("Left align group names"), _T("Center group names"), _T("Right align group names")};
+ for (int i=0; i < sizeof(align)/sizeof(char*); i++)
+ item = SendDlgItemMessage(hwndDlg,IDC_ALIGNGROUPCOMBO,CB_ADDSTRING,0,(LPARAM)TranslateTS(align[i]));
+ SendDlgItemMessage(hwndDlg,IDC_ALIGNGROUPCOMBO,CB_SETCURSEL,db_get_b(NULL,"CList","AlignGroupCaptions",SETTING_ALIGNGROPCAPTION_DEFAULT),0);
+ }
+ CheckDlgButton(hwndDlg, IDC_ALIGN_RIGHT, db_get_b(NULL,"CList","TextAlignToRight",SETTING_TEXT_RIGHTALIGN_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_REPLACE_SMILEYS, db_get_b(NULL,"CList","TextReplaceSmileys",SETTING_TEXT_SMILEY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_RESIZE_SMILEYS, db_get_b(NULL,"CList","TextResizeSmileys",SETTING_TEXT_RESIZESMILEY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_USE_PROTOCOL_SMILEYS, db_get_b(NULL,"CList","TextUseProtocolSmileys",SETTING_TEXT_PROTOSMILEY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_IGNORE_SIZE, db_get_b(NULL,"CList","TextIgnoreSizeForRownHeight",SETTING_TEXT_IGNORESIZE_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+
+ CheckDlgButton(hwndDlg, IDC_DRAW_SMILEYS_ON_FIRST_LINE, db_get_b(NULL,"CList","FirstLineDrawSmileys",SETTING_FIRSTLINE_SMILEYS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_APPEND_NICK, db_get_b(NULL,"CList","FirstLineAppendNick",SETTING_FIRSTLINE_APPENDNICK_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_TRIM_TEXT, db_get_b(NULL,"CList","TrimText",SETTING_FIRSTLINE_TRIMTEXT_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ {
+ bool smileAddPresent = ServiceExists(MS_SMILEYADD_BATCHPARSE) != 0;
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_REPLACE_SMILEYS), smileAddPresent ? SW_SHOW : SW_HIDE);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_USE_PROTOCOL_SMILEYS), smileAddPresent ? SW_SHOW : SW_HIDE);
+ //CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_RESIZE_SMILEYS), smileAddPresent ? SW_SHOW : SW_HIDE);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_DRAW_SMILEYS_ON_FIRST_LINE), smileAddPresent ? SW_SHOW : SW_HIDE);
+ }
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_REPLACE_SMILEYS))
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_PROTOCOL_SMILEYS),FALSE);
+
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_REPLACE_SMILEYS) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_REPLACE_SMILEYS);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_PROTOCOL_SMILEYS),enabled);
+ //EnableWindow(GetDlgItem(hwndDlg,IDC_RESIZE_SMILEYS),enabled); //Commented out for listening to icon
+ }
+ if (LOWORD(wParam) != IDC_ALIGNGROUPCOMBO || (LOWORD(wParam) == IDC_ALIGNGROUPCOMBO && HIWORD(wParam) == CBN_SELCHANGE))
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CList","TextRTL", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_RTL));
+ //TODO: Store IDC_ALIGNGROUPCOMBO at DBGetContactSettingByte(NULL,"CList","AlignGroupCaptions",SETTING_ALIGNGROPCAPTION_DEFAULT);
+ db_set_b(NULL,"CList","AlignGroupCaptions",(BYTE)SendDlgItemMessage(hwndDlg,IDC_ALIGNGROUPCOMBO,CB_GETCURSEL,0,0));
+ db_set_b(NULL,"CList","TextAlignToRight", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_ALIGN_RIGHT));
+ db_set_b(NULL,"CList","TextReplaceSmileys", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_REPLACE_SMILEYS));
+ db_set_b(NULL,"CList","TextResizeSmileys", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_RESIZE_SMILEYS));
+ db_set_b(NULL,"CList","TextUseProtocolSmileys", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_USE_PROTOCOL_SMILEYS));
+ db_set_b(NULL,"CList","TextIgnoreSizeForRownHeight", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_IGNORE_SIZE));
+ db_set_b(NULL,"CList","FirstLineDrawSmileys", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_DRAW_SMILEYS_ON_FIRST_LINE));
+ db_set_b(NULL,"CList","FirstLineAppendNick", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_APPEND_NICK));
+ db_set_b(NULL,"CList","TrimText", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_TRIM_TEXT));
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static INT_PTR CALLBACK DlgProcItemSecondLineOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_SHOW, db_get_b(NULL,"CList","SecondLineShow",SETTING_SECONDLINE_SHOW_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+
+ SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_TOP_SPACE),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_SETRANGE,0,MAKELONG(255,0));
+ SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","SecondLineTopSpace",SETTING_SECONDLINE_TOPSPACE_DEFAULT),0));
+
+ CheckDlgButton(hwndDlg, IDC_DRAW_SMILEYS, db_get_b(NULL,"CList","SecondLineDrawSmileys",SETTING_SECONDLINE_SMILEYS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ {
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingTString(NULL, "CList","SecondLineText", &dbv)) {
+ SetWindowText(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), dbv.ptszVal);
+ db_free(&dbv);
+ }
+ }
+ SendMessage(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), EM_SETLIMITTEXT, TEXT_TEXT_MAX_LENGTH, 0);
+ {
+ int radio;
+ radio = db_get_w(NULL,"CList","SecondLineType",TEXT_STATUS_MESSAGE);
+
+ CheckDlgButton(hwndDlg, IDC_STATUS, radio == TEXT_STATUS ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_NICKNAME, radio == TEXT_NICKNAME ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_STATUS_MESSAGE, radio == TEXT_STATUS_MESSAGE ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_LISTENING_TO, radio == TEXT_LISTENING_TO ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_CONTACT_TIME, radio == TEXT_CONTACT_TIME ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_TEXT, radio == TEXT_TEXT ? BST_CHECKED : BST_UNCHECKED );
+ }
+ CheckDlgButton(hwndDlg, IDC_XSTATUS_HAS_PRIORITY, db_get_b(NULL,"CList","SecondLineXStatusHasPriority",SETTING_SECONDLINE_XSTATUS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOW_STATUS_IF_NOAWAY, db_get_b(NULL,"CList","SecondLineShowStatusIfNoAway",SETTING_SECONDLINE_STATUSIFNOAWAY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOW_LISTENING_IF_NOAWAY, db_get_b(NULL,"CList","SecondLineShowListeningIfNoAway",SETTING_SECONDLINE_LISTENINGIFNOAWAY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_USE_NAME_AND_MESSAGE, db_get_b(NULL,"CList","SecondLineUseNameAndMessageForXStatus",SETTING_SECONDLINE_XSTATUSNAMETEXT_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_SHOW))
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_PROTOCOL_SMILEYS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE_SPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAW_SMILEYS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_NICKNAME),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS_MESSAGE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_LISTENING_TO),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CONTACT_TIME),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TOP),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_PIXELS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE),FALSE);
+ }
+ else {
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_TEXT)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L),FALSE);
+ }
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_STATUS) && !IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE),FALSE);
+ }
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY),FALSE);
+ }
+ }
+
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_DRAW_SMILEYS), ServiceExists(MS_SMILEYADD_BATCHPARSE) ? SW_SHOW : SW_HIDE);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_VARIABLES_L), ServiceExists(MS_VARS_FORMATSTRING) ? SW_SHOW : SW_HIDE);
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_TEXT || LOWORD(wParam) == IDC_STATUS || LOWORD(wParam) == IDC_NICKNAME || LOWORD(wParam) == IDC_STATUS_MESSAGE
+ || LOWORD(wParam) == IDC_LISTENING_TO || LOWORD(wParam) == IDC_CONTACT_TIME) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), IsDlgButtonChecked(hwndDlg,IDC_TEXT)
+ && IsDlgButtonChecked(hwndDlg,IDC_SHOW));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L), IsDlgButtonChecked(hwndDlg,IDC_TEXT)
+ && IsDlgButtonChecked(hwndDlg,IDC_SHOW));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY), IsDlgButtonChecked(hwndDlg,IDC_SHOW) &&
+ (IsDlgButtonChecked(hwndDlg,IDC_STATUS)
+ || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY), IsDlgButtonChecked(hwndDlg,IDC_SHOW) &&
+ (IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY), IsDlgButtonChecked(hwndDlg,IDC_SHOW) &&
+ (IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE), IsDlgButtonChecked(hwndDlg,IDC_SHOW) &&
+ (IsDlgButtonChecked(hwndDlg,IDC_STATUS)
+ || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ }
+ else if (LOWORD(wParam) == IDC_SHOW) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_SHOW);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_PROTOCOL_SMILEYS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE_SPIN),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAW_SMILEYS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_NICKNAME),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CONTACT_TIME),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS_MESSAGE),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_LISTENING_TO),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TEXT),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT),enabled && IsDlgButtonChecked(hwndDlg,IDC_TEXT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TOP),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_PIXELS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TEXT),enabled);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), enabled && IsDlgButtonChecked(hwndDlg,IDC_TEXT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L), enabled && IsDlgButtonChecked(hwndDlg,IDC_TEXT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY), enabled && (IsDlgButtonChecked(hwndDlg,IDC_STATUS)
+ || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY), enabled && IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY), enabled && IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE), enabled && (IsDlgButtonChecked(hwndDlg,IDC_STATUS)
+ || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ }
+
+ if (LOWORD(wParam) == IDC_TOP_SPACE && 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:
+ db_set_b(NULL,"CList","SecondLineShow", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW));
+ db_set_w(NULL,"CList","SecondLineTopSpace", (WORD)SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CList","SecondLineDrawSmileys", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_DRAW_SMILEYS));
+ {
+ int radio;
+ if (IsDlgButtonChecked(hwndDlg,IDC_STATUS))
+ radio = TEXT_STATUS;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_NICKNAME))
+ radio = TEXT_NICKNAME;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_TEXT))
+ radio = TEXT_TEXT;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_CONTACT_TIME))
+ radio = TEXT_CONTACT_TIME;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_LISTENING_TO))
+ radio = TEXT_LISTENING_TO;
+ else
+ radio = TEXT_STATUS_MESSAGE;
+ db_set_w(NULL,"CList","SecondLineType", (WORD)radio);
+ }
+ {
+ TCHAR t[TEXT_TEXT_MAX_LENGTH];
+
+ GetWindowText(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), t, SIZEOF(t));
+ t[TEXT_TEXT_MAX_LENGTH - 1] = '\0';
+
+ db_set_ws(NULL, "CList", "SecondLineText", t);
+ }
+
+ db_set_b(NULL,"CList","SecondLineXStatusHasPriority", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_XSTATUS_HAS_PRIORITY));
+ db_set_b(NULL,"CList","SecondLineShowStatusIfNoAway", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY));
+ db_set_b(NULL,"CList","SecondLineShowListeningIfNoAway", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY));
+ db_set_b(NULL,"CList","SecondLineUseNameAndMessageForXStatus", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_USE_NAME_AND_MESSAGE));
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static INT_PTR CALLBACK DlgProcItemThirdLineOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_SHOW, db_get_b(NULL,"CList","ThirdLineShow",SETTING_THIRDLINE_SHOW_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+
+ SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_TOP_SPACE),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_SETRANGE,0,MAKELONG(255,0));
+ SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","ThirdLineTopSpace",SETTING_THIRDLINE_TOPSPACE_DEFAULT),0));
+
+ CheckDlgButton(hwndDlg, IDC_DRAW_SMILEYS, db_get_b(NULL,"CList","ThirdLineDrawSmileys",SETTING_THIRDLINE_SMILEYS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ {
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingTString(NULL, "CList","ThirdLineText", &dbv)) {
+ SetWindowText(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), dbv.ptszVal);
+ db_free(&dbv);
+ }
+ }
+ SendMessage(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), EM_SETLIMITTEXT, TEXT_TEXT_MAX_LENGTH, 0);
+ {
+ int radio = db_get_w(NULL,"CList","ThirdLineType",SETTING_THIRDLINE_TYPE_DEFAULT);
+ CheckDlgButton(hwndDlg, IDC_STATUS, radio == TEXT_STATUS ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_NICKNAME, radio == TEXT_NICKNAME ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_STATUS_MESSAGE, radio == TEXT_STATUS_MESSAGE ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_LISTENING_TO, radio == TEXT_LISTENING_TO ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_CONTACT_TIME, radio == TEXT_CONTACT_TIME ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_TEXT, radio == TEXT_TEXT ? BST_CHECKED : BST_UNCHECKED );
+ }
+
+ CheckDlgButton(hwndDlg, IDC_XSTATUS_HAS_PRIORITY, db_get_b(NULL,"CList","ThirdLineXStatusHasPriority",SETTING_THIRDLINE_XSTATUS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOW_STATUS_IF_NOAWAY, db_get_b(NULL,"CList","ThirdLineShowStatusIfNoAway",SETTING_THIRDLINE_STATUSIFNOAWAY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOW_LISTENING_IF_NOAWAY, db_get_b(NULL,"CList","ThirdLineShowListeningIfNoAway",SETTING_THIRDLINE_LISTENINGIFNOAWAY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_USE_NAME_AND_MESSAGE, db_get_b(NULL,"CList","ThirdLineUseNameAndMessageForXStatus",SETTING_THIRDLINE_XSTATUSNAMETEXT_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_SHOW)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_PROTOCOL_SMILEYS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE_SPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAW_SMILEYS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_NICKNAME),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS_MESSAGE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_LISTENING_TO),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CONTACT_TIME),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TOP),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_PIXELS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY),FALSE);
+ }
+ else {
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_TEXT)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L),FALSE);
+ }
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_STATUS) && !IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE),FALSE);
+ }
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY),FALSE);
+ }
+ }
+
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_DRAW_SMILEYS), ServiceExists(MS_SMILEYADD_BATCHPARSE) ? SW_SHOW : SW_HIDE);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_VARIABLES_L), ServiceExists(MS_VARS_FORMATSTRING) ? SW_SHOW : SW_HIDE);
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_TEXT || LOWORD(wParam) == IDC_STATUS || LOWORD(wParam) == IDC_NICKNAME || LOWORD(wParam) == IDC_STATUS_MESSAGE
+ || LOWORD(wParam) == IDC_LISTENING_TO || LOWORD(wParam) == IDC_CONTACT_TIME) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), IsDlgButtonChecked(hwndDlg,IDC_TEXT)
+ && IsDlgButtonChecked(hwndDlg,IDC_SHOW));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L), IsDlgButtonChecked(hwndDlg,IDC_TEXT)
+ && IsDlgButtonChecked(hwndDlg,IDC_SHOW));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY), IsDlgButtonChecked(hwndDlg,IDC_SHOW) &&
+ (IsDlgButtonChecked(hwndDlg,IDC_STATUS)
+ || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE), IsDlgButtonChecked(hwndDlg,IDC_SHOW) && (IsDlgButtonChecked(hwndDlg,IDC_STATUS) || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY), IsDlgButtonChecked(hwndDlg,IDC_SHOW) && (IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY), IsDlgButtonChecked(hwndDlg,IDC_SHOW) && (IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ }
+ else if (LOWORD(wParam) == IDC_SHOW) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_SHOW);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_PROTOCOL_SMILEYS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE_SPIN),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAW_SMILEYS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_NICKNAME),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS_MESSAGE),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_LISTENING_TO),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CONTACT_TIME),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TEXT),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT),enabled && IsDlgButtonChecked(hwndDlg,IDC_TEXT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TOP),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_PIXELS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TEXT),enabled);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), enabled && IsDlgButtonChecked(hwndDlg,IDC_TEXT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L), enabled && IsDlgButtonChecked(hwndDlg,IDC_TEXT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY), enabled && (IsDlgButtonChecked(hwndDlg,IDC_STATUS)
+ || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE), enabled && (IsDlgButtonChecked(hwndDlg,IDC_STATUS)
+ || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY), enabled && IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY), enabled && IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE));
+ }
+
+ if (LOWORD(wParam) == IDC_TOP_SPACE && 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:
+ db_set_b(NULL,"CList","ThirdLineShow", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW));
+ db_set_w(NULL,"CList","ThirdLineTopSpace", (WORD)SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CList","ThirdLineDrawSmileys", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_DRAW_SMILEYS));
+ {
+ int radio;
+ if (IsDlgButtonChecked(hwndDlg,IDC_STATUS))
+ radio = TEXT_STATUS;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_NICKNAME))
+ radio = TEXT_NICKNAME;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_TEXT))
+ radio = TEXT_TEXT;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_CONTACT_TIME))
+ radio = TEXT_CONTACT_TIME;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_LISTENING_TO))
+ radio = TEXT_LISTENING_TO;
+ else
+ radio = TEXT_STATUS_MESSAGE;
+ db_set_w(NULL,"CList","ThirdLineType", (WORD)radio);
+ }
+ {
+ TCHAR t[TEXT_TEXT_MAX_LENGTH];
+
+ GetWindowText(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), t, SIZEOF(t));
+ t[TEXT_TEXT_MAX_LENGTH - 1] = '\0';
+
+ db_set_ws(NULL, "CList", "ThirdLineText", t);
+ }
+
+ db_set_b(NULL,"CList","ThirdLineXStatusHasPriority", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_XSTATUS_HAS_PRIORITY));
+ db_set_b(NULL,"CList","ThirdLineUseNameAndMessageForXStatus", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_USE_NAME_AND_MESSAGE));
+ db_set_b(NULL,"CList","ThirdLineShowStatusIfNoAway", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY));
+ db_set_b(NULL,"CList","ThirdLineShowListeningIfNoAway", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY));
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+/* Extra icons settings */
+typedef struct _OrderTreeData
+{
+ BYTE ID;
+ TCHAR * Name;
+ BYTE Position;
+ char * KeyName;
+ BOOL Visible;
+ BOOL fReserved;
+} *pOrderTreeData, TOrderTreeData;
+
+static TOrderTreeData OrderTreeData[] =
+{
+ {EXTRA_ICON_VISMODE, _T("Visibility/Chat activity"), EXTRA_ICON_VISMODE, "EXTRA_ICON_VISMODE", SETTING_EXTRA_ICON_VISMODE_DEFAULT,0},
+ {EXTRA_ICON_EMAIL, _T("E-mail"), EXTRA_ICON_EMAIL, "EXTRA_ICON_EMAIL", SETTING_EXTRA_ICON_EMAIL_DEFAULT, 0},
+ {EXTRA_ICON_PROTO, _T("Protocol"), EXTRA_ICON_PROTO, "EXTRA_ICON_PROTO", SETTING_EXTRA_ICON_PROTO_DEFAULT, 0},
+ {EXTRA_ICON_SMS, _T("Phone/SMS"), EXTRA_ICON_SMS, "EXTRA_ICON_SMS", SETTING_EXTRA_ICON_SMS_DEFAULT, 0},
+ {EXTRA_ICON_WEB, _T("Web page"), EXTRA_ICON_WEB, "EXTRA_ICON_WEB", SETTING_EXTRA_ICON_WEB_DEFAULT, 0},
+ {EXTRA_ICON_CLIENT, _T("Client (fingerprint.dll is required)"), EXTRA_ICON_CLIENT,"EXTRA_ICON_CLIENT", SETTING_EXTRA_ICON_CLIENT_DEFAULT, 0},
+ {EXTRA_ICON_ADV1, _T("Advanced #1"), EXTRA_ICON_ADV1, "EXTRA_ICON_ADV1", SETTING_EXTRA_ICON_ADV1_DEFAULT, 0},
+ {EXTRA_ICON_ADV2, _T("Advanced #2"), EXTRA_ICON_ADV2, "EXTRA_ICON_ADV2", SETTING_EXTRA_ICON_ADV2_DEFAULT, 0},
+ {EXTRA_ICON_ADV3, _T("Advanced #3"), EXTRA_ICON_ADV3, "EXTRA_ICON_ADV3", SETTING_EXTRA_ICON_ADV3_DEFAULT, 0},
+ {EXTRA_ICON_ADV4, _T("Advanced #4"), EXTRA_ICON_ADV4, "EXTRA_ICON_ADV4", SETTING_EXTRA_ICON_ADV4_DEFAULT, 0}
+};
+
+#define PrVer 4
+
+static char **settingname;
+static int nArrayLen;
+
+static int OrderEnumProc (const char *szSetting,LPARAM lParam)
+{
+ if (szSetting == NULL) return 0;
+ if ( !wildcmp((char*) szSetting,(char *) lParam,0)) return 0;
+ nArrayLen++;
+ settingname = (char **)realloc(settingname,nArrayLen*sizeof(char *));
+ settingname[nArrayLen-1] = _strdup(szSetting);
+ return 0;
+};
+
+static int DeleteAllSettingInOrder()
+{
+ DBCONTACTENUMSETTINGS dbces;
+ nArrayLen = 0;
+
+ dbces.pfnEnumProc = OrderEnumProc;
+ dbces.szModule = CLUIFrameModule;
+ dbces.ofsSettings = 0;
+ dbces.lParam = (LPARAM)"ORDER_EXTRA_*";
+
+ CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces);
+
+ //delete all settings
+ if (nArrayLen == 0)
+ return 0;
+
+ for (int i=0; i < nArrayLen; i++) {
+ db_unset(0, CLUIFrameModule, settingname[i]);
+ free(settingname[i]);
+ }
+ free(settingname);
+ settingname = NULL;
+
+ return 0;
+}
+
+static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+{
+ pOrderTreeData A = (pOrderTreeData)lParam1;
+ pOrderTreeData B = (pOrderTreeData)lParam2;
+ return (int)(A->Position)-(int)(B->Position);
+}
+
+static int FillOrderTree(HWND hwndDlg, HWND Tree)
+{
+ TVINSERTSTRUCT tvis = {0};
+ TreeView_DeleteAllItems(Tree);
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ if (db_get_b(NULL,CLUIFrameModule,"ExtraCountStored",0) != SIZEOF(OrderTreeData)) {
+ DeleteAllSettingInOrder();
+ db_set_b(NULL,CLUIFrameModule,"ExtraCountStored",SIZEOF(OrderTreeData));
+ }
+
+ for (int i=0; i < SIZEOF(OrderTreeData); i++) {
+ char buf[256];
+ sprintf(buf,"ORDER_%s",OrderTreeData[i].KeyName);
+ OrderTreeData[i].Position = (BYTE)db_get_b(NULL,CLUIFrameModule,buf,i);
+ OrderTreeData[i].Visible = (BOOL)db_get_b(NULL,CLUIFrameModule,OrderTreeData[i].KeyName,1);
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.lParam = (LPARAM)(&(OrderTreeData[i]));
+ tvis.item.pszText = TranslateTS(OrderTreeData[i].Name);
+ tvis.item.iImage = tvis.item.iSelectedImage = OrderTreeData[i].Visible;
+ TreeView_InsertItem(Tree,&tvis);
+ }
+
+ TVSORTCB sort = {0};
+ sort.hParent = NULL;
+ sort.lParam = 0;
+ sort.lpfnCompare = CompareFunc;
+ TreeView_SortChildrenCB(Tree,&sort,0);
+ return 0;
+}
+
+static int SaveOrderTree(HWND hwndDlg, HWND Tree)
+{
+ HTREEITEM ht;
+ BYTE pos = 0;
+ TVITEMA tvi = {0};
+ tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM;
+ ht = TreeView_GetRoot(Tree);
+ do {
+ TOrderTreeData * it = NULL;
+ tvi.hItem = ht;
+ TreeView_GetItemA(Tree,&tvi);
+ it = (TOrderTreeData*)(tvi.lParam);
+ {
+ char buf[250];
+ sprintf(buf,"ORDER_%s",it->KeyName);
+ db_set_b(NULL,CLUIFrameModule,buf,pos);
+ db_set_b(NULL,CLUIFrameModule,it->KeyName, it->Visible);
+ }
+ ht = TreeView_GetNextSibling(Tree,ht);
+ pos++;
+ }
+ while (ht);
+
+ return 0;
+}
+
+int LoadPositionsFromDB(BYTE * OrderPos)
+{
+ if (db_get_b(NULL,CLUIFrameModule,"ExtraCountStored",0) != SIZEOF(OrderTreeData)) {
+ DeleteAllSettingInOrder();
+ db_set_b(NULL,CLUIFrameModule,"ExtraCountStored",SIZEOF(OrderTreeData));
+ }
+
+ for (int i=0; i < SIZEOF(OrderTreeData); i++) {
+ char buf[256];
+ sprintf(buf,"ORDER_%s",OrderTreeData[i].KeyName);
+ OrderPos[OrderTreeData[i].ID-1] = (BYTE)db_get_b(NULL,CLUIFrameModule,buf,i);
+ }
+ return 0;
+}
+
+static int dragging = 0;
+static HANDLE hDragItem = NULL;
+
+INT_PTR CALLBACK DlgProcExtraIconsOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_EXTRAORDER),GWL_STYLE,GetWindowLongPtr(GetDlgItem(hwndDlg,IDC_EXTRAORDER),GWL_STYLE)|TVS_NOHSCROLL);
+ {
+ HIMAGELIST himlCheckBoxes;
+ himlCheckBoxes = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_COLOR32|ILC_MASK,2,2);
+ ImageList_AddIcon(himlCheckBoxes,LoadSmallIconShared(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_NOTICK)));
+ ImageList_AddIcon(himlCheckBoxes,LoadSmallIconShared(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_TICK)));
+ TreeView_SetImageList(GetDlgItem(hwndDlg,IDC_EXTRAORDER),himlCheckBoxes,TVSIL_NORMAL);
+ }
+ FillOrderTree(hwndDlg,GetDlgItem(hwndDlg,IDC_EXTRAORDER));
+ return TRUE;
+
+ case WM_COMMAND:
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ SaveOrderTree(hwndDlg,GetDlgItem(hwndDlg,IDC_EXTRAORDER));
+ ReAssignExtraIcons();
+ CLUI_ReloadCLUIOptions();
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ break;
+
+ case IDC_EXTRAORDER:
+ switch (((LPNMHDR)lParam)->code) {
+ case 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_ONITEMICON)
+ {
+ TVITEMA tvi;
+ tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ tvi.hItem = hti.hItem;
+ TreeView_GetItemA(((LPNMHDR)lParam)->hwndFrom,&tvi);
+ tvi.iImage = tvi.iSelectedImage = !tvi.iImage;
+ ((TOrderTreeData *)tvi.lParam)->Visible = tvi.iImage;
+ TreeView_SetItem(((LPNMHDR)lParam)->hwndFrom,&tvi);
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ }
+ }
+ break;
+
+ case TVN_BEGINDRAGA:
+ case TVN_BEGINDRAGW:
+ SetCapture(hwndDlg);
+ dragging = 1;
+ hDragItem = ((LPNMTREEVIEWA)lParam)->itemNew.hItem;
+ TreeView_SelectItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),hDragItem);
+ break;
+ }
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ if ( dragging) {
+ TVHITTESTINFO hti;
+ hti.pt.x = (short)LOWORD(lParam);
+ hti.pt.y = (short)HIWORD(lParam);
+ ClientToScreen(hwndDlg,&hti.pt);
+ ScreenToClient(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&hti.pt);
+ TreeView_HitTest(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&hti);
+ if (hti.flags & (TVHT_ONITEM|TVHT_ONITEMRIGHT)) {
+ HTREEITEM it = hti.hItem;
+ hti.pt.y -= TreeView_GetItemHeight(GetDlgItem(hwndDlg,IDC_EXTRAORDER))/2;
+ TreeView_HitTest(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&hti);
+ //TreeView_SetInsertMark(GetDlgItem(hwndDlg,IDC_EXTRAORDER),hti.hItem,1);
+ if ( !(hti.flags&TVHT_ABOVE))
+ TreeView_SetInsertMark(GetDlgItem(hwndDlg,IDC_EXTRAORDER),hti.hItem,1);
+ else
+ TreeView_SetInsertMark(GetDlgItem(hwndDlg,IDC_EXTRAORDER),it,0);
+ }
+ else {
+ if (hti.flags&TVHT_ABOVE) SendDlgItemMessage(hwndDlg,IDC_EXTRAORDER,WM_VSCROLL,MAKEWPARAM(SB_LINEUP,0),0);
+ if (hti.flags&TVHT_BELOW) SendDlgItemMessage(hwndDlg,IDC_EXTRAORDER,WM_VSCROLL,MAKEWPARAM(SB_LINEDOWN,0),0);
+ TreeView_SetInsertMark(GetDlgItem(hwndDlg,IDC_EXTRAORDER),NULL,0);
+ }
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ if ( dragging) {
+ TreeView_SetInsertMark(GetDlgItem(hwndDlg,IDC_EXTRAORDER),NULL,0);
+ dragging = 0;
+ ReleaseCapture();
+
+ TVHITTESTINFO hti;
+ TVITEM tvi;
+ hti.pt.x = (short)LOWORD(lParam);
+ hti.pt.y = (short)HIWORD(lParam);
+ ClientToScreen(hwndDlg,&hti.pt);
+ ScreenToClient(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&hti.pt);
+ hti.pt.y -= TreeView_GetItemHeight(GetDlgItem(hwndDlg,IDC_EXTRAORDER))/2;
+ TreeView_HitTest(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&hti);
+ if (hDragItem == hti.hItem) break;
+ if (hti.flags&TVHT_ABOVE) hti.hItem = TVI_FIRST;
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ tvi.hItem = (HTREEITEM)hDragItem;
+ TreeView_GetItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&tvi);
+ if (hti.flags&(TVHT_ONITEM|TVHT_ONITEMRIGHT) || (hti.hItem == TVI_FIRST)) {
+ TVINSERTSTRUCT tvis;
+ TCHAR name[128];
+ tvis.item.mask = TVIF_HANDLE|TVIF_PARAM|TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ tvis.item.stateMask = 0xFFFFFFFF;
+ tvis.item.pszText = name;
+ tvis.item.cchTextMax = sizeof(name);
+ tvis.item.hItem = (HTREEITEM)hDragItem;
+ tvis.item.iImage = tvis.item.iSelectedImage = ((TOrderTreeData *)tvi.lParam)->Visible;
+ TreeView_GetItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&tvis.item);
+ TreeView_DeleteItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),hDragItem);
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = hti.hItem;
+ TreeView_SelectItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),TreeView_InsertItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&tvis));
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ ImageList_Destroy(TreeView_SetImageList(GetDlgItem(hwndDlg,IDC_EXTRAORDER),NULL,TVSIL_NORMAL));
+ break;
+ }
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct
+{
+ char *name; // Tab name
+ int id; // Dialog id
+ DLGPROC wnd_proc; // Dialog function
+}
+static row_opt_items[] =
+{
+ { LPGEN("Row"), IDD_OPT_ITEM_ROW, DlgProcItemRowOpts },
+#ifdef _DEBUG
+ { LPGEN("Row design"), IDD_OPT_ROWTMPL, DlgTmplEditorOpts },
+#endif
+ { LPGEN("Avatar"), IDD_OPT_ITEM_AVATAR, DlgProcItemAvatarOpts },
+ { LPGEN("Icon"), IDD_OPT_ITEM_ICON, DlgProcItemIconOpts },
+ { LPGEN("Contact time"), IDD_OPT_ITEM_CONTACT_TIME, DlgProcItemContactTimeOpts },
+ { LPGEN("Text"), IDD_OPT_ITEM_TEXT, DlgProcItemTextOpts },
+ { LPGEN("Second Line"), IDD_OPT_ITEM_SECOND_LINE, DlgProcItemSecondLineOpts },
+ { LPGEN("Third Line"), IDD_OPT_ITEM_THIRD_LINE, DlgProcItemThirdLineOpts },
+ { LPGEN("Extra Icons"), IDD_OPT_ITEM_EXTRAICONS, DlgProcExtraIconsOpts}
+};
+
+int CListOptInit(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+ odp.cbSize = sizeof(odp);
+ odp.position = -200000000;
+ odp.hInstance = g_hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ITEMS);
+ odp.pszGroup = LPGEN("Contact List");
+ odp.pszTitle = LPGEN("Row items");
+ odp.flags = ODPF_BOLDGROUPS;
+
+ BOOL hasExtraIconsService = ServiceExists("ExtraIcon/Register");
+ for (int i=0; i < SIZEOF(row_opt_items); i++) {
+ if (hasExtraIconsService && row_opt_items[i].id == IDD_OPT_ITEM_EXTRAICONS)
+ continue;
+
+ odp.pszTemplate = MAKEINTRESOURCEA(row_opt_items[i].id);
+ odp.pszTab = row_opt_items[i].name;
+ odp.pfnDlgProc = row_opt_items[i].wnd_proc;
+ Options_AddPage(wParam, &odp);
+ }
+
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_clistsettings.cpp b/plugins/Clist_modern/src/modern_clistsettings.cpp
new file mode 100644
index 0000000000..cbea7018e0
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clistsettings.cpp
@@ -0,0 +1,531 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "m_clc.h"
+#include "hdr/modern_clist.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_awaymsg.h"
+
+void InsertContactIntoTree(HANDLE hContact,int status);
+static displayNameCacheEntry *displayNameCache;
+void CListSettings_FreeCacheItemDataOption( pdisplayNameCacheEntry pDst, DWORD flag );
+
+int PostAutoRebuidMessage(HWND hwnd);
+static int displayNameCacheSize;
+
+BOOL CLM_AUTOREBUILD_WAS_POSTED = FALSE;
+SortedList *clistCache = NULL;
+char *GetProtoForContact(HANDLE hContact);
+int GetStatusForContact(HANDLE hContact,char *szProto);
+TCHAR *UnknownConctactTranslatedName = NULL;
+
+void InvalidateDNCEbyPointer(HANDLE hContact,pdisplayNameCacheEntry pdnce,int SettingType);
+
+static int handleCompare( void* c1, void* c2 )
+{
+ INT_PTR p1, p2;
+
+ displayNameCacheEntry * dnce1 = (displayNameCacheEntry *)c1;
+ displayNameCacheEntry * dnce2 = (displayNameCacheEntry *)c2;
+
+ p1 = (INT_PTR)dnce1->hContact;
+ p2 = (INT_PTR)dnce2->hContact;
+
+ if ( p1 == p2 )
+ return 0;
+
+ return (int)(p1 - p2);
+}
+
+void InitCacheAsync();
+void UninitCacheAsync();
+
+void InitDisplayNameCache(void)
+{
+ int i=0;
+ InitCacheAsync();
+ InitAwayMsgModule();
+ clistCache = List_Create( 0, 50 );
+ clistCache->sortFunc = handleCompare;
+}
+
+void FreeDisplayNameCache()
+{
+ UninitCacheAsync();
+ UninitAwayMsgModule();
+ if ( clistCache != NULL ) {
+ int i;
+ for ( i=0; i < clistCache->realCount; i++) {
+ pcli->pfnFreeCacheItem(( ClcCacheEntryBase* )clistCache->items[i] );
+ mir_free_and_nil( clistCache->items[i] );
+ }
+
+ List_Destroy( clistCache );
+ mir_free(clistCache);
+ clistCache = NULL;
+ }
+}
+
+ClcCacheEntryBase* cliGetCacheEntry(HANDLE hContact)
+{
+ ClcCacheEntryBase* p;
+ int idx;
+ if ( !clistCache) return NULL;
+ if ( !List_GetIndex( clistCache, &hContact, &idx )) {
+ if (( p = pcli->pfnCreateCacheItem( hContact )) != NULL ) {
+ List_Insert( clistCache, p, idx );
+ pcli->pfnInvalidateDisplayNameCacheEntry( hContact );
+ }
+ }
+ else p = ( ClcCacheEntryBase* )clistCache->items[idx];
+ pcli->pfnCheckCacheItem( p );
+ return p;
+}
+
+void CListSettings_FreeCacheItemData(pdisplayNameCacheEntry pDst)
+{
+ CListSettings_FreeCacheItemDataOption( pDst, CCI_ALL);
+}
+
+void CListSettings_FreeCacheItemDataOption( pdisplayNameCacheEntry pDst, DWORD flag )
+{
+ if ( !pDst)
+ return;
+
+ if ( flag & CCI_NAME)
+ pDst->freeName();
+
+ if ( flag & CCI_GROUP )
+ mir_free_and_nil(pDst->tszGroup);
+
+ if ( flag & CCI_LINES ) {
+ mir_free_and_nil(pDst->szSecondLineText);
+ mir_free_and_nil(pDst->szThirdLineText);
+ pDst->ssSecondLine.DestroySmileyList();
+ pDst->ssThirdLine.DestroySmileyList();
+ }
+}
+
+int CListSettings_GetCopyFromCache(pdisplayNameCacheEntry pDest, DWORD flag);
+int CListSettings_SetToCache(pdisplayNameCacheEntry pSrc, DWORD flag);
+
+
+void CListSettings_CopyCacheItems(pdisplayNameCacheEntry pDst, pdisplayNameCacheEntry pSrc, DWORD flag)
+{
+ if ( !pDst || !pSrc) return;
+ CListSettings_FreeCacheItemDataOption(pDst, flag);
+
+ if ( flag & CCI_NAME ) {
+ pDst->isUnknown = pSrc->isUnknown;
+ if (pSrc->isUnknown)
+ pDst->tszName = pSrc->tszName;
+ else
+ pDst->tszName = mir_tstrdup(pSrc->tszName);
+ }
+
+ if ( flag & CCI_GROUP ) pDst->tszGroup = mir_tstrdup(pSrc->tszGroup);
+ if ( flag & CCI_PROTO ) pDst->m_cache_cszProto = pSrc->m_cache_cszProto;
+ if ( flag & CCI_STATUS ) pDst->m_cache_nStatus = pSrc->m_cache_nStatus;
+
+ if ( flag & CCI_LINES ) {
+ mir_free( pDst->szThirdLineText );
+ pDst->szThirdLineText = mir_tstrdup( pSrc->szThirdLineText );
+
+ mir_free( pDst->szSecondLineText );
+ pDst->szSecondLineText = mir_tstrdup( pSrc->szSecondLineText );
+
+ pDst->ssThirdLine = pSrc->ssThirdLine;
+ pDst->ssSecondLine = pSrc->ssSecondLine;
+ }
+
+ if ( flag & CCI_TIME)
+ pDst->hTimeZone = pSrc->hTimeZone;
+
+ if ( flag & CCI_OTHER) {
+ pDst->bIsHidden = pSrc->bIsHidden;
+ pDst->m_cache_nNoHiddenOffline = pSrc->m_cache_nNoHiddenOffline;
+ pDst->m_cache_bProtoNotExists = pSrc->m_cache_bProtoNotExists;
+
+ pDst->m_cache_nHiddenSubcontact = pSrc->m_cache_nHiddenSubcontact;
+ pDst->i = pSrc->i;
+ pDst->ApparentMode = pSrc->ApparentMode;
+ pDst->NotOnList = pSrc->NotOnList;
+ pDst->IdleTS = pSrc->IdleTS;
+ pDst->ClcContact = pSrc->ClcContact;
+ pDst->IsExpanded = pSrc->IsExpanded;
+ }
+}
+
+int CListSettings_GetCopyFromCache(pdisplayNameCacheEntry pDest, DWORD flag)
+{
+ if ( !pDest || !pDest->hContact)
+ return -1;
+
+ pdisplayNameCacheEntry pSource = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(pDest->hContact);
+ if ( !pSource)
+ return -1;
+
+ CListSettings_CopyCacheItems(pDest, pSource, flag);
+ return 0;
+}
+
+int CListSettings_SetToCache(pdisplayNameCacheEntry pSrc, DWORD flag)
+{
+ if ( !pSrc || !pSrc->hContact)
+ return -1;
+
+ pdisplayNameCacheEntry pDst = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(pSrc->hContact);
+ if ( !pDst)
+ return -1;
+
+ CListSettings_CopyCacheItems(pDst, pSrc, flag);
+ return 0;
+}
+
+void cliFreeCacheItem( pdisplayNameCacheEntry p )
+{
+ HANDLE hContact = p->hContact;
+ TRACEVAR("cliFreeCacheItem hContact = %d",hContact);
+ p->freeName();
+ mir_free_and_nil(p->tszGroup);
+ mir_free_and_nil(p->szSecondLineText);
+ mir_free_and_nil(p->szThirdLineText);
+ p->ssSecondLine.DestroySmileyList();
+ p->ssThirdLine.DestroySmileyList();
+}
+
+void cliCheckCacheItem(pdisplayNameCacheEntry pdnce)
+{
+ if (pdnce == NULL)
+ return;
+
+ if (pdnce->hContact == NULL) { //selfcontact
+ if ( !pdnce->tszName)
+ pdnce->getName();
+ return;
+ }
+
+ if (pdnce->m_cache_cszProto == NULL && pdnce->m_cache_bProtoNotExists == FALSE) {
+ pdnce->m_cache_cszProto = GetProtoForContact(pdnce->hContact);
+ if (pdnce->m_cache_cszProto == NULL)
+ pdnce->m_cache_bProtoNotExists = FALSE;
+ else if (CallService(MS_PROTO_ISPROTOCOLLOADED,0,(LPARAM)pdnce->m_cache_cszProto) == (int)NULL && 0)
+ pdnce->m_cache_bProtoNotExists = TRUE;
+ else if (pdnce->m_cache_cszProto && pdnce->tszName)
+ pdnce->freeName();
+ }
+
+ if (pdnce->tszName == NULL)
+ pdnce->getName();
+
+ else if (pdnce->isUnknown && pdnce->m_cache_cszProto && pdnce->m_cache_bProtoNotExists == TRUE && g_flag_bOnModulesLoadedCalled) {
+ if (CallService(MS_PROTO_ISPROTOCOLLOADED,0,(LPARAM)pdnce->m_cache_cszProto) == 0) {
+ pdnce->m_cache_bProtoNotExists = FALSE;
+ pdnce->getName();
+ }
+ }
+
+ if (pdnce___GetStatus( pdnce ) == 0) //very strange look status sort is broken let always reread status
+ pdnce___SetStatus( pdnce , GetStatusForContact(pdnce->hContact,pdnce->m_cache_cszProto));
+
+ if (pdnce->tszGroup == NULL) {
+ DBVARIANT dbv = {0};
+ if ( !DBGetContactSettingTString(pdnce->hContact,"CList","Group",&dbv)) {
+ pdnce->tszGroup = mir_tstrdup(dbv.ptszVal);
+ db_free(&dbv);
+ }
+ else pdnce->tszGroup = mir_tstrdup(_T(""));
+ }
+
+ if (pdnce->bIsHidden == -1)
+ pdnce->bIsHidden = db_get_b(pdnce->hContact,"CList","Hidden",0);
+
+ pdnce->m_cache_nHiddenSubcontact = g_szMetaModuleName && db_get_b(pdnce->hContact,g_szMetaModuleName,"IsSubcontact",0);
+
+ if (pdnce->m_cache_nNoHiddenOffline == -1)
+ pdnce->m_cache_nNoHiddenOffline = db_get_b(pdnce->hContact,"CList","noOffline",0);
+
+ if (pdnce->IdleTS == -1)
+ pdnce->IdleTS = db_get_dw(pdnce->hContact,pdnce->m_cache_cszProto,"IdleTS",0);
+
+ if (pdnce->ApparentMode == -1)
+ pdnce->ApparentMode = db_get_w(pdnce->hContact,pdnce->m_cache_cszProto,"ApparentMode",0);
+
+ if (pdnce->NotOnList == -1)
+ pdnce->NotOnList = db_get_b(pdnce->hContact,"CList","NotOnList",0);
+
+ if (pdnce->IsExpanded == -1)
+ pdnce->IsExpanded = db_get_b(pdnce->hContact,"CList","Expanded",0);
+
+ if (pdnce->dwLastMsgTime == 0) {
+ pdnce->dwLastMsgTime = db_get_dw(pdnce->hContact, "CList", "mf_lastmsg", 0);
+ if (pdnce->dwLastMsgTime == 0)
+ pdnce->dwLastMsgTime = CompareContacts2_getLMTime(pdnce->hContact);
+ }
+}
+
+void IvalidateDisplayNameCache(DWORD mode)
+{
+ if ( clistCache != NULL )
+ {
+ int i;
+ for ( i=0; i < clistCache->realCount; i++)
+ {
+ PDNCE pdnce = (PDNCE)clistCache->items[i];
+ if (mode&16)
+ {
+ InvalidateDNCEbyPointer(pdnce->hContact,pdnce,16);
+ }
+ }
+ }
+}
+
+void InvalidateDNCEbyPointer(HANDLE hContact, pdisplayNameCacheEntry pdnce, int SettingType)
+{
+ if (hContact == NULL || pdnce == NULL)
+ return;
+
+ if (SettingType == 16) {
+ pdnce->ssSecondLine.DestroySmileyList();
+ mir_free_and_nil(pdnce->szSecondLineText);
+ pdnce->ssThirdLine.DestroySmileyList();
+ mir_free_and_nil(pdnce->szThirdLineText);
+ pdnce->ssSecondLine.iMaxSmileyHeight = 0;
+ pdnce->ssThirdLine.iMaxSmileyHeight = 0;
+ pdnce->hTimeZone = NULL;
+ pdnce->dwLastMsgTime = 0;
+ Cache_GetTimezone(NULL,pdnce->hContact);
+ SettingType &= ~16;
+ }
+
+ if (SettingType >= DBVT_WCHAR) {
+ pdnce->freeName();
+ mir_free_and_nil(pdnce->tszGroup);
+ pdnce->m_cache_cszProto = NULL;
+ return;
+ }
+
+ if (SettingType == -1 || SettingType == DBVT_DELETED) {
+ pdnce->freeName();
+ mir_free_and_nil(pdnce->tszGroup);
+ pdnce->m_cache_cszProto = NULL;
+ }
+ // in other cases clear all binary cache
+ else pdnce->dwLastMsgTime = 0;
+
+ pdnce->bIsHidden = -1;
+ pdnce->m_cache_nHiddenSubcontact = -1;
+ pdnce->m_cache_bProtoNotExists = FALSE;
+ pdnce___SetStatus(pdnce, 0);
+ pdnce->IdleTS = -1;
+ pdnce->ApparentMode = -1;
+ pdnce->NotOnList = -1;
+ pdnce->isUnknown = FALSE;
+ pdnce->m_cache_nNoHiddenOffline = -1;
+ pdnce->IsExpanded = -1;
+}
+
+char *GetContactCachedProtocol(HANDLE hContact)
+{
+ pdisplayNameCacheEntry cacheEntry = NULL;
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ if (cacheEntry && cacheEntry->m_cache_cszProto)
+ return cacheEntry->m_cache_cszProto;
+
+ return NULL;
+}
+
+char* GetProtoForContact(HANDLE hContact)
+{
+ return (char*)CallService(MS_PROTO_GETCONTACTBASEACCOUNT,(WPARAM)hContact,0);
+}
+
+int GetStatusForContact(HANDLE hContact,char *szProto)
+{
+ return (szProto) ? (int)(db_get_w((HANDLE)hContact,szProto,"Status",ID_STATUS_OFFLINE)) : ID_STATUS_OFFLINE;
+}
+
+void displayNameCacheEntry::freeName()
+{
+ if ( !isUnknown)
+ mir_free(tszName);
+ else
+ isUnknown = false;
+ tszName = NULL;
+}
+
+void displayNameCacheEntry::getName()
+{
+ if (UnknownConctactTranslatedName == NULL)
+ UnknownConctactTranslatedName = TranslateT("(Unknown Contact)");
+
+ freeName();
+
+ if (m_cache_bProtoNotExists || !m_cache_cszProto) {
+LBL_Unknown:
+ tszName = UnknownConctactTranslatedName;
+ isUnknown = true;
+ return;
+ }
+
+ tszName = pcli->pfnGetContactDisplayName(hContact, GCDNF_NOCACHE);
+ if ( !lstrcmp(tszName, UnknownConctactTranslatedName)) {
+ mir_free(tszName);
+ goto LBL_Unknown;
+ }
+
+ isUnknown = false;
+}
+
+int GetContactInfosForSort(HANDLE hContact,char **Proto,TCHAR **Name,int *Status)
+{
+ pdisplayNameCacheEntry cacheEntry = NULL;
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ if (cacheEntry != NULL)
+ {
+ if (Proto != NULL) *Proto = cacheEntry->m_cache_cszProto;
+ if (Name != NULL) *Name = cacheEntry->tszName;
+ if (Status != NULL) *Status = pdnce___GetStatus( cacheEntry );
+ }
+ return (0);
+};
+
+
+int GetContactCachedStatus(HANDLE hContact)
+{
+ pdisplayNameCacheEntry cacheEntry = NULL;
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ return pdnce___GetStatus( cacheEntry );
+}
+
+int ContactAdded(WPARAM wParam,LPARAM lParam)
+{
+ if ( !MirandaExiting()) {
+ HANDLE hContact = (HANDLE)wParam;
+ cli_ChangeContactIcon(hContact,ExtIconFromStatusMode(hContact,(char*)GetContactCachedProtocol(hContact),ID_STATUS_OFFLINE),1); ///by FYR
+ pcli->pfnSortContacts();
+ }
+ return 0;
+}
+
+int ContactSettingChanged(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ if (MirandaExiting() || !pcli || !clistCache || hContact == NULL)
+ return 0;
+
+ pdisplayNameCacheEntry pdnce = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ if (pdnce == NULL) {
+ TRACE("!!! Very bad pdnce not found.");
+ return 0;
+ }
+
+ if (pdnce->m_cache_bProtoNotExists || !pdnce->m_cache_cszProto)
+ return 0;
+
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam;
+ if ( !strcmp(cws->szModule, pdnce->m_cache_cszProto)) {
+ InvalidateDNCEbyPointer(hContact, pdnce, cws->value.type);
+
+ if ( !strcmp(cws->szSetting,"IsSubcontact"))
+ PostMessage(pcli->hwndContactTree,CLM_AUTOREBUILD,0,0);
+
+ if ( !mir_strcmp(cws->szSetting, "Status") || wildcmp((char*)cws->szSetting, (char*) "Status?",2)) {
+ if (g_szMetaModuleName && !mir_strcmp(cws->szModule,g_szMetaModuleName) && mir_strcmp(cws->szSetting, "Status")) {
+ int res = 0;
+ if (pcli->hwndContactTree && g_flag_bOnModulesLoadedCalled)
+ res = PostAutoRebuidMessage(pcli->hwndContactTree);
+
+ if ((db_get_w(NULL,"CList","SecondLineType",SETTING_SECONDLINE_TYPE_DEFAULT) == TEXT_STATUS_MESSAGE || db_get_w(NULL,"CList","ThirdLineType",SETTING_THIRDLINE_TYPE_DEFAULT) == TEXT_STATUS_MESSAGE) && pdnce->hContact && pdnce->m_cache_cszProto)
+ amRequestAwayMsg(hContact);
+
+ return 0;
+ }
+
+ if (pdnce->bIsHidden != 1) {
+ pdnce___SetStatus( pdnce , cws->value.wVal ); //dont use direct set
+ if (cws->value.wVal == ID_STATUS_OFFLINE)
+ if (g_CluiData.bRemoveAwayMessageForOffline)
+ db_set_s(hContact,"CList","StatusMsg","");
+
+ if ((db_get_w(NULL,"CList","SecondLineType",0) == TEXT_STATUS_MESSAGE || db_get_w(NULL,"CList","ThirdLineType",0) == TEXT_STATUS_MESSAGE) && pdnce->hContact && pdnce->m_cache_cszProto)
+ amRequestAwayMsg(hContact);
+
+ pcli->pfnClcBroadcast( INTM_STATUSCHANGED,wParam,0);
+ cli_ChangeContactIcon(hContact, ExtIconFromStatusMode(hContact,cws->szModule, cws->value.wVal), 0); //by FYR
+ pcli->pfnSortContacts();
+ }
+ else {
+ if ( !(!mir_strcmp(cws->szSetting, "LogonTS") || !mir_strcmp(cws->szSetting, "TickTS") || !mir_strcmp(cws->szSetting, "InfoTS")))
+ pcli->pfnSortContacts();
+
+ return 0;
+ }
+ }
+ }
+
+ if ( !strcmp(cws->szModule,"CList")) {
+ //name is null or (setting is myhandle)
+ if ( !strcmp(cws->szSetting,"Rate"))
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+
+ else if (pdnce->tszName == NULL || !strcmp(cws->szSetting,"MyHandle"))
+ InvalidateDNCEbyPointer(hContact,pdnce,cws->value.type);
+
+ else if ( !strcmp(cws->szSetting,"Group"))
+ InvalidateDNCEbyPointer(hContact,pdnce,cws->value.type);
+
+ else if ( !strcmp(cws->szSetting,"Hidden")) {
+ InvalidateDNCEbyPointer(hContact,pdnce,cws->value.type);
+ if (cws->value.type == DBVT_DELETED || cws->value.bVal == 0)
+ {
+ char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,wParam,0);
+ cli_ChangeContactIcon(hContact,ExtIconFromStatusMode(hContact,szProto,szProto == NULL?ID_STATUS_OFFLINE:db_get_w(hContact,szProto,"Status",ID_STATUS_OFFLINE)),1); //by FYR
+ }
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD,0, 0);
+ }
+ else if ( !strcmp(cws->szSetting,"noOffline")) {
+ InvalidateDNCEbyPointer(hContact,pdnce,cws->value.type);
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD,0, 0);
+ }
+ }
+ else if ( !strcmp(cws->szModule,"Protocol")) {
+ if ( !strcmp(cws->szSetting,"p")) {
+ char *szProto;
+ InvalidateDNCEbyPointer(hContact,pdnce,cws->value.type);
+ if (cws->value.type == DBVT_DELETED) szProto = NULL;
+ else szProto = cws->value.pszVal;
+ cli_ChangeContactIcon(hContact,ExtIconFromStatusMode(hContact,szProto,szProto == NULL?ID_STATUS_OFFLINE:db_get_w(hContact,szProto,"Status",ID_STATUS_OFFLINE)),0); //by FYR
+ }
+ }
+
+ return 0;
+}
+
+int PostAutoRebuidMessage(HWND hwnd)
+{
+ if ( !CLM_AUTOREBUILD_WAS_POSTED)
+ CLM_AUTOREBUILD_WAS_POSTED = PostMessage(hwnd,CLM_AUTOREBUILD,0,0);
+ return CLM_AUTOREBUILD_WAS_POSTED;
+}
diff --git a/plugins/Clist_modern/src/modern_clisttray.cpp b/plugins/Clist_modern/src/modern_clisttray.cpp
new file mode 100644
index 0000000000..28963f200d
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clisttray.cpp
@@ -0,0 +1,736 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include <m_clui.h>
+#include "hdr/modern_clist.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_statusbar.h"
+
+int cliShowHide(WPARAM wParam,LPARAM lParam);
+int g_mutex_bOnTrayRightClick = 0;
+
+BOOL g_bMultiConnectionMode = FALSE;
+static int RefreshTimerId = 0; /////by FYR
+static VOID CALLBACK RefreshTimerProc(HWND hwnd,UINT message,UINT idEvent,DWORD dwTime); ///// by FYR
+static HMENU hMainMenu, hStatusMenu;
+BOOL IS_WM_MOUSE_DOWN_IN_TRAY;
+
+BOOL g_trayTooltipActive = FALSE;
+POINT tray_hover_pos = {0};
+
+// don't move to win2k.h, need new and old versions to work on 9x/2000/XP
+#define NIF_STATE 0x00000008
+#define NIF_INFO 0x00000010
+
+#ifndef _INC_SHLWAPI
+
+typedef struct _DllVersionInfo {
+ DWORD cbSize;
+ DWORD dwMajorVersion; // Major version
+ DWORD dwMinorVersion; // Minor version
+ DWORD dwBuildNumber; // Build number
+ DWORD dwPlatformID; // DLLVER_PLATFORM_*
+} DLLVERSIONINFO;
+
+#define DLLVER_PLATFORM_WINDOWS 0x00000001 // Windows 95
+#define DLLVER_PLATFORM_NT 0x00000002 // Windows NT
+typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *);
+
+#endif
+
+void mir_strset(TCHAR ** dest, TCHAR *source)
+{
+ if (*dest) mir_free_and_nil(*dest);
+ if (source) *dest = mir_tstrdup(source);
+}
+
+static DLLVERSIONINFO dviShell;
+BOOL g_MultiConnectionMode = FALSE;
+char * g_szConnectingProto = NULL;
+int GetStatusVal(int status)
+{
+ switch ( status ) {
+ case ID_STATUS_OFFLINE: return 50;
+ case ID_STATUS_ONLINE: return 100;
+ case ID_STATUS_FREECHAT: return 110;
+ case ID_STATUS_INVISIBLE: return 120;
+ case ID_STATUS_AWAY: return 200;
+ case ID_STATUS_DND: return 210;
+ case ID_STATUS_NA: return 220;
+ case ID_STATUS_OCCUPIED: return 230;
+ case ID_STATUS_ONTHEPHONE: return 400;
+ case ID_STATUS_OUTTOLUNCH: return 410;
+ }
+ if (status < ID_STATUS_OFFLINE && status>0) return 600; //connecting is most priority
+ return 0;
+}
+
+int GetStatusOrder(int currentStatus, int newStatus)
+{
+ int current = GetStatusVal(currentStatus);
+ int newstat = GetStatusVal(newStatus);
+ return (current>newstat)?currentStatus:newStatus;
+}
+
+INT_PTR CListTray_GetGlobalStatus(WPARAM wparam,LPARAM lparam)
+{
+ int curstatus = 0;
+ int i;
+ int connectingCount = 0;
+ for (i=0;i < pcli->hClcProtoCount;i++)
+ {
+ if ( !pcli->pfnGetProtocolVisibility(pcli->clcProto[i].szProto)) continue;
+ if (pcli->clcProto[i].dwStatus >= ID_STATUS_CONNECTING &&
+ pcli->clcProto[i].dwStatus < ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES)
+ {
+ connectingCount++;
+ if (connectingCount == 1) g_szConnectingProto = pcli->clcProto[i].szProto;
+ }
+ curstatus = GetStatusOrder(curstatus,pcli->clcProto[i].dwStatus);
+ }
+ if (connectingCount == 0)
+ {
+ //g_szConnectingProto = NULL;
+ g_bMultiConnectionMode = FALSE;
+ }
+ else if (connectingCount>1)
+ g_bMultiConnectionMode = TRUE;
+ else
+ g_bMultiConnectionMode = FALSE;
+ return curstatus?curstatus:ID_STATUS_OFFLINE;
+}
+
+int GetAverageMode()
+{
+ int count,netProtoCount,i;
+ int averageMode = 0;
+ PROTOACCOUNT **accs;
+ ProtoEnumAccounts( &count, &accs );
+ for (i=0,netProtoCount = 0;i < count;i++) {
+ if ( pcli->pfnGetProtocolVisibility(accs[i]->szModuleName) == 0 ) continue;
+ pcli->cycleStep = i;
+ netProtoCount++;
+ if (averageMode == 0) averageMode = CallProtoService(accs[i]->szModuleName,PS_GETSTATUS,0,0);
+ else if (averageMode != CallProtoService(accs[i]->szModuleName,PS_GETSTATUS,0,0)) {averageMode = -1; break;}
+ }
+ return averageMode;
+}
+
+////////////////////////////////////////////////////////////
+///// Need to refresh trays icon after timely changing/////
+////////////////////////////////////////////////////////////
+
+static VOID CALLBACK RefreshTimerProc(HWND hwnd,UINT message,UINT idEvent,DWORD dwTime)
+{
+ int count,i;
+ PROTOACCOUNT **accs;
+
+ if (RefreshTimerId) {KillTimer(NULL,RefreshTimerId); RefreshTimerId = 0;}
+
+ ProtoEnumAccounts( &count, &accs );
+ for (i=0; i < count; i++)
+ if ( pcli->pfnGetProtocolVisibility(accs[i]->szModuleName))
+ pcli->pfnTrayIconUpdateBase(accs[i]->szModuleName);
+
+}
+//////// End by FYR /////////
+
+void cliTrayIconUpdateBase(const char *szChangedProto)
+{
+ int i,count,netProtoCount,changed = -1;
+ PROTOACCOUNT **accs;
+ int averageMode = 0;
+ HWND hwnd = pcli->hwndContactList;
+
+ if ( !szChangedProto) return;
+
+ if ( !pcli->pfnGetProtocolVisibility(szChangedProto)) return;
+
+ pcli->pfnLockTray();
+ if ( pcli->cycleTimerId ) {
+ KillTimer( NULL, pcli->cycleTimerId);
+ pcli->cycleTimerId = 0;
+ }
+ ProtoEnumAccounts( &count, &accs );
+ for (i=0,netProtoCount = 0;i < count;i++) {
+ if ( pcli->pfnGetProtocolVisibility(accs[i]->szModuleName) == 0 ) continue;
+ netProtoCount++;
+ if ( !lstrcmpA(szChangedProto,accs[i]->szModuleName)) pcli->cycleStep = i;
+ if (averageMode == 0) averageMode = CallProtoService(accs[i]->szModuleName,PS_GETSTATUS,0,0);
+ else if (averageMode != CallProtoService(accs[i]->szModuleName,PS_GETSTATUS,0,0)) {averageMode = -1; break;}
+ }
+
+ if (netProtoCount>1) {
+ if (averageMode >= ID_STATUS_OFFLINE) {
+ if (db_get_b(NULL,"CList","TrayIcon",SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_MULTI) {
+ if (db_get_b(NULL,"CList","AlwaysMulti",SETTING_ALWAYSMULTI_DEFAULT))
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,szChangedProto,averageMode),szChangedProto);
+ else if (pcli->trayIcon && pcli->trayIcon[0].szProto != NULL) {
+ pcli->pfnTrayIconDestroy(hwnd);
+ pcli->pfnTrayIconInit(hwnd);
+ }
+ else
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,NULL,averageMode),NULL);
+ }
+ else
+ {
+ if (db_get_b(NULL,"CList","TrayIcon",SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_SINGLE
+ && db_get_b(NULL,"CList","AlwaysPrimary",SETTING_ALWAYSPRIMARY_DEFAULT))
+ {
+ DBVARIANT dbv = {DBVT_DELETED};
+ char *szProto;
+ if (DBGetContactSettingString(NULL,"CList","PrimaryStatus",&dbv)) szProto = NULL;
+ else szProto = dbv.pszVal;
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,szProto,averageMode),NULL);
+ mir_free(szProto);
+ }
+ else
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,NULL,averageMode),NULL);
+ }
+ }
+ else {
+ switch(db_get_b(NULL,"CList","TrayIcon",SETTING_TRAYICON_DEFAULT)) {
+ case SETTING_TRAYICON_SINGLE:
+ {
+ DBVARIANT dbv = {DBVT_DELETED};
+ char *szProto;
+ int status;
+ if (DBGetContactSettingString(NULL,"CList","PrimaryStatus",&dbv)) szProto = NULL;
+ else szProto = dbv.pszVal;
+ status = CallProtoService(szChangedProto,PS_GETSTATUS,0,0);
+
+ if ((g_StatusBarData.connectingIcon == 1) && status >= ID_STATUS_CONNECTING && status <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES) {
+ //
+ HICON hIcon;
+ // 1 check if multi connecting icon
+ CListTray_GetGlobalStatus(0,0);
+ if (g_bMultiConnectionMode)
+ if (_strcmpi(szChangedProto,g_szConnectingProto))
+ { pcli->pfnUnlockTray(); return; }
+ else
+ hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)"",1);
+ else
+ hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)szChangedProto,0);
+ if (hIcon) {
+ changed = pcli->pfnTrayIconSetBaseInfo(hIcon,NULL);
+ db_free(&dbv);
+ break;
+ }
+ }
+ else
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,szProto,szProto?CallProtoService(szProto,PS_GETSTATUS,0,0):CallService(MS_CLIST_GETSTATUSMODE,0,0)),NULL);
+
+ db_free(&dbv);
+ }
+ break;
+
+ case SETTING_TRAYICON_CYCLE:
+ {
+ int status = szChangedProto ? CallProtoService(szChangedProto,PS_GETSTATUS,0,0) : averageMode;
+ if ((g_StatusBarData.connectingIcon == 1 && CListTray_GetGlobalStatus(0,0)
+ && ((status >= ID_STATUS_CONNECTING && status <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES) || g_bMultiConnectionMode )))
+ {
+ //connecting
+ status = status;
+ //stop cycling
+ if (pcli->cycleTimerId)
+ KillTimer(NULL,pcli->cycleTimerId);
+ pcli->cycleTimerId = 0;
+ {
+ HICON hIcon;
+ // 1 check if multi connecting icon
+ if (g_bMultiConnectionMode)
+ if (_strcmpi(szChangedProto,g_szConnectingProto))
+ { pcli->pfnUnlockTray(); return; }
+ else
+ hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)"",1);
+ else
+ hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)szChangedProto,0);
+ if (hIcon)
+ changed = pcli->pfnTrayIconSetBaseInfo(hIcon,NULL);
+ }
+ }
+ else
+ {
+ pcli->cycleTimerId = CLUI_SafeSetTimer(NULL,0,db_get_w(NULL,"CList","CycleTime",SETTING_CYCLETIME_DEFAULT)*1000,pcli->pfnTrayCycleTimerProc);
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,szChangedProto,status),NULL);
+ }
+
+ }
+ break;
+
+ case SETTING_TRAYICON_MULTI:
+ if ( !pcli->trayIcon)
+ pcli->pfnTrayIconRemove(NULL,NULL);
+ else if ( db_get_b(NULL,"CList","AlwaysMulti",SETTING_ALWAYSMULTI_DEFAULT )) {
+ if (pcli->pfnGetProtocolVisibility(szChangedProto))
+ {
+
+ int status;
+ status = CallProtoService(szChangedProto,PS_GETSTATUS,0,0);
+ if ((g_StatusBarData.connectingIcon == 1) && status >= ID_STATUS_CONNECTING && status <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES)
+ {
+ //
+ HICON hIcon;
+ hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)szChangedProto,0);;
+ if (hIcon)
+ changed = pcli->pfnTrayIconSetBaseInfo(hIcon,szChangedProto);
+ }
+ else
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,szChangedProto,CallProtoService(szChangedProto,PS_GETSTATUS,0,0)),szChangedProto);
+ }
+ }
+ else if (pcli->pfnGetProtocolVisibility(szChangedProto)) {
+ int i;
+ int avg;
+ avg = GetAverageMode();
+ i = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,szChangedProto,CallProtoService(szChangedProto,PS_GETSTATUS,0,0)),szChangedProto);
+ if (i < 0 /* || (avg != -1)*/) {
+ pcli->pfnTrayIconDestroy(hwnd);
+ pcli->pfnTrayIconInit(hwnd);
+ }
+ else {
+ int status;
+ changed = i;
+ status = CallProtoService(szChangedProto,PS_GETSTATUS,0,0);
+ if ((g_StatusBarData.connectingIcon == 1) && status >= ID_STATUS_CONNECTING && status <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES) {
+ //
+ HICON hIcon;
+ hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)szChangedProto,0);;
+ if (hIcon) {
+ changed = pcli->pfnTrayIconSetBaseInfo(hIcon,szChangedProto);
+ } } } }
+ break;
+ } }
+ }
+ else if ( pcli->pfnGetProtocolVisibility( szChangedProto ))
+ {
+ DBVARIANT dbv = {DBVT_DELETED};
+ char *szProto;
+ int status = CallProtoService(szChangedProto,PS_GETSTATUS,0,0);
+
+ if ((g_StatusBarData.connectingIcon == 1) && status >= ID_STATUS_CONNECTING && status <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES)
+ {
+ HICON hIcon = ( HICON )CLUI_GetConnectingIconService((WPARAM)szChangedProto,0);;
+ if (hIcon)
+ changed = pcli->pfnTrayIconSetBaseInfo(hIcon,NULL);
+ }
+ else if (status >= ID_STATUS_OFFLINE && status <= ID_STATUS_IDLE)
+ {
+ if (DBGetContactSettingString(NULL,"CList","PrimaryStatus",&dbv))
+ szProto = NULL;
+ else
+ szProto = dbv.pszVal;
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,szProto,status),NULL);
+ mir_free(szProto);
+ }
+ }
+
+ if (changed != -1) // && pcli->trayIcon[changed].isBase)
+ pcli->pfnTrayIconUpdate(pcli->trayIcon[changed].hBaseIcon,NULL,szChangedProto,1); // by FYR (No suitable protocol)
+ { pcli->pfnUnlockTray(); return; }
+}
+
+static UINT_PTR autoHideTimerId;
+
+static VOID CALLBACK TrayIconAutoHideTimer(HWND hwnd,UINT message,UINT_PTR idEvent,DWORD dwTime)
+{
+ HWND hwndClui, ActiveWindow;
+ KillTimer(hwnd,idEvent);
+ hwndClui = pcli->hwndContactList;
+ ActiveWindow = GetActiveWindow();
+ if (ActiveWindow == hwndClui) return;
+ if (CLUI_CheckOwnedByClui(ActiveWindow)) return;
+ //CLUI_ShowWindowMod(hwndClui,SW_HIDE);
+ CListMod_HideWindow(hwndClui, SW_HIDE);
+ if (MySetProcessWorkingSetSize != NULL)
+ MySetProcessWorkingSetSize(GetCurrentProcess(),-1,-1);
+}
+
+INT_PTR TrayIconPauseAutoHide(WPARAM wParam,LPARAM lParam)
+{
+ if (db_get_b(NULL,"CList","AutoHide",SETTING_AUTOHIDE_DEFAULT))
+ {
+ if (GetActiveWindow() != pcli->hwndContactList
+ && GetWindow(GetParent(GetActiveWindow()),GW_OWNER) != pcli->hwndContactList)
+ {
+ KillTimer(NULL,autoHideTimerId);
+ autoHideTimerId = CLUI_SafeSetTimer(NULL,0,1000*db_get_w(NULL,"CList","HideTime",SETTING_HIDETIME_DEFAULT),TrayIconAutoHideTimer);
+ } }
+
+ return 0;
+}
+
+void DestroyTrayMenu(HMENU hMenu)
+{
+ int cnt = GetMenuItemCount(hMenu);
+ for (int i=0; i < cnt; ++i)
+ {
+ HMENU hSubMenu = GetSubMenu(hMenu, i);
+ if (hSubMenu == hStatusMenu || hSubMenu == hMainMenu)
+ RemoveMenu(hMenu, i--, MF_BYPOSITION);
+ }
+ DestroyMenu(hMenu);
+}
+
+INT_PTR cli_TrayIconProcessMessage(WPARAM wParam,LPARAM lParam)
+{
+ MSG *msg = (MSG*)wParam;
+ switch(msg->message) {
+ case WM_EXITMENULOOP:
+ if (pcli->bTrayMenuOnScreen)
+ pcli->bTrayMenuOnScreen = FALSE;
+ break;
+
+ // case WM_DRAWITEM:
+ // return CallService(MS_CLIST_MENUDRAWITEM,msg->wParam,msg->lParam);
+
+ // case WM_MEASUREITEM:
+ // return CallService(MS_CLIST_MENUMEASUREITEM,msg->wParam,msg->lParam);
+
+
+ case WM_ACTIVATE:
+ {
+ HWND h1,h2,h4;
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ h1 = (HWND)msg->lParam;
+ h2 = h1?GetParent(h1):NULL;
+ h4 = pcli->hwndContactList;
+ if (db_get_b(NULL,"CList","AutoHide",SETTING_AUTOHIDE_DEFAULT)) {
+ if (LOWORD(msg->wParam) == WA_INACTIVE && h2 != h4)
+ autoHideTimerId = CLUI_SafeSetTimer(NULL,0,1000*db_get_w(NULL,"CList","HideTime",SETTING_HIDETIME_DEFAULT),TrayIconAutoHideTimer);
+ else {
+ KillTimer(NULL,autoHideTimerId);
+ autoHideTimerId = 0;
+ }
+ }
+ else if (autoHideTimerId) {
+ KillTimer(NULL, autoHideTimerId);
+ autoHideTimerId = 0;
+ }
+ }
+ return FALSE; //to avoid autohideTimer in core
+
+ case TIM_CALLBACK:
+ if ((GetAsyncKeyState(VK_CONTROL)&0x8000) && msg->lParam == WM_LBUTTONDOWN && !db_get_b(NULL,"CList","Tray1Click",SETTING_TRAY1CLICK_DEFAULT)) {
+ POINT pt;
+ HMENU hMenu;
+ hMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,(WPARAM)0,(LPARAM)0);
+ g_mutex_bOnTrayRightClick = 1;
+ IS_WM_MOUSE_DOWN_IN_TRAY = 1;
+ SetForegroundWindow(msg->hwnd);
+ SetFocus(msg->hwnd);
+ GetCursorPos(&pt);
+ pcli->bTrayMenuOnScreen = TRUE;
+ TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, msg->hwnd, NULL);
+ PostMessage(msg->hwnd, WM_NULL, 0, 0);
+ g_mutex_bOnTrayRightClick = 0;
+ IS_WM_MOUSE_DOWN_IN_TRAY = 0;
+ }
+ else if (msg->lParam == WM_MBUTTONDOWN || msg->lParam == WM_LBUTTONDOWN || msg->lParam == WM_RBUTTONDOWN) {
+ IS_WM_MOUSE_DOWN_IN_TRAY = 1;
+ }
+ else if (msg->lParam == WM_RBUTTONUP) {
+ POINT pt;
+ HMENU hMenu;
+ hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDTRAY,(WPARAM)0,(LPARAM)0);
+ g_mutex_bOnTrayRightClick = 1;
+
+ SetForegroundWindow(msg->hwnd);
+ SetFocus(msg->hwnd);
+
+ GetCursorPos(&pt);
+ pcli->bTrayMenuOnScreen = TRUE;
+ TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, msg->hwnd, NULL);
+ DestroyTrayMenu(hMenu);
+ PostMessage(msg->hwnd, WM_NULL, 0, 0);
+ }
+ else break;
+ *((LRESULT*)lParam) = 0;
+ return TRUE;
+ }
+ return corecli.pfnTrayIconProcessMessage(wParam, lParam);
+}
+
+//////////////////////////////TRAY MENU/////////////////////////
+HANDLE hTrayMenuObject;
+
+HANDLE hTrayMainMenuItemProxy;
+HANDLE hTrayStatusMenuItemProxy;
+HANDLE hTrayHideShowMainMenuItem;
+
+//traymenu exec param(ownerdata)
+typedef struct{
+ char *szServiceName;
+ int Param1;
+}TrayMenuExecParam,*lpTrayMenuExecParam;
+
+/*
+wparam = handle to the menu item returned by MS_CLIST_ADDCONTACTMENUITEM
+return 0 on success.
+*/
+static INT_PTR RemoveTrayMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ CallService(MO_REMOVEMENUITEM,wParam,0);
+ return 0;
+}
+
+static INT_PTR BuildTrayMenu(WPARAM wParam,LPARAM lParam)
+{
+ int tick;
+ HMENU hMenu;
+ ListParam param;
+
+ memset(&param,0,sizeof(param));
+ param.MenuObjectHandle = hTrayMenuObject;
+
+ //hMenu = hMainMenu;
+ hMenu = CreatePopupMenu();
+ //hMenu = wParam;
+ tick = GetTickCount();
+
+ NotifyEventHooks(g_CluiData.hEventPreBuildTrayMenu,0,0);
+
+ CallService(MO_BUILDMENU,(WPARAM)hMenu,(LPARAM)&param);
+ //DrawMenuBar((HWND)CallService("CLUI/GetHwnd",0,0));
+ tick = GetTickCount()-tick;
+ return (INT_PTR)hMenu;
+}
+
+static INT_PTR AddTrayMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ TMO_MenuItem tmi;
+ CLISTMENUITEM *mi = (CLISTMENUITEM*)lParam;
+ if ( !pcli->pfnConvertMenu(mi, &tmi))
+ return NULL;
+
+ lpTrayMenuExecParam mmep = (lpTrayMenuExecParam)mir_alloc(sizeof(TrayMenuExecParam));
+ if ( mmep == NULL)
+ return 0;
+
+ //we need just one parametr.
+ mmep->szServiceName = mir_strdup(mi->pszService);
+ mmep->Param1 = mi->popupPosition;
+ tmi.ownerdata = mmep;
+
+ OptParam op;
+ op.Handle = (HANDLE)CallService(MO_ADDNEWMENUITEM,(WPARAM)hTrayMenuObject,(LPARAM)&tmi);
+ op.Setting = OPT_MENUITEMSETUNIQNAME;
+ op.Value = (INT_PTR)mi->pszService;
+ CallService(MO_SETOPTIONSMENUITEM,(WPARAM)0,(LPARAM)&op);
+ return (INT_PTR)op.Handle;
+
+ // mainItemCount++;
+ // return MENU_CUSTOMITEMMAIN|(mainMenuItem[mainItemCount-1].id);
+}
+
+INT_PTR TrayMenuonAddService(WPARAM wParam,LPARAM lParam) {
+
+ MENUITEMINFO *mii = (MENUITEMINFO* )wParam;
+ if (mii == NULL) return 0;
+
+ if (hTrayHideShowMainMenuItem == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_STATE;
+ mii->fState |= MFS_DEFAULT;
+
+ }
+ if (hTrayMainMenuItemProxy == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0);
+ }
+
+ if (hTrayStatusMenuItemProxy == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ }
+
+ return(TRUE);
+}
+
+//called with:
+//wparam - ownerdata
+//lparam - lparam from winproc
+INT_PTR TrayMenuExecService(WPARAM wParam,LPARAM lParam) {
+ if (wParam != 0)
+ {
+ lpTrayMenuExecParam mmep = (lpTrayMenuExecParam)wParam;
+ if ( !mir_strcmp(mmep->szServiceName,"Help/AboutCommand"))
+ {
+ //bug in help.c,it used wparam as parent window handle without reason.
+ mmep->Param1 = 0;
+ }
+ CallService(mmep->szServiceName,mmep->Param1,lParam);
+ }
+ return(1);
+}
+
+INT_PTR FreeOwnerDataTrayMenu (WPARAM wParam,LPARAM lParam)
+{
+
+ lpTrayMenuExecParam mmep;
+ mmep = (lpTrayMenuExecParam)lParam;
+ if (mmep != NULL){
+ FreeAndNil((void**)&mmep->szServiceName);
+ FreeAndNil((void**)&mmep);
+ }
+
+ return(0);
+}
+
+void InitTrayMenus(void)
+{
+ TMenuParam tmp;
+ OptParam op;
+
+ CreateServiceFunction("CLISTMENUSTRAY/ExecService",TrayMenuExecService);
+ CreateServiceFunction("CLISTMENUSTRAY/FreeOwnerDataTrayMenu",FreeOwnerDataTrayMenu);
+ CreateServiceFunction("CLISTMENUSTRAY/TrayMenuonAddService",TrayMenuonAddService);
+
+ CreateServiceFunction("CList/AddTrayMenuItem",AddTrayMenuItem);
+ CreateServiceFunction(MS_CLIST_REMOVETRAYMENUITEM,RemoveTrayMenuItem);
+ CreateServiceFunction(MS_CLIST_MENUBUILDTRAY,BuildTrayMenu);
+
+
+ //Tray menu
+ memset(&tmp,0,sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ tmp.CheckService = NULL;
+ tmp.ExecService = "CLISTMENUSTRAY/ExecService";
+ tmp.name = "TrayMenu";
+ hTrayMenuObject = (HANDLE)CallService(MO_CREATENEWMENUOBJECT,(WPARAM)0,(LPARAM)&tmp);
+
+
+ op.Handle = hTrayMenuObject;
+ op.Setting = OPT_USERDEFINEDITEMS;
+ op.Value = TRUE;
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ op.Handle = hTrayMenuObject;
+ op.Setting = OPT_MENUOBJECT_SET_FREE_SERVICE;
+ op.Value = (INT_PTR)"CLISTMENUSTRAY/FreeOwnerDataTrayMenu";
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ op.Handle = hTrayMenuObject;
+ op.Setting = OPT_MENUOBJECT_SET_ONADD_SERVICE;
+ op.Value = (INT_PTR)"CLISTMENUSTRAY/TrayMenuonAddService";
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ {
+ //add exit command to menu
+ CLISTMENUITEM mi;
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 900000;
+ mi.pszService = "CloseAction";
+ mi.pszName = LPGEN("E&xit");
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_EXIT);
+ AddTrayMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100000;
+ mi.pszService = MS_CLIST_SHOWHIDE;
+ mi.pszName = LPGEN("&Hide/Show");
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_SHOWHIDE);
+ hTrayHideShowMainMenuItem = (HANDLE)AddTrayMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 200000;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_FINDUSER);
+ mi.pszService = "FindAdd/FindAddCommand";
+ mi.pszName = LPGEN("&Find/Add Contacts...");
+ AddTrayMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 300000;
+ mi.flags = CMIF_ICONFROMICOLIB; // eternity #004
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_MAINMENU); // eternity #004
+ mi.pszService = "FakeService_1";
+ mi.pszName = LPGEN("&Main Menu");
+ hTrayMainMenuItemProxy = (HANDLE)AddTrayMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon); // eternity #004
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 300100;
+ mi.pszService = "FakeService_2";
+ mi.flags = CMIF_ICONFROMICOLIB; // eternity #004
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_STATUS); // eternity #004
+ mi.pszName = LPGEN("&Status");
+ hTrayStatusMenuItemProxy = (HANDLE)AddTrayMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon); // eternity #004
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 400000;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_OPTIONS);
+ mi.pszService = "Options/OptionsCommand";
+ mi.pszName = LPGEN("&Options...");
+ AddTrayMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 500000;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_MIRANDA);
+ mi.pszService = "Help/AboutCommand";
+ mi.pszName = LPGEN("&About");
+ AddTrayMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+ }
+
+ hMainMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0);
+ hStatusMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+}
+
+void UninitTrayMenu()
+{
+ if (hTrayMenuObject && ServiceExists(MO_REMOVEMENUOBJECT))
+ CallService(MO_REMOVEMENUOBJECT,(WPARAM)hTrayMenuObject,0);
+ hTrayMenuObject = NULL;
+}
+
+void InitTray(void)
+{
+ InitTrayMenus();
+ return;
+}
+
+//////////////////////////////END TRAY MENU/////////////////////////
diff --git a/plugins/Clist_modern/src/modern_clui.cpp b/plugins/Clist_modern/src/modern_clui.cpp
new file mode 100644
index 0000000000..fe27bc2a34
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clui.cpp
@@ -0,0 +1,3111 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+
+#include "m_clc.h"
+#include "m_clui.h"
+#include "m_skin.h"
+#include "m_api/m_skinbutton.h"
+#include "hdr/modern_skinengine.h"
+#include "hdr/modern_statusbar.h"
+
+#include "hdr/modern_static_clui.h"
+#include <locale.h>
+#include "hdr/modern_clcpaint.h"
+#include "hdr/modern_sync.h"
+
+int ContactSettingChanged(WPARAM, LPARAM);
+
+HRESULT (WINAPI *g_proc_DWMEnableBlurBehindWindow)(HWND hWnd, DWM_BLURBEHIND *pBlurBehind);
+BOOL CALLBACK ProcessCLUIFrameInternalMsg(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT& result );
+void DestroyTrayMenu(HMENU hMenu);
+
+// new sources
+#ifdef _MSC_VER
+#include <crtdbg.h>
+#endif
+
+//////////////// CLUI CLASS IMPLEMENTATION /////////////////////////////////
+#include "hdr/modern_clui.h"
+
+#define STATIC_METHOD
+
+CLUI* CLUI::m_pCLUI = NULL;
+BOOL CLUI::m_fMainMenuInited = FALSE;
+HWND CLUI::m_hWnd = NULL;
+
+void CLUI::cliOnCreateClc(void)
+{
+ STATIC_METHOD;
+ _ASSERT( m_pCLUI );
+ m_pCLUI->CreateCluiFrames();
+}
+
+int CLUI::OnEvent_ModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ STATIC_METHOD;
+
+ g_CluiData.bMetaAvail = ServiceExists(MS_MC_GETDEFAULTCONTACT) ? TRUE : FALSE;
+ setlocale(LC_ALL, ""); //fix for case insensitive comparing
+
+ if (ServiceExists(MS_MC_DISABLEHIDDENGROUP))
+ CallService(MS_MC_DISABLEHIDDENGROUP, (WPARAM)TRUE, (LPARAM)0);
+
+ if (ServiceExists(MS_MC_GETPROTOCOLNAME))
+ g_szMetaModuleName = (char *)CallService(MS_MC_GETPROTOCOLNAME, 0, 0);
+
+ CLUIServices_ProtocolStatusChanged(0,0);
+ SleepEx(0,TRUE);
+ g_flag_bOnModulesLoadedCalled = TRUE;
+ ///pcli->pfnInvalidateDisplayNameCacheEntry(INVALID_HANDLE_VALUE);
+ SendMessage(pcli->hwndContactList,UM_CREATECLC,0,0); //$$$
+ InitSkinHotKeys();
+ g_CluiData.bSTATE = STATE_NORMAL;
+ ske_RedrawCompleteWindow();
+
+ return 0;
+}
+
+int CLUI::OnEvent_FontReload(WPARAM wParam,LPARAM lParam)
+{
+ STATIC_METHOD;
+
+ pcli->pfnClcBroadcast( INTM_RELOADOPTIONS, wParam, lParam );
+
+ g_CluiData.dwKeyColor = db_get_dw(NULL,"ModernSettings","KeyColor",(DWORD)SETTING_KEYCOLOR_DEFAULT);
+
+ CLUI__cliInvalidateRect( pcli->hwndContactList, 0, 0 );
+
+ return 0;
+}
+
+int CLUI::OnEvent_ContactMenuPreBuild(WPARAM wParam, LPARAM lParam)
+{
+ TCHAR cls[128];
+ HANDLE hItem;
+ HWND hwndClist = GetFocus();
+ CLISTMENUITEM mi;
+ if (MirandaExiting()) return 0;
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS;
+ GetClassName(hwndClist,cls,SIZEOF(cls));
+ hwndClist = (!lstrcmp(CLISTCONTROL_CLASS,cls))?hwndClist:pcli->hwndContactList;
+ hItem = (HANDLE)SendMessage(hwndClist,CLM_GETSELECTION,0,0);
+ if ( !hItem) {
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ }
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hRenameMenuItem, (LPARAM)&mi);
+
+ if ( !hItem || !IsHContactContact(hItem) || !db_get_b(NULL,"CList","AvatarsShow",SETTINGS_SHOWAVATARS_DEFAULT))
+ {
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hShowAvatarMenuItem, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideAvatarMenuItem, (LPARAM)&mi);
+ }
+ else
+ {
+ int has_avatar;
+
+ if (ServiceExists(MS_AV_GETAVATARBITMAP))
+ {
+ has_avatar = CallService(MS_AV_GETAVATARBITMAP, (WPARAM)hItem, 0);
+ }
+ else
+ {
+ DBVARIANT dbv = {0};
+ if (DBGetContactSettingTString(hItem, "ContactPhoto", "File", &dbv))
+ {
+ has_avatar = 0;
+ }
+ else
+ {
+ has_avatar = 1;
+ db_free(&dbv);
+ }
+ }
+
+ if (db_get_b(hItem, "CList", "HideContactAvatar", 0))
+ {
+ mi.flags = CMIM_FLAGS | (has_avatar ? 0 : CMIF_GRAYED);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hShowAvatarMenuItem, (LPARAM)&mi);
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideAvatarMenuItem, (LPARAM)&mi);
+ }
+ else
+ {
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hShowAvatarMenuItem, (LPARAM)&mi);
+ mi.flags = CMIM_FLAGS | (has_avatar ? 0 : CMIF_GRAYED);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideAvatarMenuItem, (LPARAM)&mi);
+ }
+ }
+
+ return 0;
+}
+int CLUI::OnEvent_DBSettingChanging(WPARAM wParam,LPARAM lParam)
+{
+ if (ServiceExists("ExtraIcon/Register"))
+ return 0;
+
+ DBCONTACTWRITESETTING *dbcws = (DBCONTACTWRITESETTING *)lParam;
+ if (wParam == 0) return 0;
+ if (dbcws == NULL) return(0);
+ if (MirandaExiting()) return 0;
+
+ if (( dbcws->value.type == DBVT_WORD && !mir_strcmp(dbcws->szSetting,"ApparentMode")) ||
+ ( dbcws->value.type == DBVT_ASCIIZ &&
+ (( !mir_strcmp(dbcws->szSetting,"e-mail") ||
+ !mir_strcmp(dbcws->szSetting,"Mye-mail0") ||
+ !mir_strcmp(dbcws->szSetting,"Cellular")) ||
+ ( !mir_strcmp(dbcws->szModule,"UserInfo") &&
+ ( !mir_strcmp(dbcws->szSetting,"MyPhone0") ||
+ !mir_strcmp(dbcws->szSetting,"Mye-mail0"))))))
+ ExtraImage_SetAllExtraIcons(pcli->hwndContactTree,(HANDLE)wParam);
+ return(0);
+};
+INT_PTR CLUI::Service_ShowMainMenu(WPARAM wParam,LPARAM lParam)
+{
+ HMENU hMenu;
+ POINT pt;
+ hMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0);
+ GetCursorPos(&pt);
+ TrackPopupMenu(hMenu,TPM_TOPALIGN|TPM_LEFTALIGN|TPM_LEFTBUTTON,pt.x,pt.y,0,pcli->hwndContactList,NULL);
+ return 0;
+}
+INT_PTR CLUI::Service_ShowStatusMenu(WPARAM wParam,LPARAM lParam)
+{
+ HMENU hMenu;
+ POINT pt;
+ hMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ GetCursorPos(&pt);
+ TrackPopupMenu(hMenu,TPM_TOPALIGN|TPM_LEFTALIGN|TPM_LEFTBUTTON,pt.x,pt.y,0,pcli->hwndContactList,NULL);
+ return 0;
+}
+
+INT_PTR CLUI::Service_Menu_ShowContactAvatar(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE) wParam;
+
+ db_set_b(hContact, "CList", "HideContactAvatar", 0);
+
+ pcli->pfnClcBroadcast( INTM_AVATARCHANGED,wParam,0);
+ return 0;
+}
+
+INT_PTR CLUI::Service_Menu_HideContactAvatar(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE) wParam;
+
+ db_set_b(hContact, "CList", "HideContactAvatar", 1);
+
+ pcli->pfnClcBroadcast( INTM_AVATARCHANGED,wParam,0);
+ return 0;
+}
+
+
+
+HRESULT CLUI::CreateCluiFrames()
+{
+ g_hMenuMain = GetMenu(pcli->hwndContactList);
+ MENUITEMINFO mii;
+ ZeroMemory(&mii,sizeof(mii));
+ mii.cbSize = MENUITEMINFO_V4_SIZE;
+ mii.fMask = MIIM_SUBMENU;
+ mii.hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0);
+ SetMenuItemInfo(g_hMenuMain,0,TRUE,&mii);
+ mii.hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ SetMenuItemInfo(g_hMenuMain,1,TRUE,&mii);
+
+ CreateCLCWindow(CluiWnd());
+
+ CLUI_ChangeWindowMode();
+
+ RegisterAvatarMenu();
+
+ CLUI_ReloadCLUIOptions();
+
+ CreateUIFrames();
+
+ HookEvent(ME_SYSTEM_MODULESLOADED,CLUI::OnEvent_ModulesLoaded);
+ HookEvent(ME_SKIN2_ICONSCHANGED,CLUI_IconsChanged);
+ HookEvent(ME_FONT_RELOAD, CLUI::OnEvent_FontReload);
+ return S_OK;
+}
+CLUI::CLUI() :
+m_hUserDll( NULL ),
+m_hDwmapiDll( NULL )
+{
+ m_pCLUI = this;
+ g_CluiData.bSTATE = STATE_CLUI_LOADING;
+ LoadDllsRuntime();
+ hFrameContactTree = NULL;
+
+ CLUIServices_LoadModule();
+
+ // Call InitGroup menus before
+ GroupMenus_Init();
+
+ CreateServiceFunction(MS_CLUI_SHOWMAINMENU,Service_ShowMainMenu);
+ CreateServiceFunction(MS_CLUI_SHOWSTATUSMENU,Service_ShowStatusMenu);
+
+
+ //TODO Add Row template loading here.
+
+ RowHeight_InitModernRow();
+ nLastRequiredHeight = 0;
+
+ LoadCLUIFramesModule();
+ ExtraImage_LoadModule();
+
+ g_CluiData.boldHideOffline = -1;
+ bOldHideOffline = db_get_b(NULL,"CList","HideOffline",SETTING_HIDEOFFLINE_DEFAULT);
+
+ g_CluiData.bOldUseGroups = -1;
+ bOldUseGroups = db_get_b( NULL,"CList","UseGroups", SETTING_USEGROUPS_DEFAULT );
+}
+
+CLUI::~CLUI()
+{
+ FreeLibrary(m_hUserDll);
+ FreeLibrary(m_hDwmapiDll);
+ m_pCLUI = NULL;
+}
+
+HRESULT CLUI::LoadDllsRuntime()
+{
+ m_hUserDll = LoadLibrary(_T("user32.dll"));
+ if (m_hUserDll)
+ {
+ g_proc_UpdateLayeredWindow = (BOOL (WINAPI *)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD))GetProcAddress(m_hUserDll, "UpdateLayeredWindow");
+ g_proc_SetLayeredWindowAttributesNew = (BOOL (WINAPI *)(HWND,COLORREF,BYTE,DWORD))GetProcAddress(m_hUserDll, "SetLayeredWindowAttributes");
+ g_proc_AnimateWindow = (BOOL (WINAPI*)(HWND,DWORD,DWORD))GetProcAddress(m_hUserDll,"AnimateWindow");
+
+ g_CluiData.fLayered = (g_proc_UpdateLayeredWindow != NULL) && !db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT);
+ g_CluiData.fSmoothAnimation = IsWinVer2000Plus() && db_get_b(NULL, "CLUI", "FadeInOut", SETTING_FADEIN_DEFAULT);
+ g_CluiData.fLayered = (g_CluiData.fLayered*db_get_b(NULL, "ModernData", "EnableLayering", g_CluiData.fLayered)) && !db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT);
+ }
+
+ if (IsWinVerVistaPlus())
+ {
+ m_hDwmapiDll = LoadLibrary(_T("dwmapi.dll"));
+ if (m_hDwmapiDll)
+ {
+ g_proc_DWMEnableBlurBehindWindow = (HRESULT (WINAPI *)(HWND, DWM_BLURBEHIND *))GetProcAddress(m_hDwmapiDll, "DwmEnableBlurBehindWindow");
+ }
+ }
+ g_CluiData.fAeroGlass = FALSE;
+
+ return S_OK;
+}
+HRESULT CLUI::RegisterAvatarMenu()
+{
+ CLISTMENUITEM mi;
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = 0;
+ mi.pszContactOwner = NULL; //on every contact
+ CreateServiceFunction("CList/ShowContactAvatar",CLUI::Service_Menu_ShowContactAvatar);
+ mi.position = 2000150000;
+ mi.hIcon = LoadSmallIcon(g_hInst,MAKEINTRESOURCE(IDI_SHOW_AVATAR));
+ mi.pszName = LPGEN("Show Contact &Avatar");
+ mi.pszService = "CList/ShowContactAvatar";
+ hShowAvatarMenuItem = Menu_AddContactMenuItem(&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ CreateServiceFunction("CList/HideContactAvatar",CLUI::Service_Menu_HideContactAvatar);
+ mi.position = 2000150001;
+ mi.hIcon = LoadSmallIcon(g_hInst,MAKEINTRESOURCE(IDI_HIDE_AVATAR));
+ mi.pszName = LPGEN("Hide Contact &Avatar");
+ mi.pszService = "CList/HideContactAvatar";
+ hHideAvatarMenuItem = Menu_AddContactMenuItem(&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ HookEvent(ME_CLIST_PREBUILDCONTACTMENU, CLUI::OnEvent_ContactMenuPreBuild);
+
+ return S_OK;
+}
+
+HRESULT CLUI::CreateCLCWindow(const HWND hwndClui)
+{
+ ClcWnd() = CreateWindow(CLISTCONTROL_CLASS,_T(""),
+ WS_CHILD|WS_CLIPCHILDREN|CLS_CONTACTLIST
+ |(db_get_b(NULL,"CList","UseGroups",SETTING_USEGROUPS_DEFAULT)?CLS_USEGROUPS:0)
+ |(db_get_b(NULL,"CList","HideOffline",SETTING_HIDEOFFLINE_DEFAULT)?CLS_HIDEOFFLINE:0)
+ |(db_get_b(NULL,"CList","HideEmptyGroups",SETTING_HIDEEMPTYGROUPS_DEFAULT)?CLS_HIDEEMPTYGROUPS:0
+ |CLS_MULTICOLUMN
+ ),
+ 0,0,0,0,hwndClui,NULL,g_hInst,NULL);
+
+ return S_OK;
+}
+
+HRESULT CLUI::CreateUIFrames()
+{
+ EventArea_Create(pcli->hwndContactList);
+ CreateViewModeFrame();
+ pcli->hwndStatus = StatusBar_Create(pcli->hwndContactList);
+
+ return S_OK;
+}
+
+
+
+HRESULT CLUI::FillAlphaChannel( HDC hDC, RECT * prcParent, BYTE bAlpha)
+{
+
+ RECT rcWindow;
+ GetWindowRect( m_hWnd, &rcWindow );
+
+ HRGN hRgn = CreateRectRgn(0,0,0,0);
+
+ if ( GetWindowRgn(m_hWnd,hRgn) == ERROR )
+ {
+ DeleteObject(hRgn);
+ hRgn = CreateRectRgn(rcWindow.left ,rcWindow.top ,rcWindow.right,rcWindow.bottom);
+ }
+
+ OffsetRgn(hRgn,-prcParent->left,-prcParent->top);
+
+ RECT rcBounds;
+ GetRgnBox(hRgn,&rcBounds);
+
+ if ( IsRectEmpty(&rcBounds))
+ {
+ DeleteObject(hRgn);
+ return S_FALSE;
+ }
+
+ DWORD dwRgnSize = GetRegionData( hRgn, 0, NULL );
+ RGNDATA * rgnData = (RGNDATA *)malloc(dwRgnSize);
+ GetRegionData(hRgn,dwRgnSize,rgnData);
+
+ RECT * pRect = (RECT *)rgnData->Buffer;
+
+ for (DWORD i=0; i < rgnData->rdh.nCount; i++)
+ ske_SetRectOpaque( hDC, &pRect[i] );
+
+ free(rgnData);
+ DeleteObject(hRgn);
+
+ return S_OK;
+}
+
+HRESULT CLUI::CreateCLC()
+{
+ INIT < CLISTFrame> Frame;
+
+ Frame.hWnd = ClcWnd();
+ Frame.align = alClient;
+ Frame.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ Frame.Flags = F_VISIBLE|/*F_SHOWTB|*/F_SHOWTBTIP|F_NO_SUBCONTAINER|F_TCHAR;
+ Frame.tname = LPGENT("My Contacts");
+ Frame.TBtname = TranslateT("My Contacts");
+ hFrameContactTree = (HWND)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&Frame,(LPARAM)0);
+
+ CallService(MS_SKINENG_REGISTERPAINTSUB,(WPARAM)Frame.hWnd,(LPARAM)CLCPaint::PaintCallbackProc);
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_TBTIPNAME,hFrameContactTree),(LPARAM)Translate("My Contacts"));
+
+ ExtraImage_ReloadExtraIcons();
+
+ nLastRequiredHeight = 0;
+ if ( g_CluiData.current_viewmode[0] == '\0' )
+ {
+ if (bOldHideOffline != (BYTE)-1)
+ CallService( MS_CLIST_SETHIDEOFFLINE,(WPARAM)bOldHideOffline, 0);
+ else
+ CallService( MS_CLIST_SETHIDEOFFLINE,(WPARAM)0, 0);
+ if (bOldUseGroups != (BYTE)-1)
+ CallService( MS_CLIST_SETUSEGROUPS ,(WPARAM)bOldUseGroups, 0);
+ else
+ CallService( MS_CLIST_SETUSEGROUPS ,(WPARAM)bOldUseGroups, 0);
+ }
+ nLastRequiredHeight = 0;
+ mutex_bDisableAutoUpdate = 0;
+
+ HookEvent(ME_DB_CONTACT_SETTINGCHANGED, ContactSettingChanged);
+ HookEvent(ME_DB_CONTACT_SETTINGCHANGED,CLUI::OnEvent_DBSettingChanging);
+ return S_OK;
+
+};
+HRESULT CLUI::SnappingToEdge( WINDOWPOS * lpWindowPos )
+{
+ //by ZORG
+ if ( MyMonitorFromWindow == NULL || MyGetMonitorInfo == NULL )
+ return S_FALSE;
+
+ if (db_get_b(NULL,"CLUI","SnapToEdges",SETTING_SNAPTOEDGES_DEFAULT))
+ {
+ RECT* dr;
+ MONITORINFO monInfo;
+ HMONITOR curMonitor = MyMonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
+
+ monInfo.cbSize = sizeof(monInfo);
+ MyGetMonitorInfo(curMonitor, &monInfo);
+
+ dr = &(monInfo.rcWork);
+
+ // Left side
+ if ( lpWindowPos->x < dr->left + SNAPTOEDGESENSIVITY && lpWindowPos->x > dr->left - SNAPTOEDGESENSIVITY && g_CluiData.bBehindEdgeSettings != 1)
+ lpWindowPos->x = dr->left;
+
+ // Right side
+ if ( dr->right - lpWindowPos->x - lpWindowPos->cx < SNAPTOEDGESENSIVITY && dr->right - lpWindowPos->x - lpWindowPos->cx > -SNAPTOEDGESENSIVITY && g_CluiData.bBehindEdgeSettings != 2)
+ lpWindowPos->x = dr->right - lpWindowPos->cx;
+
+ // Top side
+ if ( lpWindowPos->y < dr->top + SNAPTOEDGESENSIVITY && lpWindowPos->y > dr->top - SNAPTOEDGESENSIVITY)
+ lpWindowPos->y = dr->top;
+
+ // Bottom side
+ if ( dr->bottom - lpWindowPos->y - lpWindowPos->cy < SNAPTOEDGESENSIVITY && dr->bottom - lpWindowPos->y - lpWindowPos->cy > -SNAPTOEDGESENSIVITY)
+ lpWindowPos->y = dr->bottom - lpWindowPos->cy;
+ }
+ return S_OK;
+}
+
+HICON GetMainStatusOverlay(int STATUS)
+{
+ return ImageList_GetIcon(hAvatarOverlays,g_pStatusOverlayIcons[STATUS-ID_STATUS_OFFLINE].listID,ILD_NORMAL);
+}
+
+void UnloadAvatarOverlayIcon()
+{
+ for (int i=0 ; i < MAX_REGS(g_pAvatarOverlayIcons); i++) {
+ g_pAvatarOverlayIcons[i].listID = -1;
+ g_pStatusOverlayIcons[i].listID = -1;
+ }
+ ImageList_Destroy(hAvatarOverlays);
+ hAvatarOverlays = NULL;
+ DestroyIcon_protect(g_hListeningToIcon);
+ g_hListeningToIcon = NULL;
+}
+
+BOOL CLUI_CheckOwnedByClui(HWND hWnd)
+{
+ HWND hWndMid, hWndClui;
+ if ( !hWnd) return FALSE;
+ hWndClui = pcli->hwndContactList;
+ hWndMid = fnGetAncestor(hWnd,GA_ROOTOWNER);
+ if (hWndMid == hWndClui) return TRUE;
+ {
+ TCHAR buf[255];
+ GetClassName(hWndMid,buf,254);
+ if ( !mir_tstrcmpi(buf,CLUIFrameSubContainerClassName)) return TRUE;
+ }
+ return FALSE;
+}
+
+int CLUI_ShowWindowMod(HWND hWnd, int nCmd)
+{
+ int res = 0;
+
+ if (hWnd == pcli->hwndContactList && (nCmd == SW_HIDE || nCmd == SW_MINIMIZE))
+ {
+ AniAva_InvalidateAvatarPositions(NULL);
+ AniAva_RemoveInvalidatedAvatars();
+ }
+
+ if (hWnd == pcli->hwndContactList
+ && !g_mutex_bChangingMode
+ && nCmd == SW_HIDE
+ && !g_CluiData.fLayered
+ && IsWinVerXPPlus()
+ && db_get_b(NULL,"CList","WindowShadow",SETTING_WINDOWSHADOW_DEFAULT))
+ {
+ ShowWindow(hWnd,SW_MINIMIZE); //removing of shadow
+ return ShowWindow(hWnd,nCmd);
+ }
+ if (hWnd == pcli->hwndContactList
+ && !g_mutex_bChangingMode
+ && nCmd == SW_RESTORE
+ && !g_CluiData.fLayered
+ && IsWinVerXPPlus()
+ && g_CluiData.fSmoothAnimation
+ && !g_bTransparentFlag
+ )
+ {
+ if (db_get_b(NULL,"CList","WindowShadow",SETTING_WINDOWSHADOW_DEFAULT))
+ {
+ CLUI_SmoothAlphaTransition(hWnd, 255, 1);
+ }
+ else
+ {
+
+ int ret = ShowWindow(hWnd,nCmd);
+ CLUI_SmoothAlphaTransition(hWnd, 255, 1);
+ return ret;
+ }
+ }
+ return ShowWindow(hWnd,nCmd);
+}
+
+static BOOL CLUI_WaitThreadsCompletion(HWND hwnd)
+{
+ static BYTE bEntersCount = 0;
+ static const BYTE bcMAX_AWAITING_RETRY = 10; //repeat awaiting only 10 times
+ TRACE("CLUI_WaitThreadsCompletion Enter");
+ if (bEntersCount < bcMAX_AWAITING_RETRY
+ && ( g_mutex_nCalcRowHeightLock ||
+ g_CluiData.mutexPaintLock ||
+ g_dwAwayMsgThreadID ||
+ g_dwGetTextAsyncThreadID ||
+ g_dwSmoothAnimationThreadID ||
+ g_dwFillFontListThreadID)
+ && !Miranda_Terminated())
+ {
+ TRACE("Waiting threads");
+ TRACEVAR("g_mutex_nCalcRowHeightLock: %x",g_mutex_nCalcRowHeightLock);
+ TRACEVAR("g_CluiData.mutexPaintLock: %x",g_CluiData.mutexPaintLock);
+ TRACEVAR("g_dwAwayMsgThreadID: %x",g_dwAwayMsgThreadID);
+ TRACEVAR("g_dwGetTextAsyncThreadID: %x",g_dwGetTextAsyncThreadID);
+ TRACEVAR("g_dwSmoothAnimationThreadID: %x",g_dwSmoothAnimationThreadID);
+ TRACEVAR("g_dwFillFontListThreadID: %x",g_dwFillFontListThreadID);
+ bEntersCount++;
+ SleepEx(10,TRUE);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void CLUI_UpdateLayeredMode()
+{
+ g_CluiData.fDisableSkinEngine = db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT);
+ if (IsWinVer2000Plus())
+ {
+ BOOL tLayeredFlag = TRUE;
+ tLayeredFlag &= (db_get_b(NULL, "ModernData", "EnableLayering", tLayeredFlag) && !g_CluiData.fDisableSkinEngine);
+
+ if (g_CluiData.fLayered != tLayeredFlag)
+ {
+ LONG exStyle;
+ BOOL fWasVisible = IsWindowVisible(pcli->hwndContactList);
+ if (fWasVisible) ShowWindow(pcli->hwndContactList,SW_HIDE);
+ //change layered mode
+ exStyle = GetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE);
+ if (tLayeredFlag)
+ exStyle |= WS_EX_LAYERED;
+ else
+ exStyle &= ~WS_EX_LAYERED;
+ SetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE,exStyle&~WS_EX_LAYERED);
+ SetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE,exStyle);
+ g_CluiData.fLayered = tLayeredFlag;
+ Sync(CLUIFrames_SetLayeredMode, tLayeredFlag,pcli->hwndContactList);
+ CLUI_ChangeWindowMode();
+ Sync(CLUIFrames_OnClistResize_mod, (WPARAM)0, (LPARAM)0 );
+ if (fWasVisible) ShowWindow(pcli->hwndContactList,SW_SHOW);
+ }
+ }
+}
+
+void CLUI_UpdateAeroGlass()
+{
+ BOOL tAeroGlass = db_get_b(NULL, "ModernData", "AeroGlass", SETTING_AEROGLASS_DEFAULT) && (g_CluiData.fLayered);
+ if (g_proc_DWMEnableBlurBehindWindow && (tAeroGlass != g_CluiData.fAeroGlass))
+ {
+ if (g_CluiData.hAeroGlassRgn)
+ {
+ DeleteObject(g_CluiData.hAeroGlassRgn);
+ g_CluiData.hAeroGlassRgn = 0;
+ }
+
+ DWM_BLURBEHIND bb = {0};
+ bb.dwFlags = DWM_BB_ENABLE;
+ bb.fEnable = tAeroGlass;
+
+ if (tAeroGlass)
+ {
+ g_CluiData.hAeroGlassRgn = ske_CreateOpaqueRgn(AEROGLASS_MINALPHA, true);
+ bb.hRgnBlur = g_CluiData.hAeroGlassRgn;
+ bb.dwFlags |= DWM_BB_BLURREGION;
+ }
+
+ g_proc_DWMEnableBlurBehindWindow(pcli->hwndContactList, &bb);
+ g_CluiData.fAeroGlass = tAeroGlass;
+ }
+}
+
+extern int CLUIFrames_UpdateBorders();
+
+void CLUI_ChangeWindowMode()
+{
+ BOOL storedVisMode = FALSE;
+ LONG style,styleEx;
+ LONG oldStyle,oldStyleEx;
+ LONG styleMask = WS_CLIPCHILDREN|WS_BORDER|WS_CAPTION|WS_MINIMIZEBOX|WS_POPUPWINDOW|WS_CLIPCHILDREN|WS_THICKFRAME|WS_SYSMENU;
+ LONG styleMaskEx = WS_EX_TOOLWINDOW|WS_EX_LAYERED;
+ LONG curStyle,curStyleEx;
+ if ( !pcli->hwndContactList) return;
+
+ g_mutex_bChangingMode = TRUE;
+ g_bTransparentFlag = IsWinVer2000Plus() && db_get_b( NULL,"CList","Transparent",SETTING_TRANSPARENT_DEFAULT);
+ g_CluiData.fSmoothAnimation = IsWinVer2000Plus() && db_get_b(NULL, "CLUI", "FadeInOut", SETTING_FADEIN_DEFAULT);
+ if (g_bTransparentFlag == 0 && g_CluiData.bCurrentAlpha != 0)
+ g_CluiData.bCurrentAlpha = 255;
+ //2- Calculate STYLES and STYLESEX
+ if ( !g_CluiData.fLayered)
+ {
+ style = 0;
+ styleEx = 0;
+ if (db_get_b(NULL,"CList","ThinBorder",SETTING_THINBORDER_DEFAULT) || (db_get_b(NULL,"CList","NoBorder",SETTING_NOBORDER_DEFAULT)))
+ {
+ style = WS_CLIPCHILDREN| (db_get_b(NULL,"CList","ThinBorder",SETTING_THINBORDER_DEFAULT)?WS_BORDER:0);
+ styleEx = WS_EX_TOOLWINDOW;
+ styleMaskEx |= WS_EX_APPWINDOW;
+ }
+ else if (db_get_b(NULL,"CLUI","ShowCaption",SETTING_SHOWCAPTION_DEFAULT) && db_get_b(NULL,"CList","ToolWindow",SETTING_TOOLWINDOW_DEFAULT))
+ {
+ styleEx = WS_EX_TOOLWINDOW/*|WS_EX_WINDOWEDGE*/;
+ style = WS_CAPTION|WS_POPUPWINDOW|WS_CLIPCHILDREN|WS_THICKFRAME;
+ styleMaskEx |= WS_EX_APPWINDOW;
+ }
+ else if (db_get_b(NULL,"CLUI","ShowCaption",SETTING_SHOWCAPTION_DEFAULT))
+ {
+ style = WS_CAPTION|WS_SYSMENU|WS_POPUPWINDOW|WS_CLIPCHILDREN|WS_THICKFRAME|WS_MINIMIZEBOX;
+ }
+ else
+ {
+ style = WS_POPUPWINDOW|WS_CLIPCHILDREN|WS_THICKFRAME;
+ styleEx = WS_EX_TOOLWINDOW/*|WS_EX_WINDOWEDGE*/;
+ styleMaskEx |= WS_EX_APPWINDOW;
+ }
+ }
+ else
+ {
+ style = WS_CLIPCHILDREN;
+ styleEx = WS_EX_TOOLWINDOW;
+ styleMaskEx |= WS_EX_APPWINDOW;
+ }
+ //3- TODO Update Layered mode
+ if (g_bTransparentFlag && g_CluiData.fLayered)
+ styleEx |= WS_EX_LAYERED;
+
+ //4- Set Title
+ {
+ TCHAR titleText[255] = {0};
+ DBVARIANT dbv = {0};
+ if (DBGetContactSettingTString(NULL,"CList","TitleText",&dbv))
+ lstrcpyn(titleText,_T(MIRANDANAME),SIZEOF(titleText));
+ else
+ {
+ lstrcpyn(titleText,dbv.ptszVal,SIZEOF(titleText));
+ db_free(&dbv);
+ }
+ SetWindowText(pcli->hwndContactList,titleText);
+ }
+ // < ->
+ //1- If visible store it and hide
+
+ if (g_CluiData.fLayered && (db_get_b(NULL,"CList","OnDesktop", SETTING_ONDESKTOP_DEFAULT)))// && !flag_bFirstTimeCall))
+ {
+ SetParent(pcli->hwndContactList,NULL);
+ Sync( CLUIFrames_SetParentForContainers, (HWND) NULL );
+ UpdateWindow(pcli->hwndContactList);
+ g_CluiData.fOnDesktop = 0;
+ }
+ //5- TODO Apply Style
+ oldStyleEx = curStyleEx = GetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE);
+ oldStyle = curStyle = GetWindowLongPtr(pcli->hwndContactList,GWL_STYLE);
+
+ curStyleEx = (curStyleEx & ~styleMaskEx) | styleEx;
+ curStyle = (curStyle & ~styleMask) | style;
+ if (oldStyleEx != curStyleEx || oldStyle != curStyle)
+ {
+ if (IsWindowVisible(pcli->hwndContactList))
+ {
+ storedVisMode = TRUE;
+ mutex_bShowHideCalledFromAnimation = TRUE;
+ ShowWindow(pcli->hwndContactList,SW_HIDE);
+ Sync(CLUIFrames_OnShowHide, pcli->hwndContactList,0);
+ }
+ SetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE,curStyleEx);
+ SetWindowLongPtr(pcli->hwndContactList,GWL_STYLE,curStyle);
+ }
+
+ CLUI_UpdateAeroGlass();
+
+ if (g_CluiData.fLayered || !db_get_b(NULL,"CLUI","ShowMainMenu",SETTING_SHOWMAINMENU_DEFAULT))
+ {
+ HMENU m = GetMenu(pcli->hwndContactList);
+ SetMenu(pcli->hwndContactList,NULL);
+ }
+ else
+ SetMenu(pcli->hwndContactList,g_hMenuMain);
+
+ if (g_CluiData.fLayered && (db_get_b(NULL,"CList","OnDesktop", SETTING_ONDESKTOP_DEFAULT)))
+ ske_UpdateWindowImage();
+
+
+ //6- Pin to desktop mode
+ if (db_get_b(NULL,"CList","OnDesktop", SETTING_ONDESKTOP_DEFAULT))
+ {
+ HWND hProgMan = FindWindow(_T("Progman"),NULL);
+ if (IsWindow(hProgMan))
+ {
+ SetParent(pcli->hwndContactList,hProgMan);
+ Sync( CLUIFrames_SetParentForContainers, (HWND) hProgMan );
+ g_CluiData.fOnDesktop = 1;
+ }
+ }
+ else
+ {
+ // HWND parent = GetParent(pcli->hwndContactList);
+ // HWND progman = FindWindow(_T("Progman"),NULL);
+ // if (parent == progman)
+ {
+ SetParent(pcli->hwndContactList,NULL);
+ Sync(CLUIFrames_SetParentForContainers, (HWND) NULL);
+ }
+ g_CluiData.fOnDesktop = 0;
+ }
+
+ //7- if it was visible - show
+ if (storedVisMode)
+ {
+ ShowWindow(pcli->hwndContactList,SW_SHOW);
+ Sync(CLUIFrames_OnShowHide, pcli->hwndContactList,1);
+ }
+ mutex_bShowHideCalledFromAnimation = FALSE;
+
+ CLUIFrames_UpdateBorders();
+
+ if ( !g_CluiData.fLayered)
+ {
+ HRGN hRgn1;
+ RECT r;
+ int v,h;
+ int w = 10;
+ GetWindowRect(pcli->hwndContactList,&r);
+ h = (r.right-r.left)>(w*2)?w:(r.right-r.left);
+ v = (r.bottom-r.top)>(w*2)?w:(r.bottom-r.top);
+ h = (h < v)?h:v;
+ hRgn1 = CreateRoundRectRgn(0,0,(r.right-r.left+1),(r.bottom-r.top+1),h,h);
+ if ((db_get_b(NULL,"CLC","RoundCorners",SETTING_ROUNDCORNERS_DEFAULT)) && (!CallService(MS_CLIST_DOCKINGISDOCKED,0,0)))
+ SetWindowRgn(pcli->hwndContactList,hRgn1,1);
+ else
+ {
+ DeleteObject(hRgn1);
+ SetWindowRgn(pcli->hwndContactList,NULL,1);
+ }
+
+ RedrawWindow(pcli->hwndContactList,NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_FRAME|RDW_UPDATENOW|RDW_ALLCHILDREN);
+ }
+ g_mutex_bChangingMode = FALSE;
+ flag_bFirstTimeCall = TRUE;
+ AniAva_UpdateParent();
+}
+struct _tagTimerAsync
+{
+ HWND hwnd;
+ int ID;
+ int Timeout;
+ TIMERPROC proc;
+};
+static UINT_PTR SetTimerSync(WPARAM wParam , LPARAM lParam)
+{
+ struct _tagTimerAsync * call = (struct _tagTimerAsync *) wParam;
+ return SetTimer(call->hwnd, call->ID ,call->Timeout, call->proc);
+}
+
+UINT_PTR CLUI_SafeSetTimer(HWND hwnd, int ID, int Timeout, TIMERPROC proc)
+{
+ struct _tagTimerAsync param = { hwnd, ID, Timeout, proc };
+ return Sync(SetTimerSync, (WPARAM) &param, (LPARAM) 0);
+}
+
+int CLUI_UpdateTimer(BYTE BringIn)
+{
+ if (g_CluiData.nBehindEdgeState == 0)
+ {
+ KillTimer(pcli->hwndContactList,TM_BRINGOUTTIMEOUT);
+ CLUI_SafeSetTimer(pcli->hwndContactList,TM_BRINGOUTTIMEOUT,wBehindEdgeHideDelay*100,NULL);
+ }
+ if (bShowEventStarted == 0 && g_CluiData.nBehindEdgeState>0 )
+ {
+ KillTimer(pcli->hwndContactList,TM_BRINGINTIMEOUT);
+ bShowEventStarted = (BOOL)CLUI_SafeSetTimer(pcli->hwndContactList,TM_BRINGINTIMEOUT,wBehindEdgeShowDelay*100,NULL);
+ }
+ return 0;
+}
+
+int CLUI_HideBehindEdge()
+{
+ int method = g_CluiData.bBehindEdgeSettings;
+ if (method)
+ {
+ // if (DBGetContactSettingByte(NULL, "ModernData", "BehindEdge", SETTING_BEHINDEDGE_DEFAULT) == 0)
+ {
+ RECT rcScreen;
+ RECT rcWindow;
+ int bordersize = 0;
+ //Need to be moved out of screen
+ bShowEventStarted = 0;
+ //1. get work area rectangle
+ Docking_GetMonitorRectFromWindow(pcli->hwndContactList,&rcScreen);
+ //SystemParametersInfo(SPI_GETWORKAREA,0,&rcScreen,FALSE);
+ //2. move out
+ bordersize = wBehindEdgeBorderSize;
+ GetWindowRect(pcli->hwndContactList,&rcWindow);
+ switch (method)
+ {
+ case 1: //left
+ rcWindow.left = rcScreen.left-(rcWindow.right-rcWindow.left)+bordersize;
+ break;
+ case 2: //right
+ rcWindow.left = rcScreen.right-bordersize;
+ break;
+ }
+ g_CluiData.mutexPreventDockMoving = 0;
+ SetWindowPos(pcli->hwndContactList,NULL,rcWindow.left,rcWindow.top,0,0,SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE);
+ Sync(CLUIFrames_OnMoving,pcli->hwndContactList,&rcWindow);
+ g_CluiData.mutexPreventDockMoving = 1;
+
+ //3. store setting
+ db_set_b(NULL, "ModernData", "BehindEdge",method);
+ g_CluiData.nBehindEdgeState = method;
+ return 1;
+ }
+ return 2;
+ }
+ return 0;
+}
+
+
+int CLUI_ShowFromBehindEdge()
+{
+ int method = g_CluiData.bBehindEdgeSettings;
+ bShowEventStarted = 0;
+ if (g_mutex_bOnTrayRightClick)
+ {
+ g_mutex_bOnTrayRightClick = 0;
+ return 0;
+ }
+ if (method)// && (DBGetContactSettingByte(NULL, "ModernData", "BehindEdge", SETTING_BEHINDEDGE_DEFAULT) == 0))
+ {
+ RECT rcScreen;
+ RECT rcWindow;
+ int bordersize = 0;
+ //Need to be moved out of screen
+
+ //1. get work area rectangle
+ //SystemParametersInfo(SPI_GETWORKAREA,0,&rcScreen,FALSE);
+ Docking_GetMonitorRectFromWindow(pcli->hwndContactList,&rcScreen);
+ //2. move out
+ bordersize = wBehindEdgeBorderSize;
+ GetWindowRect(pcli->hwndContactList,&rcWindow);
+ switch (method)
+ {
+ case 1: //left
+ rcWindow.left = rcScreen.left;
+ break;
+ case 2: //right
+ rcWindow.left = rcScreen.right-(rcWindow.right-rcWindow.left);
+ break;
+ }
+ g_CluiData.mutexPreventDockMoving = 0;
+ SetWindowPos(pcli->hwndContactList,NULL,rcWindow.left,rcWindow.top,0,0,SWP_NOZORDER|SWP_NOSIZE);
+ Sync(CLUIFrames_OnMoving,pcli->hwndContactList,&rcWindow);
+ g_CluiData.mutexPreventDockMoving = 1;
+
+ //3. store setting
+ db_set_b(NULL, "ModernData", "BehindEdge",0);
+ g_CluiData.nBehindEdgeState = 0;
+ }
+ return 0;
+}
+
+
+int CLUI_IsInMainWindow(HWND hwnd)
+{
+ if (hwnd == pcli->hwndContactList) return 1;
+ if (GetParent(hwnd) == pcli->hwndContactList) return 2;
+ return 0;
+}
+
+int CLUI_OnSkinLoad(WPARAM wParam, LPARAM lParam)
+{
+ ske_LoadSkinFromDB();
+
+ return 0;
+}
+
+
+
+
+static LPPROTOTICKS CLUI_GetProtoTicksByProto(char * szProto)
+{
+ int i;
+
+ for (i=0;i < 64;i++)
+ {
+ if (CycleStartTick[i].szProto == NULL) break;
+ if (mir_strcmp(CycleStartTick[i].szProto,szProto)) continue;
+ return(&CycleStartTick[i]);
+ }
+ for (i=0;i < 64;i++)
+ {
+ if (CycleStartTick[i].szProto == NULL)
+ {
+ CycleStartTick[i].szProto = mir_strdup(szProto);
+ CycleStartTick[i].nCycleStartTick = 0;
+ CycleStartTick[i].nIndex = i;
+ CycleStartTick[i].bGlobal = ( szProto[0] == 0 );
+ CycleStartTick[i].himlIconList = NULL;
+ return(&CycleStartTick[i]);
+ }
+ }
+ return (NULL);
+}
+
+static int CLUI_GetConnectingIconForProtoCount(char *szAccoName)
+{
+ char fileFull[MAX_PATH];
+ static char szFolderPath[MAX_PATH] = "";
+
+ int count = 8;
+
+ if ( !szFolderPath[0] )
+ {
+ char szRelativePath[MAX_PATH];
+ GetModuleFileNameA(GetModuleHandle(NULL), szRelativePath, MAX_PATH);
+ char *str = strrchr( szRelativePath, '\\' );
+ if ( str != NULL ) *str = 0;
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)szRelativePath, (LPARAM)szFolderPath);
+ }
+
+ if ( szAccoName )
+ {
+ // first of all try to find by account name( or empty - global )
+ mir_snprintf( fileFull, SIZEOF(fileFull), "%s\\Icons\\proto_conn_%s.dll", szFolderPath, szAccoName );
+ count = ExtractIconExA(fileFull,-1,NULL,NULL,1);
+ if ( count ) return count;
+
+ if ( szAccoName[0] )
+ {
+ // second try to find by protocol name
+ PROTOACCOUNT * acc = ProtoGetAccount( szAccoName );
+ if ( acc && !acc->bOldProto )
+ {
+ mir_snprintf( fileFull, SIZEOF(fileFull), "%s\\Icons\\proto_conn_%s.dll", szFolderPath, acc->szProtoName );
+ count = ExtractIconExA(fileFull,-1,NULL,NULL,1);
+ if ( count ) return count;
+ }
+ }
+ }
+ // third try global
+ mir_snprintf( fileFull, SIZEOF(fileFull), "%s\\Icons\\proto_conn.dll", szFolderPath );
+ count = ExtractIconExA(fileFull,-1,NULL,NULL,1);
+ if ( count ) return count;
+
+ return 8;
+}
+
+static HICON CLUI_ExtractIconFromPath(const char *path, BOOL * needFree)
+{
+ char *comma;
+ char file[MAX_PATH],fileFull[MAX_PATH];
+ int n;
+ HICON hIcon;
+ lstrcpynA(file,path,sizeof(file));
+ comma = strrchr(file,',');
+ if (comma == NULL) n = 0;
+ else {n = atoi(comma+1); *comma = 0;}
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)file, (LPARAM)fileFull);
+ hIcon = NULL;
+ ExtractIconExA(fileFull,n,NULL,&hIcon,1);
+ if (needFree)
+ {
+ *needFree = (hIcon != NULL);
+ }
+ return hIcon;
+}
+
+HICON CLUI_LoadIconFromExternalFile(char *filename,int i,BOOL UseLibrary,bool registerit,char *IconName,char *SectName,char *Description,int internalidx, BOOL * needFree)
+{
+ char szPath[MAX_PATH],szMyPath[MAX_PATH], szFullPath[MAX_PATH],*str;
+ HICON hIcon = NULL;
+ BOOL has_proto_icon = FALSE;
+ SKINICONDESC sid = {0};
+ if (needFree) *needFree = FALSE;
+ GetModuleFileNameA(GetModuleHandle(NULL), szPath, MAX_PATH);
+ GetModuleFileNameA(g_hInst, szMyPath, MAX_PATH);
+ str = strrchr(szPath,'\\');
+ if (str != NULL) *str = 0;
+ if (UseLibrary&2)
+ mir_snprintf(szMyPath, SIZEOF(szMyPath), "%s\\Icons\\%s", szPath, filename);
+ mir_snprintf(szFullPath, SIZEOF(szFullPath), "%s\\Icons\\%s,%d", szPath, filename, i);
+ if (str != NULL) *str = '\\';
+ if (UseLibrary&2)
+ {
+ BOOL nf;
+ HICON hi = CLUI_ExtractIconFromPath(szFullPath,&nf);
+ if (hi) has_proto_icon = TRUE;
+ if (hi && nf) DestroyIcon(hi);
+ }
+ if ( !UseLibrary) {
+ hIcon = CLUI_ExtractIconFromPath(szFullPath,needFree);
+ if (hIcon) return hIcon;
+ if (UseLibrary)
+ {
+ mir_snprintf(szFullPath, SIZEOF(szFullPath), "%s,%d", szMyPath, internalidx);
+ hIcon = CLUI_ExtractIconFromPath(szFullPath,needFree);
+ if (hIcon) return hIcon;
+ }
+ }
+ else {
+ if (registerit && IconName != NULL && SectName != NULL) {
+ sid.cbSize = sizeof(sid);
+ sid.cx = 16;
+ sid.cy = 16;
+ sid.hDefaultIcon = (has_proto_icon || !(UseLibrary&2))?NULL:(HICON)CallService(MS_SKIN_LOADPROTOICON,(WPARAM)NULL,(LPARAM)(-internalidx));
+ sid.pszSection = SectName;
+ sid.pszName = IconName;
+ sid.pszDescription = Description;
+ sid.pszDefaultFile = internalidx < 0?szMyPath:szPath;
+
+ sid.iDefaultIndex = (UseLibrary&2)?i:(internalidx < 0)?internalidx:-internalidx;
+ Skin_AddIcon(&sid);
+ }
+ return ((HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)IconName));
+ }
+
+
+
+
+ return (HICON)0;
+}
+
+static HICON CLUI_GetConnectingIconForProto(char *szAccoName, int b)
+{
+ char szFullPath[MAX_PATH];
+ HICON hIcon = NULL;
+ BOOL needFree;
+ b = b-1;
+
+ if ( szAccoName )
+ {
+ mir_snprintf(szFullPath, SIZEOF(szFullPath), "proto_conn_%s.dll",szAccoName);
+ hIcon = CLUI_LoadIconFromExternalFile(szFullPath,b+1,FALSE,FALSE,NULL,NULL,NULL,0,&needFree);
+ if (hIcon) return hIcon;
+
+ if ( szAccoName[0] )
+ {
+ // second try to find by protocol name
+ PROTOACCOUNT * acc = ProtoGetAccount( szAccoName );
+ if ( acc && !acc->bOldProto )
+ {
+ mir_snprintf( szFullPath, SIZEOF(szFullPath), "proto_conn_%s.dll", acc->szProtoName );
+ hIcon = CLUI_LoadIconFromExternalFile(szFullPath,b+1,FALSE,FALSE,NULL,NULL,NULL,0,&needFree);
+ if ( hIcon ) return hIcon;
+ }
+ }
+ }
+ // third try global
+ mir_snprintf( szFullPath, SIZEOF(szFullPath), "proto_conn.dll" );
+ hIcon = CLUI_LoadIconFromExternalFile(szFullPath,b+1,FALSE,FALSE,NULL,NULL,NULL,0,&needFree);
+ if ( hIcon ) return hIcon;
+
+ hIcon = LoadSmallIcon(g_hInst,(TCHAR *)(IDI_ICQC1+b+1));
+ return(hIcon);
+}
+
+
+INT_PTR CLUI_GetConnectingIconService(WPARAM wParam,LPARAM lParam)
+{
+ int b;
+ PROTOTICKS *pt = NULL;
+ HICON hIcon = NULL;
+
+ char *szProto = (char *)wParam;
+ if ( !szProto) return 0;
+
+ pt = CLUI_GetProtoTicksByProto(szProto);
+
+ if (pt != NULL)
+ {
+ if (pt->nCycleStartTick == 0)
+ {
+ CLUI_CreateTimerForConnectingIcon(ID_STATUS_CONNECTING,wParam);
+ pt = CLUI_GetProtoTicksByProto(szProto);
+ }
+ }
+ if (pt != NULL)
+ {
+ if (pt->nCycleStartTick != 0 && pt->nIconsCount != 0)
+ {
+ b = ((GetTickCount()-pt->nCycleStartTick)/(nAnimatedIconStep))%(pt->nIconsCount);
+ // if (lParam)
+ // hIcon = CLUI_GetConnectingIconForProto("Global",b);
+ // else
+ if (pt->himlIconList)
+ hIcon = ske_ImageList_GetIcon(pt->himlIconList,b,ILD_NORMAL);
+ else
+ hIcon = NULL;
+ //hIcon = CLUI_GetConnectingIconForProto(szProto,b);
+ };
+ }
+
+
+ return (INT_PTR)hIcon;
+};
+
+
+static int CLUI_CreateTimerForConnectingIcon(WPARAM wParam,LPARAM lParam)
+{
+
+ int status = (int)wParam;
+ char *szProto = (char *)lParam;
+ if ( !szProto) return (0);
+ if ( !status) return (0);
+
+ if ((g_StatusBarData.connectingIcon == 1) && status >= ID_STATUS_CONNECTING && status <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES)
+ {
+
+ PROTOTICKS *pt = NULL;
+ int cnt;
+
+ pt = CLUI_GetProtoTicksByProto(szProto);
+ if (pt != NULL)
+ {
+ if (pt->nCycleStartTick == 0)
+ {
+ KillTimer(pcli->hwndContactList,TM_STATUSBARUPDATE+pt->nIndex);
+ cnt = CLUI_GetConnectingIconForProtoCount(szProto);
+ if (cnt != 0)
+ {
+ int i=0;
+ nAnimatedIconStep = 100;/*DBGetContactSettingWord(NULL,"CLUI","DefaultStepConnectingIcon",100);*/
+ pt->nIconsCount = cnt;
+ if (pt->himlIconList) ImageList_Destroy(pt->himlIconList);
+ pt->himlIconList = ImageList_Create(16,16,ILC_MASK|ILC_COLOR32,cnt,1);
+ for (i=0; i < cnt; i++)
+ {
+ HICON ic = CLUI_GetConnectingIconForProto(szProto,i);
+ if (ic) ImageList_AddIcon(pt->himlIconList,ic);
+ DestroyIcon_protect(ic);
+ }
+ CLUI_SafeSetTimer(pcli->hwndContactList,TM_STATUSBARUPDATE+pt->nIndex,(int)(nAnimatedIconStep)/1,0);
+ pt->bTimerCreated = 1;
+ pt->nCycleStartTick = GetTickCount();
+ }
+
+ };
+ };
+ }
+ return 0;
+}
+
+static BOOL CALLBACK BroadcastEnumChildProc(HWND hwndChild, LPARAM lParam)
+{
+ MSG * pMsg = (MSG*)lParam;
+ SendNotifyMessage( hwndChild, pMsg->message, pMsg->wParam, pMsg->lParam );
+ EnumChildWindows( hwndChild, BroadcastEnumChildProc, lParam );
+ return TRUE;
+}
+
+static LRESULT BroadCastMessageToChild(HWND hwnd, int message, WPARAM wParam, LPARAM lParam )
+{
+ MSG msg = {0};
+ msg.hwnd = hwnd;
+ msg.lParam = lParam;
+ msg.wParam = wParam;
+ msg.message = message;
+ EnumChildWindows(hwnd, BroadcastEnumChildProc, (LPARAM) &msg);
+ return 1;
+}
+
+int CLUI_ReloadCLUIOptions()
+{
+ KillTimer(pcli->hwndContactList,TM_UPDATEBRINGTIMER);
+ g_CluiData.bBehindEdgeSettings = db_get_b(NULL, "ModernData", "HideBehind", SETTING_HIDEBEHIND_DEFAULT);
+ wBehindEdgeShowDelay = db_get_w(NULL,"ModernData","ShowDelay",SETTING_SHOWDELAY_DEFAULT);
+ wBehindEdgeHideDelay = db_get_w(NULL,"ModernData","HideDelay",SETTING_HIDEDELAY_DEFAULT);
+ wBehindEdgeBorderSize = db_get_w(NULL,"ModernData","HideBehindBorderSize",SETTING_HIDEBEHINDBORDERSIZE_DEFAULT);
+
+ g_CluiData.fAutoSize = db_get_b(NULL,"CLUI","AutoSize",SETTING_AUTOSIZE_DEFAULT);
+ g_CluiData.bInternalAwayMsgDiscovery = db_get_b(NULL,"ModernData","InternalAwayMsgDiscovery",SETTING_INTERNALAWAYMSGREQUEST_DEFAULT);
+ g_CluiData.bRemoveAwayMessageForOffline = db_get_b(NULL,"ModernData","RemoveAwayMessageForOffline",SETTING_REMOVEAWAYMSGFOROFFLINE_DEFAULT);
+ //window borders
+ if (g_CluiData.fDisableSkinEngine) {
+ g_CluiData.LeftClientMargin = 0;
+ g_CluiData.RightClientMargin = 0;
+ g_CluiData.TopClientMargin = 0;
+ g_CluiData.BottomClientMargin = 0;
+ } else {
+ //window borders
+ g_CluiData.LeftClientMargin = (int)db_get_b(NULL,"CLUI","LeftClientMargin",SETTING_LEFTCLIENTMARIGN_DEFAULT);
+ g_CluiData.RightClientMargin = (int)db_get_b(NULL,"CLUI","RightClientMargin",SETTING_RIGHTCLIENTMARIGN_DEFAULT);
+ g_CluiData.TopClientMargin = (int)db_get_b(NULL,"CLUI","TopClientMargin",SETTING_TOPCLIENTMARIGN_DEFAULT);
+ g_CluiData.BottomClientMargin = (int)db_get_b(NULL,"CLUI","BottomClientMargin",SETTING_BOTTOMCLIENTMARIGN_DEFAULT);
+ }
+ BroadCastMessageToChild(pcli->hwndContactList, WM_THEMECHANGED, 0, 0);
+
+ NotifyEventHooks(g_CluiData.hEventBkgrChanged, 0, 0);
+ return 0;
+}
+
+void CLUI_DisconnectAll()
+{
+ PROTOACCOUNT **accs;
+ int nProtoCount;
+ int nProto;
+
+ ProtoEnumAccounts( &nProtoCount, &accs );
+ for (nProto = 0; nProto < nProtoCount; nProto++)
+ if ( IsAccountEnabled( accs[nProto] ))
+ CallProtoService( accs[nProto]->szModuleName, PS_SETSTATUS, ID_STATUS_OFFLINE, 0 );
+}
+
+static int CLUI_DrawMenuBackGround(HWND hwnd, HDC hdc, int item, int state)
+{
+ RECT ra,r1;
+ // HBRUSH hbr;
+ HRGN treg,treg2;
+ struct ClcData * dat;
+
+ if ( !fnGetMenuBarInfo )
+ return 1;
+
+ dat = (struct ClcData*)GetWindowLongPtr(pcli->hwndContactTree,0);
+ if ( !dat) return 1;
+ GetWindowRect(hwnd,&ra);
+ {
+ MENUBARINFO mbi = {0};
+ mbi.cbSize = sizeof(MENUBARINFO);
+ fnGetMenuBarInfo(hwnd,OBJID_MENU, 0, &mbi);
+ if ( !(mbi.rcBar.right-mbi.rcBar.left>0 && mbi.rcBar.bottom-mbi.rcBar.top>0)) return 1;
+ r1 = mbi.rcBar;
+ r1.bottom += !db_get_b(NULL,"CLUI","LineUnderMenu",SETTING_LINEUNDERMENU_DEFAULT);
+ if (item < 1)
+ {
+ treg = CreateRectRgn(mbi.rcBar.left,mbi.rcBar.top,mbi.rcBar.right,r1.bottom);
+ if (item == 0) //should remove item clips
+ {
+ int t;
+ for (t = 1; t <= 2; t++)
+ {
+ fnGetMenuBarInfo(hwnd,OBJID_MENU, t, &mbi);
+ treg2 = CreateRectRgn(mbi.rcBar.left,mbi.rcBar.top,mbi.rcBar.right,mbi.rcBar.bottom);
+ CombineRgn(treg,treg,treg2,RGN_DIFF);
+ DeleteObject(treg2);
+ }
+
+ }
+ }
+ else
+ {
+ fnGetMenuBarInfo(hwnd,OBJID_MENU, item, &mbi);
+ treg = CreateRectRgn(mbi.rcBar.left,mbi.rcBar.top,mbi.rcBar.right,mbi.rcBar.bottom+!db_get_b(NULL,"CLUI","LineUnderMenu",SETTING_LINEUNDERMENU_DEFAULT));
+ }
+ OffsetRgn(treg,-ra.left,-ra.top);
+ r1.left -= ra.left;
+ r1.top -= ra.top;
+ r1.bottom -= ra.top;
+ r1.right -= ra.left;
+ }
+ //SelectClipRgn(hdc,NULL);
+ SelectClipRgn(hdc,treg);
+ DeleteObject(treg);
+ {
+ RECT rc;
+ HWND hwnd = pcli->hwndContactList;
+ GetWindowRect(hwnd,&rc);
+ OffsetRect(&rc,-rc.left, -rc.top);
+ FillRect(hdc,&r1,GetSysColorBrush(COLOR_MENU));
+ ske_SetRectOpaque(hdc,&r1);
+ //ske_BltBackImage(hwnd,hdc,&r1);
+ }
+ if ( !g_CluiData.fDisableSkinEngine)
+ SkinDrawGlyph(hdc,&r1,&r1,"Main,ID=MenuBar");
+ else
+ {
+ HBRUSH hbr = NULL;
+ if (dat->hMenuBackground)
+ {
+ BITMAP bmp;
+ HBITMAP oldbm;
+ HDC hdcBmp;
+ int x,y;
+ int maxx,maxy;
+ int destw,desth;
+ RECT clRect = r1;
+
+
+ // XXX: Halftone isnt supported on 9x, however the scretch problems dont happen on 98.
+ SetStretchBltMode(hdc, HALFTONE);
+
+ GetObject(dat->hMenuBackground,sizeof(bmp),&bmp);
+ hdcBmp = CreateCompatibleDC(hdc);
+ oldbm = (HBITMAP)SelectObject(hdcBmp,dat->hMenuBackground);
+ y = clRect.top;
+ x = clRect.left;
+ maxx = dat->MenuBmpUse&CLBF_TILEH?maxx = r1.right:x+1;
+ maxy = dat->MenuBmpUse&CLBF_TILEV?maxy = r1.bottom:y+1;
+ switch(dat->MenuBmpUse&CLBM_TYPE) {
+ case CLB_STRETCH:
+ if (dat->MenuBmpUse&CLBF_PROPORTIONAL) {
+ if (clRect.right-clRect.left*bmp.bmHeight < clRect.bottom-clRect.top*bmp.bmWidth)
+ {
+ desth = clRect.bottom-clRect.top;
+ destw = desth*bmp.bmWidth/bmp.bmHeight;
+ }
+ else
+ {
+ destw = clRect.right-clRect.left;
+ desth = destw*bmp.bmHeight/bmp.bmWidth;
+ }
+ }
+ else {
+ destw = clRect.right-clRect.left;
+ desth = clRect.bottom-clRect.top;
+ }
+ break;
+ case CLB_STRETCHH:
+ if (dat->MenuBmpUse&CLBF_PROPORTIONAL) {
+ destw = clRect.right-clRect.left;
+ desth = destw*bmp.bmHeight/bmp.bmWidth;
+ }
+ else {
+ destw = clRect.right-clRect.left;
+ desth = bmp.bmHeight;
+ }
+ break;
+ case CLB_STRETCHV:
+ if (dat->MenuBmpUse&CLBF_PROPORTIONAL) {
+ desth = clRect.bottom-clRect.top;
+ destw = desth*bmp.bmWidth/bmp.bmHeight;
+ }
+ else {
+ destw = bmp.bmWidth;
+ desth = clRect.bottom-clRect.top;
+ }
+ break;
+ default: //clb_topleft
+ destw = bmp.bmWidth;
+ desth = bmp.bmHeight;
+ break;
+ }
+ if (desth && destw)
+ for (y = clRect.top;y < maxy;y += desth) {
+ for (x = clRect.left;x < maxx;x += destw)
+ StretchBlt(hdc,x,y,destw,desth,hdcBmp,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
+ }
+ SelectObject(hdcBmp,oldbm);
+ DeleteDC(hdcBmp);
+
+ }
+
+ else
+ {
+ hbr = CreateSolidBrush(dat->MenuBkColor);
+ FillRect(hdc,&r1,hbr);
+ DeleteObject(hbr);
+ }
+ if (item != 0 && state&(ODS_SELECTED))
+ {
+ hbr = CreateSolidBrush(dat->MenuBkHiColor);
+ FillRect(hdc,&r1,hbr);
+ DeleteObject(hbr);
+ }
+ }
+ SelectClipRgn(hdc,NULL);
+ return 0;
+}
+
+int CLUI_SizingGetWindowRect(HWND hwnd,RECT * rc)
+{
+ if (mutex_bDuringSizing && hwnd == pcli->hwndContactList)
+ *rc = rcSizingRect;
+ else
+ GetWindowRect(hwnd,rc);
+ return 1;
+}
+
+
+int CLUI_SyncGetPDNCE(WPARAM wParam, LPARAM lParam)
+{
+ //log0("CLUI_SyncGetPDNCE");
+ return CListSettings_GetCopyFromCache((pdisplayNameCacheEntry)lParam, wParam ? (DWORD) wParam : CCI_ALL );
+}
+
+int CLUI_SyncSetPDNCE(WPARAM wParam, LPARAM lParam)
+{
+ //log0("CLUI_SyncSetPDNCE");
+ return CListSettings_SetToCache((pdisplayNameCacheEntry)lParam, wParam ? (DWORD) wParam : CCI_ALL );
+}
+
+int CLUI_SyncGetShortData(WPARAM wParam, LPARAM lParam)
+{
+ HWND hwnd = (HWND) wParam;
+ struct ClcData * dat = (struct ClcData * )GetWindowLongPtr(hwnd,0);
+ //log0("CLUI_SyncGetShortData");
+ return ClcGetShortData(dat,(struct SHORTDATA *)lParam);
+}
+
+int CLUI_SyncSmoothAnimation(WPARAM wParam, LPARAM lParam)
+{
+ return CLUI_SmoothAlphaThreadTransition((HWND)lParam);
+}
+
+
+
+int CLUI_IconsChanged(WPARAM wParam,LPARAM lParam)
+{
+ if (MirandaExiting()) return 0;
+ DrawMenuBar(pcli->hwndContactList);
+ ExtraImage_ReloadExtraIcons();
+ ExtraImage_SetAllExtraIcons(pcli->hwndContactTree,0);
+ // need to update tray cause it use combined icons
+ pcli->pfnTrayIconIconsChanged(); //TODO: remove as soon as core will include icolib
+ ske_RedrawCompleteWindow();
+ // pcli->pfnClcBroadcast( INTM_INVALIDATE,0,0);
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+void CLUI_cli_LoadCluiGlobalOpts()
+{
+ BOOL tLayeredFlag = FALSE;
+ tLayeredFlag = IsWinVer2000Plus();
+ tLayeredFlag &= db_get_b(NULL, "ModernData", "EnableLayering", tLayeredFlag);
+
+ if (tLayeredFlag)
+ {
+ if (db_get_b(NULL,"CList","WindowShadow",SETTING_WINDOWSHADOW_DEFAULT) == 1)
+ db_set_b(NULL,"CList","WindowShadow",2);
+ }
+ else
+ {
+ if (db_get_b(NULL,"CList","WindowShadow",SETTING_WINDOWSHADOW_DEFAULT) == 2)
+ db_set_b(NULL,"CList","WindowShadow",1);
+ }
+ corecli.pfnLoadCluiGlobalOpts();
+}
+
+
+int CLUI_TestCursorOnBorders()
+{
+ HWND hwnd = pcli->hwndContactList;
+ HCURSOR hCurs1 = NULL;
+ RECT r;
+ POINT pt;
+ int k = 0, t = 0, fx,fy;
+ HWND hAux;
+ BOOL mouse_in_window = 0;
+ HWND gf = GetForegroundWindow();
+ GetCursorPos(&pt);
+ hAux = WindowFromPoint(pt);
+ if (CLUI_CheckOwnedByClui(hAux))
+ {
+ if (g_bTransparentFlag) {
+ if ( !bTransparentFocus && gf != hwnd) {
+ CLUI_SmoothAlphaTransition(hwnd, db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT), 1);
+ //g_proc_SetLayeredWindowAttributes(hwnd, RGB(0,0,0), (BYTE)DBGetContactSettingByte(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT), LWA_ALPHA);
+ bTransparentFocus = 1;
+ CLUI_SafeSetTimer(hwnd, TM_AUTOALPHA,250,NULL);
+ }
+ }
+ }
+
+ mutex_bIgnoreActivation = 0;
+ GetWindowRect(hwnd,&r);
+ /*
+ * Size borders offset (contract)
+ */
+ r.top += db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Top",SKIN_OFFSET_TOP_DEFAULT);
+ r.bottom -= db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Bottom",SKIN_OFFSET_BOTTOM_DEFAULT);
+ r.left += db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Left",SKIN_OFFSET_LEFT_DEFAULT);
+ r.right -= db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Right",SKIN_OFFSET_RIGHT_DEFAULT);
+
+ if (r.right < r.left) r.right = r.left;
+ if (r.bottom < r.top) r.bottom = r.top;
+
+ /*
+ * End of size borders offset (contract)
+ */
+
+ hAux = WindowFromPoint(pt);
+ while(hAux != NULL)
+ {
+ if (hAux == hwnd) {mouse_in_window = 1; break;}
+ hAux = GetParent(hAux);
+ }
+ fx = GetSystemMetrics(SM_CXFULLSCREEN);
+ fy = GetSystemMetrics(SM_CYFULLSCREEN);
+ if (g_CluiData.fDocked || g_CluiData.nBehindEdgeState == 0)
+ //if (g_CluiData.fDocked) || ((pt.x < fx-1) && (pt.y < fy-1) && pt.x>1 && pt.y>1)) // workarounds for behind the edge.
+ {
+ //ScreenToClient(hwnd,&pt);
+ //GetClientRect(hwnd,&r);
+ if (pt.y <= r.bottom && pt.y >= r.bottom-SIZING_MARGIN && !g_CluiData.fAutoSize) k = 6;
+ else if (pt.y >= r.top && pt.y <= r.top+SIZING_MARGIN && !g_CluiData.fAutoSize) k = 3;
+ if (pt.x <= r.right && pt.x >= r.right-SIZING_MARGIN && g_CluiData.bBehindEdgeSettings != 2) k += 2;
+ else if (pt.x >= r.left && pt.x <= r.left+SIZING_MARGIN && g_CluiData.bBehindEdgeSettings != 1) k += 1;
+ if ( !(pt.x >= r.left && pt.x <= r.right && pt.y >= r.top && pt.y <= r.bottom)) k = 0;
+ k *= mouse_in_window;
+ hCurs1 = LoadCursor(NULL, IDC_ARROW);
+ if (g_CluiData.nBehindEdgeState <= 0 && (!(db_get_b(NULL,"CLUI","LockSize",SETTING_LOCKSIZE_DEFAULT))))
+ switch(k)
+ {
+ case 1:
+ case 2:
+ if ( !g_CluiData.fDocked || (g_CluiData.fDocked == 2 && k == 1) || (g_CluiData.fDocked == 1 && k == 2)){hCurs1 = LoadCursor(NULL, IDC_SIZEWE); break;}
+ case 3: if ( !g_CluiData.fDocked) {hCurs1 = LoadCursor(NULL, IDC_SIZENS); break;}
+ case 4: if ( !g_CluiData.fDocked) {hCurs1 = LoadCursor(NULL, IDC_SIZENWSE); break;}
+ case 5: if ( !g_CluiData.fDocked) {hCurs1 = LoadCursor(NULL, IDC_SIZENESW); break;}
+ case 6: if ( !g_CluiData.fDocked) {hCurs1 = LoadCursor(NULL, IDC_SIZENS); break;}
+ case 7: if ( !g_CluiData.fDocked) {hCurs1 = LoadCursor(NULL, IDC_SIZENESW); break;}
+ case 8: if ( !g_CluiData.fDocked) {hCurs1 = LoadCursor(NULL, IDC_SIZENWSE); break;}
+ }
+ if (hCurs1) SetCursor(hCurs1);
+ return k;
+ }
+
+ return 0;
+}
+
+int CLUI_SizingOnBorder(POINT pt, int PerformSize)
+{
+ if ( !(db_get_b(NULL,"CLUI","LockSize",SETTING_LOCKSIZE_DEFAULT)))
+ {
+ RECT r;
+ HWND hwnd = pcli->hwndContactList;
+ int sizeOnBorderFlag = 0;
+ GetWindowRect(hwnd,&r);
+ /*
+ * Size borders offset (contract)
+ */
+ r.top += db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Top",SKIN_OFFSET_TOP_DEFAULT);
+ r.bottom -= db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Bottom",SKIN_OFFSET_BOTTOM_DEFAULT);
+ r.left += db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Left",SKIN_OFFSET_LEFT_DEFAULT);
+ r.right -= db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Right",SKIN_OFFSET_RIGHT_DEFAULT);
+
+ if (r.right < r.left) r.right = r.left;
+ if (r.bottom < r.top) r.bottom = r.top;
+
+ /*
+ * End of size borders offset (contract)
+ */
+ if ( !g_CluiData.fAutoSize )
+ {
+ if ( pt.y <= r.bottom && pt.y >= r.bottom - SIZING_MARGIN ) sizeOnBorderFlag = SCF_BOTTOM;
+ else if ( pt.y >= r.top && pt.y <= r.top + SIZING_MARGIN ) sizeOnBorderFlag = SCF_TOP;
+ }
+
+ if ( pt.x <= r.right && pt.x >= r.right - SIZING_MARGIN ) sizeOnBorderFlag += SCF_RIGHT;
+ else if ( pt.x >= r.left && pt.x <= r.left + SIZING_MARGIN ) sizeOnBorderFlag += SCF_LEFT;
+
+ if ( !(pt.x >= r.left && pt.x <= r.right && pt.y >= r.top && pt.y <= r.bottom)) sizeOnBorderFlag = SCF_NONE;
+
+ if (sizeOnBorderFlag && PerformSize)
+ {
+ ReleaseCapture();
+ SendMessage(hwnd, WM_SYSCOMMAND, SC_SIZE + sizeOnBorderFlag,MAKELPARAM(pt.x,pt.y));
+ return sizeOnBorderFlag;
+ }
+ else return sizeOnBorderFlag;
+ }
+ return SCF_NONE;
+}
+int CLUI_SyncSmoothAnimation(WPARAM wParam, LPARAM lParam);
+static void CLUI_SmoothAnimationThreadProc(HWND hwnd)
+{
+ // return;
+ if ( !mutex_bAnimationInProgress)
+ {
+ g_dwSmoothAnimationThreadID = 0;
+ return; /// Should be some locked to avoid painting against contact deletion.
+ }
+ do
+ {
+ if ( !g_mutex_bLockUpdating)
+ {
+ if ( !MirandaExiting())
+ Sync(CLUI_SyncSmoothAnimation, (WPARAM)0, (LPARAM)hwnd );
+ SleepEx(20,TRUE);
+ if (MirandaExiting())
+ {
+ g_dwSmoothAnimationThreadID = 0;
+ return;
+ }
+ }
+ else SleepEx(0,TRUE);
+
+ } while (mutex_bAnimationInProgress);
+ g_dwSmoothAnimationThreadID = 0;
+ return;
+}
+
+static int CLUI_SmoothAlphaThreadTransition(HWND hwnd)
+{
+ int step;
+ int a;
+
+ step = (g_CluiData.bCurrentAlpha>bAlphaEnd)?-1*ANIMATION_STEP:ANIMATION_STEP;
+ a = g_CluiData.bCurrentAlpha+step;
+ if ((step >= 0 && a >= bAlphaEnd) || (step <= 0 && a <= bAlphaEnd))
+ {
+ mutex_bAnimationInProgress = 0;
+ g_CluiData.bCurrentAlpha = bAlphaEnd;
+ if (g_CluiData.bCurrentAlpha == 0)
+ {
+ g_CluiData.bCurrentAlpha = 1;
+ ske_JustUpdateWindowImage();
+ mutex_bShowHideCalledFromAnimation = 1;
+ CLUI_ShowWindowMod(pcli->hwndContactList,0);
+ Sync(CLUIFrames_OnShowHide, hwnd,0);
+ mutex_bShowHideCalledFromAnimation = 0;
+ g_CluiData.bCurrentAlpha = 0;
+ if ( !g_CluiData.fLayered) RedrawWindow(pcli->hwndContactList,NULL,NULL,RDW_ERASE|RDW_FRAME);
+ return 0;
+ }
+ }
+ else g_CluiData.bCurrentAlpha = a;
+ ske_JustUpdateWindowImage();
+ return 1;
+}
+
+int CLUI_SmoothAlphaTransition(HWND hwnd, BYTE GoalAlpha, BOOL wParam)
+{
+
+ if ((!g_CluiData.fLayered
+ && (!g_CluiData.fSmoothAnimation && !g_bTransparentFlag)) || !g_proc_SetLayeredWindowAttributesNew)
+ {
+ if (GoalAlpha>0 && wParam != 2)
+ {
+ if ( !IsWindowVisible(hwnd))
+ {
+ mutex_bShowHideCalledFromAnimation = 1;
+ CLUI_ShowWindowMod(pcli->hwndContactList,SW_RESTORE);
+ Sync(CLUIFrames_OnShowHide, hwnd,1);
+ mutex_bShowHideCalledFromAnimation = 0;
+ g_CluiData.bCurrentAlpha = GoalAlpha;
+ ske_UpdateWindowImage();
+
+ }
+ }
+ else if (GoalAlpha == 0 && wParam != 2)
+ {
+ if (IsWindowVisible(hwnd))
+ {
+ mutex_bShowHideCalledFromAnimation = 1;
+ CLUI_ShowWindowMod(pcli->hwndContactList,0);
+ Sync(CLUIFrames_OnShowHide, hwnd,0);
+ g_CluiData.bCurrentAlpha = GoalAlpha;
+ mutex_bShowHideCalledFromAnimation = 0;
+
+ }
+ }
+ return 0;
+ }
+ if (g_CluiData.bCurrentAlpha == GoalAlpha && 0)
+ {
+ if (mutex_bAnimationInProgress)
+ {
+ KillTimer(hwnd,TM_SMOTHALPHATRANSITION);
+ mutex_bAnimationInProgress = 0;
+ }
+ return 0;
+ }
+ if (mutex_bShowHideCalledFromAnimation) return 0;
+ if (wParam != 2) //not from timer
+ {
+ bAlphaEnd = GoalAlpha;
+ if ( !mutex_bAnimationInProgress)
+ {
+ if ((!IsWindowVisible(hwnd) || g_CluiData.bCurrentAlpha == 0) && bAlphaEnd>0 )
+ {
+ mutex_bShowHideCalledFromAnimation = 1;
+ CLUI_ShowWindowMod(pcli->hwndContactList,SW_SHOWNA);
+ Sync(CLUIFrames_OnShowHide, hwnd,SW_SHOW);
+ mutex_bShowHideCalledFromAnimation = 0;
+ g_CluiData.bCurrentAlpha = 1;
+ ske_UpdateWindowImage();
+ }
+ if (IsWindowVisible(hwnd) && !g_dwSmoothAnimationThreadID)
+ {
+ mutex_bAnimationInProgress = 1;
+ if (g_CluiData.fSmoothAnimation)
+ g_dwSmoothAnimationThreadID = (DWORD)mir_forkthread((pThreadFunc)CLUI_SmoothAnimationThreadProc,pcli->hwndContactList);
+
+ }
+ }
+ }
+
+ {
+ int step;
+ int a;
+ step = (g_CluiData.bCurrentAlpha>bAlphaEnd)?-1*ANIMATION_STEP:ANIMATION_STEP;
+ a = g_CluiData.bCurrentAlpha+step;
+ if ((step >= 0 && a >= bAlphaEnd) || (step <= 0 && a <= bAlphaEnd) || g_CluiData.bCurrentAlpha == bAlphaEnd || !g_CluiData.fSmoothAnimation) //stop animation;
+ {
+ KillTimer(hwnd,TM_SMOTHALPHATRANSITION);
+ mutex_bAnimationInProgress = 0;
+ if (bAlphaEnd == 0)
+ {
+ g_CluiData.bCurrentAlpha = 1;
+ ske_UpdateWindowImage();
+ mutex_bShowHideCalledFromAnimation = 1;
+ CLUI_ShowWindowMod(pcli->hwndContactList,0);
+ Sync(CLUIFrames_OnShowHide, pcli->hwndContactList,0);
+ mutex_bShowHideCalledFromAnimation = 0;
+ g_CluiData.bCurrentAlpha = 0;
+ }
+ else
+ {
+ g_CluiData.bCurrentAlpha = bAlphaEnd;
+ ske_UpdateWindowImage();
+ }
+ }
+ else
+ {
+ g_CluiData.bCurrentAlpha = a;
+ ske_UpdateWindowImage();
+ }
+ }
+
+ return 0;
+}
+
+BOOL CLUI__cliInvalidateRect(HWND hWnd, CONST RECT* lpRect,BOOL bErase )
+{
+ if (g_mutex_bSetAllExtraIconsCycle)
+ return FALSE;
+ if (CLUI_IsInMainWindow(hWnd) && g_CluiData.fLayered)// && IsWindowVisible(hWnd))
+ {
+ if (IsWindowVisible(hWnd))
+ return SkinInvalidateFrame( hWnd, lpRect );
+ else
+ {
+ g_flag_bFullRepaint = 1;
+ return 0;
+ }
+ }
+ else
+ return InvalidateRect(hWnd,lpRect,bErase);
+ return 1;
+}
+
+static BOOL FileExists(TCHAR * tszFilename)
+{
+ BOOL result = FALSE;
+ FILE * f = _tfopen(tszFilename,_T("r"));
+ if (f == NULL) return FALSE;
+ fclose(f);
+ return TRUE;
+}
+
+HANDLE RegisterIcolibIconHandle(char * szIcoID, char *szSectionName, char * szDescription, TCHAR * tszDefaultFile, int iDefaultIndex, HINSTANCE hDefaultModuleInst, int iDefaultResource )
+{
+ TCHAR fileFull[MAX_PATH] = {0};
+ SKINICONDESC sid = {0};
+ HANDLE hIcolibItem = NULL;
+ sid.cbSize = sizeof(sid);
+ sid.cx = 16;
+ sid.cy = 16;
+ sid.pszSection = szSectionName;
+ sid.pszName = szIcoID;
+ sid.flags |= SIDF_PATH_TCHAR;
+ sid.pszDescription = szDescription;
+
+ if (tszDefaultFile)
+ {
+ CallService( MS_UTILS_PATHTOABSOLUTET, ( WPARAM )tszDefaultFile, ( LPARAM )fileFull );
+ if ( !FileExists(fileFull)) fileFull[0] = _T('\0');
+ }
+ if (fileFull[0] != _T('\0'))
+ {
+ sid.ptszDefaultFile = fileFull;
+ sid.iDefaultIndex = iDefaultIndex;
+ sid.hDefaultIcon = NULL;
+ }
+ else
+ {
+ sid.pszDefaultFile = NULL;
+ sid.iDefaultIndex = 0;
+ sid.hDefaultIcon = LoadSmallIcon( hDefaultModuleInst, MAKEINTRESOURCE(iDefaultResource));
+ }
+ hIcolibItem = Skin_AddIcon(&sid);
+ if ( sid.hDefaultIcon ) DestroyIcon(sid.hDefaultIcon);
+ return hIcolibItem;
+}
+
+// MAIN WINPROC MESSAGE HANDLERS
+LRESULT CLUI::PreProcessWndProc( UINT msg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
+{
+ // proxy CLUI Messages
+ LRESULT result = 0;
+ if ( ProcessCLUIFrameInternalMsg( m_hWnd, msg, wParam, lParam, result ))
+ {
+ bHandled = TRUE;
+ return result;
+ }
+
+ /*
+ This registers a window message with RegisterWindowMessage() and then waits for such a message,
+ if it gets it, it tries to open a file mapping object and then maps it to this process space,
+ it expects 256 bytes of data (incl. NULL) it will then write back the profile it is using the DB to fill in the answer.
+
+ The caller is expected to create this mapping object and tell us the ID we need to open ours.
+ */
+ if (g_CluiData.bSTATE == STATE_EXITING && msg != WM_DESTROY)
+ {
+ bHandled = TRUE;
+ return 0;
+ }
+ if (msg == uMsgGetProfile && wParam != 0) /* got IPC message */
+ {
+ HANDLE hMap;
+ char szName[MAX_PATH];
+ int rc = 0;
+ mir_snprintf( szName, SIZEOF(szName), "Miranda::%u", wParam ); // caller will tell us the ID of the map
+ hMap = OpenFileMappingA( FILE_MAP_ALL_ACCESS,FALSE, szName );
+ if ( hMap != NULL )
+ {
+ void *hView = NULL;
+ hView = MapViewOfFile( hMap, FILE_MAP_ALL_ACCESS, 0, 0, MAX_PATH );
+ if (hView)
+ {
+ char szFilePath[MAX_PATH], szProfile[MAX_PATH];
+ CallService( MS_DB_GETPROFILEPATH,MAX_PATH,(LPARAM)&szFilePath );
+ CallService( MS_DB_GETPROFILENAME,MAX_PATH,(LPARAM)&szProfile );
+ _snprintf((char*)hView, MAX_PATH, "%s\\%s", szFilePath, szProfile );
+ UnmapViewOfFile( hView );
+ rc = 1;
+ }
+ CloseHandle( hMap );
+ }
+ bHandled = TRUE;
+ return rc;
+ }
+ return FALSE;
+}
+
+
+LRESULT CLUI::OnSizingMoving( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ if (g_CluiData.fLayered)
+ {
+ if (msg == WM_SIZING)
+ {
+ static int a = 0;
+ RECT* wp = (RECT*)lParam;
+ if (bNeedFixSizingRect && (rcCorrectSizeRect.bottom != 0 || rcCorrectSizeRect.top != 0))
+ {
+ if (wParam != WMSZ_BOTTOM) wp->bottom = rcCorrectSizeRect.bottom;
+ if (wParam != WMSZ_TOP) wp->top = rcCorrectSizeRect.top;
+ }
+ bNeedFixSizingRect = 0;
+ rcSizingRect = *wp;
+ mutex_bDuringSizing = 1;
+ return 1;
+ }
+
+ if (msg == WM_WINDOWPOSCHANGING)
+ {
+
+
+ WINDOWPOS * wp;
+ HDWP PosBatch;
+ RECT work_rect = {0};
+ RECT temp_rect = {0};
+ wp = (WINDOWPOS *)lParam;
+ GetWindowRect(m_hWnd,&rcOldWindowRect);
+
+ // Ïðèëèïàíèå ê êðàÿì by ZorG
+ CLUI::SnappingToEdge(wp);
+
+ if ((rcOldWindowRect.bottom-rcOldWindowRect.top != wp->cy || rcOldWindowRect.right-rcOldWindowRect.left != wp->cx) && !(wp->flags&SWP_NOSIZE))
+ {
+ {
+ if ( !(wp->flags&SWP_NOMOVE))
+ {
+ rcNewWindowRect.left = wp->x;
+ rcNewWindowRect.top = wp->y;
+ }
+ else
+ {
+ rcNewWindowRect.left = rcOldWindowRect.left;
+ rcNewWindowRect.top = rcOldWindowRect.top;
+ }
+ rcNewWindowRect.right = rcNewWindowRect.left+wp->cx;
+ rcNewWindowRect.bottom = rcNewWindowRect.top+wp->cy;
+ work_rect = rcNewWindowRect;
+ }
+ //resize frames (batch)
+ {
+ PosBatch = BeginDeferWindowPos(1);
+ SizeFramesByWindowRect(&work_rect,&PosBatch,0);
+ }
+ //Check rect after frames resize
+ {
+ GetWindowRect(m_hWnd,&temp_rect);
+ }
+ //Here work_rect should be changed to fit possible changes in cln_listsizechange
+ if (bNeedFixSizingRect)
+ {
+ work_rect = rcSizingRect;
+ wp->x = work_rect.left;
+ wp->y = work_rect.top;
+ wp->cx = work_rect.right-work_rect.left;
+ wp->cy = work_rect.bottom-work_rect.top;
+ wp->flags &= ~(SWP_NOMOVE);
+ }
+ //reposition buttons and new size applying
+ {
+ ModernSkinButton_ReposButtons( m_hWnd, SBRF_DO_NOT_DRAW, &work_rect );
+ ske_PrepeareImageButDontUpdateIt(&work_rect);
+ g_CluiData.mutexPreventDockMoving = 0;
+ ske_UpdateWindowImageRect(&work_rect);
+ EndDeferWindowPos(PosBatch);
+ g_CluiData.mutexPreventDockMoving = 1;
+ }
+ Sleep(0);
+ mutex_bDuringSizing = 0;
+ DefWindowProc(m_hWnd,msg,wParam,lParam);
+ return SendMessage(m_hWnd,WM_WINDOWPOSCHANGED,wParam,lParam);
+ }
+ else
+ {
+ SetRect(&rcCorrectSizeRect,0,0,0,0);
+ // bNeedFixSizingRect = 0;
+ }
+ return DefWindowProc(m_hWnd,msg,wParam,lParam);
+ }
+ }
+
+ else if (msg == WM_WINDOWPOSCHANGING)
+ {
+ // Snaping if it is not in LayeredMode
+ WINDOWPOS * wp;
+ wp = (WINDOWPOS *)lParam;
+ CLUI::SnappingToEdge( wp );
+ return DefWindowProc(m_hWnd,msg,wParam,lParam);
+ }
+ switch (msg)
+ {
+ case WM_DISPLAYCHANGE:
+ SendMessage(pcli->hwndContactTree, WM_SIZE, 0, 0);
+ return TRUE;
+
+ case WM_EXITSIZEMOVE:
+ {
+ int res = DefWindowProc(m_hWnd, msg, wParam, lParam);
+ ReleaseCapture();
+ TRACE("WM_EXITSIZEMOVE\n");
+ SendMessage(m_hWnd, WM_ACTIVATE, (WPARAM)WA_ACTIVE, (LPARAM)m_hWnd);
+ return res;
+ }
+
+ case WM_SIZING:
+ return DefWindowProc(m_hWnd, msg, wParam, lParam);;
+
+ case WM_MOVE:
+ {
+ RECT rc;
+ CallWindowProc(DefWindowProc, m_hWnd, msg, wParam, lParam);
+ mutex_bDuringSizing = 0;
+ GetWindowRect(m_hWnd, &rc);
+ CheckFramesPos(&rc);
+ Sync(CLUIFrames_OnMoving,m_hWnd,&rc);
+ if ( !IsIconic(m_hWnd)) {
+ if ( !CallService(MS_CLIST_DOCKINGISDOCKED,0,0))
+ { //if g_CluiData.fDocked, dont remember pos (except for width)
+ db_set_dw(NULL,"CList","Height",(DWORD)(rc.bottom - rc.top));
+ db_set_dw(NULL,"CList","x",(DWORD)rc.left);
+ db_set_dw(NULL,"CList","y",(DWORD)rc.top);
+ }
+ db_set_dw(NULL,"CList","Width",(DWORD)(rc.right - rc.left));
+ }
+ return TRUE;
+ }
+ case WM_SIZE:
+ {
+ RECT rc;
+ if (g_mutex_bSizing) return 0;
+ if (wParam != SIZE_MINIMIZED /* && IsWindowVisible(m_hWnd)*/)
+ {
+ if ( pcli->hwndContactList == NULL )
+ return 0;
+
+ if ( !g_CluiData.fLayered && !g_CluiData.fDisableSkinEngine)
+ ske_ReCreateBackImage(TRUE,NULL);
+
+ GetWindowRect(m_hWnd, &rc);
+ CheckFramesPos(&rc);
+ ModernSkinButton_ReposButtons( m_hWnd, SBRF_DO_NOT_DRAW, &rc);
+ ModernSkinButton_ReposButtons( m_hWnd, SBRF_REDRAW, NULL);
+ if (g_CluiData.fLayered)
+ CallService(MS_SKINENG_UPTATEFRAMEIMAGE,(WPARAM)m_hWnd,0);
+
+ if ( !g_CluiData.fLayered)
+ {
+ g_mutex_bSizing = 1;
+ Sync(CLUIFrames_OnClistResize_mod,(WPARAM)m_hWnd,(LPARAM)1);
+ CLUIFrames_ApplyNewSizes(2);
+ CLUIFrames_ApplyNewSizes(1);
+ SendMessage(m_hWnd,CLN_LISTSIZECHANGE,0,0);
+ g_mutex_bSizing = 0;
+ }
+
+ // ske_RedrawCompleteWindow();
+ if ( !CallService(MS_CLIST_DOCKINGISDOCKED,0,0))
+ { //if g_CluiData.fDocked, dont remember pos (except for width)
+ db_set_dw(NULL,"CList","Height",(DWORD)(rc.bottom - rc.top));
+ db_set_dw(NULL,"CList","x",(DWORD)rc.left);
+ db_set_dw(NULL,"CList","y",(DWORD)rc.top);
+ }
+ else SetWindowRgn(m_hWnd,NULL,0);
+ db_set_dw(NULL,"CList","Width",(DWORD)(rc.right - rc.left));
+
+ if ( !g_CluiData.fLayered)
+ {
+ HRGN hRgn1;
+ RECT r;
+ int v,h;
+ int w = 10;
+ GetWindowRect(m_hWnd,&r);
+ h = (r.right-r.left)>(w*2)?w:(r.right-r.left);
+ v = (r.bottom-r.top)>(w*2)?w:(r.bottom-r.top);
+ h = (h < v)?h:v;
+ hRgn1 = CreateRoundRectRgn(0,0,(r.right-r.left+1),(r.bottom-r.top+1),h,h);
+ if ((db_get_b(NULL,"CLC","RoundCorners",SETTING_ROUNDCORNERS_DEFAULT)) && (!CallService(MS_CLIST_DOCKINGISDOCKED,0,0)))
+ SetWindowRgn(m_hWnd,hRgn1,FALSE);
+ else
+ {
+ DeleteObject(hRgn1);
+ SetWindowRgn(m_hWnd,NULL,FALSE);
+ }
+ RedrawWindow(m_hWnd,NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_FRAME|RDW_UPDATENOW|RDW_ALLCHILDREN);
+ }
+ }
+ else {
+ if (db_get_b(NULL,"CList","Min2Tray",SETTING_MIN2TRAY_DEFAULT)) {
+ CLUI_ShowWindowMod(m_hWnd, SW_HIDE);
+ db_set_b(NULL,"CList","State",SETTING_STATE_HIDDEN);
+ }
+ else db_set_b(NULL,"CList","State",SETTING_STATE_MINIMIZED);
+ if (MySetProcessWorkingSetSize != NULL)
+ MySetProcessWorkingSetSize(GetCurrentProcess(),-1,-1);
+ }
+
+ return TRUE;
+ }
+ case WM_WINDOWPOSCHANGING:
+ {
+ WINDOWPOS *wp = (WINDOWPOS *)lParam;
+ if (wp->flags&SWP_HIDEWINDOW && mutex_bAnimationInProgress)
+ return 0;
+ if (g_CluiData.fOnDesktop)
+ wp->flags |= SWP_NOACTIVATE|SWP_NOZORDER;
+ return DefWindowProc(m_hWnd, msg, wParam, lParam);
+ }
+ }
+ return 0;
+}
+
+LRESULT CLUI::OnThemeChanged( UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ )
+{
+ xpt_OnWM_THEMECHANGED();
+ return FALSE;
+}
+
+LRESULT CLUI::OnDwmCompositionChanged( UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ )
+{
+ g_CluiData.fAeroGlass = false;
+ CLUI_UpdateAeroGlass();
+ return FALSE;
+}
+
+LRESULT CLUI::OnSyncCall( UINT /*msg*/, WPARAM wParam, LPARAM /*lParam*/ )
+{
+ return SyncOnWndProcCall( wParam );
+}
+
+LRESULT CLUI::OnUpdate( UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ )
+{
+ if ( g_flag_bPostWasCanceled )
+ return FALSE;
+ return ske_ValidateFrameImageProc( NULL );
+}
+
+LRESULT CLUI::OnInitMenu( UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ )
+{
+ if ( !CLUI::IsMainMenuInited()) {
+ if ( ServiceExists( MS_CLIST_MENUBUILDMAIN ))
+ CallService( MS_CLIST_MENUBUILDMAIN, 0, 0 );
+ CLUI::m_fMainMenuInited = TRUE;
+ }
+ return FALSE;
+}
+
+LRESULT CLUI::OnNcPaint( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ int lRes = DefWindowProc( m_hWnd, msg, wParam, lParam );
+ if ( !g_CluiData.fLayered && db_get_b( NULL,"CLUI","ShowMainMenu",SETTING_SHOWMAINMENU_DEFAULT )) {
+ HDC hdc = NULL;
+ if ( msg == WM_PRINT ) hdc = (HDC)wParam;
+ if ( !hdc ) hdc = GetWindowDC( m_hWnd );
+ CLUI_DrawMenuBackGround( m_hWnd, hdc, 0, 0 );
+ if ( msg != WM_PRINT ) ReleaseDC( m_hWnd, hdc );
+ }
+ return lRes;
+}
+
+LRESULT CLUI::OnEraseBkgnd( UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ )
+{
+ return TRUE;
+}
+
+LRESULT CLUI::OnNcCreate( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ ((LPCREATESTRUCT)lParam )->style &= ~(CS_HREDRAW | CS_VREDRAW);
+ return DefCluiWndProc( msg, wParam, lParam );
+}
+
+LRESULT CLUI::OnPaint( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ if ( !g_CluiData.fLayered && IsWindowVisible(m_hWnd)) {
+ RECT w = {0};
+ RECT w2 = {0};
+ PAINTSTRUCT ps = {0};
+ HDC hdc;
+ HBITMAP hbmp,oldbmp;
+ HDC paintDC;
+
+ GetClientRect(m_hWnd,&w);
+ if ( !(w.right>0 && w.bottom>0)) return DefWindowProc(m_hWnd, msg, wParam, lParam);
+
+ if ( !g_CluiData.fDisableSkinEngine)
+ {
+ paintDC = GetDC(m_hWnd);
+ w2 = w;
+ hdc = CreateCompatibleDC(paintDC);
+ hbmp = ske_CreateDIB32(w.right,w.bottom);
+ oldbmp = (HBITMAP)SelectObject(hdc,hbmp);
+ ske_ReCreateBackImage(FALSE,NULL);
+ BitBlt(paintDC,w2.left,w2.top,w2.right-w2.left,w2.bottom-w2.top,g_pCachedWindow->hBackDC,w2.left,w2.top,SRCCOPY);
+ SelectObject(hdc,oldbmp);
+ DeleteObject(hbmp);
+ mod_DeleteDC(hdc);
+ ReleaseDC(m_hWnd,paintDC);
+ }
+ else {
+ HDC hdc = BeginPaint(m_hWnd,&ps);
+ ske_BltBackImage(m_hWnd,hdc,&ps.rcPaint);
+ ps.fErase = FALSE;
+ EndPaint(m_hWnd,&ps);
+ }
+
+ ValidateRect(m_hWnd,NULL);
+ }
+
+ if (0 && (db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT) || db_get_dw(NULL,"CLUIFrames","GapBetweenTitleBar",SETTING_GAPTITLEBAR_DEFAULT)))
+ {
+ if (IsWindowVisible(m_hWnd)) {
+ if (g_CluiData.fLayered)
+ SkinInvalidateFrame(m_hWnd,NULL);
+ else {
+ RECT w = {0};
+ RECT w2 = {0};
+ PAINTSTRUCT ps = {0};
+ GetWindowRect(m_hWnd,&w);
+ OffsetRect(&w,-w.left,-w.top);
+ BeginPaint(m_hWnd,&ps);
+ if ((ps.rcPaint.bottom-ps.rcPaint.top)*(ps.rcPaint.right-ps.rcPaint.left) == 0)
+ w2 = w;
+ else
+ w2 = ps.rcPaint;
+ SkinDrawGlyph(ps.hdc,&w,&w2,"Main,ID=Background,Opt=Non-Layered");
+ ps.fErase = FALSE;
+ EndPaint(m_hWnd,&ps);
+ }
+ }
+ }
+ return DefWindowProc(m_hWnd, msg, wParam, lParam);
+}
+
+LRESULT CLUI::OnCreate( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ TranslateMenu(GetMenu(m_hWnd));
+ DrawMenuBar(m_hWnd);
+ CLUIServices_ProtocolStatusChanged(0,0);
+
+ { MENUITEMINFO mii;
+ ZeroMemory(&mii,sizeof(mii));
+ mii.cbSize = MENUITEMINFO_V4_SIZE;
+ mii.fMask = MIIM_TYPE|MIIM_DATA;
+ mii.dwItemData = MENU_MIRANDAMENU;
+ mii.fType = MFT_OWNERDRAW;
+ mii.dwTypeData = NULL;
+ SetMenuItemInfo(GetMenu(m_hWnd),0,TRUE,&mii);
+
+ // mii.fMask = MIIM_TYPE;
+ mii.fType = MFT_OWNERDRAW;
+ mii.dwItemData = MENU_STATUSMENU;
+ SetMenuItemInfo(GetMenu(m_hWnd),1,TRUE,&mii);
+
+ // mii.fMask = MIIM_TYPE;
+ mii.fType = MFT_OWNERDRAW;
+ mii.dwItemData = MENU_MINIMIZE;
+ SetMenuItemInfo(GetMenu(m_hWnd),2,TRUE,&mii);
+ }
+ //PostMessage(m_hWnd, M_CREATECLC, 0, 0);
+ //pcli->hwndContactList = m_hWnd;
+ uMsgGetProfile = RegisterWindowMessage(_T("Miranda::GetProfile")); // don't localise
+ bTransparentFocus = 1;
+ return FALSE;
+}
+
+LRESULT CLUI::OnSetAllExtraIcons( UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ )
+{
+ return FALSE;
+}
+
+LRESULT CLUI::OnCreateClc( UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ )
+{
+ CreateCLC();
+ if ( db_get_b( NULL, "CList", "ShowOnStart", SETTING_SHOWONSTART_DEFAULT ))
+ cliShowHide((WPARAM) m_hWnd, (LPARAM)TRUE );
+ PostMessage( pcli->hwndContactTree, CLM_AUTOREBUILD, 0, 0 );
+ return FALSE;
+}
+
+LRESULT CLUI::OnLButtonDown( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ POINT pt;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ ClientToScreen( m_hWnd, &pt );
+
+ if ( CLUI_SizingOnBorder( pt, 1 ))
+ {
+ mutex_bIgnoreActivation = TRUE;
+ return FALSE;
+ }
+ return DefCluiWndProc( msg, wParam, lParam );
+}
+LRESULT CLUI::OnParentNotify( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ switch ( wParam )
+ {
+ case WM_LBUTTONDOWN:
+ {
+ POINT pt;
+
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ ClientToScreen( m_hWnd, &pt );
+ wParam = 0;
+ lParam = 0;
+
+ if ( CLUI_SizingOnBorder( pt,1 ))
+ {
+ mutex_bIgnoreActivation = TRUE;
+ return 0;
+ }
+ }
+ }
+ return DefWindowProc(m_hWnd, msg, wParam, lParam);;
+}
+
+LRESULT CLUI::OnSetFocus( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ if ( hFrameContactTree && ( !CallService( MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM( FO_FLOATING, hFrameContactTree ), 0 )))
+ {
+ SetFocus(pcli->hwndContactTree);
+ }
+
+ return FALSE;
+}
+
+LRESULT CLUI::OnStatusBarUpdateTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ int status,i;
+ PROTOTICKS *pt = NULL;
+
+ for (i=0;i < 64;i++)
+ {
+
+ pt = &CycleStartTick[i];
+
+ if (pt->szProto != NULL && pt->bTimerCreated == 1)
+ {
+ if (pt->bGlobal)
+ status = g_bMultiConnectionMode?ID_STATUS_CONNECTING:0;
+ else
+ status = CallProtoService(pt->szProto,PS_GETSTATUS,0,0);
+
+ if ( !(status >= ID_STATUS_CONNECTING && status <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES))
+ {
+ pt->nCycleStartTick = 0;
+ ImageList_Destroy(pt->himlIconList);
+ pt->himlIconList = NULL;
+ KillTimer(m_hWnd,TM_STATUSBARUPDATE+pt->nIndex);
+ pt->bTimerCreated = 0;
+ }
+ }
+
+ };
+
+ pt = &CycleStartTick[wParam-TM_STATUSBARUPDATE];
+ {
+ if (IsWindowVisible(pcli->hwndStatus)) pcli->pfnInvalidateRect(pcli->hwndStatus,NULL,0);//InvalidateRectZ(pcli->hwndStatus,NULL,TRUE);
+ //if (DBGetContactSettingByte(NULL,"CList","TrayIcon",SETTING_TRAYICON_DEFAULT) != SETTING_TRAYICON_CYCLE)
+ if (pt->bGlobal)
+ cliTrayIconUpdateBase(g_szConnectingProto);
+ else
+ cliTrayIconUpdateBase(pt->szProto);
+
+ }
+ pcli->pfnInvalidateRect(pcli->hwndStatus,NULL,TRUE);
+ return DefCluiWndProc( msg, wParam, lParam );
+}
+
+LRESULT CLUI::OnAutoAlphaTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ int inwnd;
+
+ if (GetForegroundWindow() == m_hWnd)
+ {
+ KillTimer(m_hWnd,TM_AUTOALPHA);
+ inwnd = 1;
+ }
+ else
+ {
+ POINT pt;
+ HWND hwndPt;
+ pt.x = (short)LOWORD(GetMessagePos());
+ pt.y = (short)HIWORD(GetMessagePos());
+ hwndPt = WindowFromPoint(pt);
+
+ inwnd = FALSE;
+ inwnd = CLUI_CheckOwnedByClui(hwndPt);
+ if ( ! inwnd )
+ inwnd = ( GetCapture() == pcli->hwndContactList );
+
+ }
+ if (inwnd != bTransparentFocus)
+ { //change
+ HWND hwn = GetCapture();
+ hwn = hwn;
+ bTransparentFocus = inwnd;
+ if (bTransparentFocus) CLUI_SmoothAlphaTransition(m_hWnd, (BYTE)db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT), 1);
+ else
+ {
+ CLUI_SmoothAlphaTransition(m_hWnd, (BYTE)(g_bTransparentFlag?db_get_b(NULL,"CList","AutoAlpha",SETTING_AUTOALPHA_DEFAULT):255), 1);
+ }
+ }
+ if ( !bTransparentFocus) KillTimer(m_hWnd,TM_AUTOALPHA);
+ return TRUE;
+}
+LRESULT CLUI::OnSmoothAlphaTransitionTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ CLUI_SmoothAlphaTransition(m_hWnd, 0, 2);
+ return TRUE;
+}
+LRESULT CLUI::OnDelayedSizingTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ if ( mutex_bDelayedSizing && !mutex_bDuringSizing )
+ {
+ mutex_bDelayedSizing = 0;
+ KillTimer( m_hWnd,TM_DELAYEDSIZING );
+ pcli->pfnClcBroadcast( INTM_SCROLLBARCHANGED, 0, 0 );
+ }
+ return TRUE;
+}
+LRESULT CLUI::OnBringOutTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ //hide
+ KillTimer(m_hWnd,TM_BRINGINTIMEOUT);
+ KillTimer(m_hWnd,TM_BRINGOUTTIMEOUT);
+ bShowEventStarted = 0;
+ POINT pt; GetCursorPos(&pt);
+ HWND hAux = WindowFromPoint(pt);
+ BOOL mouse_in_window = CLUI_CheckOwnedByClui(hAux);
+ if ( !mouse_in_window && GetForegroundWindow() != m_hWnd )
+ CLUI_HideBehindEdge();
+ return TRUE;
+}
+LRESULT CLUI::OnBringInTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ //show
+ KillTimer(m_hWnd,TM_BRINGINTIMEOUT);
+ bShowEventStarted = 0;
+ KillTimer(m_hWnd,TM_BRINGOUTTIMEOUT);
+ POINT pt; GetCursorPos(&pt);
+ HWND hAux = WindowFromPoint(pt);
+ BOOL mouse_in_window = FALSE;
+ while(hAux != NULL)
+ {
+ if (hAux == m_hWnd) { mouse_in_window = TRUE; break;}
+ hAux = GetParent(hAux);
+ }
+ if ( mouse_in_window )
+ CLUI_ShowFromBehindEdge();
+ return TRUE;
+}
+LRESULT CLUI::OnUpdateBringTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ CLUI_UpdateTimer( 0 );
+ return TRUE;
+}
+
+LRESULT CLUI::OnTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ if ( MirandaExiting()) return FALSE;
+
+ if ((int)wParam >= TM_STATUSBARUPDATE && (int)wParam <= TM_STATUSBARUPDATE+64 )
+ {
+ if ( !pcli->hwndStatus ) return FALSE;
+ else return OnStatusBarUpdateTimer( msg, wParam, lParam );
+ }
+
+ switch ( wParam )
+ {
+ case TM_AUTOALPHA: return OnAutoAlphaTimer( msg, wParam, lParam );
+ case TM_SMOTHALPHATRANSITION: return OnSmoothAlphaTransitionTimer( msg, wParam, lParam );
+ case TM_DELAYEDSIZING: return OnDelayedSizingTimer( msg, wParam, lParam );
+ case TM_BRINGOUTTIMEOUT: return OnBringOutTimer( msg, wParam, lParam );
+ case TM_BRINGINTIMEOUT: return OnBringInTimer( msg, wParam, lParam );
+ case TM_UPDATEBRINGTIMER: return OnUpdateBringTimer( msg, wParam, lParam );
+ default: return DefCluiWndProc( msg, wParam, lParam );
+ }
+ return TRUE;
+}
+
+
+LRESULT CLUI::OnActivate( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ BOOL IsOption = FALSE;
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ SendMessage(pcli->hwndContactTree, WM_ACTIVATE, wParam, lParam);
+ if (db_get_b(NULL, "ModernData", "HideBehind", SETTING_HIDEBEHIND_DEFAULT))
+ {
+ if (wParam == WA_INACTIVE && ((HWND)lParam != m_hWnd) && GetParent((HWND)lParam) != m_hWnd && !IsOption)
+ {
+ if ( !g_bCalledFromShowHide) CLUI_UpdateTimer(0);
+ }
+ else if ( !g_bCalledFromShowHide )
+ {
+ CLUI_ShowFromBehindEdge();
+ }
+ }
+
+ if ( !IsWindowVisible(m_hWnd) || mutex_bShowHideCalledFromAnimation)
+ {
+ KillTimer(m_hWnd,TM_AUTOALPHA);
+ return 0;
+ }
+ if (wParam == WA_INACTIVE && ((HWND)lParam != m_hWnd) && !CLUI_CheckOwnedByClui((HWND)lParam) && !IsOption)
+ {
+ if (g_bTransparentFlag)
+ if (bTransparentFocus)
+ CLUI_SafeSetTimer(m_hWnd, TM_AUTOALPHA,250,NULL);
+
+ }
+ else {
+ if ( !db_get_b(NULL,"CList","OnTop",SETTING_ONTOP_DEFAULT))
+ Sync(CLUIFrames_ActivateSubContainers,TRUE);
+ if (g_bTransparentFlag) {
+ KillTimer(m_hWnd,TM_AUTOALPHA);
+ CLUI_SmoothAlphaTransition(m_hWnd, db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT), 1);
+ bTransparentFocus = 1;
+ }
+ }
+ RedrawWindow(m_hWnd,NULL,NULL,RDW_INVALIDATE|RDW_ALLCHILDREN);
+ if (g_bTransparentFlag)
+ {
+ BYTE alpha;
+ if (wParam != WA_INACTIVE || CLUI_CheckOwnedByClui((HWND)lParam) || IsOption || ((HWND)lParam == m_hWnd) || GetParent((HWND)lParam) == m_hWnd) alpha = db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT);
+ else
+ alpha = g_bTransparentFlag?db_get_b(NULL,"CList","AutoAlpha",SETTING_AUTOALPHA_DEFAULT):255;
+ CLUI_SmoothAlphaTransition(m_hWnd, alpha, 1);
+ if (IsOption) DefWindowProc(m_hWnd,msg,wParam,lParam);
+ else return 1;
+ }
+ return DefWindowProc(m_hWnd,msg,wParam,lParam);
+}
+
+LRESULT CLUI::OnSetCursor( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ HWND gf = GetForegroundWindow();
+ if (g_CluiData.nBehindEdgeState >= 0) CLUI_UpdateTimer(1);
+ if (g_bTransparentFlag) {
+ if ( !bTransparentFocus && gf != m_hWnd)
+ {
+ CLUI_SmoothAlphaTransition(m_hWnd, db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT), 1);
+ bTransparentFocus = 1;
+ CLUI_SafeSetTimer(m_hWnd, TM_AUTOALPHA,250,NULL);
+ }
+ }
+ int k = CLUI_TestCursorOnBorders();
+ return k ? k : 1;
+}
+
+LRESULT CLUI::OnMouseActivate( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+
+ if ( mutex_bIgnoreActivation )
+ {
+ mutex_bIgnoreActivation = 0;
+ return( MA_NOACTIVATEANDEAT );
+ }
+ int lRes = DefWindowProc(m_hWnd,msg,wParam,lParam);
+ CLUIFrames_RepaintSubContainers();
+ return lRes;
+}
+
+LRESULT CLUI::OnNcLButtonDown( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ POINT pt;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ int k = CLUI_SizingOnBorder(pt,1);
+ return k ? k : DefWindowProc( m_hWnd, msg, wParam, lParam );
+}
+
+LRESULT CLUI::OnNcLButtonDblClk( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ if (wParam == HTMENU || wParam == HTCAPTION)
+ {
+ RECT rc;
+ GetWindowRect(m_hWnd, &rc);
+ POINT pt;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ if ( pt.x > rc.right - 16 && pt.x < rc.right )
+ return CallService(MS_CLIST_SHOWHIDE, 0, 0);
+ }
+ return DefCluiWndProc( msg, wParam, lParam );
+}
+
+LRESULT CLUI::OnNcHitTest( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ LRESULT result;
+ result = DefWindowProc(m_hWnd,WM_NCHITTEST,wParam,lParam);
+
+ if ((g_CluiData.fAutoSize) && ( result == HTSIZE || result == HTTOP ||
+ result == HTTOPLEFT || result == HTTOPRIGHT ||
+ result == HTBOTTOM || result == HTBOTTOMRIGHT ||
+ result == HTBOTTOMLEFT))
+ return HTCLIENT;
+
+ if (result == HTMENU)
+ {
+ int t;
+ POINT pt;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ t = MenuItemFromPoint(m_hWnd,g_hMenuMain,pt);
+
+ if (t == -1 && (db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT)))
+ return HTCAPTION;
+ }
+
+ if (result == HTCLIENT)
+ {
+ POINT pt;
+ int k;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ k = CLUI_SizingOnBorder(pt,0);
+ if ( !k && (db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT)))
+ return HTCAPTION;
+ else return k+9;
+ }
+ return result;
+}
+
+LRESULT CLUI::OnShowWindow( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ BYTE gAlpha;
+
+ if (lParam) return 0;
+ if (mutex_bShowHideCalledFromAnimation) return 1;
+ {
+
+ if ( !wParam) gAlpha = 0;
+ else
+ gAlpha = (db_get_b(NULL,"CList","Transparent",SETTING_TRANSPARENT_DEFAULT)?db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT):255);
+ if (wParam)
+ {
+ g_CluiData.bCurrentAlpha = 0;
+ Sync(CLUIFrames_OnShowHide, pcli->hwndContactList,1);
+ ske_RedrawCompleteWindow();
+ }
+ CLUI_SmoothAlphaTransition(m_hWnd, gAlpha, 1);
+ }
+ return FALSE;
+}
+
+LRESULT CLUI::OnSysCommand( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ switch (wParam)
+ {
+ case SC_MAXIMIZE:
+ return 0;
+
+ case SC_CLOSE:
+ PostMessage(m_hWnd, msg, SC_MINIMIZE, lParam);
+ return 0;
+ }
+
+ DefWindowProc(m_hWnd, msg, wParam, lParam);
+ if (db_get_b(NULL,"CList","OnDesktop",SETTING_ONDESKTOP_DEFAULT))
+ Sync( CLUIFrames_ActivateSubContainers, TRUE );
+ return FALSE;
+}
+
+LRESULT CLUI::OnKeyDown( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ if (wParam == VK_F5)
+ SendMessage(pcli->hwndContactTree,CLM_AUTOREBUILD,0,0);
+ return DefCluiWndProc( msg, wParam, lParam );
+}
+
+LRESULT CLUI::OnGetMinMaxInfo( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ DefWindowProc(m_hWnd,msg,wParam,lParam);
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = max(db_get_w(NULL,"CLUI","MinWidth",SETTING_MINWIDTH_DEFAULT),max(18,db_get_b(NULL,"CLUI","LeftClientMargin",SETTING_LEFTCLIENTMARIGN_DEFAULT)+db_get_b(NULL,"CLUI","RightClientMargin",SETTING_RIGHTCLIENTMARIGN_DEFAULT)+18));
+ if (nRequiredHeight == 0)
+ {
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = CLUIFramesGetMinHeight();
+ }
+ return FALSE;
+}
+
+LRESULT CLUI::OnMoving( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ CallWindowProc( DefWindowProc, m_hWnd, msg, wParam, lParam );
+ if ( FALSE ) //showcontents is turned on
+ {
+ Sync(CLUIFrames_OnMoving,m_hWnd,(RECT*)lParam);
+ }
+ return TRUE;
+}
+
+LRESULT CLUI::OnNewContactNotify( NMCLISTCONTROL * pnmc )
+{
+ ExtraImage_SetAllExtraIcons( pcli->hwndContactTree, pnmc->hItem );
+ return FALSE;
+}
+
+LRESULT CLUI::OnListRebuildNotify( NMCLISTCONTROL * pnmc )
+{
+ ExtraImage_SetAllExtraIcons( pcli->hwndContactTree, 0 );
+ return FALSE;
+}
+LRESULT CLUI::OnListSizeChangeNotify( NMCLISTCONTROL * pnmc )
+{
+
+ // TODO: Check and refactor possible problem of clist resized to full screen problem
+ static RECT rcWindow,rcTree,rcTree2,rcWorkArea,rcOld;
+ int maxHeight, minHeight,newHeight;
+ int winstyle;
+ if (mutex_bDisableAutoUpdate == 1)
+ return FALSE;
+ if (mutex_bDuringSizing)
+ rcWindow = rcSizingRect;
+ else
+ GetWindowRect(m_hWnd,&rcWindow);
+ if ( !g_CluiData.fAutoSize || pcli->hwndContactTree == 0 || CallService(MS_CLIST_DOCKINGISDOCKED,0,0))
+ return FALSE;
+
+ maxHeight = db_get_b(NULL,"CLUI","MaxSizeHeight",SETTING_MAXSIZEHEIGHT_DEFAULT);
+ minHeight = db_get_b(NULL,"CLUI","MinSizeHeight",SETTING_MINSIZEHEIGHT_DEFAULT);
+ rcOld = rcWindow;
+ GetWindowRect(pcli->hwndContactTree,&rcTree);
+
+ FRAMEWND* frm = FindFrameByItsHWND(pcli->hwndContactTree);
+ if (frm)
+ rcTree2 = frm->wndSize;
+ else
+ SetRect(&rcTree2,0,0,0,0);
+
+ winstyle = GetWindowLongPtr(pcli->hwndContactTree,GWL_STYLE);
+
+ SystemParametersInfo(SPI_GETWORKAREA,0,&rcWorkArea,FALSE);
+ if (MyMonitorFromWindow)
+ {
+ HMONITOR hMon = MyMonitorFromWindow(pcli->hwndContactTree, MONITOR_DEFAULTTONEAREST);
+ MONITORINFO mi;
+ mi.cbSize = sizeof(mi);
+ if (MyGetMonitorInfo(hMon, &mi))
+ rcWorkArea = mi.rcWork;
+ }
+
+
+ if (pnmc->pt.y>(rcWorkArea.bottom-rcWorkArea.top))
+ {
+ pnmc->pt.y = (rcWorkArea.bottom-rcWorkArea.top);
+
+ };
+ if ((pnmc->pt.y) == nLastRequiredHeight)
+ {
+ }
+ nLastRequiredHeight = pnmc->pt.y;
+ newHeight = max(CLUIFramesGetMinHeight(),max(pnmc->pt.y,3)+1+((winstyle&WS_BORDER)?2:0)+(rcWindow.bottom-rcWindow.top)-(rcTree.bottom-rcTree.top));
+ if (newHeight < (rcWorkArea.bottom-rcWorkArea.top)*minHeight/100)
+ newHeight = (rcWorkArea.bottom-rcWorkArea.top)*minHeight/100;
+
+ if (newHeight>(rcWorkArea.bottom-rcWorkArea.top)*maxHeight/100)
+ newHeight = (rcWorkArea.bottom-rcWorkArea.top)*maxHeight/100;
+
+ if (newHeight == (rcWindow.bottom-rcWindow.top)) return 0;
+
+ if (db_get_b(NULL,"CLUI","AutoSizeUpward",SETTING_AUTOSIZEUPWARD_DEFAULT)) {
+ rcWindow.top = rcWindow.bottom-newHeight;
+ if (rcWindow.top < rcWorkArea.top) rcWindow.top = rcWorkArea.top;
+ }
+ else {
+ rcWindow.bottom = rcWindow.top+newHeight;
+ if (rcWindow.bottom>rcWorkArea.bottom) rcWindow.bottom = rcWorkArea.bottom;
+ }
+ if (nRequiredHeight == 1)
+ return FALSE;
+ nRequiredHeight = 1;
+ if (mutex_bDuringSizing)
+ {
+ bNeedFixSizingRect = 1;
+ rcSizingRect.top = rcWindow.top;
+ rcSizingRect.bottom = rcWindow.bottom;
+ rcCorrectSizeRect = rcSizingRect;
+ }
+ else
+ {
+ bNeedFixSizingRect = 0;
+ }
+ if ( !mutex_bDuringSizing)
+ SetWindowPos(m_hWnd,0,rcWindow.left,rcWindow.top,rcWindow.right-rcWindow.left,rcWindow.bottom-rcWindow.top,SWP_NOZORDER|SWP_NOACTIVATE);
+ else
+ {
+ SetWindowPos(m_hWnd,0,rcWindow.left,rcWindow.top,rcWindow.right-rcWindow.left,rcWindow.bottom-rcWindow.top,SWP_NOZORDER|SWP_NOACTIVATE);
+ }
+ nRequiredHeight = 0;
+
+ return FALSE;
+}
+
+LRESULT CLUI::OnClickNotify( NMCLISTCONTROL * pnmc )
+{
+ DWORD hitFlags;
+ HANDLE hItem = (HANDLE)SendMessage(pcli->hwndContactTree,CLM_HITTEST,(WPARAM)&hitFlags,MAKELPARAM(pnmc->pt.x,pnmc->pt.y));
+
+ if (hitFlags&CLCHT_ONITEMEXTRA)
+ {
+ if ( !IsHContactGroup(hItem) && !IsHContactInfo(hItem))
+ {
+ pdisplayNameCacheEntry pdnce = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(pnmc->hItem);
+ if (pdnce == NULL) return 0;
+
+ int extra = ExtraImage_ColumnNumToExtraID(pnmc->iColumn);
+ NotifyEventHooks(g_CluiData.hEventExtraClick, (WPARAM)pnmc->hItem, extra);
+
+ if ( !ServiceExists("ExtraIcon/Register"))
+ {
+ int v,e,w;
+ v = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_PROTO);
+ e = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_EMAIL);
+ w = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_WEB);
+
+ if (pnmc->iColumn == v) {
+ CallService(MS_USERINFO_SHOWDIALOG,(WPARAM)pnmc->hItem,0);
+ };
+ if (pnmc->iColumn == e)
+ {
+ char *email = db_get_sa(pnmc->hItem,"UserInfo", "Mye-mail0");
+ if ( !email)
+ email = db_get_sa(pnmc->hItem, pdnce->m_cache_cszProto, "e-mail");
+ if (email) {
+ char buf[4096];
+ sprintf(buf,"mailto:%s",email);
+ mir_free(email);
+ ShellExecuteA(m_hWnd,"open",buf,NULL,NULL,SW_SHOW);
+ }
+ };
+ if (pnmc->iColumn == w) {
+ char *homepage = db_get_sa(pdnce->hContact,"UserInfo", "Homepage");
+ if ( !homepage)
+ homepage = db_get_sa(pdnce->hContact,pdnce->m_cache_cszProto, "Homepage");
+ if (homepage != NULL)
+ {
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM)homepage);
+ mir_free(homepage);
+ }
+ }
+ }
+ }
+ };
+ if (hItem && !(hitFlags&CLCHT_NOWHERE))
+ return DefCluiWndProc( WM_NOTIFY, 0, (LPARAM)pnmc );
+ if ((hitFlags&(CLCHT_NOWHERE|CLCHT_INLEFTMARGIN|CLCHT_BELOWITEMS)) == 0)
+ return DefCluiWndProc( WM_NOTIFY, 0, (LPARAM)pnmc );
+ if (db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT)) {
+ POINT pt;
+ int res;
+ pt = pnmc->pt;
+ ClientToScreen(pcli->hwndContactTree,&pt);
+ res = PostMessage(m_hWnd, WM_SYSCOMMAND, SC_MOVE|HTCAPTION,MAKELPARAM(pt.x,pt.y));
+ return res;
+ }
+ /*== == == == == == == == == = */
+ if (db_get_b(NULL,"CLUI","DragToScroll",SETTING_DRAGTOSCROLL_DEFAULT) && !db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT))
+ return ClcEnterDragToScroll(pcli->hwndContactTree,pnmc->pt.y);
+ /*== == == == == == == == == = */
+ return 0;
+}
+
+LRESULT CLUI::OnNotify( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ LPNMHDR pnmhdr = (LPNMHDR)lParam;
+ if ( pnmhdr->hwndFrom != pcli->hwndContactTree )
+ return DefCluiWndProc( msg, wParam, lParam );
+
+ switch ( pnmhdr->code)
+ {
+ case CLN_NEWCONTACT: return OnNewContactNotify((NMCLISTCONTROL *)pnmhdr );
+ case CLN_LISTREBUILT: return OnListRebuildNotify((NMCLISTCONTROL *)pnmhdr );
+ case CLN_LISTSIZECHANGE: return OnListSizeChangeNotify((NMCLISTCONTROL *)pnmhdr );
+ case NM_CLICK: return OnClickNotify((NMCLISTCONTROL *)pnmhdr );
+
+ }
+ return DefCluiWndProc( msg, wParam, lParam );
+}
+
+LRESULT CLUI::OnContextMenu( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ RECT rc;
+ POINT pt;
+
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ // x/y might be -1 if it was generated by a kb click
+ GetWindowRect(pcli->hwndContactTree,&rc);
+ if ( pt.x == -1 && pt.y == -1) {
+ // all this is done in screen-coords!
+ GetCursorPos(&pt);
+ // the mouse isnt near the window, so put it in the middle of the window
+ if ( !PtInRect(&rc,pt)) {
+ pt.x = rc.left + (rc.right - rc.left) / 2;
+ pt.y = rc.top + (rc.bottom - rc.top) / 2;
+ }
+ }
+ if (PtInRect( &rc ,pt ))
+ {
+ HMENU hMenu;
+ hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDGROUP,0,0);
+ TrackPopupMenu(hMenu,TPM_TOPALIGN|TPM_LEFTALIGN|TPM_LEFTBUTTON,pt.x,pt.y,0,m_hWnd,NULL);
+ DestroyTrayMenu(hMenu);
+ }
+ return FALSE;
+
+}
+LRESULT CLUI::OnMeasureItem( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ LPMEASUREITEMSTRUCT pmis = (LPMEASUREITEMSTRUCT)lParam;
+ switch ( pmis->itemData )
+ {
+ case MENU_MIRANDAMENU:
+ {
+ pmis->itemWidth = GetSystemMetrics( SM_CXSMICON ) * 4 / 3;
+ pmis->itemHeight = 0;
+ }
+ return TRUE;
+ case MENU_STATUSMENU:
+ {
+ HDC hdc;
+ SIZE textSize;
+ hdc = GetDC( m_hWnd );
+ GetTextExtentPoint32A( hdc, Translate("Status"), lstrlenA( Translate( "Status" )), &textSize );
+ pmis->itemWidth = textSize.cx;
+ pmis->itemHeight = 0;
+ ReleaseDC( m_hWnd, hdc );
+ }
+ return TRUE;
+ }
+ return CallService( MS_CLIST_MENUMEASUREITEM, wParam, lParam );
+}
+
+LRESULT CLUI::OnDrawItem( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ struct ClcData * dat = (struct ClcData*)GetWindowLongPtr(pcli->hwndContactTree,0);
+ LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
+ if ( !dat) return 0;
+
+ if (dis->CtlType == ODT_MENU) {
+ if (dis->itemData == MENU_MIRANDAMENU) {
+ if ( !g_CluiData.fLayered)
+ {
+ char buf[255];
+ short offset = 1 + ( dis->itemState&ODS_SELECTED ? 1 : 0 )
+ - ( dis->itemState&ODS_HOTLIGHT ? 1 : 0 );
+
+ HICON hIcon = LoadSkinnedIcon(SKINICON_OTHER_MAINMENU);
+
+ CLUI_DrawMenuBackGround(m_hWnd, dis->hDC, 1, dis->itemState);
+ mir_snprintf(buf,SIZEOF(buf),"Main,ID=MainMenu,Selected=%s,Hot=%s",(dis->itemState&ODS_SELECTED)?"True":"False",(dis->itemState&ODS_HOTLIGHT)?"True":"False");
+ SkinDrawGlyph(dis->hDC,&dis->rcItem,&dis->rcItem,buf);
+
+ int x = (dis->rcItem.right + dis->rcItem.left - GetSystemMetrics(SM_CXSMICON)) / 2 + offset;
+ int y = (dis->rcItem.bottom + dis->rcItem.top - GetSystemMetrics(SM_CYSMICON)) / 2 + offset;
+
+ DrawState( dis->hDC, NULL, NULL, (LPARAM)hIcon, 0, x, y , 0 , 0 ,
+ DST_ICON | ( dis->itemState & ODS_INACTIVE && (((FALSE))) ? DSS_DISABLED : DSS_NORMAL ));
+
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ nMirMenuState = dis->itemState;
+ } else {
+ nMirMenuState = dis->itemState;
+ pcli->pfnInvalidateRect(m_hWnd,NULL,0);
+ }
+ return TRUE;
+ }
+ else if (dis->itemData == MENU_STATUSMENU) {
+ if ( !g_CluiData.fLayered)
+ {
+ char buf[255] = {0};
+ RECT rc = dis->rcItem;
+ short dx = 1+(dis->itemState&ODS_SELECTED?1:0)-(dis->itemState&ODS_HOTLIGHT?1:0);
+ if (dx>1){
+ rc.left += dx;
+ rc.top += dx;
+ }else if (dx == 0){
+ rc.right -= 1;
+ rc.bottom -= 1;
+ }
+ CLUI_DrawMenuBackGround(m_hWnd, dis->hDC, 2, dis->itemState);
+ SetBkMode(dis->hDC,TRANSPARENT);
+ mir_snprintf(buf,SIZEOF(buf),"Main,ID=StatusMenu,Selected=%s,Hot=%s",(dis->itemState&ODS_SELECTED)?"True":"False",(dis->itemState&ODS_HOTLIGHT)?"True":"False");
+ SkinDrawGlyph(dis->hDC,&dis->rcItem,&dis->rcItem,buf);
+ SetTextColor(dis->hDC, (dis->itemState&ODS_SELECTED/*|dis->itemState&ODS_HOTLIGHT*/)?dat->MenuTextHiColor:dat->MenuTextColor);
+ DrawText(dis->hDC,TranslateT("Status"), lstrlen(TranslateT("Status")),&rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
+ nStatusMenuState = dis->itemState;
+ } else {
+ nStatusMenuState = dis->itemState;
+ pcli->pfnInvalidateRect(m_hWnd,NULL,0);
+ }
+ return TRUE;
+ } else if (dis->itemData == MENU_MINIMIZE && !g_CluiData.fLayered)
+ {
+ //TODO check if caption is visible
+ char buf[255] = {0};
+ short dx = 1+(dis->itemState&ODS_SELECTED?1:0)-(dis->itemState&ODS_HOTLIGHT?1:0);
+ HICON hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ CLUI_DrawMenuBackGround(m_hWnd, dis->hDC, 3, dis->itemState);
+ mir_snprintf(buf,SIZEOF(buf),"Main,ID=MainMenu,Selected=%s,Hot=%s",(dis->itemState&ODS_SELECTED)?"True":"False",(dis->itemState&ODS_HOTLIGHT)?"True":"False");
+ SkinDrawGlyph(dis->hDC,&dis->rcItem,&dis->rcItem,buf);
+ DrawState(dis->hDC,NULL,NULL,(LPARAM)hIcon,0,(dis->rcItem.right+dis->rcItem.left-GetSystemMetrics(SM_CXSMICON))/2+dx,(dis->rcItem.bottom+dis->rcItem.top-GetSystemMetrics(SM_CYSMICON))/2+dx,0,0,DST_ICON|(dis->itemState&ODS_INACTIVE && FALSE?DSS_DISABLED:DSS_NORMAL));
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ nMirMenuState = dis->itemState;
+ }
+
+ return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam);
+ }
+ return 0;
+}
+
+LRESULT CLUI::OnDestroy( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ int state = db_get_b(NULL,"CList","State",SETTING_STATE_NORMAL);
+ BOOL wait = FALSE;
+
+ AniAva_UnloadModule();
+ TRACE("CLUI.c: WM_DESTROY\n");
+ g_CluiData.bSTATE = STATE_EXITING;
+ CLUI_DisconnectAll();
+ //fire the "Away Message" Event to wake the thread so it can die.
+ //fire the "Get Text Async" Event to wake the thread so it can die.
+ if (amWakeThread())
+ wait = TRUE;
+
+ if (gtaWakeThread())
+ wait = TRUE;
+
+ if (wait)
+ {
+ //need to give them a little time to exit.
+ Sleep(50);
+ }
+
+ TRACE("CLUI.c: WM_DESTROY - WaitThreadsCompletion \n");
+ while (CLUI_WaitThreadsCompletion(m_hWnd)); //stop all my threads
+ TRACE("CLUI.c: WM_DESTROY - WaitThreadsCompletion DONE\n");
+
+ for (int i=0; i < 64; i++)
+ if (CycleStartTick[i].szProto)
+ mir_free_and_nil(CycleStartTick[i].szProto);
+
+ if (state == SETTING_STATE_NORMAL)
+ CLUI_ShowWindowMod(m_hWnd,SW_HIDE);
+ UnLoadContactListModule();
+ ClcUnloadModule();
+
+ RemoveMenu(g_hMenuMain, 0, MF_BYPOSITION);
+ RemoveMenu(g_hMenuMain, 0, MF_BYPOSITION);
+ DestroyMenu(g_hMenuMain);
+
+ pcli->pfnTrayIconDestroy(m_hWnd);
+ mutex_bAnimationInProgress = 0;
+ CallService(MS_CLIST_FRAMES_REMOVEFRAME,(WPARAM)hFrameContactTree,(LPARAM)0);
+ TRACE("CLUI.c: WM_DESTROY - hFrameContactTree removed\n");
+ pcli->hwndContactTree = NULL;
+ pcli->hwndStatus = NULL;
+ {
+ if (g_CluiData.fAutoSize && !g_CluiData.fDocked)
+ {
+ RECT r;
+ GetWindowRect(pcli->hwndContactList,&r);
+ if (db_get_b(NULL,"CLUI","AutoSizeUpward",SETTING_AUTOSIZEUPWARD_DEFAULT))
+ r.top = r.bottom-CLUIFrames_GetTotalHeight();
+ else
+ r.bottom = r.top+CLUIFrames_GetTotalHeight();
+ db_set_dw(NULL,"CList","y",r.top);
+ db_set_dw(NULL,"CList","Height",r.bottom-r.top);
+ }
+ }
+ UnLoadCLUIFramesModule();
+ //ExtFrames_Uninit();
+ TRACE("CLUI.c: WM_DESTROY - UnLoadCLUIFramesModule DONE\n");
+ db_set_b(NULL,"CList","State",(BYTE)state);
+ ske_UnloadSkin(&g_SkinObjectList);
+
+ delete m_pCLUI;
+
+ pcli->hwndContactList = NULL;
+ pcli->hwndStatus = NULL;
+ PostQuitMessage(0);
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_cluiframes.cpp b/plugins/Clist_modern/src/modern_cluiframes.cpp
new file mode 100644
index 0000000000..4e6940e5e2
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_cluiframes.cpp
@@ -0,0 +1,4222 @@
+/*
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_api/m_skin_eng.h"
+#include "hdr/modern_cluiframes.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_sync.h"
+
+
+// ALL THIS MODULE FUNCTION SHOULD BE EXECUTED FROM MAIN THREAD
+
+#include "hdr/modern_static_cluiframes_service.h" // contain services initialization and proxiation
+
+
+static const int UNCOLLAPSED_FRAME_SIZE = 0;
+static const int DEFAULT_TITLEBAR_HEIGHT = 18;
+
+//GLOBALS
+FRAMEWND * g_pfwFrames = NULL;
+int g_nFramesCount = 0;
+int g_nTitleBarHeight = DEFAULT_TITLEBAR_HEIGHT;
+
+// STATIC
+
+enum {
+ frame_menu_lock = 1,
+ frame_menu_visible,
+ frame_menu_showtitlebar,
+ frame_menu_floating
+}; //legacy menu support
+
+enum { eUnknownId = -1 };
+
+static int _us_DoSetFrameFloat( WPARAM wParam,LPARAM lParam );
+static int CLUIFrameResizeFloatingFrame( int framepos );
+static HWND CreateSubContainerWindow( HWND parent,int x,int y,int width,int height );
+static BOOL CLUIFramesFitInSize();
+static int RemoveItemFromList(int pos, FRAMEWND **lpFrames, int *FrameItemCount );
+static int _us_DoSetFramePaintProc(WPARAM wParam, LPARAM lParam);
+
+
+
+static CRITICAL_SECTION _cluiFramesModuleCS = {0};
+static BOOL _cluiFramesModuleCSInitialized = FALSE;
+static BOOL _fCluiFramesModuleNotStarted = TRUE;
+static XPTHANDLE _hFrameTitleTheme = NULL;
+static int _nClientFrameId = eUnknownId; //for fast access to frame with alclient properties
+static int _iNextFrameId = 100;
+static HFONT _hTitleBarFont = NULL;
+
+// menus
+static HGENMENU _hmiVisible = (HGENMENU)-1;
+static HGENMENU _hmiTBVisible = (HGENMENU)-1;
+static HGENMENU _hmiLock = (HGENMENU)-1;
+static HGENMENU _hmiColl = (HGENMENU)-1;
+static HGENMENU _hmiFloating = (HGENMENU)-1;
+static HGENMENU _hmiAlignRoot = (HGENMENU)-1;
+static HGENMENU _hmiAlignTop = (HGENMENU)-1;
+static HGENMENU _hmiAlignClient = (HGENMENU)-1;
+static HGENMENU _hmiAlignBottom = (HGENMENU)-1;
+static HGENMENU _hmiPosRoot = (HGENMENU)-1;
+static HGENMENU _hmiPosUp = (HGENMENU)-1;
+static HGENMENU _hmiPosDown = (HGENMENU)-1;
+static HGENMENU _hmiBorder = (HGENMENU)-1;
+static HGENMENU _hmiRoot = (HGENMENU)-1;
+
+// others
+static int _nContactListHeight = 0;
+static DWORD _dwLastStoreTick = 0;
+
+HWND hWndExplorerToolBar;
+static int GapBetweenFrames = 1;
+
+BOOLEAN bMoveTogether;
+int recurs_prevent = 0;
+static BOOL PreventSizeCalling = FALSE;
+
+static HBITMAP hBmpBackground;
+static int backgroundBmpUse;
+static COLORREF bkColour;
+static COLORREF SelBkColour;
+static BOOL bkUseWinColours;
+BYTE AlignCOLLIconToLeft; //will hide frame icon
+COLORREF sttGetColor(char * module, char * color, COLORREF defColor);
+//for old multiwindow
+#define MPCF_CONTEXTFRAMEMENU 3
+POINT ptOld;
+short nLeft = 0;
+short nTop = 0;
+
+static int sortfunc(const void *a,const void *b)
+{
+ SortData *sd1,*sd2;
+ sd1 = (SortData *)a;
+ sd2 = (SortData *)b;
+ if (sd1->order > sd2->order){return(1);};
+ if (sd1->order < sd2->order){return(-1);};
+ return (0);
+};
+int CLUIFrames_OnMoving( HWND hwnd, RECT * r)
+{
+ int i;
+ g_CluiData.mutexPreventDockMoving = 0;
+ for (i=0;i < g_nFramesCount;i++) {
+
+ if ( !g_pfwFrames[i].floating && g_pfwFrames[i].OwnerWindow != NULL && g_pfwFrames[i].OwnerWindow != (HWND)-2)
+ {
+ int x;
+ int y;
+ int dx,dy;
+ FRAMEWND * Frame;
+ POINT pt = {0};
+ RECT wr;
+ Frame = &(g_pfwFrames[i]);
+
+ GetWindowRect(hwnd,&wr);
+ ClientToScreen(hwnd,&pt);
+ dx = (r->left-wr.left)+pt.x;
+ dy = (r->top-wr.top)+pt.y;
+ x = Frame->wndSize.left;
+ y = Frame->wndSize.top;
+ SetWindowPos(Frame->OwnerWindow,NULL,x+dx,y+dy,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSENDCHANGING|SWP_ASYNCWINDOWPOS|SWP_DEFERERASE|SWP_NOOWNERZORDER);
+ };
+
+ }
+ g_CluiData.mutexPreventDockMoving = 1;
+ AniAva_RedrawAllAvatars(FALSE);
+ return 0;
+}
+int SetAlpha(BYTE Alpha)
+{
+ int i;
+
+ for (i=0;i < g_nFramesCount;i++) {
+
+ if ( !g_pfwFrames[i].floating && g_pfwFrames[i].OwnerWindow != NULL && g_pfwFrames[i].OwnerWindow != (HWND)-2 && g_pfwFrames[i].visible && !g_pfwFrames[i].needhide )
+ {
+ HWND hwnd = g_pfwFrames[i].OwnerWindow;
+ if (g_proc_SetLayeredWindowAttributesNew)
+ {
+ long l;
+ l = GetWindowLongPtr(hwnd,GWL_EXSTYLE);
+ if ( !(l&WS_EX_LAYERED))
+ {
+ HWND parent = NULL;
+ if (g_CluiData.fOnDesktop)
+ {
+ HWND hProgMan = FindWindow(_T("Progman"),NULL);
+ if (IsWindow(hProgMan))
+ parent = hProgMan;
+ }
+
+ CLUI_ShowWindowMod(hwnd,SW_HIDE);
+ SetParent(hwnd,NULL);
+ SetWindowLongPtr(hwnd,GWL_EXSTYLE,l|WS_EX_LAYERED);
+ SetParent(hwnd,parent);
+ if (l&WS_VISIBLE) CLUI_ShowWindowMod(hwnd,SW_SHOW);
+ }
+ g_proc_SetLayeredWindowAttributesNew(hwnd, g_CluiData.dwKeyColor,Alpha, LWA_ALPHA|LWA_COLORKEY);
+ }
+ }
+ }
+ AniAva_RedrawAllAvatars(FALSE);
+ return 0;
+}
+
+
+int CLUIFrames_RepaintSubContainers()
+{
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ if ( !g_pfwFrames[i].floating && g_pfwFrames[i].OwnerWindow != (HWND)0 && g_pfwFrames[i].OwnerWindow != (HWND)-2 && g_pfwFrames[i].visible && !g_pfwFrames[i].needhide )
+ {
+ RedrawWindow(g_pfwFrames[i].hWnd,NULL,NULL,RDW_ALLCHILDREN|RDW_UPDATENOW|RDW_INVALIDATE|RDW_FRAME);
+ };
+ return 0;
+}
+
+int CLUIFrames_ActivateSubContainers( BOOL active)
+{
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ if (active && !g_pfwFrames[i].floating && g_pfwFrames[i].OwnerWindow != (HWND)0 && g_pfwFrames[i].OwnerWindow != (HWND)-2 && g_pfwFrames[i].visible && !g_pfwFrames[i].needhide )
+ {
+ HWND hwnd = g_pfwFrames[i].OwnerWindow;
+ hwnd = g_pfwFrames[i].hWnd;//OwnerWindow;
+ if (db_get_b(NULL,"CList","OnDesktop",SETTING_ONDESKTOP_DEFAULT))
+ {
+ SetWindowPos(g_pfwFrames[i].OwnerWindow,HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+ SetWindowPos(g_pfwFrames[i].OwnerWindow,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+ }
+ else SetWindowPos(g_pfwFrames[i].OwnerWindow, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOSIZE | SWP_NOMOVE);
+ };
+ return 0;
+}
+int CLUIFrames_SetParentForContainers( HWND parent )
+{
+ int i;
+ if (parent && parent != pcli->hwndContactList)
+ g_CluiData.fOnDesktop = 1;
+ else
+ g_CluiData.fOnDesktop = 0;
+ for (i=0;i < g_nFramesCount;i++) {
+ if ( !g_pfwFrames[i].floating && g_pfwFrames[i].OwnerWindow != (HWND)0 && g_pfwFrames[i].OwnerWindow != (HWND)-2 && g_pfwFrames[i].visible && !g_pfwFrames[i].needhide )
+ {
+ HWND hwnd = g_pfwFrames[i].OwnerWindow;
+ SetParent(hwnd,parent);
+ }
+ }
+ return 0;
+}
+
+int CLUIFrames_OnShowHide( HWND hwnd, int mode )
+{
+ int i;
+ int prevFrameCount;
+ for (i=0;i < g_nFramesCount;i++) {
+ if ( !g_pfwFrames[i].floating && g_pfwFrames[i].OwnerWindow != (HWND)0 && g_pfwFrames[i].OwnerWindow != (HWND)-2)
+ {
+ {
+ //Try to avoid crash on exit due to unlock.
+ HWND owner = g_pfwFrames[i].OwnerWindow;
+ HWND Frmhwnd = g_pfwFrames[i].hWnd;
+ BOOL visible = g_pfwFrames[i].visible;
+ BOOL needhide = g_pfwFrames[i].needhide;
+ needhide |= (!g_pfwFrames[i].collapsed || g_pfwFrames[i].height == 0 );
+ prevFrameCount = g_nFramesCount;
+ ShowWindow(owner,(mode == SW_HIDE || !visible || needhide)?SW_HIDE:mode);
+ ShowWindow(Frmhwnd,(mode == SW_HIDE || !visible || needhide)?SW_HIDE:mode);
+ }
+
+ if (mode != SW_HIDE)
+ {
+ SetWindowPos(g_pfwFrames[i].OwnerWindow,HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+ if (db_get_b(NULL,"CList","OnDesktop",SETTING_ONDESKTOP_DEFAULT))
+ {
+ SetWindowPos(g_pfwFrames[i].OwnerWindow,HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+ SetWindowPos(g_pfwFrames[i].OwnerWindow,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+ }
+ else SetWindowPos(g_pfwFrames[i].OwnerWindow, HWND_NOTOPMOST, 0, 0, 0, 0,SWP_NOACTIVATE|SWP_NOSIZE | SWP_NOMOVE);
+ }
+ }
+ }
+ if (mode != SW_HIDE) SetForegroundWindow(pcli->hwndContactList);
+ AniAva_RedrawAllAvatars(TRUE);
+ return 0;
+}
+static int RemoveItemFromList(int pos,FRAMEWND **lpFrames,int *FrameItemCount)
+{
+ memmove(&((*lpFrames)[pos]),&((*lpFrames)[pos+1]),sizeof(FRAMEWND)*(*FrameItemCount-pos-1));
+ (*FrameItemCount)--;
+ (*lpFrames) = (FRAMEWND*)realloc((*lpFrames),sizeof(FRAMEWND)*(*FrameItemCount));
+ return 0;
+}
+
+static int id2pos(int id)
+{
+ int i;
+ if (_fCluiFramesModuleNotStarted) return -1;
+ for (i=0;i < g_nFramesCount;i++)
+ if (g_pfwFrames[i].id == id) return(i);
+ return(-1);
+};
+
+static int btoint(BOOLEAN b)
+{
+ if (b) return 1;
+ return 0;
+}
+
+
+static FRAMEWND* FindFrameByWnd( HWND hwnd )
+{
+ int i;
+
+ if ( hwnd == NULL ) return( NULL );
+
+ for (i=0;i < g_nFramesCount;i++)
+ if ((g_pfwFrames[i].floating) && (g_pfwFrames[i].ContainerWnd == hwnd))
+ return(&g_pfwFrames[i]);
+
+ return( NULL);
+}
+
+
+int QueueAllFramesUpdating(BYTE queue)
+{
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if ( !g_CluiData.fLayered)
+ {
+ if (queue)
+ InvalidateRect(g_pfwFrames[i].hWnd,NULL,FALSE);
+ else
+ ValidateRect(g_pfwFrames[i].hWnd,NULL);
+ }
+ if (g_pfwFrames[i].PaintCallbackProc)
+ {
+ g_pfwFrames[i].bQueued = queue;
+ if (g_pfwFrames[i].UpdateRgn)
+ {
+ DeleteObject(g_pfwFrames[i].UpdateRgn);
+ }
+ g_pfwFrames[i].UpdateRgn = 0;
+ }
+
+ }
+ return queue;
+
+}
+int FindFrameID(HWND FrameHwnd)
+{
+ FRAMEWND * frm = NULL;
+ if (FrameHwnd == NULL ) return 0;
+ frm = FindFrameByItsHWND(FrameHwnd);
+ if (frm)
+ return frm->id;
+ else return 0;
+}
+FRAMEWND * FindFrameByItsHWND(HWND FrameHwnd)
+{
+ int i;
+ if ( FrameHwnd == NULL ) return( NULL );
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if (g_pfwFrames[i].hWnd == FrameHwnd){return(&g_pfwFrames[i]);};
+ };
+ return NULL;
+}
+
+static void DockThumbs( FRAMEWND *pThumbLeft, FRAMEWND *pThumbRight, BOOL bMoveLeft )
+{
+ if (( pThumbRight->dockOpt.hwndLeft == NULL ) && ( pThumbLeft->dockOpt.hwndRight == NULL ))
+ {
+ pThumbRight->dockOpt.hwndLeft = pThumbLeft->ContainerWnd;
+ pThumbLeft->dockOpt.hwndRight = pThumbRight->ContainerWnd;
+ }
+}
+
+
+static void UndockThumbs( FRAMEWND *pThumb1, FRAMEWND *pThumb2 )
+{
+ if (( pThumb1 == NULL ) || ( pThumb2 == NULL ))
+ {
+ return;
+ }
+
+ if ( pThumb1->dockOpt.hwndRight == pThumb2->ContainerWnd )
+ {
+ pThumb1->dockOpt.hwndRight = NULL;
+ }
+
+ if ( pThumb1->dockOpt.hwndLeft == pThumb2->ContainerWnd )
+ {
+ pThumb1->dockOpt.hwndLeft = NULL;
+ }
+
+ if ( pThumb2->dockOpt.hwndRight == pThumb1->ContainerWnd )
+ {
+ pThumb2->dockOpt.hwndRight = NULL;
+ }
+
+ if ( pThumb2->dockOpt.hwndLeft == pThumb1->ContainerWnd )
+ {
+ pThumb2->dockOpt.hwndLeft = NULL;
+ }
+}
+static void PositionThumb( FRAMEWND *pThumb, short nX, short nY )
+{
+ FRAMEWND *pCurThumb = &g_pfwFrames[0];
+ FRAMEWND *pDockThumb = pThumb;
+ FRAMEWND fakeMainWindow;
+ FRAMEWND fakeTaskBarWindow;
+ RECT rc;
+ RECT rcThumb;
+ RECT rcOld;
+ SIZE sizeScreen;
+ int nNewX;
+ int nNewY;
+ int nOffs = 10;
+ int nWidth;
+ int nHeight;
+ POINT pt;
+ RECT rcLeft;
+ RECT rcTop;
+ RECT rcRight;
+ RECT rcBottom;
+ BOOL bDocked;
+ BOOL bDockedLeft;
+ BOOL bDockedRight;
+ BOOL bLeading;
+ int frmidx = 0;
+
+ if ( pThumb == NULL ) return;
+
+ sizeScreen.cx = GetSystemMetrics( SM_CXSCREEN );
+ sizeScreen.cy = GetSystemMetrics( SM_CYSCREEN );
+
+ // Get thumb dimnsions
+ GetWindowRect( pThumb->ContainerWnd, &rcThumb );
+ nWidth = rcThumb.right - rcThumb.left;
+ nHeight = rcThumb.bottom - rcThumb.top;
+
+ // Docking to the edges of the screen
+ nNewX = nX < nOffs ? 0 : nX;
+ nNewX = nNewX > ( sizeScreen.cx - nWidth - nOffs ) ? ( sizeScreen.cx - nWidth ) : nNewX;
+ nNewY = nY < nOffs ? 0 : nY;
+ nNewY = nNewY > ( sizeScreen.cy - nHeight - nOffs ) ? ( sizeScreen.cy - nHeight ) : nNewY;
+
+ bLeading = pThumb->dockOpt.hwndRight != NULL;
+
+ if ( bMoveTogether )
+ {
+ UndockThumbs( pThumb, FindFrameByWnd( pThumb->dockOpt.hwndLeft ));
+ GetWindowRect( pThumb->ContainerWnd, &rcOld );
+ }
+
+ memset(&fakeMainWindow,0,sizeof(fakeMainWindow));
+ fakeMainWindow.ContainerWnd = pcli->hwndContactList;
+ fakeMainWindow.floating = TRUE;
+
+ memset(&fakeTaskBarWindow,0,sizeof(fakeTaskBarWindow));
+ fakeTaskBarWindow.ContainerWnd = hWndExplorerToolBar;
+ fakeTaskBarWindow.floating = TRUE;
+
+
+ while( pCurThumb != NULL )
+ {
+ if (pCurThumb->floating) {
+
+ if ( pCurThumb != pThumb )
+ {
+ GetWindowRect( pThumb->ContainerWnd, &rcThumb );
+ OffsetRect( &rcThumb, nX - rcThumb.left, nY - rcThumb.top );
+
+ GetWindowRect( pCurThumb->ContainerWnd, &rc );
+
+ // These are rects we will dock into
+
+ rcLeft.left = rc.left - nOffs;
+ rcLeft.top = rc.top - nOffs;
+ rcLeft.right = rc.left + nOffs;
+ rcLeft.bottom = rc.bottom + nOffs;
+
+ rcTop.left = rc.left - nOffs;
+ rcTop.top = rc.top - nOffs;
+ rcTop.right = rc.right + nOffs;
+ rcTop.bottom = rc.top + nOffs;
+
+ rcRight.left = rc.right - nOffs;
+ rcRight.top = rc.top - nOffs;
+ rcRight.right = rc.right + nOffs;
+ rcRight.bottom = rc.bottom + nOffs;
+
+ rcBottom.left = rc.left - nOffs;
+ rcBottom.top = rc.bottom - nOffs;
+ rcBottom.right = rc.right + nOffs;
+ rcBottom.bottom = rc.bottom + nOffs;
+
+
+ bDockedLeft = FALSE;
+ bDockedRight = FALSE;
+
+ // Upper-left
+ pt.x = rcThumb.left;
+ pt.y = rcThumb.top;
+ bDocked = FALSE;
+
+ if ( PtInRect( &rcRight, pt ))
+ {
+ nNewX = rc.right;
+ bDocked = TRUE;
+ }
+
+ if ( PtInRect( &rcBottom, pt ))
+ {
+ nNewY = rc.bottom;
+
+ if ( PtInRect( &rcLeft, pt ))
+ {
+ nNewX = rc.left;
+ }
+ }
+
+ if ( PtInRect( &rcTop, pt ))
+ {
+ nNewY = rc.top;
+ bDockedLeft = bDocked;
+ }
+
+ // Upper-right
+ pt.x = rcThumb.right;
+ pt.y = rcThumb.top;
+ bDocked = FALSE;
+
+ if ( !bLeading && PtInRect( &rcLeft, pt ))
+ {
+ if ( !bDockedLeft )
+ {
+ nNewX = rc.left - nWidth;
+ bDocked = TRUE;
+ }
+ else if ( rc.right == rcThumb.left )
+ {
+ bDocked = TRUE;
+ }
+ }
+
+
+ if ( PtInRect( &rcBottom, pt ))
+ {
+ nNewY = rc.bottom;
+
+ if ( PtInRect( &rcRight, pt ))
+ {
+ nNewX = rc.right - nWidth;
+ }
+ }
+
+ if ( !bLeading && PtInRect( &rcTop, pt ))
+ {
+ nNewY = rc.top;
+ bDockedRight = bDocked;
+ }
+
+ if ( bMoveTogether )
+ {
+ if ( bDockedRight )
+ {
+ DockThumbs( pThumb, pCurThumb, TRUE );
+ }
+
+ if ( bDockedLeft )
+ {
+ DockThumbs( pCurThumb, pThumb, FALSE );
+ }
+ }
+
+ // Lower-left
+ pt.x = rcThumb.left;
+ pt.y = rcThumb.bottom;
+
+ if ( PtInRect( &rcRight, pt ))
+ {
+ nNewX = rc.right;
+ }
+
+ if ( PtInRect( &rcTop, pt ))
+ {
+ nNewY = rc.top - nHeight;
+
+ if ( PtInRect( &rcLeft, pt ))
+ {
+ nNewX = rc.left;
+ }
+ }
+
+
+ // Lower-right
+ pt.x = rcThumb.right;
+ pt.y = rcThumb.bottom;
+
+ if ( !bLeading && PtInRect( &rcLeft, pt ))
+ {
+ nNewX = rc.left - nWidth;
+ }
+
+ if ( !bLeading && PtInRect( &rcTop, pt ))
+ {
+ nNewY = rc.top - nHeight;
+
+ if ( PtInRect( &rcRight, pt ))
+ {
+ nNewX = rc.right - nWidth;
+ }
+ }
+ }
+
+ };
+ frmidx++;
+ if (pCurThumb->ContainerWnd == fakeTaskBarWindow.ContainerWnd){break;};
+ if (pCurThumb->ContainerWnd == fakeMainWindow.ContainerWnd){
+ pCurThumb = &fakeTaskBarWindow;continue;};
+ if (frmidx == g_nFramesCount){
+ pCurThumb = &fakeMainWindow;continue;
+ }
+
+ pCurThumb = &g_pfwFrames[frmidx];
+
+
+
+ }
+
+ // Adjust coords once again
+ nNewX = nNewX < nOffs ? 0 : nNewX;
+ nNewX = nNewX > ( sizeScreen.cx - nWidth - nOffs ) ? ( sizeScreen.cx - nWidth ) : nNewX;
+ nNewY = nNewY < nOffs ? 0 : nNewY;
+ nNewY = nNewY > ( sizeScreen.cy - nHeight - nOffs ) ? ( sizeScreen.cy - nHeight ) : nNewY;
+
+
+ SetWindowPos( pThumb->ContainerWnd,
+ HWND_TOPMOST,
+ nNewX,
+ nNewY,
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOZORDER|SWP_NOACTIVATE );
+
+
+ // OK, move all g_CluiData.fDocked thumbs
+ if ( bMoveTogether )
+ {
+ pDockThumb = FindFrameByWnd( pDockThumb->dockOpt.hwndRight );
+
+ PositionThumb( pDockThumb, (short)( nNewX + nWidth ), (short)nNewY );
+ }
+}
+
+
+
+static void GetBorderSize(HWND hwnd,RECT *rect)
+{
+ RECT wr,cr;
+ POINT pt1,pt2;
+ // RECT r = {0};
+ // *rect = r;
+ // return;
+ GetWindowRect(hwnd,&wr);
+ GetClientRect(hwnd,&cr);
+ pt1.y = cr.top;pt1.x = cr.left;
+ pt2.y = cr.bottom;pt2.x = cr.right;
+
+ ClientToScreen(hwnd,&pt1);
+ ClientToScreen(hwnd,&pt2);
+
+ cr.top = pt1.y;cr.left = pt1.x;
+ cr.bottom = pt2.y;cr.right = pt2.x;
+
+ rect->top = cr.top-wr.top;
+ rect->left = cr.left-wr.left;
+ rect->right = wr.right-cr.right;
+ rect->bottom = wr.bottom-cr.bottom;
+ //if (rect->top+rect->bottom>10){rect->top = rect->bottom = 2;};
+ //if (rect->left+rect->right>10){rect->top = rect->bottom = 2;};
+
+};
+
+static char __inline *AS(char *str,const char *setting,char *addstr)
+{
+ if (str != NULL) {
+ strcpy(str,setting);
+ strcat(str,addstr);
+ }
+ return str;
+}
+
+static int DBLoadFrameSettingsAtPos(int pos,int Frameid)
+{
+ char sadd[15];
+ char buf[255];
+ // char *oldtb;
+
+ _itoa(pos,sadd,10);
+
+ //DBWriteContactSettingString(0,CLUIFrameModule,strcat("Name",sadd),Frames[Frameid].name);
+ //bool
+ g_pfwFrames[Frameid].collapsed = db_get_b(0,CLUIFrameModule,AS(buf,"Collapse",sadd),g_pfwFrames[Frameid].collapsed);
+
+ g_pfwFrames[Frameid].Locked = db_get_b(0,CLUIFrameModule,AS(buf,"Locked",sadd),g_pfwFrames[Frameid].Locked);
+ g_pfwFrames[Frameid].visible = db_get_b(0,CLUIFrameModule,AS(buf,"Visible",sadd),g_pfwFrames[Frameid].visible);
+ g_pfwFrames[Frameid].TitleBar.ShowTitleBar = db_get_b(0,CLUIFrameModule,AS(buf,"TBVisile",sadd),g_pfwFrames[Frameid].TitleBar.ShowTitleBar);
+
+ g_pfwFrames[Frameid].height = db_get_w(0,CLUIFrameModule,AS(buf,"Height",sadd),g_pfwFrames[Frameid].height);
+ g_pfwFrames[Frameid].HeightWhenCollapsed = db_get_w(0,CLUIFrameModule,AS(buf,"HeightCollapsed",sadd),0);
+ g_pfwFrames[Frameid].align = db_get_w(0,CLUIFrameModule,AS(buf,"Align",sadd),g_pfwFrames[Frameid].align);
+
+ g_pfwFrames[Frameid].FloatingPos.x = DBGetContactSettingRangedWord(0,CLUIFrameModule,AS(buf,"FloatX",sadd),100,0,2048);
+ g_pfwFrames[Frameid].FloatingPos.y = DBGetContactSettingRangedWord(0,CLUIFrameModule,AS(buf,"FloatY",sadd),100,0,2048);
+ g_pfwFrames[Frameid].FloatingSize.x = DBGetContactSettingRangedWord(0,CLUIFrameModule,AS(buf,"FloatW",sadd),100,0,2048);
+ g_pfwFrames[Frameid].FloatingSize.y = DBGetContactSettingRangedWord(0,CLUIFrameModule,AS(buf,"FloatH",sadd),100,0,2048);
+
+ g_pfwFrames[Frameid].floating = db_get_b(0,CLUIFrameModule,AS(buf,"Floating",sadd),0);
+ g_pfwFrames[Frameid].order = db_get_w(0,CLUIFrameModule,AS(buf,"Order",sadd),0);
+
+ g_pfwFrames[Frameid].UseBorder = db_get_b(0,CLUIFrameModule,AS(buf,"UseBorder",sadd),g_pfwFrames[Frameid].UseBorder);
+
+ return 0;
+}
+
+static int DBStoreFrameSettingsAtPos(int pos,int Frameid)
+{
+ char sadd[16];
+ char buf[255];
+
+ _itoa(pos,sadd,10);
+
+ db_set_ws(0,CLUIFrameModule,AS(buf,"Name",sadd),g_pfwFrames[Frameid].Name);
+ //bool
+ db_set_b(0,CLUIFrameModule,AS(buf,"Collapse",sadd),(BYTE)btoint(g_pfwFrames[Frameid].collapsed));
+ db_set_b(0,CLUIFrameModule,AS(buf,"Locked",sadd),(BYTE)btoint(g_pfwFrames[Frameid].Locked));
+ db_set_b(0,CLUIFrameModule,AS(buf,"Visible",sadd),(BYTE)btoint(g_pfwFrames[Frameid].visible));
+ db_set_b(0,CLUIFrameModule,AS(buf,"TBVisile",sadd),(BYTE)btoint(g_pfwFrames[Frameid].TitleBar.ShowTitleBar));
+
+ db_set_w(0,CLUIFrameModule,AS(buf,"Height",sadd),(WORD)g_pfwFrames[Frameid].height);
+ db_set_w(0,CLUIFrameModule,AS(buf,"HeightCollapsed",sadd),(WORD)g_pfwFrames[Frameid].HeightWhenCollapsed);
+ db_set_w(0,CLUIFrameModule,AS(buf,"Align",sadd),(WORD)g_pfwFrames[Frameid].align);
+ //FloatingPos
+ db_set_w(0,CLUIFrameModule,AS(buf,"FloatX",sadd),(WORD)g_pfwFrames[Frameid].FloatingPos.x);
+ db_set_w(0,CLUIFrameModule,AS(buf,"FloatY",sadd),(WORD)g_pfwFrames[Frameid].FloatingPos.y);
+ db_set_w(0,CLUIFrameModule,AS(buf,"FloatW",sadd),(WORD)g_pfwFrames[Frameid].FloatingSize.x);
+ db_set_w(0,CLUIFrameModule,AS(buf,"FloatH",sadd),(WORD)g_pfwFrames[Frameid].FloatingSize.y);
+
+ db_set_b(0,CLUIFrameModule,AS(buf,"Floating",sadd),(BYTE)btoint(g_pfwFrames[Frameid].floating));
+ db_set_b(0,CLUIFrameModule,AS(buf,"UseBorder",sadd),(BYTE)btoint(g_pfwFrames[Frameid].UseBorder));
+ db_set_w(0,CLUIFrameModule,AS(buf,"Order",sadd),(WORD)g_pfwFrames[Frameid].order);
+ return 0;
+}
+
+static int LocateStorePosition(int Frameid,int maxstored)
+{
+
+ if (g_pfwFrames[Frameid].Name == NULL)
+ return -1;
+ char settingname[255];
+ for ( int i=0;i < maxstored;i++)
+ {
+
+ mir_snprintf(settingname,SIZEOF(settingname),"Name%d",i);
+ DBVARIANT dbv = {0};
+ if ( DBGetContactSettingTString( NULL, CLUIFrameModule, settingname, &dbv ))
+ continue;
+
+ if ( lstrcmpi( dbv.ptszVal, g_pfwFrames[Frameid].Name ) == 0 )
+ {
+ db_free( &dbv );
+ return i;
+ }
+ db_free( &dbv );
+ }
+ return -1;
+}
+
+static int CLUIFramesLoadFrameSettings(int Frameid)
+{
+ int storpos,maxstored;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if (Frameid < 0 || Frameid >= g_nFramesCount) return -1;
+
+ maxstored = db_get_w(0,CLUIFrameModule,"StoredFrames",-1);
+ if (maxstored == -1) return 0;
+
+ storpos = LocateStorePosition(Frameid,maxstored);
+ if (storpos == -1) return 0;
+
+ DBLoadFrameSettingsAtPos(storpos,Frameid);
+ return 0;
+}
+
+static int CLUIFramesStoreFrameSettings(int Frameid)
+{
+ int maxstored,storpos;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if (Frameid < 0 || Frameid >= g_nFramesCount) return -1;
+
+ maxstored = db_get_w(0,CLUIFrameModule,"StoredFrames",-1);
+ if (maxstored == -1) maxstored = 0;
+
+ storpos = LocateStorePosition(Frameid,maxstored);
+ if (storpos == -1) {storpos = maxstored; maxstored++;}
+
+ DBStoreFrameSettingsAtPos(storpos,Frameid);
+ db_set_w(0,CLUIFrameModule,"StoredFrames",(WORD)maxstored);
+
+ return 0;
+}
+
+static int CLUIFramesStoreAllFrames()
+{
+ int i;
+ if (_fCluiFramesModuleNotStarted) return -1;
+ for (i=0;i < g_nFramesCount;i++)
+ CLUIFramesStoreFrameSettings(i);
+ return 0;
+}
+
+static int CLUIFramesGetalClientFrame(void)
+{
+ int i;
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if ( _nClientFrameId != eUnknownId ) {
+ /* this value could become invalid if RemoveItemFromList was called,
+ * so we double-check */
+ if (_nClientFrameId < g_nFramesCount) {
+ if (g_pfwFrames[_nClientFrameId].align == alClient) {
+ return _nClientFrameId;
+ }
+ }
+ }
+
+ for (i=0;i < g_nFramesCount;i++)
+ if (g_pfwFrames[i].align == alClient) {
+ _nClientFrameId = i;
+ return i;
+ }
+ return -1;
+}
+
+static HMENU CLUIFramesCreateMenuForFrame(int frameid,int root,int popuppos,HGENMENU (*pfnAdd)(CLISTMENUITEM*))
+{
+ //TMO_MenuItem tmi;
+ HGENMENU menuid;
+ int framepos = id2pos(frameid);
+
+ if (_fCluiFramesModuleNotStarted)
+ return NULL;
+
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Visible");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_CHECKED;
+ mi.pszContactOwner = (char *)0;
+ mi.pszService = MS_CLIST_FRAMES_SHFRAME;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiVisible = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIVisible = menuid;
+
+ popuppos += 100000;
+
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Show title");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_CHECKED;
+ mi.pszService = MS_CLIST_FRAMES_SHFRAMETITLEBAR;
+ mi.pszContactOwner = (char *)0;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiTBVisible = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MITBVisible = menuid;
+
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Locked");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_CHECKED;
+ mi.pszService = MS_CLIST_FRAMES_ULFRAME;
+ mi.pszContactOwner = (char *)0;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiLock = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MILock = menuid;
+
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Expanded");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_CHECKED;
+ mi.pszService = MS_CLIST_FRAMES_UCOLLFRAME;
+ mi.pszContactOwner = (char *)0;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiColl = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIColl = menuid;
+
+ //floating
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Floating Mode");
+ mi.flags = CMIF_CHILDPOPUP;
+ mi.pszService = "Set_Floating";
+ mi.pszContactOwner = (char *)0;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiFloating = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIFloating = menuid;
+
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Border");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_CHECKED;
+ mi.pszService = MS_CLIST_FRAMES_SETUNBORDER;
+ mi.pszContactOwner = (char *)0;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiBorder = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIBorder = menuid;
+
+ popuppos += 100000;
+
+ {
+ //alignment root
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Align");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_ROOTPOPUP;
+ mi.pszService = "";
+ mi.pszContactOwner = (char *)0;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiAlignRoot = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIAlignRoot = menuid;
+
+ mi.flags = CMIF_CHILDPOPUP;
+ //align top
+ mi.pszPopupName = (char *)menuid;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Top");
+ mi.pszService = CLUIFRAMESSETALIGNALTOP;
+ mi.pszContactOwner = (char *)alTop;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiAlignTop = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIAlignTop = menuid;
+
+
+ //align client
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Client");
+ mi.pszService = CLUIFRAMESSETALIGNALCLIENT;
+ mi.pszContactOwner = (char *)alClient;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiAlignClient = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIAlignClient = menuid;
+
+ //align bottom
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Bottom");
+ mi.pszService = CLUIFRAMESSETALIGNALBOTTOM;
+ mi.pszContactOwner = (char *)alBottom;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiAlignBottom = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIAlignBottom = menuid;
+
+ }
+
+ { //position
+ //position root
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Position");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_ROOTPOPUP;
+ mi.pszService = "";
+ mi.pszContactOwner = (char *)0;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiPosRoot = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIPosRoot = menuid;
+ //??????
+ mi.pszPopupName = (char *)menuid;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Up");
+ mi.flags = CMIF_CHILDPOPUP;
+ mi.pszService = CLUIFRAMESMOVEUP;
+ mi.pszContactOwner = (char *)1;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiPosUp = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIPosUp = menuid;
+
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Down");
+ mi.flags = CMIF_CHILDPOPUP;
+ mi.pszService = CLUIFRAMESMOVEDOWN;
+ mi.pszContactOwner = (char *)-1;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiPosDown = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIPosDown = menuid;
+
+ }
+
+ return 0;
+}
+
+static int ModifyMItem(WPARAM wParam,LPARAM lParam)
+{
+ if ((int) wParam == -1 ) return 0; // FIXME
+
+ return ModifyMenuItemProxy(wParam,lParam);
+};
+
+
+static int CLUIFramesModifyContextMenuForFrame(WPARAM wParam,LPARAM lParam)
+{
+ int pos;
+ CLISTMENUITEM mi;
+ /* HOOK */
+ if (MirandaExiting()) return 0;
+ if (_fCluiFramesModuleNotStarted) return -1;
+ pos = id2pos(wParam);
+ if (pos >= 0 && pos < g_nFramesCount) {
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS|CMIM_NAME|CMIF_CHILDPOPUP|CMIF_TCHAR;
+ if (g_pfwFrames[pos].visible) mi.flags |= CMIF_CHECKED;
+ mi.ptszName = g_pfwFrames[pos].TitleBar.tbname ? g_pfwFrames[pos].TitleBar.tbname : g_pfwFrames[pos].Name;
+ ModifyMItem((WPARAM)_hmiVisible,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].Locked) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)_hmiLock,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].TitleBar.ShowTitleBar) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)_hmiTBVisible,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].floating) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)_hmiFloating,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if ( g_CluiData.fLayered ) mi.flags |= CMIF_GRAYED;
+ else if ((g_pfwFrames[pos].UseBorder)) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)_hmiBorder,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].align&alTop) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)_hmiAlignTop,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].align&alClient) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)_hmiAlignClient,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].align&alBottom) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)_hmiAlignBottom,(LPARAM)&mi);
+
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].collapsed) mi.flags |= CMIF_CHECKED;
+ if ((!g_pfwFrames[pos].visible) || (g_pfwFrames[pos].Locked) || (pos == CLUIFramesGetalClientFrame())) mi.flags |= CMIF_GRAYED;
+ ModifyMItem((WPARAM)_hmiColl,(LPARAM)&mi);
+ }
+ return 0;
+}
+
+static int CLUIFramesModifyMainMenuItems(WPARAM wParam,LPARAM lParam)
+{
+ //hiword(wParam) = frameid,loword(wParam) = flag
+ int pos;
+ CLISTMENUITEM mi;
+ //TMO_MenuItem tmi;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+
+ pos = id2pos(wParam);
+
+ if (pos >= 0 && pos < g_nFramesCount) {
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS|CMIM_NAME|CMIF_CHILDPOPUP|CMIF_TCHAR;
+ if (g_pfwFrames[pos].visible) mi.flags |= CMIF_CHECKED;
+ mi.ptszName = g_pfwFrames[pos].TitleBar.tbname ? g_pfwFrames[pos].TitleBar.tbname : g_pfwFrames[pos].Name;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MIVisible,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].Locked) mi.flags |= CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MILock,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].TitleBar.ShowTitleBar) mi.flags |= CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MITBVisible,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].floating) mi.flags |= CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MIFloating,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+
+ if ( g_CluiData.fLayered ) mi.flags |= CMIF_GRAYED;
+ else if ((g_pfwFrames[pos].UseBorder)) mi.flags |= CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MIBorder,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP|((g_pfwFrames[pos].align&alClient)?CMIF_GRAYED:0);
+ if (g_pfwFrames[pos].align&alTop) mi.flags |= CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MIAlignTop,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].align&alClient) mi.flags |= CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MIAlignClient,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP|((g_pfwFrames[pos].align&alClient)?CMIF_GRAYED:0);
+ if (g_pfwFrames[pos].align&alBottom) mi.flags |= CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MIAlignBottom,(LPARAM)&mi);
+
+ /*
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP|((Frames[pos].align&alClient)?CMIF_GRAYED:0);
+ if (Frames[pos].align&alTop) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)contMIAlignTop,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP|CMIF_GRAYED;
+ if (Frames[pos].align&alClient) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)contMIAlignClient,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP|((Frames[pos].align&alClient)?CMIF_GRAYED:0);
+ if (Frames[pos].align&alBottom) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)contMIAlignBottom,(LPARAM)&mi);
+
+ */
+
+
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].collapsed) mi.flags |= CMIF_CHECKED;
+ if ((!g_pfwFrames[pos].visible) || g_pfwFrames[pos].Locked || (pos == CLUIFramesGetalClientFrame())) mi.flags |= CMIF_GRAYED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MIColl,(LPARAM)&mi);
+ }
+
+ return 0;
+}
+
+
+static INT_PTR _us_DoGetFrameOptions(WPARAM wParam,LPARAM lParam)
+{
+ int pos;
+ INT_PTR retval;
+ BOOL bUnicodeText = (LOWORD(wParam) & FO_UNICODETEXT) != 0;
+ wParam = MAKEWPARAM((LOWORD(wParam)) & ~FO_UNICODETEXT, HIWORD(wParam));
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+
+ pos = id2pos(HIWORD(wParam));
+ if (pos < 0 || pos >= g_nFramesCount) {
+
+ return -1;
+ }
+
+ switch(LOWORD(wParam))
+ {
+ case FO_FLAGS:
+ retval = 0;
+ if (g_pfwFrames[pos].visible) retval |= F_VISIBLE;
+ if ( !g_pfwFrames[pos].collapsed) retval |= F_UNCOLLAPSED;
+ if (g_pfwFrames[pos].Locked) retval |= F_LOCKED;
+ if (g_pfwFrames[pos].TitleBar.ShowTitleBar) retval |= F_SHOWTB;
+ if (g_pfwFrames[pos].TitleBar.ShowTitleBarTip) retval |= F_SHOWTBTIP;
+ if ( !g_CluiData.fLayered)
+ {
+ if ( !(GetWindowLongPtr(g_pfwFrames[pos].hWnd,GWL_STYLE)&WS_BORDER)) retval |= F_NOBORDER;
+ }
+ else
+ if ( !g_pfwFrames[pos].UseBorder) retval |= F_NOBORDER;
+
+
+ break;
+
+ case FO_NAME:
+ if (bUnicodeText)
+ retval = (INT_PTR)g_pfwFrames[pos].Name;
+ else
+ retval = (INT_PTR)g_pfwFrames[pos].szName;
+ break;
+
+ case FO_TBNAME:
+ if (bUnicodeText)
+ retval = (INT_PTR)g_pfwFrames[pos].TitleBar.tbname;
+ else
+ retval = (INT_PTR)g_pfwFrames[pos].TitleBar.sztbname;
+ break;
+
+ case FO_TBTIPNAME:
+ if (bUnicodeText)
+ retval = (INT_PTR)g_pfwFrames[pos].TitleBar.tooltip;
+ else
+ retval = (INT_PTR)g_pfwFrames[pos].TitleBar.sztooltip;
+ break;
+
+ case FO_TBSTYLE:
+ retval = GetWindowLongPtr(g_pfwFrames[pos].TitleBar.hwnd,GWL_STYLE);
+ break;
+
+ case FO_TBEXSTYLE:
+ retval = GetWindowLongPtr(g_pfwFrames[pos].TitleBar.hwnd,GWL_EXSTYLE);
+ break;
+
+ case FO_ICON:
+ retval = (INT_PTR)g_pfwFrames[pos].TitleBar.hicon;
+ break;
+
+ case FO_HEIGHT:
+ retval = (INT_PTR)g_pfwFrames[pos].height;
+ break;
+
+ case FO_ALIGN:
+ retval = (INT_PTR)g_pfwFrames[pos].align;
+ break;
+ case FO_FLOATING:
+ retval = (INT_PTR)g_pfwFrames[pos].floating;
+ break;
+ default:
+ retval = -1;
+ break;
+ }
+
+ return retval;
+}
+
+static int UpdateTBToolTip(int framepos)
+{
+ {
+ TOOLINFO ti;
+
+ ZeroMemory(&ti,sizeof(ti));
+ ti.cbSize = sizeof(ti);
+ ti.lpszText = g_pfwFrames[framepos].TitleBar.tooltip;
+ ti.hinst = g_hInst;
+ ti.uFlags = TTF_IDISHWND|TTF_SUBCLASS ;
+ ti.uId = (UINT_PTR)g_pfwFrames[framepos].TitleBar.hwnd;
+
+ return(SendMessage(g_pfwFrames[framepos].TitleBar.hwndTip,TTM_UPDATETIPTEXT ,(WPARAM)0,(LPARAM)&ti));
+ }
+
+};
+//hiword(wParam) = frameid,loword(wParam) = flag
+static int _us_DoSetFrameOptions(WPARAM wParam,LPARAM lParam)
+{
+ int pos;
+ int retval; // value to be returned
+ BOOL bUnicodeText = (LOWORD(wParam) & FO_UNICODETEXT) != 0;
+ wParam = MAKEWPARAM((LOWORD(wParam))& ~FO_UNICODETEXT, HIWORD(wParam));
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+
+ pos = id2pos(HIWORD(wParam));
+ if (pos < 0 || pos >= g_nFramesCount) {
+
+ return -1;
+ }
+
+ switch(LOWORD(wParam))
+ {
+ case FO_FLAGS:{
+ int flag = lParam;
+ int style;
+
+ g_pfwFrames[pos].dwFlags = flag;
+ g_pfwFrames[pos].visible = FALSE;
+ if (flag&F_VISIBLE) g_pfwFrames[pos].visible = TRUE;
+
+ g_pfwFrames[pos].collapsed = TRUE;
+ if (flag&F_UNCOLLAPSED) g_pfwFrames[pos].collapsed = FALSE;
+
+ g_pfwFrames[pos].Locked = FALSE;
+ if (flag&F_LOCKED) g_pfwFrames[pos].Locked = TRUE;
+
+ g_pfwFrames[pos].UseBorder = TRUE;
+ if (flag&F_NOBORDER) g_pfwFrames[pos].UseBorder = FALSE;
+
+ g_pfwFrames[pos].TitleBar.ShowTitleBar = FALSE;
+ if (flag&F_SHOWTB) g_pfwFrames[pos].TitleBar.ShowTitleBar = TRUE;
+
+ g_pfwFrames[pos].TitleBar.ShowTitleBarTip = FALSE;
+ if (flag&F_SHOWTBTIP) g_pfwFrames[pos].TitleBar.ShowTitleBarTip = TRUE;
+
+ SendMessageA(g_pfwFrames[pos].TitleBar.hwndTip,TTM_ACTIVATE,(WPARAM)g_pfwFrames[pos].TitleBar.ShowTitleBarTip,0);
+
+ style = (int)GetWindowLongPtr(g_pfwFrames[pos].hWnd,GWL_STYLE);
+ style &= (~WS_BORDER);
+
+ if ( !(flag&F_NOBORDER ) && !g_CluiData.fLayered ) style |= WS_BORDER;
+
+ SetWindowLongPtr(g_pfwFrames[pos].hWnd,GWL_STYLE,(long)style);
+ SetWindowLongPtr(g_pfwFrames[pos].TitleBar.hwnd,GWL_STYLE,(long)style& ~(WS_VSCROLL | WS_HSCROLL));
+
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ SetWindowPos(g_pfwFrames[pos].TitleBar.hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED|SWP_NOACTIVATE);
+ return 0;
+ }
+
+ case FO_NAME:
+ if (lParam == (LPARAM)NULL)
+ return -1;
+
+ mir_free(g_pfwFrames[pos].Name);
+ mir_free(g_pfwFrames[pos].szName);
+ if (bUnicodeText) {
+ g_pfwFrames[pos].Name = mir_tstrdup((LPTSTR)lParam);
+ g_pfwFrames[pos].szName = mir_t2a((LPTSTR)lParam);
+ }
+ else {
+ g_pfwFrames[pos].szName = mir_strdup((char*)lParam);
+ g_pfwFrames[pos].Name = mir_a2t((char *)lParam);
+ }
+ return 0;
+
+ case FO_TBNAME:
+ if (lParam == (LPARAM)NULL) { return(-1);}
+
+ mir_free(g_pfwFrames[pos].TitleBar.tbname);
+ mir_free(g_pfwFrames[pos].TitleBar.sztbname);
+ if (bUnicodeText) {
+ g_pfwFrames[pos].TitleBar.tbname = mir_tstrdup((LPTSTR)lParam);
+ g_pfwFrames[pos].TitleBar.sztbname = mir_t2a((LPTSTR)lParam);
+ }
+ else {
+ g_pfwFrames[pos].TitleBar.sztbname = mir_strdup((char*)lParam);
+ g_pfwFrames[pos].TitleBar.tbname = mir_a2t((char*)lParam);
+ }
+
+ if (g_pfwFrames[pos].floating && (g_pfwFrames[pos].TitleBar.tbname != NULL))
+ SetWindowText(g_pfwFrames[pos].ContainerWnd,g_pfwFrames[pos].TitleBar.tbname);
+ return 0;
+
+ case FO_TBTIPNAME:
+ if (lParam == (LPARAM)NULL) { return(-1);}
+ if (g_pfwFrames[pos].TitleBar.tooltip != NULL) mir_free_and_nil(g_pfwFrames[pos].TitleBar.tooltip);
+ if (g_pfwFrames[pos].TitleBar.sztooltip != NULL) mir_free_and_nil(g_pfwFrames[pos].TitleBar.sztooltip);
+ if (bUnicodeText)
+ {
+ g_pfwFrames[pos].TitleBar.tooltip = mir_tstrdup((LPTSTR)lParam);
+ g_pfwFrames[pos].TitleBar.sztooltip = mir_t2a((LPTSTR)lParam);
+ }
+ else
+ {
+ g_pfwFrames[pos].TitleBar.sztooltip = mir_strdup((char*)lParam);
+ g_pfwFrames[pos].TitleBar.tooltip = mir_a2t((char*)lParam);
+ }
+ UpdateTBToolTip(pos);
+
+ return 0;
+
+ case FO_TBSTYLE:
+ SetWindowLongPtr(g_pfwFrames[pos].TitleBar.hwnd,GWL_STYLE,lParam& ~(WS_VSCROLL | WS_HSCROLL));
+
+ return 0;
+
+ case FO_TBEXSTYLE:
+ SetWindowLongPtr(g_pfwFrames[pos].TitleBar.hwnd,GWL_EXSTYLE,lParam);
+
+ return 0;
+
+ case FO_ICON:
+ g_pfwFrames[pos].TitleBar.hicon = (HICON)lParam;
+
+ return 0;
+
+ case FO_HEIGHT:
+ if (lParam < 0) { return -1;}
+
+ if (g_pfwFrames[pos].collapsed)
+ {
+ int oldHeight = g_pfwFrames[pos].height;
+ retval = g_pfwFrames[pos].height;
+ g_pfwFrames[pos].height = lParam;
+ if ( !CLUIFramesFitInSize()) g_pfwFrames[pos].height = retval;
+ retval = g_pfwFrames[pos].height;
+ if (g_pfwFrames[pos].height != oldHeight)
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ }
+ else
+ {
+ retval = g_pfwFrames[pos].HeightWhenCollapsed;
+ g_pfwFrames[pos].HeightWhenCollapsed = lParam;
+ if ( !CLUIFramesFitInSize()) g_pfwFrames[pos].HeightWhenCollapsed = retval;
+ retval = g_pfwFrames[pos].HeightWhenCollapsed;
+
+ }
+ return retval;
+
+ case FO_FLOATING:
+ if (lParam < 0) { return -1;}
+
+ {
+ int id = g_pfwFrames[pos].id;
+ g_pfwFrames[pos].floating = !(lParam);
+
+
+ CLUIFrames_SetFrameFloat(id,1);//lparam = 1 use stored width and height
+ return(wParam);
+ }
+
+ case FO_ALIGN:
+ if ( !(lParam&alTop || lParam&alBottom || lParam&alClient))
+ {
+ TRACE("Wrong align option \r\n");
+ return (-1);
+ };
+
+ if ((lParam&alClient) && (CLUIFramesGetalClientFrame() >= 0)) { //only one alClient frame possible
+ _nClientFrameId = eUnknownId;//recalc it
+
+ return -1;
+ }
+ g_pfwFrames[pos].align = lParam;
+
+
+ return(0);
+ }
+
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ return -1;
+}
+
+//wparam = lparam = 0
+static int _us_DoShowAllFrames(WPARAM wParam,LPARAM lParam)
+{
+ int i;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ for (i=0;i < g_nFramesCount;i++)
+ g_pfwFrames[i].visible = TRUE;
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ return 0;
+}
+
+//wparam = lparam = 0
+static int _us_DoShowTitles(WPARAM wParam,LPARAM lParam)
+{
+ int i;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ for (i=0;i < g_nFramesCount;i++)
+ g_pfwFrames[i].TitleBar.ShowTitleBar = TRUE;
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ return 0;
+}
+
+//wparam = lparam = 0
+static int _us_DoHideTitles(WPARAM wParam,LPARAM lParam)
+{
+ int i;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ for (i=0;i < g_nFramesCount;i++)
+ g_pfwFrames[i].TitleBar.ShowTitleBar = FALSE;
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ return 0;
+}
+
+//wparam = frameid
+static int _us_DoShowHideFrame(WPARAM wParam,LPARAM lParam)
+{
+ int pos;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if (wParam == 0) {
+ pos = lParam;
+ } else {
+ pos = id2pos(wParam);
+ }
+ if (pos >= 0 && (int)pos < g_nFramesCount)
+ {
+ g_pfwFrames[pos].visible = !g_pfwFrames[pos].visible;
+ if (g_pfwFrames[pos].OwnerWindow != (HWND)-2)
+ {
+ if (g_pfwFrames[pos].OwnerWindow)
+ CLUI_ShowWindowMod(g_pfwFrames[pos].OwnerWindow,(g_pfwFrames[pos].visible && g_pfwFrames[pos].collapsed && IsWindowVisible(pcli->hwndContactList))?SW_SHOW/*NOACTIVATE*/:SW_HIDE);
+ else if (g_pfwFrames[pos].visible)
+ {
+ g_pfwFrames[pos].OwnerWindow = CreateSubContainerWindow(pcli->hwndContactList,g_pfwFrames[pos].FloatingPos.x,g_pfwFrames[pos].FloatingPos.y,10,10);
+ SetParent(g_pfwFrames[pos].hWnd,g_pfwFrames[pos].OwnerWindow);
+ CLUI_ShowWindowMod(g_pfwFrames[pos].OwnerWindow,(g_pfwFrames[pos].visible && g_pfwFrames[pos].collapsed && IsWindowVisible(pcli->hwndContactList))?SW_SHOW/*NOACTIVATE*/:SW_HIDE);
+ }
+ }
+ if (g_pfwFrames[pos].floating){CLUIFrameResizeFloatingFrame(pos);};
+
+ if ( !g_pfwFrames[pos].floating) CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ }
+ return 0;
+}
+
+//wparam = frameid
+static int _us_DoShowHideFrameTitle(WPARAM wParam,LPARAM lParam)
+{
+ int pos;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if (wParam == 0) {
+ pos = lParam;
+ } else {
+ pos = id2pos(wParam);
+ }
+ if (pos >= 0 && (int)pos < g_nFramesCount)
+ g_pfwFrames[pos].TitleBar.ShowTitleBar = !g_pfwFrames[pos].TitleBar.ShowTitleBar;
+ //if (Frames[pos].height>
+
+
+
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+
+
+ return 0;
+}
+
+//wparam = frameid
+//lparam = -1 up ,1 down
+static int _us_DoMoveFrame(WPARAM wParam,LPARAM lParam)
+{
+ int pos,i,curpos,curalign,v,tmpval;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ pos = id2pos(wParam);
+ if (pos >= 0 && (int)pos < g_nFramesCount) {
+ SortData *sd;
+ curpos = g_pfwFrames[pos].order;
+ curalign = g_pfwFrames[pos].align;
+ v = 0;
+ sd = (SortData*)malloc(sizeof(SortData)*g_nFramesCount);
+ memset(sd,0,sizeof(SortData)*g_nFramesCount);
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if (g_pfwFrames[i].floating || (!g_pfwFrames[i].visible) || (g_pfwFrames[i].align != curalign)){continue;};
+
+ sd[v].order = g_pfwFrames[i].order;
+ sd[v].realpos = i;
+ v++;
+ };
+ if (v == 0){return(0);};
+ qsort(sd,v,sizeof(SortData),sortfunc);
+ for (i=0;i < v;i++)
+ g_pfwFrames[sd[i].realpos].order = i+1; //to be sure that order is incremental
+ for (i=0;i < v;i++)
+ {
+ if (sd[i].realpos == pos)
+ {
+ if (lParam == -1)
+ {
+ if (i >= v-1) break;
+ tmpval = g_pfwFrames[sd[i+1].realpos].order;
+ g_pfwFrames[sd[i+1].realpos].order = g_pfwFrames[pos].order;
+ g_pfwFrames[pos].order = tmpval;
+ break;
+ };
+ if (lParam == +1)
+ {
+ if (i < 1) break;
+ tmpval = g_pfwFrames[sd[i-1].realpos].order;
+ g_pfwFrames[sd[i-1].realpos].order = g_pfwFrames[pos].order;
+ g_pfwFrames[pos].order = tmpval;
+ break;
+ };
+
+
+ };
+ };
+
+ if (sd != NULL){free(sd);};
+ CLUIFramesStoreFrameSettings(pos);
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,0);
+
+ }
+
+ return(0);
+};
+
+
+
+static int _us_DoMoveFrameUp(WPARAM wParam,LPARAM lParam)
+{
+ return CLUIFrames_MoveFrame(wParam,(LPARAM)+1);
+}
+static int _us_DoMoveFrameDown(WPARAM wParam,LPARAM lParam)
+{
+ return CLUIFrames_MoveFrame(wParam,(LPARAM)-1);
+}
+//wparam = frameid
+//lparam = alignment
+static int _us_DoSetFrameAlign(WPARAM wParam,LPARAM lParam)
+{
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ CLUIFrames_SetFrameOptions(MAKEWPARAM(FO_ALIGN,wParam),lParam);
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,0);
+ return(0);
+}
+static int _us_DoAlignFrameTop(WPARAM wParam,LPARAM lParam)
+{
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ return CLUIFrames_SetFrameAlign(wParam,alTop);
+}
+static int _us_DoAlignFrameBottom(WPARAM wParam,LPARAM lParam)
+{
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ return CLUIFrames_SetFrameAlign(wParam,alBottom);
+}
+static int _us_DoAlignFrameClient(WPARAM wParam,LPARAM lParam)
+{
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ return CLUIFrames_SetFrameAlign(wParam,alClient);
+}
+
+
+//wparam = frameid
+static int _us_DoLockFrame(WPARAM wParam,LPARAM lParam)
+{
+ int pos;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if (wParam == 0) {
+ pos = lParam;
+ } else {
+ pos = id2pos(wParam);
+ }
+ if (pos >= 0 && (int)pos < g_nFramesCount) {
+ g_pfwFrames[pos].Locked = !g_pfwFrames[pos].Locked;
+ CLUIFramesStoreFrameSettings(pos);
+ }
+
+ return 0;
+}
+
+//wparam = frameid
+static int _us_DoSetFrameBorder(WPARAM wParam,LPARAM lParam)
+{
+ RECT rc;
+ int FrameId,oldflags;
+ HWND hw;
+ int flt;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if (wParam == 0) {
+ FrameId = lParam;
+ } else {
+ FrameId = id2pos(wParam);
+ }
+ if (FrameId == -1){return(-1);};
+ flt =
+ oldflags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,wParam),0);
+ if (oldflags&F_NOBORDER)
+ {
+ oldflags &= (~F_NOBORDER);
+ }
+ else
+ {
+ oldflags |= F_NOBORDER;
+ };
+ hw = g_pfwFrames[FrameId].hWnd;
+ GetWindowRect(hw,&rc);
+
+
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,wParam),oldflags);
+ {
+ SetWindowPos(hw,0,0,0,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE|SWP_DRAWFRAME);
+ };
+ return(0);
+};
+//wparam = frameid
+static int _us_DoCollapseFrame(WPARAM wParam,LPARAM lParam)
+{
+ int FrameId;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if (wParam == 0) {
+ FrameId = lParam;
+ } else {
+ FrameId = id2pos(wParam);
+ }
+ if (FrameId >= 0 && FrameId < g_nFramesCount)
+ {
+ int oldHeight;
+
+ // do not collapse/uncollapse client/locked/invisible frames
+ if (g_pfwFrames[FrameId].align == alClient && !(g_pfwFrames[FrameId].Locked || (!g_pfwFrames[FrameId].visible) || g_pfwFrames[FrameId].floating))
+ {
+ RECT rc;
+ if (CallService(MS_CLIST_DOCKINGISDOCKED,0,0)) {return 0;};
+ if ( !g_CluiData.fDocked && g_CluiData.fAutoSize) {return 0;};
+ GetWindowRect(pcli->hwndContactList,&rc);
+
+ if (g_pfwFrames[FrameId].collapsed == TRUE) {
+ rc.bottom -= rc.top;
+ rc.bottom -= g_pfwFrames[FrameId].height;
+ g_pfwFrames[FrameId].HeightWhenCollapsed = g_pfwFrames[FrameId].height;
+ g_pfwFrames[FrameId].collapsed = FALSE;
+ }
+ else
+ {
+ rc.bottom -= rc.top;
+ rc.bottom += g_pfwFrames[FrameId].HeightWhenCollapsed;
+ g_pfwFrames[FrameId].collapsed = TRUE;
+ }
+
+ SetWindowPos(pcli->hwndContactList,NULL,0,0,rc.right-rc.left,rc.bottom,SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE);
+
+ CLUIFramesStoreAllFrames();
+
+
+ return 0;
+
+ }
+ if (g_pfwFrames[FrameId].Locked || (!g_pfwFrames[FrameId].visible)) return 0;
+
+ oldHeight = g_pfwFrames[FrameId].height;
+
+ // if collapsed, uncollapse
+ if (g_pfwFrames[FrameId].collapsed == TRUE) {
+ g_pfwFrames[FrameId].HeightWhenCollapsed = g_pfwFrames[FrameId].height;
+ g_pfwFrames[FrameId].height = UNCOLLAPSED_FRAME_SIZE;
+ g_pfwFrames[FrameId].collapsed = FALSE;
+ }
+ // if uncollapsed, collapse
+ else {
+ g_pfwFrames[FrameId].height = g_pfwFrames[FrameId].HeightWhenCollapsed;
+ g_pfwFrames[FrameId].collapsed = TRUE;
+ }
+
+ if ( !g_pfwFrames[FrameId].floating)
+ {
+
+ if ( !CLUIFramesFitInSize()) {
+ //cant collapse,we can resize only for height < alclient frame height
+ int alfrm = CLUIFramesGetalClientFrame();
+
+ if (alfrm != -1) {
+ g_pfwFrames[FrameId].collapsed = FALSE;
+ if (g_pfwFrames[alfrm].height>2*UNCOLLAPSED_FRAME_SIZE) {
+ oldHeight = g_pfwFrames[alfrm].height-UNCOLLAPSED_FRAME_SIZE;
+ g_pfwFrames[FrameId].collapsed = TRUE;
+ }
+ }else
+ {
+ int i,sumheight = 0;
+ for (i=0;i < g_nFramesCount;i++) {
+ if ((g_pfwFrames[i].align != alClient) && (!g_pfwFrames[i].floating) && (g_pfwFrames[i].visible) && (!g_pfwFrames[i].needhide)) {
+ sumheight += (g_pfwFrames[i].height)+(g_nTitleBarHeight*btoint(g_pfwFrames[i].TitleBar.ShowTitleBar))+2;
+ return FALSE;
+ }
+ if (sumheight>_nContactListHeight-0-2)
+ {
+ g_pfwFrames[FrameId].height = (_nContactListHeight-0-2)-sumheight;
+ }
+
+ }
+ }
+
+ g_pfwFrames[FrameId].height = oldHeight;
+
+ if (g_pfwFrames[FrameId].collapsed == FALSE) {
+
+ if ( !g_pfwFrames[FrameId].floating)
+ {
+ }
+ else
+ {
+ //SetWindowPos(Frames[FrameId].hWnd,HWND_TOP,0,0,Frames[FrameId].wndSize.right-Frames[FrameId].wndSize.left,Frames[FrameId].height,SWP_SHOWWINDOW|SWP_NOMOVE);
+ SetWindowPos(g_pfwFrames[FrameId].ContainerWnd,HWND_TOP,0,0,g_pfwFrames[FrameId].wndSize.right-g_pfwFrames[FrameId].wndSize.left+6,g_pfwFrames[FrameId].height+DEFAULT_TITLEBAR_HEIGHT+4,SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOMOVE);
+ };
+
+
+ return -1;};//redraw not needed
+ }
+ };//floating test
+
+ //CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,0);
+ if ( !g_pfwFrames[FrameId].floating)
+ {
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,0);
+ }
+ else
+ {
+ //SetWindowPos(Frames[FrameId].hWnd,HWND_TOP,0,0,Frames[FrameId].wndSize.right-Frames[FrameId].wndSize.left,Frames[FrameId].height,SWP_SHOWWINDOW|SWP_NOMOVE);
+ RECT contwnd;
+ GetWindowRect(g_pfwFrames[FrameId].ContainerWnd,&contwnd);
+ contwnd.top = contwnd.bottom-contwnd.top;//height
+ contwnd.left = contwnd.right-contwnd.left;//width
+
+ contwnd.top -= (oldHeight-g_pfwFrames[FrameId].height);//newheight
+ SetWindowPos(g_pfwFrames[FrameId].ContainerWnd,HWND_TOP,0,0,contwnd.left,contwnd.top,SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOMOVE);
+ };
+ CLUIFramesStoreAllFrames();
+ return(0);
+ }
+ else
+ return -1;
+}
+
+static int CLUIFramesLoadMainMenu()
+{
+ if (_fCluiFramesModuleNotStarted)
+ return -1;
+
+ if (_hmiRoot != (HGENMENU)-1) {
+ CallService(MS_CLIST_REMOVEMAINMENUITEM,(WPARAM)_hmiRoot,0);
+ _hmiRoot = (HGENMENU)-1;
+ }
+
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof(mi);
+ // create root menu
+ mi.flags = CMIF_ICONFROMICOLIB | CMIF_ROOTHANDLE;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_MIRANDA);
+ mi.position = 3000090000;
+ mi.pszName = LPGEN("Frames");
+ _hmiRoot = Menu_AddMainMenuItem(&mi);
+ DestroyIcon_protect(mi.hIcon);
+ // create frames menu
+ int separator = 3000200000;
+ for (int i=0; i < g_nFramesCount; i++) {
+ mi.hIcon = g_pfwFrames[i].TitleBar.hicon;
+ mi.flags = CMIF_ROOTHANDLE | CMIF_TCHAR;
+ mi.position = separator;
+ mi.hParentMenu = _hmiRoot;
+ mi.ptszName = g_pfwFrames[i].TitleBar.tbname ? g_pfwFrames[i].TitleBar.tbname : g_pfwFrames[i].Name;
+ mi.pszService = 0;
+ g_pfwFrames[i].MenuHandles.MainMenuItem = Menu_AddMainMenuItem(&mi);
+ CLUIFramesCreateMenuForFrame(g_pfwFrames[i].id,(int)g_pfwFrames[i].MenuHandles.MainMenuItem,separator,Menu_AddMainMenuItem);
+ CLUIFramesModifyMainMenuItems(g_pfwFrames[i].id,0);
+ CallService(MS_CLIST_FRAMEMENUNOTIFY,(WPARAM)g_pfwFrames[i].id,(LPARAM)g_pfwFrames[i].MenuHandles.MainMenuItem);
+ separator++;
+ }
+
+ separator += 100000;
+
+ // create "show all frames" menu
+ mi.hIcon = NULL;
+ mi.flags = CMIF_ROOTHANDLE;
+ mi.position = separator++;
+ mi.hParentMenu = _hmiRoot;
+ mi.pszName = LPGEN("Show All Frames");
+ mi.pszService = MS_CLIST_FRAMES_SHOWALLFRAMES;
+ Menu_AddMainMenuItem(&mi);
+
+ // create "show all titlebars" menu
+ mi.position = separator++;
+ mi.pszName = LPGEN("Show All Titlebars");
+ mi.pszService = MS_CLIST_FRAMES_SHOWALLFRAMESTB;
+ Menu_AddMainMenuItem(&mi);
+
+ // create "hide all titlebars" menu
+ mi.position = separator++;
+ mi.pszName = LPGEN("Hide All Titlebars");
+ mi.pszService = MS_CLIST_FRAMES_HIDEALLFRAMESTB;
+ Menu_AddMainMenuItem(&mi);
+ return 0;
+}
+
+static HFONT CLUILoadTitleBarFont()
+{
+ char facename[] = "MS Shell Dlg";
+ HFONT hfont;
+ LOGFONTA logfont;
+ memset(&logfont,0,sizeof(logfont));
+ memmove(logfont.lfFaceName,facename,sizeof(facename));
+ logfont.lfWeight = FW_NORMAL;
+ logfont.lfHeight = -10;
+ logfont.lfCharSet = DEFAULT_CHARSET;
+ hfont = CreateFontIndirectA(&logfont);
+ return hfont;
+}
+
+
+//wparam = (CLISTFrame*)clfrm
+static int _us_DoAddFrame(WPARAM wParam,LPARAM lParam)
+{
+ int style,retval;
+ //char * CustomName = NULL;
+ CLISTFrame *clfrm = (CLISTFrame *)wParam;
+
+ if (pcli->hwndContactList == 0) return -1;
+ if (_fCluiFramesModuleNotStarted) return -1;
+ if (clfrm->cbSize != sizeof(CLISTFrame)) return -1;
+ if ( !(_hTitleBarFont)) _hTitleBarFont = CLUILoadTitleBarFont();
+
+ g_pfwFrames = (FRAMEWND*)realloc(g_pfwFrames,sizeof(FRAMEWND)*(g_nFramesCount+1));
+
+ memset(&g_pfwFrames[g_nFramesCount],0,sizeof(FRAMEWND));
+ g_pfwFrames[g_nFramesCount].id = _iNextFrameId++;
+ g_pfwFrames[g_nFramesCount].align = clfrm->align;
+ g_pfwFrames[g_nFramesCount].hWnd = clfrm->hWnd;
+ g_pfwFrames[g_nFramesCount].height = clfrm->height;
+ g_pfwFrames[g_nFramesCount].TitleBar.hicon = clfrm->hIcon;
+ //Frames[nFramescount].TitleBar.BackColour;
+ g_pfwFrames[g_nFramesCount].floating = FALSE;
+ if (clfrm->Flags&F_NO_SUBCONTAINER || !g_CluiData.fLayered)
+ g_pfwFrames[g_nFramesCount].OwnerWindow = (HWND)-2;
+ else g_pfwFrames[g_nFramesCount].OwnerWindow = 0;
+
+ //override tbbtip
+ //clfrm->Flags |= F_SHOWTBTIP;
+ //
+ if (db_get_b(0,CLUIFrameModule,"RemoveAllBorders",0) == 1)
+ {
+ clfrm->Flags |= F_NOBORDER;
+ };
+ g_pfwFrames[g_nFramesCount].dwFlags = clfrm->Flags;
+
+ if (clfrm->name == NULL || ((clfrm->Flags&F_UNICODE) ? lstrlenW(clfrm->wname) : lstrlenA(clfrm->name)) == 0) {
+ g_pfwFrames[g_nFramesCount].Name = (LPTSTR)mir_alloc(255 * sizeof(TCHAR));
+ GetClassName(g_pfwFrames[g_nFramesCount].hWnd,g_pfwFrames[g_nFramesCount].Name,255);
+ }
+ else
+ {
+ g_pfwFrames[g_nFramesCount].Name = (clfrm->Flags&F_UNICODE) ? mir_u2t(clfrm->wname) : mir_a2t(clfrm->name);
+ }
+ g_pfwFrames[g_nFramesCount].szName = mir_t2a(g_pfwFrames[g_nFramesCount].Name);
+ if (IsBadCodePtr((FARPROC)clfrm->TBname) || clfrm->TBname == NULL
+ || ((clfrm->Flags&F_UNICODE) ? lstrlenW(clfrm->TBwname) : lstrlenA(clfrm->TBname)) == 0)
+ g_pfwFrames[g_nFramesCount].TitleBar.tbname = mir_tstrdup(g_pfwFrames[g_nFramesCount].Name);
+ else
+ g_pfwFrames[g_nFramesCount].TitleBar.tbname = (clfrm->Flags&F_UNICODE) ? mir_u2t(clfrm->TBwname) : mir_a2t(clfrm->TBname);
+ g_pfwFrames[g_nFramesCount].TitleBar.sztbname = mir_t2a(g_pfwFrames[g_nFramesCount].TitleBar.tbname);
+ g_pfwFrames[g_nFramesCount].needhide = FALSE;
+ g_pfwFrames[g_nFramesCount].TitleBar.ShowTitleBar = (clfrm->Flags&F_SHOWTB?TRUE:FALSE);
+ g_pfwFrames[g_nFramesCount].TitleBar.ShowTitleBarTip = (clfrm->Flags&F_SHOWTBTIP?TRUE:FALSE);
+
+ g_pfwFrames[g_nFramesCount].collapsed = (clfrm->Flags&F_UNCOLLAPSED)?FALSE:TRUE;
+
+
+ g_pfwFrames[g_nFramesCount].Locked = clfrm->Flags&F_LOCKED?TRUE:FALSE;
+ g_pfwFrames[g_nFramesCount].visible = clfrm->Flags&F_VISIBLE?TRUE:FALSE;
+
+ g_pfwFrames[g_nFramesCount].UseBorder = ((clfrm->Flags&F_NOBORDER) || g_CluiData.fLayered)?FALSE:TRUE;
+
+ //Frames[nFramescount].OwnerWindow = 0;
+
+
+
+ g_pfwFrames[g_nFramesCount].TitleBar.hwnd
+ = CreateWindow(CLUIFrameTitleBarClassName,g_pfwFrames[g_nFramesCount].Name,
+ (db_get_b(0,CLUIFrameModule,"RemoveAllTitleBarBorders",1)?0:WS_BORDER)
+
+ |WS_CHILD|WS_CLIPCHILDREN|
+ (g_pfwFrames[g_nFramesCount].TitleBar.ShowTitleBar?WS_VISIBLE:0)|
+ WS_CLIPCHILDREN,
+ 0,0,0,0,pcli->hwndContactList,NULL,g_hInst,NULL);
+ SetWindowLongPtr(g_pfwFrames[g_nFramesCount].TitleBar.hwnd,GWLP_USERDATA,g_pfwFrames[g_nFramesCount].id);
+
+
+ g_pfwFrames[g_nFramesCount].TitleBar.hwndTip
+ = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL,
+ WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ pcli->hwndContactList, NULL, g_hInst,
+ NULL);
+
+ SetWindowPos(g_pfwFrames[g_nFramesCount].TitleBar.hwndTip, HWND_TOPMOST,0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ {
+ TOOLINFOA ti;
+ int res;
+
+ ZeroMemory(&ti,sizeof(ti));
+ ti.cbSize = sizeof(ti);
+ ti.lpszText = "";
+ ti.hinst = g_hInst;
+ ti.uFlags = TTF_IDISHWND|TTF_SUBCLASS ;
+ ti.uId = (UINT_PTR)g_pfwFrames[g_nFramesCount].TitleBar.hwnd;
+ res = SendMessageA(g_pfwFrames[g_nFramesCount].TitleBar.hwndTip,TTM_ADDTOOL,(WPARAM)0,(LPARAM)&ti);
+ }
+
+ SendMessageA(g_pfwFrames[g_nFramesCount].TitleBar.hwndTip,TTM_ACTIVATE,(WPARAM)g_pfwFrames[g_nFramesCount].TitleBar.ShowTitleBarTip,0);
+
+ g_pfwFrames[g_nFramesCount].oldstyles = GetWindowLongPtr(g_pfwFrames[g_nFramesCount].hWnd,GWL_STYLE);
+ g_pfwFrames[g_nFramesCount].TitleBar.oldstyles = GetWindowLongPtr(g_pfwFrames[g_nFramesCount].TitleBar.hwnd,GWL_STYLE);
+ //Frames[nFramescount].FloatingPos.x =
+
+ retval = g_pfwFrames[g_nFramesCount].id;
+ g_pfwFrames[g_nFramesCount].order = g_nFramesCount+1;
+ g_nFramesCount++;
+
+
+ CLUIFramesLoadFrameSettings(id2pos(retval));
+ if (g_pfwFrames[g_nFramesCount-1].collapsed == FALSE)
+ {
+ g_pfwFrames[g_nFramesCount-1].height = 0;
+ }
+
+ // create frame
+
+
+ // else Frames[nFramescount-1].height = Frames[nFramescount-1].HeightWhenCollapsed;
+
+ style = GetWindowLongPtr(g_pfwFrames[g_nFramesCount-1].hWnd,GWL_STYLE);
+ style &= (~WS_BORDER);
+ style |= (((g_pfwFrames[g_nFramesCount-1].UseBorder) && !g_CluiData.fLayered)?WS_BORDER:0);
+ SetWindowLongPtr(g_pfwFrames[g_nFramesCount-1].hWnd,GWL_STYLE,style);
+ SetWindowLongPtr(g_pfwFrames[g_nFramesCount-1].TitleBar.hwnd,GWL_STYLE,style& ~(WS_VSCROLL | WS_HSCROLL));
+ SetWindowLongPtr(g_pfwFrames[g_nFramesCount-1].TitleBar.hwnd,GWL_STYLE,GetWindowLongPtr(g_pfwFrames[g_nFramesCount-1].TitleBar.hwnd,GWL_STYLE)&~(WS_VSCROLL|WS_HSCROLL));
+
+ if (g_pfwFrames[g_nFramesCount-1].order == 0){g_pfwFrames[g_nFramesCount-1].order = g_nFramesCount;};
+
+
+ //need to enlarge parent
+ {
+ RECT mainRect;
+ int mainHeight, minHeight;
+ GetWindowRect(pcli->hwndContactList,&mainRect);
+ mainHeight = mainRect.bottom-mainRect.top;
+ minHeight = CLUIFrames_GetTotalHeight();
+ if (mainHeight < minHeight)
+ {
+ BOOL Upward = FALSE;
+ Upward = !g_CluiData.fDocked && g_CluiData.fAutoSize && db_get_b(NULL,"CLUI","AutoSizeUpward",SETTING_AUTOSIZEUPWARD_DEFAULT);
+
+ if (Upward)
+ mainRect.top = mainRect.bottom-minHeight;
+ else
+ mainRect.bottom = mainRect.top+minHeight;
+ SetWindowPos(pcli->hwndContactList,NULL,mainRect.left,mainRect.top,mainRect.right-mainRect.left, mainRect.bottom-mainRect.top, SWP_NOZORDER|SWP_NOREDRAW|SWP_NOACTIVATE|SWP_NOSENDCHANGING);
+ }
+ GetWindowRect(pcli->hwndContactList,&mainRect);
+ mainHeight = mainRect.bottom-mainRect.top;
+ //if (mainHeight < minHeight)
+ // DebugBreak();
+ }
+ _nClientFrameId = eUnknownId;//recalc it
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,0);
+
+ if (g_pfwFrames[g_nFramesCount-1].floating)
+ {
+
+ g_pfwFrames[g_nFramesCount-1].floating = FALSE;
+ //SetWindowPos(Frames[nFramescount-1].hw
+ CLUIFrames_SetFrameFloat(retval,1);//lparam = 1 use stored width and height
+ }
+ else
+ CLUIFrames_SetFrameFloat(retval,2);
+
+ /** Remove */
+ //_ExtFramesSrv_AddFrame( wParam, lParam);
+
+ return retval;
+}
+
+static int _us_DoRemoveFrame(WPARAM wParam,LPARAM lParam)
+{
+ int pos;
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ pos = id2pos(wParam);
+
+ if (pos < 0 || pos>g_nFramesCount){return(-1);};
+
+ mir_free_and_nil(g_pfwFrames[pos].Name);
+ mir_free_and_nil(g_pfwFrames[pos].szName);
+ mir_free_and_nil(g_pfwFrames[pos].TitleBar.tbname);
+ mir_free_and_nil(g_pfwFrames[pos].TitleBar.sztbname);
+ mir_free_and_nil(g_pfwFrames[pos].TitleBar.tooltip);
+ mir_free_and_nil(g_pfwFrames[pos].TitleBar.sztooltip);
+ DestroyWindow(g_pfwFrames[pos].hWnd);
+ g_pfwFrames[pos].hWnd = (HWND)-1;
+ DestroyWindow(g_pfwFrames[pos].TitleBar.hwnd);
+ if (g_pfwFrames[pos].TitleBar.hwndTip)
+ DestroyWindow(g_pfwFrames[pos].TitleBar.hwndTip);
+ g_pfwFrames[pos].TitleBar.hwnd = (HWND)-1;
+ if (g_pfwFrames[pos].ContainerWnd && g_pfwFrames[pos].ContainerWnd != (HWND)-1) DestroyWindow(g_pfwFrames[pos].ContainerWnd);
+ g_pfwFrames[pos].ContainerWnd = (HWND)-1;
+ if (g_pfwFrames[pos].TitleBar.hmenu) DestroyMenu(g_pfwFrames[pos].TitleBar.hmenu);
+ g_pfwFrames[pos].PaintCallbackProc = NULL;
+ if (g_pfwFrames[pos].UpdateRgn) DeleteObject(g_pfwFrames[pos].UpdateRgn);
+
+ if (g_pfwFrames[pos].OwnerWindow != (HWND)-1
+ && g_pfwFrames[pos].OwnerWindow != (HWND)-2
+ && g_pfwFrames[pos].OwnerWindow != (HWND)0)
+ DestroyWindow(g_pfwFrames[pos].OwnerWindow);
+
+ g_pfwFrames[pos].OwnerWindow = NULL;
+ RemoveItemFromList(pos,&g_pfwFrames,&g_nFramesCount);
+
+ CLUI__cliInvalidateRect(pcli->hwndContactList,NULL,TRUE);
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,0);
+ CLUI__cliInvalidateRect(pcli->hwndContactList,NULL,TRUE);
+
+ return(0);
+};
+
+
+static int CLUIFramesForceUpdateTB(const FRAMEWND *Frame)
+{
+ if (Frame->TitleBar.hwnd != 0) RedrawWindow(Frame->TitleBar.hwnd,NULL,NULL,RDW_ALLCHILDREN|RDW_UPDATENOW|RDW_ERASE|RDW_INVALIDATE|RDW_FRAME);
+ //UpdateWindow(Frame->TitleBar.hwnd);
+ return 0;
+}
+
+static int CLUIFramesForceUpdateFrame(const FRAMEWND *Frame)
+{
+ if (Frame->hWnd != 0)
+ {
+ RedrawWindow(Frame->hWnd,NULL,NULL,RDW_UPDATENOW|RDW_FRAME|RDW_ERASE|RDW_INVALIDATE);
+ UpdateWindow(Frame->hWnd);
+ };
+ if (Frame->floating)
+ {
+ if (Frame->ContainerWnd != 0) RedrawWindow(Frame->ContainerWnd,NULL,NULL,RDW_UPDATENOW|RDW_ALLCHILDREN|RDW_ERASE|RDW_INVALIDATE|RDW_FRAME);
+ //UpdateWindow(Frame->ContainerWnd);
+ };
+ return 0;
+}
+
+static int CLUIFrameMoveResize(const FRAMEWND *Frame)
+{
+ // we need to show or hide the frame?
+ if (Frame->visible && (!Frame->needhide)) {
+ if (Frame->OwnerWindow != (HWND)-2 && Frame->OwnerWindow)
+ {
+ // CLUI_ShowWindowMod(Frame->OwnerWindow,SW_SHOW);
+ }
+ CLUI_ShowWindowMod(Frame->hWnd,SW_SHOW/*NOACTIVATE*/);
+ CLUI_ShowWindowMod(Frame->TitleBar.hwnd,Frame->TitleBar.ShowTitleBar == TRUE?SW_SHOW/*NOACTIVATE*/:SW_HIDE);
+ }
+ else {
+ if (Frame->OwnerWindow && Frame->OwnerWindow != (HWND)(-1) && Frame->OwnerWindow != (HWND)(-2))
+ {
+ CLUI_ShowWindowMod(Frame->OwnerWindow,SW_HIDE);
+ }
+ CLUI_ShowWindowMod(Frame->hWnd,SW_HIDE);
+ CLUI_ShowWindowMod(Frame->TitleBar.hwnd,SW_HIDE);
+ return(0);
+ }
+
+ if (Frame->OwnerWindow && Frame->OwnerWindow != (HWND)-2 )
+ {
+ RECT pr;
+ POINT Off = {0};
+
+ ClientToScreen(pcli->hwndContactList,&Off);
+ GetWindowRect(pcli->hwndContactList,&pr);
+
+ if ( Frame->visible && (!Frame->collapsed || Frame->wndSize.bottom-Frame->wndSize.top == 0))
+ {
+ ShowWindowAsync( Frame->OwnerWindow, SW_HIDE );
+ ShowWindowAsync( Frame->hWnd, SW_HIDE );
+ }
+
+ {
+ SetWindowPos(Frame->OwnerWindow,NULL,Frame->wndSize.left+Off.x,Frame->wndSize.top+Off.y,
+ Frame->wndSize.right-Frame->wndSize.left,
+ Frame->wndSize.bottom-Frame->wndSize.top,SWP_NOZORDER|SWP_NOACTIVATE ); //- -= -=
+
+ SetWindowPos(Frame->hWnd,NULL,0,0,
+ Frame->wndSize.right-Frame->wndSize.left,
+ Frame->wndSize.bottom-Frame->wndSize.top,SWP_NOZORDER|SWP_NOACTIVATE);
+ }
+ // set titlebar position
+ if (Frame->TitleBar.ShowTitleBar) {
+ SetWindowPos(Frame->TitleBar.hwnd,NULL,Frame->wndSize.left,Frame->wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar,
+ Frame->wndSize.right-Frame->wndSize.left,
+ g_nTitleBarHeight,SWP_NOZORDER|SWP_NOACTIVATE );
+ }
+ if ( Frame->visible && IsWindowVisible( pcli->hwndContactList ) && Frame->collapsed && Frame->wndSize.bottom-Frame->wndSize.top != 0 )
+ {
+ ShowWindow( Frame->OwnerWindow, SW_SHOW );
+ ShowWindow( Frame->hWnd, SW_SHOW );
+ }
+
+ }
+ else
+ {
+ // set frame position
+ SetWindowPos(Frame->hWnd,NULL,Frame->wndSize.left,Frame->wndSize.top,
+ Frame->wndSize.right-Frame->wndSize.left,
+ Frame->wndSize.bottom-Frame->wndSize.top,SWP_NOZORDER|SWP_NOACTIVATE);
+ // set titlebar position
+ if (Frame->TitleBar.ShowTitleBar) {
+ SetWindowPos(Frame->TitleBar.hwnd,NULL,Frame->wndSize.left,Frame->wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar,
+ Frame->wndSize.right-Frame->wndSize.left,
+ g_nTitleBarHeight,SWP_NOZORDER|SWP_NOACTIVATE);
+
+ }
+ }
+ // Sleep(0);
+ return 0;
+}
+
+static BOOL CLUIFramesFitInSize(void)
+{
+ int i;
+ int sumheight = 0;
+ int tbh = 0; // title bar height
+ int clientfrm;
+ clientfrm = CLUIFramesGetalClientFrame();
+ if (clientfrm != -1)
+ tbh = g_nTitleBarHeight*btoint(g_pfwFrames[clientfrm].TitleBar.ShowTitleBar);
+
+ for (i=0;i < g_nFramesCount;i++) {
+ if ((g_pfwFrames[i].align != alClient) && (!g_pfwFrames[i].floating) && (g_pfwFrames[i].visible) && (!g_pfwFrames[i].needhide)) {
+ sumheight += (g_pfwFrames[i].height)+(g_nTitleBarHeight*btoint(g_pfwFrames[i].TitleBar.ShowTitleBar))+2/*+btoint(Frames[i].UseBorder)*2*/;
+ if (sumheight>_nContactListHeight-tbh-2)
+ {
+ if ( !g_CluiData.fDocked && g_CluiData.fAutoSize)
+ {
+ return TRUE; //Can be required to enlarge
+ }
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+int CLUIFrames_GetTotalHeight()
+{
+ int i;
+ int sumheight = 0;
+ RECT border;
+ if (pcli->hwndContactList == NULL) return 0;
+
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if ((g_pfwFrames[i].visible) && (!g_pfwFrames[i].needhide) && (!g_pfwFrames[i].floating) && (pcli->hwndContactTree) && (g_pfwFrames[i].hWnd != pcli->hwndContactTree))
+ sumheight += (g_pfwFrames[i].height)+(g_nTitleBarHeight*btoint(g_pfwFrames[i].TitleBar.ShowTitleBar));
+ };
+
+ GetBorderSize(pcli->hwndContactList,&border);
+
+ //GetWindowRect(pcli->hwndContactList,&winrect);
+ //GetClientRect(pcli->hwndContactList,&clirect);
+ // clirect.bottom -= clirect.top;
+ // clirect.bottom += border.top+border.bottom;
+ //allbord = (winrect.bottom-winrect.top)-(clirect.bottom-clirect.top);
+
+ //TODO minsize
+ sumheight += g_CluiData.TopClientMargin;
+ sumheight += g_CluiData.BottomClientMargin;
+ return max(db_get_w(NULL,"CLUI","MinHeight",SETTING_MINHEIGTH_DEFAULT),
+ (sumheight+border.top+border.bottom));
+}
+
+int CLUIFramesGetMinHeight()
+{
+ int i,tbh,clientfrm,sumheight = 0;
+ RECT border;
+ int allbord = 0;
+ if (pcli->hwndContactList == NULL) return 0;
+
+
+ // search for alClient frame and get the titlebar's height
+ tbh = 0;
+ clientfrm = CLUIFramesGetalClientFrame();
+ if (clientfrm != -1)
+ tbh = g_nTitleBarHeight*btoint(g_pfwFrames[clientfrm].TitleBar.ShowTitleBar);
+
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if ((g_pfwFrames[i].align != alClient) && (g_pfwFrames[i].visible) && (!g_pfwFrames[i].needhide) && (!g_pfwFrames[i].floating))
+ {
+ RECT wsize;
+
+ GetWindowRect(g_pfwFrames[i].hWnd,&wsize);
+ sumheight += (wsize.bottom-wsize.top)+(g_nTitleBarHeight*btoint(g_pfwFrames[i].TitleBar.ShowTitleBar));
+ }
+ };
+
+ GetBorderSize(pcli->hwndContactList,&border);
+
+ //GetWindowRect(pcli->hwndContactList,&winrect);
+ //GetClientRect(pcli->hwndContactList,&clirect);
+ // clirect.bottom -= clirect.top;
+ // clirect.bottom += border.top+border.bottom;
+ //allbord = (winrect.bottom-winrect.top)-(clirect.bottom-clirect.top);
+
+ //TODO minsize
+ sumheight += g_CluiData.TopClientMargin;
+ sumheight += g_CluiData.BottomClientMargin;
+ return max(db_get_w(NULL,"CLUI","MinHeight",SETTING_MINHEIGTH_DEFAULT),
+ (sumheight+border.top+border.bottom+allbord+tbh) );
+}
+
+
+
+
+static int CLUIFramesResizeFrames(const RECT newsize)
+{
+ int sumheight = 9999999,newheight;
+ int prevframe,prevframebottomline;
+ int tbh,curfrmtbh;
+ int drawitems;
+ int clientfrm;
+ int i,j;
+ int sepw = GapBetweenFrames;
+ int topBorder = newsize.top;
+ int minHeight = CLUIFrames_GetTotalHeight();
+ SortData *sdarray;
+
+
+ g_CluiData.nGapBetweenTitlebar = (int)db_get_dw(NULL,"CLUIFrames","GapBetweenTitleBar",SETTING_GAPTITLEBAR_DEFAULT);
+ GapBetweenFrames = db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT);
+ sepw = GapBetweenFrames;
+
+ if (g_nFramesCount < 1) return 0;
+ newheight = newsize.bottom-newsize.top;
+
+ // search for alClient frame and get the titlebar's height
+ tbh = 0;
+ clientfrm = CLUIFramesGetalClientFrame();
+ if (clientfrm != -1)
+ tbh = (g_nTitleBarHeight+g_CluiData.nGapBetweenTitlebar)*btoint(g_pfwFrames[clientfrm].TitleBar.ShowTitleBar);
+
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if ( !g_pfwFrames[i].floating)
+ {
+ g_pfwFrames[i].needhide = FALSE;
+ g_pfwFrames[i].wndSize.left = newsize.left;
+ g_pfwFrames[i].wndSize.right = newsize.right;
+
+ };
+ };
+ {
+ //sorting stuff
+ sdarray = (SortData*)malloc(sizeof(SortData)*g_nFramesCount);
+ if (sdarray == NULL){return(-1);};
+ for (i=0;i < g_nFramesCount;i++)
+ {sdarray[i].order = g_pfwFrames[i].order;
+ sdarray[i].realpos = i;
+ };
+ qsort(sdarray,g_nFramesCount,sizeof(SortData),sortfunc);
+
+ }
+
+ drawitems = g_nFramesCount;
+
+ while(sumheight>(newheight-tbh) && drawitems>0) {
+ sumheight = 0;
+ drawitems = 0;
+ for (i=0;i < g_nFramesCount;i++) {
+ if (((g_pfwFrames[i].align != alClient)) && (!g_pfwFrames[i].floating) && (g_pfwFrames[i].visible) && (!g_pfwFrames[i].needhide)) {
+ drawitems++;
+ curfrmtbh = (g_nTitleBarHeight+g_CluiData.nGapBetweenTitlebar)*btoint(g_pfwFrames[i].TitleBar.ShowTitleBar);
+ sumheight += (g_pfwFrames[i].height)+curfrmtbh+(i > 0 ? sepw : 0)+((g_pfwFrames[i].UseBorder && !g_CluiData.fLayered)?2:0);
+ if (sumheight>newheight-tbh) {
+ sumheight -= (g_pfwFrames[i].height)+curfrmtbh + (i > 0 ? sepw : 0);
+ g_pfwFrames[i].needhide = !g_CluiData.fDocked && g_CluiData.fAutoSize?FALSE:TRUE;
+ drawitems--;
+ break;
+ }
+ }
+ }
+ }
+
+ prevframe = -1;
+ prevframebottomline = topBorder;
+ for (j = 0;j < g_nFramesCount;j++) {
+ //move all alTop frames
+ i = sdarray[j].realpos;
+ if ((!g_pfwFrames[i].needhide) && (!g_pfwFrames[i].floating) && (g_pfwFrames[i].visible) && (g_pfwFrames[i].align == alTop)) {
+ curfrmtbh = (g_nTitleBarHeight+g_CluiData.nGapBetweenTitlebar)*btoint(g_pfwFrames[i].TitleBar.ShowTitleBar);
+ g_pfwFrames[i].wndSize.top = prevframebottomline+(i > 0 ? sepw : 0)+(curfrmtbh);
+ g_pfwFrames[i].wndSize.bottom = g_pfwFrames[i].height+g_pfwFrames[i].wndSize.top+((g_pfwFrames[i].UseBorder && !g_CluiData.fLayered)?2:0);
+ g_pfwFrames[i].prevvisframe = prevframe;
+ prevframe = i;
+ prevframebottomline = g_pfwFrames[i].wndSize.bottom;
+ if (prevframebottomline>newheight){
+ //prevframebottomline -= Frames[i].height+(curfrmtbh+1);
+ //Frames[i].needhide = TRUE;
+ }
+ }
+ }
+
+ if (sumheight < newheight) {
+ for (j = 0;j < g_nFramesCount;j++) {
+ //move alClient frame
+ i = sdarray[j].realpos;
+ if ((!g_pfwFrames[i].needhide) && (!g_pfwFrames[i].floating) && (g_pfwFrames[i].visible) && (g_pfwFrames[i].align == alClient)) {
+ int oldh;
+ g_pfwFrames[i].wndSize.top = prevframebottomline+(j > 0 ? sepw : 0)+(tbh);
+ g_pfwFrames[i].wndSize.bottom = g_pfwFrames[i].wndSize.top+newheight-sumheight-tbh-(j > 0 ? sepw : 0);
+
+ oldh = g_pfwFrames[i].height;
+ g_pfwFrames[i].height = g_pfwFrames[i].wndSize.bottom-g_pfwFrames[i].wndSize.top;
+ g_pfwFrames[i].prevvisframe = prevframe;
+ prevframe = i;
+ prevframebottomline = g_pfwFrames[i].wndSize.bottom;
+ if (prevframebottomline>newheight) {
+ //prevframebottomline -= Frames[i].height+(tbh+1);
+ //Frames[i].needhide = TRUE;
+ }
+ break;
+ }
+ }
+ }
+
+ //newheight
+ prevframebottomline = newheight+sepw+topBorder;
+ //prevframe = -1;
+ for (j = g_nFramesCount-1;j >= 0;j--) {
+ //move all alBottom frames
+ i = sdarray[j].realpos;
+ if ((g_pfwFrames[i].visible) && (!g_pfwFrames[i].floating) && (!g_pfwFrames[i].needhide) && (g_pfwFrames[i].align == alBottom)) {
+ curfrmtbh = (g_nTitleBarHeight+g_CluiData.nGapBetweenTitlebar)*btoint(g_pfwFrames[i].TitleBar.ShowTitleBar);
+
+ g_pfwFrames[i].wndSize.bottom = prevframebottomline-(j > 0 ? sepw : 0);
+ g_pfwFrames[i].wndSize.top = g_pfwFrames[i].wndSize.bottom-g_pfwFrames[i].height-((g_pfwFrames[i].UseBorder && !g_CluiData.fLayered)?2:0);
+ g_pfwFrames[i].prevvisframe = prevframe;
+ prevframe = i;
+ prevframebottomline = g_pfwFrames[i].wndSize.top/*-1*/-curfrmtbh;
+ if (prevframebottomline>newheight) {
+
+ }
+ }
+ }
+ for (i=0;i < g_nFramesCount;i++)
+ if (g_pfwFrames[i].TitleBar.ShowTitleBar)
+ SetRect(&g_pfwFrames[i].TitleBar.wndSize,g_pfwFrames[i].wndSize.left,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar,g_pfwFrames[i].wndSize.right,g_pfwFrames[i].wndSize.top-g_CluiData.nGapBetweenTitlebar);
+ if (sdarray != NULL){free(sdarray);sdarray = NULL;};
+
+
+
+ return 0;
+}
+
+static int SizeMoveNewSizes()
+{
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ {
+
+ if (g_pfwFrames[i].floating){
+ CLUIFrameResizeFloatingFrame(i);
+ }else
+ {
+ CLUIFrameMoveResize(&g_pfwFrames[i]);
+ };
+ }
+ return 0;
+}
+
+
+static int CLUIFramesResize(RECT newsize)
+{
+ CLUIFramesResizeFrames(newsize);
+ SizeMoveNewSizes();
+ return 0;
+}
+int CLUIFrames_ApplyNewSizes(int mode)
+{
+ int i;
+ g_CluiData.mutexPreventDockMoving = 0;
+ for (i=0;i < g_nFramesCount;i++) {
+ if ((mode == 1 && g_pfwFrames[i].OwnerWindow != (HWND)-2 && g_pfwFrames[i].OwnerWindow) ||
+ (mode == 2 && g_pfwFrames[i].OwnerWindow == (HWND)-2) ||
+ (mode == 3))
+ if (g_pfwFrames[i].floating){
+ CLUIFrameResizeFloatingFrame(i);
+ }else
+ {
+ CLUIFrameMoveResize(&g_pfwFrames[i]);
+ };
+ }
+ if (IsWindowVisible(pcli->hwndContactList))
+ {
+ ske_DrawNonFramedObjects(1,0);
+ CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,0,0);
+ }
+ g_CluiData.mutexPreventDockMoving = 1;
+ return 0;
+}
+
+static int _us_DoUpdateFrame(WPARAM wParam,LPARAM lParam)
+{
+ if (_fCluiFramesModuleNotStarted) return -1;
+ if (wParam == -1) { CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0); return 0;}
+ if (lParam&FU_FMPOS) CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,1);
+
+ int pos = id2pos( wParam );
+ if ( pos < 0 || pos >= g_nFramesCount ) { return -1; }
+ if ( lParam&FU_TBREDRAW ) CLUIFramesForceUpdateTB( &g_pfwFrames[pos] );
+ if ( lParam&FU_FMREDRAW ) CLUIFramesForceUpdateFrame( &g_pfwFrames[pos] );
+ return 0;
+}
+
+int CLUIFrames_OnClistResize_mod(WPARAM wParam,LPARAM mode)
+{
+ RECT nRect;
+ int tick;
+ GapBetweenFrames = db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT);
+ g_CluiData.nGapBetweenTitlebar = db_get_dw(NULL,"CLUIFrames","GapBetweenTitleBar",SETTING_GAPTITLEBAR_DEFAULT);
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ GetClientRect(pcli->hwndContactList,&nRect);
+
+ nRect.left += g_CluiData.LeftClientMargin;
+ nRect.right -= g_CluiData.RightClientMargin;
+ nRect.top += g_CluiData.TopClientMargin;
+ nRect.bottom -= g_CluiData.BottomClientMargin;
+ // g_CluiData.mutexPreventDockMoving = 0;
+ tick = GetTickCount();
+ CLUIFramesResize(nRect);
+ if (mode == 0) CLUIFrames_ApplyNewSizes(3);
+
+ tick = GetTickCount()-tick;
+
+ Sleep(0);
+
+ //dont save to database too many times
+ if (GetTickCount()-_dwLastStoreTick>1000){ CLUIFramesStoreAllFrames();_dwLastStoreTick = GetTickCount();};
+
+ return 0;
+}
+
+int SizeFramesByWindowRect(RECT *r, HDWP * PosBatch, int mode)
+{
+ RECT nRect;
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ g_CluiData.nGapBetweenTitlebar = (int)db_get_dw(NULL,"CLUIFrames","GapBetweenTitleBar",SETTING_GAPTITLEBAR_DEFAULT);
+ GapBetweenFrames = db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT);
+ nRect.left = 0;
+ nRect.top = 0;
+ nRect.right = r->right-r->left;
+ nRect.bottom = r->bottom-r->top;
+ nRect.left += g_CluiData.LeftClientMargin;
+ nRect.right -= g_CluiData.RightClientMargin;
+ nRect.top += g_CluiData.TopClientMargin;
+ nRect.bottom -= g_CluiData.BottomClientMargin;
+ CLUIFramesResizeFrames(nRect);
+ {
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ int dx;
+ int dy;
+ dx = 0;//rcNewWindowRect.left-rcOldWindowRect.left;
+ dy = 0;//_window_rect.top-rcOldWindowRect.top;
+ if ( !g_pfwFrames[i].floating)
+ {
+ if (g_pfwFrames[i].visible && !g_pfwFrames[i].needhide && !IsWindowVisible(g_pfwFrames[i].hWnd))
+ {
+ ShowWindow(g_pfwFrames[i].hWnd,SW_SHOW);
+ if (g_pfwFrames[i].TitleBar.ShowTitleBar) ShowWindow(g_pfwFrames[i].TitleBar.hwnd,SW_SHOW);
+ }
+ if (g_pfwFrames[i].OwnerWindow && (INT_PTR)(g_pfwFrames[i].OwnerWindow) != -2 )
+ {
+ if ( !(mode&2))
+ {
+ HWND hwnd;
+ hwnd = GetParent(g_pfwFrames[i].OwnerWindow);
+ *PosBatch = DeferWindowPos(*PosBatch,g_pfwFrames[i].OwnerWindow,NULL,g_pfwFrames[i].wndSize.left+r->left,g_pfwFrames[i].wndSize.top+r->top,
+ g_pfwFrames[i].wndSize.right-g_pfwFrames[i].wndSize.left, g_pfwFrames[i].wndSize.bottom-g_pfwFrames[i].wndSize.top,SWP_NOZORDER|SWP_NOACTIVATE);
+ SetWindowPos(g_pfwFrames[i].hWnd,NULL,0,0,
+ g_pfwFrames[i].wndSize.right-g_pfwFrames[i].wndSize.left, g_pfwFrames[i].wndSize.bottom-g_pfwFrames[i].wndSize.top,SWP_NOZORDER|SWP_NOACTIVATE/*|SWP_NOSENDCHANGING*/);
+ }
+ //Frame
+ if (g_pfwFrames[i].TitleBar.ShowTitleBar)
+ {
+ SetWindowPos(g_pfwFrames[i].TitleBar.hwnd,NULL,g_pfwFrames[i].wndSize.left+dx,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar+dy,
+ g_pfwFrames[i].wndSize.right-g_pfwFrames[i].wndSize.left,g_nTitleBarHeight,SWP_NOZORDER|SWP_NOACTIVATE );
+ SetRect(&g_pfwFrames[i].TitleBar.wndSize,g_pfwFrames[i].wndSize.left,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar,g_pfwFrames[i].wndSize.right,g_pfwFrames[i].wndSize.top-g_CluiData.nGapBetweenTitlebar);
+ UpdateWindow(g_pfwFrames[i].TitleBar.hwnd);
+ }
+ }
+ else
+ {
+ if (1)
+ {
+ int res = 0;
+ // set frame position
+ res = SetWindowPos(g_pfwFrames[i].hWnd,NULL,g_pfwFrames[i].wndSize.left+dx,g_pfwFrames[i].wndSize.top+dy,
+ g_pfwFrames[i].wndSize.right-g_pfwFrames[i].wndSize.left,
+ g_pfwFrames[i].wndSize.bottom-g_pfwFrames[i].wndSize.top,SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSENDCHANGING);
+ }
+ if (1)
+ {
+ // set titlebar position
+ if (g_pfwFrames[i].TitleBar.ShowTitleBar)
+ {
+ SetWindowPos(g_pfwFrames[i].TitleBar.hwnd,NULL,g_pfwFrames[i].wndSize.left+dx,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar+dy,
+ g_pfwFrames[i].wndSize.right-g_pfwFrames[i].wndSize.left,g_nTitleBarHeight,SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSENDCHANGING );
+ SetRect(&g_pfwFrames[i].TitleBar.wndSize,g_pfwFrames[i].wndSize.left,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar,g_pfwFrames[i].wndSize.right,g_pfwFrames[i].wndSize.top-g_CluiData.nGapBetweenTitlebar);
+
+ }
+ }
+ UpdateWindow(g_pfwFrames[i].hWnd);
+ if (g_pfwFrames[i].TitleBar.ShowTitleBar) UpdateWindow(g_pfwFrames[i].TitleBar.hwnd);
+ };
+ }
+
+ }
+ if (GetTickCount()-_dwLastStoreTick>1000)
+ {
+ CLUIFramesStoreAllFrames();
+ _dwLastStoreTick = GetTickCount();
+ };
+ }
+ return 0;
+}
+
+int CheckFramesPos(RECT *wr)
+{
+ //CALLED only FROM MainWindow procedure at CLUI.c
+ int i;
+ if (_fCluiFramesModuleNotStarted) return -1;
+ g_CluiData.nGapBetweenTitlebar = (int)db_get_dw(NULL,"CLUIFrames","GapBetweenTitleBar",SETTING_GAPTITLEBAR_DEFAULT);
+ GapBetweenFrames = db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT);
+
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ int dx;
+ int dy;
+ dx = 0;//rcNewWindowRect.left-rcOldWindowRect.left;
+ dy = 0;//_window_rect.top-rcOldWindowRect.top;
+ if ( !g_pfwFrames[i].floating && g_pfwFrames[i].visible)
+ {
+ if ( !(g_pfwFrames[i].OwnerWindow && (INT_PTR)(g_pfwFrames[i].OwnerWindow) != -2))
+ {
+ RECT r;
+ GetWindowRect(g_pfwFrames[i].hWnd,&r);
+ if (r.top-wr->top != g_pfwFrames[i].wndSize.top || r.left-wr->left != g_pfwFrames[i].wndSize.left)
+ SetWindowPos(g_pfwFrames[i].hWnd,NULL,g_pfwFrames[i].wndSize.left, g_pfwFrames[i].wndSize.top,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
+ }
+ if (g_pfwFrames[i].TitleBar.ShowTitleBar)
+ {
+ RECT r;
+ GetWindowRect(g_pfwFrames[i].TitleBar.hwnd,&r);
+ if (r.top-wr->top != g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar || r.left-wr->left != g_pfwFrames[i].wndSize.left)
+ {
+ SetWindowPos(g_pfwFrames[i].TitleBar.hwnd,NULL,g_pfwFrames[i].wndSize.left+dx,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar+dy,
+ g_pfwFrames[i].wndSize.right-g_pfwFrames[i].wndSize.left,g_nTitleBarHeight,SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE);
+ SetRect(&g_pfwFrames[i].TitleBar.wndSize,g_pfwFrames[i].wndSize.left,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar,g_pfwFrames[i].wndSize.right,g_pfwFrames[i].wndSize.top-g_CluiData.nGapBetweenTitlebar);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+int CLUIFramesOnClistResize(WPARAM wParam,LPARAM lParam)
+{
+ RECT nRect;
+ int tick;
+ GapBetweenFrames = db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT);
+ g_CluiData.nGapBetweenTitlebar = db_get_dw(NULL,"CLUIFrames","GapBetweenTitleBar",SETTING_GAPTITLEBAR_DEFAULT);
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ //need to enlarge parent
+ {
+ RECT mainRect;
+ int mainHeight, minHeight;
+ GetWindowRect(pcli->hwndContactList,&mainRect);
+ mainHeight = mainRect.bottom-mainRect.top;
+ minHeight = CLUIFrames_GetTotalHeight();
+ if (mainHeight < minHeight)
+ {
+ BOOL Upward = FALSE;
+ Upward = !g_CluiData.fDocked && g_CluiData.fAutoSize && db_get_b(NULL,"CLUI","AutoSizeUpward",SETTING_AUTOSIZEUPWARD_DEFAULT);
+
+ if (Upward)
+ mainRect.top = mainRect.bottom-minHeight;
+ else
+ mainRect.bottom = mainRect.top+minHeight;
+ SetWindowPos(pcli->hwndContactList,NULL,mainRect.left,mainRect.top,mainRect.right-mainRect.left, mainRect.bottom-mainRect.top, SWP_NOZORDER|SWP_NOREDRAW|SWP_NOACTIVATE|SWP_NOSENDCHANGING);
+ }
+ GetWindowRect(pcli->hwndContactList,&mainRect);
+ mainHeight = mainRect.bottom-mainRect.top;
+ }
+ GetClientRect(pcli->hwndContactList,&nRect);
+ //$$$ Fixed borders
+ if (lParam && lParam != 1 && lParam != 2)
+ {
+ RECT oldRect;
+ POINT pt;
+ RECT * newRect = (RECT *)lParam;
+ int dl,dt,dr,db;
+ GetWindowRect((HWND)wParam,&oldRect);
+ pt.x = nRect.left;
+ pt.y = nRect.top;
+ ClientToScreen(pcli->hwndContactList,&pt);
+ dl = pt.x-oldRect.left;
+ dt = pt.y-oldRect.top;
+ dr = (oldRect.right-oldRect.left)-(nRect.right-nRect.left)-dl;
+ db = (oldRect.bottom-oldRect.top)-(nRect.bottom-nRect.top)-dt;
+ nRect.left = newRect->left+dl;
+ nRect.top = newRect->top+dt;
+ nRect.bottom = newRect->bottom-db;
+ nRect.right = newRect->right-dr;
+ }
+
+
+ //if (DBGetContactSettingByte(NULL,"CLUI","ShowSBar",SETTING_SHOWSBAR_DEFAULT))GetWindowRect(pcli->hwndStatus,&rcStatus);
+ //else rcStatus.top = rcStatus.bottom = 0;
+ // nRect.top--;
+ /* $$$ rcStatus.top = rcStatus.bottom = 0;
+
+
+ nRect.bottom -= nRect.top;
+ nRect.bottom -= (rcStatus.bottom-rcStatus.top);
+ nRect.right -= nRect.left;
+ nRect.left = 0;
+ nRect.top = 0;
+ ContactListHeight = nRect.bottom; $$$*/
+
+ nRect.left += g_CluiData.LeftClientMargin;
+ nRect.right -= g_CluiData.RightClientMargin;
+ nRect.top += g_CluiData.TopClientMargin;
+ nRect.bottom -= g_CluiData.BottomClientMargin;
+
+ if (nRect.bottom < nRect.top)
+ nRect.bottom = nRect.top;
+ _nContactListHeight = nRect.bottom-nRect.top; //$$
+
+ tick = GetTickCount();
+
+
+ CLUIFramesResize(nRect);
+
+ CLUIFrames_ApplyNewSizes(2);
+ CLUIFrames_ApplyNewSizes(1);
+
+ //resizing = FALSE;
+
+ tick = GetTickCount()-tick;
+
+ if (pcli->hwndContactList != 0) CLUI__cliInvalidateRect(pcli->hwndContactList,NULL,TRUE);
+ if (pcli->hwndContactList != 0) UpdateWindow(pcli->hwndContactList);
+
+ if (lParam == 2) RedrawWindow(pcli->hwndContactList,NULL,NULL,RDW_UPDATENOW|RDW_ALLCHILDREN|RDW_ERASE|RDW_INVALIDATE);
+
+
+ Sleep(0);
+
+ //dont save to database too many times
+ if (GetTickCount()-_dwLastStoreTick>1000){ CLUIFramesStoreAllFrames();_dwLastStoreTick = GetTickCount();};
+
+ return 0;
+}
+
+int OnFrameTitleBarBackgroundChange(WPARAM wParam,LPARAM lParam)
+{
+ if (MirandaExiting()) return 0;
+ {
+ DBVARIANT dbv = {0};
+
+ AlignCOLLIconToLeft = db_get_b(NULL,"FrameTitleBar","AlignCOLLIconToLeft",CLCDEFAULT_COLLICONTOLEFT);
+
+ bkColour = sttGetColor("FrameTitleBar","BkColour",CLCDEFAULT_BKCOLOUR);
+ bkUseWinColours = db_get_b(NULL,"FrameTitleBar","UseWinColours",CLCDEFAULT_USEWINDOWSCOLOURS);
+ SelBkColour = sttGetColor("FrameTitleBar","TextColour",CLCDEFAULT_TEXTCOLOUR);
+ if (hBmpBackground) {DeleteObject(hBmpBackground); hBmpBackground = NULL;}
+ if (g_CluiData.fDisableSkinEngine)
+ {
+ if (db_get_b(NULL,"FrameTitleBar","UseBitmap",CLCDEFAULT_USEBITMAP)) {
+ if ( !DBGetContactSettingString(NULL,"FrameTitleBar","BkBitmap",&dbv)) {
+ hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ }
+ backgroundBmpUse = db_get_w(NULL,"FrameTitleBar","BkBmpUse",CLCDEFAULT_BKBMPUSE);
+ }
+ };
+
+ CLUI__cliInvalidateRect( pcli->hwndContactList, 0, 0 );
+
+ RedrawWindow(pcli->hwndContactList,NULL,NULL,RDW_UPDATENOW|RDW_ALLCHILDREN|RDW_ERASE|RDW_INVALIDATE);
+
+ return 0;
+}
+
+void DrawBackGround(HWND hwnd,HDC mhdc, HBITMAP hBmpBackground, COLORREF bkColour, DWORD backgroundBmpUse )
+{
+ HDC hdcMem,hdc;
+ RECT clRect,*rcPaint;
+
+ int yScroll = 0;
+ int y;
+ PAINTSTRUCT paintst = {0};
+ HBITMAP hBmpOsb,hOldBmp;
+ DWORD style = GetWindowLongPtr(hwnd,GWL_STYLE);
+ int grey = 0;
+ HFONT oFont;
+ HBRUSH hBrushAlternateGrey = NULL;
+
+ HFONT hFont;
+
+ //InvalidateRect(hwnd,0,FALSE);
+
+ hFont = (HFONT)SendMessage(hwnd,WM_GETFONT,0,0);
+
+ if (mhdc)
+ {
+ hdc = mhdc;
+ rcPaint = NULL;
+ }
+ else
+ {
+ hdc = BeginPaint(hwnd,&paintst);
+ rcPaint = &(paintst.rcPaint);
+ }
+
+ GetClientRect(hwnd,&clRect);
+ if (rcPaint == NULL) rcPaint = &clRect;
+ if (rcPaint->right-rcPaint->left == 0 || rcPaint->top-rcPaint->bottom == 0) rcPaint = &clRect;
+ y = -yScroll;
+ hdcMem = CreateCompatibleDC(hdc);
+ hBmpOsb = CreateBitmap(clRect.right,clRect.bottom,1,GetDeviceCaps(hdc,BITSPIXEL),NULL);
+ hOldBmp = (HBITMAP)SelectObject(hdcMem,hBmpOsb);
+ oFont = (HFONT)SelectObject(hdcMem,hFont);
+ SetBkMode(hdcMem,TRANSPARENT);
+ SetStretchBltMode(hdcMem,HALFTONE);
+ { HBRUSH hBrush;
+
+ hBrush = CreateSolidBrush(bkColour);
+ FillRect(hdcMem,rcPaint,hBrush);
+ DeleteObject(hBrush);
+ if (hBmpBackground) {
+ BITMAP bmp;
+ HDC hdcBmp;
+ int x,y;
+ int maxx,maxy;
+ int destw,desth;
+
+ GetObject(hBmpBackground,sizeof(bmp),&bmp);
+ hdcBmp = CreateCompatibleDC(hdcMem);
+ SelectObject(hdcBmp,hBmpBackground);
+ y = backgroundBmpUse&CLBF_SCROLL?-yScroll:0;
+ maxx = backgroundBmpUse&CLBF_TILEH?clRect.right:1;
+ maxy = backgroundBmpUse&CLBF_TILEV?maxy = rcPaint->bottom:y+1;
+ switch(backgroundBmpUse&CLBM_TYPE) {
+ case CLB_STRETCH:
+ if (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 (backgroundBmpUse&CLBF_PROPORTIONAL) {
+ destw = clRect.right;
+ desth = destw*bmp.bmHeight/bmp.bmWidth;
+ }
+ else {
+ destw = clRect.right;
+ desth = bmp.bmHeight;
+ }
+ break;
+ case CLB_STRETCHV:
+ if (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;
+ }
+ desth = clRect.bottom -clRect.top;
+ 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);
+ }
+ }
+
+ {
+
+ BitBlt(hdc,rcPaint->left,rcPaint->top,rcPaint->right-rcPaint->left,rcPaint->bottom-rcPaint->top,hdcMem,rcPaint->left,rcPaint->top,SRCCOPY);
+
+ SelectObject(hdcMem,hOldBmp);
+ SelectObject(hdcMem,oFont);
+ DeleteObject(hBmpOsb);
+ DeleteDC(hdcMem);
+ paintst.fErase = FALSE;
+ //DeleteObject(hFont);
+ if ( !mhdc)
+ {
+ EndPaint(hwnd,&paintst);
+ }
+ }
+}
+
+
+int DrawTitleBar(HDC hdcMem2,RECT * rect,int Frameid)
+{
+ int pos;
+ BOOL bThemed = FALSE;
+ HDC hdcMem;
+ HFONT hoTTBFont;
+ RECT rc = *rect;
+ HBRUSH hBack,hoBrush;
+ HBITMAP b1 = NULL,b2 = NULL;
+ hdcMem = CreateCompatibleDC(hdcMem2);
+
+ SetBkMode(hdcMem,TRANSPARENT);
+ hoTTBFont = (HFONT)SelectObject(hdcMem,_hTitleBarFont);
+ ske_ResetTextEffect(hdcMem);
+ ske_ResetTextEffect(hdcMem2);
+ hBack = GetSysColorBrush(COLOR_3DFACE);
+ hoBrush = (HBRUSH)SelectObject(hdcMem,hBack);
+
+ pos = id2pos(Frameid);
+
+ if (pos >= 0 && pos < g_nFramesCount)
+ {
+ GetClientRect(g_pfwFrames[pos].TitleBar.hwnd,&rc);
+ if (g_pfwFrames[pos].floating)
+ {
+
+ rc.bottom = rc.top+g_nTitleBarHeight;
+ g_pfwFrames[pos].TitleBar.wndSize = rc;
+ }
+ else
+ {
+ g_pfwFrames[pos].TitleBar.wndSize = rc;
+ }
+ b1 = ske_CreateDIB32(rc.right-rc.left,rc.bottom-rc.top);
+ b2 = (HBITMAP)SelectObject(hdcMem,b1);
+ if ( g_pfwFrames[pos].floating && !g_CluiData.fDisableSkinEngine)
+ {
+ FillRect(hdcMem,&rc,hBack);
+ //SelectObject(hdcMem,hoBrush);
+ SkinDrawGlyph(hdcMem,&rc,&rc,"Main,ID=FrameCaption");
+ }
+ else
+ {
+ if (g_CluiData.fDisableSkinEngine)
+ {
+ if ( !hBmpBackground && bkUseWinColours && xpt_IsThemed(_hFrameTitleTheme))
+ {
+ int state = CS_ACTIVE;
+ // if (GetForegroundWindow() != pcli->hwndContactList) state = CS_INACTIVE;
+ xpt_DrawThemeBackground(_hFrameTitleTheme,hdcMem, WP_SMALLCAPTION, state, &rc,&rc);
+ bThemed = TRUE;
+ }
+ else
+ DrawBackGround(g_pfwFrames[pos].TitleBar.hwnd,hdcMem, hBmpBackground, bkColour, backgroundBmpUse);
+ }
+ else if ( !g_CluiData.fLayered)
+ {
+ ske_BltBackImage(g_pfwFrames[pos].TitleBar.hwnd,hdcMem,&rc);
+ }
+ else BitBlt(hdcMem,0,0,rc.right-rc.left,rc.bottom-rc.top,hdcMem2,rect->left,rect->top,SRCCOPY);
+ SkinDrawGlyph(hdcMem,&rc,&rc,"Main,ID=FrameCaption");
+ }
+ if (bThemed)
+ SetTextColor(hdcMem,GetSysColor(COLOR_CAPTIONTEXT ));
+ else
+ SetTextColor(hdcMem,SelBkColour);
+ {
+ RECT textrc = rc;
+ if ( !AlignCOLLIconToLeft)
+ {
+
+ if (g_pfwFrames[pos].TitleBar.hicon != NULL)
+ {
+ mod_DrawIconEx_helper(hdcMem,rc.left +2,rc.top+((g_nTitleBarHeight>>1)-(GetSystemMetrics(SM_CYSMICON)>>1)),g_pfwFrames[pos].TitleBar.hicon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL);
+ textrc.left += GetSystemMetrics(SM_CXSMICON)+4;
+ textrc.top += 2;
+ }
+ else
+ {
+ textrc.left += 2;
+ textrc.top += 2;
+ }
+
+ }
+ else
+ {
+ textrc.left += GetSystemMetrics(SM_CXSMICON)+2;
+ textrc.top += 2;
+ }
+ ske_TextOut(hdcMem,textrc.left,textrc.top,g_pfwFrames[pos].TitleBar.tbname,lstrlen(g_pfwFrames[pos].TitleBar.tbname));
+
+ }
+ if ( !AlignCOLLIconToLeft)
+ {
+ mod_DrawIconEx_helper(hdcMem,g_pfwFrames[pos].TitleBar.wndSize.right-GetSystemMetrics(SM_CXSMICON)-2,rc.top+((g_nTitleBarHeight>>1)-(GetSystemMetrics(SM_CXSMICON)>>1)),g_pfwFrames[pos].collapsed?LoadSkinnedIcon(SKINICON_OTHER_GROUPOPEN):LoadSkinnedIcon(SKINICON_OTHER_GROUPSHUT),GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL);
+ }
+ else
+ {
+ mod_DrawIconEx_helper(hdcMem,rc.left,rc.top+((g_nTitleBarHeight>>1)-(GetSystemMetrics(SM_CXSMICON)>>1)),g_pfwFrames[pos].collapsed?LoadSkinnedIcon(SKINICON_OTHER_GROUPOPEN):LoadSkinnedIcon(SKINICON_OTHER_GROUPSHUT),GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL);
+ }
+
+
+ }
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ if (g_pfwFrames[pos].floating || (!g_CluiData.fLayered))
+ {
+ HRGN rgn = CreateRectRgn(rect->left,rect->top,rect->right,rect->bottom);
+ SelectClipRgn(hdcMem2,rgn);
+ BitBlt(hdcMem2,rect->left,rect->top,rc.right-rc.left,rc.bottom-rc.top,hdcMem,0,0,SRCCOPY);
+ DeleteObject(rgn);
+ }
+ else
+ BitBlt(hdcMem2,rect->left,rect->top,rc.right-rc.left,rc.bottom-rc.top,hdcMem,0,0,SRCCOPY);
+ //MyAlphaBlend(hdcMem2,rect.left,rect.top,rc.right-rc.left,rc.bottom-rc.top,hdcMem,0,0,rc.right-rc.left,rc.bottom-rc.top,bf);
+ }
+
+ SelectObject(hdcMem,b2);
+ DeleteObject(b1);
+ SelectObject(hdcMem,hoTTBFont);
+ SelectObject(hdcMem,hoBrush);
+ mod_DeleteDC(hdcMem);
+ return 0;
+}
+static LRESULT CALLBACK CLUIFrameTitleBarProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static int s_nLastByPos = -1;
+ static int s_nOldFrameHeight = -1;
+ static int s_nCurDragBar = -1;
+
+ RECT rect;
+ int Frameid,Framemod,direction;
+ int xpos,ypos;
+
+ Frameid = (GetWindowLongPtr(hwnd,GWLP_USERDATA));
+ memset(&rect,0,sizeof(rect));
+
+
+ switch(msg)
+ {
+ case WM_CREATE:
+ if ( !_hFrameTitleTheme)
+ _hFrameTitleTheme = xpt_AddThemeHandle(hwnd,L"WINDOW");
+ SendMessage(hwnd,WM_SETFONT,(WPARAM)_hTitleBarFont,0);
+ return FALSE;
+ case WM_MEASUREITEM:
+ return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam);
+ case WM_DRAWITEM:
+ return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam);
+ case WM_USER+100:
+ return 1;
+ case WM_ENABLE:
+ if (hwnd != 0) CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ return 0;
+ case WM_ERASEBKGND:
+ {
+ return 1;
+ }
+ case WM_COMMAND:
+
+
+ if (ServiceExists(MO_CREATENEWMENUOBJECT))
+ {
+ //if ( CallService(MS_CLIST_MENUPROCESSCOMMAND,MAKEWPARAM(LOWORD(wParam),0),(LPARAM)Frameid)){break;};
+ if (ProcessCommandProxy(MAKEWPARAM(LOWORD(wParam),0),(LPARAM)Frameid)) break;
+ }else
+ {
+ if ( CallService(MS_CLIST_MENUPROCESSCOMMAND,MAKEWPARAM(LOWORD(wParam),MPCF_CONTEXTFRAMEMENU),(LPARAM)Frameid)){break;};
+
+ };
+
+
+ if (HIWORD(wParam) == 0) {//mouse events for self created menu
+ int framepos = id2pos(Frameid);
+ if (framepos == -1){break;};
+
+ switch(LOWORD(wParam))
+ {
+ case frame_menu_lock:
+ g_pfwFrames[framepos].Locked = !g_pfwFrames[framepos].Locked;
+ break;
+ case frame_menu_visible:
+ g_pfwFrames[framepos].visible = !g_pfwFrames[framepos].visible;
+ break;
+ case frame_menu_showtitlebar:
+ g_pfwFrames[framepos].TitleBar.ShowTitleBar = !g_pfwFrames[framepos].TitleBar.ShowTitleBar;
+ break;
+ case frame_menu_floating:
+ CLUIFrames_SetFrameFloat(Frameid,0);
+ break;
+ }
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ }
+
+ break;
+ case WM_RBUTTONDOWN:
+ {
+ HMENU hmenu;
+ POINT pt;
+ GetCursorPos(&pt);
+
+ if (ServiceExists(MS_CLIST_MENUBUILDFRAMECONTEXT))
+ {
+ hmenu = (HMENU)CallService(MS_CLIST_MENUBUILDFRAMECONTEXT,Frameid,0);
+ }
+ else
+ {//legacy menu support
+ int framepos = id2pos(Frameid);
+
+ if (framepos == -1){break;};
+ hmenu = CreatePopupMenu();
+ // Frames[Frameid].TitleBar.hmenu = hmenu;
+ AppendMenu(hmenu,MF_STRING|MF_DISABLED|MF_GRAYED,15,g_pfwFrames[framepos].Name);
+ AppendMenu(hmenu,MF_SEPARATOR,16,_T(""));
+
+ if (g_pfwFrames[framepos].Locked)
+ {AppendMenu(hmenu,MF_STRING|MF_CHECKED,frame_menu_lock,TranslateT("Lock Frame"));}
+ else{AppendMenu(hmenu,MF_STRING,frame_menu_lock,TranslateT("Lock Frame"));};
+
+ if (g_pfwFrames[framepos].visible)
+ {AppendMenu(hmenu,MF_STRING|MF_CHECKED,frame_menu_visible,TranslateT("Visible"));}
+ else{AppendMenu(hmenu,MF_STRING,frame_menu_visible,TranslateT("Visible"));};
+
+ if (g_pfwFrames[framepos].TitleBar.ShowTitleBar)
+ {AppendMenu(hmenu,MF_STRING|MF_CHECKED,frame_menu_showtitlebar,TranslateT("Show TitleBar"));}
+ else{AppendMenu(hmenu,MF_STRING,frame_menu_showtitlebar,TranslateT("Show TitleBar"));};
+
+ if (g_pfwFrames[framepos].floating)
+ {AppendMenu(hmenu,MF_STRING|MF_CHECKED,frame_menu_floating,TranslateT("Floating"));}
+ else{AppendMenu(hmenu,MF_STRING,frame_menu_floating,TranslateT("Floating"));};
+
+ //err = GetMenuItemCount(hmenu)
+
+ };
+
+ TrackPopupMenu(hmenu,TPM_LEFTALIGN,pt.x,pt.y,0,hwnd,0);
+ DestroyMenu(hmenu);
+ }
+ break;
+ case WM_LBUTTONDBLCLK:
+ {
+ Framemod = -1;
+ s_nLastByPos = -1;s_nOldFrameHeight = -1;ReleaseCapture();
+ CallService(MS_CLIST_FRAMES_UCOLLFRAME,Frameid,0);
+ s_nLastByPos = -1;s_nOldFrameHeight = -1;ReleaseCapture();
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ {
+ if (GetCapture() != hwnd){break;};
+ s_nCurDragBar = -1;s_nLastByPos = -1;s_nOldFrameHeight = -1;ReleaseCapture();
+ break;
+ };
+ case WM_LBUTTONDOWN:
+ {
+
+ int framepos = id2pos(Frameid);
+
+ if (framepos == -1){break;};
+ {
+ if (g_pfwFrames[framepos].floating)
+ {
+
+ POINT pt;
+ GetCursorPos(&pt);
+ g_pfwFrames[framepos].TitleBar.oldpos = pt;
+ };
+ };
+
+ //ScreenToClient(Frames[framepos].ContainerWnd,&Frames[framepos].TitleBar.oldpos);
+
+ if ((!(wParam&MK_CONTROL)) && g_pfwFrames[framepos].Locked && (!(g_pfwFrames[framepos].floating)))
+ {
+ if (db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT)) {
+ POINT pt;
+ int res;
+ //pt = nm->pt;
+ GetCursorPos(&pt);
+ res = SendMessage(GetParent(hwnd), WM_SYSCOMMAND, SC_MOVE|HTCAPTION,MAKELPARAM(pt.x,pt.y));
+ return res;
+ }
+ };
+
+ if (g_pfwFrames[framepos].floating)
+ {
+ RECT rc;
+ GetCursorPos(&ptOld);
+ //ClientToScreen(hwnd,&ptOld);
+ GetWindowRect( hwnd, &rc );
+
+ nLeft = (short)rc.left;
+ nTop = (short)rc.top;
+ };
+
+ SetCapture(hwnd);
+
+
+ break;
+ };
+ case WM_MOUSEMOVE:
+ {
+ POINT pt,pt2;
+ RECT wndr;
+ int pos;
+ //tbinfo
+ {
+ char TBcapt[255];
+
+
+ pos = id2pos(Frameid);
+
+ if (pos != -1)
+ {
+ int oldflags;
+
+
+ sprintf(TBcapt,"%s - h:%d, vis:%d, fl:%d, fl:(%d,%d,%d,%d),or: %d",
+ g_pfwFrames[pos].szName,g_pfwFrames[pos].height,g_pfwFrames[pos].visible,g_pfwFrames[pos].floating,
+ g_pfwFrames[pos].FloatingPos.x,g_pfwFrames[pos].FloatingPos.y,
+ g_pfwFrames[pos].FloatingSize.x,g_pfwFrames[pos].FloatingSize.y,
+ g_pfwFrames[pos].order
+ );
+
+ oldflags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,g_pfwFrames[pos].id),(LPARAM)0);
+ if ( !(oldflags&F_SHOWTBTIP))
+ {
+ oldflags |= F_SHOWTBTIP;
+ //CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,Frames[pos].id),(LPARAM)oldflags);
+ };
+ //CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_TBTIPNAME,Frames[pos].id),(LPARAM)TBcapt);
+ };
+
+
+
+ }
+ //
+ if ((wParam&MK_LBUTTON)/* && (wParam&MK_CONTROL)*/)
+ {
+ RECT rcMiranda;
+ RECT rcwnd,rcOverlap;
+ POINT newpt,ofspt,curpt,newpos;
+ //if (GetCapture() != hwnd){break;};
+ //curdragbar = -1;lbypos = -1;oldframeheight = -1;ReleaseCapture();
+
+ pos = id2pos(Frameid);
+ if (g_pfwFrames[pos].floating)
+ {
+
+ GetCursorPos(&curpt);
+ rcwnd.bottom = curpt.y+5;
+ rcwnd.top = curpt.y;
+ rcwnd.left = curpt.x;
+ rcwnd.right = curpt.x+5;
+
+ GetWindowRect(pcli->hwndContactList, &rcMiranda );
+ //GetWindowRect( Frames[pos].ContainerWnd, &rcwnd );
+ //IntersectRect( &rcOverlap, &rcwnd, &rcMiranda )
+ if (IsWindowVisible(pcli->hwndContactList) && IntersectRect( &rcOverlap, &rcwnd, &rcMiranda ))
+ {
+ int id = g_pfwFrames[pos].id;
+
+
+
+
+ ofspt.x = 0;ofspt.y = 0;
+ ClientToScreen(g_pfwFrames[pos].TitleBar.hwnd,&ofspt);
+ ofspt.x = curpt.x-ofspt.x;ofspt.y = curpt.y-ofspt.y;
+
+ CLUIFrames_SetFrameFloat(id,0);
+ newpt.x = 0;newpt.y = 0;
+ ClientToScreen(g_pfwFrames[pos].TitleBar.hwnd,&newpt);
+ SetCursorPos(newpt.x+ofspt.x,newpt.y+ofspt.y);
+ GetCursorPos(&curpt);
+
+ g_pfwFrames[pos].TitleBar.oldpos = curpt;
+
+ return(0);
+ };
+
+ }
+ else
+ {
+ int id = g_pfwFrames[pos].id;
+
+ GetCursorPos(&curpt);
+ rcwnd.bottom = curpt.y+5;
+ rcwnd.top = curpt.y;
+ rcwnd.left = curpt.x;
+ rcwnd.right = curpt.x+5;
+
+ GetWindowRect(pcli->hwndContactList, &rcMiranda );
+ //GetWindowRect( Frames[pos].ContainerWnd, &rcwnd );
+ //IntersectRect( &rcOverlap, &rcwnd, &rcMiranda )
+
+
+ if ( !IntersectRect( &rcOverlap, &rcwnd, &rcMiranda ))
+ {
+ GetCursorPos(&curpt);
+ GetWindowRect( g_pfwFrames[pos].hWnd, &rcwnd );
+ rcwnd.left = rcwnd.right-rcwnd.left;
+ rcwnd.top = rcwnd.bottom-rcwnd.top;
+ newpos.x = curpt.x;newpos.y = curpt.y;
+ if (curpt.x >= (rcMiranda.right-1)){newpos.x = curpt.x+5;};
+ if (curpt.x <= (rcMiranda.left+1)){newpos.x = curpt.x-(rcwnd.left)-5;};
+ if (curpt.y >= (rcMiranda.bottom-1)){newpos.y = curpt.y+5;};
+ if (curpt.y <= (rcMiranda.top+1)){newpos.y = curpt.y-(rcwnd.top)-5;};
+ ofspt.x = 0;ofspt.y = 0;
+ //ClientToScreen(Frames[pos].TitleBar.hwnd,&ofspt);
+ GetWindowRect(g_pfwFrames[pos].TitleBar.hwnd,&rcwnd);
+ ofspt.x = curpt.x-ofspt.x;ofspt.y = curpt.y-ofspt.y;
+
+ g_pfwFrames[pos].FloatingPos.x = newpos.x;
+ g_pfwFrames[pos].FloatingPos.y = newpos.y;
+ CLUIFrames_SetFrameFloat(id,0);
+ //SetWindowPos(Frames[pos].ContainerWnd,0,newpos.x,newpos.y,0,0,SWP_NOSIZE);
+
+
+ newpt.x = 0;newpt.y = 0;
+ ClientToScreen(g_pfwFrames[pos].TitleBar.hwnd,&newpt);
+
+ GetWindowRect( g_pfwFrames[pos].hWnd, &rcwnd );
+ SetCursorPos(newpt.x+(rcwnd.right-rcwnd.left)/2,newpt.y+(rcwnd.bottom-rcwnd.top)/2);
+ GetCursorPos(&curpt);
+
+ g_pfwFrames[pos].TitleBar.oldpos = curpt;
+
+
+ return(0);
+ };
+
+ };
+
+ //return(0);
+ };
+
+ if (wParam&MK_LBUTTON) {
+ int newh = -1,prevold;
+
+ if (GetCapture() != hwnd){break;};
+
+
+ pos = id2pos(Frameid);
+
+ if (g_pfwFrames[pos].floating)
+ {
+ GetCursorPos(&pt);
+ if ((g_pfwFrames[pos].TitleBar.oldpos.x != pt.x) || (g_pfwFrames[pos].TitleBar.oldpos.y != pt.y))
+ {
+
+ pt2 = pt;
+ ScreenToClient(hwnd,&pt2);
+ GetWindowRect(g_pfwFrames[pos].ContainerWnd,&wndr);
+ {
+ int dX,dY;
+ POINT ptNew;
+
+ ptNew.x = pt.x;
+ ptNew.y = pt.y;
+ //ClientToScreen( hwnd, &ptNew );
+
+ dX = ptNew.x - ptOld.x;
+ dY = ptNew.y - ptOld.y;
+
+ nLeft += (short)dX;
+ nTop += (short)dY;
+
+ if ( !(wParam&MK_CONTROL))
+ {
+ PositionThumb( &g_pfwFrames[pos], nLeft, nTop );
+ }else
+ {
+
+ SetWindowPos( g_pfwFrames[pos].ContainerWnd,
+ HWND_TOPMOST,
+ nLeft,
+ nTop,
+ 0,
+ 0,
+ SWP_NOSIZE |SWP_NOACTIVATE| SWP_NOZORDER );
+ };
+
+ ptOld = ptNew;
+
+
+
+ }
+
+ pt.x = nLeft;
+ pt.y = nTop;
+ g_pfwFrames[pos].TitleBar.oldpos = pt;
+ };
+
+ //break;
+ return(0);
+ };
+
+
+ if (g_pfwFrames[pos].prevvisframe != -1) {
+ GetCursorPos(&pt);
+
+ if ((g_pfwFrames[pos].TitleBar.oldpos.x == pt.x) && (g_pfwFrames[pos].TitleBar.oldpos.y == pt.y))
+ {break;};
+
+ ypos = rect.top+pt.y;xpos = rect.left+pt.x;
+ Framemod = -1;
+
+ if (g_pfwFrames[pos].align == alBottom) {
+ direction = -1;
+ Framemod = pos;
+ }
+ else {
+ direction = 1;
+ Framemod = g_pfwFrames[pos].prevvisframe;
+ }
+ if (g_pfwFrames[Framemod].Locked) {break;};
+ if (s_nCurDragBar != -1 && s_nCurDragBar != pos) {break;};
+
+ if (s_nLastByPos == -1) {
+ s_nCurDragBar = pos;
+ s_nLastByPos = ypos;
+ s_nOldFrameHeight = g_pfwFrames[Framemod].height;
+ SetCapture(hwnd);
+ {break;};
+ }
+ else
+ {
+ // if (GetCapture() != hwnd){break;};
+ };
+
+ newh = s_nOldFrameHeight+direction*(ypos-s_nLastByPos);
+ if (newh>0) {
+ prevold = g_pfwFrames[Framemod].height;
+ g_pfwFrames[Framemod].height = newh;
+ if ( !CLUIFramesFitInSize()) { g_pfwFrames[Framemod].height = prevold; return TRUE;}
+ g_pfwFrames[Framemod].height = newh;
+ if (newh>3) g_pfwFrames[Framemod].collapsed = TRUE;
+
+ }
+ g_pfwFrames[pos].TitleBar.oldpos = pt;
+ }
+
+ if (newh>0)
+ {
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ };
+ break;
+ }
+ s_nCurDragBar = -1;s_nLastByPos = -1;s_nOldFrameHeight = -1;ReleaseCapture();
+ }
+ break;
+ case WM_PRINT:
+ case WM_PRINTCLIENT:
+ {
+ //if (lParam&PRF_CLIENT)
+ {
+ GetClientRect(hwnd,&rect);
+ if ( !g_CluiData.fLayered)
+ {
+ ske_BltBackImage(hwnd,(HDC)wParam,&rect);
+ }
+ DrawTitleBar((HDC)wParam,&rect,Frameid);
+ }
+ break;
+ }
+ case WM_SIZE:
+ {
+ InvalidateRect(hwnd,NULL,FALSE);
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ case WM_PAINT:
+ {
+ HDC paintDC;
+ if (g_pfwFrames[id2pos(Frameid)].floating || (!g_CluiData.fLayered))
+ {
+ GetClientRect(hwnd,&rect);
+ paintDC = GetDC(hwnd);
+ DrawTitleBar(paintDC,&rect,Frameid);
+ ReleaseDC(hwnd,paintDC);
+ ValidateRect(hwnd,NULL);
+
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ default:return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return TRUE;
+}
+static int CLUIFrameResizeFloatingFrame(int framepos)
+{
+
+ int width,height;
+ RECT rect;
+
+ if ( !g_pfwFrames[framepos].floating){return(0);};
+ if (g_pfwFrames[framepos].ContainerWnd == 0){return(0);};
+ GetClientRect(g_pfwFrames[framepos].ContainerWnd,&rect);
+
+ width = rect.right-rect.left;
+ height = rect.bottom-rect.top;
+
+ g_pfwFrames[framepos].visible?CLUI_ShowWindowMod(g_pfwFrames[framepos].ContainerWnd,SW_SHOW/*NOACTIVATE*/):CLUI_ShowWindowMod(g_pfwFrames[framepos].ContainerWnd,SW_HIDE);
+
+
+
+ if (g_pfwFrames[framepos].TitleBar.ShowTitleBar)
+ {
+ CLUI_ShowWindowMod(g_pfwFrames[framepos].TitleBar.hwnd,SW_SHOW/*NOACTIVATE*/);
+ //if (Frames[framepos].Locked){return(0);};
+ g_pfwFrames[framepos].height = height-DEFAULT_TITLEBAR_HEIGHT;
+
+ SetWindowPos(g_pfwFrames[framepos].TitleBar.hwnd,HWND_TOP,0,0,width,DEFAULT_TITLEBAR_HEIGHT,SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_DRAWFRAME);
+ SetWindowPos(g_pfwFrames[framepos].hWnd,HWND_TOP,0,DEFAULT_TITLEBAR_HEIGHT,width,height-DEFAULT_TITLEBAR_HEIGHT,SWP_SHOWWINDOW);
+
+ }
+ else
+ {
+ //SetWindowPos(Frames[framepos].TitleBar.hwnd,HWND_TOP,0,0,width,DEFAULT_TITLEBAR_HEIGHT,SWP_SHOWWINDOW|SWP_NOMOVE);
+ //if (Frames[framepos].Locked){return(0);};
+ g_pfwFrames[framepos].height = height;
+ CLUI_ShowWindowMod(g_pfwFrames[framepos].TitleBar.hwnd,SW_HIDE);
+ SetWindowPos(g_pfwFrames[framepos].hWnd,HWND_TOP,0,0,width,height,SWP_SHOWWINDOW|SWP_NOACTIVATE);
+
+ };
+ // CLUIFramesForceUpdateFrame(&Frames[framepos]);
+ if (g_pfwFrames[framepos].ContainerWnd != 0) UpdateWindow(g_pfwFrames[framepos].ContainerWnd);
+ //GetClientRect(Frames[framepos].TitleBar.hwnd,&Frames[framepos].TitleBar.wndSize);
+ GetWindowRect(g_pfwFrames[framepos].hWnd,&g_pfwFrames[framepos].wndSize);
+ //Frames[framepos].height = Frames[framepos].wndSize.bottom-Frames[framepos].wndSize.top;
+ //GetClientRect(Frames[framepos].hWnd,&Frames[framepos].wndSize);
+ //Frames[framepos].height = Frames[framepos].wndSize.bottom-Frames[framepos].wndSize.top;
+ return(0);
+};
+
+static int CLUIFrameOnMainMenuBuild(WPARAM wParam,LPARAM lParam)
+{
+ if (MirandaExiting()) return 0;
+ CLUIFramesLoadMainMenu();
+
+ return 0;
+}
+
+static LRESULT CALLBACK CLUIFrameSubContainerProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+
+ RECT rect;
+ int Frameid;
+
+ Frameid = (GetWindowLongPtr(hwnd,GWLP_USERDATA));
+ memset(&rect,0,sizeof(rect));
+
+ /*
+ if ((msg == WM_MOVE) || (msg == WM_MOVING) || (msg == WM_NCLBUTTONDOWN) || (msg == WM_SYSCOMMAND) )
+ {
+ if (ServiceExists("Utils/SnapWindowProc"))
+ {
+ SnapWindowProc_t SnapInfo;
+ memset(&SnapInfo,0,sizeof(SnapInfo));
+
+ SnapInfo.hWnd = hwnd;
+ SnapInfo.wParam = wParam;
+ SnapInfo.lParam = lParam;
+ if (CallService("Utils/SnapWindowProc",(WPARAM)&SnapInfo,msg) != 0){return(TRUE);};
+ };
+ };
+ */
+ switch(msg) {
+ case WM_ACTIVATE:
+ {
+ if (g_bTransparentFlag)
+ {
+ BYTE alpha;
+ if ((wParam != WA_INACTIVE || ((HWND)lParam == hwnd) || GetParent((HWND)lParam) == hwnd))
+ {
+ HWND hw = lParam?GetParent((HWND)lParam):0;
+ alpha = db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT);
+ if (hw) SetWindowPos(hw,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
+ CLUI_SmoothAlphaTransition(hwnd, alpha, 1);
+ }
+ }
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ case WM_NOTIFY:
+ case WM_PARENTNOTIFY:
+ case WM_SYSCOMMAND:
+ return SendMessage(pcli->hwndContactList,msg,wParam,lParam);
+
+ case WM_MOVE:
+ if (g_CluiData.fDocked) return 1;
+ break;
+
+ case WM_WINDOWPOSCHANGING:
+ {
+ if (g_CluiData.mutexPreventDockMoving)
+ {
+ WINDOWPOS *wp;
+ wp = (WINDOWPOS*)lParam;
+ wp->flags |= SWP_NOMOVE/*|SWP_NOSIZE*/;
+ wp->flags &= (wp->flags&~SWP_NOACTIVATE);
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ break;
+ }
+ case WM_WINDOWPOSCHANGED:
+ {
+ if (g_CluiData.fDocked && g_CluiData.mutexPreventDockMoving)
+ return 0;
+ }
+ break;
+ case WM_NCPAINT:
+ case WM_PAINT:
+ {
+ //ValidateRect(hwnd,NULL);
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ case WM_ERASEBKGND:
+ {
+ return 1;
+ }
+ };
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+};
+
+static HWND CreateSubContainerWindow(HWND parent,int x,int y,int width,int height)
+{
+ HWND hwnd;
+ hwnd = CreateWindowEx(g_proc_SetLayeredWindowAttributesNew ? WS_EX_LAYERED:0,CLUIFrameSubContainerClassName,_T("SubContainerWindow"),WS_POPUP|(!g_CluiData.fLayered ? WS_BORDER : 0),x,y,width,height,parent,0,g_hInst,0);
+ SetWindowLongPtr(hwnd,GWL_STYLE,GetWindowLongPtr(hwnd,GWL_STYLE)&~(WS_CAPTION|WS_BORDER));
+ if (g_CluiData.fOnDesktop)
+ {
+ HWND hProgMan = FindWindow(_T("Progman"),NULL);
+ if (IsWindow(hProgMan))
+ SetParent(hwnd,hProgMan);
+ }
+
+
+ return hwnd;
+};
+
+
+
+static LRESULT CALLBACK CLUIFrameContainerWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+
+ RECT rect;
+ int Frameid;
+
+ Frameid = (GetWindowLongPtr(hwnd,GWLP_USERDATA));
+ memset(&rect,0,sizeof(rect));
+ /*
+ if ((msg == WM_MOVE) || (msg == WM_MOVING) || (msg == WM_NCLBUTTONDOWN) || (msg == WM_SYSCOMMAND) )
+ {
+ if (ServiceExists("Utils/SnapWindowProc"))
+ {
+ SnapWindowProc_t SnapInfo;
+ memset(&SnapInfo,0,sizeof(SnapInfo));
+
+ SnapInfo.hWnd = hwnd;
+ SnapInfo.wParam = wParam;
+ SnapInfo.lParam = lParam;
+ if (CallService("Utils/SnapWindowProc",(WPARAM)&SnapInfo,msg) != 0){return(TRUE);};
+ };
+ };
+ */
+ switch(msg)
+ {
+
+ case WM_CREATE:
+ {
+ int framepos;
+
+ framepos = id2pos(Frameid);
+ //SetWindowPos(Frames[framepos].TitleBar.hwndTip, HWND_TOPMOST,0, 0, 0, 0,SWP_NOMOVE | SWP_NOSIZE );
+
+ return(0);
+ };
+ case WM_GETMINMAXINFO:
+ //DefWindowProc(hwnd,msg,wParam,lParam);
+ {
+ int framepos;
+ MINMAXINFO minmax;
+
+
+ framepos = id2pos(Frameid);
+ if (framepos < 0 || framepos >= g_nFramesCount){break;};
+ if ( !g_pfwFrames[framepos].minmaxenabled){break;};
+ if (g_pfwFrames[framepos].ContainerWnd == 0){break;};
+
+ if (g_pfwFrames[framepos].Locked)
+ {
+ RECT rct;
+
+ GetWindowRect(hwnd,&rct);
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = rct.right-rct.left;
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = rct.bottom-rct.top;
+ ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = rct.right-rct.left;
+ ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = rct.bottom-rct.top;
+ //
+ //return(0);
+ };
+
+
+ memset(&minmax,0,sizeof(minmax));
+ if (SendMessage(g_pfwFrames[framepos].hWnd,WM_GETMINMAXINFO,(WPARAM)0,(LPARAM)&minmax) == 0)
+ {
+ RECT border;
+ int tbh = g_nTitleBarHeight*btoint(g_pfwFrames[framepos].TitleBar.ShowTitleBar);
+ GetBorderSize(hwnd,&border);
+ if (minmax.ptMaxTrackSize.x != 0 && minmax.ptMaxTrackSize.y != 0){
+
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = minmax.ptMinTrackSize.x;
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = minmax.ptMinTrackSize.y;
+ ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = minmax.ptMaxTrackSize.x+border.left+border.right;
+ ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = minmax.ptMaxTrackSize.y+tbh+border.top+border.bottom;
+ };
+
+ }
+ else
+ {
+
+
+ return(DefWindowProc(hwnd, msg, wParam, lParam));
+ };
+
+
+
+ }
+ //return 0;
+
+ case WM_MOVE:
+ {
+ int framepos;
+ RECT rect;
+
+ framepos = id2pos(Frameid);
+
+ if (framepos < 0 || framepos >= g_nFramesCount){break;};
+ if (g_pfwFrames[framepos].ContainerWnd == 0){return(0);};
+
+ GetWindowRect(g_pfwFrames[framepos].ContainerWnd,&rect);
+ g_pfwFrames[framepos].FloatingPos.x = rect.left;
+ g_pfwFrames[framepos].FloatingPos.y = rect.top;
+ g_pfwFrames[framepos].FloatingSize.x = rect.right-rect.left;
+ g_pfwFrames[framepos].FloatingSize.y = rect.bottom-rect.top;
+
+ CLUIFramesStoreFrameSettings(framepos);
+
+ if ( g_pfwFrames[framepos].floating )
+ {
+ POINT curpt,ofspt, newpt, newpos;
+ RECT rcwnd, rcOverlap, rcMiranda;
+
+ GetCursorPos(&curpt);
+ rcwnd.bottom = curpt.y+5;
+ rcwnd.top = curpt.y;
+ rcwnd.left = curpt.x;
+ rcwnd.right = curpt.x+5;
+
+ GetWindowRect(pcli->hwndContactList, &rcMiranda );
+ //GetWindowRect( Frames[pos].ContainerWnd, &rcwnd );
+ //IntersectRect( &rcOverlap, &rcwnd, &rcMiranda )
+
+
+ if (IntersectRect( &rcOverlap, &rcwnd, &rcMiranda ))
+ {
+ GetCursorPos(&curpt);
+ GetWindowRect( g_pfwFrames[framepos].hWnd, &rcwnd );
+ rcwnd.left = rcwnd.right-rcwnd.left;
+ rcwnd.top = rcwnd.bottom-rcwnd.top;
+ newpos.x = curpt.x;newpos.y = curpt.y;
+ if (curpt.x >= (rcMiranda.right-1)){newpos.x = curpt.x+5;};
+ if (curpt.x <= (rcMiranda.left+1)){newpos.x = curpt.x-(rcwnd.left)-5;};
+ if (curpt.y >= (rcMiranda.bottom-1)){newpos.y = curpt.y+5;};
+ if (curpt.y <= (rcMiranda.top+1)){newpos.y = curpt.y-(rcwnd.top)-5;};
+ ofspt.x = 0;ofspt.y = 0;
+ //ClientToScreen(Frames[pos].TitleBar.hwnd,&ofspt);
+ GetWindowRect(g_pfwFrames[framepos].TitleBar.hwnd,&rcwnd);
+ ofspt.x = curpt.x-ofspt.x;ofspt.y = curpt.y-ofspt.y;
+
+ g_pfwFrames[framepos].FloatingPos.x = newpos.x;
+ g_pfwFrames[framepos].FloatingPos.y = newpos.y;
+ CLUIFrames_SetFrameFloat(Frameid,0);
+ //SetWindowPos(Frames[pos].ContainerWnd,0,newpos.x,newpos.y,0,0,SWP_NOSIZE);
+
+
+ newpt.x = 0;newpt.y = 0;
+ ClientToScreen(g_pfwFrames[framepos].TitleBar.hwnd,&newpt);
+
+ GetWindowRect( g_pfwFrames[framepos].hWnd, &rcwnd );
+ SetCursorPos(newpt.x+(rcwnd.right-rcwnd.left)/2,newpt.y+(rcwnd.bottom-rcwnd.top)/2);
+ GetCursorPos(&curpt);
+
+ g_pfwFrames[framepos].TitleBar.oldpos = curpt;
+
+
+ return(0);
+ };
+
+ };
+
+
+ return(0);
+ };
+
+ case WM_SIZE:
+ {
+ int framepos;
+ RECT rect;
+
+ CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
+
+ framepos = id2pos(Frameid);
+
+ if (framepos < 0 || framepos >= g_nFramesCount){break;};
+ if (g_pfwFrames[framepos].ContainerWnd == 0){return(0);};
+ CLUIFrameResizeFloatingFrame(framepos);
+
+ GetWindowRect(g_pfwFrames[framepos].ContainerWnd,&rect);
+ g_pfwFrames[framepos].FloatingPos.x = rect.left;
+ g_pfwFrames[framepos].FloatingPos.y = rect.top;
+ g_pfwFrames[framepos].FloatingSize.x = rect.right-rect.left;
+ g_pfwFrames[framepos].FloatingSize.y = rect.bottom-rect.top;
+
+ CLUIFramesStoreFrameSettings(framepos);
+
+
+ return(0);
+ };
+ case WM_LBUTTONDOWN:
+ {
+ if (db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT)) {
+ POINT pt;
+ GetCursorPos(&pt);
+ return SendMessage( hwnd, WM_SYSCOMMAND, SC_MOVE|HTCAPTION,MAKELPARAM(pt.x,pt.y));
+ }
+ break;
+ }
+ case WM_CLOSE:
+ {
+ DestroyWindow(hwnd);
+ break;
+ };
+
+ case WM_DESTROY:
+ {
+ //{ CLUIFramesStoreAllFrames();};
+ return(0);
+ };
+ /*
+ case WM_COMMAND:
+ case WM_NOTIFY:
+ return(SendMessage(pcli->hwndContactList,msg,wParam,lParam));
+ */
+
+
+ };
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+};
+static HWND CreateContainerWindow(HWND parent,int x,int y,int width,int height)
+{
+ return(CreateWindow(_T("FramesContainer"),_T("FramesContainer"),WS_POPUP|WS_THICKFRAME,x,y,width,height,parent,0,g_hInst,0));
+};
+
+
+static int _us_DoSetFrameFloat(WPARAM wParam,LPARAM lParam)
+{
+ HWND hwndtmp,hwndtooltiptmp;
+
+
+ int pos = id2pos( wParam );
+ if ( pos >= 0 && pos < g_nFramesCount )
+
+ if (g_pfwFrames[pos].floating || (lParam&2))
+ {
+ if (g_pfwFrames[pos].OwnerWindow != (HWND)-2 && g_pfwFrames[pos].visible)
+ {
+ if (g_pfwFrames[pos].OwnerWindow == 0) g_pfwFrames[pos].OwnerWindow = CreateSubContainerWindow(pcli->hwndContactList,g_pfwFrames[pos].FloatingPos.x,g_pfwFrames[pos].FloatingPos.y,10,10);
+ CLUI_ShowWindowMod(g_pfwFrames[pos].OwnerWindow,(g_pfwFrames[pos].visible && g_pfwFrames[pos].collapsed && IsWindowVisible(pcli->hwndContactList))?SW_SHOW/*NOACTIVATE*/:SW_HIDE);
+ SetParent(g_pfwFrames[pos].hWnd,g_pfwFrames[pos].OwnerWindow);
+ SetParent(g_pfwFrames[pos].TitleBar.hwnd,pcli->hwndContactList);
+ SetWindowLongPtr(g_pfwFrames[pos].OwnerWindow,GWLP_USERDATA,g_pfwFrames[pos].id);
+ g_pfwFrames[pos].floating = FALSE;
+ if ( !(lParam&2))
+ {
+ DestroyWindow(g_pfwFrames[pos].ContainerWnd);
+ g_pfwFrames[pos].ContainerWnd = 0;
+ }
+ }
+ else
+ {
+ SetParent(g_pfwFrames[pos].hWnd,pcli->hwndContactList);
+ SetParent(g_pfwFrames[pos].TitleBar.hwnd,pcli->hwndContactList);
+ g_pfwFrames[pos].floating = FALSE;
+ if (g_pfwFrames[pos].ContainerWnd) DestroyWindow(g_pfwFrames[pos].ContainerWnd);
+ g_pfwFrames[pos].ContainerWnd = 0;
+ }
+ }
+ else
+ {
+ RECT recttb,rectw,border;
+ int temp;
+ int neww,newh;
+ BOOLEAN locked;
+
+ g_pfwFrames[pos].oldstyles = GetWindowLongPtr(g_pfwFrames[pos].hWnd,GWL_STYLE);
+ g_pfwFrames[pos].TitleBar.oldstyles = GetWindowLongPtr(g_pfwFrames[pos].TitleBar.hwnd,GWL_STYLE);
+ locked = g_pfwFrames[pos].Locked;
+ g_pfwFrames[pos].Locked = FALSE;
+ g_pfwFrames[pos].minmaxenabled = FALSE;
+
+ GetWindowRect(g_pfwFrames[pos].hWnd,&rectw);
+ GetWindowRect(g_pfwFrames[pos].TitleBar.hwnd,&recttb);
+ if ( !g_pfwFrames[pos].TitleBar.ShowTitleBar){
+ recttb.top = recttb.bottom = recttb.left = recttb.right = 0;
+ };
+
+ g_pfwFrames[pos].ContainerWnd = CreateContainerWindow(pcli->hwndContactList,g_pfwFrames[pos].FloatingPos.x,g_pfwFrames[pos].FloatingPos.y,10,10);
+
+
+
+
+ SetParent(g_pfwFrames[pos].hWnd,g_pfwFrames[pos].ContainerWnd);
+ SetParent(g_pfwFrames[pos].TitleBar.hwnd,g_pfwFrames[pos].ContainerWnd);
+ if (g_pfwFrames[pos].OwnerWindow != (HWND)-2 && g_pfwFrames[pos].OwnerWindow != 0)
+ {
+ DestroyWindow(g_pfwFrames[pos].OwnerWindow);
+ g_pfwFrames[pos].OwnerWindow = 0;
+ }
+
+ GetBorderSize(g_pfwFrames[pos].ContainerWnd,&border);
+
+
+ SetWindowLongPtr(g_pfwFrames[pos].ContainerWnd,GWLP_USERDATA,g_pfwFrames[pos].id);
+ if ((lParam == 1))
+ {
+ //if ((Frames[pos].FloatingPos.x != 0) && (Frames[pos].FloatingPos.y != 0))
+ {
+ if (g_pfwFrames[pos].FloatingPos.x < 0){g_pfwFrames[pos].FloatingPos.x = 0;};
+ if (g_pfwFrames[pos].FloatingPos.y < 0){g_pfwFrames[pos].FloatingPos.y = 0;};
+
+ SetWindowPos(g_pfwFrames[pos].ContainerWnd,HWND_TOPMOST,g_pfwFrames[pos].FloatingPos.x,g_pfwFrames[pos].FloatingPos.y,g_pfwFrames[pos].FloatingSize.x,g_pfwFrames[pos].FloatingSize.y,SWP_HIDEWINDOW|SWP_NOACTIVATE);
+ }
+ }
+ else if (lParam == 0)
+ {
+ neww = rectw.right-rectw.left+border.left+border.right;
+ newh = (rectw.bottom-rectw.top)+(recttb.bottom-recttb.top)+border.top+border.bottom;
+ if (neww < 20){neww = 40;};
+ if (newh < 20){newh = 40;};
+ if (g_pfwFrames[pos].FloatingPos.x < 20){g_pfwFrames[pos].FloatingPos.x = 40;};
+ if (g_pfwFrames[pos].FloatingPos.y < 20){g_pfwFrames[pos].FloatingPos.y = 40;};
+
+ SetWindowPos(g_pfwFrames[pos].ContainerWnd,HWND_TOPMOST,g_pfwFrames[pos].FloatingPos.x,g_pfwFrames[pos].FloatingPos.y,neww,newh,SWP_HIDEWINDOW|SWP_NOACTIVATE);
+ };
+
+
+ SetWindowText(g_pfwFrames[pos].ContainerWnd,g_pfwFrames[pos].TitleBar.tbname);
+
+ temp = GetWindowLongPtr(g_pfwFrames[pos].ContainerWnd,GWL_EXSTYLE);
+ temp |= WS_EX_TOOLWINDOW|WS_EX_TOPMOST ;
+ SetWindowLongPtr(g_pfwFrames[pos].ContainerWnd,GWL_EXSTYLE,temp);
+
+ g_pfwFrames[pos].floating = TRUE;
+ g_pfwFrames[pos].Locked = locked;
+
+ }
+ CLUIFramesStoreFrameSettings(pos);
+ g_pfwFrames[pos].minmaxenabled = TRUE;
+ hwndtooltiptmp = g_pfwFrames[pos].TitleBar.hwndTip;
+
+ hwndtmp = g_pfwFrames[pos].ContainerWnd;
+
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ if (hwndtmp) SendMessage(hwndtmp,WM_SIZE,0,0);
+
+
+ SetWindowPos(hwndtooltiptmp, HWND_TOPMOST,0, 0, 0, 0,SWP_NOMOVE | SWP_NOSIZE|SWP_NOACTIVATE );
+
+ return 0;
+}
+
+
+int CLUIFrameOnModulesLoad(WPARAM wParam,LPARAM lParam)
+{
+ /* HOOK */
+ CLUIFramesLoadMainMenu();
+ CLUIFramesCreateMenuForFrame(-1,-1,000010000,Menu_AddContextFrameMenuItem);
+ return 0;
+}
+int CLUIFrameOnModulesUnload(WPARAM wParam,LPARAM lParam)
+{
+ //
+ //if (MirandaExiting()) return 0;
+ if ( !_hmiVisible) return 0;
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiVisible, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiTBVisible, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiLock, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiColl, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiFloating, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiAlignTop, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiAlignClient, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiAlignBottom, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiBorder, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiAlignRoot, 1 );
+
+
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiPosUp, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiPosDown, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiPosRoot, 1 );
+
+
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiVisible, 1 );
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiTBVisible, 1 );
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiLock, 1 );
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiColl, 1 );
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiFloating, 1 );
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiBorder, 1 );
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiAlignRoot, 1 );
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiPosRoot, 1 );
+
+ _hmiVisible = 0;
+ return 0;
+}
+
+int LoadCLUIFramesModule(void)
+{
+ WNDCLASS wndclass;
+ WNDCLASS cntclass;
+ WNDCLASS subconclass;
+ InitializeCriticalSection(&_cluiFramesModuleCS);
+ _cluiFramesModuleCSInitialized = TRUE;
+
+ wndclass.style = CS_DBLCLKS;//|CS_HREDRAW|CS_VREDRAW ;
+ wndclass.lpfnWndProc = CLUIFrameTitleBarProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = CLUIFrameTitleBarClassName;
+ RegisterClass(&wndclass);
+
+ subconclass.style = CS_DBLCLKS;//|CS_HREDRAW|CS_VREDRAW ;
+ subconclass.lpfnWndProc = CLUIFrameSubContainerProc;
+ subconclass.cbClsExtra = 0;
+ subconclass.cbWndExtra = 0;
+ subconclass.hInstance = g_hInst;
+ subconclass.hIcon = NULL;
+ subconclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ subconclass.hbrBackground = NULL;
+ subconclass.lpszMenuName = NULL;
+ subconclass.lpszClassName = CLUIFrameSubContainerClassName;
+ RegisterClass(&subconclass);
+
+ //container helper
+
+ cntclass.style = CS_DBLCLKS/*|CS_HREDRAW|CS_VREDRAW*/|( IsWinVerXPPlus() ? CS_DROPSHADOW : 0);
+ cntclass.lpfnWndProc = CLUIFrameContainerWndProc;
+ cntclass.cbClsExtra = 0;
+ cntclass.cbWndExtra = 0;
+ cntclass.hInstance = g_hInst;
+ cntclass.hIcon = NULL;
+ cntclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ cntclass.hbrBackground = NULL;
+ cntclass.lpszMenuName = NULL;
+ cntclass.lpszClassName = _T("FramesContainer");
+ RegisterClass(&cntclass);
+ //end container helper
+
+ GapBetweenFrames = db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT);
+
+ g_nFramesCount = 0;
+
+ InitFramesMenus();
+
+ HookEvent(ME_SYSTEM_MODULESLOADED,CLUIFrameOnModulesLoad);
+ HookEvent(ME_CLIST_PREBUILDFRAMEMENU,CLUIFramesModifyContextMenuForFrame);
+ HookEvent(ME_CLIST_PREBUILDMAINMENU,CLUIFrameOnMainMenuBuild);
+ HookEvent(ME_SYSTEM_PRESHUTDOWN, CLUIFrameOnModulesUnload);
+
+ CreateCluiFramesServices();
+
+
+ hWndExplorerToolBar = FindWindowEx(0,0,_T("Shell_TrayWnd"),NULL);
+ OnFrameTitleBarBackgroundChange(0,0);
+ _fCluiFramesModuleNotStarted = FALSE;
+ return 0;
+}
+
+static INT_PTR UnloadMainMenu()
+{
+ CLUIFrameOnModulesUnload(0,0);
+ if (_hmiRoot != (HANDLE)-1)
+ {
+ CallService(MS_CLIST_REMOVEMAINMENUITEM,(WPARAM)_hmiRoot,0);
+ _hmiRoot = (HGENMENU)-1;
+ }
+
+ return (INT_PTR) _hmiRoot;
+}
+
+int UnLoadCLUIFramesModule(void)
+{
+ int i;
+
+ _fCluiFramesModuleNotStarted = TRUE;
+ if (hBmpBackground) {DeleteObject(hBmpBackground); hBmpBackground = NULL;}
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,0);
+ CLUIFramesStoreAllFrames();
+
+
+ UnitFramesMenu();
+ UnloadMainMenu();
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if (g_pfwFrames[i].hWnd != pcli->hwndContactTree)
+ DestroyWindow(g_pfwFrames[i].hWnd);
+
+ g_pfwFrames[i].hWnd = (HWND)-1;
+ DestroyWindow(g_pfwFrames[i].TitleBar.hwnd);
+ g_pfwFrames[i].TitleBar.hwnd = (HWND)-1;
+ if (g_pfwFrames[i].ContainerWnd && g_pfwFrames[i].ContainerWnd != (HWND)(-2) && g_pfwFrames[i].ContainerWnd != (HWND)(-1)) DestroyWindow(g_pfwFrames[i].ContainerWnd);
+ g_pfwFrames[i].ContainerWnd = (HWND)-1;
+ if (g_pfwFrames[i].TitleBar.hmenu) DestroyMenu(g_pfwFrames[i].TitleBar.hmenu);
+ if (g_pfwFrames[i].OwnerWindow && g_pfwFrames[i].OwnerWindow != (HWND)(-2) && g_pfwFrames[i].OwnerWindow != (HWND)(-1))
+ DestroyWindow(g_pfwFrames[i].OwnerWindow );
+ g_pfwFrames[i].OwnerWindow = (HWND)-2;
+ if (g_pfwFrames[i].UpdateRgn) DeleteObject(g_pfwFrames[i].UpdateRgn);
+
+ mir_free_and_nil(g_pfwFrames[i].Name);
+ mir_free_and_nil(g_pfwFrames[i].szName);
+ mir_free_and_nil(g_pfwFrames[i].TitleBar.tbname);
+ mir_free_and_nil(g_pfwFrames[i].TitleBar.sztbname);
+ mir_free_and_nil(g_pfwFrames[i].TitleBar.tooltip);
+ mir_free_and_nil(g_pfwFrames[i].TitleBar.sztooltip);
+
+ }
+ if (g_pfwFrames) free(g_pfwFrames);
+ g_pfwFrames = NULL;
+ g_nFramesCount = 0;
+ UnregisterClass(CLUIFrameTitleBarClassName,g_hInst);
+ DeleteObject(_hTitleBarFont);
+
+ _cluiFramesModuleCSInitialized = FALSE;
+ DeleteCriticalSection(&_cluiFramesModuleCS);
+ return 0;
+}
+
+static int _us_DoSetFramePaintProc(WPARAM wParam, LPARAM lParam)
+{
+ if ( !wParam) return 0;
+ {
+ // LOOK REQUIRED OR SYNC CALL NEEDED
+ FRAMEWND *frm = FindFrameByItsHWND((HWND)wParam);
+ if ( !frm) return 0;
+ if (lParam)
+ frm->PaintCallbackProc = (tPaintCallbackProc)lParam;
+ else
+ frm->PaintCallbackProc = NULL;
+ return 1;
+ }
+}
+int CLUIFrames_SetLayeredMode( BOOL fLayeredMode, HWND hwnd )
+{
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if (fLayeredMode)
+ {
+ if (g_pfwFrames[i].visible && GetParent(g_pfwFrames[i].hWnd) == pcli->hwndContactList && g_pfwFrames[i].PaintCallbackProc == NULL)
+ {
+ //create owner window
+ g_pfwFrames[i].OwnerWindow = CreateSubContainerWindow(pcli->hwndContactList,g_pfwFrames[i].FloatingPos.x,g_pfwFrames[i].FloatingPos.y,10,10);
+ SetParent(g_pfwFrames[i].hWnd,g_pfwFrames[i].OwnerWindow);
+ }
+ }
+ else
+ {
+ if (GetParent(g_pfwFrames[i].hWnd) == g_pfwFrames[i].OwnerWindow)
+ {
+ SetParent(g_pfwFrames[i].hWnd,hwnd);
+ if ((INT_PTR)g_pfwFrames[i].OwnerWindow>0)
+ {
+ DestroyWindow(g_pfwFrames[i].OwnerWindow);
+ g_pfwFrames[i].OwnerWindow = (HWND)-2;
+ }
+ }
+ }
+ }
+
+ CLUIFrames_UpdateFrame((WPARAM)-1,0); //update all frames
+ return 0;
+}
+
+int CLUIFrames_UpdateBorders()
+{
+ for ( int i=0; i < g_nFramesCount; i++ )
+ {
+ if ( !g_pfwFrames[i].floating )
+ {
+ DWORD style = (int)GetWindowLongPtr( g_pfwFrames[i].hWnd, GWL_STYLE ) & ( ~WS_BORDER );
+ if ( !g_CluiData.fLayered && g_pfwFrames[i].UseBorder ) style |= WS_BORDER;
+ SetWindowLongPtr( g_pfwFrames[i].hWnd, GWL_STYLE, style );
+ CLUIFramesModifyMainMenuItems( g_pfwFrames[i].id, 0 );
+ RedrawWindow( g_pfwFrames[i].hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE );
+ };
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_cluiservices.cpp b/plugins/Clist_modern/src/modern_cluiservices.cpp
new file mode 100644
index 0000000000..0b48b0ec47
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_cluiservices.cpp
@@ -0,0 +1,178 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "m_clui.h"
+#include "hdr/modern_commonprototypes.h"
+
+INT_PTR CListTray_GetGlobalStatus(WPARAM wparam,LPARAM lparam);
+
+int CLUIUnreadEmailCountChanged(WPARAM wParam,LPARAM lParam)
+{
+ CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE, 0 ,0);
+ return 0;
+}
+
+INT_PTR CLUIServices_ProtocolStatusChanged(WPARAM wParam,LPARAM lParam)
+{
+ CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,(WPARAM)pcli->hwndStatus,0);
+ if (lParam) cliTrayIconUpdateBase((char*)lParam);
+ return 0;
+}
+
+void cliCluiProtocolStatusChanged(int status,const char * proto)
+{
+ CLUIServices_ProtocolStatusChanged((WPARAM)status,(LPARAM)proto);
+}
+
+INT_PTR SortList(WPARAM wParam,LPARAM lParam)
+{
+ pcli->pfnClcBroadcast( WM_TIMER,TIMERID_DELAYEDRESORTCLC,0);
+ pcli->pfnClcBroadcast( INTM_SCROLLBARCHANGED,0,0);
+
+ return 0;
+}
+
+static INT_PTR MetaSupportCheck(WPARAM wParam,LPARAM lParam)
+{
+ return 1;
+}
+
+static INT_PTR GetHwnd(WPARAM wParam, LPARAM lParam)
+{
+ return (INT_PTR)pcli->hwndContactList;
+}
+
+static INT_PTR GetHwndTree(WPARAM wParam,LPARAM lParam)
+{
+ return (INT_PTR)pcli->hwndContactTree;
+}
+
+static INT_PTR GroupAdded(WPARAM wParam, LPARAM lParam)
+{
+ //CLC does this automatically unless it's a new group
+ if (lParam) {
+ HANDLE hItem;
+ TCHAR szFocusClass[64];
+ HWND hwndFocus = GetFocus();
+
+ GetClassName(hwndFocus, szFocusClass, SIZEOF(szFocusClass));
+ if ( !lstrcmp(szFocusClass, CLISTCONTROL_CLASS)) {
+ hItem = (HANDLE) SendMessage(hwndFocus, CLM_FINDGROUP, wParam, 0);
+ if (hItem)
+ SendMessage(hwndFocus, CLM_EDITLABEL, (WPARAM) hItem, 0);
+ }
+ }
+ return 0;
+}
+
+static INT_PTR ContactSetIcon(WPARAM wParam, LPARAM lParam)
+{
+ //unnecessary: CLC does this automatically
+ return 0;
+}
+
+static INT_PTR ContactDeleted(WPARAM wParam, LPARAM lParam)
+{
+ //unnecessary: CLC does this automatically
+ return 0;
+}
+
+static INT_PTR ContactAdded(WPARAM wParam, LPARAM lParam)
+{
+ //unnecessary: CLC does this automatically
+ return 0;
+}
+
+static INT_PTR ListBeginRebuild(WPARAM wParam, LPARAM lParam)
+{
+ //unnecessary: CLC does this automatically
+ return 0;
+}
+
+static INT_PTR ContactRenamed(WPARAM wParam, LPARAM lParam)
+{
+ //unnecessary: CLC does this automatically
+ return 0;
+}
+
+static INT_PTR ListEndRebuild(WPARAM wParam, LPARAM lParam)
+{
+ int rebuild = 0;
+ //CLC does this automatically, but we need to force it if hideoffline or hideempty has changed
+ if ((db_get_b(NULL, "CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT) == 0) != ((GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & CLS_HIDEOFFLINE) == 0)) {
+ if (db_get_b(NULL, "CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT))
+ SetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) | CLS_HIDEOFFLINE);
+ else
+ SetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & ~CLS_HIDEOFFLINE);
+ rebuild = 1;
+ }
+ if ((db_get_b(NULL, "CList", "HideEmptyGroups", SETTING_HIDEEMPTYGROUPS_DEFAULT) == 0) != ((GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & CLS_HIDEEMPTYGROUPS) == 0)) {
+ if (db_get_b(NULL, "CList", "HideEmptyGroups", SETTING_HIDEEMPTYGROUPS_DEFAULT))
+ SetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) | CLS_HIDEEMPTYGROUPS);
+ else
+ SetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & ~CLS_HIDEEMPTYGROUPS);
+ rebuild = 1;
+ }
+ if ((db_get_b(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT) == 0) != ((GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & CLS_USEGROUPS) == 0)) {
+ if (db_get_b(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT))
+ SetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) | CLS_USEGROUPS);
+ else
+ SetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & ~CLS_USEGROUPS);
+ rebuild = 1;
+ }
+ if (rebuild)
+ SendMessage(pcli->hwndContactTree, CLM_AUTOREBUILD, 0, 0);
+ return 0;
+}
+
+static int GetCaps(WPARAM wParam, LPARAM lParam)
+{
+ switch (wParam) {
+ case CLUICAPS_FLAGS1:
+ return CLUIF_HIDEEMPTYGROUPS | CLUIF_DISABLEGROUPS | CLUIF_HASONTOPOPTION | CLUIF_HASAUTOHIDEOPTION;
+ }
+ return 0;
+}
+
+
+
+int CLUIServices_LoadModule(void)
+{
+ CreateServiceFunction(MS_CLUI_METASUPPORT,MetaSupportCheck);
+ CreateServiceFunction(MS_CLUI_PROTOCOLSTATUSCHANGED,CLUIServices_ProtocolStatusChanged);
+ CreateServiceFunction(MS_CLUI_SORTLIST,SortList);
+ CreateServiceFunction(MS_CLIST_GETSTATUSMODE,CListTray_GetGlobalStatus);
+
+ CreateServiceFunction(MS_CLUI_GETHWND, GetHwnd);
+ CreateServiceFunction(MS_CLUI_GETHWNDTREE,GetHwndTree);
+ CreateServiceFunction(MS_CLUI_GROUPADDED, GroupAdded);
+ CreateServiceFunction(MS_CLUI_CONTACTSETICON, ContactSetIcon);
+ CreateServiceFunction(MS_CLUI_CONTACTADDED, ContactAdded);
+ CreateServiceFunction(MS_CLUI_CONTACTDELETED, ContactDeleted);
+ CreateServiceFunction(MS_CLUI_CONTACTRENAMED, ContactRenamed);
+ CreateServiceFunction(MS_CLUI_LISTBEGINREBUILD, ListBeginRebuild);
+ CreateServiceFunction(MS_CLUI_LISTENDREBUILD, ListEndRebuild);
+ return 0;
+}
+
diff --git a/plugins/Clist_modern/src/modern_commonheaders.cpp b/plugins/Clist_modern/src/modern_commonheaders.cpp
new file mode 100644
index 0000000000..45c2709d2b
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_commonheaders.cpp
@@ -0,0 +1,247 @@
+#define DB_USEHELPERFUNCTIONS
+#include "hdr/modern_commonheaders.h"
+
+BYTE gl_TrimText = 1;
+
+char * __cdecl strstri( char *a, const char *b)
+{
+ char * x, *y;
+ if ( !a || !b) return FALSE;
+ x = _strdup(a);
+ y = _strdup(b);
+ x = _strupr(x);
+ y = _strupr(y);
+ char * pos = strstr(x,y);
+ if ( pos )
+ {
+ char * retval = a + ( pos - x );
+ free(x);
+ free(y);
+ return retval;
+ }
+ free(x);
+ free(y);
+ return NULL;
+}
+int __cdecl mir_strcmpi(const char *a, const char *b)
+{
+ if (a == NULL && b == NULL) return 0;
+ if (a == NULL || b == NULL) return _stricmp(a?a:"",b?b:"");
+ return _stricmp(a,b);
+}
+
+int __cdecl mir_tstrcmpi(const TCHAR *a, const TCHAR *b)
+{
+ if (a == NULL && b == NULL) return 0;
+ if (a == NULL || b == NULL) return _tcsicmp(a?a:_T(""),b?b:_T(""));
+ return _tcsicmp(a,b);
+}
+BOOL __cdecl mir_bool_strcmpi(const char *a, const char *b)
+{
+ if (a == NULL && b == NULL) return 1;
+ if (a == NULL || b == NULL) return _stricmp(a?a:"",b?b:"") == 0;
+ return _stricmp(a,b) == 0;
+}
+
+BOOL __cdecl mir_bool_tstrcmpi(const TCHAR *a, const TCHAR *b)
+{
+ if (a == NULL && b == NULL) return 1;
+ if (a == NULL || b == NULL) return _tcsicmp(a?a:_T(""),b?b:_T("")) == 0;
+ return _tcsicmp(a,b) == 0;
+}
+
+#ifdef strlen
+#undef strcmp
+#undef strlen
+#endif
+
+int __cdecl mir_strcmp (const char *a, const char *b)
+{
+ if ( !(a && b)) return a != b;
+ return (strcmp(a,b));
+};
+
+int mir_strlen (const char *a)
+{
+ if (a == NULL) return 0;
+ return (int)(strlen(a));
+};
+
+#define strlen(a) mir_strlen(a)
+#define strcmp(a,b) mir_strcmp(a,b)
+
+/*
+__inline void *mir_calloc( size_t num, size_t size )
+{
+ void *p = mir_alloc(num*size);
+ if (p == NULL) return NULL;
+ memset(p,0,num*size);
+ return p;
+};
+*/
+wchar_t * mir_strdupW(const wchar_t * src)
+{
+ wchar_t * p;
+ if (src == NULL) return NULL;
+ p = (wchar_t *) mir_alloc((lstrlenW(src)+1)*sizeof(wchar_t));
+ if ( !p) return 0;
+ lstrcpyW(p, src);
+ return p;
+}
+
+//copy len symbols from string - do not check is it null terminated or len is more then actual
+char * strdupn(const char * src, int len)
+{
+ char * p;
+ if (src == NULL) return NULL;
+ p = (char*)malloc(len+1);
+ if ( !p) return 0;
+ memcpy(p,src,len);
+ p[len] = '\0';
+ return p;
+}
+
+DWORD exceptFunction(LPEXCEPTION_POINTERS EP)
+{
+ //printf("1 "); // printed first
+ char buf[4096];
+
+
+ mir_snprintf(buf, SIZEOF(buf), "\r\nExceptCode: %x\r\nExceptFlags: %x\r\nExceptAddress: %p\r\n",
+ EP->ExceptionRecord->ExceptionCode,
+ EP->ExceptionRecord->ExceptionFlags,
+ EP->ExceptionRecord->ExceptionAddress
+ );
+ TRACE(buf);
+ MessageBoxA(0,buf,"clist_mw Exception",0);
+
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+#ifdef _DEBUG
+#undef DeleteObject
+#endif
+
+void TRACE_ERROR()
+{
+ DWORD t = GetLastError();
+ LPVOID lpMsgBuf;
+ if ( !FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ t,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL ))
+ {
+ // Handle the error.
+ return ;
+ }
+#ifdef _DEBUG
+ MessageBox( NULL, (LPCTSTR)lpMsgBuf, _T("Error"), MB_OK | MB_ICONINFORMATION );
+ DebugBreak();
+#endif
+ LocalFree( lpMsgBuf );
+
+}
+
+BOOL DebugDeleteObject(HGDIOBJ a)
+{
+ BOOL res = DeleteObject(a);
+ if ( !res) TRACE_ERROR();
+ return res;
+}
+
+BOOL mod_DeleteDC(HDC hdc)
+{
+// ske_ResetTextEffect(hdc);
+ return DeleteDC(hdc);
+}
+#ifdef _DEBUG
+#define DeleteObject(a) DebugDeleteObject(a)
+#endif
+
+
+// load small icon (shared) it's not need to be destroyed
+
+HICON LoadSmallIconShared(HINSTANCE hInstance, LPCTSTR lpIconName)
+{
+ int cx = GetSystemMetrics(SM_CXSMICON);
+ return (HICON)LoadImage(hInstance,lpIconName, IMAGE_ICON,cx,cx, LR_DEFAULTCOLOR|LR_SHARED);
+}
+
+// load small icon (not shared) it IS NEED to be destroyed
+HICON LoadSmallIcon(HINSTANCE hInstance, LPCTSTR lpIconName)
+{
+ HICON hIcon = NULL; // icon handle
+ int index = -(int)lpIconName;
+ TCHAR filename[MAX_PATH] = {0};
+ GetModuleFileName(hInstance,filename,MAX_PATH);
+ ExtractIconEx(filename,index,NULL,&hIcon,1);
+ return hIcon;
+}
+
+// load small icon from hInstance
+HICON LoadIconEx(HINSTANCE hInstance, LPCTSTR lpIconName, BOOL bShared)
+{
+ HICON hResIcon = bShared?LoadSmallIcon(hInstance,lpIconName):LoadSmallIconShared(hInstance,lpIconName);
+ if ( !hResIcon) //Icon not found in hInstance lets try to load it from core
+ {
+ HINSTANCE hCoreInstance = GetModuleHandle(NULL);
+ if (hCoreInstance != hInstance)
+ hResIcon = bShared?LoadSmallIcon(hInstance,lpIconName):LoadSmallIconShared(hInstance,lpIconName);
+ }
+ return hResIcon;
+}
+
+BOOL DestroyIcon_protect(HICON icon)
+{
+ if (icon) return DestroyIcon(icon);
+ return FALSE;
+}
+
+void li_ListDestruct(SortedList *pList, ItemDestuctor pItemDestructor)
+{
+ int i=0;
+ if ( !pList) return;
+ for (i=0; i < pList->realCount; i++) pItemDestructor(pList->items[i]);
+ List_Destroy(pList);
+ mir_free(pList);
+}
+
+void li_RemoveDestruct(SortedList *pList, int index, ItemDestuctor pItemDestructor)
+{
+ if (index >= 0 && index < pList->realCount)
+ {
+ pItemDestructor(pList->items[index]);
+ List_Remove(pList, index);
+ }
+}
+
+void li_RemovePtrDestruct(SortedList *pList, void * ptr, ItemDestuctor pItemDestructor)
+{
+ if (List_RemovePtr(pList, ptr))
+ pItemDestructor(ptr);
+}
+
+void li_SortList(SortedList *pList, FSortFunc pSortFunct)
+{
+ FSortFunc pOldSort = pList->sortFunc;
+ int i;
+ if ( !pSortFunct) pSortFunct = pOldSort;
+ pList->sortFunc = NULL;
+ for (i=0; i < pList->realCount-1; i++)
+ if (pOldSort(pList->items[i],pList->items[i+1]) < 0)
+ {
+ void * temp = pList->items[i];
+ pList->items[i] = pList->items[i+1];
+ pList->items[i+1] = temp;
+ i--;
+ if (i>0) i--;
+ }
+ pList->sortFunc = pOldSort;
+}
diff --git a/plugins/Clist_modern/src/modern_contact.cpp b/plugins/Clist_modern/src/modern_contact.cpp
new file mode 100644
index 0000000000..7b1ba95544
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_contact.cpp
@@ -0,0 +1,219 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "hdr/modern_commonprototypes.h"
+
+struct
+{
+ int m_cache_nStatus,order;
+} statusModeOrder[] = {
+ {ID_STATUS_OFFLINE,500},
+ {ID_STATUS_ONLINE,10},
+ {ID_STATUS_AWAY,200},
+ {ID_STATUS_DND,110},
+ {ID_STATUS_NA,450},
+ {ID_STATUS_OCCUPIED,100},
+ {ID_STATUS_FREECHAT,0},
+ {ID_STATUS_INVISIBLE,20},
+ {ID_STATUS_ONTHEPHONE,150},
+ {ID_STATUS_OUTTOLUNCH,425}};
+
+static int GetContactStatus(HANDLE hContact)
+{
+ return (GetContactCachedStatus(hContact));
+}
+
+
+void cli_ChangeContactIcon(HANDLE hContact,int iIcon,int add)
+{
+ corecli.pfnChangeContactIcon((HANDLE) hContact,(int) iIcon,(int) add);
+}
+
+static int GetStatusModeOrdering(int statusMode)
+{
+ int i;
+ for (i=0;i < SIZEOF(statusModeOrder);i++)
+ if (statusModeOrder[i].m_cache_nStatus == statusMode) return statusModeOrder[i].order;
+ return 1000;
+}
+
+
+DWORD CompareContacts2_getLMTime(HANDLE hContact)
+{
+ HANDLE hDbEvent;
+ DBEVENTINFO dbei = {0};
+
+ hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0);
+ while(hDbEvent) {
+ dbei.cbSize = sizeof(dbei);
+ dbei.pBlob = 0;
+ dbei.cbBlob = 0;
+ CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei);
+ if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT))
+ return dbei.timestamp;
+ hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hDbEvent, 0);
+ }
+ return 0;
+}
+
+#define SAFESTRING(a) a?a:""
+#define SAFETSTRING(a) a?a:_T("")
+
+int GetProtoIndex(char * szName)
+{
+ PROTOACCOUNT **accs = NULL;
+ int accCount = 0;
+ int i;
+ if ( !szName) return -1;
+ ProtoEnumAccounts( &accCount, &accs );
+ for (i=0; i < accCount; i++)
+ if ( !mir_strcmpi(szName,accs[i]->szModuleName))
+ return accs[i]->iOrder;
+ return -1;
+}
+
+int CompareContacts2(const struct ClcContact *contact1,const struct ClcContact *contact2, int by)
+{
+
+ HANDLE a;
+ HANDLE b;
+ TCHAR *namea, *nameb;
+ int statusa,statusb;
+ char *szProto1,*szProto2;
+
+ if ((INT_PTR)contact1 < 100 || (INT_PTR)contact2 < 100) return 0;
+
+ a = contact1->hContact;
+ b = contact2->hContact;
+
+ namea = (TCHAR *)contact1->szText;
+ statusa = GetContactCachedStatus(contact1->hContact);
+ szProto1 = contact1->proto;
+
+ nameb = (TCHAR *)contact2->szText;
+ statusb = GetContactCachedStatus(contact2->hContact);
+ szProto2 = contact2->proto;
+
+
+ if (by == SORTBY_STATUS)
+ { //status
+ int ordera,orderb;
+ ordera = GetStatusModeOrdering(statusa);
+ orderb = GetStatusModeOrdering(statusb);
+ if (ordera != orderb) return ordera-orderb;
+ else return 0;
+ }
+
+
+ if (g_CluiData.fSortNoOfflineBottom == 0 && (statusa == ID_STATUS_OFFLINE) != (statusb == ID_STATUS_OFFLINE)) { //one is offline: offline goes below online
+ return 2*(statusa == ID_STATUS_OFFLINE)-1;
+ }
+
+ if (by == SORTBY_NAME)
+ { //name
+ return mir_tstrcmpi(namea,nameb);
+ }
+ if (by == SORTBY_NAME_LOCALE)
+ { //name
+ static int LocaleId = -1;
+ if (LocaleId == -1) LocaleId = CallService(MS_LANGPACK_GETLOCALE,0,0);
+ return (CompareString(LocaleId,NORM_IGNORECASE,SAFETSTRING(namea),-1,SAFETSTRING(nameb),-1))-2;
+ }
+ else if (by == SORTBY_LASTMSG)
+ { //last message
+ DWORD ta = CompareContacts2_getLMTime(a);
+ DWORD tb = CompareContacts2_getLMTime(b);
+ return tb-ta;
+ }
+ else if (by == SORTBY_PROTO)
+ {
+ int rc = GetProtoIndex(szProto1)-GetProtoIndex(szProto2);
+
+ if (rc != 0 && (szProto1 != NULL && szProto2 != NULL)) return rc;
+ }
+ else if (by == SORTBY_RATE)
+ return contact2->bContactRate-contact1->bContactRate;
+ // else :o)
+ return 0;
+}
+
+int cliCompareContacts(const struct ClcContact *contact1,const struct ClcContact *contact2)
+{
+ int i, r;
+ for (i=0; i < SIZEOF(g_CluiData.bSortByOrder); i++)
+ {
+ r = CompareContacts2(contact1, contact2, g_CluiData.bSortByOrder[i]);
+ if (r != 0)
+ return r;
+ }
+ return 0;
+}
+
+#undef SAFESTRING
+
+INT_PTR ContactChangeGroup(WPARAM wParam,LPARAM lParam)
+{
+ CallService(MS_CLUI_CONTACTDELETED,wParam,0);
+ if ((HANDLE)lParam == NULL)
+ db_unset((HANDLE)wParam,"CList","Group");
+ else
+ db_set_ws((HANDLE)wParam,"CList","Group",pcli->pfnGetGroupName(lParam, NULL));
+ CallService(MS_CLUI_CONTACTADDED,wParam,ExtIconFromStatusMode((HANDLE)wParam,(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,wParam,0),GetContactStatus((HANDLE)wParam)));
+ return 0;
+}
+
+INT_PTR ToggleHideOffline(WPARAM wParam,LPARAM lParam)
+{
+ return pcli->pfnSetHideOffline((WPARAM)-1,0);
+}
+
+INT_PTR ToggleGroups(WPARAM wParam,LPARAM lParam)
+{
+
+ db_set_b(NULL, "CList", "UseGroups",
+ (BYTE) !db_get_b(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT));
+ pcli->pfnLoadContactTree();
+ return 0;
+}
+
+INT_PTR SetUseGroups(WPARAM wParam, LPARAM lParam)
+{
+ int newVal = !(GetWindowLongPtr(pcli->hwndContactTree,GWL_STYLE)&CLS_USEGROUPS);
+ if ( wParam != -1 )
+ {
+ if ( !newVal == wParam ) return 0;
+ newVal = wParam;
+ }
+ db_set_b(NULL,"CList","UseGroups",(BYTE)newVal);
+ SendMessage(pcli->hwndContactTree,CLM_SETUSEGROUPS,newVal,0);
+ return 0;
+}
+
+INT_PTR ToggleSounds(WPARAM wParam,LPARAM lParam)
+{
+ db_set_b(NULL, "Skin", "UseSound",
+ (BYTE) !db_get_b(NULL, "Skin", "UseSound", SETTING_ENABLESOUNDS_DEFAULT ));
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_docking.cpp b/plugins/Clist_modern/src/modern_docking.cpp
new file mode 100644
index 0000000000..e05de26096
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_docking.cpp
@@ -0,0 +1,372 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "hdr/modern_clist.h"
+#include "m_api/m_skin_eng.h"
+#include "m_api/m_skinbutton.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_sync.h"
+
+#define WM_DOCKCALLBACK (WM_USER+121)
+#define WM_CREATEDOCKED (WM_USER+122)
+#define EDGESENSITIVITY 3
+
+#define DOCKED_NONE 0
+#define DOCKED_LEFT 1
+#define DOCKED_RIGHT 2
+
+BOOL LockSubframeMoving = 0;
+static int TempDock = 0;
+static int dock_drag_dx = 0;
+static int dock_drag_dy = 0;
+
+static void Docking_GetMonitorRectFromPoint(POINT pt,RECT *rc)
+{
+ HMODULE hUserInstance = GetModuleHandle(_T("user32"));
+
+ if ( MyMonitorFromPoint )
+ {
+ MONITORINFO monitorInfo;
+ HMONITOR hMonitor = MyMonitorFromPoint(pt,MONITOR_DEFAULTTONEAREST); // always returns a valid value
+ monitorInfo.cbSize = sizeof(MONITORINFO);
+
+ if ( MyGetMonitorInfo(hMonitor,&monitorInfo))
+ {
+ CopyMemory(rc,&monitorInfo.rcMonitor,sizeof(RECT));
+ return;
+ }
+ }
+
+ // "generic" win95/NT support, also serves as failsafe
+ rc->left = 0;
+ rc->top = 0;
+ rc->bottom = GetSystemMetrics(SM_CYSCREEN);
+ rc->right = GetSystemMetrics(SM_CXSCREEN);
+}
+
+void Docking_GetMonitorRectFromWindow(HWND hWnd,RECT *rc)
+{
+ POINT ptWindow;
+ GetWindowRect(hWnd,rc);
+ ptWindow.x = rc->left;
+ ptWindow.y = rc->top;
+ Docking_GetMonitorRectFromPoint(ptWindow,rc);
+}
+
+static void Docking_AdjustPosition(HWND hwnd,RECT *rcDisplay,RECT *rc)
+{
+ APPBARDATA abd;
+
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = hwnd;
+ abd.uEdge = g_CluiData.fDocked == DOCKED_LEFT?ABE_LEFT:ABE_RIGHT;
+ abd.rc = *rc;
+ abd.rc.top = rcDisplay->top;
+ abd.rc.bottom = rcDisplay->bottom;
+ if (g_CluiData.fDocked == DOCKED_LEFT) {
+ abd.rc.right = rcDisplay->left+abd.rc.right-abd.rc.left;
+ abd.rc.left = rcDisplay->left;
+ }
+ else {
+ abd.rc.left = rcDisplay->right-(abd.rc.right-abd.rc.left);
+ abd.rc.right = rcDisplay->right;
+
+ }
+ SHAppBarMessage(ABM_SETPOS,&abd);
+ *rc = abd.rc;
+}
+
+int Docking_IsDocked(WPARAM wParam,LPARAM lParam)
+{
+ return g_CluiData.fDocked;
+}
+
+int Docking_ProcessWindowMessage(WPARAM wParam,LPARAM lParam)
+{
+ APPBARDATA abd;
+ static int draggingTitle;
+ MSG *msg = (MSG*)wParam;
+
+ if (msg->message == WM_DESTROY)
+ db_set_b(NULL,"CList","Docked",(BYTE)g_CluiData.fDocked);
+
+ if ( !g_CluiData.fDocked && msg->message != WM_CREATE && msg->message != WM_MOVING && msg->message != WM_CREATEDOCKED && msg->message != WM_MOVE && msg->message != WM_SIZE) return 0;
+ switch(msg->message) {
+ case WM_CREATE:
+ //if (GetSystemMetrics(SM_CMONITORS)>1) return 0;
+ if (db_get_b(NULL,"CList","Docked",0) && db_get_b(NULL,"CLUI","DockToSides",SETTING_DOCKTOSIDES_DEFAULT))
+ {
+ PostMessage(msg->hwnd,WM_CREATEDOCKED,0,0);
+ }
+ draggingTitle = 0;
+ return 0;
+
+ case WM_CREATEDOCKED:
+ //we need to post a message just after creation to let main message function do some work
+ g_CluiData.fDocked = (BOOL)db_get_b(NULL,"CList","Docked",0);
+ if (IsWindowVisible(msg->hwnd) && !IsIconic(msg->hwnd)) {
+ RECT rc, rcMonitor;
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ abd.lParam = 0;
+ abd.uCallbackMessage = WM_DOCKCALLBACK;
+ SHAppBarMessage(ABM_NEW,&abd);
+ GetWindowRect(msg->hwnd,&rc);
+ Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
+ Docking_AdjustPosition(msg->hwnd,&rcMonitor,&rc);
+ MoveWindow(msg->hwnd,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,TRUE);
+ g_CluiData.mutexPreventDockMoving = 0;
+ Sync(CLUIFrames_OnMoving,msg->hwnd,&rc);
+ g_CluiData.mutexPreventDockMoving = 1;
+ ModernSkinButton_ReposButtons( msg->hwnd, SBRF_DO_NOT_DRAW, NULL );
+ }
+ break;
+ case WM_CAPTURECHANGED:
+ ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_NOT_DRAW,NULL);
+ return 0;
+ case WM_ACTIVATE:
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ SHAppBarMessage(ABM_ACTIVATE,&abd);
+ return 0;
+ case WM_SIZE:
+ ModernSkinButton_ReposButtons( msg->hwnd, SBRF_DO_REDRAW_ALL, NULL );
+ return 0;
+
+ case WM_WINDOWPOSCHANGED:
+ {
+ if (g_CluiData.fDocked) ModernSkinButton_ReposButtons( msg->hwnd,SBRF_DO_NOT_DRAW, NULL );
+ return 0;
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ SHAppBarMessage(ABM_WINDOWPOSCHANGED,&abd);
+ ModernSkinButton_ReposButtons( msg->hwnd, SBRF_DO_NOT_DRAW, NULL );
+ return 0;
+ }
+ case WM_MOVING:
+ {
+ RECT rcMonitor;
+ RECT rcWindow;
+ RECT *rc;
+ int dx = 0;
+ POINT ptCursor;
+ if (g_CluiData.fDocked) return 0;
+ // stop early
+ BOOL bControlled = (BOOL)(GetAsyncKeyState(VK_CONTROL)&0x8000);
+
+ // GetMessagePos() is no good, position is always unsigned
+ GetCursorPos(&ptCursor);
+ GetWindowRect(msg->hwnd,&rcWindow);
+ dock_drag_dx = rcWindow.left-ptCursor.x;
+ dock_drag_dy = rcWindow.top-ptCursor.y;
+ Docking_GetMonitorRectFromPoint(ptCursor,&rcMonitor);
+
+ if (((ptCursor.x < rcMonitor.left+EDGESENSITIVITY)
+ || (ptCursor.x >= rcMonitor.right-EDGESENSITIVITY))
+ && db_get_b(NULL,"CLUI","DockToSides",SETTING_DOCKTOSIDES_DEFAULT))
+ {
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ abd.lParam = 0;
+ abd.uCallbackMessage = WM_DOCKCALLBACK;
+ SHAppBarMessage(ABM_NEW,&abd);
+ if (ptCursor.x < rcMonitor.left+EDGESENSITIVITY) g_CluiData.fDocked = DOCKED_LEFT;
+ else g_CluiData.fDocked = DOCKED_RIGHT;
+ // TempDock = 1;
+ GetWindowRect(msg->hwnd,(LPRECT)msg->lParam);
+ rc = (RECT*)msg->lParam;
+ if (g_CluiData.fDocked == DOCKED_RIGHT)
+ dx = (rc->right>rcMonitor.right)?rc->right-rcMonitor.right:0;
+ else
+ dx = (rc->left < rcMonitor.left)?rc->left-rcMonitor.left:0;
+ OffsetRect(rc,-dx,0);
+ Docking_AdjustPosition(msg->hwnd,(LPRECT)&rcMonitor,(LPRECT)msg->lParam);
+ SendMessage(msg->hwnd,WM_SIZE,0,0);
+ g_CluiData.mutexPreventDockMoving = 0;
+ Sync(CLUIFrames_OnMoving,msg->hwnd,(LPRECT)msg->lParam);
+ g_CluiData.mutexPreventDockMoving = 1;
+ mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
+ db_set_b(NULL,"CList","Docked",(BYTE)g_CluiData.fDocked);
+ ModernSkinButton_ReposButtons( msg->hwnd, SBRF_DO_NOT_DRAW, NULL );
+ return TRUE;
+ }
+ return 0;
+ }
+ case WM_EXITSIZEMOVE:
+ {
+ RECT rcMonitor;
+ RECT rcWindow;
+ if (TempDock) TempDock = 0;
+ GetWindowRect(msg->hwnd,&rcWindow);
+ Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
+ Docking_AdjustPosition(msg->hwnd,&rcMonitor,&rcWindow);
+ *((LRESULT*)lParam) = TRUE;
+ g_CluiData.mutexPreventDockMoving = 0;
+ SetWindowPos(msg->hwnd,0,rcWindow.left,rcWindow.top,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOSENDCHANGING);
+ Sync(CLUIFrames_OnMoving,msg->hwnd,&rcWindow);
+ ModernSkinButton_ReposButtons( msg->hwnd, SBRF_DO_NOT_DRAW, NULL );// -= -= -=
+ g_CluiData.mutexPreventDockMoving = 1;
+ return 1;
+ }
+
+ case WM_MOVE:
+ {
+
+ if (g_CluiData.fDocked && 0) {
+ RECT rc, rcMonitor;
+ Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
+ GetWindowRect(msg->hwnd,&rc);
+ Docking_AdjustPosition(msg->hwnd,&rcMonitor,&rc);
+ MoveWindow(msg->hwnd,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,TRUE);
+ Sync(CLUIFrames_OnMoving,msg->hwnd,&rc);
+ ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_NOT_DRAW, NULL);// -= -= -=
+
+ return 1;
+ }
+ ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_ALT_DRAW, NULL);
+ return 0;
+ }
+ case WM_SIZING:
+ {
+
+ /*RECT rcMonitor;
+ Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
+ Docking_AdjustPosition(msg->hwnd,&rcMonitor,(LPRECT)msg->lParam);
+ *((LRESULT*)lParam) = TRUE;
+ */
+ RECT rc;
+ if (g_CluiData.fDocked) ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_NOT_DRAW,NULL);
+ return FALSE;
+ rc = *(RECT*)(msg->lParam);
+ g_CluiData.mutexPreventDockMoving = 0;
+ Sync(CLUIFrames_OnMoving,msg->hwnd,&rc);
+ // -= -= -=
+ return TRUE;
+ }
+ case WM_SHOWWINDOW:
+ {
+ if (msg->lParam) return 0;
+ BOOL toBeDocked = (BOOL) db_get_b(NULL,"CLUI","DockToSides",SETTING_DOCKTOSIDES_DEFAULT);
+ if ((msg->wParam && g_CluiData.fDocked < 0) || (!msg->wParam && g_CluiData.fDocked>0)) g_CluiData.fDocked = -g_CluiData.fDocked;
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ if (msg->wParam) {
+ RECT rc, rcMonitor;
+ Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
+ abd.lParam = 0;
+ abd.uCallbackMessage = WM_DOCKCALLBACK;
+ SHAppBarMessage(ABM_NEW,&abd);
+ GetWindowRect(msg->hwnd,&rc);
+ Docking_AdjustPosition(msg->hwnd,&rcMonitor,&rc);
+ MoveWindow(msg->hwnd,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,FALSE);
+ Sync(CLUIFrames_OnMoving,msg->hwnd,&rc);
+ ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_NOT_DRAW,NULL);// -= -= -=
+ }
+ else {
+ SHAppBarMessage(ABM_REMOVE,&abd);
+ }
+ }
+ return 0;
+ case WM_NCHITTEST:
+ { LONG result;
+ result = DefWindowProc(msg->hwnd,WM_NCHITTEST,msg->wParam,msg->lParam);
+ if (result == HTSIZE || result == HTTOP || result == HTTOPLEFT || result == HTTOPRIGHT ||
+ result == HTBOTTOM || result == HTBOTTOMRIGHT || result == HTBOTTOMLEFT) {*((LRESULT*)lParam) = HTCLIENT; return TRUE;}
+ if (g_CluiData.fDocked == DOCKED_LEFT && result == HTLEFT) {*((LRESULT*)lParam) = HTCLIENT; return TRUE;}
+ if (g_CluiData.fDocked == DOCKED_RIGHT && result == HTRIGHT) {*((LRESULT*)lParam) = HTCLIENT; return TRUE;}
+
+
+ return 0;
+ }
+ case WM_SYSCOMMAND:
+ if ((msg->wParam&0xFFF0) != SC_MOVE) return 0;
+ SetActiveWindow(msg->hwnd);
+ SetCapture(msg->hwnd);
+ draggingTitle = 1;
+ *((LRESULT*)lParam) = 0;
+ return TRUE;
+ case WM_MOUSEMOVE:
+
+ if ( !draggingTitle) return 0;
+ { RECT rc;
+ POINT pt;
+ GetClientRect(msg->hwnd,&rc);
+ if (((g_CluiData.fDocked == DOCKED_LEFT || g_CluiData.fDocked == -DOCKED_LEFT) && (short)LOWORD(msg->lParam)>rc.right) ||
+ ((g_CluiData.fDocked == DOCKED_RIGHT || g_CluiData.fDocked == -DOCKED_RIGHT) && (short)LOWORD(msg->lParam) < 0)) {
+ ReleaseCapture();
+ draggingTitle = 0;
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ SHAppBarMessage(ABM_REMOVE,&abd);
+ g_CluiData.fDocked = 0;
+ GetCursorPos(&pt);
+ PostMessage(msg->hwnd,WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(pt.x,pt.y));
+ SetWindowPos(msg->hwnd,0,pt.x-rc.right/2,pt.y-GetSystemMetrics(SM_CYFRAME)-GetSystemMetrics(SM_CYSMCAPTION)/2,db_get_dw(NULL,"CList","Width",0),db_get_dw(NULL,"CList","Height",0),SWP_NOZORDER);
+ db_set_b(NULL,"CList","Docked",(BYTE)g_CluiData.fDocked);
+ // ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_NOT_DRAW, NULL);
+ }
+ return 1;
+ }
+ case WM_LBUTTONUP:
+ if (draggingTitle) {
+ ReleaseCapture();
+ draggingTitle = 0;
+ }
+ return 0;
+ case WM_DOCKCALLBACK:
+ switch(msg->wParam) {
+ case ABN_WINDOWARRANGE:
+ CLUI_ShowWindowMod(msg->hwnd,msg->lParam?SW_HIDE:SW_SHOW);
+ {
+
+ RECT rc, rcMonitor;
+ Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
+ GetWindowRect(msg->hwnd,&rc);
+ Docking_AdjustPosition(msg->hwnd,&rcMonitor,&rc);
+ Sync(CLUIFrames_OnMoving,msg->hwnd,&rc); // -= -= -=
+ ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_NOT_DRAW, NULL);
+
+ g_CluiData.mutexPreventDockMoving = 1;
+ }
+ break;
+ }
+ return TRUE;
+ case WM_DESTROY:
+ if (g_CluiData.fDocked>0) {
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ SHAppBarMessage(ABM_REMOVE,&abd);
+ ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_NOT_DRAW, NULL);
+ }
+ return 0;
+ }
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_extraimage.cpp b/plugins/Clist_modern/src/modern_extraimage.cpp
new file mode 100644
index 0000000000..3a306081fe
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_extraimage.cpp
@@ -0,0 +1,509 @@
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_commonprototypes.h"
+
+
+
+#define ExtraImageIconsIndexCount 6
+
+bool visar[EXTRACOLUMNCOUNT];
+int ExtraImageIconsIndex[ExtraImageIconsIndexCount];
+int EnabledColumnCount = 0;
+BOOL g_mutex_bSetAllExtraIconsCycle = 0;
+
+static HIMAGELIST hExtraImageList = NULL;
+static HIMAGELIST hWideExtraImageList = NULL;
+
+void ExtraImage_SetAllExtraIcons(HWND hwndList,HANDLE hContact);
+
+void ClearExtraIcons();
+
+bool ImageCreated = FALSE;
+BYTE ExtraOrder[] =
+{
+ 1, // EXTRA_ICON_EMAIL
+ 2, // EXTRA_ICON_PROTO
+ 3, // EXTRA_ICON_SMS
+ 4, // EXTRA_ICON_ADV1
+ 5, // EXTRA_ICON_ADV2
+ 6, // EXTRA_ICON_WEB
+ 7, // EXTRA_ICON_CLIENT
+ 0, // EXTRA_ICON_VISMODE
+ 8, // EXTRA_ICON_ADV3
+ 9, // EXTRA_ICON_ADV4
+};
+
+BOOL HasExtraIconsService()
+{
+ return ServiceExists("ExtraIcon/Register");
+}
+
+bool isColumnVisible(int extra)
+{
+ if (HasExtraIconsService())
+ return true;
+
+ int i=0;
+ for (i=0; i < sizeof(ExtraOrder)/sizeof(ExtraOrder[0]); i++)
+ if (ExtraOrder[i] == extra)
+ {
+ switch(i+1)
+ {
+ case EXTRA_ICON_EMAIL: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_EMAIL",SETTING_EXTRA_ICON_EMAIL_DEFAULT) != 0;
+ case EXTRA_ICON_PROTO: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_PROTO",SETTING_EXTRA_ICON_PROTO_DEFAULT) != 0;
+ case EXTRA_ICON_SMS: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_SMS",SETTING_EXTRA_ICON_SMS_DEFAULT) != 0;
+ case EXTRA_ICON_ADV1: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_ADV1",SETTING_EXTRA_ICON_ADV1_DEFAULT) != 0;
+ case EXTRA_ICON_ADV2: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_ADV2",SETTING_EXTRA_ICON_ADV2_DEFAULT) != 0;
+ case EXTRA_ICON_WEB: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_WEB",SETTING_EXTRA_ICON_WEB_DEFAULT) != 0;
+ case EXTRA_ICON_CLIENT: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_CLIENT",SETTING_EXTRA_ICON_CLIENT_DEFAULT) != 0;
+ case EXTRA_ICON_VISMODE: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_VISMODE",SETTING_EXTRA_ICON_VISMODE_DEFAULT) != 0;
+ case EXTRA_ICON_ADV3: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_ADV3",SETTING_EXTRA_ICON_ADV3_DEFAULT) != 0;
+ case EXTRA_ICON_ADV4: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_ADV4",SETTING_EXTRA_ICON_ADV4_DEFAULT) != 0;
+ }
+ break;
+ }
+ return(FALSE);
+}
+
+void GetVisColumns()
+{
+ visar[0] = isColumnVisible(0);
+ visar[1] = isColumnVisible(1);
+ visar[2] = isColumnVisible(2);
+ visar[3] = isColumnVisible(3);
+ visar[4] = isColumnVisible(4);
+ visar[5] = isColumnVisible(5);
+ visar[6] = isColumnVisible(6);
+ visar[7] = isColumnVisible(7);
+ visar[8] = isColumnVisible(8);
+ visar[9] = isColumnVisible(9);
+};
+
+__inline int bti(bool b)
+{
+ return(b?1:0);
+};
+int colsum(int from,int to)
+{
+ int i,sum;
+ if (from < 0 || from >= EXTRACOLUMNCOUNT){return(-1);};
+ if (to < 0 || to >= EXTRACOLUMNCOUNT){return(-1);};
+ if (to < from){return(-1);};
+
+ sum = 0;
+ for (i = from;i <= to;i++)
+ {
+ sum += bti(visar[i]);
+ };
+ return(sum);
+};
+
+
+
+
+int ExtraImage_ExtraIDToColumnNum(int extra)
+{
+ if (HasExtraIconsService())
+ {
+ if (extra < 1 || extra > EXTRACOLUMNCOUNT)
+ return -1;
+ else
+ return extra-1;
+ }
+
+ int ord = ExtraOrder[extra-1];
+ if ( !visar[ord]) return -1;
+ return (colsum(0,ord)-1);
+};
+
+int ExtraImage_ColumnNumToExtraID(int column)
+{
+ if (HasExtraIconsService())
+ return column+1;
+
+ for (int i=0; i < EXTRA_ICON_COUNT; i++)
+ if (ExtraImage_ExtraIDToColumnNum(i) == column)
+ return i;
+
+ return -1;
+}
+
+INT_PTR SetIconForExtraColumn(WPARAM wParam,LPARAM lParam)
+{
+ pIconExtraColumn piec;
+ int icol;
+ HANDLE hItem;
+
+ if (pcli->hwndContactTree == 0){return(-1);};
+ if (wParam == 0 || lParam == 0){return(-1);};
+ piec = (pIconExtraColumn)lParam;
+
+ if (piec->cbSize != sizeof(IconExtraColumn)){return(-1);};
+ icol = ExtraImage_ExtraIDToColumnNum(piec->ColumnType);
+ if (icol == -1){return(-1);};
+ hItem = (HANDLE)SendMessage(pcli->hwndContactTree,CLM_FINDCONTACT,(WPARAM)wParam,0);
+ if (hItem == 0){return(-1);};
+
+ SendMessage(pcli->hwndContactTree,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(icol,piec->hImage));
+ return(0);
+}
+
+//wparam = hIcon
+//return hImage on success,-1 on failure
+INT_PTR AddIconToExtraImageList(WPARAM wParam,LPARAM lParam)
+{
+ if (hExtraImageList == 0 || wParam == 0)
+ return -1;
+
+ int res = ((int)ImageList_AddIcon(hExtraImageList,(HICON)wParam));
+ return (res > 254) ? -1 : res;
+}
+
+void SetNewExtraColumnCount()
+{
+ LoadPositionsFromDB(ExtraOrder);
+ GetVisColumns();
+
+ int newcount = colsum(0,EXTRACOLUMNCOUNT-1);
+ db_set_b(NULL,CLUIFrameModule,"EnabledColumnCount",(BYTE)newcount);
+ EnabledColumnCount = newcount;
+ SendMessage(pcli->hwndContactTree,CLM_SETEXTRACOLUMNS,EnabledColumnCount,0);
+}
+
+void ExtraImage_ReloadExtraIcons()
+{
+ int count,i;
+ PROTOACCOUNT **accs;
+ HICON hicon;
+ BOOL needFree;
+
+ SendMessage(pcli->hwndContactTree,CLM_SETEXTRACOLUMNSSPACE,db_get_b(NULL,"CLUI","ExtraColumnSpace",18),0);
+ SendMessage(pcli->hwndContactTree,CLM_SETEXTRAIMAGELIST,0,(LPARAM)NULL);
+ if (hExtraImageList){ImageList_Destroy(hExtraImageList);};
+ if (hWideExtraImageList){ImageList_Destroy(hWideExtraImageList);};
+
+ hExtraImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_COLOR32|ILC_MASK,1,256);
+ hWideExtraImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_COLOR32|ILC_MASK,1,256);
+
+ if ( !HasExtraIconsService()) {
+ //loading icons
+ HICON hIcon = LoadSkinnedIcon(SKINICON_OTHER_SENDEMAIL);
+ ExtraImageIconsIndex[0] = ImageList_AddIcon(hExtraImageList, hIcon);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ hIcon = LoadSkinnedIcon(SKINICON_OTHER_SMS);
+ ExtraImageIconsIndex[1] = ImageList_AddIcon(hExtraImageList, hIcon);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ hIcon = LoadSkinnedIcon(SKINICON_EVENT_URL);
+ ExtraImageIconsIndex[2] = ImageList_AddIcon(hExtraImageList, hIcon);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+
+ //calc only needed protocols
+ //adding protocol icons
+ ProtoEnumAccounts( &count, &accs );
+ for (i=0;i < count;i++) {
+ if ( !IsAccountEnabled(accs[i]) || CallProtoService(accs[i]->szModuleName, PS_GETCAPS,PFLAGNUM_2, 0 ) == 0)
+ continue;
+
+ hIcon = LoadSkinnedProtoIcon(accs[i]->szModuleName,ID_STATUS_ONLINE);
+ ImageList_AddIcon(hExtraImageList, hIcon);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ }
+
+ hicon = CLUI_LoadIconFromExternalFile("clisticons.dll",5,TRUE,TRUE,"AlwaysVis","Contact List",Translate("Always Visible"),-IDI_ALWAYSVIS,&needFree);
+ if ( !hicon) {hicon = LoadSmallIcon(g_hInst, MAKEINTRESOURCE(IDI_ALWAYSVIS));needFree = TRUE;}
+ ExtraImageIconsIndex[3] = ImageList_AddIcon(hExtraImageList,hicon );
+ if (needFree) DestroyIcon_protect(hicon);
+
+ hicon = CLUI_LoadIconFromExternalFile("clisticons.dll",6,TRUE,TRUE,"NeverVis","Contact List",Translate("Never Visible"),-IDI_NEVERVIS,&needFree);
+ if ( !hicon) {hicon = LoadSmallIcon(g_hInst, MAKEINTRESOURCE(IDI_NEVERVIS));needFree = TRUE;}
+ ExtraImageIconsIndex[4] = ImageList_AddIcon(hExtraImageList,hicon );
+ if (needFree) DestroyIcon_protect(hicon);
+
+ hicon = CLUI_LoadIconFromExternalFile("clisticons.dll",7,TRUE,TRUE,"ChatActivity","Contact List",Translate("Chat Activity"),-IDI_CHAT,&needFree);
+ if ( !hicon) {hicon = LoadSmallIcon(g_hInst, MAKEINTRESOURCE(IDI_CHAT));needFree = TRUE;}
+ ExtraImageIconsIndex[5] = ImageList_AddIcon(hExtraImageList,hicon );
+ if (needFree) DestroyIcon_protect(hicon);
+ }
+
+ SendMessage(pcli->hwndContactTree,CLM_SETEXTRAIMAGELIST,(WPARAM)hWideExtraImageList,(LPARAM)hExtraImageList);
+ //ExtraImage_SetAllExtraIcons(hImgList);
+ SetNewExtraColumnCount();
+ NotifyEventHooks(g_CluiData.hEventExtraImageListRebuilding,0,0);
+ ImageCreated = TRUE;
+}
+
+void ReAssignExtraIcons()
+{
+ ClearExtraIcons();
+ SetNewExtraColumnCount();
+ ExtraImage_SetAllExtraIcons(pcli->hwndContactTree,0);
+ SendMessage(pcli->hwndContactTree,CLM_AUTOREBUILD,0,0);
+}
+
+void ClearExtraIcons()
+{
+ SetNewExtraColumnCount();
+
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ do {
+ HANDLE hItem = (HANDLE)SendMessage(pcli->hwndContactTree,CLM_FINDCONTACT,(WPARAM)hContact,0);
+ if (hItem == 0)
+ continue;
+
+ for (int i=0;i < EnabledColumnCount;i++)
+ SendMessage(pcli->hwndContactTree,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(i,0xFF));
+ }
+ while(hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0));
+};
+
+void ExtraImage_SetAllExtraIcons(HWND hwndList,HANDLE hContact)
+{
+ HANDLE hItem;
+ int locApparentMode = 0;
+ char * locApparentModeProto = NULL;
+ bool hcontgiven = FALSE;
+ char *szProto;
+ char *(ImgIndex[64]);
+ int maxpr,count,i;
+ PROTOACCOUNT **accs;
+ pdisplayNameCacheEntry pdnce;
+ int em,pr,sms,a1,a2,w1,c1;
+ int tick = 0;
+ g_mutex_bSetAllExtraIconsCycle = 1;
+ hcontgiven = (hContact != 0);
+
+ if (pcli->hwndContactTree == 0){return;};
+ tick = GetTickCount();
+ if (ImageCreated == FALSE) ExtraImage_ReloadExtraIcons();
+
+ SetNewExtraColumnCount();
+
+ BOOL hasExtraIconsService = HasExtraIconsService();
+ if ( !hasExtraIconsService)
+ {
+ em = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_EMAIL);
+ pr = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_PROTO);
+ sms = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_SMS);
+ a1 = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_ADV1);
+ a2 = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_ADV2);
+ w1 = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_WEB);
+ c1 = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_CLIENT);
+
+ memset( ImgIndex, 0, sizeof( ImgIndex ));
+ ProtoEnumAccounts( &count, &accs );
+ maxpr = 0;
+ //calc only needed protocols
+ for (i=0;i < count;i++) {
+ if ( !IsAccountEnabled( accs[i] ) || CallProtoService(accs[i]->szModuleName,PS_GETCAPS,PFLAGNUM_2,0) == 0) continue;
+ ImgIndex[maxpr] = accs[i]->szModuleName;
+ maxpr++;
+ }
+ }
+
+ if (hContact == NULL)
+ {
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ }
+
+ do {
+
+ szProto = NULL;
+ hItem = hContact;
+ if (hItem == 0){continue;};
+ pdnce = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hItem);
+ if (pdnce == NULL) {continue;};
+
+ // szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0);
+ szProto = pdnce->m_cache_cszProto;
+
+ if ( !hasExtraIconsService)
+ {
+ {
+ bool showweb;
+ showweb = FALSE;
+ if (ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_WEB) != -1)
+ {
+
+ if (szProto != NULL)
+ {
+ char *homepage;
+ homepage = db_get_sa(pdnce->hContact,"UserInfo", "Homepage");
+ if ( !homepage)
+ homepage = db_get_sa(pdnce->hContact,pdnce->m_cache_cszProto, "Homepage");
+ if (homepage != NULL)
+ {
+ showweb = TRUE;
+ mir_free(homepage);
+ }
+ }
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_WEB),(showweb)?2:0xFF));
+ }
+ }
+ {
+ DBVARIANT dbv = {0};
+ bool showemail;
+ showemail = TRUE;
+ if (ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_EMAIL) != -1)
+ {
+
+ if (szProto == NULL || DBGetContactSettingString(hContact, szProto, "e-mail",&dbv))
+ {
+ db_free(&dbv);
+ if (DBGetContactSettingString(hContact, "UserInfo", "Mye-mail0", &dbv))
+ showemail = FALSE;
+ }
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_EMAIL),(showemail)?0:0xFF));
+ db_free(&dbv);
+ }
+ }
+
+ {
+ DBVARIANT dbv = {0};
+ bool showsms;
+ showsms = TRUE;
+ if (ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_SMS) != -1)
+ {
+ if (szProto == NULL || DBGetContactSettingString(hContact, szProto, "Cellular",&dbv))
+ {
+ db_free(&dbv);
+ if (DBGetContactSettingString(hContact, "UserInfo", "MyPhone0", &dbv))
+ showsms = FALSE;
+ }
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_SMS),(showsms)?1:0xFF));
+ db_free(&dbv);
+ }
+ }
+
+ if (ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_PROTO) != -1)
+ {
+ for (i=0;i < maxpr;i++)
+ {
+ if ( !mir_strcmp(ImgIndex[i],szProto))
+ {
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_PROTO),i+3));
+ break;
+ };
+ };
+ };
+ if (ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_VISMODE) != -1)
+ {
+ BYTE iconIndex = 0xFF;
+ if (szProto != NULL)
+ {
+ if ( !db_get_b(hContact, szProto, "ChatRoom", 0))
+ {
+ if (pdnce->ApparentMode == ID_STATUS_OFFLINE)
+ iconIndex = ExtraImageIconsIndex[4];
+ else if (pdnce->ApparentMode == ID_STATUS_ONLINE)
+ {
+ if (szProto != locApparentModeProto)
+ {
+ locApparentModeProto = szProto;
+ locApparentMode = CallProtoService(locApparentModeProto,PS_GETSTATUS,0,0);
+ }
+ if (locApparentMode == ID_STATUS_INVISIBLE || db_get_b(NULL,"CList","AlwaysShowAlwaysVisIcon",SETTING_ALWAYSVISICON_DEFAULT) == 1)
+ iconIndex = ExtraImageIconsIndex[3]; }
+ }
+ else
+ {
+ if (pdnce->ApparentMode == ID_STATUS_OFFLINE)
+ iconIndex = ExtraImageIconsIndex[5];
+ else iconIndex = 255;
+ }
+ }
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_VISMODE),iconIndex));
+ }
+ }
+ NotifyEventHooks(g_CluiData.hEventExtraImageApplying,(WPARAM)hContact,0);
+ if (hcontgiven) break;
+ Sleep(0);
+ } while(hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0));
+
+ tick = GetTickCount()-tick;
+ g_mutex_bSetAllExtraIconsCycle = 0;
+ CLUI__cliInvalidateRect(hwndList,NULL,FALSE);
+ Sleep(0);
+}
+
+HWND SetToolTip(HWND hwnd, TCHAR * tip);
+
+HWND tipHWND = NULL;
+
+static int ehhShowExtraInfoTip(WPARAM wParam, LPARAM lParam)
+{
+ CLCEXTRAINFOTIP * eit = (CLCEXTRAINFOTIP *)lParam;
+ //tipHWND = SetToolTip(eit->hwnd,_T("TEST"));
+ //SendMessage(tipHWND,TTM_ACTIVATE,1,0);
+ //SendMessage(tipHWND,TTM_POPUP,0,0);
+ return 1;
+
+}
+
+int ehhHideExtraInfoTip(WPARAM wParam, LPARAM lParam)
+{
+
+ //SendMessage(tipHWND,TTM_ACTIVATE,0,0);
+ return 0;
+
+}
+
+INT_PTR WideSetIconForExtraColumn(WPARAM wParam,LPARAM lParam)
+{
+ pIconExtraColumn piec;
+ int icol;
+ HANDLE hItem;
+
+ if (pcli->hwndContactTree == 0){return(-1);};
+ if (wParam == 0 || lParam == 0){return(-1);};
+ piec = (pIconExtraColumn)lParam;
+
+ if (piec->cbSize != sizeof(IconExtraColumn)){return(-1);};
+ icol = ExtraImage_ExtraIDToColumnNum(piec->ColumnType);
+ if (icol == -1){return(-1);};
+
+ hItem = (HANDLE)SendMessage(pcli->hwndContactTree,CLM_FINDCONTACT,(WPARAM)wParam,0);
+ if (hItem == 0){return(-1);};
+ if (piec->hImage == (HANDLE)0xFF) piec->hImage = (HANDLE)0xFFFF;
+
+ SendMessage(pcli->hwndContactTree,CLM_SETWIDEEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(icol,piec->hImage));
+ return(0);
+};
+
+//wparam = hIcon
+//return hImage on success,-1 on failure
+INT_PTR WideAddIconToExtraImageList(WPARAM wParam,LPARAM lParam)
+{
+ int res = -1;
+ if (hWideExtraImageList == 0 || wParam == 0){return(-1);};
+ res = ((int)ImageList_AddIcon(hWideExtraImageList,(HICON)wParam));
+ if (res == 0xFF) res = ((int)ImageList_AddIcon(hWideExtraImageList,(HICON)wParam));
+ if (res>0xFFFE) return -1;
+ return res;
+};
+static int ehhExtraImage_UnloadModule(WPARAM wParam,LPARAM lParam)
+{
+ if (hExtraImageList) { ImageList_Destroy(hExtraImageList); };
+ if (hWideExtraImageList) { ImageList_Destroy(hWideExtraImageList); };
+ return 0;
+
+}
+void ExtraImage_LoadModule()
+{
+ CreateServiceFunction(MS_CLIST_EXTRA_SET_ICON,WideSetIconForExtraColumn);
+ CreateServiceFunction(MS_CLIST_EXTRA_ADD_ICON,WideAddIconToExtraImageList);
+
+ //CreateServiceFunction(MS_CLIST_EXTRA2_SET_ICON,WideSetIconForExtraColumn);
+ //CreateServiceFunction(MS_CLIST_EXTRA2_ADD_ICON,WideAddIconToExtraImageList);
+
+
+
+ //HookEvent(ME_SKIN2_ICONSCHANGED,OnIconLibIconChanged);
+
+ HookEvent(ME_CLC_SHOWEXTRAINFOTIP, ehhShowExtraInfoTip );
+ HookEvent(ME_CLC_HIDEINFOTIP, ehhHideExtraInfoTip );
+ HookEvent(ME_SYSTEM_SHUTDOWN, ehhExtraImage_UnloadModule );
+};
+
+
+
+
+
diff --git a/plugins/Clist_modern/src/modern_framesmenu.cpp b/plugins/Clist_modern/src/modern_framesmenu.cpp
new file mode 100644
index 0000000000..950bf122bb
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_framesmenu.cpp
@@ -0,0 +1,214 @@
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_commonprototypes.h"
+
+// == == == == == == == == == == == == == Frames
+HANDLE hFrameMenuObject;
+
+//contactmenu exec param(ownerdata)
+//also used in checkservice
+typedef struct{
+ char *szServiceName;
+ int Frameid;
+ INT_PTR param1;
+}
+ FrameMenuExecParam,*lpFrameMenuExecParam;
+
+void FreeAndNil( void **p )
+{
+ if ( p == NULL )
+ return;
+
+ if ( *p != NULL ) {
+ mir_free( *p );
+ *p = NULL;
+} }
+
+static INT_PTR AddContextFrameMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ TMO_MenuItem tmi;
+ CLISTMENUITEM *mi = (CLISTMENUITEM*)lParam;
+ if ( !pcli->pfnConvertMenu(mi, &tmi))
+ return NULL;
+
+ tmi.root = (mi->flags & CMIF_ROOTHANDLE) ? mi->hParentMenu : NULL;
+
+ lpFrameMenuExecParam fmep = (lpFrameMenuExecParam)mir_alloc(sizeof(FrameMenuExecParam));
+ if (fmep == NULL)
+ return 0;
+
+ memset(fmep, 0, sizeof(FrameMenuExecParam));
+ fmep->szServiceName = mir_strdup(mi->pszService);
+ fmep->Frameid = mi->popupPosition;
+ fmep->param1 = (INT_PTR)mi->pszContactOwner;
+ tmi.ownerdata = fmep;
+
+ return CallService(MO_ADDNEWMENUITEM,(WPARAM)hFrameMenuObject,(LPARAM)&tmi);
+}
+
+static INT_PTR RemoveContextFrameMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ lpFrameMenuExecParam fmep = (lpFrameMenuExecParam)CallService(MO_MENUITEMGETOWNERDATA,wParam,lParam);
+ if (fmep != NULL){
+ if (fmep->szServiceName != NULL)
+ mir_free(fmep->szServiceName);
+ mir_free(fmep);
+ }
+
+ if (lParam != 1)
+ CallService(MO_REMOVEMENUITEM,wParam,0);
+
+ return 0;
+}
+
+//called with:
+//wparam - ownerdata
+//lparam - lparam from winproc
+INT_PTR FrameMenuExecService(WPARAM wParam,LPARAM lParam) {
+ lpFrameMenuExecParam fmep = (lpFrameMenuExecParam)wParam;
+ if (fmep == NULL){return(-1);};
+ CallService(fmep->szServiceName,lParam,fmep->param1);
+
+ return(0);
+};
+
+//true - ok,false ignore
+INT_PTR FrameMenuCheckService(WPARAM wParam,LPARAM lParam) {
+
+ PCheckProcParam pcpp = (PCheckProcParam)wParam;
+ lpFrameMenuExecParam fmep;
+ TMO_MenuItem mi;
+
+ if (pcpp == NULL){return(FALSE);};
+ if (CallService(MO_GETMENUITEM,(WPARAM)pcpp->MenuItemHandle,(LPARAM)&mi) == 0)
+ {
+ fmep = (lpFrameMenuExecParam)mi.ownerdata;
+ if (fmep != NULL)
+ {
+ //pcpp->wParam - frameid
+ if (((WPARAM)fmep->Frameid == pcpp->wParam) || fmep->Frameid == -1) return(TRUE);
+ };
+
+ };
+ return(FALSE);
+};
+
+static INT_PTR ContextFrameMenuNotify(WPARAM wParam,LPARAM lParam)
+{
+ NotifyEventHooks(g_CluiData.hEventPreBuildFrameMenu,wParam,lParam);
+ return(0);
+};
+
+static INT_PTR BuildContextFrameMenu(WPARAM wParam,LPARAM lParam)
+{
+ ListParam param = { 0 };
+ param.MenuObjectHandle = hFrameMenuObject;
+ param.wParam = wParam;
+ param.lParam = lParam;
+
+ HMENU hMenu = CreatePopupMenu();
+ //NotifyEventHooks(hPreBuildFrameMenuEvent,wParam,-1);
+ ContextFrameMenuNotify(wParam,-1);
+ CallService(MO_BUILDMENU,(WPARAM)hMenu,(LPARAM)&param);
+ return (INT_PTR)hMenu;
+}
+
+// == == == == == == == == == == == == == Frames end
+bool InternalGenMenuModule = FALSE;
+
+int MeasureItemProxy(WPARAM wParam,LPARAM lParam) {
+
+ int val;
+ if (InternalGenMenuModule)
+ {
+
+ val = CallService(MS_INT_MENUMEASUREITEM,wParam,lParam);
+ if (val) return(val);
+ };
+ return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam);
+
+
+};
+
+
+int DrawItemProxy(WPARAM wParam,LPARAM lParam) {
+ if (InternalGenMenuModule)
+ {
+ int val;
+ val = CallService(MS_INT_MENUDRAWITEM,wParam,lParam);
+ if (val) return(val);
+ }
+ return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam);
+
+};
+
+
+
+int ProcessCommandProxy(WPARAM wParam,LPARAM lParam) {
+ if (InternalGenMenuModule)
+ {
+ int val;
+ val = CallService(MS_INT_MENUPROCESSCOMMAND,wParam,lParam);
+ if (val) return(val);
+ };
+
+ return CallService(MS_CLIST_MENUPROCESSCOMMAND,wParam,lParam);
+
+};
+
+int ModifyMenuItemProxy(WPARAM wParam,LPARAM lParam) {
+ if (InternalGenMenuModule)
+ {
+ int val;
+ val = CallService(MS_INT_MODIFYMENUITEM,wParam,lParam);
+ if (val) return(val);
+ };
+
+ return CallService(MS_CLIST_MODIFYMENUITEM,wParam,lParam);
+
+};
+
+
+int InitFramesMenus(void)
+{
+ TMenuParam tmp;
+
+ if ( !ServiceExists(MO_REMOVEMENUOBJECT))
+ {
+
+ InitCustomMenus();
+ InternalGenMenuModule = TRUE;
+ };
+
+ if (ServiceExists(MO_REMOVEMENUOBJECT))
+ {
+ CreateServiceFunction("FrameMenuExecService",FrameMenuExecService);
+ CreateServiceFunction("FrameMenuCheckService",FrameMenuCheckService);
+
+ CreateServiceFunction(MS_CLIST_REMOVECONTEXTFRAMEMENUITEM,RemoveContextFrameMenuItem);
+ CreateServiceFunction("CList/AddContextFrameMenuItem",AddContextFrameMenuItem);
+ CreateServiceFunction(MS_CLIST_MENUBUILDFRAMECONTEXT,BuildContextFrameMenu);
+ CreateServiceFunction(MS_CLIST_FRAMEMENUNOTIFY,ContextFrameMenuNotify);
+
+
+ //frame menu object
+ memset(&tmp,0,sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ tmp.CheckService = "FrameMenuCheckService";
+ tmp.ExecService = "FrameMenuExecService";
+ tmp.name = "FrameMenu";
+ hFrameMenuObject = (HANDLE)CallService(MO_CREATENEWMENUOBJECT,0,(LPARAM)&tmp);
+ }
+ return 0;
+}
+int UnitFramesMenu()
+{
+
+ /*
+ if (ServiceExists(MO_REMOVEMENUOBJECT))
+ {
+ CallService(MO_REMOVEMENUOBJECT,hFrameMenuObject,0);
+ if (InternalGenMenuModule){UnitGenMenu();};
+ };
+ */
+ return(0);
+};
diff --git a/plugins/Clist_modern/src/modern_gdiplus.cpp b/plugins/Clist_modern/src/modern_gdiplus.cpp
new file mode 100644
index 0000000000..f07e294dbd
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_gdiplus.cpp
@@ -0,0 +1,308 @@
+/*
+ * test for gdi+
+ */
+
+
+#include "hdr/modern_commonheaders.h"
+
+#undef Translate //otherwise will conflict with gdi plus Translate
+#include <gdiplus.h>
+
+#include "hdr/modern_global_structure.h"
+
+BYTE saved_alpha;
+ULONG_PTR g_gdiplusToken;
+int mir_strlen(const char *a);
+HBITMAP ske_CreateDIB32(int cx, int cy);
+void InitGdiPlus(void)
+{
+ Gdiplus::GdiplusStartupInput gdiplusStartupInput;
+ g_CluiData.fGDIPlusFail = false;
+ __try {
+ if (g_gdiplusToken == 0)
+ Gdiplus::GdiplusStartup(&g_gdiplusToken, &gdiplusStartupInput, NULL);
+ }
+ __except ( EXCEPTION_EXECUTE_HANDLER ) {
+ g_CluiData.fGDIPlusFail = true;
+ }
+}
+
+void ShutdownGdiPlus(void)
+{
+ Gdiplus::GdiplusStartupInput gdiplusStartupInput;
+ __try {
+ if (g_gdiplusToken)
+ Gdiplus::GdiplusShutdown(g_gdiplusToken);
+ }
+ __except ( EXCEPTION_EXECUTE_HANDLER ) {
+ g_CluiData.fGDIPlusFail = true;
+ }
+ g_gdiplusToken = 0;
+}
+
+
+
+
+using namespace Gdiplus;
+
+static ColorMatrix ClrMatrix = {
+ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.5f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
+};
+
+
+
+int g_hottrack;
+
+DWORD argb_from_cola(COLORREF col, BYTE alpha)
+{
+ return((BYTE) (alpha) << 24 | col);
+}
+HBITMAP GDIPlus_LoadGlyphImage(char *szFileName)
+{
+ WCHAR *string;
+ string = (WCHAR*)malloc(sizeof(WCHAR)*(mir_strlen(szFileName)+2));
+ MultiByteToWideChar(CP_ACP, 0, szFileName, -1, string, (mir_strlen(szFileName)+2)*sizeof(WCHAR));
+ // Create a Bitmap object from a JPEG file.
+ Bitmap bitmap(string,0);
+ free(string);
+ // Clone a portion of the bitmap.
+ Bitmap* clone = bitmap.Clone(0, 0, bitmap.GetWidth(), bitmap.GetHeight(), PixelFormat32bppPARGB);
+ HBITMAP hbmp = NULL;
+ if (clone)
+ {
+ clone->GetHBITMAP(Color(0,0,0),&hbmp);
+ delete clone;
+ }
+ return hbmp;
+}
+void TextOutWithGDIp(HDC hDestDC, int x, int y, LPCTSTR lpString, int nCount)
+{
+// Graphics s(hDestDC);
+// HBITMAP hs;
+// hs = (HBITMAP)GetCurrentObject(hDestDC,OBJ_BITMAP);
+// Bitmap sb(hs,NULL);
+// Bitmap *b = (sb.Clone(x,y,150,30,PixelFormat32bppARGB));
+// Graphics g(b);//(100,100,PixelFormat32bppPARGB);
+// //g.DrawImage(sb);
+// // s.SetCompositingMode(CompositingModeSourceCopy);
+// // g.SetCompositingMode(CompositingModeSourceCopy);
+// g.DrawImage(&sb,0,0,x,y,100,30,UnitPixel);
+// //s.SetCompositingMode(CompositingModeSourceCopy);
+// //g.SetCompositingMode(CompositingModeSourceCopy);
+// // Create a string.
+//
+// WCHAR *string;
+// string = (WCHAR*)malloc(sizeof(WCHAR)*(nCount+2));
+// MultiByteToWideChar(CP_ACP, 0, lpString, -1, string, (nCount+2)*sizeof(WCHAR));
+// Font myFont(hDestDC);
+//
+// PointF origin((float)0, (float)0);
+// PointF origin2((float)x, (float)y);
+// g.SetTextRenderingHint(TextRenderingHintSystemDefault);
+// g.SetSmoothingMode(SmoothingModeAntiAlias);
+// COLORREF ref = GetTextColor(hDestDC);
+// SolidBrush blackBrush(Color(255, GetRValue(ref),GetGValue(ref),GetBValue(ref)));
+// g.SetInterpolationMode(InterpolationModeHighQualityBicubic);
+// g.DrawString(string,nCount,&myFont,origin, &blackBrush);
+// //g.SetCompositingMode(CompositingModeSourceCopy);
+// //s.SetCompositingMode(CompositingModeSourceCopy);
+// free(string);
+// //HDC temp = g.GetHDC();
+// //BitBlt(hDestDC,x,y,100,100,temp,0,0,SRCCOPY);
+// //g.ReleaseHDC(temp);
+// s.DrawImage(b,origin2);
+//
+}
+
+void DrawAvatarImageWithGDIp(HDC hDestDC,int x, int y, DWORD width, DWORD height, HBITMAP hbmp, int x1, int y1, DWORD width1, DWORD height1,DWORD flag,BYTE alpha)
+{
+ BITMAP bmp;
+ Bitmap *bm;
+ BYTE * bmbits = NULL;
+ GetObject(hbmp,sizeof(BITMAP),&bmp);
+ Graphics g(hDestDC);
+ if (bmp.bmBitsPixel == 32 && (flag&AVS_PREMULTIPLIED))
+ {
+ bmbits = (BYTE*)bmp.bmBits;
+ if ( !bmbits)
+ {
+ bmbits = (BYTE*)malloc(bmp.bmHeight*bmp.bmWidthBytes);
+ GetBitmapBits(hbmp,bmp.bmHeight*bmp.bmWidthBytes,bmbits);
+ }
+ bm = new Bitmap(bmp.bmWidth,bmp.bmHeight,bmp.bmWidthBytes,PixelFormat32bppPARGB,bmbits);
+ bm->RotateFlip(RotateNoneFlipY);
+ if ( !bmp.bmBits)
+ {
+ bm->RotateFlip(RotateNoneFlipY);
+ free(bmbits);
+ }
+ }
+ else
+ bm = new Bitmap(hbmp,NULL);
+
+ ImageAttributes attr;
+ ColorMatrix ClrMatrix =
+ {
+ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, ((float)alpha)/255, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ attr.SetColorMatrix(&ClrMatrix, ColorMatrixFlagsDefault,ColorAdjustTypeBitmap);
+ g.SetInterpolationMode(InterpolationModeHighQualityBicubic);
+ RectF rect((float)x,(float)y,(float)width,(float)height);
+ g.DrawImage(bm, rect, (float)x1, (float)y1, (float)width1, (float)height1 , UnitPixel, &attr, NULL, NULL);
+ delete bm;
+}
+BOOL GDIPlus_AlphaBlend(HDC hdcDest,int nXOriginDest,int nYOriginDest,int nWidthDest,int nHeightDest,HDC hdcSrc,int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc, BLENDFUNCTION * bf)
+{
+ Graphics g(hdcDest);
+ BITMAP bmp;
+ HBITMAP hbmp = (HBITMAP)GetCurrentObject(hdcSrc,OBJ_BITMAP);
+ GetObject(hbmp,sizeof(BITMAP),&bmp);
+ Bitmap *bm = new Bitmap(hbmp,NULL);
+ if (bmp.bmBitsPixel == 32 && bf->AlphaFormat)
+ {
+ bm = new Bitmap(bmp.bmWidth,bmp.bmHeight,bmp.bmWidthBytes,PixelFormat32bppPARGB,(BYTE*)bmp.bmBits);
+ bm->RotateFlip(RotateNoneFlipY);
+ }
+ else
+ bm = new Bitmap(hbmp,NULL);
+ ImageAttributes attr;
+ ColorMatrix ClrMatrix =
+ {
+ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, ((float)bf->SourceConstantAlpha)/255, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ attr.SetColorMatrix(&ClrMatrix, ColorMatrixFlagsDefault,ColorAdjustTypeBitmap);
+
+ if (bf->BlendFlags&128 && nWidthDest < nWidthSrc && nHeightDest < nHeightSrc)
+ {
+ g.SetInterpolationMode(InterpolationModeHighQualityBicubic);
+ g.SetPixelOffsetMode(PixelOffsetModeHalf);
+ attr.SetGamma((REAL)0.8,ColorAdjustTypeBitmap);
+ }
+ else
+ {
+ g.SetInterpolationMode(InterpolationModeLowQuality);
+ //g.SetPixelOffsetMode(PixelOffsetModeHalf);
+ }
+
+ RectF rect((float)nXOriginDest,(float)nYOriginDest,(float)nWidthDest,(float)nHeightDest);
+ g.DrawImage(bm, rect, (float)nXOriginSrc, (float)nYOriginSrc, (float)nWidthSrc, (float)nHeightSrc , UnitPixel, &attr, NULL, NULL);
+ delete bm;
+ return TRUE;
+}
+COLORREF __inline _revcolref(COLORREF colref)
+{
+ return RGB(GetBValue(colref), GetGValue(colref), GetRValue(colref));
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+// GDIPlus_IsAnimatedGIF and GDIPlus_ExtractAnimatedGIF
+// based on routine from http://www.codeproject.com/vcpp/gdiplus/imageexgdi.asp
+//
+
+BOOL GDIPlus_IsAnimatedGif (TCHAR * szName)
+{
+ int nFrameCount = 0;
+ Image image(szName);
+ UINT count = 0;
+
+ count = image.GetFrameDimensionsCount();
+ GUID* pDimensionIDs = new GUID[count];
+
+ // Get the list of frame dimensions from the Image object.
+ image.GetFrameDimensionsList(pDimensionIDs, count);
+
+ // Get the number of frames in the first dimension.
+ nFrameCount = image.GetFrameCount(&pDimensionIDs[0]);
+
+ delete[] pDimensionIDs;
+
+ return (BOOL) (nFrameCount > 1);
+}
+
+void GDIPlus_ExtractAnimatedGIF (TCHAR * szName, int width, int height, HBITMAP * pBitmap, int ** pframesDelay, int * pframesCount, SIZE * pSizeAvatar)
+{
+ int nFrameCount = 0;
+ Bitmap image(szName);
+ PropertyItem * pPropertyItem;
+
+ UINT count = 0;
+
+ count = image.GetFrameDimensionsCount();
+ GUID* pDimensionIDs = new GUID[count];
+
+ // Get the list of frame dimensions from the Image object.
+ image.GetFrameDimensionsList(pDimensionIDs, count);
+
+ // Get the number of frames in the first dimension.
+ nFrameCount = image.GetFrameCount(&pDimensionIDs[0]);
+
+ // Assume that the image has a property item of type PropertyItemEquipMake.
+ // Get the size of that property item.
+ int nSize = image.GetPropertyItemSize(PropertyTagFrameDelay);
+
+ // Allocate a buffer to receive the property item.
+ pPropertyItem = (PropertyItem*) malloc(nSize);
+
+ image.GetPropertyItem(PropertyTagFrameDelay, nSize, pPropertyItem);
+
+ int clipWidth;
+ int clipHeight;
+ int imWidth = image.GetWidth();
+ int imHeight = image.GetHeight();
+ float xscale = (float)width/imWidth;
+ float yscale = (float)height/imHeight;
+ xscale = min(xscale,yscale);
+ clipWidth = (int)(xscale*imWidth+.5);
+ clipHeight = (int)(xscale*imHeight+.5);
+
+ HBITMAP hBitmap = ske_CreateDIB32(clipWidth*nFrameCount, height);
+ HDC hdc = CreateCompatibleDC(NULL);
+ HBITMAP oldBmp = (HBITMAP)SelectObject(hdc,hBitmap);
+ Graphics graphics(hdc);
+ ImageAttributes attr;
+
+ graphics.SetInterpolationMode( InterpolationModeHighQualityBicubic );
+ graphics.SetPixelOffsetMode( PixelOffsetModeHalf );
+ int * delays = (int*)malloc(nFrameCount*sizeof(int));
+ memset(delays,0,nFrameCount*sizeof(int));
+
+ GUID pageGuid = FrameDimensionTime;
+ /*
+ The GDIPlus strange behavior: without next 2 lines it will draw first frame anti aliased, but next - not
+ */
+ if ( nFrameCount > 1 )
+ image.SelectActiveFrame(&pageGuid, 1 );
+
+ for (int i=0; i < nFrameCount; i++)
+ {
+ image.SelectActiveFrame( &pageGuid, i );
+ graphics.DrawImage( &image, Rect(i*clipWidth, 0,clipWidth,clipHeight ), 0, 0, imWidth, imHeight , UnitPixel, &attr);
+ long lPause = ((long*) pPropertyItem->value)[i] * 10;
+ delays[i] = (int)lPause;
+ }
+ SelectObject(hdc,oldBmp);
+ DeleteDC(hdc);
+ free(pPropertyItem);
+ delete[] pDimensionIDs;
+ if (pBitmap && pframesDelay && pframesCount && pSizeAvatar)
+ {
+ *pBitmap = hBitmap;
+ *pframesDelay = delays;
+ *pframesCount = nFrameCount;
+ pSizeAvatar->cx = clipWidth;
+ pSizeAvatar->cy = clipHeight;
+ }
+ GdiFlush();
+} \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_gettextasync.cpp b/plugins/Clist_modern/src/modern_gettextasync.cpp
new file mode 100644
index 0000000000..0e01838ae4
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_gettextasync.cpp
@@ -0,0 +1,205 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+
+*/
+
+/*
+* Author Artem Shpynov aka FYR
+* Copyright 2000-2008 Artem Shpynov
+*/
+
+//////////////////////////////////////////////////////////////////////////
+// Module to async parsing of texts
+
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_gettextasync.h"
+#include "newpluginapi.h"
+#include "hdr/modern_sync.h"
+
+int CLUI_SyncSetPDNCE(WPARAM wParam, LPARAM lParam);
+int CLUI_SyncGetShortData(WPARAM wParam, LPARAM lParam);
+
+#define gtalock EnterCriticalSection(&gtaCS)
+#define gtaunlock LeaveCriticalSection( &gtaCS )
+
+typedef struct _GetTextAsyncItem {
+ HANDLE hContact;
+ struct ClcData *dat;
+ struct _GetTextAsyncItem *Next;
+} GTACHAINITEM;
+
+static GTACHAINITEM * gtaFirstItem = NULL;
+static GTACHAINITEM * gtaLastItem = NULL;
+static CRITICAL_SECTION gtaCS;
+static HANDLE hgtaWakeupEvent = NULL;
+
+
+static BOOL gtaGetItem(GTACHAINITEM * mpChain)
+{
+ gtalock;
+ if ( !gtaFirstItem)
+ {
+ gtaunlock;
+ return FALSE;
+ }
+ else if (mpChain)
+ {
+ GTACHAINITEM * ch;
+ ch = gtaFirstItem;
+ *mpChain = *ch;
+ gtaFirstItem = (GTACHAINITEM *)ch->Next;
+ if ( !gtaFirstItem) gtaLastItem = NULL;
+ free(ch);
+ gtaunlock;
+ return TRUE;
+ }
+ gtaunlock;
+ return FALSE;
+}
+
+static int gtaThreadProc(void * lpParam)
+{
+ BOOL exit = FALSE;
+ HWND hwnd = pcli->hwndContactList;
+ struct SHORTDATA data = {0};
+ struct SHORTDATA * dat;
+
+ while (!MirandaExiting())
+ {
+ Sync(CLUI_SyncGetShortData,(WPARAM)pcli->hwndContactTree,(LPARAM)&data);
+ do
+ {
+ if ( !MirandaExiting())
+ SleepEx(0,TRUE); //1000 contacts per second
+ if (MirandaExiting())
+ {
+ g_dwGetTextAsyncThreadID = 0;
+ return 0;
+ }
+ else
+ {
+ GTACHAINITEM mpChain = {0};
+ struct SHORTDATA dat2 = {0};
+ if ( !gtaGetItem(&mpChain)) break;
+ if (mpChain.dat == NULL || (!IsBadReadPtr(mpChain.dat,sizeof(mpChain.dat)) && mpChain.dat->hWnd == data.hWnd)) dat = &data;
+ else
+ {
+ Sync(CLUI_SyncGetShortData,(WPARAM)mpChain.dat->hWnd,(LPARAM)&dat2);
+ dat = &dat2;
+ }
+ if ( !MirandaExiting())
+ {
+ displayNameCacheEntry cacheEntry;
+ memset( &cacheEntry, 0, sizeof(cacheEntry));
+ cacheEntry.hContact = mpChain.hContact;
+ if ( !Sync(CLUI_SyncGetPDNCE, (WPARAM) 0,(LPARAM)&cacheEntry))
+ {
+ if ( !MirandaExiting())
+ Cache_GetSecondLineText(dat, &cacheEntry);
+ if ( !MirandaExiting())
+ Cache_GetThirdLineText(dat, &cacheEntry);
+ if ( !MirandaExiting())
+ Sync(CLUI_SyncSetPDNCE, (WPARAM) CCI_LINES,(LPARAM)&cacheEntry);
+ CListSettings_FreeCacheItemData(&cacheEntry);
+ }
+ }
+ else
+ {
+ g_dwGetTextAsyncThreadID = 0;
+ return 0;
+ }
+ KillTimer(dat->hWnd,TIMERID_INVALIDATE_FULL);
+ CLUI_SafeSetTimer(dat->hWnd,TIMERID_INVALIDATE_FULL,500,NULL);
+ }
+ }
+ while (!exit);
+
+ WaitForSingleObjectEx(hgtaWakeupEvent, INFINITE, FALSE );
+ ResetEvent(hgtaWakeupEvent);
+ }
+ g_dwGetTextAsyncThreadID = 0;
+ return 1;
+}
+
+BOOL gtaWakeThread()
+{
+ if (hgtaWakeupEvent && g_dwGetTextAsyncThreadID)
+ {
+ SetEvent(hgtaWakeupEvent);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int gtaAddRequest(struct ClcData *dat,struct ClcContact *contact,HANDLE hContact)
+{
+ if (MirandaExiting()) return 0;
+ gtalock;
+ {
+ GTACHAINITEM * mpChain = (GTACHAINITEM *)malloc(sizeof(GTACHAINITEM));
+ mpChain->hContact = hContact;
+ mpChain->dat = dat;
+ mpChain->Next = NULL;
+ if (gtaLastItem)
+ {
+ gtaLastItem->Next = (GTACHAINITEM *)mpChain;
+ gtaLastItem = mpChain;
+ }
+ else
+ {
+ gtaFirstItem = mpChain;
+ gtaLastItem = mpChain;
+ SetEvent(hgtaWakeupEvent);
+ }
+ }
+ gtaunlock;
+ return FALSE;
+}
+void gtaRenewText(HANDLE hContact)
+{
+ gtaAddRequest(NULL,NULL, hContact);
+}
+int gtaOnModulesUnload(WPARAM wParam,LPARAM lParam)
+{
+ SetEvent(hgtaWakeupEvent);
+ return 0;
+}
+void InitCacheAsync()
+{
+ InitializeCriticalSection(&gtaCS);
+ hgtaWakeupEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
+ g_dwGetTextAsyncThreadID = (DWORD)mir_forkthread((pThreadFunc)gtaThreadProc,0);
+ HookEvent(ME_SYSTEM_PRESHUTDOWN, gtaOnModulesUnload);
+}
+
+void UninitCacheAsync()
+{
+ GTACHAINITEM mpChain;
+ SetEvent(hgtaWakeupEvent);
+ CloseHandle(hgtaWakeupEvent);
+ gtalock;
+ while(gtaGetItem(&mpChain));
+ gtaunlock;
+ DeleteCriticalSection(&gtaCS);
+}
diff --git a/plugins/Clist_modern/src/modern_global.cpp b/plugins/Clist_modern/src/modern_global.cpp
new file mode 100644
index 0000000000..269abb136e
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_global.cpp
@@ -0,0 +1,35 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+
+//////////////////////////////////////////////////////////////////////////
+// Global variables
+
+//int hClcProtoCount = 0;
+//ClcProtoStatus *clcProto = NULL;
+HIMAGELIST g_himlCListClc = NULL;
+HICON g_hListeningToIcon = NULL;
+char* g_szMetaModuleName = 0;
diff --git a/plugins/Clist_modern/src/modern_groupmenu.cpp b/plugins/Clist_modern/src/modern_groupmenu.cpp
new file mode 100644
index 0000000000..33c93a10a6
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_groupmenu.cpp
@@ -0,0 +1,754 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "hdr/modern_clc.h"
+
+//////////////////////////////Group MENU/////////////////////////
+HANDLE hGroupMenuObject;
+
+HANDLE hGroupMainMenuItemProxy;
+HANDLE hHideShowMainMenuItem;
+HANDLE hGroupStatusMenuItemProxy;
+
+HANDLE hHideOfflineUsersMenuItem;
+HANDLE hHideOfflineUsersOutHereMenuItem;
+HANDLE hHideEmptyGroupsMenuItem;
+HANDLE hDisableGroupsMenuItem;
+HANDLE hNewGroupMenuItem;
+HANDLE hNewSubGroupMenuItem;
+
+int NewGroupIconidx;
+
+void InitSubGroupMenus(void);
+
+//Groupmenu exec param(ownerdata)
+typedef struct{
+char *szServiceName;
+int Param1,Param2;
+}GroupMenuExecParam,*lpGroupMenuExecParam;
+
+/*
+wparam = handle to the menu item returned by MS_CLIST_ADDCONTACTMENUITEM
+return 0 on success.
+*/
+static INT_PTR RemoveGroupMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ CallService(MO_REMOVEMENUITEM,wParam,0);
+ return 0;
+}
+
+
+INT_PTR BuildGroupMenu(WPARAM wParam,LPARAM lParam)
+{
+ ListParam param = { 0 };
+ param.MenuObjectHandle = hGroupMenuObject;
+
+ //hMenu = hMainMenu;
+ HMENU hMenu = CreatePopupMenu();
+ //hMenu = wParam;
+ int tick = GetTickCount();
+
+ NotifyEventHooks(g_CluiData.hEventPreBuildGroupMenu,0,0);
+
+ CallService(MO_BUILDMENU,(WPARAM)hMenu,(LPARAM)&param);
+ //DrawMenuBar((HWND)CallService("CLUI/GetHwnd",0,0));
+ tick = GetTickCount()-tick;
+ return (INT_PTR)hMenu;
+}
+
+static INT_PTR AddGroupMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ TMO_MenuItem tmi;
+ CLISTMENUITEM *mi = (CLISTMENUITEM*)lParam;
+ if ( !pcli->pfnConvertMenu(mi, &tmi))
+ return NULL;
+
+ lpGroupMenuExecParam mmep = (lpGroupMenuExecParam)mir_calloc(sizeof(GroupMenuExecParam));
+ if (mmep == NULL)
+ return 0;
+
+ //we need just one parametr.
+ mmep->szServiceName = mir_strdup(mi->pszService);
+ mmep->Param1 = mi->popupPosition;
+ lpGroupMenuParam gmp = (lpGroupMenuParam)wParam;
+ if (gmp != NULL) {
+ mmep->Param1 = gmp->wParam;
+ mmep->Param2 = gmp->lParam;
+ }
+ tmi.ownerdata = mmep;
+
+ char buf[1024];
+ sprintf(buf,"%s/%s",mi->pszService,mi->pszName);
+
+ OptParam op;
+ op.Handle = (HANDLE)CallService(MO_ADDNEWMENUITEM,(WPARAM)hGroupMenuObject,(LPARAM)&tmi);
+ op.Setting = OPT_MENUITEMSETUNIQNAME;
+ op.Value = (INT_PTR)buf;
+ CallService(MO_SETOPTIONSMENUITEM,(WPARAM)0,(LPARAM)&op);
+ return (INT_PTR)op.Handle;
+}
+
+int GroupMenuCheckService(WPARAM wParam,LPARAM lParam) {
+//not used
+ return(0);
+};
+
+INT_PTR GroupMenuonAddService(WPARAM wParam,LPARAM lParam) {
+
+ MENUITEMINFO *mii = (MENUITEMINFO* )wParam;
+ if (mii == NULL) return 0;
+
+ if (hHideShowMainMenuItem == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_STATE;
+ mii->fState |= MFS_DEFAULT;
+
+ }
+ if (hGroupMainMenuItemProxy == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0);
+ }
+
+ if (hGroupStatusMenuItemProxy == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ }
+
+ return(TRUE);
+};
+
+
+//called with:
+//wparam - ownerdata
+//lparam - lparam from winproc
+INT_PTR GroupMenuExecService(WPARAM wParam,LPARAM lParam) {
+ if (wParam != 0)
+ {
+ lpGroupMenuExecParam mmep = (lpGroupMenuExecParam)wParam;
+ if ( !mir_strcmp(mmep->szServiceName,"Help/AboutCommand"))
+ {
+ //bug in help.c,it used wparam as parent window handle without reason.
+ mmep->Param1 = 0;
+ CallService(mmep->szServiceName,mmep->Param1,lParam);
+ }else
+ {
+ CallService(mmep->szServiceName,mmep->Param1,mmep->Param2);
+ }
+
+ };
+ return(1);
+};
+INT_PTR FreeOwnerDataGroupMenu (WPARAM wParam,LPARAM lParam)
+{
+
+ lpGroupMenuExecParam mmep;
+ mmep = (lpGroupMenuExecParam)lParam;
+ if (mmep != NULL){
+ FreeAndNil((void **)&mmep->szServiceName);
+ FreeAndNil((void **)&mmep);
+ }
+
+return(0);
+};
+
+INT_PTR HideGroupsHelper(WPARAM wParam,LPARAM lParam)
+{
+ int newVal = !(GetWindowLongPtr(pcli->hwndContactTree,GWL_STYLE)&CLS_HIDEEMPTYGROUPS);
+ db_set_b(NULL,"CList","HideEmptyGroups",(BYTE)newVal);
+ SendMessage(pcli->hwndContactTree,CLM_SETHIDEEMPTYGROUPS,newVal,0);
+ return 0;
+}
+
+INT_PTR UseGroupsHelper(WPARAM wParam,LPARAM lParam)
+{
+ int newVal = !(GetWindowLongPtr(pcli->hwndContactTree,GWL_STYLE)&CLS_USEGROUPS);
+ db_set_b(NULL,"CList","UseGroups",(BYTE)newVal);
+ SendMessage(pcli->hwndContactTree,CLM_SETUSEGROUPS,newVal,0);
+ return 0;
+}
+
+INT_PTR HideOfflineRootHelper(WPARAM wParam,LPARAM lParam)
+{
+SendMessage(
+ (HWND)CallService(MS_CLUI_GETHWNDTREE,0,0),
+ CLM_SETHIDEOFFLINEROOT,
+ !SendMessage((HWND)CallService(MS_CLUI_GETHWNDTREE,0,0),CLM_GETHIDEOFFLINEROOT,0,0),
+ 0);
+ return 0;
+};
+
+INT_PTR CreateGroupHelper(WPARAM wParam,LPARAM lParam)
+{
+ SendMessage((HWND)CallService(MS_CLUI_GETHWNDTREE,0,0), CLM_SETHIDEEMPTYGROUPS, 0, 0);
+ SendMessage((HWND)CallService(MS_CLUI_GETHWNDTREE,0,0), CLM_SETUSEGROUPS, 1, 0);
+ CallService(MS_CLIST_GROUPCREATE, 0, 0);
+
+ return 0;
+};
+
+static int OnBuildGroupMenu(WPARAM wParam,LPARAM lParam)
+{
+ CLISTMENUITEM mi;
+ if (MirandaExiting()) return 0;
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | (db_get_b(NULL,"CList","HideOffline",SETTING_HIDEOFFLINE_DEFAULT)?CMIF_CHECKED:0);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideOfflineUsersMenuItem, (LPARAM)&mi);
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | (SendMessage(pcli->hwndContactTree,CLM_GETHIDEOFFLINEROOT,0,0)?CMIF_CHECKED:0);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideOfflineUsersOutHereMenuItem, (LPARAM)&mi);
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | (GetWindowLongPtr(pcli->hwndContactTree,GWL_STYLE)&CLS_HIDEEMPTYGROUPS?CMIF_CHECKED:0);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideEmptyGroupsMenuItem, (LPARAM)&mi);
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | (GetWindowLongPtr(pcli->hwndContactTree,GWL_STYLE)&CLS_USEGROUPS?0:CMIF_CHECKED);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hDisableGroupsMenuItem, (LPARAM)&mi);
+
+ return 0;
+};
+
+int static OnIconLibIconChanged(WPARAM wParam,LPARAM lParam)
+{
+ HICON hicon;
+ CLISTMENUITEM clmi = {0};
+ BOOL needFree;
+ if (MirandaExiting()) return 0;
+ hicon = CLUI_LoadIconFromExternalFile("clisticons.dll",2,TRUE,FALSE,"NewGroup","Contact List","New Group",-IDI_NEWGROUP2,&needFree);
+ NewGroupIconidx = ImageList_ReplaceIcon(hCListImages,NewGroupIconidx,hicon);
+ if (needFree) DestroyIcon_protect(hicon);
+ clmi.cbSize = sizeof(clmi);
+ clmi.flags = CMIM_ICON;
+ clmi.hIcon = ske_ImageList_GetIcon(hCListImages,NewGroupIconidx,0);
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hNewSubGroupMenuItem,(LPARAM)&clmi);
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hNewGroupMenuItem,(LPARAM)&clmi);
+ //
+
+
+ return 0;
+};
+
+void GroupMenus_Init(void)
+{
+ TMenuParam tmp;
+ OptParam op;
+ HICON hicon;
+ BOOL needFree;
+ hicon = CLUI_LoadIconFromExternalFile("clisticons.dll",2,TRUE,TRUE,"NewGroup","Contact List","New Group",-IDI_NEWGROUP2,&needFree);
+ NewGroupIconidx = hicon?ImageList_AddIcon(hCListImages,hicon ):-1;
+ if (needFree) DestroyIcon_protect(hicon);
+ CreateServiceFunction("CLISTMENUSGroup/ExecService",GroupMenuExecService);
+ CreateServiceFunction("CLISTMENUSGroup/FreeOwnerDataGroupMenu",FreeOwnerDataGroupMenu);
+ CreateServiceFunction("CLISTMENUSGroup/GroupMenuonAddService",GroupMenuonAddService);
+ CreateServiceFunction("CLISTMENUSGroup/HideGroupsHelper",HideGroupsHelper);
+ CreateServiceFunction("CLISTMENUSGroup/UseGroupsHelper",UseGroupsHelper);
+ CreateServiceFunction("CLISTMENUSGroup/HideOfflineRootHelper",HideOfflineRootHelper);
+ CreateServiceFunction("CLISTMENUSGroup/CreateGroupHelper",CreateGroupHelper);
+
+ CreateServiceFunction("CList/AddGroupMenuItem",AddGroupMenuItem);
+ CreateServiceFunction(MS_CLIST_REMOVEGROUPMENUITEM,RemoveGroupMenuItem);
+ CreateServiceFunction(MS_CLIST_MENUBUILDGROUP,BuildGroupMenu);
+
+ HookEvent(ME_CLIST_PREBUILDGROUPMENU,OnBuildGroupMenu);
+
+ InitSubGroupMenus();
+
+ //Group menu
+ memset(&tmp,0,sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ tmp.CheckService = NULL;
+ tmp.ExecService = "CLISTMENUSGroup/ExecService";
+ tmp.name = LPGEN("GroupMenu");
+ hGroupMenuObject = (HANDLE)CallService(MO_CREATENEWMENUOBJECT,(WPARAM)0,(LPARAM)&tmp);
+
+
+ op.Handle = hGroupMenuObject;
+ op.Setting = OPT_USERDEFINEDITEMS;
+ op.Value = TRUE;
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ op.Handle = hGroupMenuObject;
+ op.Setting = OPT_MENUOBJECT_SET_FREE_SERVICE;
+ op.Value = (INT_PTR)"CLISTMENUSGroup/FreeOwnerDataGroupMenu";
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ op.Handle = hGroupMenuObject;
+ op.Setting = OPT_MENUOBJECT_SET_ONADD_SERVICE;
+ op.Value = (INT_PTR)"CLISTMENUSGroup/GroupMenuonAddService";
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ {
+ //add exit command to menu
+ CLISTMENUITEM mi;
+ GroupMenuParam gmp;
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 1900000;
+ mi.pszService = "CloseAction";
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_EXIT);
+ mi.pszName = LPGEN("E&xit");
+ mi.flags = CMIF_ICONFROMICOLIB;
+ AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 500;
+ mi.pszService = MS_CLIST_SHOWHIDE;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_SHOWHIDE);
+ mi.pszName = LPGEN("&Hide/Show");
+ mi.flags = CMIF_ICONFROMICOLIB;
+ hHideShowMainMenuItem = (HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 200000;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_FINDUSER);
+ mi.pszService = "FindAdd/FindAddCommand";
+ mi.pszName = LPGEN("&Find/Add Contacts...");
+ AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 300000;
+ mi.pszService = "";
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_MAINMENU); // eternity #004
+ mi.pszName = LPGEN("&Main Menu");
+ mi.flags = CMIF_ICONFROMICOLIB; // eternity #004
+ hGroupMainMenuItemProxy = (HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon); // eternity #004
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 300100;
+ mi.pszService = "";
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_STATUS); // eternity #004
+ mi.pszName = LPGEN("&Status");
+ mi.flags = CMIF_ICONFROMICOLIB; // eternity #004
+ hGroupStatusMenuItemProxy = (HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon); // eternity #004
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 400000;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_OPTIONS);
+ mi.pszService = "Options/OptionsCommand";
+ mi.pszName = LPGEN("&Options...");
+ AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 500000;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_MIRANDA);
+ mi.pszService = "Help/AboutCommand";
+ mi.pszName = LPGEN("&About");
+ AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100000;
+ mi.hIcon = ske_ImageList_GetIcon(hCListImages,NewGroupIconidx,0);
+ mi.pszService = "CLISTMENUSGroup/CreateGroupHelper";
+ mi.pszName = LPGEN("&New Group");
+ hNewGroupMenuItem = (HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100001;
+ mi.hIcon = NULL;
+ mi.pszService = MS_CLIST_SETHIDEOFFLINE;
+ mi.pszName = LPGEN("&Hide Offline Users");
+ gmp.lParam = 0;gmp.wParam = -1;
+ hHideOfflineUsersMenuItem = (HANDLE)AddGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100002;
+ mi.hIcon = NULL;
+ mi.pszService = "CLISTMENUSGroup/HideOfflineRootHelper";
+ mi.pszName = LPGEN("Hide &Offline Users out here");
+ hHideOfflineUsersOutHereMenuItem = (HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100003;
+ mi.hIcon = NULL;
+ mi.pszService = "CLISTMENUSGroup/HideGroupsHelper";
+ mi.pszName = LPGEN("Hide &Empty Groups");
+ hHideEmptyGroupsMenuItem = (HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+
+
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100004;
+ mi.hIcon = NULL;
+ mi.pszService = "CLISTMENUSGroup/UseGroupsHelper";
+ mi.pszName = LPGEN("Disable &Groups");
+ hDisableGroupsMenuItem = (HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+
+
+ HookEvent(ME_SKIN2_ICONSCHANGED,OnIconLibIconChanged);
+
+ //MS_CLIST_GROUPCREATE
+
+ };
+}
+
+//////////////////////////////END Group MENU/////////////////////////
+
+
+
+
+//////////////////////////////SubGroup MENU/////////////////////////
+HANDLE hSubGroupMenuObject;
+
+HANDLE hSubGroupMainMenuItemProxy;
+HANDLE hSubGroupStatusMenuItemProxy;
+HANDLE hHideOfflineUsersHereMenuItem;
+HANDLE hShowOfflineUsersHereMenuItem;
+
+//SubGroupmenu exec param(ownerdata)
+typedef struct{
+char *szServiceName;
+int Param1,Param2;
+}SubGroupMenuExecParam,*lpSubGroupMenuExecParam;
+
+/*
+wparam = handle to the menu item returned by MS_CLIST_ADDCONTACTMENUITEM
+return 0 on success.
+*/
+static INT_PTR RemoveSubGroupMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ CallService(MO_REMOVEMENUITEM,wParam,0);
+ return 0;
+}
+
+
+static int OnBuildSubGroupMenu(WPARAM wParam,LPARAM lParam)
+{
+ CLISTMENUITEM mi;
+ BOOL gray1 = FALSE;
+ BOOL gray2 = FALSE;
+ BOOL showOfflineinGroup = FALSE;
+
+
+ struct ClcGroup *group = (struct ClcGroup *)wParam;
+ if (wParam == 0) return 0;
+
+ if (MirandaExiting()) return 0;
+ //contact->group
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+
+ showOfflineinGroup = CLCItems_IsShowOfflineGroup(group);
+ gray1 = (showOfflineinGroup != FALSE);
+ gray2 = (group->hideOffline != FALSE);
+
+ if (gray1 && gray2) gray1 = FALSE; //should not be cause CLCItems_IsShowOfflineGroup return false if group->hideOffline
+
+ mi.flags = CMIM_FLAGS | ((group->hideOffline && !gray1)?CMIF_CHECKED:0)| (gray1?CMIF_GRAYED:0);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideOfflineUsersHereMenuItem, (LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS | ((showOfflineinGroup && !gray2) ? CMIF_CHECKED:0)| (gray2?CMIF_GRAYED:0);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hShowOfflineUsersHereMenuItem, (LPARAM)&mi);
+
+ return 0;
+};
+INT_PTR BuildSubGroupMenu(WPARAM wParam,LPARAM lParam)
+{
+ ListParam param = { 0 };
+ param.MenuObjectHandle = hSubGroupMenuObject;
+ param.wParam = wParam;
+ param.lParam = lParam;
+
+ //hMenu = hMainMenu;
+ HMENU hMenu = CreatePopupMenu();
+ //hMenu = wParam;
+ int tick = GetTickCount();
+
+ NotifyEventHooks(g_CluiData.hEventPreBuildSubGroupMenu,wParam,0);
+
+ CallService(MO_BUILDMENU,(WPARAM)hMenu,(LPARAM)&param);
+ //DrawMenuBar((HWND)CallService("CLUI/GetHwnd",0,0));
+ tick = GetTickCount()-tick;
+ return (INT_PTR)hMenu;
+}
+
+HMENU cliBuildGroupPopupMenu(struct ClcGroup *group)
+{
+ //HWND wnd = GetForegroundWindow();
+ return (HMENU)CallService(MS_CLIST_MENUBUILDSUBGROUP,(WPARAM)group,0);
+}
+static INT_PTR AddSubGroupMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ TMO_MenuItem tmi;
+ CLISTMENUITEM *mi = (CLISTMENUITEM*)lParam;
+ if ( !pcli->pfnConvertMenu(mi, &tmi))
+ return NULL;
+
+ lpSubGroupMenuExecParam mmep = (lpSubGroupMenuExecParam)mir_calloc(sizeof(SubGroupMenuExecParam));
+ if ( mmep == NULL)
+ return 0;
+
+ //we need just one parametr.
+ mmep->szServiceName = mir_strdup(mi->pszService);
+ mmep->Param1 = mi->popupPosition;
+ lpGroupMenuParam gmp = (lpGroupMenuParam)wParam;
+ if (gmp != NULL) {
+ mmep->Param1 = gmp->wParam;
+ mmep->Param2 = gmp->lParam;
+ }
+ tmi.ownerdata = mmep;
+
+ char buf[1024];
+ sprintf(buf,"%s/%s",mi->pszService,mi->pszName);
+
+ OptParam op;
+ op.Handle = (HANDLE)CallService(MO_ADDNEWMENUITEM,(WPARAM)hSubGroupMenuObject,(LPARAM)&tmi);
+ op.Setting = OPT_MENUITEMSETUNIQNAME;
+ op.Value = (INT_PTR)buf;
+ CallService(MO_SETOPTIONSMENUITEM,(WPARAM)0,(LPARAM)&op);
+ return (INT_PTR)op.Handle;
+}
+
+INT_PTR SubGroupMenuCheckService(WPARAM wParam,LPARAM lParam) {
+//not used
+ //TODO ADD
+ lpSubGroupMenuExecParam mmep;
+ TCheckProcParam * CParam = (TCheckProcParam*)wParam;
+ if (CParam)
+ {
+
+ mmep = (lpSubGroupMenuExecParam)(CParam->MenuItemOwnerData);
+ if (mmep)
+ {
+ mmep->Param2 = CParam->lParam;
+ }
+
+ }
+ return(1);
+};
+
+INT_PTR SubGroupMenuonAddService(WPARAM wParam,LPARAM lParam) {
+
+ MENUITEMINFO *mii = (MENUITEMINFO* )wParam;
+
+ if (mii == NULL) return 0;
+
+/*
+ if (hHideShowMainMenuItem == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_STATE;
+ mii->fState |= MFS_DEFAULT;
+
+ }
+ if (hSubGroupMainMenuItemProxy == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0);
+ }
+
+ if (hSubGroupStatusMenuItemProxy == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ }
+*/
+ return(TRUE);
+};
+
+
+//called with:
+//wparam - ownerdata
+//lparam - lparam from winproc
+INT_PTR SubGroupMenuExecService(WPARAM wParam,LPARAM lParam) {
+ if (wParam != 0)
+ {
+ lpSubGroupMenuExecParam mmep = (lpSubGroupMenuExecParam)wParam;
+ if ( !mir_strcmp(mmep->szServiceName,"Help/AboutCommand"))
+ {
+ //bug in help.c,it used wparam as parent window handle without reason.
+ mmep->Param1 = 0;
+ CallService(mmep->szServiceName,mmep->Param1,lParam);
+ }else
+ {
+ CallService(mmep->szServiceName,mmep->Param1,lParam);
+ }
+
+ };
+ return(1);
+};
+INT_PTR FreeOwnerDataSubGroupMenu (WPARAM wParam,LPARAM lParam)
+{
+
+ lpSubGroupMenuExecParam mmep;
+ mmep = (lpSubGroupMenuExecParam)lParam;
+ if (mmep != NULL){
+ FreeAndNil((void **)&mmep->szServiceName);
+ FreeAndNil((void **)&mmep);
+ }
+
+return(0);
+};
+
+//wparam menu handle to pass to clc.c
+//lparam WM_COMMAND HWND
+INT_PTR GroupMenuExecProxy(WPARAM wParam,LPARAM lParam)
+{
+ SendMessage(lParam?(HWND)lParam:(HWND)pcli->hwndContactTree,WM_COMMAND,wParam,0);
+ return 0;
+};
+
+void InitSubGroupMenus(void)
+{
+ TMenuParam tmp;
+ OptParam op;
+
+ CreateServiceFunction("CLISTMENUSSubGroup/ExecService",SubGroupMenuExecService);
+ CreateServiceFunction("CLISTMENUSSubGroup/FreeOwnerDataSubGroupMenu",FreeOwnerDataSubGroupMenu);
+ CreateServiceFunction("CLISTMENUSSubGroup/SubGroupMenuonAddService",SubGroupMenuonAddService);
+ CreateServiceFunction("CLISTMENUSSubGroup/SubGroupMenuCheckService",SubGroupMenuCheckService);
+ CreateServiceFunction("CLISTMENUSSubGroup/GroupMenuExecProxy",GroupMenuExecProxy);
+
+ //CreateServiceFunction("CLISTMENUSSubGroup/HideSubGroupsHelper",HideSubGroupsHelper);
+ //CreateServiceFunction("CLISTMENUSSubGroup/UseSubGroupsHelper",UseSubGroupsHelper);
+ //CreateServiceFunction("CLISTMENUSSubGroup/HideOfflineRootHelper",HideOfflineRootHelper);
+
+ CreateServiceFunction("CList/AddSubGroupMenuItem",AddSubGroupMenuItem);
+ CreateServiceFunction(MS_CLIST_REMOVESUBGROUPMENUITEM,RemoveSubGroupMenuItem);
+ CreateServiceFunction(MS_CLIST_MENUBUILDSUBGROUP,BuildSubGroupMenu);
+
+ HookEvent(ME_CLIST_PREBUILDSUBGROUPMENU,OnBuildSubGroupMenu);
+
+ //SubGroup menu
+ memset(&tmp,0,sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ tmp.CheckService = NULL;
+ tmp.ExecService = "CLISTMENUSSubGroup/ExecService";
+ tmp.name = LPGEN("SubGroupMenu");
+ hSubGroupMenuObject = (HANDLE)CallService(MO_CREATENEWMENUOBJECT,(WPARAM)0,(LPARAM)&tmp);
+
+ op.Handle = hSubGroupMenuObject;
+ op.Setting = OPT_USERDEFINEDITEMS;
+ op.Value = TRUE;
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ op.Handle = hSubGroupMenuObject;
+ op.Setting = OPT_MENUOBJECT_SET_FREE_SERVICE;
+ op.Value = (INT_PTR)"CLISTMENUSSubGroup/FreeOwnerDataSubGroupMenu";
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ op.Handle = hSubGroupMenuObject;
+ op.Setting = OPT_MENUOBJECT_SET_ONADD_SERVICE;
+ op.Value = (INT_PTR)"CLISTMENUSSubGroup/SubGroupMenuonAddService";
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ op.Handle = hSubGroupMenuObject;
+ op.Setting = OPT_MENUOBJECT_SET_CHECK_SERVICE;
+ op.Value = (INT_PTR)"CLISTMENUSSubGroup/SubGroupMenuCheckService";
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ //add exit command to menu
+ CLISTMENUITEM mi;
+ GroupMenuParam gmp;
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 1000;
+ mi.hIcon = ske_ImageList_GetIcon(hCListImages,NewGroupIconidx,0);
+ mi.pszService = "CLISTMENUSSubGroup/GroupMenuExecProxy";
+ mi.pszName = LPGEN("&New SubGroup");
+ gmp.lParam = 0;gmp.wParam = POPUP_NEWSUBGROUP;
+ hNewSubGroupMenuItem = (HANDLE)AddSubGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 1001;
+ mi.hIcon = NULL;
+ mi.pszService = "CLISTMENUSSubGroup/GroupMenuExecProxy";
+ mi.pszName = LPGEN("&Hide Offline Users in here");
+ gmp.lParam = 0;
+ gmp.wParam = POPUP_GROUPHIDEOFFLINE;
+ hHideOfflineUsersHereMenuItem = (HANDLE)AddSubGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 1002;
+ mi.hIcon = NULL;
+ mi.pszService = "CLISTMENUSSubGroup/GroupMenuExecProxy";
+ mi.pszName = LPGEN("&Show Offline Users in here");
+ gmp.lParam = 0;
+ gmp.wParam = POPUP_GROUPSHOWOFFLINE;
+ hShowOfflineUsersHereMenuItem = (HANDLE)AddSubGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 900001;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_RENAME);
+ mi.pszService = "CLISTMENUSSubGroup/GroupMenuExecProxy";
+ mi.pszName = LPGEN("&Rename Group");
+ gmp.lParam = 0;gmp.wParam = POPUP_RENAMEGROUP;
+ AddSubGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 900002;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_DELETE);
+ mi.pszService = "CLISTMENUSSubGroup/GroupMenuExecProxy";
+ mi.pszName = LPGEN("&Delete Group");
+ gmp.lParam = 0;gmp.wParam = POPUP_DELETEGROUP;
+ AddSubGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+}
+
+//////////////////////////////END SubGroup MENU/////////////////////////
diff --git a/plugins/Clist_modern/src/modern_image_array.cpp b/plugins/Clist_modern/src/modern_image_array.cpp
new file mode 100644
index 0000000000..21a87c18d7
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_image_array.cpp
@@ -0,0 +1,705 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+
+Created by Pescuma
+
+*/
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_image_array.h"
+#include "hdr/modern_commonprototypes.h"
+
+// To use this code in other places, replace the body of this func by the body of ske_CreateDIB32
+static HBITMAP ImageArray_CreateBitmapPoint(int cx, int cy, void ** pt)
+{
+ return ske_CreateDIB32Point(cx, cy, pt);
+}
+
+
+// Initialize data
+static BOOL ImageArray_Alloc(LP_IMAGE_ARRAY_DATA iad, int size)
+{
+ int size_grow = size;
+
+ if (size_grow > iad->nodes_allocated_size)
+ {
+ size_grow += iad->grow_step - (size_grow % iad->grow_step);
+
+ if (iad->nodes != NULL)
+ {
+ IMAGE_ARRAY_DATA_NODE *tmp = (IMAGE_ARRAY_DATA_NODE *) realloc((void *)iad->nodes,
+ sizeof(IMAGE_ARRAY_DATA_NODE) * size_grow);
+
+ if (tmp == NULL)
+ {
+ TRACE("Out of memory: realloc returned NULL (ImageArray_Alloc)");
+ ImageArray_Free(iad, FALSE);
+ return FALSE;
+ }
+
+ iad->nodes = tmp;
+ memset( &iad->nodes[iad->nodes_allocated_size], 0, (size_grow - iad->nodes_allocated_size) * sizeof(IMAGE_ARRAY_DATA_NODE));
+ }
+ else
+ {
+ iad->nodes = (IMAGE_ARRAY_DATA_NODE *) malloc(sizeof(IMAGE_ARRAY_DATA_NODE) * size_grow);
+
+ if (iad->nodes == NULL)
+ {
+ TRACE("Out of memory: alloc returned NULL (ImageArray_Alloc)");
+
+ ImageArray_Free(iad, FALSE);
+
+ return FALSE;
+ }
+
+ ZeroMemory(iad->nodes, sizeof(IMAGE_ARRAY_DATA_NODE) * size_grow);
+ }
+
+ iad->nodes_allocated_size = size_grow;
+ }
+ else if (size < iad->nodes_allocated_size)
+ {
+ // Give some more space to try to avoid a free
+ if ((iad->nodes_allocated_size - size) / iad->grow_step >= 2 )
+ {
+ IMAGE_ARRAY_DATA_NODE *tmp;
+
+ size_grow += iad->grow_step - (size_grow % iad->grow_step);
+
+ tmp = (IMAGE_ARRAY_DATA_NODE *) realloc((void *)iad->nodes, sizeof(IMAGE_ARRAY_DATA_NODE) * size_grow);
+
+ if (tmp == NULL)
+ {
+ TRACE("Out of memory: realloc returned NULL when reducing size! (ImageArray_Alloc)");
+
+ ImageArray_Free(iad, FALSE);
+
+ return FALSE;
+ }
+
+ iad->nodes = tmp;
+ }
+ }
+
+ iad->nodes_size = size;
+
+ return TRUE;
+}
+
+
+// Initialize data
+void ImageArray_Initialize(LP_IMAGE_ARRAY_DATA iad, BOOL width_based, int grow_step)
+{
+ iad->width_based = width_based;
+ iad->grow_step = grow_step;
+ if (iad->grow_step <= 0)
+ {
+ iad->grow_step = 1;
+ }
+ iad->hdc = CreateCompatibleDC(NULL);
+ iad->img = NULL;
+
+ iad->width = 0;
+ iad->height = 0;
+
+ InitializeCriticalSection(&iad->cs);
+
+ iad->nodes = NULL;
+ iad->nodes_allocated_size = 0;
+ iad->nodes_size = 0;
+}
+
+
+// Free data
+// If keep_bitmap is TRUE, doesn't delete de bitmap and return its handle. Else, return NULL
+HBITMAP ImageArray_Free(LP_IMAGE_ARRAY_DATA iad, BOOL keep_bitmap)
+{
+ mod_DeleteDC(iad->hdc);
+
+ if (iad->img != NULL && !keep_bitmap)
+ {
+ DeleteObject(iad->img);
+ iad->img = NULL;
+ iad->width = 0;
+ iad->height = 0;
+ }
+
+ if (iad->nodes != NULL)
+ {
+ free(iad->nodes);
+ iad->nodes = NULL;
+ iad->nodes_allocated_size = 0;
+ iad->nodes_size = 0;
+ }
+
+ DeleteCriticalSection(&iad->cs);
+
+ return iad->img;
+}
+
+// Free data but keep config
+void ImageArray_Clear(LP_IMAGE_ARRAY_DATA iad)
+{
+ HDC tmpdc = CreateCompatibleDC(iad->hdc);
+ if (iad->hdc) mod_DeleteDC(iad->hdc);
+ iad->hdc = tmpdc;
+
+ if (iad->img != NULL)
+ {
+ DeleteObject(iad->img);
+ iad->img = NULL;
+ iad->width = 0;
+ iad->height = 0;
+ }
+
+ if (iad->nodes != NULL)
+ {
+ free(iad->nodes);
+ iad->nodes = NULL;
+ iad->nodes_allocated_size = 0;
+ iad->nodes_size = 0;
+ }
+}
+
+
+// Add image to the list (return the index of the image or -1 on error)
+// If pos == -1, add to the end of the list
+int ImageArray_AddImage(LP_IMAGE_ARRAY_DATA iad, HBITMAP hBmp, int pos)
+{
+ BITMAP bm;
+ int new_width, new_height;
+ HBITMAP hNewBmp, old_bmp;
+ HDC hdc_old;
+ BOOL last_one;
+
+ int i;
+
+ if (hBmp == NULL)
+ return -1;
+
+ EnterCriticalSection(&iad->cs);
+
+ if (pos < 0)
+ pos = iad->nodes_size;
+
+ // Add to end?
+ if (pos >= iad->nodes_size)
+ {
+ pos = iad->nodes_size;
+ last_one = TRUE;
+ }
+ else
+ {
+ last_one = FALSE;
+ }
+
+ // Get bounds
+ if ( !GetObject(hBmp,sizeof(BITMAP),&bm))
+ {
+ LeaveCriticalSection(&iad->cs);
+ return -1;
+ }
+
+ if (iad->width_based)
+ {
+ new_width = max(bm.bmWidth, iad->width);
+ new_height = iad->height + bm.bmHeight;
+ }
+ else
+ {
+ new_width = bm.bmWidth + iad->width;
+ new_height = max(iad->height, bm.bmHeight);
+ }
+
+ // Alloc image
+ hNewBmp = ImageArray_CreateBitmapPoint(new_width, new_height,&(iad->lpBits));
+ if (hNewBmp == NULL)
+ {
+ LeaveCriticalSection(&iad->cs);
+ return -1;
+ }
+
+ // Alloc array
+ if ( !ImageArray_Alloc(iad, iad->nodes_size + 1))
+ {
+ DeleteObject(hNewBmp);
+ LeaveCriticalSection(&iad->cs);
+ return -1;
+ }
+
+ // Move image...
+
+ // Set some draw states
+ SelectObject(iad->hdc, hNewBmp);
+ hdc_old = CreateCompatibleDC(iad->hdc);
+ old_bmp = (HBITMAP)GetCurrentObject(hdc_old, OBJ_BITMAP);
+
+ SetBkMode(iad->hdc,TRANSPARENT);
+ {
+ POINT org;
+ GetBrushOrgEx(iad->hdc, &org);
+ SetStretchBltMode(iad->hdc, HALFTONE);
+ SetBrushOrgEx(iad->hdc, org.x, org.y, NULL);
+ }
+
+ {
+ int x = 0, y = 0, w = 0, h = 0;
+
+ // 1- old data
+ if (pos > 0)
+ {
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ w = iad->width;
+ h = 0;
+ for (i=0; i < pos; i++)
+ {
+ h += iad->nodes[i].height;
+ }
+ }
+ else
+ {
+ h = iad->height;
+ w = 0;
+ for (i=0; i < pos; i++)
+ {
+ w += iad->nodes[i].width;
+ }
+ }
+ BitBlt(iad->hdc, 0, 0, w, h, hdc_old, 0, 0, SRCCOPY);
+ }
+
+ // 2- new image
+ if (iad->width_based)
+ {
+ x = 0;
+ y = h;
+ }
+ else
+ {
+ x = w;
+ y = 0;
+ }
+ SelectObject(hdc_old, hBmp);
+ BitBlt(iad->hdc, x, y, bm.bmWidth, bm.bmHeight, hdc_old, 0, 0, SRCCOPY);
+
+ // 3- old data
+ if ( !last_one)
+ {
+ int ox, oy;
+
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ ox = 0;
+ oy = y;
+
+ x = 0;
+ y += bm.bmHeight;
+
+ w = iad->width;
+ h = iad->height - h;
+ }
+ else
+ {
+ ox = x;
+ oy = 0;
+
+ x += bm.bmWidth;
+ y = 0;
+
+ w = iad->width - w;
+ h = iad->height;
+ }
+ BitBlt(iad->hdc, x, y, w, h, hdc_old, ox, oy, SRCCOPY);
+ }
+ }
+
+ // restore things
+ SelectObject(hdc_old,old_bmp);
+ mod_DeleteDC(hdc_old);
+ if (iad->img != NULL) DeleteObject(iad->img);
+ iad->img = hNewBmp;
+
+ // Move array
+ if ( !last_one && iad->nodes_size > 1)
+ {
+ memmove(&iad->nodes[pos+1], &iad->nodes[pos], (iad->nodes_size - pos) * sizeof(IMAGE_ARRAY_DATA_NODE));
+ }
+ iad->nodes[pos].width = bm.bmWidth;
+ iad->nodes[pos].height = bm.bmHeight;
+
+ iad->width = new_width;
+ iad->height = new_height;
+
+ // Finished it!
+ LeaveCriticalSection(&iad->cs);
+
+ return pos;
+}
+
+
+
+// Change an image in the list (return TRUE on success)
+BOOL ImageArray_ChangeImage(LP_IMAGE_ARRAY_DATA iad, HBITMAP hBmp, int pos)
+{
+ BITMAP bm;
+ int new_width, new_height;
+ HBITMAP hNewBmp;
+ HDC hdc_old;
+ int i;
+
+ if (hBmp == NULL)
+ return FALSE;
+
+ if (pos < 0)
+ return FALSE;
+
+ if (pos >= iad->nodes_size)
+ return FALSE;
+
+ EnterCriticalSection(&iad->cs);
+
+ // Get bounds
+ if ( !GetObject(hBmp,sizeof(BITMAP),&bm))
+ {
+ LeaveCriticalSection(&iad->cs);
+ return FALSE;
+ }
+
+ if (iad->width_based)
+ {
+ new_width = max(bm.bmWidth, iad->width);
+ new_height = iad->height + bm.bmHeight - iad->nodes[pos].height;
+ }
+ else
+ {
+ new_width = bm.bmWidth + iad->width - iad->nodes[pos].width;
+ new_height = max(iad->height, bm.bmHeight);
+ }
+
+ // Alloc image
+ hNewBmp = ImageArray_CreateBitmapPoint(new_width, new_height,&(iad->lpBits));
+ if (hNewBmp == NULL)
+ {
+ LeaveCriticalSection(&iad->cs);
+ return FALSE;
+ }
+
+ // Move image...
+
+ // Set some draw states
+ SelectObject(iad->hdc, hNewBmp);
+ hdc_old = CreateCompatibleDC(iad->hdc);
+
+ SetBkMode(iad->hdc, TRANSPARENT);
+ {
+ POINT org;
+ GetBrushOrgEx(iad->hdc, &org);
+ SetStretchBltMode(iad->hdc, HALFTONE);
+ SetBrushOrgEx(iad->hdc, org.x, org.y, NULL);
+ }
+
+ {
+ int x = 0, y = 0, w = 0, h = 0;
+
+ // 1- old data
+ if (pos > 0)
+ {
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ w = iad->width;
+ h = 0;
+ for (i=0; i < pos; i++)
+ {
+ h += iad->nodes[i].height;
+ }
+ }
+ else
+ {
+ h = iad->height;
+ w = 0;
+ for (i=0; i < pos; i++)
+ {
+ w += iad->nodes[i].width;
+ }
+ }
+ BitBlt(iad->hdc, 0, 0, w, h, hdc_old, 0, 0, SRCCOPY);
+ }
+
+ // 2- new image
+ if (iad->width_based)
+ {
+ x = 0;
+ y = h;
+ }
+ else
+ {
+ x = w;
+ y = 0;
+ }
+ SelectObject(hdc_old, hBmp);
+ BitBlt(iad->hdc, x, y, bm.bmWidth, bm.bmHeight, hdc_old, 0, 0, SRCCOPY);
+
+ // 3- old data
+ if (pos < iad->nodes_size - 1)
+ {
+ int ox, oy;
+
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ ox = 0;
+ oy = y + iad->nodes[pos].height;
+
+ x = 0;
+ y += bm.bmHeight;
+
+ w = iad->width;
+ h = iad->height - h - iad->nodes[pos].height;
+ }
+ else
+ {
+ ox = x + iad->nodes[pos].width;
+ oy = 0;
+
+ x += bm.bmWidth;
+ y = 0;
+
+ w = iad->width - w - iad->nodes[pos].width;
+ h = iad->height;
+ }
+ BitBlt(iad->hdc, x, y, w, h, hdc_old, ox, oy, SRCCOPY);
+ }
+ }
+
+ // restore things
+ mod_DeleteDC(hdc_old);
+ if (iad->img != NULL) DeleteObject(iad->img);
+ iad->img = hNewBmp;
+
+ // Move array
+ iad->nodes[pos].width = bm.bmWidth;
+ iad->nodes[pos].height = bm.bmHeight;
+
+ iad->width = new_width;
+ iad->height = new_height;
+
+ // Finished it!
+ LeaveCriticalSection(&iad->cs);
+
+ return pos;
+}
+
+
+// Remove an image
+BOOL ImageArray_RemoveImage(LP_IMAGE_ARRAY_DATA iad, int pos)
+{
+ int new_width, new_height;
+ HBITMAP hNewBmp;
+ HDC hdc_old;
+ int i;
+
+ if (pos < 0)
+ return FALSE;
+
+ if (pos >= iad->nodes_size)
+ return FALSE;
+
+ EnterCriticalSection(&iad->cs);
+
+ // Get bounds
+ if (iad->width_based)
+ {
+ new_width = iad->width;
+ new_height = iad->height - iad->nodes[pos].height;
+ }
+ else
+ {
+ new_width = iad->width - iad->nodes[pos].width;
+ new_height = iad->height;
+ }
+
+ // Alloc image
+ hNewBmp = ImageArray_CreateBitmapPoint(new_width, new_height,&(iad->lpBits));
+ if (hNewBmp == NULL)
+ {
+ LeaveCriticalSection(&iad->cs);
+ return FALSE;
+ }
+
+ // Move image...
+
+ // Set some draw states
+ SelectObject(iad->hdc, hNewBmp);
+ hdc_old = CreateCompatibleDC(iad->hdc);
+
+ SetBkMode(iad->hdc, TRANSPARENT);
+ {
+ POINT org;
+ GetBrushOrgEx(iad->hdc, &org);
+ SetStretchBltMode(iad->hdc, HALFTONE);
+ SetBrushOrgEx(iad->hdc, org.x, org.y, NULL);
+ }
+
+ {
+ int x = 0, y = 0, w = 0, h = 0;
+
+ if (pos > 0)
+ {
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ w = iad->width;
+ h = 0;
+ for (i=0; i < pos; i++)
+ {
+ h += iad->nodes[i].height;
+ }
+ }
+ else
+ {
+ h = iad->height;
+ w = 0;
+ for (i=0; i < pos; i++)
+ {
+ w += iad->nodes[i].width;
+ }
+ }
+ BitBlt(iad->hdc, 0, 0, w, h, hdc_old, 0, 0, SRCCOPY);
+ }
+
+ if (pos < iad->nodes_size - 1)
+ {
+ int ox, oy;
+
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ ox = 0;
+ oy = h + iad->nodes[pos].height;
+
+ x = 0;
+ y = h;
+
+ w = iad->width;
+ h = iad->height - h - iad->nodes[pos].height;
+ }
+ else
+ {
+ ox = w + iad->nodes[pos].width;
+ oy = 0;
+
+ x = w;
+ y = 0;
+
+ w = iad->width - w - iad->nodes[pos].width;
+ h = iad->height;
+ }
+ BitBlt(iad->hdc, x, y, w, h, hdc_old, ox, oy, SRCCOPY);
+ }
+ }
+
+ // restore things
+ mod_DeleteDC(hdc_old);
+ if (iad->img != NULL) DeleteObject(iad->img);
+ iad->img = hNewBmp;
+
+ // Move array
+ if (pos < iad->nodes_size - 1)
+ {
+ memmove(&iad->nodes[pos], &iad->nodes[pos + 1], (iad->nodes_size - pos - 1) * sizeof(IMAGE_ARRAY_DATA_NODE));
+ }
+
+ iad->nodes_size--;
+
+ iad->width = new_width;
+ iad->height = new_height;
+
+ // Free array
+ ImageArray_Alloc(iad, iad->nodes_size);
+
+ // Finished it!
+ LeaveCriticalSection(&iad->cs);
+
+ return pos;
+}
+
+
+
+BOOL ImageArray_DrawImage(LP_IMAGE_ARRAY_DATA iad, int pos, HDC hdcDest, int nXDest, int nYDest, BYTE Alpha)
+{
+ if (hdcDest == NULL || pos < 0 || pos >= iad->nodes_size)
+ return FALSE;
+
+ EnterCriticalSection(&iad->cs);
+ {
+ int w, h, i;
+
+ if (iad->width_based)
+ {
+ w = 0;
+ h = 0;
+ for (i=0; i < pos; i++)
+ {
+ h += iad->nodes[i].height;
+ }
+ }
+ else
+ {
+ h = 0;
+ w = 0;
+ for (i=0; i < pos; i++)
+ {
+ w += iad->nodes[i].width;
+ }
+ }
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, Alpha, AC_SRC_ALPHA };
+ /*ske_*/AlphaBlend(hdcDest, nXDest, nYDest, iad->nodes[pos].width, iad->nodes[pos].height, iad->hdc, w, h, iad->nodes[pos].width, iad->nodes[pos].height,bf);
+ }
+ }
+
+
+ LeaveCriticalSection(&iad->cs);
+ return FALSE;
+}
+
+BOOL ImageArray_GetImageSize(LP_IMAGE_ARRAY_DATA iad, int pos, SIZE * lpSize)
+{
+ EnterCriticalSection(&iad->cs);
+ if (lpSize)
+ {
+ lpSize->cx = iad->nodes[pos].width;
+ lpSize->cy = iad->nodes[pos].height;
+ }
+ LeaveCriticalSection(&iad->cs);
+ return TRUE;
+} \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_keyboard.cpp b/plugins/Clist_modern/src/modern_keyboard.cpp
new file mode 100644
index 0000000000..56f9ed6d2e
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_keyboard.cpp
@@ -0,0 +1,67 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include <m_hotkeys.h>
+
+int InitSkinHotKeys(void);
+
+INT_PTR hkCloseMiranda(WPARAM wParam,LPARAM lParam)
+{
+ CallService("CloseAction", 0, 0);
+ return 0;
+}
+
+INT_PTR hkRestoreStatus(WPARAM wParam,LPARAM lParam)
+{
+ int nStatus = db_get_w(NULL, "CList", "Status", ID_STATUS_OFFLINE);
+ CallService(MS_CLIST_SETSTATUSMODE, nStatus, 0);
+
+ return 0;
+}
+
+int InitSkinHotKeys(void)
+{
+ CreateServiceFunction("CLIST/HK/CloseMiranda",hkCloseMiranda);
+ CreateServiceFunction("CLIST/HK/RestoreStatus",hkRestoreStatus);
+
+ HOTKEYDESC shk = {0};
+ shk.cbSize = sizeof(shk);
+
+ shk.pszDescription = LPGEN("Close Miranda");
+ shk.pszName = "CloseMiranda";
+ shk.pszSection = LPGEN("Main");
+ shk.pszService = "CLIST/HK/CloseMiranda";
+ Hotkey_Register(&shk);
+
+ shk.pszDescription = LPGEN("Restore last status");
+ shk.pszName = "RestoreLastStatus";
+ shk.pszSection = LPGEN("Status");
+ shk.pszService = "CLIST/HK/RestoreStatus";
+ Hotkey_Register(&shk);
+
+ return 0;
+}
+
+void UninitSkinHotKeys(void)
+{
+}
diff --git a/plugins/Clist_modern/src/modern_log.cpp b/plugins/Clist_modern/src/modern_log.cpp
new file mode 100644
index 0000000000..af2b9c9a68
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_log.cpp
@@ -0,0 +1,46 @@
+#include "hdr/modern_commonheaders.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+
+void Log(const char *file,int line,const char *fmt,...)
+{
+
+
+ va_list vararg;
+ const char *file_tmp;
+ char str[1024];
+ char buf[1024];
+
+ file_tmp = strrchr(file, '\\');
+ if (file_tmp == NULL)
+ file_tmp = file;
+ else
+ file_tmp++;
+
+ va_start(vararg,fmt);
+ mir_vsnprintf(str,SIZEOF(str),fmt,vararg);
+ va_end(vararg);
+ {
+ char * tmp = str;
+ while(*tmp != '\0')
+ {
+ if (*tmp == '\n') *tmp = ' ';
+ tmp++;
+ }
+ }
+ mir_snprintf(buf,SIZEOF(buf),"clist_modern:[%u - %u]: %s \t\t(%s Ln %d)\n",GetCurrentThreadId(),GetTickCount(),str,file_tmp,line);
+#ifdef _FILELOG_
+ {
+ FILE *fp;
+ fp = fopen(_FILELOG_,"at");
+ fprintf(fp,buf);
+ fclose(fp);
+ }
+#else
+ OutputDebugStringA(buf);
+#endif
+}
+
diff --git a/plugins/Clist_modern/src/modern_newrowopts.cpp b/plugins/Clist_modern/src/modern_newrowopts.cpp
new file mode 100644
index 0000000000..b44ea0dbe3
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_newrowopts.cpp
@@ -0,0 +1,198 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2003 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.
+*/
+
+/************************************************************************/
+/* Author Artem Shpynov (shpynov@nm.ru) */
+/************************************************************************/
+
+/************************************************************************/
+/********* New row design options file handle ********/
+/************************************************************************/
+
+
+#include "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "m_clc.h"
+
+#define EMPTY_PLACE 255
+#define COLUMNS_PLACE 254
+#define ROWS_PLACE 253
+
+typedef struct _NodeList
+{
+ BYTE bType;
+ int pData;
+ DWORD AllocatedChilds;
+ struct _NodeList * childNodes;
+ struct _NodeList * itemParent;
+} NodeList;
+
+NodeList * RootNode = NULL;
+
+NodeList * AddNode(NodeList * Parent)
+{
+ NodeList * res;
+ if ( !Parent)
+ {
+ res = (NodeList *)mir_alloc(sizeof(NodeList));
+ memset(res,0,sizeof(NodeList));
+ return res;
+ }
+ Parent->childNodes = (NodeList*) mir_realloc(Parent->childNodes,sizeof(NodeList)*(Parent->AllocatedChilds+1));
+ memset(&(Parent->childNodes[Parent->AllocatedChilds]),0,sizeof(NodeList));
+ Parent->childNodes[Parent->AllocatedChilds].itemParent = Parent;
+ Parent->AllocatedChilds++;
+ return &(Parent->childNodes[Parent->AllocatedChilds-1]);
+}
+
+
+BOOL RemoveChildNode(NodeList * FromList, DWORD index)
+{
+ if ( !FromList) return FALSE;
+ if (FromList->AllocatedChilds <= index) return FALSE;
+ NodeList *work = &(FromList->childNodes[index]);
+ for (size_t i=0; i < work->AllocatedChilds; i++)
+ if (work->childNodes[i].AllocatedChilds)
+ RemoveChildNode(work->childNodes, (DWORD)i);
+
+ if (work->AllocatedChilds) {
+ mir_free_and_nil(work->childNodes);
+ work->AllocatedChilds = 0;
+ }
+ memmove(FromList->childNodes+index,FromList->childNodes+index+1,sizeof(NodeList)*(FromList->AllocatedChilds-index-1));
+ FromList->AllocatedChilds--;
+ return TRUE;
+}
+
+BOOL RemoveNode(NodeList * FromList)
+{
+ if ( !FromList) return FALSE;
+ if (FromList->itemParent)
+ {
+ DWORD k;
+ for (k = 0;k < FromList->itemParent->AllocatedChilds;k++)
+ if (&(FromList->itemParent->childNodes[k]) == FromList)
+ {
+ BOOL res = RemoveChildNode(FromList->itemParent,k);
+ return res;
+ }
+ }
+ do
+ {
+ RemoveChildNode(FromList,0);
+ }
+ while (FromList->AllocatedChilds>0);
+ mir_free_and_nil(FromList->childNodes);
+ mir_free_and_nil(FromList);
+ return TRUE;
+}
+int ident = 0;
+void PrintIdent()
+{
+ int k;
+ for (k = 0;k < ident;k++)
+ TRACE("-");
+}
+
+void TraceTreeLevel(NodeList * node)
+{
+ DWORD i;
+ if ( !node) return;
+ PrintIdent();
+ {
+ char buf[255];
+ mir_snprintf(buf,SIZEOF(buf),"%d\n",node->pData);
+ TRACE(buf);
+ }
+ ident += 5;
+ for (i=0; i < node->AllocatedChilds;i++)
+ {
+
+ if (node->childNodes[i].AllocatedChilds>0)
+ TraceTreeLevel(&(node->childNodes[i]));
+ else
+ {
+ PrintIdent();
+ {
+ char buf[255];
+ mir_snprintf(buf,SIZEOF(buf),"%d\n",node->childNodes[i].pData);
+ TRACE(buf);
+ }
+ }
+ }
+ ident -= 5;
+}
+
+BOOL CALLBACK DlgProcItemNewRowOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ NodeList * res1,*res2, *res3;
+ int i=0;
+ RootNode = AddNode(NULL);
+ RootNode->pData = i++;
+ res1 = AddNode(RootNode);
+ res1->pData = i++;
+ res1 = AddNode(RootNode);
+ res1->pData = i++;
+ res2 = AddNode(res1);
+ res2->pData = i++;
+ res2 = AddNode(res1);
+ res2->pData = i++;
+ res3 = AddNode(res2);
+ res3->pData = i++;
+ res3 = AddNode(res1);
+ res3->pData = i++;
+ res3 = AddNode(RootNode);
+ res3->pData = i++;
+ TRACE("*********** Nodes DUMP 1 ***********\n");
+ TraceTreeLevel(RootNode);
+ if (RemoveNode(res1)) res1 = 0;
+ TRACE("*********** Nodes DUMP 2 ***********\n");
+ TraceTreeLevel(RootNode);
+ //CheckDlgButton(hwndDlg, IDC_HIDE_ICON_ON_AVATAR, DBGetContactSettingByte(NULL,"CList","IconHideOnAvatar",SETTING_HIDEICONONAVATAR_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ MessageBox(hwndDlg,_T("Init NewRow Dialog"),_T("Notify"),MB_OK);
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->idFrom)
+ {
+ case 0:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ return 0;
+};
diff --git a/plugins/Clist_modern/src/modern_popup.cpp b/plugins/Clist_modern/src/modern_popup.cpp
new file mode 100644
index 0000000000..9da27e5ff9
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_popup.cpp
@@ -0,0 +1,131 @@
+/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_popup.h"
+
+
+BOOL EnablePopups = FALSE;
+
+static LRESULT CALLBACK DumbPopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+
+// Show an error popup
+void ShowErrPopup(const char *title, const char *description)
+{
+ ShowPopup(title == NULL ? "Modern Contact List Error" : title, description, POPUP_TYPE_ERROR);
+}
+
+
+// Show an trace popup
+void ShowTracePopup(const char *text)
+{
+#ifdef _DEBUG
+ static int num = 0;
+ char tmp[1024];
+
+ mir_snprintf(tmp, SIZEOF(tmp), "CM TRACE %d: %s", num, text);
+ TRACE(tmp);
+ TRACE("\n");
+ num++;
+
+ ShowPopup(tmp, "", POPUP_TYPE_NORMAL);
+#endif
+}
+
+
+// Show an popup
+void ShowPopup(const char *title, const char *description, int type)
+{
+ POPUPDATAEX ppd;
+ int ret;
+
+ if ( !ServiceExists(MS_POPUP_ADDPOPUPEX) || !EnablePopups)
+ {
+ return;
+ }
+
+ // Make popup
+ ZeroMemory(&ppd, sizeof(ppd));
+ ppd.lchContact = 0;
+ ppd.lchIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+
+ strncpy(ppd.lpzContactName, title == NULL ? "Modern Contact List" : title, SIZEOF(ppd.lpzContactName)-1);
+ ppd.lpzContactName[SIZEOF(ppd.lpzContactName)-1] = '\0';
+
+ if (description != NULL)
+ {
+ strncpy(ppd.lpzText, description, SIZEOF(ppd.lpzText)-1);
+ ppd.lpzText[SIZEOF(ppd.lpzText)-1] = '\0';
+ }
+
+ if (type == POPUP_TYPE_NORMAL || type == POPUP_TYPE_TEST)
+ {
+ ppd.colorBack = 0;
+ ppd.colorText = 0;
+ }
+ else // if (type == POPUP_TYPE_ERROR)
+ {
+ ppd.colorBack = -1;
+ ppd.colorText = RGB(255,255,255);
+ }
+
+ ppd.PluginWindowProc = DumbPopupDlgProc;
+
+ if (type == POPUP_TYPE_NORMAL || type == POPUP_TYPE_TEST)
+ {
+ ppd.iSeconds = 0;
+ }
+ else // if (type == POPUP_TYPE_ERROR)
+ {
+ ppd.iSeconds = 0;
+ }
+
+ // Now that every field has been filled, we want to see the popup.
+ ret = CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd,0);
+
+ ret++;
+}
+
+
+
+// Handle to popup events
+static LRESULT CALLBACK DumbPopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch(message) {
+ case WM_COMMAND:
+ {
+ PUDeletePopUp(hWnd);
+ return TRUE;
+ }
+
+ case WM_CONTEXTMENU:
+ {
+ PUDeletePopUp(hWnd);
+ return TRUE;
+ }
+
+ case UM_FREEPLUGINDATA:
+ {
+ return TRUE;
+ }
+ }
+
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
diff --git a/plugins/Clist_modern/src/modern_row.cpp b/plugins/Clist_modern/src/modern_row.cpp
new file mode 100644
index 0000000000..d2799d2b9a
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_row.cpp
@@ -0,0 +1,789 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+
+Created by Anton Senko aka ZORG , tweaked by Artem Shpynov aka FYR
+
+*/
+
+#include "hdr/modern_commonheaders.h"
+
+/*
+#include "m_stdhdr.h"
+
+#include <windows.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 "resource.h"
+#include "hdr/modern_commonheaders.h"
+*/
+#include "hdr/modern_row.h"
+
+//Futher declaration
+void rowCalculateMinSize(ROWCELL* cell);
+void rowEqualize(ROWCELL* cell);
+void rowResetEmptyRects(ROWCELL* cell);
+void rowDeleteTree(ROWCELL* cell);
+////////
+
+
+
+//extern ROWCELL * gl_RowRoot; // Óêàçàòåëü íà êîðíåâîé òýã < contact> â øàáëîíå
+//ROWOBJECTS RowTA; // Ñòðóêòóðà, ÷åðåç êîòîðóþ îñóùåñòâëÿåòñÿ äîñòóï ê ýëåìåíòàì êîíòàêòà.
+// Ôîðìèðóåòñÿ ïðè âûïîëíåíèè ôó-è RowParce. Íåÿâíûé ïàðàìåòð ôóè rowParserGetParam
+
+
+// Ôîðìèðóåòñÿ ïðè âûïîëíåíèè ôó-è RowParce. Íåÿâíûé ïàðàìåòð ôóè rowParserGetParam
+
+char *tmplbuf; // Áóôåð äëÿ õðàíåíèÿ øàáëîíà â òåêñòîâîì âèäå
+
+ROWCELL *cppInitModernRow(ROWCELL ** tabAccess)
+{
+ int fsize;
+ int seq = 0;
+ ROWCELL * RowRoot = NULL;
+ FILE * hFile;
+ int i=0;
+ if ( !db_get_b(NULL,"ModernData","UseAdvancedRowLayout",SETTING_ROW_ADVANCEDLAYOUT_DEFAULT)) return NULL;
+ tmplbuf = NULL;
+ if (db_get_b(NULL,"ModernData","UseAdvancedRowLayout",SETTING_ROW_ADVANCEDLAYOUT_DEFAULT) == 1)
+ tmplbuf = db_get_sa(NULL,"ModernData","RowTemplate");
+ if (tmplbuf) {
+ rowParse(RowRoot, RowRoot, tmplbuf, i, seq,tabAccess);
+ mir_free(tmplbuf);
+ return RowRoot;
+ }
+ if (hFile = fopen("template.txt", "rb"))
+ {
+ fsize = _filelength(_fileno(hFile));
+ tmplbuf = (char*)malloc(fsize+1);
+ ZeroMemory(tmplbuf, fsize+1);
+
+ for (i=0; i < fsize; i++) tmplbuf[i] = getc(hFile);
+ tmplbuf[i] = 0;
+ i=0;
+ rowParse(RowRoot, RowRoot, tmplbuf, i, seq,tabAccess);
+ db_set_s(NULL,"ModernData","RowTemplate",tmplbuf);
+ free(tmplbuf);
+ fclose(hFile);
+ return RowRoot;
+ }
+ return NULL;
+
+}
+
+void cppDeleteTree(ROWCELL * RowRoot)
+{
+ ROWCELL *rc = RowRoot;
+ rowDeleteTree(rc);
+}
+
+int cppCalculateRowHeight(ROWCELL *RowRoot)
+{
+ RowRoot->h = 0;
+ RowRoot->w = 0;
+ rowResetEmptyRects(RowRoot);
+ rowCalculateMinSize(RowRoot);
+ rowEqualize(RowRoot);
+ if (RowRoot) return RowRoot->r.bottom;
+ return 0;
+}
+void cppCalculateRowItemsPos(ROWCELL *RowRoot, int width)
+{
+ rowSizeWithReposition(RowRoot, width);
+}
+
+// rowAddCell
+// Âûäåëÿåò íåîáõîäèìîå êîë-âî äèí. ïàìÿòè äëÿ ñòðóêòóðû ROWCELL
+// è ñâÿçûâàåò åå ñ äåðåâîì îïèñàíèÿ êîíòàêòà
+// link - ïîëå child èëè next, ðîäèòåëüñêîé ñòðóêòóðû ROWCELL
+// cont - òèï êîíòåéíåðà: ñòðîêà, ñòîëáåö èëè êîðíåâîé óçåë
+//
+//
+const ROWCELL * rowAddCell(ROWCELL* &link, int cont)
+{
+ link = (ROWCELL*)malloc(sizeof(ROWCELL));
+ ZeroMemory(link, sizeof(ROWCELL));
+ link->cont = cont;
+ return link;
+}
+
+// rowDeleteTree
+// Îñâîáîæäàåò ïàìÿòü çàíÿòóþ äåðåâîì îïèñàíèÿ êîíòàêòà
+// cell - àäðåñ êîðíåâîãî óçëà äåðåâà îïèñàíèÿ êîíòàêòà
+//
+//
+void rowDeleteTree(ROWCELL* cell)
+{
+ if ( !cell) return;
+ if (cell->child)
+ rowDeleteTree((ROWCELL*)(cell->child));
+ if (cell->next)
+ rowDeleteTree((ROWCELL*)(cell->next));
+ free(cell);
+ cell = NULL;
+ return;
+}
+
+// rowParserGetNextWord
+// Âûáèðàåò èç ïîòîêà äàííûõ (ñåé÷àñ ôàéëîâîãî) î÷åðåäíîå ñëîâî.
+// Ñëîâîì ñ÷èòàåòñÿ ïîñëåäîâàòåëüíîñòü ñèìâîëîâ, îãðàíè÷åííàÿ çíàêàìè: SP, < , >, ;, TAB, CR, LF
+// ñèìâîëû îò ; è äî êîíöà ñòðîêè ñ÷èòàþòñÿ êîììåíòàðèåì.
+// NOTE: Äàííàÿ ðåàëèçàöèÿ íå ñîâñåì ïîäõîäèò äëÿ âêëþ÷åíèÿ åå â ModernCL,
+// à ïî ñåìó, òóò íàäî áóäåò ïåðåäåëûâàòü
+// tbuf - óêàçàòåëü íà áóôåð ñîäåðæàùèé òåêñò øàáëîíà
+// hbuf - óêàçàòåëü áóôåðà
+//
+//
+char * rowParserGetNextWord(char *tbuf, int &hbuf)
+{
+ static char buf[256];
+ char ch;
+
+ int j = -1;
+
+ ZeroMemory(buf, 256);
+
+ while(tbuf[hbuf] != 0)
+ {
+ ch = tbuf[hbuf];
+
+ // Remark found
+ if (ch == ';')
+ {
+ if (j >= 0) return buf;
+
+ while (tbuf[hbuf] != 10 && tbuf[hbuf] != 13) hbuf++;
+ }
+
+ // Tag-bracers found
+ if ( !(ch == '>' && j < 0)) //not single '>' found
+ {
+ if ((ch == '<' || ch == '>') && j >= 0)
+ {
+ if (ch == '>')
+ {
+ if (buf[0] == '/' || buf[0] == '<') buf[++j] = ch;
+ hbuf++;
+ }
+ return buf;
+ }
+
+ if (ch == ' ' || ch == 9 || ch == 10 || ch == 13 || ch == ';' || ch == '>')
+ {
+ if (ch == '>')
+ {
+ buf[++j] = ch;
+ hbuf++;
+ }
+
+ if (j >= 0) return buf; // Word is selected
+ }
+ else
+ buf[++j] = ch;
+ }
+ hbuf++;
+ }
+ return NULL;
+}
+
+// rowParserGetParam
+// èùåò è èíòåðïðåòèðóåò ñëîâà â øàáëîíå, çàêëþ÷åííûå ìåæäó òýãàìè
+// cell - óêàçàòåëü íà òåêóùèé èíòåðïðåòèðóåìûé êîíòåéíåð øàáëîíà
+// tbuf - óêàçàòåëü íà áóôåð ñîäåðæàùèé òåêñò øàáëîíà
+// hbuf - óêàçàòåëü áóôåðà
+//
+//
+void rowParserGetParam(ROWCELL* &cell, char *tbuf, int &hbuf)
+{
+ char * word = rowParserGetNextWord(tbuf, hbuf);
+ int param = 0;
+
+ if ( !_strnicmp(word, "avatar", strlen(word))) param = TC_AVATAR;
+ else if ( !_strnicmp(word, "text1", strlen(word))) param = TC_TEXT1;
+ else if ( !_strnicmp(word, "text2", strlen(word))) param = TC_TEXT2;
+ else if ( !_strnicmp(word, "text3", strlen(word))) param = TC_TEXT3;
+ else if ( !_strnicmp(word, "status", strlen(word))) param = TC_STATUS;
+ else if ( !_strnicmp(word, "extra", strlen(word))) param = TC_EXTRA;
+ else if ( !_strnicmp(word, "extra1", strlen(word))) param = TC_EXTRA1;
+ else if ( !_strnicmp(word, "extra2", strlen(word))) param = TC_EXTRA2;
+ else if ( !_strnicmp(word, "extra3", strlen(word))) param = TC_EXTRA3;
+ else if ( !_strnicmp(word, "extra4", strlen(word))) param = TC_EXTRA4;
+ else if ( !_strnicmp(word, "extra5", strlen(word))) param = TC_EXTRA5;
+ else if ( !_strnicmp(word, "extra6", strlen(word))) param = TC_EXTRA6;
+ else if ( !_strnicmp(word, "extra7", strlen(word))) param = TC_EXTRA7;
+ else if ( !_strnicmp(word, "extra8", strlen(word))) param = TC_EXTRA8;
+ else if ( !_strnicmp(word, "extra9", strlen(word))) param = TC_EXTRA9;
+ else if ( !_strnicmp(word, "time", strlen(word))) param = TC_TIME;
+ else if ( !_strnicmp(word, "space", strlen(word))) param = TC_SPACE;
+ else if ( !_strnicmp(word, "fspace", strlen(word))) param = TC_FIXED;
+
+ else if ( !_strnicmp(word, "left", strlen(word))) param = TC_LEFT;
+ else if ( !_strnicmp(word, "top", strlen(word))) param = TC_TOP;
+ else if ( !_strnicmp(word, "vcenter", strlen(word))) param = TC_VCENTER;
+ else if ( !_strnicmp(word, "hcenter", strlen(word))) param = TC_HCENTER;
+ else if ( !_strnicmp(word, "right", strlen(word))) param = TC_RIGHT;
+ else if ( !_strnicmp(word, "bottom", strlen(word))) param = TC_BOTTOM;
+
+ else if ( !_strnicmp(word, "layer", strlen(word))) cell->layer = TRUE;
+
+ else if ( !_strnicmp(word, "width", strlen(word))) param = TC_WIDTH;
+ else if ( !_strnicmp(word, "height", strlen(word))) param = TC_HEIGHT;
+
+ else
+ {
+ hbuf -= (int)strlen(word);
+ return;
+ }
+
+ if (param>TC_TEXT3 && param != TC_SPACE) cell->hasfixed = 1;
+
+ switch (param)
+ {
+ case TC_TEXT1:
+ case TC_TEXT2:
+ case TC_TEXT3:
+ case TC_SPACE:
+ cell->sizing = 1;
+ case TC_STATUS:
+ case TC_AVATAR:
+ case TC_EXTRA:
+ case TC_EXTRA1:
+ case TC_EXTRA2:
+ case TC_EXTRA3:
+ case TC_EXTRA4:
+ case TC_EXTRA5:
+ case TC_EXTRA6:
+ case TC_EXTRA7:
+ case TC_EXTRA8:
+ case TC_EXTRA9:
+ case TC_TIME:
+ case TC_FIXED:
+
+ cell->type = param;
+ break;
+
+ case TC_HCENTER:
+ case TC_RIGHT:
+ cell->halign = param;
+ break;
+
+ case TC_VCENTER:
+ case TC_BOTTOM:
+ cell->valign = param;
+ break;
+
+ case TC_WIDTH:
+ word = rowParserGetNextWord(tbuf, hbuf);
+ param = atoi(word);
+ cell->w = param;
+ break;
+
+ case TC_HEIGHT:
+ word = rowParserGetNextWord(tbuf, hbuf);
+ param = atoi(word);
+ cell->h = param;
+ }
+
+ rowParserGetParam(cell, tbuf, hbuf);
+ return;
+}
+// rowParse
+// Èùåò â øàáëîíå òåãè < contact>, < tr> è < tc>, è äîáàâëÿåò ñîîòâåòñòâóþùèå óçëû
+// â äåðåâî îïèñàíèÿ êîíòàêòà
+// cell - ïîëå child èëè next ðîäèòåëüñêîãî êîíòåéíåðà
+// parent - óêàçàòåëü íà ðîäèòåëüñêèé êîíòåéíåð
+// tbuf - óêàçàòåëü íà áóôåð ñîäåðæàùèé òåêñò øàáëîíà
+// hbuf - óêàçàòåëü áóôåðà
+// sequence - íóæíî çàäàâàòü 0, ýòî î÷åðåäíîñòü íàõîæäåíèÿ
+//
+BOOL rowParse(ROWCELL* &cell, ROWCELL* parent, char *tbuf, int &hbuf, int &sequence, ROWCELL** RowTabAccess )
+{
+ char * word;
+ word = rowParserGetNextWord(tbuf, hbuf);
+ int cont;
+
+ if (!_strnicmp(word, "<tr", strlen(word)) || !_strnicmp(word, "<tr>", strlen(word))) cont = TC_ROW;
+ else if ( !_strnicmp(word, "<tc", strlen(word)) || !_strnicmp(word, "<tc>", strlen(word))) cont = TC_COL;
+ else if ( !_strnicmp(word, "/>", strlen(word)) ||
+ !_strnicmp(word, "</tr>", strlen(word)) ||
+ !_strnicmp(word, "</tc>", strlen(word))) return TRUE;
+ else return FALSE;
+
+ rowAddCell(cell, cont);
+ rowParserGetParam(cell, tbuf, hbuf);
+ if (cell->type != 0 && cell->type != TC_SPACE && cell->type != TC_FIXED)
+ RowTabAccess[sequence++] = cell;
+
+ if ( !rowParse(cell->child, cell, tbuf, hbuf, sequence,RowTabAccess))
+ return FALSE;
+
+ if ( !parent)
+ {
+ RowTabAccess[sequence] = NULL;
+ return TRUE;
+ }
+
+ if ( !rowParse(cell->next, parent, tbuf, hbuf, sequence,RowTabAccess))
+ return FALSE;
+
+ parent->sizing |= cell->sizing;
+ parent->hasfixed |= cell->hasfixed;
+ return TRUE;
+}
+
+void rowResetEmptyRects(ROWCELL* cell)
+{
+ if ( !cell) return;
+ if (cell->type == 0)
+ {
+ SetRect(&(cell->r),0,0,0,0);
+ cell->full_width = 0;
+ cell->fixed_width = 0;
+ }
+ rowResetEmptyRects(cell->child);
+ rowResetEmptyRects(cell->next);
+}
+
+// rowCalculateMinSize
+// Âû÷èñëåíèå ìèíèìàëüíûõ ðàçìåðîâ êàæäîãî êîíòåéíåðà äåðåâà îïèñàíèÿ êîíòàêòà
+// Ýòà ôó-ÿ ÂÑÅÃÄÀ! äîëæíà âûçûâàòüñÿ íåïîñðåäñòâåííî ïåðåä rowPositioning
+// cell - óêàçàòåëü íà êîðíåâîé óçåë äåðåâà îïèñàíèÿ êîíòàêòà
+// NOTE: Ïåðåä âûçûâîì rowCalculateMinSize íåîáõîäèìî çàïîëíèòü ïîëÿ w è h ñòðóêòóðû RowTA, äëÿ êàæäîãî ýëåìåíòà
+//
+void rowCalculateMinSize(ROWCELL* cell)
+{
+ ROWCELL* curchild = NULL;
+ int w = 0,h = 0;
+ int wl = 0, hl = 0;
+ int fullWidth = 0;
+ if ( !cell) return;
+
+ cell->r.left = 0;
+ cell->r.top = 0;
+
+ if (cell->type < TC_TEXT1 || cell->type > TC_TEXT3 && cell->type != TC_SPACE)
+ cell->r.right = cell->w;
+ else
+ cell->r.right = 0;
+
+ cell->r.bottom = cell->h;
+
+ rowCalculateMinSize(cell->child);
+ rowCalculateMinSize(cell->next);
+
+ if ( !(curchild = cell->child)) return;
+
+ if (cell->cont == TC_ROW)
+ {
+ do
+ {
+ h = max(h, curchild->r.bottom);
+
+ if (curchild->layer)
+ {
+ //w = max(w, curchild->r.right);
+ wl += curchild->r.right;
+ fullWidth = max(fullWidth,max(curchild->full_width,curchild->w));
+ }
+ else
+ {
+ w += curchild->r.right;
+ fullWidth += max(curchild->full_width,curchild->w);
+ }
+ }
+ while (curchild = curchild->next);
+ }
+
+ if (cell->cont == TC_COL)
+ {
+ while (curchild)
+ {
+ w = max(w, curchild->r.right);
+ fullWidth = max(fullWidth,max(curchild->full_width,curchild->w));
+
+ if (curchild->layer)
+ {
+ hl = curchild->r.bottom;
+ // h = max(h, curchild->r.bottom);
+ }
+ else
+ h += curchild->r.bottom;
+
+ curchild = curchild->next;
+ }
+ }
+
+ cell->r.right = max(max(w, cell->r.right),wl);
+ cell->r.bottom = max(max(h, cell->r.bottom),hl);
+ cell->full_width = max(fullWidth,cell->full_width);
+ cell->fixed_width = max(cell->fixed_width,cell->r.right);
+ return;
+}
+
+// void rowEqualise(ROWCELL* cell)
+//
+// Óðàâíèâàåò âûñîòû äåòåé âíóòðè ñòðîê, è øèðèíû äåòåé âíóòðè ñòîáöîâ
+// cell - óêàçàòåëü íà êîðíåâîé óçåë äåðåâà îïèñàíèÿ êîíòàêòà
+//
+void rowEqualize(ROWCELL* cell)
+{
+ ROWCELL* curchild = NULL;
+ if ( !cell) return;
+ rowEqualize(cell->child);
+ rowEqualize(cell->next);
+
+ if ( !(curchild = cell->child)) return;
+
+ if (cell->cont == TC_ROW)
+ {
+ do
+ {
+ if (curchild->layer) continue;
+ curchild->r.bottom = cell->r.bottom;
+ }
+ while (curchild = curchild->next);
+ }
+
+ if (cell->cont == TC_COL)
+ {
+ do
+ {
+ if (curchild->layer) continue;
+ curchild->r.right = cell->r.right;
+ }
+ while (curchild = curchild->next);
+ }
+
+
+ //rowEqualize(cell->child);
+ //rowEqualize(cell->next);
+}
+
+// void rowPlacing(pttCell cell, pttCell parent)
+//
+// Ïîçèöèîíèðóåò ýëåìåíò ñòðîêè êîíòàêòà â åãî êîíòåéíåðå
+// cell - óêàçàòåëü íà ïëàâàþùèé êîíòåéíåð
+//
+void rowPlacing(pROWCELL cell)
+{
+ if (cell->type == 0) return;
+
+ switch(cell->type)
+ {
+ case TC_TEXT1:
+ case TC_TEXT2:
+ case TC_TEXT3:
+ case TC_SPACE:
+ cell->r.right += cell->r.left;
+ break;
+ default:
+ {
+ switch(cell->halign)
+ {
+ case TC_LEFT:
+ break;
+ case TC_HCENTER:
+ cell->r.left += (cell->r.right - cell->w)/2;
+ break;
+ case TC_RIGHT:
+ cell->r.left += cell->r.right - cell->w;
+ }
+ cell->r.right = cell->r.left + cell->w;
+ }
+ }
+
+ switch(cell->valign)
+ {
+ case TC_TOP:
+ break;
+ case TC_VCENTER:
+ cell->r.top += (cell->r.bottom - cell->h)/2;
+ break;
+ case TC_BOTTOM:
+ cell->r.top += cell->r.bottom - cell->h;
+ }
+ cell->r.bottom = cell->r.top + cell->h;
+}
+
+// void ttTLProc(pROWCELL cell, pROWCELL parent)
+//
+// Ïîçèöèîíèðóåò ïëàâàþùèé êîíòåéíåð, âíóòðè ðîäèòåëüñêîãî
+// cell - óêàçàòåëü íà ïëàâàþùèé êîíòåéíåð
+// parent - óêàçàòåëü íà ðîäèòåëüñêèé êîíòåéíåð
+//
+void rowLayerProc(pROWCELL cell, pROWCELL parent)
+{
+ if (cell->sizing)
+ {
+ cell->r.left = parent->r.left;
+ //cell->r.right += cell->r.left;
+ }
+ else
+ {
+ switch(cell->halign)
+ {
+ case TC_LEFT:
+ cell->r.left = parent->r.left;
+ break;
+ case TC_HCENTER:
+ cell->r.left = parent->r.left + (parent->r.right - cell->r.right)/2;
+ break;
+ case TC_RIGHT:
+ cell->r.left = parent->r.left + parent->r.right - cell->r.right;
+ }
+ }
+
+ switch(cell->valign)
+ {
+ case TC_TOP:
+ cell->r.top = parent->r.top;
+ break;
+ case TC_VCENTER:
+ cell->r.top = parent->r.top + (parent->r.bottom - cell->r.bottom)/2;
+ break;
+ case TC_BOTTOM:
+ cell->r.top = parent->r.top + parent->r.bottom - cell->r.bottom;
+ break;
+ }
+}
+
+// void rowPositioning(pROWCELL cell, int &dist)
+//
+// Âû÷èñëÿåò ïðÿìîóãîëüíèêè ýëåìåíòîâ êîíòàêòà, ó÷èòûâàÿ âûðàâíèâàíèå â êîíòåéíåðå
+// cell - óêàçàòåëü íà êîðíåâîé óçåë äåðåâà îïèñàíèÿ êîíòàêòà
+// dist - íîâàÿ øèðèíà êîíòàêòà
+//
+void rowPositioning(pROWCELL cell, int &dist)
+{
+ ROWCELL* curchild = NULL;
+
+ int x = cell->r.left;
+ int y = cell->r.top;
+
+ int h = cell->r.bottom;
+ int w = dist;
+
+ int r = 0;
+ int size = 0;
+ int cw = 0;
+ int fixedsized = 0;
+ int autosized = 0;
+ int dummy = 0;
+
+ // Êîðððåêòèðîâêà íàçíà÷àåìîé øèðèíû dist
+ if (w < cell->r.right && (cell->type < TC_TEXT1 || cell->type > TC_TEXT3 && cell->type != TC_SPACE) || !cell->sizing)
+ dist = w = cell->r.right;
+
+ cell->r.right = dist;
+ dummy = dist;
+ if ( !(curchild = cell->child))
+ {
+ rowPlacing(cell);
+ return;
+ }
+
+ // Ïîçèöèîíèðîâàíèå êîíòåéíåðîâ â ñòðîêå
+ if (cell->cont == TC_ROW)
+ {
+ fixedsized = cell->fixed_width;
+ while (curchild)
+ {
+ // Êîíòåéíåðû layer íå äîëæíû âëèÿòü íà ïîçèöèîíèðîâàíèå êîíòåéíåðîâ tc
+ if (curchild->layer)
+ {
+ curchild = curchild->next;
+ continue;
+ }
+
+ cw += curchild->r.right;
+
+ if (curchild->sizing)
+ {
+ autosized += max(curchild->w,curchild->full_width);
+ r++;
+ }
+ else
+ size += curchild->r.right;
+
+ curchild = curchild->next;
+ }
+
+ w -= size;
+ fixedsized -= size;
+
+ if (r == 0)
+ {
+ switch(cell->halign)
+ {
+ case TC_HCENTER:
+ x += (dist - cw)/2;// - 1;
+ break;
+ case TC_RIGHT:
+ x += dist - cw;
+ break;
+ }
+ }
+
+
+ curchild = cell->child;
+
+ size = 0;
+ while(curchild)
+ {
+ if (curchild->layer)
+ {
+ //int dummy = 0;
+ rowLayerProc(curchild, cell);
+ rowPositioning(curchild, dummy);
+ }
+ else
+ {
+ curchild->r.top = cell->r.top;
+ curchild->r.left = x;
+
+
+ w -= size;
+ if (curchild->sizing)
+ {
+ if ((0&!curchild->fitwidth) || r>1) //ïîêà îòêëþ÷åíî -ïðîáëåìû ñ âûðàâíèâàíèåì
+ {
+ if (curchild->hasfixed)
+ fixedsized -= curchild->fixed_width;
+ switch (cell->halign)
+ {
+ case TC_RIGHT:
+ size = (w-fixedsized)-(autosized-max(curchild->full_width,curchild->w));
+ break;
+ case TC_LEFT:
+ size = min(w-fixedsized,max(curchild->full_width,curchild->w));
+ break;
+ case TC_HCENTER:
+ if (autosized) {size = max(curchild->full_width,curchild->w)*w/autosized; break;}
+ default:
+ size = w / r;
+ }
+ autosized -= (max(curchild->full_width,curchild->w));
+ if (autosized < 0) autosized = 0;
+ if (size < 0) size = 0;
+ }
+ else size = w;
+ /* ïîêà îòêëþ÷åíî èáî ïàðàìåòð âëèÿåò íà âûðàâíèâàíèå âêëþ÷àåòñÿ ïî ëåâîìó êðàþ
+ if (0 && !curchild->fitwidth)
+ if (size>max(curchild->full_width,curchild->w))
+ size = max(curchild->full_width,curchild->w);
+ */
+ r--;
+ }
+ else
+ size = curchild->r.right;
+
+ rowPositioning(curchild, size);
+ x += size;
+
+ if ( !curchild->sizing)
+ size = 0;
+ }
+
+ curchild = curchild->next;
+ }
+ }
+
+ // Ïîçèöèîíèðîâàíèå êîíòåéíåðîâ â ñòîëáöå
+ if (cell->cont == TC_COL)
+ {
+ while (curchild)
+ {
+ // Êîíòåéíåðû layer íå äîëæíû âëèÿòü íà ïîçèöèîíèðîâàíèå êîíòåéíåðîâ tr
+ if (curchild->layer)
+ {
+ curchild = curchild->next;
+ continue;
+ }
+
+ size += curchild->r.bottom;
+ curchild = curchild->next;
+ }
+
+ if (h > size)
+ {
+ switch(cell->valign)
+ {
+ case TC_VCENTER:
+ y += (h - size) / 2;
+ break;
+ case TC_BOTTOM:
+ y += (h - size);
+ break;
+ }
+ }
+
+ curchild = cell->child;
+ while(curchild)
+ {
+ if (curchild->layer)
+ {
+ rowLayerProc(curchild, cell);
+ rowPositioning(curchild, dummy);
+ }
+ else
+ {
+ curchild->r.top = y;
+ y += curchild->r.bottom;
+
+ curchild->r.left = cell->r.left;
+ curchild->r.right = dist;
+
+ rowPositioning(curchild, size);
+
+ }
+
+ curchild = curchild->next;
+ }
+ }
+
+ rowPlacing(cell);
+
+}
+
+// void rowSizeWithReposition(ROWCELL* &root, int width)
+//
+// Ïðîèçâîäèò ïðîñ÷åò è ïîçèöèîíèðîâàíèå ýëåìåíòîâ êîòàêòà
+// Ïåðåä âûçîâîì íåîáõîäèìî çàïîëíèòü ñòðóêòóðó RowTA
+//
+void rowSizeWithReposition(ROWCELL* &root, int width)
+{
+ root->h = 0;
+ root->w = 0;
+ rowCalculateMinSize(root);
+ rowEqualize(root);
+ rowPositioning(root, width);
+ root->h = root->r.bottom;
+ root->w = root->r.right;
+}
+
+#undef _CPPCODE
diff --git a/plugins/Clist_modern/src/modern_rowheight_funcs.cpp b/plugins/Clist_modern/src/modern_rowheight_funcs.cpp
new file mode 100644
index 0000000000..238962baa2
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_rowheight_funcs.cpp
@@ -0,0 +1,796 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+
+Created by Pescuma, modified by Artem Shpynov
+
+*/
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_rowheight_funcs.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_row.h"
+#include "hdr/modern_clcpaint.h"
+
+int g_mutex_nCalcRowHeightLock = 0;
+int mod_CalcRowHeight_worker(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item);
+void RowHeights_CalcRowHeights_Worker(struct ClcData *dat, HWND hwnd);
+int RowHeights_GetRowHeight_worker(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item);
+
+/*
+*
+*/
+
+ROWCELL * gl_RowTabAccess[TC_ELEMENTSCOUNT+1] = {0}; // Ìàññèâ, ÷åðåç êîòîðûé îñóùåñòâëÿåòñÿ äîñòóï ê ýëåìåíòàì êîíòàêòà.
+ROWCELL * gl_RowRoot;
+
+void FreeRowCell ()
+{
+ if (gl_RowRoot)
+ cppDeleteTree(gl_RowRoot);
+}
+
+void RowHeight_InitModernRow()
+{
+ gl_RowRoot = cppInitModernRow(gl_RowTabAccess);
+ return;
+}
+
+SIZE GetAvatarSize(int imageWidth, int imageHeight, int maxWidth, int maxHeight)
+{
+ float scalefactor = 0;
+ SIZE sz = {0};
+ if (imageWidth == 0 || imageHeight == 0) return sz;
+ if (maxWidth == 0) maxWidth = maxHeight;
+ scalefactor = min((float)maxWidth/imageWidth,(float)maxHeight/imageHeight);
+ sz.cx = (LONG)(imageWidth*scalefactor);
+ sz.cy = (LONG)(imageHeight*scalefactor);
+ return sz;
+}
+
+int RowHeight_CalcRowHeight(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item)
+{
+ int res;
+ if (MirandaExiting()) return 0;
+ g_mutex_nCalcRowHeightLock++;
+ res = mod_CalcRowHeight_worker(dat,hwnd,contact,item);
+ g_mutex_nCalcRowHeightLock--;
+ return res;
+}
+int mod_CalcRowHeight_worker(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item)
+{
+ BYTE i=0;
+ int res = 0;
+ int height = 0;
+ displayNameCacheEntry * pdnce;
+ BOOL hasAvatar = FALSE;
+ DWORD style;
+ style = GetWindowLongPtr(hwnd,GWL_STYLE);
+ pdnce = (displayNameCacheEntry*)pcli->pfnGetCacheEntry(contact->hContact);
+ if ( !RowHeights_Alloc(dat, item + 1))
+ return -1;
+ if ( !pcli->hwndContactTree) return 0;
+ //if ( !gl_RowRoot) RowHeight_InitModernRow();
+ if (dat->hWnd != pcli->hwndContactTree || !gl_RowRoot || contact->type == CLCIT_GROUP)
+ {
+ int tmp = 0;
+ tmp = dat->fontModernInfo[g_clcPainter.GetBasicFontID(contact)].fontHeight;
+ if (dat->text_replace_smileys && dat->first_line_draw_smileys && !dat->text_resize_smileys)
+ tmp = max(tmp, contact->ssText.iMaxSmileyHeight);
+ if (contact->type == CLCIT_GROUP)
+ {
+ char * szCounts = pcli->pfnGetGroupCountsText(dat, contact);
+ // Has the count?
+ if (szCounts && szCounts[0])
+ tmp = max(tmp,dat->fontModernInfo[contact->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS].fontHeight);
+ }
+ tmp = max(tmp, ICON_HEIGHT);
+ tmp = max(tmp,dat->row_min_heigh);
+ tmp += dat->row_border*2;
+ if (contact->type == CLCIT_GROUP &&
+ contact->group->parent->groupId == 0 &&
+ contact->group->parent->cl.items[0] != contact)
+ tmp += dat->row_before_group_space;
+ if (item != -1) dat->row_heights[item] = tmp;
+ return tmp;
+ }
+ hasAvatar = (dat->use_avatar_service && contact->avatar_data != NULL) || (!dat->use_avatar_service && contact->avatar_pos != AVATAR_POS_DONT_HAVE);
+ while (gl_RowTabAccess[i] != NULL)
+ {
+ if (gl_RowTabAccess[i]->type != TC_SPACE)
+ {
+ gl_RowTabAccess[i]->h = 0;
+ gl_RowTabAccess[i]->w = 0;
+ SetRect(&(gl_RowTabAccess[i]->r),0,0,0,0);
+ switch (gl_RowTabAccess[i]->type)
+ {
+ case TC_TEXT1:
+ {
+ int tmp = 0;
+ tmp = dat->fontModernInfo[g_clcPainter.GetBasicFontID(contact)].fontHeight;
+ if (dat->text_replace_smileys && dat->first_line_draw_smileys && !dat->text_resize_smileys)
+ tmp = max(tmp, contact->ssText.iMaxSmileyHeight);
+ if (item == -1)
+ {
+ //calculate text width here
+ SIZE size = {0};
+ RECT dummyRect = {0,0,1024,tmp};
+ HDC hdc = CreateCompatibleDC(NULL);
+ g_clcPainter.ChangeToFont(hdc,dat,g_clcPainter.GetBasicFontID(contact),NULL);
+ g_clcPainter.GetTextSize(&size,hdc,dummyRect,contact->szText,contact->ssText.plText,0, dat->text_resize_smileys ? 0 : contact->ssText.iMaxSmileyHeight);
+ if (contact->type == CLCIT_GROUP)
+ {
+ char * szCounts = pcli->pfnGetGroupCountsText(dat, contact);
+ if (szCounts && strlen(szCounts)>0)
+ {
+ RECT count_rc = {0};
+ // calc width and height
+ g_clcPainter.ChangeToFont(hdc,dat,contact->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS,NULL);
+ ske_DrawText(hdc,_T(" "),1,&count_rc,DT_CALCRECT | DT_NOPREFIX);
+ size.cx += count_rc.right-count_rc.left;
+ count_rc.right = 0;
+ count_rc.left = 0;
+ ske_DrawTextA(hdc,szCounts,lstrlenA(szCounts),&count_rc,DT_CALCRECT);
+ size.cx += count_rc.right-count_rc.left;
+ tmp = max(tmp,count_rc.bottom-count_rc.top);
+ }
+ }
+ gl_RowTabAccess[i]->w = size.cx;
+ SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
+ ske_ResetTextEffect(hdc);
+ mod_DeleteDC(hdc);
+ }
+ gl_RowTabAccess[i]->h = tmp;
+
+ break;
+ }
+ case TC_TEXT2:
+ {
+ int tmp = 0;
+ HANDLE hContact = pdnce->hContact;
+ if (dat->second_line_show && pdnce->szSecondLineText && pdnce->szSecondLineText[0] )
+ {
+ tmp = dat->fontModernInfo[FONTID_SECONDLINE].fontHeight;
+ if (dat->text_replace_smileys && dat->second_line_draw_smileys && !dat->text_resize_smileys)
+ tmp = max(tmp, pdnce->ssSecondLine.iMaxSmileyHeight);
+ if (item == -1)
+ {
+ //calculate text width here
+
+ SIZE size = {0};
+ RECT dummyRect = {0,0,1024,tmp};
+ HDC hdc = CreateCompatibleDC(NULL);
+ g_clcPainter.ChangeToFont(hdc,dat,FONTID_SECONDLINE,NULL);
+ g_clcPainter.GetTextSize(&size,hdc,dummyRect,pdnce->szSecondLineText,pdnce->ssSecondLine.plText,0, dat->text_resize_smileys ? 0 : pdnce->ssSecondLine.iMaxSmileyHeight);
+ gl_RowTabAccess[i]->w = size.cx;
+ SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
+ ske_ResetTextEffect(hdc);
+ mod_DeleteDC(hdc);
+ }
+ }
+ gl_RowTabAccess[i]->h = tmp;
+ break;
+ }
+ case TC_TEXT3:
+ {
+ int tmp = 0;
+ HANDLE hContact = pdnce->hContact;
+ if (dat->third_line_show && pdnce->szThirdLineText && pdnce->szThirdLineText[0])
+ {
+ tmp = dat->fontModernInfo[FONTID_THIRDLINE].fontHeight;
+ if (dat->text_replace_smileys && dat->third_line_draw_smileys && !dat->text_resize_smileys)
+ tmp = max(tmp, pdnce->ssThirdLine.iMaxSmileyHeight);
+ if (item == -1)
+ {
+ //calculate text width here
+ SIZE size = {0};
+ RECT dummyRect = {0,0,1024,tmp};
+ HDC hdc = CreateCompatibleDC(NULL);
+ g_clcPainter.ChangeToFont(hdc,dat,FONTID_THIRDLINE,NULL);
+ g_clcPainter.GetTextSize(&size,hdc,dummyRect,pdnce->szThirdLineText,pdnce->ssThirdLine.plText,0, dat->text_resize_smileys ? 0 : pdnce->ssThirdLine.iMaxSmileyHeight);
+ gl_RowTabAccess[i]->w = size.cx;
+ SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
+ ske_ResetTextEffect(hdc);
+ mod_DeleteDC(hdc);
+ }
+ }
+ gl_RowTabAccess[i]->h = tmp;
+ break;
+ }
+ case TC_STATUS:
+ {
+ if (
+ (contact->type == CLCIT_GROUP && !dat->row_hide_group_icon) ||
+ ( contact->type == CLCIT_CONTACT && contact->iImage != -1 &&
+ !(dat->icon_hide_on_avatar && dat->avatars_show && (hasAvatar || (!hasAvatar && dat->icon_draw_on_avatar_space && contact->iImage != -1)) && !contact->image_is_special))
+ )
+ {
+ gl_RowTabAccess[i]->h = ICON_HEIGHT;
+ gl_RowTabAccess[i]->w = ICON_HEIGHT;
+ }
+ break;
+ }
+ case TC_AVATAR:
+ {
+ if (dat->avatars_show &&
+ contact->type == CLCIT_CONTACT &&
+ (hasAvatar || (dat->icon_hide_on_avatar && dat->icon_draw_on_avatar_space && contact->iImage != -1) )
+ )
+ {
+ SIZE sz = {0};
+ int iW = 0, iH = 0;
+ if (dat->use_avatar_service)
+ {
+ if (contact->avatar_data)
+ {
+ iH = contact->avatar_data->bmHeight;
+ iW = contact->avatar_data->bmWidth;
+ }
+ }
+ else if (dat->avatar_cache.nodes)
+ {
+ iW = dat->avatar_cache.nodes[contact->avatar_pos].width;
+ iH = dat->avatar_cache.nodes[contact->avatar_pos].height;
+ }
+ sz = GetAvatarSize(iW,iH,dat->avatars_maxwidth_size,dat->avatars_maxheight_size);
+ if ((sz.cx == 0 || sz.cy == 0) && dat->icon_hide_on_avatar && dat->icon_draw_on_avatar_space && contact->iImage != -1)
+ { sz.cx = ICON_HEIGHT; sz.cy = ICON_HEIGHT; }
+
+ gl_RowTabAccess[i]->h = sz.cy;
+ gl_RowTabAccess[i]->w = sz.cx;
+ }
+
+ break;
+ }
+ case TC_EXTRA:
+ {
+ // Draw extra icons
+
+ if (contact->type == CLCIT_CONTACT &&
+ (!contact->isSubcontact || db_get_b(NULL,"CLC","MetaHideExtra",SETTING_METAHIDEEXTRA_DEFAULT) == 0 && dat->extraColumnsCount > 0))
+ {
+ BOOL hasExtra = FALSE;
+ int k;
+ int width = 0;
+ for (k = 0; k < dat->extraColumnsCount; k++)
+ if (contact->iExtraImage[k] != 0xFF || contact->iWideExtraImage[k] != 0xFFFF || !dat->MetaIgnoreEmptyExtra)
+ {
+ hasExtra = TRUE;
+ if (item != -1) break;
+ width += (width>0)?dat->extraColumnSpacing:(dat->extraColumnSpacing-2);
+ }
+ if (hasExtra)
+ {
+ gl_RowTabAccess[i]->h = ICON_HEIGHT;
+ gl_RowTabAccess[i]->w = width;
+ }
+ }
+ break;
+ }
+ case TC_EXTRA1:
+ case TC_EXTRA2:
+ case TC_EXTRA3:
+ case TC_EXTRA4:
+ case TC_EXTRA5:
+ case TC_EXTRA6:
+ case TC_EXTRA7:
+ case TC_EXTRA8:
+ case TC_EXTRA9:
+ {
+ if (contact->type == CLCIT_CONTACT &&
+ (!contact->isSubcontact || db_get_b(NULL,"CLC","MetaHideExtra",SETTING_METAHIDEEXTRA_DEFAULT) == 0 && dat->extraColumnsCount > 0))
+ {
+ int eNum = gl_RowTabAccess[i]->type-TC_EXTRA1;
+ if (eNum < dat->extraColumnsCount)
+ if (contact->iExtraImage[eNum] != 255 || contact->iWideExtraImage[eNum] != 0xFFFF || !dat->MetaIgnoreEmptyExtra)
+ {
+ gl_RowTabAccess[i]->h = ICON_HEIGHT;
+ gl_RowTabAccess[i]->w = ICON_HEIGHT;
+ }
+ }
+ break;
+ }
+ case TC_TIME:
+ {
+ if (contact->type == CLCIT_CONTACT && dat->contact_time_show && pdnce->hTimeZone)
+ {
+ gl_RowTabAccess[i]->h = dat->fontModernInfo[FONTID_CONTACT_TIME].fontHeight;
+ if (item == -1)
+ {
+ TCHAR szResult[80];
+
+ if ( !tmi.printDateTime(pdnce->hTimeZone, _T("t"), szResult, SIZEOF(szResult), 0))
+ {
+ SIZE text_size = {0};
+ RECT rc = {0};
+ // Select font
+ HDC hdc = CreateCompatibleDC(NULL);
+ g_clcPainter.ChangeToFont(hdc,dat,FONTID_CONTACT_TIME,NULL);
+
+ // Get text size
+ text_size.cy = ske_DrawText(hdc, szResult, lstrlen(szResult), &rc, DT_CALCRECT | DT_NOPREFIX | DT_SINGLELINE);
+ SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
+ ske_ResetTextEffect(hdc);
+ mod_DeleteDC(hdc);
+ text_size.cx = rc.right - rc.left;
+ gl_RowTabAccess[i]->w = text_size.cx;
+
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ i++;
+ }
+
+ height = cppCalculateRowHeight(gl_RowRoot);
+ height += dat->row_border*2;
+ height = max(height,dat->row_min_heigh);
+ if (item != -1) dat->row_heights[item] = height;
+ return height;
+}
+
+
+
+
+/*
+*
+*/
+
+
+
+
+BOOL RowHeights_Initialize(struct ClcData *dat)
+{
+ dat->max_row_height = 0;
+ dat->row_heights_size = 0;
+ dat->row_heights_allocated = 0;
+ dat->row_heights = NULL;
+
+ return TRUE;
+}
+
+void RowHeights_Free(struct ClcData *dat)
+{
+ if (dat->row_heights != NULL)
+ {
+ free(dat->row_heights);
+ dat->row_heights = NULL;
+ }
+
+ dat->row_heights_allocated = 0;
+ dat->row_heights_size = 0;
+}
+
+void RowHeights_Clear(struct ClcData *dat)
+{
+ dat->row_heights_size = 0;
+}
+
+
+BOOL RowHeights_Alloc(struct ClcData *dat, int size)
+{
+ if (size > dat->row_heights_size)
+ {
+ if (size > dat->row_heights_allocated)
+ {
+ int size_grow = size;
+
+ size_grow += 100 - (size_grow % 100);
+
+ if (dat->row_heights != NULL)
+ {
+ int *tmp = (int *) realloc((void *)dat->row_heights, sizeof(int) * size_grow);
+
+ if (tmp == NULL)
+ {
+ TRACE("Out of memory: realloc returned NULL (RowHeights_Alloc)");
+ RowHeights_Free(dat);
+ return FALSE;
+ }
+
+ dat->row_heights = tmp;
+ memset(dat->row_heights+(dat->row_heights_allocated),0,sizeof(int) * (size_grow-dat->row_heights_allocated));
+ }
+ else
+ {
+ dat->row_heights = (int *) malloc(sizeof(int) * size_grow);
+
+ if (dat->row_heights == NULL)
+ {
+ TRACE("Out of memory: alloc returned NULL (RowHeights_Alloc)");
+ RowHeights_Free(dat);
+ return FALSE;
+ }
+ memset(dat->row_heights,0,sizeof(int) * size_grow);
+ }
+
+ dat->row_heights_allocated = size_grow;
+ }
+
+ dat->row_heights_size = size;
+ }
+
+ return TRUE;
+}
+
+
+// Calc and store max row height
+int RowHeights_GetMaxRowHeight(struct ClcData *dat, HWND hwnd)
+{
+ int max_height = 0, i, tmp;
+ DWORD style = GetWindowLongPtr(hwnd,GWL_STYLE);
+
+ if ( !dat->text_ignore_size_for_row_height)
+ {
+ int contact_fonts[] = {FONTID_CONTACTS, FONTID_INVIS, FONTID_OFFLINE, FONTID_NOTONLIST, FONTID_OFFINVIS,
+ FONTID_AWAY,FONTID_DND, FONTID_NA, FONTID_OCCUPIED, FONTID_CHAT, FONTID_INVISIBLE,
+ FONTID_PHONE, FONTID_LUNCH};
+ int other_fonts[] = {FONTID_OPENGROUPS, FONTID_OPENGROUPCOUNTS,FONTID_CLOSEDGROUPS, FONTID_CLOSEDGROUPCOUNTS, FONTID_DIVIDERS, FONTID_CONTACT_TIME};
+
+ // Get contact font size
+ tmp = 0;
+ for (i=0 ; i < MAX_REGS(contact_fonts) ; i++)
+ {
+ if (tmp < dat->fontModernInfo[contact_fonts[i]].fontHeight)
+ tmp = dat->fontModernInfo[contact_fonts[i]].fontHeight;
+ }
+ if (dat->text_replace_smileys && dat->first_line_draw_smileys && !dat->text_resize_smileys)
+ {
+ tmp = max(tmp, dat->text_smiley_height);
+ }
+ max_height += tmp;
+
+ if (dat->second_line_show)
+ {
+ tmp = dat->fontModernInfo[FONTID_SECONDLINE].fontHeight;
+ if (dat->text_replace_smileys && dat->second_line_draw_smileys && !dat->text_resize_smileys)
+ {
+ tmp = max(tmp, dat->text_smiley_height);
+ }
+ max_height += dat->second_line_top_space + tmp;
+ }
+
+ if (dat->third_line_show)
+ {
+ tmp = dat->fontModernInfo[FONTID_THIRDLINE].fontHeight;
+ if (dat->text_replace_smileys && dat->third_line_draw_smileys && !dat->text_resize_smileys)
+ {
+ tmp = max(tmp, dat->text_smiley_height);
+ }
+ max_height += dat->third_line_top_space + tmp;
+ }
+
+ // Get other font sizes
+ for (i=0 ; i < MAX_REGS(other_fonts) ; i++)
+ {
+ if (max_height < dat->fontModernInfo[other_fonts[i]].fontHeight)
+ max_height = dat->fontModernInfo[other_fonts[i]].fontHeight;
+ }
+ }
+
+ // Avatar size
+ if (dat->avatars_show && !dat->avatars_ignore_size_for_row_height)
+ {
+ max_height = max(max_height, dat->avatars_maxheight_size);
+ }
+
+ // Checkbox size
+ if (style&CLS_CHECKBOXES || style&CLS_GROUPCHECKBOXES)
+ {
+ max_height = max(max_height, dat->checkboxSize);
+ }
+
+ // Icon size
+ if ( !dat->icon_ignore_size_for_row_height)
+ {
+ max_height = max(max_height, ICON_HEIGHT);
+ }
+
+ max_height += 2 * dat->row_border;
+
+ // Min size
+ max_height = max(max_height, dat->row_min_heigh);
+
+ dat->max_row_height = max_height;
+
+ return max_height;
+}
+
+
+// Calc and store row height for all items in the list
+void RowHeights_CalcRowHeights(struct ClcData *dat, HWND hwnd)
+{
+ if (MirandaExiting()) return;
+ g_mutex_nCalcRowHeightLock++;
+ RowHeights_CalcRowHeights_Worker(dat, hwnd);
+ g_mutex_nCalcRowHeightLock--;
+}
+
+void RowHeights_CalcRowHeights_Worker(struct ClcData *dat, HWND hwnd)
+{
+ int indent, subident, subindex, line_num;
+ struct ClcContact *Drawing;
+ struct ClcGroup *group;
+
+ if (MirandaExiting()) return;
+
+ // Draw lines
+ group = &dat->list;
+ group->scanIndex = 0;
+ indent = 0;
+ subindex = -1;
+ line_num = -1;
+
+ RowHeights_Clear(dat);
+
+ while(TRUE)
+ {
+ if (subindex == -1)
+ {
+ if (group->scanIndex == group->cl.count)
+ {
+ group = group->parent;
+ indent--;
+ if (group == NULL) break; // Finished list
+ group->scanIndex++;
+ continue;
+ }
+
+ // Get item to draw
+ Drawing = group->cl.items[group->scanIndex];
+ subident = 0;
+ }
+ else
+ {
+ // Get item to draw
+ Drawing = &(group->cl.items[group->scanIndex]->subcontacts[subindex]);
+ subident = dat->subIndent;
+ }
+
+ line_num++;
+
+ // Calc row height
+ if ( !gl_RowRoot) RowHeights_GetRowHeight(dat, hwnd, Drawing, line_num);
+ else RowHeight_CalcRowHeight(dat, hwnd, Drawing, line_num);
+
+ //increment by subcontacts
+ if (group->cl.items[group->scanIndex]->subcontacts != NULL && group->cl.items[group->scanIndex]->type != CLCIT_GROUP)
+ {
+ if (group->cl.items[group->scanIndex]->SubExpanded && dat->expandMeta)
+ {
+ if (subindex < group->cl.items[group->scanIndex]->SubAllocated-1)
+ {
+ subindex++;
+ }
+ else
+ {
+ subindex = -1;
+ }
+ }
+ }
+
+ if (subindex == -1)
+ {
+ 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;
+ subindex = -1;
+ continue;
+ }
+ group->scanIndex++;
+ }
+ }
+
+}
+
+
+// Calc and store row height
+int RowHeights_GetRowHeight(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item)
+{
+ int res;
+ if (MirandaExiting()) return 0;
+ g_mutex_nCalcRowHeightLock++;
+ res = RowHeights_GetRowHeight_worker(dat, hwnd, contact, item);
+ g_mutex_nCalcRowHeightLock--;
+ return res;
+}
+
+int RowHeights_GetRowHeight_worker(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item)
+{
+ int height = 0;
+ if (MirandaExiting()) return 0;
+ if (gl_RowRoot)
+ return RowHeight_CalcRowHeight(dat, hwnd, contact, item);
+ else
+ {
+ displayNameCacheEntry *pdnce = (displayNameCacheEntry *)pcli->pfnGetCacheEntry(contact->hContact);
+ DWORD style = GetWindowLongPtr(hwnd,GWL_STYLE);
+ //TODO replace futher code with new rowheight definition
+ int tmp;
+ BOOL selected = ((item == dat->selection) && (dat->hwndRenameEdit != NULL || dat->showSelAlways || dat->exStyle&CLS_EX_SHOWSELALWAYS || g_clcPainter.IsForegroundWindow(hwnd)) && contact->type != CLCIT_DIVIDER);
+ BOOL hottrack = ((item == dat->iHotTrack) && (dat->hwndRenameEdit != NULL || dat->showSelAlways || dat->exStyle&CLS_EX_SHOWSELALWAYS || g_clcPainter.IsForegroundWindow(hwnd)) && contact->type != CLCIT_DIVIDER);
+ BOOL minimalistic = (g_clcPainter.CheckMiniMode(dat,selected,hottrack));
+ if ( !RowHeights_Alloc(dat, item + 1))
+ return -1;
+
+ if (dat->row_variable_height)
+ {
+ if ( !dat->text_ignore_size_for_row_height)
+ {
+ HANDLE hContact = pdnce->hContact;
+ tmp = dat->fontModernInfo[g_clcPainter.GetBasicFontID(contact)].fontHeight;
+ if (dat->text_replace_smileys && dat->first_line_draw_smileys && !dat->text_resize_smileys)
+ {
+ tmp = max(tmp, contact->ssText.iMaxSmileyHeight);
+ }
+ height += tmp;
+
+ if ( !minimalistic && dat->second_line_show && pdnce->szSecondLineText && pdnce->szSecondLineText[0])
+ {
+ tmp = dat->fontModernInfo[FONTID_SECONDLINE].fontHeight;
+ if (dat->text_replace_smileys && dat->second_line_draw_smileys && !dat->text_resize_smileys)
+ {
+ tmp = max(tmp, pdnce->ssSecondLine.iMaxSmileyHeight);
+ }
+ height += dat->second_line_top_space + tmp;
+ }
+
+ if ( !minimalistic && dat->third_line_show && pdnce->szThirdLineText && pdnce->szThirdLineText[0])
+ {
+ tmp = dat->fontModernInfo[FONTID_THIRDLINE].fontHeight;
+ if (dat->text_replace_smileys && dat->third_line_draw_smileys && !dat->text_resize_smileys)
+ {
+ tmp = max(tmp, pdnce->ssThirdLine.iMaxSmileyHeight);
+ }
+ height += dat->third_line_top_space + tmp;
+ }
+ }
+
+ // Avatar size
+ if (dat->avatars_show && !dat->avatars_ignore_size_for_row_height &&
+ contact->type == CLCIT_CONTACT &&
+ (
+ (dat->use_avatar_service && contact->avatar_data != NULL) ||
+ (!dat->use_avatar_service && contact->avatar_pos != AVATAR_POS_DONT_HAVE)
+ ) && !minimalistic )
+ {
+ height = max(height, dat->avatars_maxheight_size);
+ }
+
+ // Checkbox size
+ if ((style&CLS_CHECKBOXES && contact->type == CLCIT_CONTACT) ||
+ (style&CLS_GROUPCHECKBOXES && contact->type == CLCIT_GROUP) ||
+ (contact->type == CLCIT_INFO && contact->flags&CLCIIF_CHECKBOX))
+ {
+ height = max(height, dat->checkboxSize);
+ }
+
+ // Icon size
+ if ( !dat->icon_ignore_size_for_row_height)
+ {
+ if (contact->type == CLCIT_GROUP
+ || (contact->type == CLCIT_CONTACT && contact->iImage != -1
+ && !(dat->icon_hide_on_avatar && dat->avatars_show
+ && ((dat->use_avatar_service && contact->avatar_data != NULL) ||
+ (!dat->use_avatar_service && contact->avatar_pos != AVATAR_POS_DONT_HAVE)
+ )
+ && !contact->image_is_special)))
+ {
+ height = max(height, ICON_HEIGHT);
+ }
+ }
+
+ height += 2 * dat->row_border;
+
+ // Min size
+ height = max(height, dat->row_min_heigh);
+ }
+ else
+ {
+ height = dat->max_row_height;
+ }
+
+ dat->row_heights[item] = height;
+
+ return height;
+ }
+}
+
+
+// Calc item top Y (using stored data)
+int cliGetRowTopY(struct ClcData *dat, int item)
+{
+ int i;
+ int y = 0;
+ if (item >= dat->row_heights_size)
+ return cliGetRowBottomY(dat,item-1);
+
+ for (i=0 ; i < item ; i++)
+ {
+ y += dat->row_heights[i];
+ }
+
+ return y;
+}
+
+
+// Calc item bottom Y (using stored data)
+int cliGetRowBottomY(struct ClcData *dat, int item)
+{
+ int i;
+ int y = 0;
+
+ if (item >= dat->row_heights_size)
+ return -1;
+
+ for (i=0 ; i <= item ; i++)
+ {
+ y += dat->row_heights[i];
+ }
+
+ return y;
+}
+
+
+// Calc total height of rows (using stored data)
+int cliGetRowTotalHeight(struct ClcData *dat)
+{
+ int i;
+ int y = 0;
+
+ for (i=0 ; i < dat->row_heights_size ; i++)
+ {
+ y += dat->row_heights[i];
+ }
+
+ return y;
+}
+
+// Return the line that pos_y is at or -1 (using stored data)
+int cliRowHitTest(struct ClcData *dat, int pos_y)
+{
+ int i;
+ int y = 0;
+
+ if (pos_y < 0)
+ return -1;
+
+ for (i=0 ; i < dat->row_heights_size ; i++)
+ {
+ y += dat->row_heights[i];
+
+ if (pos_y < y)
+ return i;
+ }
+
+ return -1;
+}
+
+int cliGetRowHeight(struct ClcData *dat, int item)
+{
+ if ( item >= dat->row_heights_size || item < 0 )
+ return dat->max_row_height;
+ return dat->row_heights[ item ];
+}
diff --git a/plugins/Clist_modern/src/modern_rowtemplateopt.cpp b/plugins/Clist_modern/src/modern_rowtemplateopt.cpp
new file mode 100644
index 0000000000..cc64f3a522
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_rowtemplateopt.cpp
@@ -0,0 +1,704 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "m_clc.h"
+#include "io.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_row.h"
+
+
+
+
+
+
+void RefreshTree(HWND hwndDlg,HTREEITEM hti);
+static char* rowOptTmplStr;
+static ROWCELL* rowOptTmplRoot;
+static ROWCELL* rowOptTA[100];
+ TCHAR *types[] = {_T("none"), _T("text1"), _T("text2"), _T("text3"), _T("status"),
+ _T("avatar"), _T("extra"), _T("extra1"), _T("extra2"), _T("extra3"),
+ _T("extra4"), _T("extra5"), _T("extra6"), _T("extra7"), _T("extra8"),
+ _T("extra9"), _T("time"), _T("space"), _T("fspace")};
+RECT da = {205,58,440,130}; // Draw area
+// Add by ZorG
+
+//char * rowOptBuildTmpl(HTREEITEM node, HWND htree)
+//{
+//}
+void rowOptBuildTA(pROWCELL cell, pROWCELL* TA, int* i)
+{
+ if ( !cell) return;
+ TA[(*i)++] = cell;
+ rowOptBuildTA(cell->child,TA, i);
+ rowOptBuildTA(cell->next, TA, i);
+}
+
+void rowOptShowSettings(HWND hwnd)
+{
+ TVITEM tvi;
+ pROWCELL cell;
+ HTREEITEM node = TreeView_GetSelection(GetDlgItem(hwnd, IDC_ROWTREE));
+ int param;
+
+ tvi.hItem = node;
+ tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+
+ TreeView_GetItem(GetDlgItem(hwnd, IDC_ROWTREE), &tvi);
+ cell = (pROWCELL)tvi.lParam;
+
+ if ( !tvi.hItem)
+ {
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTTYPE) ,0);
+ EnableWindow(GetDlgItem(hwnd,IDC_VALIGN),0);
+ EnableWindow(GetDlgItem(hwnd,IDC_HALIGN) ,0);
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTWIDTH) ,0);
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTHEIGHT),0);
+ EnableWindow(GetDlgItem(hwnd,IDC_SPINCONTWIDTH) ,0);
+ EnableWindow(GetDlgItem(hwnd,IDC_SPINCONTHEIGHT),0);
+ SendDlgItemMessage(hwnd,IDC_SPINCONTWIDTH, UDM_SETPOS,0,0);
+ SendDlgItemMessage(hwnd,IDC_SPINCONTHEIGHT,UDM_SETPOS,0,0);
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTLAYER),0);
+ return;
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTTYPE) ,1);
+ EnableWindow(GetDlgItem(hwnd,IDC_VALIGN),1);
+ EnableWindow(GetDlgItem(hwnd,IDC_HALIGN) ,1);
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTLAYER),1);
+
+ if (cell->type != TC_SPACE && cell->type != TC_FIXED)
+ {
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTWIDTH) ,0);
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTHEIGHT),0);
+ EnableWindow(GetDlgItem(hwnd,IDC_SPINCONTWIDTH) ,0);
+ EnableWindow(GetDlgItem(hwnd,IDC_SPINCONTHEIGHT),0);
+ SendDlgItemMessage(hwnd,IDC_SPINCONTWIDTH, UDM_SETPOS,0,0);
+ SendDlgItemMessage(hwnd,IDC_SPINCONTHEIGHT,UDM_SETPOS,0,0);
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTWIDTH) ,1);
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTHEIGHT),1);
+ EnableWindow(GetDlgItem(hwnd,IDC_SPINCONTWIDTH) ,1);
+ EnableWindow(GetDlgItem(hwnd,IDC_SPINCONTHEIGHT),1);
+ SendDlgItemMessage(hwnd,IDC_SPINCONTWIDTH, UDM_SETPOS,0,MAKELONG(cell->w,0));
+ SendDlgItemMessage(hwnd,IDC_SPINCONTHEIGHT,UDM_SETPOS,0,MAKELONG(cell->h,0));
+ }
+
+ }
+
+ SendDlgItemMessage(hwnd, IDC_CONTTYPE, CB_SETCURSEL, cell->type, 0);
+
+ switch (cell->valign)
+ {
+ case TC_VCENTER:
+ param = 1;
+ break;
+ case TC_BOTTOM:
+ param = 2;
+ break;
+ default:
+ param = 0;
+ }
+ SendDlgItemMessage(hwnd, IDC_VALIGN, CB_SETCURSEL, param, 0);
+
+ switch (cell->halign)
+ {
+ case TC_HCENTER:
+ param = 1;
+ break;
+ case TC_RIGHT:
+ param = 2;
+ break;
+ default:
+ param = 0;
+ }
+ SendDlgItemMessage(hwnd, IDC_HALIGN, CB_SETCURSEL, param, 0);
+
+ CheckDlgButton(hwnd,IDC_CONTLAYER,cell->layer?BST_CHECKED:BST_UNCHECKED);
+
+ return;
+
+}
+
+void rowOptGenerateTreeView(pROWCELL cell, HTREEITEM node, HWND hwnd)
+{
+ TVINSERTSTRUCT tvis;
+ HTREEITEM pnode;
+
+ if ( !cell) return;
+
+ tvis.hParent = node;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ tvis.item.stateMask = TVIS_STATEIMAGEMASK;
+ tvis.item.lParam = (LPARAM)cell;
+
+ switch (cell->cont)
+ {
+ case TC_ROW:
+ tvis.item.pszText = _T("Line");
+ break;
+ case TC_COL:
+ tvis.item.pszText = _T("Column");
+ }
+
+ tvis.item.iImage = cell->child?1:2;
+ tvis.item.iSelectedImage = cell->child?0:2;
+
+ pnode = TreeView_InsertItem(hwnd,&tvis);
+
+ rowOptGenerateTreeView(cell->child, pnode, hwnd);
+ rowOptGenerateTreeView(cell->next, node, hwnd);
+}
+
+int rowOptFillRowTree(HWND hwnd)
+{
+ int i=0;
+ TreeView_DeleteAllItems(hwnd);
+ rowOptGenerateTreeView(rowOptTmplRoot, NULL, hwnd);
+ TreeView_Expand(hwnd, TreeView_GetRoot(hwnd), TVM_EXPAND);
+
+ return 0;
+}
+
+void rowOptAddContainer(HWND htree, HTREEITEM hti)
+{
+ TVINSERTSTRUCT tvis;
+ TVITEM tviparent;
+ ROWCELL *cell = NULL;
+
+ if ( !hti)
+ {
+ if (TreeView_GetRoot(htree)) return;
+ else
+ {
+ rowAddCell(rowOptTmplRoot, TC_ROW);
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = TVI_ROOT;
+ tvis.item.pszText = _T("Line");
+ tvis.item.lParam = (LPARAM)rowOptTmplRoot;
+ cell = rowOptTmplRoot;
+ }
+ }
+ else
+ {
+ // Get parent item
+ tviparent.hItem = hti;
+ tviparent.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ TreeView_GetItem(htree, &tviparent);
+ cell = (pROWCELL)tviparent.lParam;
+
+ if (cell->cont == TC_ROW)
+ tvis.item.pszText = _T("Column");
+ else
+ tvis.item.pszText = _T("Line");
+
+ if (cell->child)
+ {
+ cell = cell->child;
+
+ while (cell->next)
+ cell = cell->next;
+
+ rowAddCell(cell->next, ((ROWCELL*)tviparent.lParam)->cont == TC_ROW?TC_COL:TC_ROW);
+ cell = cell->next;
+ }
+ else
+ {
+ rowAddCell(cell->child, ((ROWCELL*)tviparent.lParam)->cont == TC_ROW?TC_COL:TC_ROW);
+ cell = cell->child;
+ }
+
+ tvis.hInsertAfter = TVI_LAST;
+ }
+
+ tvis.item.lParam = (LPARAM)cell;
+ tvis.hParent = hti;
+
+ tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ tvis.item.stateMask = TVIS_STATEIMAGEMASK;
+ tvis.item.iImage = 2;
+ tvis.item.iSelectedImage = 2;
+
+ TreeView_InsertItem(htree,&tvis);
+
+ TreeView_Expand(htree, hti, TVM_EXPAND);
+
+ // Change icon at parent item
+ tviparent.iImage = 1;
+ tviparent.iSelectedImage = 0;
+ TreeView_SetItem(htree, &tviparent);
+
+ {
+ int i=0;
+ ZeroMemory( rowOptTA, sizeof( rowOptTA ));
+ rowOptBuildTA(rowOptTmplRoot, (pROWCELL*)&rowOptTA, &i);
+ }
+
+}
+
+void rowOptDelContainer(HWND htree, HTREEITEM hti)
+{
+ HTREEITEM prev = TreeView_GetPrevSibling(htree, hti);
+ HTREEITEM prnt = TreeView_GetParent(htree, hti);
+ TVITEM tvi, tvpi;
+
+ if ( !hti) return;
+
+ // Get current tree item
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ TreeView_GetItem(htree, &tvi);
+
+ tvpi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+
+ if (prev)
+ {
+ tvpi.hItem = prev;
+ TreeView_GetItem(htree, &tvpi);
+ ((pROWCELL)tvpi.lParam)->next = ((pROWCELL)tvi.lParam)->next;
+ }
+ else
+ {
+ if (prnt)
+ {
+ tvpi.hItem = prnt;
+ TreeView_GetItem(htree, &tvpi);
+ ((pROWCELL)tvpi.lParam)->child = ((pROWCELL)tvi.lParam)->next;
+ prev = prnt;
+ }
+ else
+ {
+
+ tvpi.lParam = (LPARAM)NULL;
+ rowOptTmplRoot = (pROWCELL)tvpi.lParam;
+ }
+
+ }
+
+ ((pROWCELL)tvi.lParam)->next = NULL;
+ rowDeleteTree((pROWCELL)tvi.lParam);
+
+ {
+ int i=0;
+ ZeroMemory( rowOptTA, sizeof( rowOptTA ));
+ rowOptBuildTA((pROWCELL)tvpi.lParam, (pROWCELL*)&rowOptTA, &i );
+ }
+
+ TreeView_DeleteItem(htree, hti);
+
+
+ // Change icon at parent item
+ if ( !prnt || (prnt != prev)) return;
+
+ if ( TreeView_GetChild(htree, prnt))
+ {
+ tvpi.iImage = 1;
+ tvpi.iSelectedImage = 0;
+ }
+ else
+ {
+ tvpi.iImage = 2;
+ tvpi.iSelectedImage = 2;
+ }
+ TreeView_SetItem(htree, &tvpi);
+
+}
+
+void RefreshTree(HWND hwndDlg,HTREEITEM hti)
+{
+ HWND htree = GetDlgItem(hwndDlg, IDC_ROWTREE);
+ pROWCELL cell;
+ TVITEM tvi = {0};
+ if (hti == NULL) hti = TreeView_GetRoot(htree);
+ while (hti)
+ {
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE;//|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT;
+ TreeView_GetItem(htree, &tvi);
+ cell = (pROWCELL)tvi.lParam;
+ if (cell)
+ {
+ TCHAR buf[200] = {0};
+ if ( !cell->child)
+ {
+ if (cell->type == 0)
+ mir_sntprintf(buf, SIZEOF(buf), TranslateT("Empty %s cell"), cell->cont == TC_COL?TranslateT("column"):TranslateT("line"));
+ else
+ mir_sntprintf(buf, SIZEOF(buf), TranslateT("%s"), TranslateTS(types[cell->type]));
+ }
+ else
+ {
+ if (cell->type == 0)
+ mir_sntprintf(buf, SIZEOF(buf), TranslateT("%s"), cell->cont != TC_COL?TranslateT("columns"):TranslateT("lines"));
+ else
+ mir_sntprintf(buf, SIZEOF(buf), TranslateT("%s, contain %s"), TranslateTS(types[cell->type]),cell->cont != TC_COL?TranslateT("columns"):TranslateT("lines"));
+ }
+ if (cell->layer) _tcsncat(buf,TranslateT(" layered"),SIZEOF(buf));
+ tvi.mask = TVIF_HANDLE|TVIF_TEXT;
+ tvi.pszText = buf;
+ TreeView_SetItem(htree,&tvi);
+ }
+ {
+ HTREEITEM child_hti = TreeView_GetChild(htree,hti);
+ if (child_hti) RefreshTree(hwndDlg,child_hti);
+ }
+ hti = TreeView_GetNextSibling(htree,hti);
+ }
+
+ RedrawWindow(hwndDlg,NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_UPDATENOW|RDW_ALLCHILDREN);
+}
+
+INT_PTR CALLBACK DlgTmplEditorOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ int hbuf = 0, seq = 0;
+ HWND htree = GetDlgItem(hwndDlg,IDC_ROWTREE);
+
+ TranslateDialogDefault(hwndDlg);
+ rowOptTmplStr = db_get_sa(NULL, "ModernData", "RowTemplate");
+ if ( !rowOptTmplStr) rowOptTmplStr = mir_strdup("<TR />");
+ {
+ //HIMAGELIST himlTreeIcons;
+ //himlTreeIcons = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_COLOR32|ILC_MASK,3,2);
+ //ImageList_AddIcon(himlTreeIcons,LoadSmallIconShared(g_hInst,MAKEINTRESOURCE(IDI_ROWCONT1)));
+ //ImageList_AddIcon(himlTreeIcons,LoadSmallIconShared(g_hInst,MAKEINTRESOURCE(IDI_ROWCONT2)));
+ //ImageList_AddIcon(himlTreeIcons,LoadSmallIconShared(g_hInst,MAKEINTRESOURCE(IDI_ROWCONT3)));
+ //TreeView_SetImageList(htree,himlTreeIcons,TVSIL_NORMAL);
+ }
+
+ SendDlgItemMessage(hwndDlg,IDC_SPINCONTWIDTH, UDM_SETRANGE,0,MAKELONG(999,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPINCONTHEIGHT,UDM_SETRANGE,0,MAKELONG(999,0));
+
+ {
+ int i, item;
+
+ for (i=0; i < SIZEOF(types); i++)
+ {
+ item = SendDlgItemMessage(hwndDlg,IDC_CONTTYPE,CB_ADDSTRING,0,(LPARAM)TranslateTS(types[i]));
+ SendDlgItemMessage(hwndDlg,IDC_CONTTYPE,CB_SETITEMDATA,item,(LPARAM)0);
+ }
+ SendDlgItemMessage(hwndDlg,IDC_CONTTYPE,CB_SETCURSEL,0,0);
+ }
+
+ {
+ int i, item;
+ TCHAR *alignment[] = {_T("left"), _T("hCenter"), _T("right")};
+ for (i=0; i < SIZEOF(alignment); i++)
+ {
+ item = SendDlgItemMessage(hwndDlg,IDC_HALIGN,CB_ADDSTRING,0,(LPARAM)TranslateTS(alignment[i]));
+ SendDlgItemMessage(hwndDlg,IDC_HALIGN,CB_SETITEMDATA,item,(LPARAM)0);
+ }
+ SendDlgItemMessage(hwndDlg,IDC_HALIGN,CB_SETCURSEL,0,0);
+
+ }
+
+ {
+ int i, item;
+ TCHAR *alignment[] = {_T("top"), _T("vCenter"), _T("bottom")};
+ for (i=0; i < SIZEOF(alignment); i++)
+ {
+ item = SendDlgItemMessage(hwndDlg,IDC_VALIGN,CB_ADDSTRING,0,(LPARAM)TranslateTS(alignment[i]));
+ SendDlgItemMessage(hwndDlg,IDC_VALIGN,CB_SETITEMDATA,item,(LPARAM)0);
+ }
+ SendDlgItemMessage(hwndDlg,IDC_VALIGN,CB_SETCURSEL,0,0);
+ }
+
+ rowDeleteTree(rowOptTmplRoot);
+ rowOptTmplRoot = NULL;
+ rowParse(rowOptTmplRoot, rowOptTmplRoot, rowOptTmplStr, hbuf, seq, rowOptTA);
+ seq = 0;
+ ZeroMemory( rowOptTA, sizeof( rowOptTA ));
+ rowOptBuildTA(rowOptTmplRoot, (pROWCELL*)&rowOptTA, &seq);
+
+ rowOptFillRowTree(htree);
+ RefreshTree(hwndDlg,NULL);
+ TreeView_SelectItem(GetDlgItem(hwndDlg, IDC_ROWTREE), TreeView_GetRoot(GetDlgItem(hwndDlg, IDC_ROWTREE)));
+ rowOptShowSettings(hwndDlg);
+
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ HWND htree = GetDlgItem(hwndDlg, IDC_ROWTREE);
+ pROWCELL cell;
+ TVITEM tvi = {0};
+ HTREEITEM hti = TreeView_GetSelection(htree);
+
+
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ TreeView_GetItem(htree, &tvi);
+ cell = (pROWCELL)tvi.lParam;
+
+ switch (LOWORD(wParam))
+ {
+ case IDC_CONTTYPE:
+ if (HIWORD(wParam) == CBN_SELENDOK)
+ {
+ TVITEM tv = {0};
+ int index = SendMessage(GetDlgItem(hwndDlg,IDC_CONTTYPE),CB_GETCURSEL, 0, 0);
+ cell->type = index;
+ RefreshTree(hwndDlg,NULL);
+ }
+
+ case IDC_VALIGN:
+ if (HIWORD(wParam) == CBN_SELENDOK)
+ {
+ switch (SendMessage(GetDlgItem(hwndDlg,IDC_VALIGN),CB_GETCURSEL, 0, 0))
+ {
+ case 0:
+ cell->valign = TC_TOP;
+ break;
+ case 1:
+ cell->valign = TC_VCENTER;
+ break;
+ case 2:
+ cell->valign = TC_BOTTOM;
+ break;
+ }
+ RefreshTree(hwndDlg,NULL);
+ }
+
+ case IDC_HALIGN:
+ if (HIWORD(wParam) == CBN_SELENDOK)
+ {
+ switch (SendMessage(GetDlgItem(hwndDlg,IDC_HALIGN),CB_GETCURSEL, 0, 0))
+ {
+ case 0:
+ cell->halign = TC_LEFT;
+ break;
+ case 1:
+ cell->halign = TC_HCENTER;
+ break;
+ case 2:
+ cell->halign = TC_RIGHT;
+ break;
+ }
+ RefreshTree(hwndDlg,NULL);
+ }
+
+
+ }
+
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ if (lParam == (LPARAM)GetDlgItem(hwndDlg,IDC_ADDCONTAINER))
+ // Adding new container
+ {
+ rowOptAddContainer(htree, hti);
+ }
+ else if (lParam == (LPARAM)GetDlgItem(hwndDlg,IDC_DELCONTAINER))
+ // Deleting container
+ {
+ rowOptDelContainer(htree, hti);
+ }
+ else if (lParam == (LPARAM)GetDlgItem(hwndDlg,IDC_CONTUP))
+ // Moving container to up
+ {
+ RedrawWindow(htree,&da,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_UPDATENOW|RDW_ALLCHILDREN);
+ }
+ else if (lParam == (LPARAM)GetDlgItem(hwndDlg,IDC_CONTDOWN))
+ // Moving container to down
+ {
+ }
+ RefreshTree(hwndDlg,NULL);
+ RedrawWindow(GetParent(hwndDlg),NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_UPDATENOW|RDW_ALLCHILDREN);
+ }
+
+
+ //SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ return TRUE;
+ }
+
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+
+ case IDC_ROWTREE:
+ if (((LPNMHDR)lParam)->code == NM_SETCURSOR )
+ rowOptShowSettings(hwndDlg);
+ if (((LPNMHDR)lParam)->code == NM_CLICK )
+ RedrawWindow(hwndDlg,&da,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_UPDATENOW);
+ break;
+
+ case 0: // Apply or Ok button is pressed
+ return FALSE; // Temporary
+ break;
+ }
+ return TRUE;
+
+ case WM_PAINT:
+ {
+ int i=0;
+
+ // Drawning row template at properties page
+ PAINTSTRUCT ps;
+ HDC hdc;
+ TVITEM curItem;
+
+ if ( !rowOptTmplRoot) return FALSE;
+ hdc = BeginPaint(hwndDlg, &ps);
+
+ curItem.hItem = TreeView_GetSelection(GetDlgItem(hwndDlg, IDC_ROWTREE));
+ curItem.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ TreeView_GetItem(GetDlgItem(hwndDlg, IDC_ROWTREE), &curItem);
+
+ while(rowOptTA[i])
+ {
+ switch(rowOptTA[i]->type)
+ {
+ case TC_AVATAR:
+ rowOptTA[i]->w = 25;
+ rowOptTA[i]->h = 30;
+ break;
+
+ case TC_STATUS:
+ case TC_EXTRA1:
+ case TC_EXTRA2:
+ case TC_EXTRA3:
+ case TC_EXTRA4:
+ case TC_EXTRA5:
+ case TC_EXTRA6:
+ case TC_EXTRA7:
+ case TC_EXTRA8:
+ case TC_EXTRA9:
+ rowOptTA[i]->w = 16;
+ rowOptTA[i]->h = 16;
+ break;
+
+ case TC_EXTRA:
+ rowOptTA[i]->w = 112;
+ rowOptTA[i]->h = 16;
+ break;
+
+ case TC_TEXT1:
+ case TC_TEXT2:
+ case TC_TEXT3:
+ rowOptTA[i]->w = 200;
+ rowOptTA[i]->h = 16;
+ break;
+
+ case TC_TIME:
+ rowOptTA[i]->w = 30;
+ rowOptTA[i]->h = 10;
+ default:
+ {
+ rowOptTA[i]->w = 0;
+ rowOptTA[i]->h = 0;
+ }
+
+ }
+
+
+ i++;
+ }
+
+ rowSizeWithReposition(rowOptTmplRoot, da.right-da.left);
+
+
+
+ i = -1;
+ while (rowOptTA[++i])
+ {
+
+ switch(rowOptTA[i]->type)
+ {
+ case TC_SPACE:
+ case TC_FIXED:
+ case 0:
+ //if (rowOptTA[i] != (pROWCELL)curItem.lParam)
+ continue;
+ }
+ Rectangle(hdc,
+ rowOptTA[i]->r.left + da.left,
+ rowOptTA[i]->r.top + da.top,
+ rowOptTA[i]->r.right + da.left,
+ rowOptTA[i]->r.bottom + da.top);
+ }
+
+ EndPaint(hwndDlg, &ps);
+ return FALSE;
+ }
+
+ }
+ return FALSE;
+}
+
+
+
+
+/*
+BOOL CALLBACK DlgTmplEditorOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+
+{
+ switch (msg)
+ {
+ case WM_DESTROY:
+ {
+ break;
+ }
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ break;
+ }
+ case WM_COMMAND:
+ {
+ //LOWORD(wParam) == IDC_control
+ //HIWORD(wParam) == Message
+ //SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->idFrom)
+ {
+// case IDC_control:
+// {
+// break;
+// }
+ case 0:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ break;
+ } //case PSN_APPLY
+ } //switch code
+ } //case 0:
+ } //switch from
+ } //case: WM_NOTIFY
+ } // switch msg
+ return FALSE;
+}
+*/ \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_skinbutton.cpp b/plugins/Clist_modern/src/modern_skinbutton.cpp
new file mode 100644
index 0000000000..8bae142748
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_skinbutton.cpp
@@ -0,0 +1,815 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+*/
+
+/*
+This file contains code related to new modern free positioned skinned buttons
+*/
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_skinengine.h"
+#include "hdr/modern_clcpaint.h"
+#include "m_api/m_skinbutton.h"
+
+
+
+
+
+#define MODERNSKINBUTTONCLASS "MirandaModernSkinButtonClass"
+BOOL ModernSkinButtonModuleIsLoaded = FALSE;
+static HANDLE hookSystemShutdown_ModernSkinButton = NULL;
+static LRESULT CALLBACK ModernSkinButtonWndProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+int ModernSkinButtonUnloadModule(WPARAM wParam, LPARAM lParam);
+int SkinSelector_DeleteMask(MODERNMASK * mm);
+HWND SetToolTip(HWND hwnd, TCHAR * tip);
+
+typedef struct _ModernSkinButtonCtrl
+{
+ HWND hwnd;
+ BYTE down; // button state
+ BYTE focus; // has focus (1 or 0)
+ BYTE hover;
+ BYTE IsSwitcher;
+ BOOL fCallOnPress;
+ char * ID;
+ char * CommandService;
+ char * StateService;
+ char * HandleService;
+ char * ValueDBSection;
+ char * ValueTypeDef;
+ int Left, Top, Bottom, Right;
+ HMENU hMenu;
+ TCHAR * Hint;
+
+} ModernSkinButtonCtrl;
+typedef struct _HandleServiceParams
+{
+ HWND hwnd;
+ DWORD msg;
+ WPARAM wParam;
+ LPARAM lParam;
+ BOOL handled;
+} HandleServiceParams;
+
+static CRITICAL_SECTION csTips;
+static HWND hwndToolTips = NULL;
+
+int ModernSkinButtonLoadModule()
+{
+ WNDCLASSEX wc;
+ ZeroMemory(&wc, sizeof(wc));
+ wc.cbSize = sizeof(wc);
+ wc.lpszClassName = _T(MODERNSKINBUTTONCLASS);
+ wc.lpfnWndProc = ModernSkinButtonWndProc;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.cbWndExtra = sizeof(ModernSkinButtonCtrl*);
+ wc.hbrBackground = 0;
+ wc.style = CS_GLOBALCLASS;
+ RegisterClassEx(&wc);
+ InitializeCriticalSection(&csTips);
+ hookSystemShutdown_ModernSkinButton = HookEvent(ME_SYSTEM_SHUTDOWN, ModernSkinButtonUnloadModule);
+ ModernSkinButtonModuleIsLoaded = TRUE;
+ return 0;
+}
+
+int ModernSkinButtonUnloadModule(WPARAM wParam, LPARAM lParam)
+{
+ DeleteCriticalSection(&csTips);
+ return 0;
+}
+
+static int ModernSkinButtonPaintWorker(HWND hwnd, HDC whdc)
+{
+ HDC hdc;
+ HBITMAP bmp,oldbmp;
+ RECT rc;
+ HDC sdc = NULL;
+ ModernSkinButtonCtrl* bct = (ModernSkinButtonCtrl *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ if ( !bct) return 0;
+ if ( !IsWindowVisible(hwnd)) return 0;
+ if ( !whdc && !g_CluiData.fLayered) InvalidateRect(hwnd,NULL,FALSE);
+
+ if (whdc && g_CluiData.fLayered) hdc = whdc;
+ else
+ {
+ //sdc = GetWindowDC(GetParent(hwnd));
+ hdc = CreateCompatibleDC(NULL);
+ }
+ GetClientRect(hwnd,&rc);
+ bmp = ske_CreateDIB32(rc.right,rc.bottom);
+ oldbmp = (HBITMAP)SelectObject(hdc,bmp);
+ if ( !g_CluiData.fLayered)
+ ske_BltBackImage(bct->hwnd,hdc,NULL);
+ {
+ MODERNMASK Request = {0};
+ // int res;
+ //HBRUSH br = CreateSolidBrush(RGB(255,255,255));
+ char * Value = NULL;
+ DWORD val = 0;
+ {
+ if (bct->ValueDBSection && bct->ValueTypeDef)
+ {
+ char * key;
+ char * section;
+ DWORD defval = 0;
+ char buf[20];
+ key = mir_strdup(bct->ValueDBSection);
+ section = key;
+ if (bct->ValueTypeDef[0] != 's')
+ defval = (DWORD)atol(bct->ValueTypeDef+1);
+ do
+ {
+ if (key[0] == '/') {key[0] = '\0'; key++; break;}
+ key++;
+ } while (key[0] != '\0');
+ switch (bct->ValueTypeDef[0])
+ {
+ case 's':
+ {
+ Value = db_get_sa(NULL,section,key);
+ if ( !Value)
+ Value = mir_strdup(bct->ValueTypeDef+1);
+ break;
+ }
+ case 'd':
+ defval = db_get_dw(NULL,section,key,defval);
+ Value = mir_strdup(_ltoa(defval,buf,SIZEOF(buf)));
+ break;
+ case 'w':
+ defval = db_get_w(NULL,section,key,defval);
+ Value = mir_strdup(_ltoa(defval,buf,SIZEOF(buf)));
+ break;
+ case 'b':
+ defval = db_get_b(NULL,section,key,defval);
+ Value = mir_strdup(_ltoa(defval,buf,SIZEOF(buf)));
+ break;
+ }
+ mir_free(section);
+ }
+
+ }
+ g_clcPainter.AddParam(&Request,mod_CalcHash("Module"),"MButton",0);
+ g_clcPainter.AddParam(&Request,mod_CalcHash("ID"),bct->ID,0);
+ g_clcPainter.AddParam(&Request,mod_CalcHash("Down"),bct->down?"1":"0",0);
+ g_clcPainter.AddParam(&Request,mod_CalcHash("Focused"),bct->focus?"1":"0",0);
+ g_clcPainter.AddParam(&Request,mod_CalcHash("Hovered"),bct->hover?"1":"0",0);
+ if (Value) {
+ g_clcPainter.AddParam(&Request,mod_CalcHash("Value"),Value,0);
+ mir_free(Value);
+ }
+ SkinDrawGlyphMask(hdc,&rc,&rc,&Request);
+ SkinSelector_DeleteMask(&Request);
+ // DeleteObject(br);
+ }
+
+ if ( !whdc && g_CluiData.fLayered)
+ {
+ RECT r;
+ SetRect(&r,bct->Left,bct->Top,bct->Right,bct->Bottom);
+ ske_DrawImageAt(hdc,&r);
+ //CallingService to immeadeately update window with new image.
+ }
+ if (whdc && !g_CluiData.fLayered)
+ {
+ RECT r = {0};
+ GetClientRect(bct->hwnd,&r);
+ BitBlt(whdc,0,0,r.right,r.bottom,hdc,0,0,SRCCOPY);
+ }
+ SelectObject(hdc,oldbmp);
+ DeleteObject(bmp);
+ if ( !whdc || !g_CluiData.fLayered)
+ {
+ SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
+ mod_DeleteDC(hdc);
+ }
+ // if (sdc)
+ // ReleaseDC(GetParent(hwnd),sdc);
+ return 0;
+}
+
+static int ModernSkinButtonToggleDBValue(char * ValueDBSection,char *ValueTypeDef)
+{
+ if (ValueDBSection && ValueTypeDef)
+ {
+ char * key;
+ char * section;
+ char * val;
+ char * val2;
+ char * Value;
+ long l1,l2,curval;
+ DWORD defval = 0;
+ // char buf[20];
+ key = mir_strdup(ValueDBSection);
+ section = key;
+ do
+ {
+ if (key[0] == '/') {key[0] = '\0'; key++; break;}
+ key++;
+ } while (key[0] != '\0');
+
+ val = mir_strdup(ValueTypeDef+1);
+ val2 = val;
+ do
+ {
+ if (val2[0] == '/') {val2[0] = '\0'; val2++; break;}
+ val2++;
+ } while (val2[0] != '\0');
+
+ if (ValueTypeDef[0] != 's')
+ {
+ l1 = (DWORD)atol(val);
+ l2 = (DWORD)atol(val2);
+ }
+
+ switch (ValueTypeDef[0]) {
+ case 's':
+ Value = db_get_sa(NULL,section,key);
+ if ( !Value || (Value && mir_bool_strcmpi(Value,val2)))
+ Value = mir_strdup(val);
+ else
+ Value = mir_strdup(val2);
+ db_set_s(NULL,section,key,Value);
+ mir_free(Value);
+ break;
+
+ case 'd':
+ curval = db_get_dw(NULL,section,key,l2);
+ curval = (curval == l2)?l1:l2;
+ db_set_dw(NULL,section,key,(DWORD)curval);
+ break;
+
+ case 'w':
+ curval = db_get_w(NULL,section,key,l2);
+ curval = (curval == l2)?l1:l2;
+ db_set_w(NULL,section,key,(WORD)curval);
+ break;
+
+ case 'b':
+ curval = db_get_b(NULL,section,key,l2);
+ curval = (curval == l2)?l1:l2;
+ db_set_b(NULL,section,key,(BYTE)curval);
+ break;
+ }
+ mir_free(section);
+ mir_free(val);
+ }
+ return 0;
+}
+
+static char *_skipblank(char * str) //str will be modified;
+{
+ char * endstr = str+strlen(str);
+ while ((*str == ' ' || *str == '\t') && *str != '\0') str++;
+ while ((*endstr == ' ' || *endstr == '\t') && *endstr != '\0' && endstr < str) endstr--;
+ if (*endstr != '\0')
+ {
+ endstr++;
+ *endstr = '\0';
+ }
+ return str;
+}
+
+static int _CallServiceStrParams(IN char * toParce, OUT int *Return)
+{
+ char * pszService;
+ char * param1 = NULL;
+ char * param2 = NULL;
+ int paramCount = 0;
+ int result = 0;
+ pszService = mir_strdup(toParce);
+ param2 = strrchr(pszService, '%');
+ if (param2)
+ {
+ paramCount++;
+ *param2 = '\0'; param2++;
+ _skipblank(param2);
+ if (strlen(param2) == 0) param2 = NULL;
+ }
+ param1 = strrchr(pszService, '%');
+ if (param1)
+ {
+ paramCount++;
+ *param1 = '\0'; param1++;
+ _skipblank(param1);
+ if (strlen(param1) == 0) param1 = NULL;
+ }
+ if ( !pszService) return 0;
+ if (strlen(pszService) == 0) {
+ mir_free(pszService);
+ return 0;
+ }
+ if (param1 && *param1 == '\"')
+ {
+ param1++;
+ *(param1+strlen(param1)) = '\0';
+ }
+ else if (param1)
+ {
+ param1 = (char*)atoi(param1);
+ }
+ if (param2 && *param2 == '\"')
+ {
+ param2++;
+ *(param2+strlen(param2)) = '\0';
+ }
+ else if (param2)
+ param2 = (char*)atoi(param2);
+
+ if (paramCount == 1)
+ {
+ param1 = param2;
+ param2 = NULL;
+ }
+ if ( !ServiceExists(pszService))
+ {
+ result = 0;
+ }
+ else
+ {
+ int ret = 0;
+ result = 1;
+ ret = CallService(pszService, (WPARAM)param1, (WPARAM)param2);
+ if (Return) *Return = ret;
+ }
+ mir_free(pszService);
+ return result;
+}
+
+
+static LRESULT CALLBACK ModernSkinButtonWndProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ ModernSkinButtonCtrl* bct = (msg != WM_NCCREATE)?(ModernSkinButtonCtrl *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA):0;
+ if (bct && bct->HandleService && IsBadStringPtrA(bct->HandleService,255))
+ bct->HandleService = NULL;
+
+ if (bct)
+ if (bct->HandleService)
+ if (ServiceExists(bct->HandleService))
+ {
+ int t;
+ HandleServiceParams MSG = {0};
+ MSG.hwnd = hwndDlg;
+ MSG.msg = msg;
+ MSG.wParam = wParam;
+ MSG.lParam = lParam;
+ t = CallService(bct->HandleService,(WPARAM)&MSG,0);
+ if (MSG.handled) return t;
+ }
+ switch(msg)
+ {
+ case WM_NCCREATE:
+ {
+ SetWindowLongPtr(hwndDlg, GWL_STYLE, GetWindowLongPtr(hwndDlg, GWL_STYLE)|BS_OWNERDRAW);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ if (((CREATESTRUCT *)lParam)->lpszName) SetWindowText(hwndDlg, ((CREATESTRUCT *)lParam)->lpszName);
+ return TRUE;
+ }
+ case WM_DESTROY:
+ {
+ if (bct) {
+ EnterCriticalSection(&csTips);
+ if (hwndToolTips) {
+ TOOLINFO ti;
+ ZeroMemory(&ti, sizeof(ti));
+ ti.cbSize = sizeof(ti);
+ ti.uFlags = TTF_IDISHWND;
+ ti.hwnd = bct->hwnd;
+ ti.uId = (UINT_PTR)bct->hwnd;
+ if (SendMessage(hwndToolTips, TTM_GETTOOLINFO, 0, (LPARAM)&ti)) {
+ SendMessage(hwndToolTips, TTM_DELTOOL, 0, (LPARAM)&ti);
+ }
+ if (SendMessage(hwndToolTips, TTM_GETTOOLCOUNT, 0, (LPARAM)&ti) == 0) {
+ DestroyWindow(hwndToolTips);
+ hwndToolTips = NULL;
+ }
+ }
+ LeaveCriticalSection(&csTips);
+ mir_free(bct->ID);
+ mir_free(bct->CommandService);
+ mir_free(bct->StateService);
+ mir_free(bct->HandleService);
+ mir_free(bct->Hint);
+ mir_free(bct->ValueDBSection);
+ mir_free(bct->ValueTypeDef);
+ mir_free(bct);
+ }
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ break; // DONT! fall thru
+ }
+ case WM_SETCURSOR:
+ {
+ HCURSOR hCurs1;
+ hCurs1 = LoadCursor(NULL, IDC_ARROW);
+ if (hCurs1) SetCursor(hCurs1);
+ if (bct) SetToolTip(hwndDlg, bct->Hint);
+ return 1;
+ }
+ case WM_PRINT:
+ {
+ if (IsWindowVisible(hwndDlg))
+ ModernSkinButtonPaintWorker(hwndDlg,(HDC)wParam);
+ break;
+ }
+ case WM_PAINT:
+ {
+ if (IsWindowVisible(hwndDlg) && !g_CluiData.fLayered)
+ {
+ PAINTSTRUCT ps = {0};
+ BeginPaint(hwndDlg,&ps);
+ ModernSkinButtonPaintWorker(hwndDlg,(HDC)ps.hdc);
+ EndPaint(hwndDlg,&ps);
+ }
+ return DefWindowProc(hwndDlg, msg, wParam, lParam);
+ }
+ case WM_CAPTURECHANGED:
+ {
+ bct->hover = 0;
+ bct->down = 0;
+ ModernSkinButtonPaintWorker(bct->hwnd,0);
+ // KillTimer(bct->hwnd,1234);
+ break;
+ }
+ //case WM_TIMER:
+ // {
+ // POINT t;
+ // GetCursorPos(&t);
+ // if (bct->hover && WindowFromPoint(t) != bct->hwnd)
+ // {
+ // KillTimer(bct->hwnd,1234);
+ // bct->hover = 0;
+ // ReleaseCapture();
+ // PaintWorker(bct->hwnd,0);
+ // }
+ // return 0;
+ // }
+ case WM_MOUSEMOVE:
+ {
+ if ( !bct->hover)
+ {
+ SetCapture(bct->hwnd);
+ bct->hover = 1;
+ //KillTimer(bct->hwnd,1234);
+ //CLUI_SafeSetTimer(bct->hwnd,1234,100,NULL);
+ ModernSkinButtonPaintWorker(bct->hwnd,0);
+ return 0;
+ }
+ else
+ {
+ POINT t;
+ t.x = LOWORD(lParam);
+ t.y = HIWORD(lParam);
+ ClientToScreen(bct->hwnd,&t);
+ if (WindowFromPoint(t) != bct->hwnd)
+ ReleaseCapture();
+ return 0;
+ }
+
+
+ }
+ case WM_LBUTTONDOWN:
+ {
+ //KillTimer(bct->hwnd,1234);
+ //CLUI_SafeSetTimer(bct->hwnd,1234,100,NULL);
+ bct->down = 1;
+ SetForegroundWindow(GetParent(bct->hwnd));
+ ModernSkinButtonPaintWorker(bct->hwnd,0);
+ if (bct && bct->CommandService && IsBadStringPtrA(bct->CommandService,255))
+ bct->CommandService = NULL;
+ if (bct->fCallOnPress)
+ {
+ if (bct->CommandService)
+ {
+
+ if ( !_CallServiceStrParams(bct->CommandService, NULL) && (bct->ValueDBSection && bct->ValueTypeDef))
+ ModernSkinButtonToggleDBValue(bct->ValueDBSection,bct->ValueTypeDef);
+ }
+ bct->down = 0;
+
+ ModernSkinButtonPaintWorker(bct->hwnd,0);
+ }
+
+ return 0;
+ }
+ case WM_LBUTTONUP:
+ if (bct->down)
+ {
+ //KillTimer(bct->hwnd,1234);
+ //CLUI_SafeSetTimer(bct->hwnd,1234,100,NULL);
+ ReleaseCapture();
+ bct->hover = 0;
+ bct->down = 0;
+ ModernSkinButtonPaintWorker(bct->hwnd,0);
+ if (bct && bct->CommandService && IsBadStringPtrA(bct->CommandService,255))
+ bct->CommandService = NULL;
+ if (bct->CommandService)
+ if (_CallServiceStrParams(bct->CommandService, NULL))
+ {}
+ else if (bct->ValueDBSection && bct->ValueTypeDef)
+ ModernSkinButtonToggleDBValue(bct->ValueDBSection,bct->ValueTypeDef);
+ }
+
+
+ }
+ return DefWindowProc(hwndDlg, msg, wParam, lParam);
+}
+
+
+HWND SetToolTip(HWND hwnd, TCHAR * tip)
+{
+ TOOLINFO ti;
+ if ( !tip) return 0;
+ EnterCriticalSection(&csTips);
+ if ( !hwndToolTips) {
+ // hwndToolTips = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, _T(""), WS_POPUP, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL), NULL);
+
+ hwndToolTips = CreateWindowEx(0, TOOLTIPS_CLASS, NULL,
+ WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ hwnd, NULL, GetModuleHandle(NULL),
+ NULL);
+
+ SetWindowPos(hwndToolTips, HWND_TOPMOST,0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ }
+
+ ZeroMemory(&ti, sizeof(ti));
+ ti.cbSize = sizeof(ti);
+ ti.uFlags = TTF_IDISHWND;
+ ti.hwnd = hwnd;
+ ti.uId = (UINT_PTR)hwnd;
+ if (SendMessage(hwndToolTips, TTM_GETTOOLINFO, 0, (LPARAM)&ti)) {
+ SendMessage(hwndToolTips, TTM_DELTOOL, 0, (LPARAM)&ti);
+ }
+ ti.uFlags = TTF_IDISHWND|TTF_SUBCLASS;
+ ti.uId = (UINT_PTR)hwnd;
+ ti.lpszText = (TCHAR*)tip;
+ SendMessage(hwndToolTips,TTM_ADDTOOL,0,(LPARAM)&ti);
+
+ LeaveCriticalSection(&csTips);
+ return hwndToolTips;
+}
+
+
+
+typedef struct _MButton
+{
+ HWND hwnd;
+ BYTE ConstrainPositionFrom; //(BBRRTTLL) L = 0 - from left, L = 1 from right, L = 2 from center
+ int OrL,OrR,OrT,OrB;
+ int minW,minH;
+ ModernSkinButtonCtrl * bct;
+
+} MButton;
+MButton * Buttons = NULL;
+DWORD ButtonsCount = 0;
+
+#define _center_h( rc ) (((rc)->right + (rc)->left ) >> 1)
+#define _center_v( rc ) (((rc)->bottom + (rc)->top ) >> 1)
+
+int ModernSkinButton_AddButton(HWND parent,
+ char * ID,
+ char * CommandService,
+ char * StateDefService,
+ char * HandeService,
+ int Left,
+ int Top,
+ int Right,
+ int Bottom,
+ DWORD sbFlags,
+ TCHAR * Hint,
+ char * DBkey,
+ char * TypeDef,
+ int MinWidth, int MinHeight)
+{
+ // if ( !parent) return 0;
+ if ( !ModernSkinButtonModuleIsLoaded) return 0;
+ if ( !Buttons)
+ Buttons = (MButton*)mir_alloc(sizeof(MButton));
+ else
+ Buttons = (MButton*)mir_realloc(Buttons,sizeof(MButton)*(ButtonsCount+1));
+ {
+ //HWND hwnd;
+ RECT rc = {0};
+ ModernSkinButtonCtrl* bct;
+ int l,r,b,t;
+ if (parent) GetClientRect(parent,&rc);
+ l = ( sbFlags & SBF_ALIGN_TL_RIGHT ) ? ( rc.right + Left ) :
+ ( sbFlags & SBF_ALIGN_TL_HCENTER ) ? ( _center_h( &rc ) + Left ) :
+ ( rc.left + Left );
+
+ t = ( sbFlags & SBF_ALIGN_TL_BOTTOM ) ? ( rc.bottom + Top ) :
+ ( sbFlags & SBF_ALIGN_TL_VCENTER ) ? ( _center_v( &rc ) + Top ) :
+ ( rc.top+Top );
+
+ r = ( sbFlags & SBF_ALIGN_BR_RIGHT ) ? ( rc.right + Right ) :
+ ( sbFlags & SBF_ALIGN_BR_HCENTER ) ? ( _center_h( &rc) + Right ) :
+ ( rc.left + Right );
+
+ b = ( sbFlags & SBF_ALIGN_BR_BOTTOM ) ? ( rc.bottom + Bottom ) :
+ ( sbFlags & SBF_ALIGN_BR_VCENTER ) ? ( _center_v( &rc ) + Bottom ) :
+ ( rc.top + Bottom );
+ bct = (ModernSkinButtonCtrl *)mir_alloc(sizeof(ModernSkinButtonCtrl));
+ memset(bct,0,sizeof(ModernSkinButtonCtrl));
+ bct->Left = l;
+ bct->Right = r;
+ bct->Top = t;
+ bct->Bottom = b;
+ bct->fCallOnPress = ( sbFlags & SBF_CALL_ON_PRESS ) != 0;
+ bct->HandleService = mir_strdup(HandeService);
+ bct->CommandService = mir_strdup(CommandService);
+ bct->StateService = mir_strdup(StateDefService);
+ if (DBkey && &DBkey != '\0') bct->ValueDBSection = mir_strdup(DBkey); else bct->ValueDBSection = NULL;
+ if (TypeDef && &TypeDef != '\0') bct->ValueTypeDef = mir_strdup(TypeDef); else bct->ValueTypeDef = mir_strdup("sDefault");
+ bct->ID=mir_strdup(ID);
+ bct->Hint = mir_tstrdup(Hint);
+ Buttons[ButtonsCount].bct = bct;
+ Buttons[ButtonsCount].hwnd = NULL;
+ Buttons[ButtonsCount].OrL = Left;
+ Buttons[ButtonsCount].OrT = Top;
+ Buttons[ButtonsCount].OrR = Right;
+ Buttons[ButtonsCount].OrB = Bottom;
+ Buttons[ButtonsCount].ConstrainPositionFrom = (BYTE)sbFlags;
+ Buttons[ButtonsCount].minH = MinHeight;
+ Buttons[ButtonsCount].minW = MinWidth;
+ ButtonsCount++;
+ // CLUI_ShowWindowMod(hwnd,SW_SHOW);
+ }
+ return 0;
+}
+
+
+
+static int ModernSkinButtonErase(int l,int t,int r, int b)
+{
+ DWORD i;
+ if ( !ModernSkinButtonModuleIsLoaded) return 0;
+ if ( !g_CluiData.fLayered) return 0;
+ if ( !g_pCachedWindow) return 0;
+ if ( !g_pCachedWindow->hImageDC || !g_pCachedWindow->hBackDC) return 0;
+ if ( !(l || r || t || b))
+ {
+ for (i=0; i < ButtonsCount; i++)
+ {
+ if (pcli->hwndContactList && Buttons[i].hwnd != NULL)
+ {
+ //TODO: Erase button
+ BitBlt(g_pCachedWindow->hImageDC,Buttons[i].bct->Left,Buttons[i].bct->Top,Buttons[i].bct->Right-Buttons[i].bct->Left,Buttons[i].bct->Bottom-Buttons[i].bct->Top,
+ g_pCachedWindow->hBackDC,Buttons[i].bct->Left,Buttons[i].bct->Top,SRCCOPY);
+ }
+ }
+ }
+ else
+ {
+ BitBlt(g_pCachedWindow->hImageDC,l,t,r-l,b-t, g_pCachedWindow->hBackDC,l,t,SRCCOPY);
+ }
+ return 0;
+}
+
+static HWND ModernSkinButtonCreateWindow(ModernSkinButtonCtrl * bct, HWND parent)
+{
+ HWND hwnd;
+
+ if (bct == NULL) return FALSE;
+ {
+ TCHAR *UnicodeID;
+ UnicodeID = mir_a2u(bct->ID);
+ hwnd = CreateWindow(_T(MODERNSKINBUTTONCLASS),UnicodeID,WS_VISIBLE|WS_CHILD,bct->Left,bct->Top,bct->Right-bct->Left,bct->Bottom-bct->Top,parent,NULL,g_hInst,NULL);
+ mir_free(UnicodeID);
+ }
+
+ bct->hwnd = hwnd;
+ bct->focus = 0;
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)bct);
+ return hwnd;
+}
+
+int ModernSkinButtonRedrawAll(HDC hdc)
+{
+ DWORD i;
+ if ( !ModernSkinButtonModuleIsLoaded) return 0;
+ g_mutex_bLockUpdating++;
+ for (i=0; i < ButtonsCount; i++)
+ {
+ if (pcli->hwndContactList && Buttons[i].hwnd == NULL)
+ Buttons[i].hwnd = ModernSkinButtonCreateWindow(Buttons[i].bct,pcli->hwndContactList);
+ ModernSkinButtonPaintWorker(Buttons[i].hwnd,0);
+ }
+ g_mutex_bLockUpdating--;
+ return 0;
+}
+
+int ModernSkinButtonDeleteAll()
+{
+ if ( !ModernSkinButtonModuleIsLoaded)
+ return 0;
+
+ for (size_t i=0; i < ButtonsCount; i++)
+ if (Buttons[i].hwnd)
+ DestroyWindow(Buttons[i].hwnd);
+
+ mir_free_and_nil(Buttons);
+ ButtonsCount = 0;
+ return 0;
+}
+
+int ModernSkinButton_ReposButtons(HWND parent, BYTE draw, RECT * r)
+{
+ DWORD i;
+ RECT rc;
+ RECT clr;
+ RECT rd;
+ BOOL altDraw = FALSE;
+ static SIZE oldWndSize = {0};
+ if ( !ModernSkinButtonModuleIsLoaded) return 0;
+ GetWindowRect(parent,&rd);
+ GetClientRect(parent,&clr);
+ if ( !r)
+ GetWindowRect(parent,&rc);
+ else
+ rc = *r;
+ if (g_CluiData.fLayered && ( draw & SBRF_DO_ALT_DRAW ))
+ {
+ int sx,sy;
+ sx = rd.right-rd.left;
+ sy = rd.bottom-rd.top;
+ if (sx != oldWndSize.cx || sy != oldWndSize.cy)
+ altDraw = TRUE;//EraseButtons();
+ oldWndSize.cx = sx;
+ oldWndSize.cy = sy;
+ }
+
+ OffsetRect(&rc,-rc.left,-rc.top);
+ rc.right = rc.left+(clr.right-clr.left);
+ rc.bottom = rc.top+(clr.bottom-clr.top);
+ for (i=0; i < ButtonsCount; i++)
+ {
+ int l,r,b,t;
+ RECT oldRect = {0};
+ int sbFlags = Buttons[i].ConstrainPositionFrom;
+ if (parent && Buttons[i].hwnd == NULL)
+ {
+ Buttons[i].hwnd = ModernSkinButtonCreateWindow(Buttons[i].bct,parent);
+ altDraw = FALSE;
+ }
+
+ l = ( sbFlags & SBF_ALIGN_TL_RIGHT ) ? ( rc.right + Buttons[i].OrL ) :
+ ( sbFlags & SBF_ALIGN_TL_HCENTER ) ? ( _center_h( &rc ) + Buttons[i].OrL ) :
+ ( rc.left + Buttons[i].OrL );
+
+ t = ( sbFlags & SBF_ALIGN_TL_BOTTOM ) ? ( rc.bottom + Buttons[i].OrT ) :
+ ( sbFlags & SBF_ALIGN_TL_VCENTER ) ? ( _center_v( &rc ) + Buttons[i].OrT ) :
+ ( rc.top + Buttons[i].OrT );
+
+ r = ( sbFlags & SBF_ALIGN_BR_RIGHT ) ? ( rc.right + Buttons[i].OrR ) :
+ ( sbFlags & SBF_ALIGN_BR_HCENTER ) ? ( _center_h( &rc) + Buttons[i].OrR ) :
+ ( rc.left + Buttons[i].OrR );
+
+ b = ( sbFlags & SBF_ALIGN_BR_BOTTOM ) ? ( rc.bottom + Buttons[i].OrB ) :
+ ( sbFlags & SBF_ALIGN_BR_VCENTER ) ? ( _center_v( &rc ) + Buttons[i].OrB ) :
+ ( rc.top + Buttons[i].OrB );
+
+ SetWindowPos(Buttons[i].hwnd,HWND_TOP,l,t,r-l,b-t,0);
+ if ( (rc.right-rc.left < Buttons[i].minW /* && Buttons[i].minW != 0*/)
+ || (rc.bottom-rc.top < Buttons[i].minH /* && Buttons[i].minH != 0*/))
+ CLUI_ShowWindowMod(Buttons[i].hwnd,SW_HIDE);
+ else
+ CLUI_ShowWindowMod(Buttons[i].hwnd,SW_SHOW);
+ if ((1 || altDraw) &&
+ (Buttons[i].bct->Left != l ||
+ Buttons[i].bct->Top != t ||
+ Buttons[i].bct->Right != r ||
+ Buttons[i].bct->Bottom != b))
+ {
+ //Need to erase in old location
+ ModernSkinButtonErase(Buttons[i].bct->Left,Buttons[i].bct->Top,Buttons[i].bct->Right,Buttons[i].bct->Bottom);
+ }
+
+ Buttons[i].bct->Left = l;
+ Buttons[i].bct->Top = t;
+ Buttons[i].bct->Right = r;
+ Buttons[i].bct->Bottom = b;
+
+
+ }
+ if ( draw & SBRF_DO_REDRAW_ALL ) ModernSkinButtonRedrawAll(0);
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_skineditor.cpp b/plugins/Clist_modern/src/modern_skineditor.cpp
new file mode 100644
index 0000000000..36763ef5d5
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_skineditor.cpp
@@ -0,0 +1,841 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "m_clc.h"
+#include "io.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_sync.h"
+
+typedef struct _OPT_OBJECT_DATA
+{
+ char * szName;
+ char * szPath;
+ char * szValue;
+ char * szTempValue;
+} OPT_OBJECT_DATA;
+
+static char *gl_Mask = NULL;
+HWND gl_Dlg = NULL;
+int gl_controlID = 0;
+int EnableGroup(HWND hwndDlg, HWND first, BOOL bEnable);
+int ShowGroup(HWND hwndDlg, HWND first, BOOL bEnable);
+BOOL glOtherSkinWasLoaded = FALSE;
+BYTE glSkinWasModified = 0; //1- but not applied, 2-stored to DB
+HTREEITEM FindChild(HWND hTree, HTREEITEM Parent, char * Caption)
+{
+ HTREEITEM res = NULL, tmp = NULL;
+ if (Parent)
+ tmp = TreeView_GetChild(hTree,Parent);
+ else
+ tmp = TreeView_GetRoot(hTree);
+ while (tmp)
+ {
+ TVITEMA tvi;
+ char buf[255];
+ tvi.hItem = tmp;
+ tvi.mask = TVIF_TEXT|TVIF_HANDLE;
+ tvi.pszText = (LPSTR)&buf;
+ tvi.cchTextMax = 254;
+ TreeView_GetItemA(hTree,&tvi);
+ if (mir_bool_strcmpi(Caption,tvi.pszText))
+ return tmp;
+ tmp = TreeView_GetNextSibling(hTree,tmp);
+ }
+ return tmp;
+}
+
+int TreeAddObject(HWND hwndDlg, int ID, OPT_OBJECT_DATA * data)
+{
+ HTREEITEM rootItem = NULL;
+ HTREEITEM cItem = NULL;
+ char * path;
+ char * ptr;
+ char * ptrE;
+ char buf[255];
+ BOOL ext = FALSE;
+ path = data->szPath?mir_strdup(data->szPath):(data->szName[1] == '$')?mir_strdup((data->szName)+2):NULL;
+ if ( !path) {
+ mir_snprintf(buf,SIZEOF(buf),"$(other)/%s",(data->szName)+1);
+ path = mir_strdup(buf);
+ }
+
+ ptr = path;
+ ptrE = path;
+ do
+ {
+
+ while (*ptrE != '/' && *ptrE != '\0') ptrE++;
+ if (*ptrE == '/')
+ {
+ *ptrE = '\0';
+ ptrE++;
+ // find item if not - create;
+ {
+ cItem = FindChild(GetDlgItem(hwndDlg,ID),rootItem,ptr);
+ if ( !cItem) // not found - create node
+ {
+ TVINSERTSTRUCTA tvis;
+ tvis.hParent = rootItem;
+ tvis.hInsertAfter = TVI_SORT;
+ tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_PARAM;
+ tvis.item.pszText = ptr;
+ tvis.item.lParam = (LPARAM)NULL;
+ cItem = TreeView_InsertItemA(GetDlgItem(hwndDlg,ID),&tvis);
+
+ }
+ rootItem = cItem;
+ }
+ ptr = ptrE;
+ }
+ else ext = TRUE;
+ }while (!ext);
+
+ //Insert item node
+ {
+ TVINSERTSTRUCTA tvis;
+ tvis.hParent = rootItem;
+ tvis.hInsertAfter = TVI_SORT;
+ tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_PARAM;
+ tvis.item.pszText = ptr;
+ tvis.item.lParam = (LPARAM)data;
+ TreeView_InsertItemA(GetDlgItem(hwndDlg,ID),&tvis);
+ }
+ mir_free(path);
+ return 0;
+}
+
+int enumDB_SkinObjectsForEditorProc(const char *szSetting,LPARAM lParam)
+{
+ if (wildcmp((char *)szSetting,gl_Mask,0) || wildcmp((char *)szSetting,"$*",0))
+ {
+ char * value;
+ char *desc;
+ char *descKey;
+ descKey = mir_strdup(szSetting);
+ descKey[0] = '%';
+ value = db_get_sa(NULL,SKIN,szSetting);
+ desc = db_get_sa(NULL,SKIN,descKey);
+ if (wildcmp(value,"?lyph*",0))
+ {
+ OPT_OBJECT_DATA * a = (OPT_OBJECT_DATA*)mir_alloc(sizeof(OPT_OBJECT_DATA));
+ a->szPath = desc;
+ a->szName = mir_strdup(szSetting);
+ a->szValue = value;
+ a->szTempValue = NULL;
+ TreeAddObject(gl_Dlg,gl_controlID,a);
+ }
+ else {
+ mir_free(value);
+ mir_free(desc);
+ }
+ mir_free(descKey);
+ }
+ return 0;
+}
+
+int FillObjectTree(HWND hwndDlg, int ObjectTreeID, char * wildmask)
+{
+ DBCONTACTENUMSETTINGS dbces;
+ gl_Dlg = hwndDlg;
+ gl_controlID = ObjectTreeID;
+ gl_Mask = wildmask;
+ dbces.pfnEnumProc = enumDB_SkinObjectsForEditorProc;
+ dbces.szModule = SKIN;
+ dbces.ofsSettings = 0;
+ CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces);
+ return 0;
+}
+TCHAR *TYPES[] = {_T("- Empty - (do not draw this object)"),_T("Solid fill object"),_T("Image (draw image)"),_T("Fragment (draw portion of image)")};
+TCHAR *FITMODES[] = {_T("Stretch Both directions"),_T("Stretch Vertical, Tile Horizontal"),_T("Tile Vertical, Stretch Horizontal"),_T("Tile Both directions")};
+
+void SetAppropriateGroups(HWND hwndDlg, int Type)
+//str contains default values
+{
+ switch (Type)
+ {
+ case -1:
+ {
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_1),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_COLOUR),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_ALPHA),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_2),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_3),FALSE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_S_SIZE),FALSE);
+ }
+ break;
+ case 0:
+ {
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_1),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_COLOUR),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_ALPHA),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_2),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_3),FALSE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_S_SIZE),FALSE);
+ }
+ break;
+ case 1:
+ {
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_1),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_COLOUR),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_ALPHA),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_2),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_3),FALSE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_S_SIZE),FALSE);
+ //Set Color and alpha
+ }
+ break;
+ case 2:
+ {
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_1),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_COLOUR),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_ALPHA),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_2),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_3),FALSE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_S_SIZE),TRUE);
+ //Set alpha, image, margins etc.
+ }
+ break;
+ case 3:
+ {
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_1),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_COLOUR),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_ALPHA),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_2),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_3),TRUE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_S_SIZE),TRUE);
+ //Set alpha, image, margins etc.
+ }
+ break;
+ }
+}
+
+void SetControls(HWND hwndDlg, char * str)
+{
+ char buf[250];
+ int Type=0;
+ if ( !str)
+ {
+ SetAppropriateGroups(hwndDlg,-1);
+ return;
+ }
+ GetParamN(str,buf,SIZEOF(buf),1,',',TRUE);
+ if (mir_bool_strcmpi(buf,"Solid")) Type=1;
+ else if (mir_bool_strcmpi(buf,"Image")) Type=2;
+ else if (mir_bool_strcmpi(buf,"Fragment")) Type=3;
+ SendDlgItemMessage(hwndDlg,IDC_TYPE,CB_SETCURSEL,(WPARAM)Type,(LPARAM)0);
+ SetAppropriateGroups(hwndDlg,Type);
+ switch (Type)
+ {
+ case 1:
+ {
+ int r,g,b,a;
+ r = g = b = 200;
+ a = 255;
+ r = atoi(GetParamN(str,buf,SIZEOF(buf),2,',',TRUE));
+ g = atoi(GetParamN(str,buf,SIZEOF(buf),3,',',TRUE));
+ b = atoi(GetParamN(str,buf,SIZEOF(buf),4,',',TRUE));
+ a = atoi(GetParamN(str,buf,SIZEOF(buf),5,',',TRUE));
+ SendDlgItemMessage(hwndDlg,IDC_COLOR,CPM_SETCOLOUR,(WPARAM)0,(LPARAM)RGB(r,g,b));
+ SendDlgItemMessage(hwndDlg,IDC_COLOR,CPM_SETDEFAULTCOLOUR,(WPARAM)0,(LPARAM)RGB(r,g,b));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_SETPOS,0,MAKELONG(a,0));
+ }
+ break;
+ case 2:
+ {
+ int a;
+ int l,t,r,b;
+ int fitmode = 0;
+ l = t = r = b = 0;
+ a = 255;
+
+ l = atoi(GetParamN(str,buf,SIZEOF(buf),4,',',TRUE));
+ t = atoi(GetParamN(str,buf,SIZEOF(buf),5,',',TRUE));
+ r = atoi(GetParamN(str,buf,SIZEOF(buf),6,',',TRUE));
+ b = atoi(GetParamN(str,buf,SIZEOF(buf),7,',',TRUE));
+ a = atoi(GetParamN(str,buf,SIZEOF(buf),8,',',TRUE));
+
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_SETPOS,0,MAKELONG(a,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_LEFT,UDM_SETPOS,0,MAKELONG(l,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_TOP,UDM_SETPOS,0,MAKELONG(t,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_RIGHT,UDM_SETPOS,0,MAKELONG(r,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_BOTTOM,UDM_SETPOS,0,MAKELONG(b,0));
+
+ GetParamN(str,buf,SIZEOF(buf),2,',',TRUE);
+ SendDlgItemMessageA(hwndDlg,IDC_FILE,WM_SETTEXT,0,(LPARAM)buf);
+
+ GetParamN(str,buf,SIZEOF(buf),3,',',TRUE);
+ if (mir_bool_strcmpi(buf,"TileBoth")) fitmode = FM_TILE_BOTH;
+ else if (mir_bool_strcmpi(buf,"TileVert")) fitmode = FM_TILE_VERT;
+ else if (mir_bool_strcmpi(buf,"TileHorz")) fitmode = FM_TILE_HORZ;
+ else fitmode = 0;
+ SendDlgItemMessage(hwndDlg,IDC_FIT,CB_SETCURSEL,(WPARAM)fitmode,(LPARAM)0);
+ }
+
+ break;
+ case 3:
+ {
+ int a;
+ int l,t,r,b;
+ int x,y,w,h;
+ int fitmode = 0;
+ l = t = r = b = 0;
+ x = y = w = h = 0;
+ a = 255;
+
+ x = atoi(GetParamN(str,buf,SIZEOF(buf),3,',',TRUE));
+ y = atoi(GetParamN(str,buf,SIZEOF(buf),4,',',TRUE));
+ w = atoi(GetParamN(str,buf,SIZEOF(buf),5,',',TRUE));
+ h = atoi(GetParamN(str,buf,SIZEOF(buf),6,',',TRUE));
+
+ l = atoi(GetParamN(str,buf,SIZEOF(buf),8,',',TRUE));
+ t = atoi(GetParamN(str,buf,SIZEOF(buf),9,',',TRUE));
+ r = atoi(GetParamN(str,buf,SIZEOF(buf),10,',',TRUE));
+ b = atoi(GetParamN(str,buf,SIZEOF(buf),11,',',TRUE));
+ a = atoi(GetParamN(str,buf,SIZEOF(buf),12,',',TRUE));
+
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_SETPOS,0,MAKELONG(a,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_LEFT,UDM_SETPOS,0,MAKELONG(l,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_TOP,UDM_SETPOS,0,MAKELONG(t,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_RIGHT,UDM_SETPOS,0,MAKELONG(r,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_BOTTOM,UDM_SETPOS,0,MAKELONG(b,0));
+
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_POSLEFT,UDM_SETPOS,0,MAKELONG(x,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_POSTOP,UDM_SETPOS,0,MAKELONG(y,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_WIDTH,UDM_SETPOS,0,MAKELONG(w,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_HEIGHT,UDM_SETPOS,0,MAKELONG(h,0));
+
+ GetParamN(str,buf,SIZEOF(buf),2,',',TRUE);
+ SendDlgItemMessageA(hwndDlg,IDC_FILE,WM_SETTEXT,0,(LPARAM)buf);
+
+ GetParamN(str,buf,SIZEOF(buf),7,',',TRUE);
+ if (mir_bool_strcmpi(buf,"TileBoth")) fitmode = FM_TILE_BOTH;
+ else if (mir_bool_strcmpi(buf,"TileVert")) fitmode = FM_TILE_VERT;
+ else if (mir_bool_strcmpi(buf,"TileHorz")) fitmode = FM_TILE_HORZ;
+ else fitmode = 0;
+ SendDlgItemMessage(hwndDlg,IDC_FIT,CB_SETCURSEL,(WPARAM)fitmode,(LPARAM)0);
+ }
+
+ break;
+ }
+}
+
+
+
+int GetShortFileName(char * FullFile)
+{
+ char buf[MAX_PATH] = {0};
+ char * f = strrchr(FullFile,'\\');
+ char * file = f?mir_strdup(f+1):0;
+ if ( !file) return 0;
+ ske_GetFullFilename(buf,file,0,TRUE);
+ if (mir_bool_strcmpi(buf,FullFile))
+ {
+ _snprintf(FullFile,MAX_PATH,"%s",file);
+ mir_free(file);
+ return 1; //skin folder relative
+ }
+
+ CallService(MS_UTILS_PATHTORELATIVE,(WPARAM)FullFile,(LPARAM)buf);
+ if (buf[0] != '\\' && buf[1] != ':')
+ _snprintf(FullFile,MAX_PATH,"\\%s",buf);
+ else
+ _snprintf(FullFile,MAX_PATH,"%s",buf);
+
+ mir_free(file);
+ return 2; //mirand folder relative
+}
+
+char * MadeString(HWND hwndDlg)
+{
+ char buf[MAX_PATH*2] = {0};
+ int i = SendDlgItemMessage(hwndDlg,IDC_TYPE,CB_GETCURSEL,(WPARAM)0,(LPARAM)0);
+ switch (i)
+ {
+ case 0:
+ mir_snprintf(buf,SIZEOF(buf),"Glyph,Skip");
+ break;
+ case 1:
+ {
+ BYTE a;
+ DWORD col;
+ a = (BYTE)SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_GETPOS,0,0);
+ col = (DWORD)SendDlgItemMessage(hwndDlg,IDC_COLOR,CPM_GETCOLOUR,(WPARAM)0,(LPARAM)0);
+ mir_snprintf(buf,SIZEOF(buf),"Glyph,Solid,%d,%d,%d,%d",GetRValue(col),GetGValue(col),GetBValue(col),a);
+ }
+ break;
+ case 2:
+ {
+ BYTE a;
+ WORD l,t,b,r;
+ char buf_name[MAX_PATH] = {0};
+ int i=0;
+ a = (BYTE)SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_GETPOS,0,0);
+ l = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_LEFT,UDM_GETPOS,0,0);
+ t = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_TOP,UDM_GETPOS,0,0);
+ r = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_RIGHT,UDM_GETPOS,0,0);
+ b = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_BOTTOM,UDM_GETPOS,0,0);
+ SendDlgItemMessageA(hwndDlg,IDC_FILE,WM_GETTEXT,(WPARAM)MAX_PATH,(LPARAM)buf_name);
+ i = SendDlgItemMessage(hwndDlg,IDC_FIT,CB_GETCURSEL,0,0);
+ mir_snprintf(buf,SIZEOF(buf),"Glyph,Image,%s,%s,%d,%d,%d,%d,%d",buf_name,
+ //fitmode
+ (i == FM_TILE_BOTH)?"TileBoth":
+ (i == FM_TILE_VERT)?"TileVert":
+ (i == FM_TILE_HORZ)?"TileHorz":"StretchBoth",
+ l,t,r,b,a);
+ }
+ break;
+ case 3:
+ {
+ BYTE a;
+ WORD l,t,b,r;
+ WORD x,y,w,h;
+ char buf_name[MAX_PATH] = {0};
+ int i=0;
+ a = (BYTE)SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_GETPOS,0,0);
+ l = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_LEFT,UDM_GETPOS,0,0);
+ t = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_TOP,UDM_GETPOS,0,0);
+ r = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_RIGHT,UDM_GETPOS,0,0);
+ b = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_BOTTOM,UDM_GETPOS,0,0);
+
+ x = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_POSLEFT,UDM_GETPOS,0,0);
+ y = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_POSTOP,UDM_GETPOS,0,0);
+
+ w = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_WIDTH,UDM_GETPOS,0,0);
+ h = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_HEIGHT,UDM_GETPOS,0,0);
+
+ SendDlgItemMessageA(hwndDlg,IDC_FILE,WM_GETTEXT,(WPARAM)MAX_PATH,(LPARAM)buf_name);
+ i = SendDlgItemMessage(hwndDlg,IDC_FIT,CB_GETCURSEL,0,0);
+ mir_snprintf(buf,SIZEOF(buf),"Glyph,Fragment,%s,%d,%d,%d,%d,%s,%d,%d,%d,%d,%d",buf_name,x,y,w,h,
+ //fitmode
+ (i == FM_TILE_BOTH)?"TileBoth":
+ (i == FM_TILE_VERT)?"TileVert":
+ (i == FM_TILE_HORZ)?"TileHorz":"StretchBoth",
+ l,t,r,b,a);
+ }
+ break;
+ }
+ if (buf[0] != '\0') return mir_strdup(buf);
+ return 0;
+}
+void UpdateInfo(HWND hwndDlg)
+{
+ char *b = MadeString(hwndDlg);
+ if ( !b)
+ {
+ SendDlgItemMessageA(hwndDlg,IDC_EDIT1,WM_SETTEXT,0,(LPARAM)"");
+ return;
+ }
+ SendDlgItemMessageA(hwndDlg,IDC_EDIT1,WM_SETTEXT,0,(LPARAM)b);
+ {
+ OPT_OBJECT_DATA *sd = NULL;
+ HTREEITEM hti = TreeView_GetSelection(GetDlgItem(hwndDlg,IDC_OBJECT_TREE));
+ if (hti)
+ {
+ TVITEMA tvi = {0};
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ TreeView_GetItem(GetDlgItem(hwndDlg,IDC_OBJECT_TREE),&tvi);
+ sd = (OPT_OBJECT_DATA*)(tvi.lParam);
+ if (sd)
+ {
+ mir_free(sd->szValue);
+ sd->szValue = mir_strdup(b);
+ }
+ }
+ }
+ mir_free(b);
+ glSkinWasModified = 1;
+}
+
+void StoreTreeNode(HWND hTree, HTREEITEM node, char * section)
+{
+ HTREEITEM tmp;
+ tmp = node;
+ while (tmp)
+ {
+ HTREEITEM tmp2 = NULL;
+ TVITEMA tvi;
+ char buf[255];
+ tvi.hItem = tmp;
+ tvi.mask = TVIF_TEXT|TVIF_HANDLE;
+ tvi.pszText = (LPSTR)&buf;
+ tvi.cchTextMax = 254;
+ TreeView_GetItemA(hTree,&tvi);
+ if (tvi.lParam)
+ {
+ OPT_OBJECT_DATA * dat = (OPT_OBJECT_DATA*)(tvi.lParam);
+ if (dat->szName && dat->szValue)
+ db_set_s(NULL,section,dat->szName,dat->szValue);
+ }
+ tmp2 = TreeView_GetChild(hTree,tmp);
+ if (tmp2) StoreTreeNode(hTree,tmp2,section);
+ tmp = TreeView_GetNextSibling(hTree,tmp);
+ }
+ return;
+}
+
+void StoreTreeToDB(HWND hTree, char * section)
+{
+ HTREEITEM tmp = NULL;
+ tmp = TreeView_GetRoot(hTree);
+ StoreTreeNode(hTree,tmp,section);
+ db_set_b(NULL,section,"Modified",1);
+ glSkinWasModified = 2;
+}
+static BOOL fileChanged = FALSE;
+static char * object_clipboard = NULL;
+int GetFileSizes(HWND hwndDlg)
+{
+ char buf[MAX_PATH];
+ SIZE sz = {0};
+ SendDlgItemMessageA(hwndDlg,IDC_FILE,WM_GETTEXT,(WPARAM)MAX_PATH,(LPARAM)buf);
+ ske_GetFullFilename(buf,buf,0,TRUE);
+ {
+ HBITMAP hbmp = ske_LoadGlyphImage(buf);
+ if (hbmp)
+ {
+ BITMAP bm = {0};
+ GetObject(hbmp,sizeof(BITMAP),&bm);
+ sz.cx = bm.bmWidth;
+ sz.cy = bm.bmHeight;
+ ske_UnloadGlyphImage(hbmp);
+ }
+ }
+ _snprintf(buf, MAX_PATH, "%s %d x %d %s",Translate("Image size is"),sz.cx, sz.cy, Translate("pixels"));
+ SendDlgItemMessageA(hwndDlg,IDC_S_SIZE,WM_SETTEXT,0,(LPARAM)buf);
+ return 0;
+}
+
+INT_PTR CALLBACK DlgSkinEditorOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_WINDOWPOSCHANGED:
+ {
+ WINDOWPOS * wp = (WINDOWPOS *)lParam;
+ if (lParam && wp->flags&SWP_SHOWWINDOW)
+ {
+ if (glOtherSkinWasLoaded)
+ {
+ TreeView_DeleteAllItems(GetDlgItem(hwndDlg,IDC_OBJECT_TREE));
+ FillObjectTree(hwndDlg,IDC_OBJECT_TREE,"$$*");
+ glSkinWasModified = 0;
+ glOtherSkinWasLoaded = FALSE;
+ }
+ }
+ break;
+ }
+
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ FillObjectTree(hwndDlg,IDC_OBJECT_TREE,"$$*");
+ { //Fill types combo
+ int i=0;
+ for (i=0; i < SIZEOF(TYPES); i++)
+ SendDlgItemMessage(hwndDlg,IDC_TYPE,CB_ADDSTRING,0,(LPARAM)TranslateTS(TYPES[i]));
+ }
+ { //Fill fit combo
+ int i=0;
+ for (i=0; i < SIZEOF(FITMODES); i++)
+ SendDlgItemMessage(hwndDlg,IDC_FIT,CB_ADDSTRING,0,(LPARAM)TranslateTS(FITMODES[i]));
+ }
+ //SPIN Ranges
+ {
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_SETRANGE,0,MAKELONG(255,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_SETPOS,0,MAKELONG(255,0));
+
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_TOP,UDM_SETRANGE,0,MAKELONG(900,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_LEFT,UDM_SETRANGE,0,MAKELONG(900,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_BOTTOM,UDM_SETRANGE,0,MAKELONG(900,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_RIGHT,UDM_SETRANGE,0,MAKELONG(900,0));
+
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_POSLEFT,UDM_SETRANGE,0,MAKELONG(1000,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_POSTOP,UDM_SETRANGE,0,MAKELONG(1000,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_WIDTH,UDM_SETRANGE,0,MAKELONG(1000,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_HEIGHT,UDM_SETRANGE,0,MAKELONG(1000,0));
+ }
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_1),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_COLOUR),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_ALPHA),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_2),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_3),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PASTE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_COPY),FALSE);
+ glSkinWasModified = 0;
+ glOtherSkinWasLoaded = FALSE;
+ break;
+
+ case WM_COMMAND:
+ {
+ if (LOWORD(wParam) == IDC_TYPE)
+ {
+ if (HIWORD(wParam) == CBN_SELCHANGE)
+ {
+ int i = SendDlgItemMessage(hwndDlg,IDC_TYPE,CB_GETCURSEL,(WPARAM)0,(LPARAM)0);
+ //if (IsWindowEnabled(GetDlgItem(hwndDlg,IDC_TYPE)))
+ SetAppropriateGroups(hwndDlg,i);
+ if (GetFocus() == GetDlgItem(hwndDlg,IDC_TYPE))
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ UpdateInfo(hwndDlg);
+ break;
+ }
+ }
+ else if (LOWORD(wParam) == IDC_COPY)
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ mir_free_and_nil(object_clipboard);
+
+ OPT_OBJECT_DATA *sd = NULL;
+ HTREEITEM hti = TreeView_GetSelection(GetDlgItem(hwndDlg,IDC_OBJECT_TREE));
+ if (hti != 0)
+ {
+ TVITEM tvi = {0};
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ TreeView_GetItem(GetDlgItem(hwndDlg,IDC_OBJECT_TREE),&tvi);
+ sd = (OPT_OBJECT_DATA*)(tvi.lParam);
+ }
+ if (sd && sd->szValue)
+ object_clipboard = mir_strdup(sd->szValue);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PASTE),object_clipboard != NULL);
+ return 0;
+ }
+ }
+ else if (LOWORD(wParam) == IDC_PASTE)
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ if (object_clipboard)
+ SetControls(hwndDlg, object_clipboard);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ UpdateInfo(hwndDlg);
+ return 0;
+ }
+ }
+ else if (LOWORD(wParam) == IDC_COLOR)
+ {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ UpdateInfo(hwndDlg);
+ }
+ else if (LOWORD(wParam) == IDC_BROWSE)
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ {
+ char str[MAX_PATH] = {0};
+ OPENFILENAMEA ofn = {0};
+ char filter[512] = {0};
+ int res = 0;
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = hwndDlg;
+ ofn.hInstance = NULL;
+ ofn.lpstrFilter = "Images (*.png,*.jpg,*.bmp,*.gif,*.tga)\0*.png;*.jpg;*.jpeg;*.bmp;*.gif;*.tga\0All files (*.*)\0*.*\0\0";
+ ofn.Flags = (OFN_FILEMUSTEXIST | OFN_HIDEREADONLY);
+ SendDlgItemMessageA(hwndDlg,IDC_FILE,WM_GETTEXT,(WPARAM)SIZEOF(str),(LPARAM)str);
+ if (str[0] == '\0' || strchr(str,'%'))
+ {
+ ofn.Flags |= OFN_NOVALIDATE;
+ str[0] = '\0';
+ }
+ else
+ {
+ ske_GetFullFilename(str,str,(char*)0,TRUE);
+ }
+ ofn.lpstrFile = str;
+
+ ofn.nMaxFile = SIZEOF(str);
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.lpstrDefExt = "*.*";
+ res = GetOpenFileNameA(&ofn);
+ if (res) {
+ GetShortFileName(ofn.lpstrFile);
+ SendDlgItemMessageA(hwndDlg,IDC_FILE,WM_SETTEXT,(WPARAM)0,(LPARAM)ofn.lpstrFile);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ UpdateInfo(hwndDlg);
+ }
+ }
+ }
+ }
+ else if (LOWORD(wParam) == IDC_FILE)
+ {
+ if (HIWORD(wParam) == EN_CHANGE)
+ {
+ fileChanged = TRUE;
+ if ((HWND)lParam != GetFocus())
+ {
+ GetFileSizes(hwndDlg);
+ fileChanged = FALSE;
+ }
+ }
+ else if (HIWORD(wParam) == EN_KILLFOCUS)
+ {
+ if (fileChanged)
+ {
+ GetFileSizes(hwndDlg);
+ fileChanged = FALSE;
+ }
+ }
+ }
+ else if ((
+ (LOWORD(wParam) == IDC_E_TOP
+ || LOWORD(wParam) == IDC_E_BOTTOM
+ || LOWORD(wParam) == IDC_E_LEFT
+ || LOWORD(wParam) == IDC_E_RIGHT
+ || LOWORD(wParam) == IDC_E_X
+ || LOWORD(wParam) == IDC_E_Y
+ || LOWORD(wParam) == IDC_E_W
+ || LOWORD(wParam) == IDC_E_H
+ || LOWORD(wParam) == IDC_EDIT_ALPHA
+ )
+ && HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()))
+ {
+ return 0;
+ }
+ else if (LOWORD(wParam) != IDC_EDIT1)
+ {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ UpdateInfo(hwndDlg);
+ }
+ //check (LOWORD(wParam))
+ //SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case IDC_OBJECT_TREE:
+ {
+ //Save existed object
+ //Change to new object
+ NMTREEVIEWA * nmtv = (NMTREEVIEWA *) lParam;
+ if ( !nmtv) return 0;
+ if (nmtv->hdr.code == TVN_SELCHANGEDA || nmtv->hdr.code == TVN_SELCHANGEDW)
+ {
+ if (nmtv->itemOld.lParam)
+ {
+ OPT_OBJECT_DATA * dataOld = (OPT_OBJECT_DATA*)nmtv->itemOld.lParam;
+ if (dataOld->szValue) {
+ mir_free(dataOld->szValue);
+ dataOld->szValue = MadeString(hwndDlg);
+ }
+ }
+ if (nmtv->itemNew.lParam)
+ {
+ OPT_OBJECT_DATA * data = (OPT_OBJECT_DATA*)nmtv->itemNew.lParam;
+ char buf[255];
+
+ mir_snprintf(buf,SIZEOF(buf),"%s = %s",data->szName, data->szValue);
+ SendDlgItemMessageA(hwndDlg,IDC_EDIT1,WM_SETTEXT,0,(LPARAM)buf);
+ SetControls(hwndDlg,data->szValue);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_COPY),TRUE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PASTE),object_clipboard != NULL);
+ }
+ else
+ {
+ SendDlgItemMessageA(hwndDlg,IDC_EDIT1,WM_SETTEXT,0,(LPARAM)"");
+ SetControls(hwndDlg,NULL);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_COPY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PASTE),FALSE);
+ }
+
+ }
+ else if (nmtv->hdr.code == TVN_DELETEITEMA)
+ {
+ OPT_OBJECT_DATA * dataOld = (OPT_OBJECT_DATA*)nmtv->itemOld.lParam;
+ if (dataOld) {
+ mir_free_and_nil(dataOld->szName);
+ mir_free_and_nil(dataOld->szPath);
+ mir_free_and_nil(dataOld->szTempValue);
+ mir_free_and_nil(dataOld->szValue);
+ }
+ }
+ return 0;
+ }
+
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ if ( !glOtherSkinWasLoaded) //store only if skin is same
+ {
+ StoreTreeToDB(GetDlgItem(hwndDlg,IDC_OBJECT_TREE),SKIN);
+ //ReloadSkin
+ ske_LoadSkinFromDB();
+ pcli->pfnClcBroadcast( INTM_RELOADOPTIONS,0,0);
+ Sync(CLUIFrames_OnClistResize_mod,0,0);
+ ske_RedrawCompleteWindow();
+ Sync(CLUIFrames_OnClistResize_mod, (WPARAM)0, (LPARAM)0);
+ {
+ HWND hwnd = pcli->hwndContactList;
+ RECT rc = {0};
+ GetWindowRect(hwnd, &rc);
+ Sync(CLUIFrames_OnMoving,hwnd,&rc);
+ }
+ return TRUE;
+ }
+ else
+ return TRUE;
+ }
+ break;
+ }
+
+ case WM_DESTROY:
+ mir_free(object_clipboard);
+ break;
+
+ }
+ return FALSE;
+}
+
+int EnableGroup(HWND hwndDlg, HWND first, BOOL bEnable)
+{
+ HWND hwnd = first;
+ BOOL exit = FALSE;
+ if ( !hwnd) return 0;
+ do
+ {
+ EnableWindow(hwnd,bEnable);
+ hwnd = GetWindow(hwnd,GW_HWNDNEXT);
+ if ( !hwnd || GetWindowLongPtr(hwnd,GWL_STYLE)&WS_GROUP) exit = TRUE;
+ }
+ while (!exit);
+ return 0;
+}
+
+int ShowGroup(HWND hwndDlg, HWND first, BOOL bEnable)
+{
+ HWND hwnd = first;
+ BOOL exit = FALSE;
+ if ( !hwnd) return 0;
+ do
+ {
+ ShowWindow(hwnd,bEnable?SW_SHOW:SW_HIDE);
+ hwnd = GetWindow(hwnd,GW_HWNDNEXT);
+ if ( !hwnd || GetWindowLongPtr(hwnd,GWL_STYLE)&WS_GROUP) exit = TRUE;
+ }
+ while (!exit);
+ return 0;
+}
+
diff --git a/plugins/Clist_modern/src/modern_skinengine.cpp b/plugins/Clist_modern/src/modern_skinengine.cpp
new file mode 100644
index 0000000000..11c8391c4d
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_skinengine.cpp
@@ -0,0 +1,4650 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+//Include
+#include "hdr/modern_commonheaders.h"
+#include <m_png.h>
+#include "m_api/m_skin_eng.h"
+#include "hdr/modern_skinselector.h"
+#include "hdr/modern_cluiframes.h"
+
+#define _EFFECTENUM_FULL_H
+#include "hdr/modern_effectenum.h"
+#undef _EFFECTENUM_FULL_H
+
+#include "hdr/modern_skinengine.h"
+#include "hdr/modern_commonprototypes.h"
+#include <shlwapi.h>
+#include "hdr/modern_sync.h"
+//Implementation
+
+/* Global variables */
+
+SKINOBJECTSLIST g_SkinObjectList = {0};
+CURRWNDIMAGEDATA * g_pCachedWindow = NULL;
+
+BOOL (WINAPI *g_proc_UpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD);
+
+BOOL g_flag_bPostWasCanceled = FALSE;
+BOOL g_flag_bFullRepaint = FALSE;
+BOOL g_mutex_bLockUpdating = FALSE;
+
+SortedList * gl_plGlyphTexts = NULL;
+SortedList * gl_plSkinFonts = NULL;
+
+/* Private module variables */
+
+static HANDLE hSkinLoadedEvent;
+
+static GLYPHIMAGE * pLoadedImages = NULL;
+static DWORD dwLoadedImagesCount = 0;
+static DWORD dwLoadedImagesAlocated = 0;
+
+static BOOL flag_bUpdateQueued = FALSE;
+static BOOL flag_bJustDrawNonFramedObjects = FALSE;
+static BOOL mutex_bLockUpdate = FALSE;
+
+static SortedList * pEffectStack = NULL;
+static SKINOBJECTSLIST * pCurrentSkin = NULL;
+static char ** pszSettingName = NULL;
+static int nArrayLen = 0;
+static char * iniCurrentSection = NULL;
+static char * szFileName = NULL;
+
+static BYTE pbGammaWeight[256] = {0};
+static BYTE pbGammaWeightAdv[256] = {0};
+static BOOL bGammaWeightFilled = FALSE;
+
+static CRITICAL_SECTION cs_SkinChanging = {0};
+
+
+/* Private module procedures */
+static BOOL ske_GetMaskBit(BYTE *line, int x);
+static INT_PTR ske_Service_AlphaTextOut(WPARAM wParam,LPARAM lParam);
+static INT_PTR ske_Service_DrawIconEx(WPARAM wParam,LPARAM lParam);
+
+static int ske_AlphaTextOut (HDC hDC, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format, DWORD ARGBcolor);
+static void ske_AddParseTextGlyphObject(char * szGlyphTextID,char * szDefineString,SKINOBJECTSLIST *Skin);
+static void ske_AddParseSkinFont(char * szFontID,char * szDefineString,SKINOBJECTSLIST *Skin);
+static int ske_DeleteAllSettingInSection(char * SectionName);
+static int ske_GetSkinFromDB(char * szSection, SKINOBJECTSLIST * Skin);
+static LPSKINOBJECTDESCRIPTOR ske_FindObject(const char * szName, BYTE objType,SKINOBJECTSLIST* Skin);
+static HBITMAP ske_LoadGlyphImageByDecoders(char * szFileName);
+static int ske_LoadSkinFromResource(BOOL bOnlyObjects);
+static void ske_PreMultiplyChanells(HBITMAP hbmp,BYTE Mult);
+static int ske_ValidateSingleFrameImage(FRAMEWND * Frame, BOOL SkipBkgBlitting);
+static INT_PTR ske_Service_UpdateFrameImage(WPARAM wParam, LPARAM lParam);
+static INT_PTR ske_Service_InvalidateFrameImage(WPARAM wParam, LPARAM lParam);
+static INT_PTR ske_Service_DrawTextWithEffect( WPARAM wParam, LPARAM lParam );
+
+//Decoders
+static HMODULE hImageDecoderModule;
+
+typedef DWORD (__stdcall *pfnImgNewDecoder)(void ** ppDecoder);
+static pfnImgNewDecoder ImgNewDecoder;
+
+typedef DWORD (__stdcall *pfnImgDeleteDecoder)(void * pDecoder);
+static pfnImgDeleteDecoder ImgDeleteDecoder;
+
+typedef DWORD (__stdcall *pfnImgNewDIBFromFile)(LPVOID /*in*/pDecoder, LPCSTR /*in*/pFileName, LPVOID /*out*/*pImg);
+static pfnImgNewDIBFromFile ImgNewDIBFromFile;
+
+typedef DWORD (__stdcall *pfnImgDeleteDIBSection)(LPVOID /*in*/pImg);
+static pfnImgDeleteDIBSection ImgDeleteDIBSection;
+
+typedef DWORD (__stdcall *pfnImgGetHandle)(LPVOID /*in*/pImg, HBITMAP /*out*/*pBitmap, LPVOID /*out*/*ppDIBBits);
+static pfnImgGetHandle ImgGetHandle;
+
+static MODERNEFFECT meCurrentEffect = {-1,{0},0,0};
+
+
+//////////////////////////////////////////////////////////////////////////
+// Ini file parser
+//////////////////////////////////////////////////////////////////////////
+IniParser::IniParser( TCHAR * tcsFileName, BYTE flags ) : _Flags( flags )
+{
+ _DoInit();
+ if ( !tcsFileName ) return;
+
+ if ( tcsFileName[0] == _T('%'))
+ {
+ //TODO: Add parser of resource filename here
+ _LoadResourceIni( g_hInst, MAKEINTRESOURCEA(IDR_MSF_DEFAULT_SKIN), "MSF");
+ return;
+ }
+
+ _hFile = _tfopen( tcsFileName, _T("r"));
+
+ if ( _hFile != NULL )
+ {
+ _eType = IT_FILE;
+ _isValid = true;
+ }
+}
+
+IniParser::IniParser( HINSTANCE hInst, const char * resourceName, const char * resourceType, BYTE flags ) : _Flags( flags )
+{
+ _DoInit();
+ _LoadResourceIni( hInst, resourceName, resourceType );
+}
+
+IniParser::~IniParser()
+{
+ mir_free( _szSection );
+ if ( _hFile ) fclose( _hFile );
+ if ( _hGlobalRes ) {
+ UnlockResource( _hGlobalRes );
+ FreeResource(_hGlobalRes);
+ }
+
+ _szSection = NULL;
+ _hGlobalRes = NULL;
+ _hFile = NULL;
+ _isValid = false;
+ _eType = IT_UNKNOWN;
+}
+
+HRESULT IniParser::Parse( ParserCallback_t pLineCallBackProc, LPARAM SecCheck )
+{
+ if ( _isValid && pLineCallBackProc )
+ {
+ _pLineCallBackProc = pLineCallBackProc;
+ _SecCheck = SecCheck;
+ switch ( _eType )
+ {
+ case IT_FILE:
+ return _DoParseFile();
+ case IT_RESOURCE:
+ return _DoParseResource();
+ }
+ }
+ return E_FAIL;
+}
+
+
+HRESULT IniParser::WriteStrToDb( const char * szSection, const char * szName, const char * szValue, IniParser * This )
+{
+ if ( This->_SecCheck)
+ {
+ //TODO check security here
+ if ( wildcmp( szSection,"Skin_Description_Section",1 )) return S_OK;
+ }
+ if (( This->_Flags == IniParser::FLAG_ONLY_OBJECTS ) && !wildcmp( szSection, DEFAULTSKINSECTION,1 ))
+ return S_OK; // skip not objects
+
+
+// if ( strlen(szValue)>0 && szValue[strlen(szValue)-1] == '\n' )
+// szValue[strlen(szValue)-1] = '\0'; //kill linefeed at the end
+
+ switch(szValue[0])
+ {
+ case 'b':
+ {
+ BYTE P;
+ P = (BYTE)atoi(szValue+1);
+ db_set_b(NULL,szSection,szName,P);
+ }
+ break;
+ case 'w':
+ {
+ WORD P;
+ P = (WORD)atoi(szValue+1);
+ db_set_w(NULL,szSection,szName,P);
+ }
+ break;
+ case 'd':
+ {
+ DWORD P;
+ P = (DWORD)atoi(szValue+1);
+ db_set_dw(NULL,szSection,szName,P);
+ }
+ break;
+ case 's':
+ db_set_s(NULL,szSection,szName,szValue+1);
+ break;
+ case 'f':
+ if (szFileName)
+ {
+ char fn[MAX_PATH] = {0};
+ char bb[MAX_PATH*2] = {0};
+ int pp, i;
+ pp = -1;
+ CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)szFileName, (LPARAM)fn);
+ {
+ for (i = strlen(fn); i >= 0; i--) if (fn[i] == '.') break;
+ if (i>0) fn[i] = '\0';
+ }
+ _snprintf(bb,SIZEOF(bb),"%s\\%s",fn,szValue+1);
+ db_set_s(NULL,szSection,szName,bb);
+ }
+ break;
+ }
+ return S_OK;
+}
+int IniParser::GetSkinFolder( IN const TCHAR * szFileName, OUT TCHAR * pszFolderName )
+{
+ TCHAR *pszPos;
+ TCHAR *szBuff;
+
+ szBuff = mir_tstrdup( szFileName );
+ pszPos = szBuff + _tcslen( szBuff );
+ while ( pszPos > szBuff && *pszPos != _T('.')) { pszPos--; }
+ *pszPos = _T('\0');
+ _tcscpy( pszFolderName, szBuff );
+
+ TCHAR custom_folder[MAX_PATH];
+ TCHAR cus[MAX_PATH];
+ TCHAR *b3;
+ _tcscpy( custom_folder, pszFolderName );
+ b3 = custom_folder + _tcslen( custom_folder );
+ while ( b3 > custom_folder && *b3 != _T('\\')) { b3--; }
+ *b3 = _T('\0');
+
+ GetPrivateProfileString(_T("Skin_Description_Section"),_T("SkinFolder"),_T(""),cus,SIZEOF(custom_folder),szFileName);
+ if ( cus && _tcslen(cus)>0)
+ _sntprintf(pszFolderName,MAX_PATH,_T("%s\\%s"),custom_folder,cus);
+
+ mir_free(szBuff);
+ CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)pszFolderName, (LPARAM)pszFolderName);
+ return 0;
+}
+
+void IniParser::_DoInit()
+{
+ _isValid = false;
+ _eType = IT_UNKNOWN;
+ _szSection = NULL;
+ _hFile = NULL;
+ _hGlobalRes = NULL;
+ _dwSizeOfRes = 0;
+ _pPosition = NULL;
+ _pLineCallBackProc = NULL;
+ _SecCheck = 0;
+
+}
+
+void IniParser::_LoadResourceIni( HINSTANCE hInst, const char * resourceName, const char * resourceType )
+{
+
+ if ( _eType != IT_UNKNOWN ) return;
+
+ HRSRC hRSrc = FindResourceA( hInst, resourceName, resourceType );
+ if ( !hRSrc ) return;
+
+ _hGlobalRes = LoadResource( hInst, hRSrc );
+ if ( !_hGlobalRes ) return;
+
+ _dwSizeOfRes = SizeofResource( hInst, hRSrc );
+ _pPosition = (char*) LockResource( _hGlobalRes );
+
+ _isValid = true;
+ _eType = IT_RESOURCE;
+
+}
+
+
+
+HRESULT IniParser::_DoParseFile()
+{
+ char szLine[MAX_LINE_LEN];
+ _nLine = 0;
+ while ( fgets( szLine, SIZEOF(szLine), _hFile ) != NULL )
+ {
+ size_t len = 0;
+ char * pLine = (char*)_RemoveTailings( szLine, len );
+ if ( len > 0 )
+ {
+ pLine[len] = '\0';
+ if ( !_DoParseLine( pLine )) return E_FAIL;
+ }
+ else
+ _nLine++;
+ };
+
+ return S_OK;
+}
+
+HRESULT IniParser::_DoParseResource()
+{
+ _nLine = 0;
+ char szLine[MAX_LINE_LEN];
+ char * pos = ( char* ) _pPosition;
+
+ while ( pos < _pPosition + _dwSizeOfRes )
+ {
+ int i=0;
+ while ( pos < _pPosition + _dwSizeOfRes && *pos != '\n' && *pos != '\0' && i < MAX_LINE_LEN - 1 )
+ {
+ if ((*pos) != '\r' )
+ szLine[ i++ ] = *pos;
+ pos++;
+ }
+ szLine[ i ] = '\0';
+ pos++;
+
+ size_t len = 0;
+ char * pLine = (char*) _RemoveTailings( szLine, len );
+ if ( len > 0 )
+ {
+ pLine[len] = '\0';
+ if ( !_DoParseLine( pLine )) return E_FAIL;
+ }
+ else
+ _nLine++;
+ }
+ return S_OK;
+}
+
+const char * IniParser::_RemoveTailings( const char * szLine, size_t& len )
+{
+ const char * pStart = szLine;
+ while( *pStart == ' ' || *pStart == '\t' ) pStart++; //skip spaces at begin
+ const char * pEnd = pStart + strlen( pStart );
+ while( pEnd > pStart && ( *pEnd == ' ' || *pEnd == '\t' || *pEnd == '\n' || *pEnd == '\r' )) pEnd--;
+
+ len = pEnd - pStart;
+ return pStart;
+}
+
+BOOL IniParser::_DoParseLine( char * szLine )
+{
+ _nLine++;
+ DWORD len = strlen( szLine );
+
+ if ( len == 0 ) return TRUE;
+
+ switch( szLine[0] )
+ {
+ case ';':
+ return TRUE; // start of comment is found
+ case '[':
+ {
+ //New section start here
+ mir_free( _szSection );
+ _szSection = NULL;
+
+ char *tbuf = szLine + 1; // skip [
+
+ char *ebuf = tbuf;
+
+ while ( *ebuf != ']' && *ebuf != '\0' ) ebuf++;
+ if ( *ebuf == '\0' )
+ return FALSE; // no close bracket
+
+ DWORD sectionLen = ebuf - tbuf;
+ _szSection = (char*) mir_alloc( sectionLen + 1 );
+ strncpy( _szSection, tbuf, sectionLen );
+ _szSection[sectionLen] = '\0';
+ }
+ return TRUE;
+
+ default:
+ if ( !_szSection )
+ return TRUE; //param found out of section
+
+ char *keyName = szLine;
+ char *keyValue = szLine;
+
+ DWORD eqPlace = 0;
+ DWORD len2 = strlen(keyName);
+
+ while ( eqPlace < len2 && keyName[ eqPlace ] != '=' )
+ eqPlace++; //find '='
+
+ if (eqPlace == 0 || eqPlace == len2)
+ return TRUE; // = not found or no key name //say false
+
+ keyName[eqPlace] = '\0';
+
+ keyValue = keyName + eqPlace + 1;
+
+ //remove tail spaces in Name
+ {
+ DWORD len3 = strlen(keyName);
+ int j = len3-1;
+ while (j>0 && (keyName[j] == ' ' || keyName[j] == '\t')) j--;
+ if (j >= 0) keyName[j+1] = '\0';
+ }
+ //remove start spaces in Value
+ {
+ DWORD len3 = strlen(keyValue);
+ DWORD j = 0;
+ while (j < len3 && (keyValue[j] == ' ' || keyValue[j] == '\t')) j++;
+ if (j < len3) keyValue += j;
+ }
+ //remove tail spaces in Value
+ {
+ DWORD len3 = strlen(keyValue);
+ int j = len3-1;
+ while (j>0 && (keyValue[j] == ' ' || keyValue[j] == '\t' || keyValue[j] == '\n')) j--;
+ if (j >= 0) keyValue[j+1] = '\0';
+ }
+ _pLineCallBackProc( _szSection, keyName, keyValue, this );
+ }
+ return TRUE;
+}
+//////////////////////////////////////////////////////////////////////////
+// End of IniParser
+//////////////////////////////////////////////////////////////////////////
+
+HRESULT SkinEngineLoadModule()
+{
+ ModernSkinButtonLoadModule();
+ InitializeCriticalSection(&cs_SkinChanging);
+ MainModernMaskList = (LISTMODERNMASK*)mir_calloc(sizeof(LISTMODERNMASK));
+ //init variables
+ g_SkinObjectList.dwObjLPAlocated = 0;
+ g_SkinObjectList.dwObjLPReserved = 0;
+ g_SkinObjectList.pObjects = NULL;
+ // Initialize GDI+
+ InitGdiPlus();
+ AniAva_InitModule();
+ //load decoder
+ hImageDecoderModule = NULL;
+ if (g_CluiData.fGDIPlusFail)
+ {
+ hImageDecoderModule = LoadLibrary(_T("ImgDecoder.dll"));
+ if (hImageDecoderModule == NULL)
+ {
+ char tDllPath[ MAX_PATH ];
+ GetModuleFileNameA( g_hInst, tDllPath, sizeof( tDllPath ));
+ {
+ char* p = strrchr( tDllPath, '\\' );
+ if ( p != NULL )
+ strcpy( p+1, "ImgDecoder.dll" );
+ else
+ {
+ strcpy( tDllPath, "ImgDecoder.dll" );
+ }
+ }
+
+ hImageDecoderModule = LoadLibraryA(tDllPath);
+ }
+ if (hImageDecoderModule != NULL)
+ {
+ ImgNewDecoder = (pfnImgNewDecoder )GetProcAddress( hImageDecoderModule, "ImgNewDecoder");
+ ImgDeleteDecoder = (pfnImgDeleteDecoder )GetProcAddress( hImageDecoderModule, "ImgDeleteDecoder");
+ ImgNewDIBFromFile = (pfnImgNewDIBFromFile)GetProcAddress( hImageDecoderModule, "ImgNewDIBFromFile");
+ ImgDeleteDIBSection = (pfnImgDeleteDIBSection)GetProcAddress( hImageDecoderModule, "ImgDeleteDIBSection");
+ ImgGetHandle = (pfnImgGetHandle)GetProcAddress( hImageDecoderModule, "ImgGetHandle");
+ }
+ }
+ //create services
+ CreateServiceFunction(MS_SKIN_DRAWGLYPH,ske_Service_DrawGlyph);
+ CreateServiceFunction(MS_SKINENG_UPTATEFRAMEIMAGE,ske_Service_UpdateFrameImage);
+ CreateServiceFunction(MS_SKINENG_INVALIDATEFRAMEIMAGE,ske_Service_InvalidateFrameImage);
+ CreateServiceFunction(MS_SKINENG_ALPHATEXTOUT,ske_Service_AlphaTextOut);
+ CreateServiceFunction(MS_SKINENG_DRAWICONEXFIX,ske_Service_DrawIconEx);
+
+ CreateServiceFunction(MS_DRAW_TEXT_WITH_EFFECT,ske_Service_DrawTextWithEffect);
+
+ //create event handle
+ hSkinLoadedEvent = HookEvent(ME_SKIN_SERVICESCREATED,CLUI_OnSkinLoad);
+ NotifyEventHooks(g_CluiData.hEventSkinServicesCreated,0,0);
+ return S_OK;
+}
+
+int SkinEngineUnloadModule()
+{
+ //unload services
+ ModernSkinButtonUnloadModule(0,0);
+ ske_UnloadSkin(&g_SkinObjectList);
+
+ mir_free_and_nil(g_SkinObjectList.pObjects);
+ mir_free_and_nil(g_SkinObjectList.pMaskList);
+ mir_free_and_nil(MainModernMaskList);
+
+ if (pEffectStack)
+ {
+ for (int i=0; i < pEffectStack->realCount; i++)
+ if (pEffectStack->items[i]) {
+ EFFECTSSTACKITEM * effect = (EFFECTSSTACKITEM*)(pEffectStack->items[i]);
+ mir_free(effect);
+ }
+ List_Destroy(pEffectStack);
+ mir_free_and_nil(pEffectStack);
+ }
+ if (g_pCachedWindow) {
+ SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackOld);
+ SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageOld);
+ DeleteObject(g_pCachedWindow->hBackDIB);
+ DeleteObject(g_pCachedWindow->hImageDIB);
+ mod_DeleteDC(g_pCachedWindow->hBackDC);
+ mod_DeleteDC(g_pCachedWindow->hImageDC);
+ ReleaseDC(NULL,g_pCachedWindow->hScreenDC);
+ mir_free_and_nil(g_pCachedWindow);
+ }
+ DeleteCriticalSection(&cs_SkinChanging);
+ GdiFlush();
+ DestroyHookableEvent(g_CluiData.hEventSkinServicesCreated);
+ if (hImageDecoderModule) FreeLibrary(hImageDecoderModule);
+ AniAva_UnloadModule();
+ ShutdownGdiPlus();
+ //free variables
+ return 1;
+}
+
+BOOL ske_AlphaBlend(HDC hdcDest,int nXOriginDest,int nYOriginDest,int nWidthDest,int nHeightDest,HDC hdcSrc,int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc,BLENDFUNCTION blendFunction)
+{
+ if (g_CluiData.fDisableSkinEngine && !(!g_CluiData.fGDIPlusFail && blendFunction.BlendFlags&128))
+ {
+ if (nWidthDest != nWidthSrc || nHeightDest != nHeightSrc)
+ return StretchBlt(hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest,hdcSrc,nXOriginSrc,nYOriginSrc,nWidthSrc,nHeightSrc, SRCCOPY);
+ else
+ return BitBlt(hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest,hdcSrc,nXOriginSrc,nYOriginSrc, SRCCOPY);
+ }
+
+ if ( !g_CluiData.fGDIPlusFail && blendFunction.BlendFlags&128 ) //Use gdi+ engine
+ {
+ return GDIPlus_AlphaBlend( hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest,
+ hdcSrc,nXOriginSrc,nYOriginSrc,nWidthSrc,nHeightSrc,
+ &blendFunction);
+ }
+ blendFunction.BlendFlags &= ~128;
+ return AlphaBlend(hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest,hdcSrc,nXOriginSrc,nYOriginSrc,nWidthSrc,nHeightSrc,blendFunction);
+}
+
+static int ske_LockSkin()
+{
+ EnterCriticalSection(&cs_SkinChanging);
+ return 0;
+}
+
+static int ske_UnlockSkin()
+{
+ LeaveCriticalSection(&cs_SkinChanging);
+ return 0;
+}
+
+typedef struct _tagDCBuffer
+{
+ HDC hdcOwnedBy;
+ int nUsageID;
+ int width;
+ int height;
+ void* pImage;
+ HDC hDC;
+ HBITMAP oldBitmap;
+ HBITMAP hBitmap;
+ DWORD dwDestroyAfterTime;
+}DCBUFFER;
+CRITICAL_SECTION BufferListCS = {0};
+
+SortedList * BufferList = NULL;
+enum
+{
+ BUFFER_DRAWICON = 0,
+ BUFFER_DRAWIMAGE
+};
+
+int SortBufferList(void* it1, void * it2)
+{
+ DCBUFFER * buf1 = (DCBUFFER *)it1;
+ DCBUFFER * buf2 = (DCBUFFER *)it2;
+ if (buf1->hdcOwnedBy != buf2->hdcOwnedBy) return (int)(buf1->hdcOwnedBy < buf2->hdcOwnedBy);
+ else if (buf1->nUsageID != buf2->nUsageID) return (int) (buf1->nUsageID < buf2->nUsageID);
+ else return (int) (buf1->hDC < buf2->hDC);
+}
+
+HDC ske_RequestBufferDC(HDC hdcOwner, int dcID, int width, int height, BOOL fClear)
+{
+ DCBUFFER buf;
+ DCBUFFER * pBuf;
+ if (BufferList == NULL)
+ {
+ BufferList = List_Create(0,2);
+ BufferList->sortFunc = SortBufferList;
+ InitializeCriticalSection(&BufferListCS);
+ }
+ EnterCriticalSection(&BufferListCS);
+ //Try to find DC in buffer list
+ buf.hdcOwnedBy = hdcOwner;
+ buf.nUsageID = dcID;
+ buf.hDC = NULL;
+ pBuf = (DCBUFFER*)List_Find(BufferList,(void*)&buf);
+ if ( !pBuf)
+ {
+ //if not found - allocate it
+ pBuf = (DCBUFFER *)mir_alloc(sizeof(DCBUFFER));
+ *pBuf = buf;
+ pBuf->width = width;
+ pBuf->height = height;
+ pBuf->hBitmap = ske_CreateDIB32Point(width,height,&(pBuf->pImage));
+ pBuf->hDC = CreateCompatibleDC(hdcOwner);
+ pBuf->oldBitmap = (HBITMAP)SelectObject(pBuf->hDC,pBuf->hBitmap);
+ pBuf->dwDestroyAfterTime = 0;
+ List_InsertPtr(BufferList,pBuf);
+ }
+ else
+ {
+ if (pBuf->width != width || pBuf->height != height)
+ {
+ //resize
+ SelectObject(pBuf->hDC,pBuf->oldBitmap);
+ DeleteObject(pBuf->hBitmap);
+ pBuf->width = width;
+ pBuf->height = height;
+ pBuf->hBitmap = ske_CreateDIB32Point(width,height,&(pBuf->pImage));
+ pBuf->oldBitmap = (HBITMAP)SelectObject(pBuf->hDC,pBuf->hBitmap);
+ } else if (fClear)
+ memset(pBuf->pImage,0,width*height*sizeof(DWORD));
+ }
+ pBuf->dwDestroyAfterTime = 0;
+ LeaveCriticalSection(&BufferListCS);
+ return pBuf->hDC;
+}
+
+int ske_ReleaseBufferDC(HDC hDC, int keepTime)
+{
+ DWORD dwCurrentTime = GetTickCount();
+ DCBUFFER * pBuf = NULL;
+ //Try to find DC in buffer list - set flag to be release after time;
+ int i=0;
+ EnterCriticalSection(&BufferListCS);
+ for (i=0; i < BufferList->realCount; i++)
+ {
+ pBuf = (DCBUFFER *)BufferList->items[i];
+ if (pBuf)
+ {
+ if (hDC != NULL && pBuf->hDC == hDC)
+ {
+ pBuf->dwDestroyAfterTime = dwCurrentTime+keepTime;
+ break;
+ }
+ else
+ {
+ if ((pBuf->dwDestroyAfterTime && pBuf->dwDestroyAfterTime < dwCurrentTime) || keepTime == -1)
+ {
+ SelectObject(pBuf->hDC,pBuf->oldBitmap);
+ DeleteObject(pBuf->hBitmap);
+ DeleteDC(pBuf->hDC);
+ mir_free(pBuf);
+ List_Remove(BufferList,i);
+ i--;
+ }
+ }
+ }
+ }
+ LeaveCriticalSection(&BufferListCS);
+ return 0;
+}
+
+BOOL ske_SetRgnOpaque(HDC memdc,HRGN hrgn, BOOL force)
+{
+ RGNDATA * rdata;
+ DWORD rgnsz;
+ DWORD d;
+ RECT * rect;
+ if (g_CluiData.fDisableSkinEngine && !force) return TRUE;
+ rgnsz = GetRegionData(hrgn,0,NULL);
+ rdata = (RGNDATA *) mir_alloc(rgnsz);
+ GetRegionData(hrgn,rgnsz,rdata);
+ rect = (RECT *)rdata->Buffer;
+ for (d = 0; d < rdata->rdh.nCount; d++)
+ {
+ ske_SetRectOpaque(memdc,&rect[d], force);
+ }
+ mir_free(rdata);
+ return TRUE;
+}
+
+
+BOOL ske_SetRectOpaque(HDC memdc,RECT *fr, BOOL force)
+{
+ int f = 0;
+ BYTE * bits;
+ BITMAP bmp;
+ HBITMAP hbmp;
+
+ if ( g_CluiData.fDisableSkinEngine && !force )
+ return TRUE;
+
+ hbmp = (HBITMAP)GetCurrentObject( memdc,OBJ_BITMAP );
+ GetObject( hbmp, sizeof(bmp), &bmp );
+
+ if ( bmp.bmPlanes != 1 )
+ return FALSE;
+
+ if ( !bmp.bmBits)
+ {
+ f = 1;
+ bits = (BYTE*)malloc(bmp.bmWidthBytes*bmp.bmHeight);
+ GetBitmapBits(hbmp,bmp.bmWidthBytes*bmp.bmHeight,bits);
+ }
+ else
+ bits = (BYTE*)bmp.bmBits;
+
+ int sx = ( fr->left > 0 ) ? fr->left : 0;
+ int sy = ( fr->top > 0 ) ? fr->top : 0;
+ int ex = ( fr->right < bmp.bmWidth ) ? fr->right : bmp.bmWidth;
+ int ey = ( fr->bottom < bmp.bmHeight) ? fr->bottom : bmp.bmHeight;
+
+ int width = ex-sx;
+
+ BYTE* pLine = ((BYTE*)bits) + (bmp.bmHeight-sy-1)*bmp.bmWidthBytes + (sx << 2) + 3;
+ for ( int y = 0; y < (ey - sy); y++ )
+ {
+ BYTE * pColumn = pLine;
+ for ( int x = 0; x < width; x++ )
+ {
+ *pColumn = 255;
+ pColumn += 4;
+ }
+ pLine -= bmp.bmWidthBytes;
+ }
+ if (f)
+ {
+ SetBitmapBits(hbmp,bmp.bmWidthBytes*bmp.bmHeight,bits);
+ free(bits);
+ }
+ // DeleteObject(hbmp);
+ return 1;
+}
+
+static BOOL ske_SkinFillRectByGlyph(HDC hDest, HDC hSource, RECT * rFill, RECT * rGlyph, RECT * rClip, BYTE mode, BYTE drawMode, int depth)
+{
+ int destw = 0, desth = 0;
+ int xstart = 0, xmax = 0;
+ int ystart = 0, ymax = 0;
+ BLENDFUNCTION bfa = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+
+ //initializations
+ if (mode == FM_STRETCH)
+ {
+ HDC mem2dc;
+ HBITMAP mem2bmp, oldbmp;
+ RECT wr;
+ IntersectRect(&wr,rClip,rFill);
+ if ((wr.bottom-wr.top)*(wr.right-wr.left) == 0) return 0;
+ if (drawMode != 2)
+ {
+ mem2dc = CreateCompatibleDC(hDest);
+ mem2bmp = ske_CreateDIB32(wr.right-wr.left,wr.bottom-wr.top);
+ oldbmp = (HBITMAP)SelectObject(mem2dc,mem2bmp);
+
+ }
+
+ if (drawMode == 0 || drawMode == 2)
+ {
+ if (drawMode == 0)
+ {
+ ske_AlphaBlend(mem2dc,rFill->left-wr.left,rFill->top-wr.top,rFill->right-rFill->left,rFill->bottom-rFill->top,
+ hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,rGlyph->bottom-rGlyph->top,bf);
+ ske_AlphaBlend(hDest,wr.left,wr.top,wr.right-wr.left, wr.bottom -wr.top,mem2dc,0,0,wr.right-wr.left, wr.bottom -wr.top,bf);
+ }
+ else
+ {
+ ske_AlphaBlend(hDest,rFill->left,rFill->top,rFill->right-rFill->left,rFill->bottom-rFill->top,
+ hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,rGlyph->bottom-rGlyph->top,bf);
+
+ }
+ }
+ else
+ {
+ // BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, 0 };
+ ske_AlphaBlend(mem2dc,rFill->left-wr.left,rFill->top-wr.top,rFill->right-rFill->left,rFill->bottom-rFill->top,
+ hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,rGlyph->bottom-rGlyph->top,bf);
+ ske_AlphaBlend(hDest,wr.left,wr.top,wr.right-wr.left, wr.bottom -wr.top,mem2dc,0,0,wr.right-wr.left, wr.bottom -wr.top,bf);
+ }
+ if (drawMode != 2)
+ {
+ SelectObject(mem2dc,oldbmp);
+ DeleteObject(mem2bmp);
+ mod_DeleteDC(mem2dc);
+ }
+ return 1;
+ }
+ else if (mode == FM_TILE_VERT && (rGlyph->bottom-rGlyph->top>0) && (rGlyph->right-rGlyph->left>0))
+ {
+ HDC mem2dc;
+ HBITMAP mem2bmp,oldbmp;
+ RECT wr;
+ IntersectRect(&wr,rClip,rFill);
+ if ((wr.bottom-wr.top)*(wr.right-wr.left) == 0) return 0;
+ mem2dc = CreateCompatibleDC(hDest);
+ //SetStretchBltMode(mem2dc, HALFTONE);
+ mem2bmp = ske_CreateDIB32(wr.right-wr.left, rGlyph->bottom-rGlyph->top);
+ oldbmp = (HBITMAP)SelectObject(mem2dc,mem2bmp);
+ if ( !oldbmp)
+ return 0;
+
+ /// draw here
+ {
+ int y = 0, sy = 0, maxy = 0;
+ int w = rFill->right-rFill->left;
+ int h = rGlyph->bottom-rGlyph->top;
+ if (h>0 && (wr.bottom-wr.top)*(wr.right-wr.left) != 0)
+ {
+ w = wr.right-wr.left;
+ {
+ // BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, 0 };
+ ske_AlphaBlend(mem2dc,-(wr.left-rFill->left),0,rFill->right-rFill->left,h,hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,h,bf);
+ //StretchBlt(mem2dc,-(wr.left-rFill->left),0,rFill->right-rFill->left,h,hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,h,SRCCOPY);
+ }
+ if (drawMode == 0 || drawMode == 2)
+ {
+ if (drawMode == 0 )
+ {
+
+ int dy;
+ dy = (wr.top-rFill->top)%h;
+ if (dy >= 0)
+ {
+ int ht;
+ y = wr.top;
+ ht = (y+h-dy <= wr.bottom)?(h-dy):(wr.bottom-wr.top);
+ BitBlt(hDest,wr.left,y,w,ht,mem2dc,0,dy,SRCCOPY);
+ }
+
+ y = wr.top+h-dy;
+ while (y < wr.bottom-h){
+ BitBlt(hDest,wr.left,y,w,h,mem2dc,0,0,SRCCOPY);
+ y += h;
+ }
+ if (y <= wr.bottom)
+ BitBlt(hDest,wr.left,y,w,wr.bottom-y, mem2dc,0,0,SRCCOPY);
+
+ }
+ else
+ {
+ y = wr.top;
+ while (y < wr.bottom-h)
+ {
+ // BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, 0 };
+ ske_AlphaBlend(hDest,wr.left,y,w,h, mem2dc,0,0,w,h,bf);
+ y += h;
+ }
+ if (y <= wr.bottom)
+ {
+ // BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, 0 };
+ ske_AlphaBlend(hDest,wr.left,y,w,wr.bottom-y, mem2dc,0,0,w,wr.bottom-y,bf);
+ }
+ }
+
+ }
+ else
+ {
+ int dy;
+
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+
+ dy = (wr.top-rFill->top)%h;
+
+ if (dy >= 0)
+ {
+ int ht;
+ y = wr.top;
+ ht = (y+h-dy <= wr.bottom)?(h-dy):(wr.bottom-wr.top);
+ ske_AlphaBlend(hDest,wr.left,y,w,ht,mem2dc,0,dy,w,ht,bf);
+ }
+
+ y = wr.top+h-dy;
+ while (y < wr.bottom-h)
+ {
+ ske_AlphaBlend(hDest,wr.left,y,w,h,mem2dc,0,0,w,h,bf);
+ y += h;
+ }
+ if (y <= wr.bottom)
+ ske_AlphaBlend(hDest,wr.left,y,w,wr.bottom-y, mem2dc,0,0,w,wr.bottom-y,bf);
+ }
+ }
+ }
+ SelectObject(mem2dc,oldbmp);
+ DeleteObject(mem2bmp);
+ mod_DeleteDC(mem2dc);
+ }
+ else if (mode == FM_TILE_HORZ && (rGlyph->right-rGlyph->left>0) && (rGlyph->bottom-rGlyph->top>0) && (rFill->bottom-rFill->top)>0 && (rFill->right-rFill->left)>0)
+ {
+ HDC mem2dc;
+ RECT wr;
+ HBITMAP mem2bmp,oldbmp;
+ int w = rGlyph->right-rGlyph->left;
+ int h = rFill->bottom-rFill->top;
+ IntersectRect(&wr,rClip,rFill);
+ if ((wr.bottom-wr.top)*(wr.right-wr.left) == 0) return 0;
+ h = wr.bottom-wr.top;
+ mem2dc = CreateCompatibleDC(hDest);
+
+ mem2bmp = ske_CreateDIB32(w,h);
+ oldbmp = (HBITMAP)SelectObject(mem2dc,mem2bmp);
+
+ if ( !oldbmp)
+ return 0;
+ /// draw here
+ {
+ int x = 0, sy = 0, maxy = 0;
+ {
+ //SetStretchBltMode(mem2dc, HALFTONE);
+ //StretchBlt(mem2dc,0,0,w,h,hSource,rGlyph->left+(wr.left-rFill->left),rGlyph->top,w,h,SRCCOPY);
+
+ // BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, 0 };
+ ske_AlphaBlend(mem2dc,0,-(wr.top-rFill->top),w,rFill->bottom-rFill->top,hSource,rGlyph->left,rGlyph->top,w,rGlyph->bottom-rGlyph->top,bf);
+ if (drawMode == 0 || drawMode == 2)
+ {
+ if (drawMode == 0)
+ {
+
+ int dx;
+ dx = (wr.left-rFill->left)%w;
+ if (dx >= 0)
+ {
+ int wt;
+ x = wr.left;
+ wt = (x+w-dx <= wr.right)?(w-dx):(wr.right-wr.left);
+ BitBlt(hDest,x,wr.top,wt,h,mem2dc,dx,0,SRCCOPY);
+ }
+ x = wr.left+w-dx;
+ while (x < wr.right-w){
+ BitBlt(hDest,x,wr.top,w,h,mem2dc,0,0,SRCCOPY);
+ x += w;
+ }
+ if (x <= wr.right)
+ BitBlt(hDest,x,wr.top,wr.right-x,h, mem2dc,0,0,SRCCOPY);
+ }
+ else
+ {
+ int dx;
+ dx = (wr.left-rFill->left)%w;
+ x = wr.left-dx;
+ while (x < wr.right-w){
+ ske_AlphaBlend(hDest,x,wr.top,w,h,mem2dc,0,0,w,h,bf);
+ x += w;
+ }
+ if (x <= wr.right)
+ ske_AlphaBlend(hDest,x,wr.top,wr.right-x,h, mem2dc,0,0,wr.right-x,h,bf);
+ }
+
+ }
+ else
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ int dx;
+ dx = (wr.left-rFill->left)%w;
+ if (dx >= 0)
+ {
+ int wt;
+ x = wr.left;
+ wt = (x+w-dx <= wr.right)?(w-dx):(wr.right-wr.left);
+ ske_AlphaBlend(hDest,x,wr.top,wt,h,mem2dc,dx,0,wt,h,bf);
+ }
+ x = wr.left+w-dx;
+ while (x < wr.right-w){
+ ske_AlphaBlend(hDest,x,wr.top,w,h,mem2dc,0,0,w,h,bf);
+ x += w;
+ }
+ if (x <= wr.right)
+ ske_AlphaBlend(hDest,x,wr.top,wr.right-x,h, mem2dc,0,0,wr.right-x,h,bf);
+
+ }
+ }
+ }
+ SelectObject(mem2dc,oldbmp);
+ DeleteObject(mem2bmp);
+ mod_DeleteDC(mem2dc);
+ }
+ else if (mode == FM_TILE_BOTH && (rGlyph->right-rGlyph->left>0) && (rGlyph->bottom-rGlyph->top>0))
+ {
+ HDC mem2dc;
+ int w = rGlyph->right-rGlyph->left;
+ int x = 0, sy = 0, maxy = 0;
+ int h = rFill->bottom-rFill->top;
+ HBITMAP mem2bmp,oldbmp;
+ RECT wr;
+ IntersectRect(&wr,rClip,rFill);
+ if ((wr.bottom-wr.top)*(wr.right-wr.left) == 0) return 0;
+ mem2dc = CreateCompatibleDC(hDest);
+ mem2bmp = ske_CreateDIB32(w,wr.bottom-wr.top);
+ h = wr.bottom-wr.top;
+ oldbmp = (HBITMAP)SelectObject(mem2dc,mem2bmp);
+#ifdef _DEBUG
+ if ( !oldbmp)
+ (NULL,"Tile bitmap not selected","ERROR", MB_OK);
+#endif
+ /// draw here
+ {
+
+ //fill temp bitmap
+ {
+ int y;
+ int dy;
+ dy = (wr.top-rFill->top)%(rGlyph->bottom-rGlyph->top);
+ y = -dy;
+ while (y < wr.bottom-wr.top)
+ {
+
+ ske_AlphaBlend(mem2dc,0,y,w,rGlyph->bottom-rGlyph->top, hSource,rGlyph->left,rGlyph->top,w,rGlyph->bottom-rGlyph->top,bf);
+ y += rGlyph->bottom-rGlyph->top;
+ }
+
+ //--
+ //end temp bitmap
+ if (drawMode == 0 || drawMode == 2)
+ {
+ if (drawMode == 0)
+ {
+
+ int dx;
+ dx = (wr.left-rFill->left)%w;
+ if (dx >= 0)
+ {
+ int wt;
+ x = wr.left;
+ wt = (x+w-dx <= wr.right)?(w-dx):(wr.right-wr.left);
+ BitBlt(hDest,x,wr.top,wt,h,mem2dc,dx,0,SRCCOPY);
+ }
+ x = wr.left+w-dx;
+ while (x < wr.right-w){
+ BitBlt(hDest,x,wr.top,w,h,mem2dc,0,0,SRCCOPY);
+ x += w;
+ }
+ if (x <= wr.right)
+ BitBlt(hDest,x,wr.top,wr.right-x,h, mem2dc,0,0,SRCCOPY);
+ }
+ else
+ {
+ int dx;
+ dx = (wr.left-rFill->left)%w;
+ x = wr.left-dx;
+ while (x < wr.right-w){
+ ske_AlphaBlend(hDest,x,wr.top,w,h,mem2dc,0,0,w,h,bf);
+ x += w;
+ }
+ if (x <= wr.right)
+ ske_AlphaBlend(hDest,x,wr.top,wr.right-x,h, mem2dc,0,0,wr.right-x,h,bf);
+ }
+
+ }
+ else
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+
+ int dx;
+ dx = (wr.left-rFill->left)%w;
+ if (dx >= 0)
+ {
+ int wt;
+ x = wr.left;
+ wt = (x+w-dx <= wr.right)?(w-dx):(wr.right-wr.left);
+ ske_AlphaBlend(hDest,x,wr.top,wt,h,mem2dc,dx,0,wt,h,bf);
+ }
+ x = wr.left+w-dx;
+ while (x < wr.right-w){
+ ske_AlphaBlend(hDest,x,wr.top,w,h,mem2dc,0,0,w,h,bf);
+ x += w;
+ }
+ if (x <= wr.right)
+ ske_AlphaBlend(hDest,x,wr.top,wr.right-x,h, mem2dc,0,0,wr.right-x,h,bf);
+
+ }
+ }
+
+ }
+ SelectObject(mem2dc,oldbmp);
+ DeleteObject(mem2bmp);
+ mod_DeleteDC(mem2dc);
+ }
+ return 1;
+
+}
+
+HBITMAP ske_CreateDIB32(int cx, int cy)
+{
+ return ske_CreateDIB32Point(cx,cy,NULL);
+}
+
+HBITMAP ske_CreateDIB32Point(int cx, int cy, void ** bits)
+{
+ BITMAPINFO RGB32BitsBITMAPINFO;
+ UINT * ptPixels;
+ HBITMAP DirectBitmap;
+
+ if ( cx < 0 || cy < 0 ) {
+#ifdef _DEBUG
+ DebugBreak();
+#endif
+ return NULL;
+ }
+
+ ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO));
+ RGB32BitsBITMAPINFO.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ RGB32BitsBITMAPINFO.bmiHeader.biWidth = cx;//bm.bmWidth;
+ RGB32BitsBITMAPINFO.bmiHeader.biHeight = cy;//bm.bmHeight;
+ RGB32BitsBITMAPINFO.bmiHeader.biPlanes = 1;
+ RGB32BitsBITMAPINFO.bmiHeader.biBitCount = 32;
+ // pointer used for direct Bitmap pixels access
+
+
+ DirectBitmap = CreateDIBSection(NULL,
+ (BITMAPINFO *)&RGB32BitsBITMAPINFO,
+ DIB_RGB_COLORS,
+ (void **)&ptPixels,
+ NULL, 0);
+ if ((DirectBitmap == NULL || ptPixels == NULL) && cx != 0 && cy != 0)
+ {
+#ifdef _DEBUG
+ MessageBoxA(NULL,"Object not allocated. Check GDI object count","ERROR",MB_OK|MB_ICONERROR);
+ DebugBreak();
+#endif
+ ;
+ }
+ else memset(ptPixels,0,cx*cy*4);
+ if (bits != NULL) *bits = ptPixels;
+ return DirectBitmap;
+}
+
+HRGN ske_CreateOpaqueRgn(BYTE Level, bool Opaque)
+{
+ if ( !g_pCachedWindow)
+ return NULL;
+
+ RGBQUAD * buf = (RGBQUAD *) g_pCachedWindow->hImageDIBByte;
+
+ int x,y;
+ unsigned int cRect = 64;
+ PRGNDATA pRgnData = (PRGNDATA)malloc(sizeof(RGNDATAHEADER) + (cRect)*sizeof(RECT));
+ memset(pRgnData, 0, sizeof(RGNDATAHEADER));
+ pRgnData->rdh.dwSize = sizeof(RGNDATAHEADER);
+ pRgnData->rdh.iType = RDH_RECTANGLES;
+
+ for (y = 0; y < g_pCachedWindow->Height; ++y)
+ {
+ bool inside = false;
+ bool lastin = false;
+ unsigned int entry = 0;
+
+ for (x = 0; x < g_pCachedWindow->Width; ++x)
+ {
+ inside = Opaque ? (buf->rgbReserved > Level) : (buf->rgbReserved < Level);
+ ++buf;
+
+ if (inside != lastin)
+ {
+ if (inside)
+ {
+ lastin = true;
+ entry = x;
+ } else {
+ if (pRgnData->rdh.nCount == cRect)
+ {
+ cRect = cRect + 64;
+ pRgnData = (PRGNDATA)realloc(pRgnData, sizeof(RGNDATAHEADER) + (cRect)*sizeof(RECT));
+ }
+ SetRect(((LPRECT)pRgnData->Buffer) + pRgnData->rdh.nCount, entry, g_pCachedWindow->Height - y, x, g_pCachedWindow->Height - y + 1);
+
+ pRgnData->rdh.nCount++;
+ lastin = false;
+ }
+ }
+ }
+
+ if (lastin)
+ {
+ if (pRgnData->rdh.nCount == cRect)
+ {
+ cRect = cRect + 64;
+ pRgnData = (PRGNDATA)realloc(pRgnData, sizeof(RGNDATAHEADER) + (cRect)*sizeof(RECT));
+ }
+ SetRect(((LPRECT)pRgnData->Buffer) + pRgnData->rdh.nCount, entry, g_pCachedWindow->Height - y, x, g_pCachedWindow->Height - y + 1);
+
+ pRgnData->rdh.nCount++;
+ }
+ }
+ HRGN hRgn = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount*sizeof(RECT), (LPRGNDATA)pRgnData);
+ free(pRgnData);
+
+ return hRgn;
+}
+
+static int ske_DrawSkinObject(SKINDRAWREQUEST * preq, GLYPHOBJECT * pobj)
+{
+ HDC memdc = NULL, glyphdc = NULL;
+ int k = 0;
+ //BITMAP bmp = {0};
+ HBITMAP membmp = 0,oldbmp = 0,oldglyph = 0;
+ BYTE Is32Bit = 0;
+ RECT PRect;
+ POINT mode2offset = {0};
+ int depth = 0;
+ int mode = 0; //0-FastDraw, 1-DirectAlphaDraw, 2-BufferedAlphaDraw
+
+ if ( !(preq && pobj)) return -1;
+ if ((!pobj->hGlyph || pobj->hGlyph == (HBITMAP)-1) && ((pobj->Style&7) == ST_IMAGE || (pobj->Style&7) == ST_FRAGMENT || (pobj->Style&7) == ST_SOLARIZE)) return 0;
+ // Determine painting mode
+ depth = GetDeviceCaps(preq->hDC,BITSPIXEL);
+ depth = depth < 16?16:depth;
+ Is32Bit = pobj->bmBitsPixel == 32;
+ if ((!Is32Bit && pobj->dwAlpha == 255) && pobj->Style != ST_BRUSH) mode = 0;
+ else if (pobj->dwAlpha == 255 && pobj->Style != ST_BRUSH) mode = 1;
+ else mode = 2;
+ // End painting mode
+
+ //force mode
+
+ if (preq->rcClipRect.bottom-preq->rcClipRect.top*preq->rcClipRect.right-preq->rcClipRect.left == 0)
+ preq->rcClipRect = preq->rcDestRect;
+ IntersectRect(&PRect,&preq->rcDestRect,&preq->rcClipRect);
+ if (IsRectEmpty(&PRect))
+ {
+ return 0;
+ }
+ if (mode == 2)
+ {
+ memdc = CreateCompatibleDC(preq->hDC);
+ membmp = ske_CreateDIB32(PRect.right-PRect.left,PRect.bottom-PRect.top);
+ oldbmp = (HBITMAP)SelectObject(memdc,membmp);
+ if (oldbmp == NULL)
+ {
+ if (mode == 2)
+ {
+ SelectObject(memdc,oldbmp);
+ mod_DeleteDC(memdc);
+ DeleteObject(membmp);
+ }
+ return 0;
+ }
+ }
+
+ if (mode != 2) memdc = preq->hDC;
+ {
+ if (pobj->hGlyph && pobj->hGlyph != (HBITMAP)-1)
+ {
+ glyphdc = CreateCompatibleDC(preq->hDC);
+ if ( !oldglyph)
+ oldglyph = (HBITMAP)SelectObject(glyphdc,pobj->hGlyph);
+ else
+ SelectObject(glyphdc,pobj->hGlyph);
+ }
+ // Drawing
+ {
+ RECT rFill, rGlyph, rClip;
+ if ((pobj->Style&7) == ST_BRUSH)
+ {
+ HBRUSH br = CreateSolidBrush(pobj->dwColor);
+ RECT fr;
+ if (mode == 2)
+ {
+ SetRect(&fr,0,0,PRect.right-PRect.left,PRect.bottom-PRect.top);
+ FillRect(memdc,&fr,br);
+ ske_SetRectOpaque(memdc,&fr);
+ // FillRectAlpha(memdc,&fr,pobj->dwColor|0xFF000000);
+ }
+ else
+ {
+ fr = PRect;
+ // SetRect(&fr,0,0,PRect.right-PRect.left,PRect.bottom-PRect.top);
+ FillRect(preq->hDC,&fr,br);
+ }
+ DeleteObject(br);
+ k = -1;
+ }
+ else
+ {
+ if (mode == 2)
+ {
+ mode2offset.x = PRect.left;
+ mode2offset.y = PRect.top;
+ OffsetRect(&PRect,-mode2offset.x,-mode2offset.y);
+ }
+ rClip = (preq->rcClipRect);
+
+ {
+ int lft = 0;
+ int top = 0;
+ int rgh = pobj->bmWidth;
+ int btm = pobj->bmHeight;
+ if ((pobj->Style&7) == ST_FRAGMENT)
+ {
+ lft = pobj->clipArea.x;
+ top = pobj->clipArea.y;
+ rgh = min(rgh,lft+pobj->szclipArea.cx);
+ btm = min(btm,top+pobj->szclipArea.cy);
+ }
+
+ // Draw center...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.top+pobj->dwTop;
+ rFill.bottom = preq->rcDestRect.bottom-pobj->dwBottom;
+ rFill.left = preq->rcDestRect.left+pobj->dwLeft;
+ rFill.right = preq->rcDestRect.right-pobj->dwRight;
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+ rGlyph.top = top+pobj->dwTop;
+ rGlyph.left = lft+pobj->dwLeft;
+ rGlyph.right = rgh-pobj->dwRight;
+ rGlyph.bottom = btm-pobj->dwBottom;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode,mode,depth);
+ }
+
+ // Draw top side...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.top;
+ rFill.bottom = preq->rcDestRect.top+pobj->dwTop;
+ rFill.left = preq->rcDestRect.left+pobj->dwLeft;
+ rFill.right = preq->rcDestRect.right-pobj->dwRight;
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+ rGlyph.top = top+0;
+ rGlyph.left = lft+pobj->dwLeft;
+ rGlyph.right = rgh-pobj->dwRight;
+ rGlyph.bottom = top+pobj->dwTop;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_HORZ,mode,depth);
+ }
+ // Draw bottom side...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.bottom-pobj->dwBottom;
+ rFill.bottom = preq->rcDestRect.bottom;
+ rFill.left = preq->rcDestRect.left+pobj->dwLeft;
+ rFill.right = preq->rcDestRect.right-pobj->dwRight;
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+
+ rGlyph.top = btm-pobj->dwBottom;
+ rGlyph.left = lft+pobj->dwLeft;
+ rGlyph.right = rgh-pobj->dwRight;
+ rGlyph.bottom = btm;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_HORZ,mode,depth);
+ }
+ // Draw left side...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.top+pobj->dwTop;
+ rFill.bottom = preq->rcDestRect.bottom-pobj->dwBottom;
+ rFill.left = preq->rcDestRect.left;
+ rFill.right = preq->rcDestRect.left+pobj->dwLeft;
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+
+ rGlyph.top = top+pobj->dwTop;
+ rGlyph.left = lft;
+ rGlyph.right = lft+pobj->dwLeft;
+ rGlyph.bottom = btm-pobj->dwBottom;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_VERT,mode,depth);
+ }
+
+ // Draw right side...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.top+pobj->dwTop;
+ rFill.bottom = preq->rcDestRect.bottom-pobj->dwBottom;
+ rFill.left = preq->rcDestRect.right-pobj->dwRight;
+ rFill.right = preq->rcDestRect.right;
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+
+ rGlyph.top = top+pobj->dwTop;
+ rGlyph.left = rgh-pobj->dwRight;
+ rGlyph.right = rgh;
+ rGlyph.bottom = btm-pobj->dwBottom;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_VERT,mode,depth);
+ }
+
+
+ // Draw Top-Left corner...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.top;
+ rFill.bottom = preq->rcDestRect.top+pobj->dwTop;
+ rFill.left = preq->rcDestRect.left;
+ rFill.right = preq->rcDestRect.left+pobj->dwLeft;
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+
+ rGlyph.top = top;
+ rGlyph.left = lft;
+ rGlyph.right = lft+pobj->dwLeft;
+ rGlyph.bottom = top+pobj->dwTop;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth);
+ }
+ // Draw Top-Right corner...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.top;
+ rFill.bottom = preq->rcDestRect.top+pobj->dwTop;
+ rFill.left = preq->rcDestRect.right-pobj->dwRight;
+ rFill.right = preq->rcDestRect.right;
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+
+ rGlyph.top = top;
+ rGlyph.left = rgh-pobj->dwRight;
+ rGlyph.right = rgh;
+ rGlyph.bottom = top+pobj->dwTop;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth);
+ }
+
+ // Draw Bottom-Left corner...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.bottom-pobj->dwBottom;
+ rFill.bottom = preq->rcDestRect.bottom;
+ rFill.left = preq->rcDestRect.left;
+ rFill.right = preq->rcDestRect.left+pobj->dwLeft;
+
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+
+ rGlyph.left = lft;
+ rGlyph.right = lft+pobj->dwLeft;
+ rGlyph.top = btm-pobj->dwBottom;
+ rGlyph.bottom = btm;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth);
+ }
+ // Draw Bottom-Right corner...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.bottom-pobj->dwBottom;
+ rFill.bottom = preq->rcDestRect.bottom;
+ rFill.left = preq->rcDestRect.right-pobj->dwRight;
+ rFill.right = preq->rcDestRect.right;
+
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+ rGlyph.left = rgh-pobj->dwRight;
+ rGlyph.right = rgh;
+ rGlyph.top = btm-pobj->dwBottom;
+ rGlyph.bottom = btm;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth);
+ }
+ }
+
+ }
+
+ if ((k>0 || k == -1) && mode == 2)
+ {
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, /*(bm.bmBitsPixel == 32)?255:*/pobj->dwAlpha, (pobj->bmBitsPixel == 32 && pobj->Style != ST_BRUSH)?AC_SRC_ALPHA:0};
+ if (mode == 2)
+ OffsetRect(&PRect,mode2offset.x,mode2offset.y);
+ ske_AlphaBlend( preq->hDC,PRect.left,PRect.top,PRect.right-PRect.left,PRect.bottom-PRect.top,
+ memdc,0,0,PRect.right-PRect.left,PRect.bottom-PRect.top,bf);
+ }
+ }
+ }
+ //free GDI resources
+ //--++--
+
+ //free GDI resources
+ {
+
+ if (oldglyph) SelectObject(glyphdc,oldglyph);
+ if (glyphdc) mod_DeleteDC(glyphdc);
+ }
+ if (mode == 2)
+ {
+ SelectObject(memdc,oldbmp);
+ mod_DeleteDC(memdc);
+ DeleteObject(membmp);
+ }
+
+ }
+ if (pobj->plTextList && pobj->plTextList->realCount>0)
+ {
+ int i;
+ HFONT hOldFont;
+ for (i=0; i < pobj->plTextList->realCount; i++)
+ {
+ GLYPHTEXT * gt = (GLYPHTEXT *)pobj->plTextList->items[i];
+ if ( !gt->hFont)
+ {
+ if (gl_plSkinFonts && gl_plSkinFonts->realCount>0)
+ {
+ int j = 0;
+ for (j = 0; j < gl_plSkinFonts->realCount; j++)
+ {
+ SKINFONT * sf;
+ sf = (SKINFONT*)gl_plSkinFonts->items[j];
+ if (sf->szFontID && !strcmp(sf->szFontID,gt->szFontID))
+ {
+ gt->hFont = sf->hFont;
+ break;
+ }
+ }
+ }
+ if ( !gt->hFont) gt->hFont = (HFONT)-1;
+ }
+ if (gt->hFont != (HFONT)-1)
+ {
+ RECT rc = {0};
+ hOldFont = (HFONT)SelectObject(preq->hDC,gt->hFont);
+
+
+
+ if (gt->RelativeFlags&2) rc.left = preq->rcDestRect.right+gt->iLeft;
+ else if (gt->RelativeFlags&1) rc.left = ((preq->rcDestRect.right-preq->rcDestRect.left)>>1)+gt->iLeft;
+ else rc.left = preq->rcDestRect.left+gt->iLeft;
+
+ if (gt->RelativeFlags&8) rc.top = preq->rcDestRect.bottom+gt->iTop;
+ else if (gt->RelativeFlags&4) rc.top = ((preq->rcDestRect.bottom-preq->rcDestRect.top)>>1)+gt->iTop;
+ else rc.top = preq->rcDestRect.top+gt->iTop;
+
+ if (gt->RelativeFlags&32) rc.right = preq->rcDestRect.right+gt->iRight;
+ else if (gt->RelativeFlags&16) rc.right = ((preq->rcDestRect.right-preq->rcDestRect.left)>>1)+gt->iRight;
+ else rc.right = preq->rcDestRect.left+gt->iRight;
+
+ if (gt->RelativeFlags&128) rc.bottom = preq->rcDestRect.bottom+gt->iBottom;
+ else if (gt->RelativeFlags&64) rc.bottom = ((preq->rcDestRect.bottom-preq->rcDestRect.top)>>1)+gt->iBottom;
+ else rc.bottom = preq->rcDestRect.top+gt->iBottom;
+
+ ske_AlphaTextOut(preq->hDC, gt->stText, -1, &rc,gt->dwFlags, gt->dwColor);
+ SelectObject(preq->hDC,hOldFont);
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+
+int ske_AddDescriptorToSkinObjectList (LPSKINOBJECTDESCRIPTOR lpDescr, SKINOBJECTSLIST* Skin)
+{
+ SKINOBJECTSLIST *sk;
+ if (Skin) sk = Skin; else sk = &g_SkinObjectList;
+ if ( !sk) return 0;
+ if (mir_bool_strcmpi(lpDescr->szObjectID,"_HEADER_")) return 0;
+ {//check if new object allready presents.
+ DWORD i=0;
+ for (i=0; i < sk->dwObjLPAlocated;i++)
+ if ( !mir_strcmp(sk->pObjects[i].szObjectID,lpDescr->szObjectID)) return 0;
+ }
+ if (sk->dwObjLPAlocated+1>sk->dwObjLPReserved)
+ { // Realocated list to add space for new object
+
+ sk->pObjects = (SKINOBJECTDESCRIPTOR*)mir_realloc(sk->pObjects,sizeof(SKINOBJECTDESCRIPTOR)*(sk->dwObjLPReserved+1)/*alloc step*/);
+ sk->dwObjLPReserved++;
+ }
+ { //filling new objects field
+ sk->pObjects[sk->dwObjLPAlocated].bType = lpDescr->bType;
+ sk->pObjects[sk->dwObjLPAlocated].Data = NULL;
+ sk->pObjects[sk->dwObjLPAlocated].szObjectID = mir_strdup(lpDescr->szObjectID);
+ // sk->Objects[sk->dwObjLPAlocated].szObjectName = mir_strdup(lpDescr->szObjectName);
+ if (lpDescr->Data != NULL)
+ { //Copy defaults values
+ switch (lpDescr->bType)
+ {
+ case OT_GLYPHOBJECT:
+ {
+ GLYPHOBJECT * obdat;
+ GLYPHOBJECT * gl = (GLYPHOBJECT*)lpDescr->Data;
+ sk->pObjects[sk->dwObjLPAlocated].Data = mir_alloc(sizeof(GLYPHOBJECT));
+ obdat = (GLYPHOBJECT*)sk->pObjects[sk->dwObjLPAlocated].Data;
+ memmove(obdat,gl,sizeof(GLYPHOBJECT));
+ if (gl->szFileName != NULL)
+ {
+ obdat->szFileName = mir_strdup(gl->szFileName);
+ mir_free_and_nil(gl->szFileName);
+ }
+ else obdat->szFileName = NULL;
+
+ obdat->hGlyph = NULL;
+ break;
+ }
+ }
+
+ }
+ }
+ sk->dwObjLPAlocated++;
+ return 1;
+}
+
+static LPSKINOBJECTDESCRIPTOR ske_FindObject(const char * szName, BYTE objType, SKINOBJECTSLIST* Skin)
+{
+ // DWORD i;
+ SKINOBJECTSLIST* sk;
+ sk = (Skin == NULL)?(&g_SkinObjectList):Skin;
+ return skin_FindObjectByRequest((char *)szName,sk->pMaskList);
+}
+
+static LPSKINOBJECTDESCRIPTOR ske_FindObjectByMask(MODERNMASK * pModernMask, BYTE objType, SKINOBJECTSLIST* Skin)
+{
+ // DWORD i;
+ SKINOBJECTSLIST* sk;
+ sk = (Skin == NULL)?(&g_SkinObjectList):Skin;
+ if ( !sk->pMaskList) return NULL;
+ return skin_FindObjectByMask(pModernMask,sk->pMaskList);
+}
+
+LPSKINOBJECTDESCRIPTOR ske_FindObjectByName(const char * szName, BYTE objType, SKINOBJECTSLIST* Skin)
+{
+ DWORD i;
+ SKINOBJECTSLIST* sk;
+ sk = (Skin == NULL)?(&g_SkinObjectList):Skin;
+ for (i=0; i < sk->dwObjLPAlocated; i++)
+ {
+ if (sk->pObjects[i].bType == objType || objType == OT_ANY)
+ {
+ if ( !mir_strcmp(sk->pObjects[i].szObjectID,szName))
+ return &(sk->pObjects[i]);
+ }
+ }
+ return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Paint glyph
+// wParam - LPSKINDRAWREQUEST
+// lParam - possible direct pointer to modern mask
+//////////////////////////////////////////////////////////////////////////
+
+INT_PTR ske_Service_DrawGlyph(WPARAM wParam,LPARAM lParam)
+{
+ LPSKINDRAWREQUEST preq;
+ LPSKINOBJECTDESCRIPTOR pgl;
+ LPGLYPHOBJECT gl;
+ if ( !wParam) return -1;
+ ske_LockSkin();
+ __try
+ {
+ preq = (LPSKINDRAWREQUEST)wParam;
+ if (lParam)
+ pgl = ske_FindObjectByMask((MODERNMASK*)lParam, OT_GLYPHOBJECT,NULL);
+ else
+ pgl = ske_FindObject(preq->szObjectID, OT_GLYPHOBJECT,NULL);
+ if (pgl == NULL) return -1;
+ if (pgl->Data == NULL) return -1;
+ gl = (LPGLYPHOBJECT)pgl->Data;
+ if ((gl->Style&7) == ST_SKIP) return ST_SKIP;
+ if (gl->hGlyph == NULL && gl->hGlyph != (HBITMAP)-1 &&
+ ( (gl->Style&7) == ST_IMAGE
+ || (gl->Style&7) == ST_FRAGMENT
+ || (gl->Style&7) == ST_SOLARIZE ))
+ if (gl->szFileName)
+ {
+ gl->hGlyph = ske_LoadGlyphImage(gl->szFileName);
+ if (gl->hGlyph)
+ {
+ BITMAP bmp = {0};
+ GetObject(gl->hGlyph,sizeof(BITMAP),&bmp);
+ gl->bmBitsPixel = (BYTE)bmp.bmBitsPixel;
+ gl->bmHeight = bmp.bmHeight;
+ gl->bmWidth = bmp.bmWidth;
+ }
+ else
+ gl->hGlyph = (HBITMAP)-1; //invalid
+ }
+ return ske_DrawSkinObject(preq,gl);
+ }
+ __finally
+ {
+ ske_UnlockSkin();
+ }
+ return -1;
+}
+
+
+void ske_PreMultiplyChanells(HBITMAP hbmp,BYTE Mult)
+{
+ BITMAP bmp;
+ BOOL flag = FALSE;
+ BYTE * pBitmapBits;
+ DWORD Len;
+ int bh,bw,y,x;
+
+ GetObject(hbmp, sizeof(BITMAP), (LPSTR)&bmp);
+ bh = bmp.bmHeight;
+ bw = bmp.bmWidth;
+ Len = bh*bw*4;
+ flag = (bmp.bmBits == NULL);
+ if (flag)
+ {
+ pBitmapBits = (LPBYTE)malloc(Len);
+ GetBitmapBits(hbmp,Len,pBitmapBits);
+ }
+ else
+ pBitmapBits = (BYTE*)bmp.bmBits;
+ for (y = 0; y < bh; ++y)
+ {
+ BYTE *pPixel = pBitmapBits + bw * 4 * y;
+
+ for (x = 0; x < bw ; ++x)
+ {
+ if (Mult)
+ {
+ pPixel[0] = pPixel[0]*pPixel[3]/255;
+ pPixel[1] = pPixel[1]*pPixel[3]/255;
+ pPixel[2] = pPixel[2]*pPixel[3]/255;
+ }
+ else
+ {
+ pPixel[3] = 255;
+ }
+ pPixel += 4;
+ }
+ }
+ if (flag)
+ {
+ Len = SetBitmapBits(hbmp,Len,pBitmapBits);
+ free (pBitmapBits);
+ }
+ return;
+}
+
+int ske_GetFullFilename(char * buf, char *file, char * skinfolder,BOOL madeAbsolute)
+{
+ char b2[MAX_PATH] = {0};
+ char *SkinPlace = db_get_sa(NULL,SKIN,"SkinFolder");
+ if ( !SkinPlace) SkinPlace = mir_strdup("\\Skin\\default");
+ if (file[0] != '\\' && file[1] != ':')
+ _snprintf(b2, MAX_PATH,"%s\\%s",(skinfolder == NULL)?SkinPlace:((INT_PTR)skinfolder != -1)?skinfolder:"",file);
+ else
+ _snprintf(b2, MAX_PATH,"%s",file);
+ if (madeAbsolute)
+ if (b2[0] == '\\' && b2[1] != '\\')
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)(b2+1), (LPARAM)buf);
+ else
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)(b2), (LPARAM)buf);
+ else
+ memcpy(buf,b2,MAX_PATH);
+
+ mir_free(SkinPlace);
+ return 0;
+}
+
+
+static HBITMAP ske_skinLoadGlyphImage(char * szFileName)
+{
+ if ( !g_CluiData.fGDIPlusFail && !wildcmpi(szFileName,"*.tga"))
+ return GDIPlus_LoadGlyphImage(szFileName);
+ else
+ return ske_LoadGlyphImageByDecoders(szFileName);
+}
+
+/*
+This function is required to load TGA to dib buffer myself
+Major part of routines is from http://tfcduke.developpez.com/tutoriel/format/tga/fichiers/tga.c
+*/
+
+static BOOL ske_ReadTGAImageData(void * From, DWORD fromSize, BYTE * destBuf, DWORD bufSize, BOOL RLE)
+{
+ BYTE * pos = destBuf;
+ BYTE * from = fromSize?(BYTE*)From:NULL;
+ FILE * fp = !fromSize?(FILE*)From:NULL;
+ DWORD destCount = 0;
+ DWORD fromCount = 0;
+ if ( !RLE)
+ {
+ while (((from && fromCount < fromSize) || (fp && fromCount < bufSize))
+ && (destCount < bufSize))
+ {
+ BYTE r = from?from[fromCount++]:(BYTE)fgetc(fp);
+ BYTE g = from?from[fromCount++]:(BYTE)fgetc(fp);
+ BYTE b = from?from[fromCount++]:(BYTE)fgetc(fp);
+ BYTE a = from?from[fromCount++]:(BYTE)fgetc(fp);
+ pos[destCount++] = r;
+ pos[destCount++] = g;
+ pos[destCount++] = b;
+ pos[destCount++] = a;
+
+ if (destCount>bufSize) break;
+ if (from) if (fromCount < fromSize) break;
+ }
+ }
+ else
+ {
+ BYTE rgba[4];
+ BYTE packet_header;
+ BYTE *ptr = pos;
+ BYTE size;
+ int i;
+ while (ptr < pos + bufSize)
+ {
+ /* read first byte */
+ packet_header = from?from[fromCount]:(BYTE)fgetc(fp);
+ if (from) from++;
+ size = 1 + (packet_header & 0x7f);
+ if (packet_header & 0x80)
+ {
+ /* run-length packet */
+ if (from)
+ {
+ *((DWORD*)rgba) = *((DWORD*)(from+fromCount));
+ fromCount += 4;
+ }
+ else fread (rgba, sizeof (BYTE), 4, fp);
+ for (i=0; i < size; ++i, ptr += 4)
+ {
+ ptr[2] = rgba[2];
+ ptr[1] = rgba[1];
+ ptr[0] = rgba[0];
+ ptr[3] = rgba[3];
+ }
+ }
+ else
+ { /* not run-length packet */
+ for (i=0; i < size; ++i, ptr += 4)
+ {
+ ptr[0] = from? from[fromCount++]:(BYTE)fgetc (fp);
+ ptr[1] = from? from[fromCount++]:(BYTE)fgetc (fp);
+ ptr[2] = from? from[fromCount++]:(BYTE)fgetc (fp);
+ ptr[3] = from? from[fromCount++]:(BYTE)fgetc (fp);
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+static HBITMAP ske_LoadGlyphImage_TGA(char * szFilename)
+{
+ BYTE *colormap = NULL;
+ int cx = 0,cy = 0;
+ BOOL err = FALSE;
+ tga_header_t header;
+ if ( !szFilename) return NULL;
+ if ( !wildcmpi(szFilename,"*\\*%.tga"))
+ {
+ //Loading TGA image from file
+ FILE *fp;
+ fp = fopen (szFilename, "rb");
+ if ( !fp)
+ {
+ TRACEVAR("error: couldn't open \"%s\"!\n", szFilename);
+ return NULL;
+ }
+ /* read header */
+ fread (&header, sizeof (tga_header_t), 1, fp);
+ if ( (header.pixel_depth != 32)
+ || ((header.image_type != 10) && (header.image_type != 2))
+ )
+ {
+ fclose(fp);
+ return NULL;
+ }
+
+ /*memory allocation */
+ colormap = (BYTE*)malloc(header.width*header.height*4);
+ cx = header.width;
+ cy = header.height;
+ fseek (fp, header.id_lenght, SEEK_CUR);
+ fseek (fp, header.cm_length, SEEK_CUR);
+ err = !ske_ReadTGAImageData((void*)fp, 0, colormap, header.width*header.height*4,header.image_type == 10);
+ fclose(fp);
+ }
+
+
+ else
+ {
+ /* reading from resources IDR_TGA_DEFAULT_SKIN */
+ DWORD size = 0;
+ BYTE * mem;
+ HGLOBAL hRes;
+ HRSRC hRSrc = FindResourceA(g_hInst,MAKEINTRESOURCEA(IDR_TGA_DEFAULT_SKIN),"TGA");
+ if ( !hRSrc) return NULL;
+ hRes = LoadResource(g_hInst,hRSrc);
+ if ( !hRes) return NULL;
+ size = SizeofResource(g_hInst,hRSrc);
+ mem = (BYTE*) LockResource(hRes);
+ if (size>sizeof(header))
+ {
+ tga_header_t * header = (tga_header_t *)mem;
+ if (header->pixel_depth == 32 && (header->image_type == 2 || header->image_type == 10))
+ {
+ colormap = (BYTE*)malloc(header->width*header->height*4);
+ cx = header->width;
+ cy = header->height;
+ ske_ReadTGAImageData((void*)(mem+sizeof(tga_header_t)+header->id_lenght+header->cm_length), size-(sizeof(tga_header_t)+header->id_lenght+header->cm_length), colormap, cx*cy*4,header->image_type == 10);
+ }
+ }
+ FreeResource(hRes);
+ }
+ if (colormap) //create dib section
+ {
+ BYTE * pt;
+ HBITMAP hbmp = ske_CreateDIB32Point(cx,cy,(void**)&pt);
+ if (hbmp) memcpy(pt,colormap,cx*cy*4);
+ free(colormap);
+ return hbmp;
+ }
+ return NULL;
+}
+
+
+//this function is required to load PNG to dib buffer myself
+HBITMAP ske_LoadGlyphImage_Png2Dib(char * szFilename)
+{
+
+ {
+ HANDLE hFile, hMap = NULL;
+ BYTE* ppMap = NULL;
+ long cbFileSize = 0;
+ BITMAPINFOHEADER* pDib;
+ BYTE* pDibBits;
+
+ if ( !ServiceExists( MS_PNG2DIB )) {
+ MessageBox( NULL, TranslateT( "You need an image services plugin to process PNG images." ), TranslateT( "Error" ), MB_OK );
+ return (HBITMAP)NULL;
+ }
+
+ if (( hFile = CreateFileA( szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL )) != INVALID_HANDLE_VALUE )
+ if (( hMap = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL )) != NULL )
+ if (( ppMap = ( BYTE* )MapViewOfFile( hMap, FILE_MAP_READ, 0, 0, 0 )) != NULL )
+ cbFileSize = GetFileSize( hFile, NULL );
+
+ if ( cbFileSize != 0 ) {
+ PNG2DIB param;
+ param.pSource = ppMap;
+ param.cbSourceSize = cbFileSize;
+ param.pResult = &pDib;
+ if ( CallService( MS_PNG2DIB, 0, ( LPARAM )&param ))
+ pDibBits = ( BYTE* )( pDib+1 );
+ else
+ cbFileSize = 0;
+ }
+
+ if ( ppMap != NULL ) UnmapViewOfFile( ppMap );
+ if ( hMap != NULL ) CloseHandle( hMap );
+ if ( hFile != NULL ) CloseHandle( hFile );
+
+ if ( cbFileSize == 0 )
+ return (HBITMAP)NULL;
+
+ {
+ BITMAPINFO* bi = ( BITMAPINFO* )pDib;
+ BYTE *pt = (BYTE*)bi;
+ pt += bi->bmiHeader.biSize;
+ if (bi->bmiHeader.biBitCount != 32)
+ {
+ HDC sDC = GetDC( NULL );
+ HBITMAP hBitmap = CreateDIBitmap( sDC, pDib, CBM_INIT, pDibBits, bi, DIB_PAL_COLORS );
+ SelectObject( sDC, hBitmap );
+ DeleteDC( sDC );
+ GlobalFree( pDib );
+ return hBitmap;
+ }
+ else
+ {
+ BYTE * ptPixels = pt;
+ HBITMAP hBitmap = CreateDIBSection(NULL,bi, DIB_RGB_COLORS, (void **)&ptPixels, NULL, 0);
+ memcpy(ptPixels,pt,bi->bmiHeader.biSizeImage);
+ GlobalFree( pDib );
+ return hBitmap;
+ }
+ }
+ }
+}
+
+static HBITMAP ske_LoadGlyphImageByDecoders(char * szFileName)
+{
+ // Loading image from file by imgdecoder...
+ HBITMAP hBitmap = NULL;
+ char ext[5];
+ BYTE f = 0;
+ LPBYTE pBitmapBits;
+ LPVOID pImg = NULL;
+ LPVOID m_pImgDecoder;
+
+ BITMAP bmpInfo;
+ {
+ int l;
+ l = mir_strlen(szFileName);
+ memmove(ext,szFileName +(l-4),5);
+ }
+ if ( !strchr(szFileName,'%') && !PathFileExistsA(szFileName)) return NULL;
+ if (mir_bool_strcmpi(ext,".tga"))
+ {
+ hBitmap = ske_LoadGlyphImage_TGA(szFileName);
+ f = 1;
+ }
+ else if (ServiceExists("Image/Png2Dib") && mir_bool_strcmpi(ext,".png"))
+ {
+ hBitmap = ske_LoadGlyphImage_Png2Dib(szFileName);
+ GetObject(hBitmap, sizeof(BITMAP), &bmpInfo);
+ f = (bmpInfo.bmBits != NULL);
+ // hBitmap = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)szFileName);
+ // f = 1;
+
+ }
+ else if (hImageDecoderModule == NULL || !mir_bool_strcmpi(ext,".png"))
+ hBitmap = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)szFileName);
+ else
+ {
+ f = 1;
+ ImgNewDecoder(&m_pImgDecoder);
+ if ( !ImgNewDIBFromFile(m_pImgDecoder, szFileName, &pImg))
+ {
+ ImgGetHandle(pImg, &hBitmap, (LPVOID *)&pBitmapBits);
+ ImgDeleteDecoder(m_pImgDecoder);
+ }
+ }
+ if (hBitmap)
+ {
+
+ GetObject(hBitmap, sizeof(BITMAP), &bmpInfo);
+ if (bmpInfo.bmBitsPixel == 32)
+ ske_PreMultiplyChanells(hBitmap,f);
+ else
+ {
+ HDC dc24,dc32;
+ HBITMAP hBitmap32,obmp24,obmp32;
+ dc32 = CreateCompatibleDC(NULL);
+ dc24 = CreateCompatibleDC(NULL);
+ hBitmap32 = ske_CreateDIB32(bmpInfo.bmWidth,bmpInfo.bmHeight);
+ obmp24 = (HBITMAP)SelectObject(dc24,hBitmap);
+ obmp32 = (HBITMAP)SelectObject(dc32,hBitmap32);
+ BitBlt(dc32,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,dc24,0,0,SRCCOPY);
+ SelectObject(dc24,obmp24);
+ SelectObject(dc32,obmp32);
+ mod_DeleteDC(dc24);
+ mod_DeleteDC(dc32);
+ DeleteObject(hBitmap);
+ hBitmap = hBitmap32;
+ ske_PreMultiplyChanells(hBitmap,0);
+ }
+
+ }
+ return hBitmap;
+}
+
+HBITMAP ske_LoadGlyphImage(char * szFileName)
+{
+ // try to find image in loaded
+ DWORD i;
+ HBITMAP hbmp;
+ char szFile [MAX_PATH] = {0};
+ ske_GetFullFilename(szFile,szFileName,g_SkinObjectList.szSkinPlace,TRUE);
+ ske_LockSkin();
+ if (pLoadedImages)
+ {
+ for (i=0; i < dwLoadedImagesCount; i++)
+ {
+ if (mir_bool_strcmpi(pLoadedImages[i].szFileName,szFile))
+ {
+ pLoadedImages[i].dwLoadedTimes++;
+ ske_UnlockSkin();
+ return pLoadedImages[i].hGlyph;
+ }
+ }
+ }
+ // load new image
+ hbmp = ske_skinLoadGlyphImage(szFile);
+ if (hbmp == NULL)
+ {
+ ske_UnlockSkin();
+ return NULL;
+ }
+ // add to loaded list
+ if (dwLoadedImagesCount+1>dwLoadedImagesAlocated)
+ {
+ pLoadedImages = (GLYPHIMAGE*)mir_realloc(pLoadedImages,sizeof(GLYPHIMAGE)*(dwLoadedImagesCount+1));
+ if (pLoadedImages) dwLoadedImagesAlocated++;
+ else
+ {
+ ske_UnlockSkin();
+ return NULL;
+ }
+ }
+ pLoadedImages[dwLoadedImagesCount].dwLoadedTimes = 1;
+ pLoadedImages[dwLoadedImagesCount].hGlyph = hbmp;
+ pLoadedImages[dwLoadedImagesCount].szFileName = mir_strdup(szFile);
+ dwLoadedImagesCount++;
+ ske_UnlockSkin();
+ return hbmp;
+}
+
+int ske_UnloadGlyphImage(HBITMAP hbmp)
+{
+ DWORD i;
+ for (i=0; i < dwLoadedImagesCount; i++)
+ {
+ if (hbmp == pLoadedImages[i].hGlyph)
+ {
+ pLoadedImages[i].dwLoadedTimes--;
+ if (pLoadedImages[i].dwLoadedTimes == 0)
+ {
+ LPGLYPHIMAGE gl = &(pLoadedImages[i]);
+ mir_free_and_nil(gl->szFileName);
+ memmove(&(pLoadedImages[i]),&(pLoadedImages[i+1]),sizeof(GLYPHIMAGE)*(dwLoadedImagesCount-i-1));
+ dwLoadedImagesCount--;
+ DeleteObject(hbmp);
+ if (pLoadedImages && dwLoadedImagesCount == 0)
+ {
+ dwLoadedImagesAlocated = 0;
+ mir_free_and_nil(pLoadedImages);
+ }
+ }
+ return 0;
+ }
+
+ }
+ DeleteObject(hbmp);
+ return 0;
+}
+
+int ske_UnloadSkin(SKINOBJECTSLIST * Skin)
+{
+ DWORD i;
+ ske_LockSkin();
+ ClearMaskList(Skin->pMaskList);
+
+ //clear font list
+ if (gl_plSkinFonts && gl_plSkinFonts->realCount > 0) {
+ for (int i=0; i < gl_plSkinFonts->realCount; i++) {
+ SKINFONT * sf = (SKINFONT *)gl_plSkinFonts->items[i];
+ if (sf) {
+ mir_free(sf->szFontID);
+ DeleteObject(sf->hFont);
+ mir_free(sf);
+ }
+ }
+ List_Destroy(gl_plSkinFonts);
+ mir_free_and_nil(gl_plSkinFonts);
+ }
+
+ mir_free_and_nil(Skin->szSkinPlace);
+ if (Skin->pTextList) List_Destroy(Skin->pTextList);
+ mir_free_and_nil(Skin->pTextList);
+ ModernSkinButtonDeleteAll();
+ if (Skin->dwObjLPAlocated == 0) { ske_UnlockSkin(); return 0;}
+ for (i=0; i < Skin->dwObjLPAlocated; i++)
+ {
+ switch(Skin->pObjects[i].bType)
+ {
+ case OT_GLYPHOBJECT:
+ {
+ GLYPHOBJECT * dt;
+ dt = (GLYPHOBJECT*)Skin->pObjects[i].Data;
+ if (dt->hGlyph && dt->hGlyph != (HBITMAP)-1)
+ ske_UnloadGlyphImage(dt->hGlyph);
+ dt->hGlyph = NULL;
+ mir_free_and_nil(dt->szFileName);
+ {// delete texts
+ int i;
+ if (dt->plTextList && dt->plTextList->realCount>0)
+ {
+ for (i=0; i < dt->plTextList->realCount; i++)
+ {
+ GLYPHTEXT * gt = (GLYPHTEXT *)dt->plTextList->items[i];
+ if (gt) {
+ mir_free(gt->stText);
+ mir_free(gt->stValueText);
+ mir_free(gt->szFontID);
+ mir_free(gt->szGlyphTextID);
+ mir_free(gt);
+ }
+ }
+ List_Destroy(dt->plTextList);
+ mir_free(dt->plTextList);
+ }
+ }
+ mir_free(dt);
+ }
+ break;
+ }
+ mir_free_and_nil(Skin->pObjects[i].szObjectID);
+
+ }
+ mir_free_and_nil(Skin->pObjects);
+ Skin->pTextList = NULL;
+ Skin->dwObjLPAlocated = 0;
+ Skin->dwObjLPReserved = 0;
+ ske_UnlockSkin();
+ return 0;
+}
+
+static void RegisterMaskByParce(const char * szSetting, char * szValue, SKINOBJECTSLIST * pSkin)
+{
+ int i;
+ DWORD ID=atoi(szSetting+1);
+ for (i=0; i < mir_strlen(szValue); i++) if (szValue[i] == ':') break;
+ if (i < mir_strlen(szValue))
+ {
+ char * Obj, *Mask;
+ int res;
+ Mask = szValue+i+1;
+ Obj = (char*)mir_alloc(i+1);
+ strncpy(Obj,szValue,i);
+ Obj[i] = '\0';
+ res = AddStrModernMaskToList(ID,Mask,Obj,pSkin->pMaskList,pSkin);
+ mir_free(Obj);
+ }
+}
+
+static int ske_ProcessLoadindString(const char * szSetting, char *szValue)
+{
+ if ( !pCurrentSkin) return 0;
+ if (szSetting[0] == '$')
+ RegisterObjectByParce((char *)szSetting, szValue);
+ else if (szSetting[0] == '#')
+ RegisterButtonByParce((char *)szSetting,szValue);
+ else if (szSetting[0] == '@')
+ RegisterMaskByParce((char *)szSetting, szValue, pCurrentSkin); ///
+ else if (szSetting[0] == 't')
+ ske_AddParseTextGlyphObject((char*)szSetting,szValue,pCurrentSkin);
+ else if (szSetting[0] == 'f')
+ ske_AddParseSkinFont((char*)szSetting,szValue,pCurrentSkin);
+ else return 0;
+ return 1;
+}
+static int ske_enumdb_SkinObjectsProc (const char *szSetting,LPARAM lParam)
+{
+ char *value;
+ value = db_get_sa(NULL,SKIN,szSetting);
+ ske_ProcessLoadindString(szSetting,value);
+ mir_free_and_nil(value);
+
+ return 0;
+}
+
+static int ske_SortTextGlyphObjectFunc(void * first, void * second)
+{
+ return strcmp(((GLYPHTEXT*)(((int*)first)[0]))->szGlyphTextID,((GLYPHTEXT*)(((int*)second)[0]))->szGlyphTextID);
+}
+
+static void ske_LinkSkinObjects(SKINOBJECTSLIST * pObjectList)
+{
+ DWORD i;
+ // LINK Mask with objects
+ for (i=0; i < pObjectList->pMaskList->dwMaskCnt; i++)
+ {
+ MODERNMASK *mm = &(pObjectList->pMaskList->pl_Masks[i]);
+ void * pObject = (void*) ske_FindObjectByName(mm->szObjectName, OT_ANY, (SKINOBJECTSLIST*) pObjectList);
+ mir_free_and_nil(mm->szObjectName);
+ mm->bObjectFound = TRUE;
+ mm->pObject = pObject;
+ }
+
+ if (pObjectList->pTextList)
+ {
+ int i;
+ // LINK Text with objects
+ for (i=0; i < pObjectList->pTextList->realCount; i++)
+ {
+ GLYPHTEXT * glText;
+ GLYPHOBJECT *globj = NULL;
+ SKINOBJECTDESCRIPTOR * lpobj;
+ glText = (GLYPHTEXT *)pObjectList->pTextList->items[i];
+ lpobj = ske_FindObjectByName(glText->szObjectName,OT_GLYPHOBJECT, pObjectList);
+ mir_free_and_nil(glText->szObjectName);
+ if (lpobj)
+ globj = (GLYPHOBJECT*)lpobj->Data;
+ if (globj)
+ {
+ if ( !globj->plTextList)
+ {
+ globj->plTextList = List_Create(0,1);
+ globj->plTextList->sortFunc = ske_SortTextGlyphObjectFunc;
+ }
+ List_Insert(globj->plTextList,(void*)glText,globj->plTextList->realCount);
+ qsort(globj->plTextList->items,globj->plTextList->realCount,sizeof(void*),(int(*)(const void*, const void*))globj->plTextList->sortFunc);
+ pObjectList->pTextList->items[i] = NULL;
+ }
+ else
+ {
+ GLYPHTEXT *gt = glText;
+ if (gt) {
+ mir_free(gt->stText);
+ mir_free(gt->stValueText);
+ mir_free(gt->szFontID);
+ mir_free(gt->szGlyphTextID);
+ mir_free(gt);
+ }
+ }
+ }
+ List_Destroy(pObjectList->pTextList);
+ mir_free_and_nil(pObjectList->pTextList);
+ }
+}
+// Getting skin objects and masks from DB
+static int ske_GetSkinFromDB(char * szSection, SKINOBJECTSLIST * Skin)
+{
+ if (Skin == NULL) return 0;
+ ske_UnloadSkin(Skin);
+ g_CluiData.fDisableSkinEngine = db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT);
+ //window borders
+ if (g_CluiData.fDisableSkinEngine) {
+ g_CluiData.LeftClientMargin = 0;
+ g_CluiData.RightClientMargin = 0;
+ g_CluiData.TopClientMargin = 0;
+ g_CluiData.BottomClientMargin = 0;
+ } else {
+ //window borders
+ g_CluiData.LeftClientMargin = (int)db_get_b(NULL,"CLUI","LeftClientMargin",SETTING_LEFTCLIENTMARIGN_DEFAULT);
+ g_CluiData.RightClientMargin = (int)db_get_b(NULL,"CLUI","RightClientMargin",SETTING_RIGHTCLIENTMARIGN_DEFAULT);
+ g_CluiData.TopClientMargin = (int)db_get_b(NULL,"CLUI","TopClientMargin",SETTING_TOPCLIENTMARIGN_DEFAULT);
+ g_CluiData.BottomClientMargin = (int)db_get_b(NULL,"CLUI","BottomClientMargin",SETTING_BOTTOMCLIENTMARIGN_DEFAULT);
+ }
+
+ if (g_CluiData.fDisableSkinEngine) return 0;
+
+ Skin->pMaskList = (LISTMODERNMASK*)mir_alloc(sizeof(LISTMODERNMASK));
+ memset(Skin->pMaskList,0,sizeof(LISTMODERNMASK));
+ Skin->szSkinPlace = db_get_sa(NULL,SKIN,"SkinFolder");
+ if ( !Skin->szSkinPlace || (strchr(Skin->szSkinPlace, '%') && !db_get_b(NULL,SKIN,"Modified",0)))
+ {
+ BOOL bOnlyObjects = FALSE;
+ if (Skin->szSkinPlace && strchr(Skin->szSkinPlace, '%'))
+ bOnlyObjects = TRUE;
+ mir_free(Skin->szSkinPlace);
+ Skin->szSkinPlace = mir_strdup("%Default%");
+ ske_LoadSkinFromResource( bOnlyObjects );
+ }
+ //Load objects
+ {
+ DBCONTACTENUMSETTINGS dbces;
+ pCurrentSkin = Skin;
+ dbces.pfnEnumProc = ske_enumdb_SkinObjectsProc;
+ dbces.szModule = SKIN;
+ dbces.ofsSettings = 0;
+ CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces);
+
+ SortMaskList(pCurrentSkin->pMaskList);
+ ske_LinkSkinObjects(pCurrentSkin);
+ }
+ //Load Masks
+ return 0;
+}
+
+//surrogate to be called from outside
+void ske_LoadSkinFromDB(void)
+{
+ ske_GetSkinFromDB(SKIN,&g_SkinObjectList);
+ g_CluiData.dwKeyColor = db_get_dw(NULL,"ModernSettings","KeyColor",(DWORD)SETTING_KEYCOLOR_DEFAULT);
+}
+
+//
+
+static int ske_LoadSkinFromResource(BOOL bOnlyObjects)
+{
+
+ IniParser parser(g_hInst, MAKEINTRESOURCEA(IDR_MSF_DEFAULT_SKIN), "MSF", bOnlyObjects ? IniParser::FLAG_ONLY_OBJECTS : IniParser::FLAG_WITH_SETTINGS );
+ if ( !parser.CheckOK()) return 0;
+
+ ske_DeleteAllSettingInSection("ModernSkin");
+ db_set_s(NULL,SKIN,"SkinFolder","%Default%");
+ db_set_s(NULL,SKIN,"SkinFile","%Default%");
+ parser.Parse( IniParser::WriteStrToDb, 0 );
+ return 0;
+}
+
+//Load data from ini file
+int ske_LoadSkinFromIniFile(TCHAR * szFileName, BOOL bOnlyObjects)
+{
+ TCHAR skinFolder[MAX_PATH] = {0};
+ TCHAR skinFile[MAX_PATH] = {0};
+ if (_tcschr(szFileName,_T('%')))
+ return ske_LoadSkinFromResource( bOnlyObjects );
+
+ IniParser parser( szFileName, bOnlyObjects ? IniParser::FLAG_ONLY_OBJECTS : IniParser::FLAG_WITH_SETTINGS );
+ if ( !parser.CheckOK()) return 0;
+
+ ske_DeleteAllSettingInSection("ModernSkin");
+ IniParser::GetSkinFolder(szFileName,skinFolder);
+ CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)szFileName, (LPARAM)skinFile);
+
+ db_set_ws(NULL,SKIN,"SkinFolder", skinFolder);
+ db_set_ws(NULL,SKIN,"SkinFile", skinFile);
+
+ parser.Parse( IniParser::WriteStrToDb, 1 );
+
+ return 0;
+}
+
+
+static int ske_enumdb_SkinSectionDeletionProc (const char *szSetting,LPARAM lParam)
+{
+
+ if (szSetting == NULL){return(0);};
+ nArrayLen++;
+ pszSettingName = (char **)realloc(pszSettingName,nArrayLen*sizeof(char *));
+ pszSettingName[nArrayLen-1] = _strdup(szSetting);
+ return(0);
+};
+static int ske_DeleteAllSettingInSection(char * SectionName)
+{
+ DBCONTACTENUMSETTINGS dbces;
+ nArrayLen = 0;
+ pszSettingName = NULL;
+ dbces.pfnEnumProc = ske_enumdb_SkinSectionDeletionProc;
+ dbces.szModule = SectionName;
+ dbces.ofsSettings = 0;
+
+ CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces);
+
+ //delete all settings
+ if (nArrayLen == 0){return(0);};
+ {
+ int i;
+ for (i=0;i < nArrayLen;i++)
+ {
+ db_unset(0,SectionName,pszSettingName[i]);
+ free(pszSettingName[i]);
+ };
+ free(pszSettingName);
+ pszSettingName = NULL;
+ nArrayLen = 0;
+ };
+ return(0);
+};
+
+
+BOOL ske_TextOutA(HDC hdc, int x, int y, char * lpString, int nCount)
+{
+ TCHAR *buf = (TCHAR *)mir_alloc((2+nCount)*sizeof(TCHAR));
+ BOOL res;
+ MultiByteToWideChar(CallService( MS_LANGPACK_GETCODEPAGE, 0, 0 ), 0, lpString, -1, buf, (2+nCount)*sizeof(TCHAR));
+ res = ske_TextOut(hdc,x,y,buf,nCount);
+ mir_free(buf);
+ return res;
+}
+
+BOOL ske_TextOut(HDC hdc, int x, int y, LPCTSTR lpString, int nCount)
+{
+ int ta;
+ SIZE sz;
+ RECT rc = {0};
+ if ( !g_CluiData.fGDIPlusFail && 0) ///text via gdi+
+ {
+ TextOutWithGDIp(hdc,x,y,lpString,nCount);
+ return 0;
+ }
+ else
+
+ {
+ // return TextOut(hdc, x,y,lpString,nCount);
+ GetTextExtentPoint32(hdc,lpString,nCount,&sz);
+ ta = GetTextAlign(hdc);
+ SetRect(&rc,x,y,x+sz.cx,y+sz.cy);
+ ske_DrawText(hdc,lpString,nCount,&rc,DT_NOCLIP|DT_SINGLELINE|DT_LEFT);
+ }
+ return 1;
+}
+
+static INT_PTR ske_Service_AlphaTextOut(WPARAM wParam,LPARAM lParam)
+{
+ if ( !wParam) return 0;
+ {
+ AlphaTextOutParams ap = *(AlphaTextOutParams*)wParam;
+ return ske_AlphaTextOut(ap.hDC,ap.lpString,ap.nCount,ap.lpRect,ap.format,ap.ARGBcolor);
+ }
+}
+
+static __inline void ske_SetMatrix( sbyte * matrix,
+ sbyte a, sbyte b, sbyte c,
+ sbyte d, sbyte e, sbyte f,
+ sbyte g, sbyte h, sbyte i)
+{
+ matrix[0] = a; matrix[1] = b; matrix[2] = c;
+ matrix[3] = d; matrix[4] = e; matrix[5] = f;
+ matrix[6] = g; matrix[7] = h; matrix[8] = i;
+}
+
+static void ske_SetTextEffect(BYTE EffectID, DWORD FirstColor, DWORD SecondColor)
+{
+ if (EffectID>MAXPREDEFINEDEFFECTS) return;
+ if (EffectID == -1) meCurrentEffect.EffectID = -1;
+ else
+ {
+ meCurrentEffect.EffectID = EffectID;
+ meCurrentEffect.EffectMatrix = ModernEffectsEnum[EffectID];
+ meCurrentEffect.EffectColor1 = FirstColor;
+ meCurrentEffect.EffectColor2 = SecondColor;
+ }
+}
+
+BOOL ske_ResetTextEffect(HDC hdc)
+{
+ int i;
+ if ( !pEffectStack || !pEffectStack->realCount) return TRUE;
+ for (i=0; i < pEffectStack->realCount; i++)
+ if (pEffectStack->items[i] && ((EFFECTSSTACKITEM*)(pEffectStack->items[i]))->hdc == hdc)
+ {
+ EFFECTSSTACKITEM * effect = (EFFECTSSTACKITEM*)(pEffectStack->items[i]);
+ mir_free(effect);
+ List_Remove(pEffectStack,i);
+ return TRUE;
+ }
+ return FALSE;
+};
+
+BOOL ske_SelectTextEffect(HDC hdc, BYTE EffectID, DWORD FirstColor, DWORD SecondColor)
+{
+ if (EffectID>MAXPREDEFINEDEFFECTS) return 0;
+ if (EffectID == -1) return ske_ResetTextEffect(hdc);
+ if ( !pEffectStack)
+ {
+ pEffectStack = List_Create(0,1);
+ }
+ {
+ int i;
+ for (i=0; i < pEffectStack->realCount; i++)
+ if (pEffectStack->items[i] && ((EFFECTSSTACKITEM*)(pEffectStack->items[i]))->hdc == hdc)
+ {
+ EFFECTSSTACKITEM * effect = (EFFECTSSTACKITEM*)(pEffectStack->items[i]);
+ effect->EffectID = EffectID;
+ effect->FirstColor = FirstColor;
+ effect->SecondColor = SecondColor;
+ return TRUE;
+ }
+ }
+ {
+ EFFECTSSTACKITEM * effect = (EFFECTSSTACKITEM *) mir_alloc(sizeof(EFFECTSSTACKITEM));
+ effect->hdc = hdc;
+ effect->EffectID = EffectID;
+ effect->FirstColor = FirstColor;
+ effect->SecondColor = SecondColor;
+ List_Insert(pEffectStack, effect, 0);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static BOOL ske_GetTextEffect(HDC hdc, MODERNEFFECT * modernEffect)
+{
+ int i=0;
+ if ( !pEffectStack || !pEffectStack->realCount) return FALSE;
+ if ( !modernEffect) return FALSE;
+ for (i=0; i < pEffectStack->realCount; i++)
+ if (pEffectStack->items[i] && ((EFFECTSSTACKITEM*)(pEffectStack->items[i]))->hdc == hdc)
+ {
+ EFFECTSSTACKITEM * effect = (EFFECTSSTACKITEM*)(pEffectStack->items[i]);
+ modernEffect->EffectID = effect->EffectID;
+ modernEffect->EffectColor1 = effect->FirstColor;
+ modernEffect->EffectColor2 = effect->SecondColor;
+ modernEffect->EffectMatrix = ModernEffectsEnum[effect->EffectID];
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static BOOL ske_DrawTextEffect(BYTE* destPt,BYTE* maskPt, DWORD width, DWORD height, MODERNEFFECT *effect)
+{
+ sbyte *buf;
+ sbyte *outbuf;
+ sbyte *bufline, *buflineTop, *buflineMid;
+ int sign = 0;
+ BYTE *maskline,*destline;
+ BYTE al,rl,gl,bl,ad,rd,gd,bd;
+ int k = 0;
+ DWORD x,y;
+ sbyte *matrix;
+ BYTE mcTopStart;
+ BYTE mcBottomEnd;
+ BYTE mcLeftStart;
+ BYTE mcRightEnd;
+ BYTE effectCount;
+ int minX = width;
+ int maxX = 0;
+ int minY = height;
+ int maxY = 0;
+ if (effect->EffectID == 0xFF) return FALSE;
+ if ( !width || ! height) return FALSE;
+ if ( !destPt) return FALSE;
+ buf = (sbyte*)malloc(width*height*sizeof(BYTE));
+ {
+ matrix = effect->EffectMatrix.matrix;
+ mcTopStart = 2-effect->EffectMatrix.topEffect;
+ mcBottomEnd = 3+effect->EffectMatrix.bottomEffect;
+ mcLeftStart = 2-effect->EffectMatrix.leftEffect;
+ mcRightEnd = 3+effect->EffectMatrix.rightEffect;
+ effectCount = effect->EffectMatrix.cycleCount;
+ }
+ al = 255-((BYTE)(effect->EffectColor1>>24));
+ rl = GetRValue(effect->EffectColor1);
+ gl = GetGValue(effect->EffectColor1);
+ bl = GetBValue(effect->EffectColor1);
+ rd = GetRValue(effect->EffectColor2);
+ gd = GetGValue(effect->EffectColor2);
+ bd = GetBValue(effect->EffectColor2);
+ ad = 255-((BYTE)(effect->EffectColor2>>24));
+ rd = GetRValue(effect->EffectColor2);
+ gd = GetGValue(effect->EffectColor2);
+ bd = GetBValue(effect->EffectColor2);
+
+ //Fill buffer by mid values of image
+ for (y = 0; y < height; y++)
+ {
+ bufline = buf+y*width;
+ maskline = maskPt+((y*width) << 2);
+ for (x = 0; x < width; x++)
+ {
+ BYTE a = (sbyte)(DWORD)((maskline[0]+maskline[2]+maskline[1]+maskline[1])>>4);
+ *bufline = a;
+ if (a != 0)
+ {
+ minX = min((int)x,minX);
+ minY = min((int)y,minY);
+ maxX = max((int)x,maxX);
+ maxY = max((int)y,maxY);
+ }
+ bufline++;
+ maskline += 4;
+ }
+ }
+ //Here perform effect on buffer and place results to outbuf
+ for (k = 0; k < (effectCount&0x7F); k++)
+ {
+ minX = max( 0, minX + mcLeftStart - 2 );
+ minY = max( 0, minY + mcTopStart - 2 );
+ maxX = min((int)width, maxX + mcRightEnd - 1 );
+ maxY = min((int)height, maxY + mcBottomEnd - 1 );
+
+ outbuf = (sbyte*)malloc(width*height*sizeof(sbyte));
+ memset(outbuf,0,width*height*sizeof(sbyte));
+ for (y = (DWORD)minY; y < (DWORD)maxY; y++)
+ {
+ int val;
+ bufline = outbuf+y*width+minX;
+ buflineMid = buf+y*width+minX;
+ for (x = (DWORD)minX; x < (DWORD)maxX; x++)
+ {
+ int matrixHor,matrixVer;
+ val = 0;
+ for (matrixVer = mcTopStart; matrixVer < mcBottomEnd; matrixVer++)
+ {
+ int buflineStep = width*(matrixVer-2);
+ int as = y+matrixVer-2;
+ sbyte * buflineTopS = NULL;
+ if (as >= 0 && (DWORD)as < height) buflineTopS = buflineMid+buflineStep;
+
+ for (matrixHor = mcLeftStart; matrixHor < mcRightEnd;matrixHor++)
+ {
+ int a = as;
+ buflineTop = buflineTopS;
+ a = x+matrixHor-2;
+ if (buflineTop && a >= 0 && (DWORD)a < width) buflineTop += matrixHor-2;
+ else buflineTop = NULL;
+ if (buflineTop)
+ val += ((*buflineTop)*matrix[matrixVer*5+matrixHor]);
+ }
+ }
+ val = (val+1)>>5;
+ *bufline = (sbyte)((val>127)?127:(val < -125)?-125:val);
+ bufline++;
+ buflineMid++;
+ }
+ }
+ free(buf);
+ buf = outbuf;
+ }
+ {
+ BYTE r1,b1,g1,a1;
+ b1 = bl; r1 = rl; g1 = gl; a1 = al; sign = 1;
+ //perform out to dest
+ for (y = 0; y < height; y++)
+ {
+ bufline = buf+y*width;
+ destline = destPt+((y*width) << 2);
+ for (x = 0; x < width; x++)
+ {
+ sbyte val = *bufline;
+ BYTE absVal = ((val < 0)?-val:val);
+
+ if (val != 0)
+ {
+ if (val>0 && sign < 0)
+ { b1 = bl; r1 = rl; g1 = gl; a1 = al; sign = 1;}
+ else if (val < 0 && sign>0)
+ { b1 = bd; r1 = rd; g1 = gd; a1 = ad; sign = -1;}
+
+ absVal = absVal*a1/255;
+
+ destline[0] = ((destline[0]*(128-absVal))+absVal*b1)>>7;
+ destline[1] = ((destline[1]*(128-absVal))+absVal*g1)>>7;
+ destline[2] = ((destline[2]*(128-absVal))+absVal*r1)>>7;
+ destline[3] += ((255-destline[3])*(a1*absVal))/32640;
+ }
+ bufline++;
+ destline += 4;
+ }
+ }
+ free(buf);
+ }
+ return FALSE;
+}
+
+static int ske_AlphaTextOut (HDC hDC, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format, DWORD ARGBcolor)
+{
+ if ( !( lpString && lpRect ))
+ {
+ DebugBreak();
+ return 0;
+ }
+
+ // Step first fill fast calc correction tables:
+ static bool _tables_empty = true;
+ static BYTE gammaTbl[256]; // Gamma correction table
+ static WORD blueMulTbl[256]; // blue coefficient multiplication table
+ static WORD greenMulTbl[256]; // green coefficient multiplication table
+ static WORD redMulTbl[256]; // red coefficient multiplication table
+ if ( _tables_empty )
+ {
+ // fill tables
+ double gammaCfPw = 1000 / (double)DBGetContactSettingRangedWord(NULL,"ModernData","AlphaTextOutGamma", 700, 1, 5000 );
+ BYTE blueCf = db_get_b(NULL,"ModernData","AlphaTextOutBlueCorrection", 28 );
+ BYTE redCf = db_get_b(NULL,"ModernData","AlphaTextOutRed Correction", 77 );
+ BYTE greenCf = db_get_b(NULL,"ModernData","AlphaTextOutGreen Correction", 151 );
+
+ for ( int i=0; i < 256; i++ )
+ {
+ gammaTbl[i] = (BYTE)( 255 * pow((double)i / 255, gammaCfPw ));
+ blueMulTbl[i] = i * blueCf;
+ redMulTbl[i] = i * redCf;
+ greenMulTbl[i] = i * greenCf;
+ }
+ }
+
+ // Calc len of input string
+ if ( nCount == -1 ) nCount = lstrlen( lpString );
+
+ // retrieve destination bitmap bits
+ HBITMAP hDestBitmap = (HBITMAP) GetCurrentObject( hDC, OBJ_BITMAP );
+ BITMAP bmpDest;
+ GetObject( hDestBitmap, sizeof(BITMAP), &bmpDest );
+
+ BOOL destHasNotDIB = FALSE;
+ BYTE * pDestBits = NULL;
+ if ( bmpDest.bmBits == NULL )
+ {
+ destHasNotDIB = TRUE;
+ pDestBits = (BYTE*) malloc ( bmpDest.bmHeight * bmpDest.bmWidthBytes );
+ GetBitmapBits( hDestBitmap, bmpDest.bmHeight*bmpDest.bmWidthBytes, pDestBits );
+ }
+ else
+ pDestBits = (BYTE*)bmpDest.bmBits;
+
+ BOOL isDest16bit = ( bmpDest.bmBitsPixel ) != 32;
+
+
+ // Creating offscreen buffer
+ HDC hOffscreenDC = CreateCompatibleDC( hDC );
+
+ // Font to be used to draw text
+ HFONT hFont = (HFONT)GetCurrentObject( hDC, OBJ_FONT);
+ HFONT hOldOffscreenFont = (HFONT)SelectObject( hOffscreenDC, hFont );
+
+ // Calculating text geometric size
+ RECT workRect = *lpRect;
+ int workRectWidth = workRect.right - workRect.left;
+ int workRectHeight = workRect.bottom - workRect.top;
+
+ if ( workRectWidth <= 0 || workRectHeight <= 0 )
+ return 0;
+
+ SIZE textSize;
+ GetTextExtentPoint32( hOffscreenDC, lpString, nCount, &textSize );
+
+ LPCTSTR lpWorkString = lpString;
+ BOOL bNeedFreeWorkString = FALSE;
+
+ // if we need to cut the text with ellipsis
+ if (( format&DT_END_ELLIPSIS ) && textSize.cx > workRectWidth )
+ {
+ // Calc geometric width of ellipsis
+ SIZE szEllipsis;
+ GetTextExtentPoint32A(hOffscreenDC,"...",3,&szEllipsis);
+ szEllipsis.cx++; // CORRECTION: some width correction
+
+ // Calc count of visible chars
+ int visibleCharCount = nCount;
+ if ( workRectWidth > szEllipsis.cx)
+ {
+ GetTextExtentExPoint( hOffscreenDC, lpString, nCount,
+ workRectWidth - szEllipsis.cx,
+ &visibleCharCount, NULL, &textSize );
+ }
+ else
+ {
+ GetTextExtentExPoint( hOffscreenDC, lpString, nCount,
+ 0, &visibleCharCount, NULL, &textSize);
+ }
+
+ // replace end of string by elipsis
+ bNeedFreeWorkString = TRUE;
+ lpWorkString = (TCHAR*) malloc(( visibleCharCount + 4) * sizeof(TCHAR));
+
+ memcpy((void*) lpWorkString, lpString, visibleCharCount * sizeof(TCHAR));
+ memcpy((void*) ( lpWorkString + visibleCharCount ), _T("..."), 4 * sizeof(TCHAR)); // 3 + 1
+
+ nCount = visibleCharCount + 3;
+ }
+
+ // Calc sizes and offsets
+
+ textSize.cx += 2; // CORRECTION: for italic
+
+ int drx = 0; // x-axis offset of draw point
+
+ if ( workRectWidth > textSize.cx )
+ {
+ if ( format & ( DT_RIGHT | DT_RTLREADING ))
+ {
+ drx = workRectWidth - textSize.cx;
+ }
+ else if ( format & DT_CENTER )
+ {
+ drx = ( workRectWidth - textSize.cx ) >> 1;
+ }
+ }
+ else
+ {
+ textSize.cx = workRectWidth;
+ }
+
+ int dry = 0; // y-axis offset of draw point
+
+ if ( workRectHeight > textSize.cy )
+ {
+ if ( format & DT_BOTTOM )
+ {
+ dry = workRectHeight - textSize.cy;
+ }
+ else if ( format & DT_VCENTER )
+ {
+ dry = ( workRectHeight - textSize.cy ) >> 1;
+ }
+ }
+ else
+ {
+ textSize.cy = workRectHeight;
+ }
+
+ textSize.cx += 4; // CORRECTION: for effects ???
+ textSize.cy += 4; // CORRECTION: for effects ???
+
+ if ( textSize.cx > 0 && textSize.cy > 0 ) // Ok we need to paint
+ {
+ // probably here are mess ofscreen and temp buff dc
+
+ //Create bitmap image for offscreen
+ BYTE * bits = NULL;
+ HBITMAP hbmp = ske_CreateDIB32Point( textSize.cx, textSize.cy, (void**)&bits );
+ if ( bits != NULL )
+ {
+ HBITMAP holdbmp = (HBITMAP)SelectObject( hOffscreenDC, hbmp );
+
+ //Create buffer bitmap image for temp text
+ BYTE * bufbits = NULL;
+ HBITMAP bufbmp = ske_CreateDIB32Point( textSize.cx, textSize.cy, (void**)&bufbits );
+ if ( bufbits != NULL )
+ {
+ HDC bufDC = CreateCompatibleDC( hDC );
+ HBITMAP bufoldbmp = (HBITMAP)SelectObject( bufDC, bufbmp );
+ HFONT hOldBufFont = (HFONT)SelectObject( bufDC, hFont );
+ SetBkColor( bufDC, RGB( 0, 0, 0 ));
+ SetTextColor( bufDC,RGB(255,255,255));
+
+ // Copy from destination to temp buffer
+ BitBlt( hOffscreenDC, 0, 0, textSize.cx, textSize.cy, hDC, workRect.left + drx - 2, workRect.top + dry - 2, SRCCOPY );
+
+ //Draw text on offscreen bitmap
+ TextOut( bufDC, 2, 2, lpWorkString, nCount);
+
+ MODERNEFFECT effect;
+ if (ske_GetTextEffect( hDC, &effect ))
+ ske_DrawTextEffect( bits, bufbits, textSize.cx, textSize.cy, &effect );
+
+ //RenderText
+ RECT drawRect;
+ drawRect.left = 0; drawRect.top = 0;
+ drawRect.right = textSize.cx;
+ drawRect.bottom = textSize.cy;
+
+ DWORD x,y;
+ DWORD width = textSize.cx;
+ DWORD heigh = textSize.cy;
+
+ BYTE * pDestScanLine;
+ BYTE * pBufScanLine;
+ BYTE * pix;
+ BYTE * bufpix;
+
+ BYTE al = 255 - ((BYTE)( ARGBcolor >> 24 ));
+ BYTE r = GetRValue( ARGBcolor );
+ BYTE g = GetGValue( ARGBcolor );
+ BYTE b = GetBValue( ARGBcolor );
+
+ for ( y = 2; y < heigh - 2; y++ )
+ {
+ int lineBytes = y * (width << 2);
+
+ pDestScanLine = bits + lineBytes;
+ pBufScanLine = bufbits + lineBytes;
+
+ for ( x = 2; x < width - 2; x++)
+ {
+ pix = pDestScanLine + ( x << 2 );
+ bufpix = pBufScanLine + ( x << 2 );
+
+ // Monochromatic
+ BYTE bx = gammaTbl[ bufpix[0] ];
+ BYTE gx = gammaTbl[ bufpix[1] ];
+ BYTE rx = gammaTbl[ bufpix[2] ];
+
+ if ( al != 255 )
+ {
+ bx *= al/255;
+ gx *= al/255;
+ rx *= al/255;
+ }
+ BYTE ax = (BYTE)(( (DWORD)rx*77 + (DWORD)gx * 151 + (DWORD)bx *28 + 128 ) / 256 );
+
+ if (ax)
+ {
+ //Normalize components to gray
+ BYTE axx = 255 - (( r + g + b ) >> 2 ) ; // Coefficient of grayance, more white font - more gray edges
+ WORD atx = ax * (255 - axx);
+ bx = ( atx + bx * axx )/255;
+ gx = ( atx + gx * axx )/255;
+ rx = ( atx + rx * axx )/255;
+
+ short rrx, grx, brx;
+ brx = (short)((b-pix[0])*bx/255);
+ grx = (short)((g-pix[1])*gx/255);
+ rrx = (short)((r-pix[2])*rx/255);
+
+ pix[0] += brx;
+ pix[1] += grx;
+ pix[2] += rrx;
+ pix[3] = (BYTE)(ax+(BYTE)(255-ax)*pix[3]/255);
+ }
+ }
+ }
+
+ //Blit to destination
+ BitBlt( hDC, workRect.left + drx - 2, workRect.top + dry - 2, textSize.cx, textSize.cy, hOffscreenDC, 0, 0, SRCCOPY );
+
+ //free resources
+ SelectObject(bufDC,bufoldbmp);
+ DeleteObject(bufbmp);
+ SelectObject(bufDC, hOldBufFont );
+ mod_DeleteDC(bufDC);
+ }
+ SelectObject(hOffscreenDC,holdbmp);
+ DeleteObject(hbmp);
+ }
+ }
+
+ // Final cleanup
+ SelectObject( hOffscreenDC, hOldOffscreenFont );
+ DeleteDC( hOffscreenDC );
+
+ if ( destHasNotDIB )
+ free( pDestBits );
+
+ if ( bNeedFreeWorkString )
+ free((void*)lpWorkString );
+
+ return 0;
+}
+
+static int ske_DrawTextWithEffectWorker( HDC hdc, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format, MODERNFONTEFFECT * effect )
+{
+ if (format&DT_CALCRECT) return DrawText(hdc,lpString,nCount,lpRect,format);
+
+ if (format&DT_RTLREADING) SetTextAlign(hdc,TA_RTLREADING);
+ DWORD color = GetTextColor(hdc);
+
+ RECT r = *lpRect;
+ OffsetRect(&r,1,1);
+ DWORD form = format;
+ if ( effect && effect->effectIndex )
+ ske_SelectTextEffect( hdc, effect->effectIndex - 1, effect->baseColour, effect->secondaryColour );
+
+ int res = ske_AlphaTextOut(hdc, lpString, nCount, lpRect, form, color );
+
+ if ( effect && effect->effectIndex )
+ ske_ResetTextEffect( hdc );
+
+ return res;
+}
+
+INT_PTR ske_Service_DrawTextWithEffect( WPARAM wParam, LPARAM lParam )
+{
+ DrawTextWithEffectParam * p = ( DrawTextWithEffectParam * ) wParam;
+ if ( p->cbSize != sizeof(DrawTextWithEffectParam))
+ return FALSE;
+ return ske_DrawTextWithEffectWorker( p->hdc, p->lpchText, p->cchText, p->lprc, p->dwDTFormat, p->pEffect );
+}
+
+BOOL ske_DrawTextA(HDC hdc, char * lpString, int nCount, RECT * lpRect, UINT format)
+{
+ TCHAR *buf = mir_a2u(lpString);
+ BOOL res;
+ res = ske_DrawText(hdc,buf,nCount,lpRect,format);
+ mir_free(buf);
+ return res;
+}
+
+
+BOOL ske_DrawText(HDC hdc, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format)
+{
+ DWORD form = 0, color = 0;
+ RECT r = *lpRect;
+ OffsetRect(&r,1,1);
+ if (format&DT_RTLREADING) SetTextAlign(hdc,TA_RTLREADING);
+ if (format&DT_CALCRECT) return DrawText(hdc,lpString,nCount,lpRect,format);
+ if (format&DT_FORCENATIVERENDER || g_CluiData.fDisableSkinEngine)
+ return DrawText(hdc,lpString,nCount,lpRect,format&~DT_FORCENATIVERENDER);
+ form = format;
+ color = GetTextColor(hdc);
+ if ( !g_CluiData.fGDIPlusFail && 0) ///text via gdi+
+ {
+ TextOutWithGDIp(hdc,lpRect->left,lpRect->top,lpString,nCount);
+ return 0;
+ }
+ return ske_AlphaTextOut(hdc,lpString,nCount,lpRect,form,color);
+}
+
+HICON ske_ImageList_GetIcon(HIMAGELIST himl, int i, UINT fStyle)
+{
+ IMAGEINFO imi = {0};
+ BITMAP bm = {0};
+ if ( IsWinVerXPPlus() && i != -1 )
+ {
+ ImageList_GetImageInfo(himl,i,&imi);
+ GetObject(imi.hbmImage,sizeof(bm),&bm);
+ if (bm.bmBitsPixel == 32) //stupid bug of Microsoft
+ // Icons bitmaps are not premultiplied
+ // So Imagelist_AddIcon - premultiply alpha
+ // But incorrect - it is possible that alpha will
+ // be less than color and
+ // ImageList_GetIcon will return overflowed colors
+ // TODO: Direct draw Icon from imagelist without
+ // extracting of icon
+ {
+ BYTE * bits = NULL;
+ bits = (BYTE*)bm.bmBits;
+ if ( !bits)
+ {
+ bits = (BYTE*)malloc(bm.bmWidthBytes*bm.bmHeight);
+ GetBitmapBits(imi.hbmImage,bm.bmWidthBytes*bm.bmHeight,bits);
+ }
+ {
+ int iy;
+ BYTE *bcbits;
+ int wb = ((imi.rcImage.right-imi.rcImage.left)*bm.bmBitsPixel>>3);
+ bcbits = bits+(bm.bmHeight-imi.rcImage.bottom)*bm.bmWidthBytes+(imi.rcImage.left*bm.bmBitsPixel>>3);
+ for (iy = 0; iy < imi.rcImage.bottom-imi.rcImage.top; iy++)
+ {
+ int x;
+ // Dummy microsoft fix - alpha can be less than r,g or b
+ // Looks like color channels in icons should be non-premultiplied with alpha
+ // But AddIcon store it premultiplied (incorrectly cause can be Alpha == 7F, but R,G or B == 80
+ // So i check that alpha is 0x7F and set it to 0x80
+ DWORD *c = ((DWORD*)bcbits);
+ for (x = 0;x < imi.rcImage.right-imi.rcImage.left; x++)
+ {
+ DWORD val = *c;
+ BYTE a = (BYTE)((val)>>24);
+ if (a != 0)
+ {
+ BYTE r = (BYTE)((val&0xFF0000)>>16);
+ BYTE g = (BYTE)((val&0xFF00)>>8);
+ BYTE b = (BYTE)(val&0xFF);
+ if (a < r || a < g || a < b)
+ {
+ a = max(max(r,g),b);
+ val = a << 24|r << 16|g << 8|b;
+ *c = val;
+ }
+ }
+ c++;
+ }
+ bcbits += bm.bmWidthBytes;
+ }
+ }
+ if ( !bm.bmBits)
+ {
+ SetBitmapBits(imi.hbmImage,bm.bmWidthBytes*bm.bmHeight,bits);
+ free(bits);
+ }
+ }
+ }
+ return ImageList_GetIcon(himl,i,ILD_NORMAL);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// This creates new dib image from Imagelist icon ready to alphablend it
+
+HBITMAP ske_ExtractDIBFromImagelistIcon( HIMAGELIST himl,int index, int * outWidth, int * outHeight)
+{
+ return NULL;
+}
+
+BOOL ske_ImageList_DrawEx( HIMAGELIST himl,int i,HDC hdcDst,int x,int y,int dx,int dy,COLORREF rgbBk,COLORREF rgbFg,UINT fStyle)
+{
+ //the routine to directly draw icon from image list without creating icon from there - should be some faster
+
+ if (i < 0) return FALSE;
+
+ if (g_CluiData.fDisableSkinEngine)
+ return ImageList_DrawEx( himl, i, hdcDst, x, y, dx, dy, rgbBk, rgbFg, fStyle);
+
+ BYTE alpha;
+ if (fStyle&ILD_BLEND25) alpha = 64;
+ else if (fStyle&ILD_BLEND50) alpha = 128;
+ else alpha = 255;
+
+ HICON hIcon = ske_ImageList_GetIcon(himl,i,ILD_NORMAL);
+ if (hIcon)
+ {
+ ske_DrawIconEx(hdcDst,x,y,hIcon,dx?dx:GetSystemMetrics(SM_CXSMICON),dy?dy:GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL|(alpha << 24));
+ DestroyIcon(hIcon);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static INT_PTR ske_Service_DrawIconEx(WPARAM wParam,LPARAM lParam)
+{
+ DrawIconFixParam *p = (DrawIconFixParam*)wParam;
+ if ( !p) return 0;
+ return ske_DrawIconEx(p->hdc,p->xLeft,p->yTop,p->hIcon,p->cxWidth,p->cyWidth,p->istepIfAniCur,p->hbrFlickerFreeDraw,p->diFlags);
+}
+
+
+BOOL ske_DrawIconEx(HDC hdcDst,int xLeft,int yTop,HICON hIcon,int cxWidth,int cyWidth, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags)
+{
+
+ ICONINFO ici;
+ BYTE alpha = (BYTE)((diFlags&0xFF000000)>>24);
+
+
+ HDC imDC;
+ HBITMAP oldBmp, imBmp,tBmp;
+ BITMAP imbt,immaskbt;
+ BYTE * imbits;
+ BYTE * imimagbits;
+ BYTE * immaskbits;
+ DWORD cx,cy,icy;
+ BYTE *t1, *t2, *t3;
+
+ BOOL NoDIBImage = FALSE;
+ //lockimagelist
+ BYTE hasmask = FALSE;
+ BYTE no32bit = FALSE;
+ BYTE noMirrorMask = FALSE;
+ BYTE hasalpha = FALSE;
+ alpha = alpha?alpha:255;
+
+ if ( g_CluiData.fDisableSkinEngine && !(diFlags&0x80))
+ return DrawIconEx(hdcDst,xLeft,yTop,hIcon,cxWidth,cyWidth,istepIfAniCur,hbrFlickerFreeDraw,diFlags&0xFFFF7F);
+
+ if ( !GetIconInfo(hIcon,&ici)) return 0;
+
+ GetObject(ici.hbmColor,sizeof(BITMAP),&imbt);
+ if (imbt.bmWidth*imbt.bmHeight == 0)
+ {
+ DeleteObject(ici.hbmColor);
+ DeleteObject(ici.hbmMask);
+ return 0;
+ }
+ GetObject(ici.hbmMask,sizeof(BITMAP),&immaskbt);
+ cy = imbt.bmHeight;
+
+ if (imbt.bmBitsPixel != 32)
+ {
+ HDC tempDC1;
+ HBITMAP otBmp;
+ no32bit = TRUE;
+ tempDC1 = CreateCompatibleDC(hdcDst);
+ tBmp = ske_CreateDIB32(imbt.bmWidth,imbt.bmHeight);
+ if (tBmp)
+ {
+ GetObject(tBmp,sizeof(BITMAP),&imbt);
+ otBmp = (HBITMAP)SelectObject(tempDC1,tBmp);
+ DrawIconEx(tempDC1,0,0,hIcon,imbt.bmWidth,imbt.bmHeight,istepIfAniCur,hbrFlickerFreeDraw,DI_IMAGE);
+ noMirrorMask = TRUE;
+
+ }
+ SelectObject(tempDC1,otBmp);
+ mod_DeleteDC(tempDC1);
+ }
+ /*
+ if (imbt.bmBitsPixel != 32)
+ {
+ HDC tempDC1;
+ HBITMAP otBmp;
+ no32bit = TRUE;
+ tempDC1 = ske_RequestBufferDC(hdcDst,BUFFER_DRAWICON,imbt.bmWidth,imbt.bmHeight);
+ if (tempDC1)
+ {
+ DrawIconEx(tempDC1,0,0,hIcon,imbt.bmWidth,imbt.bmHeight,istepIfAniCur,hbrFlickerFreeDraw,DI_IMAGE);
+ noMirrorMask = TRUE;
+ ske_ReleaseBufferDC(tempDC1,2000); //keep buffer for 2 seconds
+ }
+ }
+ */
+ if (imbt.bmBits == NULL)
+ {
+ NoDIBImage = TRUE;
+ imimagbits = (BYTE*)malloc(cy*imbt.bmWidthBytes);
+ GetBitmapBits(ici.hbmColor,cy*imbt.bmWidthBytes,(void*)imimagbits);
+ }
+ else imimagbits = (BYTE*)imbt.bmBits;
+
+
+ if (immaskbt.bmBits == NULL)
+ {
+ immaskbits = (BYTE*)malloc(cy*immaskbt.bmWidthBytes);
+ GetBitmapBits(ici.hbmMask,cy*immaskbt.bmWidthBytes,(void*)immaskbits);
+ }
+ else
+ immaskbits = (BYTE*)immaskbt.bmBits;
+ icy = imbt.bmHeight;
+ cx = imbt.bmWidth;
+ imDC = CreateCompatibleDC(hdcDst);
+ imBmp = ske_CreateDIB32Point(cx,icy,(void**)&imbits);
+ oldBmp = (HBITMAP)SelectObject(imDC,imBmp);
+ if (imbits != NULL && imimagbits != NULL && immaskbits != NULL)
+ {
+ int x; int y;
+ int bottom,right,top,h;
+ int mwb,mwb2;
+ mwb = immaskbt.bmWidthBytes;
+ mwb2 = imbt.bmWidthBytes;
+ bottom = icy;
+ right = cx;
+ top = 0;
+ h = icy;
+ for (y = top;(y < bottom) && !hasmask; y++)
+ {
+ t1 = immaskbits+y*mwb;
+ for (x = 0; (x < mwb) && !hasmask; x++)
+ hasmask |= (*(t1+x) != 0);
+ }
+
+ for (y = top;(y < bottom) && !hasalpha; y++)
+ {
+ t1 = imimagbits+(cy-y-1)*mwb2;
+ for (x = 0; (x < right) && !hasalpha; x++)
+ hasalpha |= (*(t1+(x << 2)+3) != 0);
+ }
+
+ for (y = 0; y < (int)icy; y++)
+ {
+ t1 = imimagbits+(h-y-1-top)*mwb2;
+ t2 = imbits+(!no32bit?y:(icy-y-1))*mwb2;
+ t3 = immaskbits+(noMirrorMask?y:(h-y-1-top))*mwb;
+ for (x = 0; x < right; x++)
+ {
+ DWORD * src, *dest;
+ BYTE mask = 0;
+ BYTE a = 0;
+ src = (DWORD*)(t1+(x << 2));
+ dest = (DWORD*)(t2+(x << 2));
+ if (hasalpha && !hasmask)
+ a = ((BYTE*)src)[3];
+ else
+ {
+ mask = ((1 << (7-x%8))&(*(t3+(x>>3)))) != 0;
+ if (mask)// && !hasalpha)
+ {
+ if ( !hasalpha)
+ { *dest = 0; continue; }
+ else
+ {
+ if (((BYTE*)src)[3]>0 )
+ a = ((BYTE*)src)[3];
+ else
+ a = 0;
+ }
+ }
+ else if (hasalpha || hasmask)
+ a = (((BYTE*)src)[3]>0?((BYTE*)src)[3]:255);
+ else if ( !hasalpha && !hasmask)
+ a = 255;
+ else { *dest = 0; continue; }
+ }
+ if (a>0)
+ {
+ ((BYTE*)dest)[3] = a;
+ ((BYTE*)dest)[0] = ((BYTE*)src)[0]*a/255;
+ ((BYTE*)dest)[1] = ((BYTE*)src)[1]*a/255;
+ ((BYTE*)dest)[2] = ((BYTE*)src)[2]*a/255;
+ }
+ else
+ *dest = 0;
+ }
+ }
+ }
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, diFlags&128, alpha, AC_SRC_ALPHA };
+ ske_AlphaBlend(hdcDst,xLeft,yTop,cxWidth, cyWidth, imDC,0,0, cx,icy,bf);
+ }
+ if (immaskbt.bmBits == NULL) free(immaskbits);
+ if (imbt.bmBits == NULL) free(imimagbits);
+ SelectObject(imDC,oldBmp);
+ DeleteObject(imBmp);
+ if (no32bit)DeleteObject(tBmp);
+ DeleteObject(ici.hbmColor);
+ DeleteObject(ici.hbmMask);
+ SelectObject(imDC,GetStockObject(DEFAULT_GUI_FONT));
+ mod_DeleteDC(imDC);
+ return 1;// DrawIconExS(hdc,xLeft,yTop,hIcon,cxWidth,cyWidth,istepIfAniCur,hbrFlickerFreeDraw,diFlags);
+}
+
+
+
+int ske_PrepeareImageButDontUpdateIt(RECT * r)
+{
+ if (g_CluiData.fLayered)
+ {
+ mutex_bLockUpdate = 1;
+ ske_DrawNonFramedObjects(TRUE,r);
+ ske_ValidateFrameImageProc(r);
+ mutex_bLockUpdate = 0;
+ return 0;
+ }
+ else
+ {
+ return ske_ReCreateBackImage(FALSE,r);
+ }
+ return 0;
+}
+
+int ske_RedrawCompleteWindow()
+{
+ if (g_CluiData.fLayered)
+ {
+ ske_DrawNonFramedObjects(TRUE,0);
+ CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,0,0);
+ }
+ else
+ {
+ RedrawWindow(pcli->hwndContactList,NULL,NULL,RDW_ALLCHILDREN|RDW_ERASE|RDW_INVALIDATE|RDW_FRAME);
+ }
+ return 0;
+}
+// Request to repaint frame or change/drop callback data
+// wParam = hWnd of called frame
+// lParam = pointer to sPaintRequest (or NULL to redraw all)
+// return 2 - already queued, data updated, 1-have been queued, 0 - failure
+
+static INT_PTR ske_Service_UpdateFrameImage(WPARAM wParam, LPARAM lParam) // Immideately recall paint routines for frame and refresh image
+{
+ if ( MirandaLoading()) return 0;
+
+ RECT wnd;
+ FRAMEWND *frm;
+ BOOL NoCancelPost = 0;
+ BOOL IsAnyQueued = 0;
+ if ( !g_CluiData.mutexOnEdgeSizing)
+ GetWindowRect(pcli->hwndContactList,&wnd);
+ else
+ wnd = g_rcEdgeSizingRect;
+ if ( !g_CluiData.fLayered)
+ {
+ RedrawWindow((HWND)wParam,NULL,NULL,RDW_UPDATENOW|RDW_ERASE|RDW_INVALIDATE|RDW_FRAME);
+ return 0;
+ }
+ if (g_pCachedWindow == NULL) ske_ValidateFrameImageProc(&wnd);
+ else if (g_pCachedWindow->Width != wnd.right-wnd.left || g_pCachedWindow->Height != wnd.bottom-wnd.top) ske_ValidateFrameImageProc(&wnd);
+ else if (wParam == 0) ske_ValidateFrameImageProc(&wnd);
+ else // all Ok Update Single Frame
+ {
+ // TO BE LOCKED OR PROXIED
+ frm = FindFrameByItsHWND((HWND)wParam);
+ if ( !frm) ske_ValidateFrameImageProc(&wnd);
+ // Validate frame, update window image and remove it from queue
+ else
+ {
+ if (frm->UpdateRgn)
+ {
+ DeleteObject(frm->UpdateRgn);
+ frm->UpdateRgn = 0;
+ }
+ ske_ValidateSingleFrameImage(frm,0);
+ ske_UpdateWindowImage();
+ NoCancelPost = 1;
+ //-- Remove frame from queue
+ if (flag_bUpdateQueued)
+ {
+ int i;
+ frm->bQueued = 0;
+ for (i=0;i < g_nFramesCount;i++)
+ if (IsAnyQueued |= g_pfwFrames[i].bQueued) break;
+ }
+ }
+ }
+ if ((!NoCancelPost || !IsAnyQueued) && flag_bUpdateQueued) // no any queued updating cancel post or need to cancel post
+ {
+ flag_bUpdateQueued = 0;
+ g_flag_bPostWasCanceled = 1;
+ }
+ return 1;
+}
+static INT_PTR ske_Service_InvalidateFrameImage(WPARAM wParam, LPARAM lParam) // Post request for updating
+{
+ if ( MirandaLoading()) return 0;
+ if (wParam)
+ {
+ FRAMEWND *frm = FindFrameByItsHWND((HWND)wParam);
+ sPaintRequest * pr = (sPaintRequest*)lParam;
+ if ( !g_CluiData.fLayered || (frm && frm->floating)) return InvalidateRect((HWND)wParam,pr?(RECT*)&(pr->rcUpdate):NULL,FALSE);
+ if (frm)
+ {
+ if (frm->PaintCallbackProc != NULL)
+ {
+ frm->PaintData = (sPaintRequest *)pr;
+ frm->bQueued = 1;
+ if (pr)
+ {
+ HRGN r2;
+ if ( !IsRectEmpty(&pr->rcUpdate))
+ {
+ RECT rcClient;
+ RECT rcUpdate;
+ GetClientRect(frm->hWnd,&rcClient);
+ IntersectRect( &rcUpdate, &rcClient, &pr->rcUpdate );
+ if ( IsRectEmpty( &rcUpdate ))
+ return 0;
+ r2 = CreateRectRgn( rcUpdate.left, rcUpdate.top, rcUpdate.right, rcUpdate.bottom );
+ }
+ else
+ {
+ RECT r;
+ GetClientRect(frm->hWnd,&r);
+ r2 = CreateRectRgn(r.left,r.top,r.right,r.bottom);
+ }
+ if ( !frm->UpdateRgn)
+ {
+ frm->UpdateRgn = CreateRectRgn(0,0,1,1);
+ CombineRgn(frm->UpdateRgn,r2,0,RGN_COPY);
+ }
+ else CombineRgn(frm->UpdateRgn,frm->UpdateRgn,r2,RGN_OR);
+ DeleteObject(r2);
+ }
+
+ }
+ }
+ else
+ {
+ Sync( QueueAllFramesUpdating, (BYTE)1 );
+ }
+ }
+ else
+ Sync( QueueAllFramesUpdating , (BYTE)1 );
+ if ( !flag_bUpdateQueued || g_flag_bPostWasCanceled)
+ if (PostMessage(pcli->hwndContactList,UM_UPDATE,0,0))
+ {
+ flag_bUpdateQueued = 1;
+ g_flag_bPostWasCanceled = 0;
+ }
+ return 1;
+}
+
+
+static int ske_ValidateSingleFrameImage(FRAMEWND * Frame, BOOL SkipBkgBlitting) // Calling frame paint proc
+{
+ if ( !g_pCachedWindow) { TRACE("ske_ValidateSingleFrameImage calling without cached\n"); return 0;}
+ if (Frame->hWnd == (HWND)-1 && !Frame->PaintCallbackProc) { TRACE("ske_ValidateSingleFrameImage calling without FrameProc\n"); return 0;}
+ { // if ok update image
+ HDC hdc;
+ HBITMAP o,n;
+ RECT rcPaint,wnd;
+ RECT ru = {0};
+ int w,h,x,y;
+ int w1,h1,x1,y1;
+
+ CLUI_SizingGetWindowRect(pcli->hwndContactList,&wnd);
+ rcPaint = Frame->wndSize;
+ {
+ int dx,dy,bx,by;
+ if (g_CluiData.mutexOnEdgeSizing)
+ {
+ dx = rcPaint.left-wnd.left;
+ dy = rcPaint.top-wnd.top;
+ bx = rcPaint.right-wnd.right;
+ by = rcPaint.bottom-wnd.bottom;
+ wnd = g_rcEdgeSizingRect;
+ rcPaint.left = wnd.left+dx;
+ rcPaint.top = wnd.top+dy;
+ rcPaint.right = wnd.right+bx;
+ rcPaint.bottom = wnd.bottom+by;
+ }
+ }
+ //OffsetRect(&rcPaint,-wnd.left,-wnd.top);
+ w = rcPaint.right-rcPaint.left;
+ h = rcPaint.bottom-rcPaint.top;
+ if (w <= 0 || h <= 0)
+ {
+ TRACE("Frame size smaller than 0\n");
+ return 0;
+ }
+ x = rcPaint.left;
+ y = rcPaint.top;
+ hdc = CreateCompatibleDC(g_pCachedWindow->hImageDC);
+ n = ske_CreateDIB32(w,h);
+ o = (HBITMAP)SelectObject(hdc,n);
+ {
+ if (Frame->UpdateRgn && !SkipBkgBlitting)
+ {
+ GetRgnBox(Frame->UpdateRgn,&ru);
+ {
+ RECT rc;
+ GetClientRect(Frame->hWnd,&rc);
+ if (ru.top < 0) ru.top = 0;
+ if (ru.left < 0) ru.left = 0;
+ if (ru.right>rc.right) ru.right = rc.right;
+ if (ru.bottom>rc.bottom) ru.bottom = rc.bottom;
+ }
+ if ( !IsRectEmpty(&ru))
+ {
+ x1 = ru.left;
+ y1 = ru.top;
+ w1 = ru.right-ru.left;
+ h1 = ru.bottom-ru.top;
+ }
+ else
+ {x1 = 0; y1 = 0; w1 = w; h1 = h;}
+ // copy image at hdc
+ if (SkipBkgBlitting) //image already at foreground
+ {
+ BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hImageDC,x+x1,y+y1,SRCCOPY);
+ }
+ else
+ {
+ BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hBackDC,x+x1,y+y1,SRCCOPY);
+ }
+ Frame->PaintCallbackProc(Frame->hWnd,hdc,&ru,Frame->UpdateRgn, Frame->dwFlags,Frame->PaintData);
+ }
+ else
+ {
+ HRGN rgnUpdate;
+ RECT r;
+ GetClientRect(Frame->hWnd,&r);
+ rgnUpdate = CreateRectRgn(r.left,r.top,r.right,r.bottom);
+ ru = r;
+ if ( !IsRectEmpty(&ru))
+ {
+ x1 = ru.left;
+ y1 = ru.top;
+ w1 = ru.right-ru.left;
+ h1 = ru.bottom-ru.top;
+ }
+ else
+ {x1 = 0; y1 = 0; w1 = w; h1 = h;}
+ // copy image at hdc
+ if (SkipBkgBlitting) //image already at foreground
+ {
+ BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hImageDC,x+x1,y+y1,SRCCOPY);
+ }
+ else
+ {
+ BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hBackDC,x+x1,y+y1,SRCCOPY);
+ }
+ Frame->PaintCallbackProc(Frame->hWnd,hdc,&r,rgnUpdate, Frame->dwFlags,Frame->PaintData);
+ ru = r;
+ DeleteObject(rgnUpdate);
+ }
+ DeleteObject(Frame->UpdateRgn);
+ Frame->UpdateRgn = 0;
+ }
+ if ( !IsRectEmpty(&ru))
+ {
+ x1 = ru.left;
+ y1 = ru.top;
+ w1 = ru.right-ru.left;
+ h1 = ru.bottom-ru.top;
+ }
+ else
+ {x1 = 0; y1 = 0; w1 = w; h1 = h;}
+ /* if ( !SkipBkgBlitting)
+ {
+ BitBlt(g_pCachedWindow->hImageDC,x+x1,y+y1,w1,h1,g_pCachedWindow->hBackDC,x+x1,y+y1,SRCCOPY);
+ }
+
+ */
+ {
+ //BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ BitBlt(g_pCachedWindow->hImageDC,x+x1,y+y1,w1,h1,hdc,x1,y1,SRCCOPY);
+ //BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ //MyAlphaBlend(g_pCachedWindow->hImageDC,x+x1,y+y1,w1,h1,hdc,x1,y1,w1,h1,bf);
+ }
+
+ if ( fnGetScrollBarInfo && (GetWindowLongPtr(Frame->hWnd,GWL_STYLE) & WS_VSCROLL))
+ {
+ //Draw vertical scroll bar
+ //
+ RECT rThumb;
+ RECT rUpBtn;
+ RECT rDnBtn;
+ RECT rLine;
+ int dx,dy;
+ SCROLLBARINFO si = {0};
+ si.cbSize = sizeof(SCROLLBARINFO);
+ fnGetScrollBarInfo(Frame->hWnd,OBJID_VSCROLL,&si);
+ rLine = (si.rcScrollBar);
+ rUpBtn = rLine;
+ rDnBtn = rLine;
+ rThumb = rLine;
+
+ rUpBtn.bottom = rUpBtn.top+si.dxyLineButton;
+ rDnBtn.top = rDnBtn.bottom-si.dxyLineButton;
+ rThumb.top = rLine.top+si.xyThumbTop;
+ rThumb.bottom = rLine.top+si.xyThumbBottom;
+ {
+ dx = Frame->wndSize.right-rLine.right;
+ dy = -rLine.top+Frame->wndSize.top;
+ }
+ OffsetRect(&rLine,dx,dy);
+ OffsetRect(&rUpBtn,dx,dy);
+ OffsetRect(&rDnBtn,dx,dy);
+ OffsetRect(&rThumb,dx,dy);
+ BitBlt(g_pCachedWindow->hImageDC,rLine.left,rLine.top,rLine.right-rLine.left,rLine.bottom-rLine.top,g_pCachedWindow->hBackDC,rLine.left,rLine.top,SRCCOPY);
+ {
+ char req[255];
+ _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=Back",Frame->szName);
+ SkinDrawGlyph(g_pCachedWindow->hImageDC,&rLine,&rLine,req);
+ _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=Thumb",Frame->szName);
+ SkinDrawGlyph(g_pCachedWindow->hImageDC,&rThumb,&rThumb,req);
+ _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=UpLineButton",Frame->szName);
+ SkinDrawGlyph(g_pCachedWindow->hImageDC,&rUpBtn,&rUpBtn,req);
+ _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=DownLineButton",Frame->szName);
+ SkinDrawGlyph(g_pCachedWindow->hImageDC,&rDnBtn,&rDnBtn,req);
+ }
+ }
+
+ SelectObject(hdc,o);
+ DeleteObject(n);
+ mod_DeleteDC(hdc);
+ }
+ return 1;
+}
+
+int ske_BltBackImage (HWND destHWND, HDC destDC, RECT * BltClientRect)
+{
+ POINT ptMainWnd = {0};
+ POINT ptChildWnd = {0};
+ RECT from = {0};
+ RECT w = {0};
+ if (g_CluiData.fDisableSkinEngine)
+ {
+ FillRect(destDC,BltClientRect,GetSysColorBrush(COLOR_3DFACE));
+ return 0;
+ }
+ ske_ReCreateBackImage(FALSE,NULL);
+ if (BltClientRect) w = *BltClientRect;
+ else GetClientRect(destHWND,&w);
+ ptChildWnd.x = w.left;
+ ptChildWnd.y = w.top;
+ ClientToScreen(destHWND,&ptChildWnd);
+ ClientToScreen(pcli->hwndContactList,&ptMainWnd);
+ //TODO if main not relative to client area
+ return BitBlt(destDC,w.left,w.top,(w.right-w.left),(w.bottom-w.top),g_pCachedWindow->hBackDC,(ptChildWnd.x-ptMainWnd.x),(ptChildWnd.y-ptMainWnd.y),SRCCOPY);
+
+}
+int ske_ReCreateBackImage(BOOL Erase,RECT *w)
+{
+ HBITMAP hb2;
+ RECT wnd = {0};
+ BOOL IsNewCache = 0;
+ if (g_CluiData.fDisableSkinEngine) return 0;
+ GetClientRect(pcli->hwndContactList,&wnd);
+ if (w) wnd = *w;
+ //-- Check cached.
+ if (g_pCachedWindow == NULL)
+ {
+ //-- Create New Cache
+ {
+ g_pCachedWindow = (CURRWNDIMAGEDATA*)mir_calloc(sizeof(CURRWNDIMAGEDATA));
+ g_pCachedWindow->hScreenDC = GetDC(NULL);
+ g_pCachedWindow->hBackDC = CreateCompatibleDC(g_pCachedWindow->hScreenDC);
+ g_pCachedWindow->hImageDC = CreateCompatibleDC(g_pCachedWindow->hScreenDC);
+ g_pCachedWindow->Width = wnd.right-wnd.left;
+ g_pCachedWindow->Height = wnd.bottom-wnd.top;
+ if (g_pCachedWindow->Width != 0 && g_pCachedWindow->Height != 0)
+ {
+ g_pCachedWindow->hImageDIB = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte));
+ g_pCachedWindow->hBackDIB = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte));
+ g_pCachedWindow->hImageOld = (HBITMAP)SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageDIB);
+ g_pCachedWindow->hBackOld = (HBITMAP)SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackDIB);
+ }
+ }
+ IsNewCache = 1;
+ }
+ if (g_pCachedWindow->Width != wnd.right-wnd.left || g_pCachedWindow->Height != wnd.bottom-wnd.top)
+ {
+ HBITMAP hb1 = NULL,hb2 = NULL;
+ g_pCachedWindow->Width = wnd.right-wnd.left;
+ g_pCachedWindow->Height = wnd.bottom-wnd.top;
+ if (g_pCachedWindow->Width != 0 && g_pCachedWindow->Height != 0)
+ {
+ hb1 = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte));
+ hb2 = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte));
+ SelectObject(g_pCachedWindow->hImageDC,hb1);
+ SelectObject(g_pCachedWindow->hBackDC,hb2);
+ }
+ else
+ {
+ SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageOld);
+ SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackOld);
+ }
+ if (g_pCachedWindow->hImageDIB) DeleteObject(g_pCachedWindow->hImageDIB);
+ if (g_pCachedWindow->hBackDIB) DeleteObject(g_pCachedWindow->hBackDIB);
+ g_pCachedWindow->hImageDIB = hb1;
+ g_pCachedWindow->hBackDIB = hb2;
+ IsNewCache = 1;
+ }
+ if ((Erase || IsNewCache ) && (g_pCachedWindow->Width != 0 && g_pCachedWindow->Height != 0))
+ {
+
+ hb2 = ske_CreateDIB32(g_pCachedWindow->Width,g_pCachedWindow->Height);
+ SelectObject(g_pCachedWindow->hBackDC,hb2);
+ DeleteObject(g_pCachedWindow->hBackDIB);
+ g_pCachedWindow->hBackDIB = hb2;
+ FillRect(g_pCachedWindow->hBackDC,&wnd,GetSysColorBrush(COLOR_BTNFACE));
+ SkinDrawGlyph(g_pCachedWindow->hBackDC,&wnd,&wnd,"Main,ID=Background,Opt=Non-Layered");
+ ske_SetRectOpaque(g_pCachedWindow->hBackDC,&wnd);
+ }
+ return 1;
+}
+int ske_DrawNonFramedObjects(BOOL Erase,RECT *r)
+{
+ RECT w,wnd;
+ if (r) w = *r;
+ else CLUI_SizingGetWindowRect(pcli->hwndContactList,&w);
+ if ( !g_CluiData.fLayered) return ske_ReCreateBackImage(FALSE,0);
+ if (g_pCachedWindow == NULL)
+ return ske_ValidateFrameImageProc(&w);
+
+ wnd = w;
+ OffsetRect(&w, -w.left, -w.top);
+ if (Erase)
+ {
+ HBITMAP hb2;
+ hb2 = ske_CreateDIB32(g_pCachedWindow->Width,g_pCachedWindow->Height);
+ SelectObject(g_pCachedWindow->hBackDC,hb2);
+ DeleteObject(g_pCachedWindow->hBackDIB);
+ g_pCachedWindow->hBackDIB = hb2;
+ }
+
+ SkinDrawGlyph(g_pCachedWindow->hBackDC,&w,&w,"Main,ID=Background");
+ //--Draw frames captions
+ {
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ if (g_pfwFrames[i].TitleBar.ShowTitleBar && g_pfwFrames[i].visible && !g_pfwFrames[i].floating)
+ {
+ RECT rc;
+ SetRect(&rc,g_pfwFrames[i].wndSize.left,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar,g_pfwFrames[i].wndSize.right,g_pfwFrames[i].wndSize.top-g_CluiData.nGapBetweenTitlebar);
+ //GetWindowRect(Frames[i].TitleBar.hwnd,&rc);
+ //OffsetRect(&rc,-wnd.left,-wnd.top);
+ Sync( DrawTitleBar, g_pCachedWindow->hBackDC, &rc, g_pfwFrames[i].id );
+ }
+ }
+ g_mutex_bLockUpdating = 1;
+
+ flag_bJustDrawNonFramedObjects = 1;
+ return 0;
+}
+int ske_ValidateFrameImageProc(RECT * r) // Calling queued frame paint procs and refresh image
+{
+ RECT wnd = {0};
+ BOOL IsNewCache = 0;
+ BOOL IsForceAllPainting = 0;
+ if (r) wnd = *r;
+ else GetWindowRect(pcli->hwndContactList,&wnd);
+ if (wnd.right-wnd.left == 0 || wnd.bottom-wnd.top == 0) return 0;
+ g_mutex_bLockUpdating = 1;
+ //-- Check cached.
+ if (g_pCachedWindow == NULL)
+ {
+ //-- Create New Cache
+ {
+ g_pCachedWindow = (CURRWNDIMAGEDATA*)mir_calloc(sizeof(CURRWNDIMAGEDATA));
+ g_pCachedWindow->hScreenDC = GetDC(NULL);
+ g_pCachedWindow->hBackDC = CreateCompatibleDC(g_pCachedWindow->hScreenDC);
+ g_pCachedWindow->hImageDC = CreateCompatibleDC(g_pCachedWindow->hScreenDC);
+ g_pCachedWindow->Width = wnd.right-wnd.left;
+ g_pCachedWindow->Height = wnd.bottom-wnd.top;
+ g_pCachedWindow->hImageDIB = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte));
+ g_pCachedWindow->hBackDIB = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte));
+ g_pCachedWindow->hImageOld = (HBITMAP)SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageDIB);
+ g_pCachedWindow->hBackOld = (HBITMAP)SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackDIB);
+ }
+ IsNewCache = 1;
+ }
+ if (g_pCachedWindow->Width != wnd.right-wnd.left || g_pCachedWindow->Height != wnd.bottom-wnd.top)
+ {
+ HBITMAP hb1,hb2;
+ g_pCachedWindow->Width = wnd.right-wnd.left;
+ g_pCachedWindow->Height = wnd.bottom-wnd.top;
+ hb1 = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte));
+ hb2 = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte));
+ SelectObject(g_pCachedWindow->hImageDC,hb1);
+ SelectObject(g_pCachedWindow->hBackDC,hb2);
+ DeleteObject(g_pCachedWindow->hImageDIB);
+ DeleteObject(g_pCachedWindow->hBackDIB);
+ g_pCachedWindow->hImageDIB = hb1;
+ g_pCachedWindow->hBackDIB = hb2;
+ IsNewCache = 1;
+ }
+ if (IsNewCache)
+ {
+ ske_DrawNonFramedObjects(0,&wnd);
+ IsForceAllPainting = 1;
+ }
+ if (flag_bJustDrawNonFramedObjects)
+ {
+ IsForceAllPainting = 1;
+ flag_bJustDrawNonFramedObjects = 0;
+ }
+ if (IsForceAllPainting)
+ {
+ BitBlt(g_pCachedWindow->hImageDC,0,0,g_pCachedWindow->Width,g_pCachedWindow->Height,g_pCachedWindow->hBackDC,0,0,SRCCOPY);
+ Sync( QueueAllFramesUpdating, (BYTE)1 );
+ }
+ //-- Validating frames
+ {
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ if (g_pfwFrames[i].PaintCallbackProc && g_pfwFrames[i].visible && !g_pfwFrames[i].floating )
+ if (g_pfwFrames[i].bQueued || IsForceAllPainting)
+ ske_ValidateSingleFrameImage(&g_pfwFrames[i],IsForceAllPainting);
+ }
+ g_mutex_bLockUpdating = 1;
+ ModernSkinButtonRedrawAll(0);
+ g_mutex_bLockUpdating = 0;
+ if ( !mutex_bLockUpdate) ske_UpdateWindowImageRect(&wnd);
+ //-- Clear queue
+ {
+ Sync( QueueAllFramesUpdating, (BYTE)0 );
+ flag_bUpdateQueued = 0;
+ g_flag_bPostWasCanceled = 0;
+ }
+ return 1;
+}
+
+int ske_UpdateWindowImage()
+{
+ if (MirandaExiting())
+ return 0;
+ if (g_CluiData.fLayered)
+ {
+ RECT r;
+ GetWindowRect(pcli->hwndContactList,&r);
+ return ske_UpdateWindowImageRect(&r);
+ }
+ else
+ ske_ReCreateBackImage(FALSE,0);
+ ske_ApplyTransluency();
+ return 0;
+}
+
+
+int ske_UpdateWindowImageRect(RECT * r) // Update window with current image and
+{
+ //if not validity -> ValidateImageProc
+ //else Update using current alpha
+ RECT wnd = *r;
+
+ if ( !g_CluiData.fLayered) return ske_ReCreateBackImage(FALSE,0);
+ if (g_pCachedWindow == NULL) return ske_ValidateFrameImageProc(&wnd);
+ if (g_pCachedWindow->Width != wnd.right-wnd.left || g_pCachedWindow->Height != wnd.bottom-wnd.top) return ske_ValidateFrameImageProc(&wnd);
+ if (g_flag_bFullRepaint)
+ {
+ g_flag_bFullRepaint = 0;
+ return ske_ValidateFrameImageProc(&wnd);
+ }
+ ske_JustUpdateWindowImageRect(&wnd);
+ return 0;
+}
+
+void ske_ApplyTransluency()
+{
+ int IsTransparancy;
+ HWND hwnd = pcli->hwndContactList;
+ BOOL layered = (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED)?TRUE:FALSE;
+
+ IsTransparancy = g_CluiData.fSmoothAnimation || g_bTransparentFlag;
+ if ( !g_bTransparentFlag && !g_CluiData.fSmoothAnimation && g_CluiData.bCurrentAlpha != 0)
+ g_CluiData.bCurrentAlpha = 255;
+ if ( !g_CluiData.fLayered && (/*(g_CluiData.bCurrentAlpha == 255) || */(g_proc_SetLayeredWindowAttributesNew && IsTransparancy)))
+ {
+ if ( !layered) SetWindowLongPtr(hwnd, GWL_EXSTYLE, GetWindowLongPtr(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
+ if (g_proc_SetLayeredWindowAttributesNew) g_proc_SetLayeredWindowAttributesNew(hwnd, RGB(0,0,0), (BYTE)g_CluiData.bCurrentAlpha, LWA_ALPHA);
+ }
+
+ AniAva_RedrawAllAvatars(FALSE);
+ return;
+}
+
+int ske_JustUpdateWindowImage()
+{
+ RECT r;
+ if ( !g_CluiData.fLayered)
+ {
+ ske_ApplyTransluency();
+ return 0;
+ }
+ GetWindowRect(pcli->hwndContactList,&r);
+ return ske_JustUpdateWindowImageRect(&r);
+}
+int ske_JustUpdateWindowImageRect(RECT * rty)
+//Update window image
+{
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0,g_CluiData.bCurrentAlpha, AC_SRC_ALPHA };
+ POINT dest = {0}, src = {0};
+ int res;
+ RECT wnd = *rty;
+
+ RECT rect;
+ SIZE sz = {0};
+
+ if ( !g_CluiData.fLayered)
+ {
+ ske_ApplyTransluency();
+ return 0;
+ }
+ if ( !pcli->hwndContactList) return 0;
+ rect = wnd;
+ dest.x = rect.left;
+ dest.y = rect.top;
+ sz.cx = rect.right-rect.left;
+ sz.cy = rect.bottom-rect.top;
+ if (g_proc_UpdateLayeredWindow && g_CluiData.fLayered)
+ {
+ if ( !(GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE)&WS_EX_LAYERED))
+ SetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE) |WS_EX_LAYERED);
+ Sync( SetAlpha, g_CluiData.bCurrentAlpha );
+
+ res = g_proc_UpdateLayeredWindow(pcli->hwndContactList,g_pCachedWindow->hScreenDC,&dest,&sz,g_pCachedWindow->hImageDC,&src,RGB(1,1,1),&bf,ULW_ALPHA);
+ g_CluiData.fAeroGlass = false;
+ CLUI_UpdateAeroGlass();
+ }
+ else InvalidateRect(pcli->hwndContactList,NULL,TRUE);
+ return 0;
+}
+
+int ske_DrawImageAt(HDC hdc, RECT *rc)
+{
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ BitBlt(g_pCachedWindow->hImageDC,rc->left,rc->top,rc->right-rc->left,rc->bottom-rc->top,g_pCachedWindow->hBackDC,rc->left,rc->top,SRCCOPY);
+ ske_AlphaBlend(g_pCachedWindow->hImageDC,rc->left,rc->top,rc->right-rc->left,rc->bottom-rc->top,hdc,0,0,rc->right-rc->left,rc->bottom-rc->top,bf);
+ if ( !g_mutex_bLockUpdating)
+ ske_UpdateWindowImage();
+ return 0;
+}
+
+HBITMAP ske_GetCurrentWindowImage()
+{
+ return g_pCachedWindow->hImageDIB;
+}
+
+/*
+* Glyph text routine
+*/
+
+static DWORD ske_HexToARGB(char * Hex)
+{
+ char buf[10] = {0};
+ char buf2[11] = {0};
+ char * st;
+ BYTE alpha;
+ DWORD AARRGGBB = 0;
+ _snprintf(buf,10,"%s\n",Hex);
+ if (buf[1] == 'x' || buf[1] == 'X')
+ _snprintf(buf2,11,"0x%s\n",buf+2);
+ else
+ _snprintf(buf2,11,"0x%s\n",buf);
+ buf2[10] = '\0';
+ AARRGGBB = strtoul(buf2,&st,16);
+ alpha = (BYTE)((AARRGGBB&0xFF000000)>>24);
+ alpha = 255-((alpha == 0)?255:alpha);
+ AARRGGBB = (alpha << 24)+((AARRGGBB&0x00FF0000)>>16)+((AARRGGBB&0x000000FF) << 16)+(AARRGGBB&0x0000FF00);
+ return AARRGGBB;
+}
+
+static TCHAR *ske_ReAppend(TCHAR *lfirst, TCHAR * lsecond, int len)
+{
+ int l1 = lfirst?lstrlen(lfirst):0;
+ int l2 = (len?len:(lstrlen(lsecond)+1));
+ TCHAR *buf = (TCHAR *)mir_alloc((l1+l2+1)*sizeof(TCHAR));
+ if (lfirst) memmove(buf,lfirst,l1*sizeof(TCHAR));
+ memmove(buf+l1,lsecond,l2*sizeof(TCHAR));
+ mir_free(lfirst);
+ if (len) buf[l1+l2] = _T('\0');
+ return buf;
+}
+
+TCHAR* ske_ReplaceVar(TCHAR *var)
+{
+ if ( !var) return mir_tstrdup(_T(""));
+ if ( !lstrcmpi(var,_T("Profile")))
+ {
+ char buf[MAX_PATH] = {0};
+ CallService(MS_DB_GETPROFILENAME,(WPARAM)MAX_PATH,(LPARAM)buf);
+ {
+ int i = strlen(buf);
+ while (buf[i] != '.' && i>0) i--;
+ buf[i] = '\0';
+ }
+ mir_free(var);
+ return mir_a2u(buf);
+ }
+
+ mir_free(var);
+ return mir_tstrdup(_T(""));
+}
+TCHAR *ske_ParseText(TCHAR *stzText)
+{
+ int len = lstrlen(stzText);
+ TCHAR *result = NULL;
+ int stpos = 0;
+ int curpos = 0;
+
+ while(curpos < len)
+ {
+ //1 find first %
+ while(curpos < len && stzText[curpos] != (TCHAR)'%') curpos++;
+ if (curpos < len) //% found
+ {
+ if (curpos-stpos>0)
+ result = ske_ReAppend(result,stzText+stpos,curpos-stpos);
+ stpos = curpos+1;
+ curpos++;
+ //3 find second %
+ while(curpos < len && stzText[curpos] != (TCHAR)'%') curpos++;
+ if (curpos < len)
+ {
+ if (curpos-stpos>0)
+ {
+ TCHAR *var = (TCHAR *)mir_alloc((curpos-stpos+1)*sizeof(TCHAR));
+ memmove(var,stzText+stpos,(curpos-stpos)*sizeof(TCHAR));
+ var[curpos-stpos] = (TCHAR)'\0';
+ var = ske_ReplaceVar(var);
+ result = ske_ReAppend(result,var,0);
+ mir_free(var);
+ }
+ else result = ske_ReAppend(result,_T("%"),0);
+
+ curpos++;
+ stpos = curpos;
+ }
+ else
+ {
+ // if (curpos-stpos>0)
+ // result = ske_ReAppend(result,stzText+stpos,curpos-stpos);
+ break;
+ }
+ }
+ else
+ {
+ if (curpos-stpos>0)
+ result = ske_ReAppend(result,stzText+stpos,curpos-stpos);
+ break;
+ }
+ }
+ return result;
+}
+/*
+* Parse text object string, find glyph object and add text to it.
+* szGlyphTextID and Define string is:
+* t[szGlyphTextID] = s[HostObjectID],[Left],[Top],[Right],[Bottom],[LTRBHV],[FontID],[Color1],[reservedforColor2],[Text]
+*/
+static void OLDske_AddParseTextGlyphObject(char * szGlyphTextID,char * szDefineString,SKINOBJECTSLIST *Skin)
+{
+
+ GLYPHOBJECT *globj = NULL;
+ {
+ char buf[255] = {0};
+ GetParamN(szDefineString,buf,sizeof(buf),0,',',TRUE);
+ if (strlen(buf))
+ {
+ SKINOBJECTDESCRIPTOR * lpobj;
+ lpobj = ske_FindObjectByName(buf,OT_GLYPHOBJECT,Skin);
+ if (lpobj)
+ globj = (GLYPHOBJECT*)lpobj->Data;
+ }
+ if (globj)
+ {
+ GLYPHTEXT * glText;
+
+ if ( !globj->plTextList)
+ {
+ globj->plTextList = List_Create(0,1);
+ globj->plTextList->sortFunc = ske_SortTextGlyphObjectFunc;
+ }
+ glText = (GLYPHTEXT*)mir_calloc(sizeof(GLYPHTEXT));
+ glText->szGlyphTextID = mir_strdup(szGlyphTextID);
+ glText->szObjectName = mir_strdup(buf);
+ glText->iLeft = atoi(GetParamN(szDefineString,buf,sizeof(buf),1,',',TRUE));
+ glText->iTop = atoi(GetParamN(szDefineString,buf,sizeof(buf),2,',',TRUE));
+ glText->iRight = atoi(GetParamN(szDefineString,buf,sizeof(buf),3,',',TRUE));
+ glText->iBottom = atoi(GetParamN(szDefineString,buf,sizeof(buf),4,',',TRUE));
+ {
+ memset(buf,0,6);
+ GetParamN(szDefineString,buf,sizeof(buf),5,',',TRUE);
+ buf[0] &= 95; buf[1] &= 95; buf[2] &= 95; buf[3] &= 95; buf[4] &= 95; buf[5] &= 95; //to uppercase: &01011111 (0-95)
+ glText->RelativeFlags =
+ (buf[0] == 'C'?1:((buf[0] == 'R')?2:0)) //[BC][RC][BC][RC] --- Left relative
+ |(buf[1] == 'C'?4:((buf[1] == 'B')?8:0)) // | | |--------- Top relative
+ |(buf[2] == 'C'?16:((buf[2] == 'R')?32:0)) // | |--------------Right relative
+ |(buf[3] == 'C'?64:((buf[3] == 'B')?128:0)); // |------------------Bottom relative
+ glText->dwFlags = (buf[4] == 'C'?DT_CENTER:((buf[4] == 'R')?DT_RIGHT:DT_LEFT))
+ |(buf[5] == 'C'?DT_VCENTER:((buf[5] == 'B')?DT_BOTTOM:DT_TOP));
+ }
+ glText->szFontID = mir_strdup(GetParamN(szDefineString,buf,sizeof(buf),6,',',TRUE));
+
+ glText->dwColor = ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),7,',',TRUE));
+ glText->dwShadow = ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),8,',',TRUE));
+ glText->stValueText = mir_a2u(GetParamN(szDefineString,buf,sizeof(buf),9,',',TRUE));
+ glText->stText = ske_ParseText(glText->stValueText);
+ List_Insert(globj->plTextList,(void*)glText,globj->plTextList->realCount);
+ qsort(globj->plTextList->items,globj->plTextList->realCount,sizeof(void*),(int(*)(const void*, const void*))globj->plTextList->sortFunc);
+ }
+ }
+}
+
+
+static void ske_AddParseTextGlyphObject(char * szGlyphTextID,char * szDefineString,SKINOBJECTSLIST *Skin)
+{
+ char buf[255] = {0};
+ GetParamN(szDefineString,buf,sizeof(buf),0,',',TRUE);
+ if (strlen(buf))
+ {
+ GLYPHTEXT * glText;
+ glText = (GLYPHTEXT*)mir_calloc(sizeof(GLYPHTEXT));
+ glText->szGlyphTextID = mir_strdup(szGlyphTextID);
+ glText->szObjectName = mir_strdup(buf);
+ glText->iLeft = atoi(GetParamN(szDefineString,buf,sizeof(buf),1,',',TRUE));
+ glText->iTop = atoi(GetParamN(szDefineString,buf,sizeof(buf),2,',',TRUE));
+ glText->iRight = atoi(GetParamN(szDefineString,buf,sizeof(buf),3,',',TRUE));
+ glText->iBottom = atoi(GetParamN(szDefineString,buf,sizeof(buf),4,',',TRUE));
+ {
+ memset(buf,0,6);
+ GetParamN(szDefineString,buf,sizeof(buf),5,',',TRUE);
+ buf[0] &= 95; buf[1] &= 95; buf[2] &= 95; buf[3] &= 95; buf[4] &= 95; buf[5] &= 95; //to uppercase: &01011111 (0-95)
+ glText->RelativeFlags =
+ (buf[0] == 'C'?1:((buf[0] == 'R')?2:0)) //[BC][RC][BC][RC] --- Left relative
+ |(buf[1] == 'C'?4:((buf[1] == 'B')?8:0)) // | | |--------- Top relative
+ |(buf[2] == 'C'?16:((buf[2] == 'R')?32:0)) // | |--------------Right relative
+ |(buf[3] == 'C'?64:((buf[3] == 'B')?128:0)); // |------------------Bottom relative
+ glText->dwFlags = (buf[4] == 'C'?DT_CENTER:((buf[4] == 'R')?DT_RIGHT:DT_LEFT))
+ |(buf[5] == 'C'?DT_VCENTER:((buf[5] == 'B')?DT_BOTTOM:DT_TOP));
+ }
+ glText->szFontID = mir_strdup(GetParamN(szDefineString,buf,sizeof(buf),6,',',TRUE));
+
+ glText->dwColor = ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),7,',',TRUE));
+ glText->dwShadow = ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),8,',',TRUE));
+ glText->stValueText = mir_a2u(GetParamN(szDefineString,buf,sizeof(buf),9,',',TRUE));
+ glText->stText = ske_ParseText(glText->stValueText);
+
+ if ( !Skin->pTextList)
+ Skin->pTextList = List_Create(0,1);
+ List_InsertPtr(Skin->pTextList,glText);
+ }
+}
+
+
+/*
+* Parse font definition string.
+* szGlyphTextID and Define string is:
+* f[szFontID] = s[FontTypefaceName],[size],[BIU]
+*/
+static void ske_AddParseSkinFont(char * szFontID,char * szDefineString,SKINOBJECTSLIST *Skin)
+{
+ //SortedList * gl_plSkinFonts = NULL;
+ SKINFONT * sf = NULL;
+ sf = (SKINFONT*)mir_calloc(sizeof(SKINFONT));
+ if (sf)
+ {
+ {
+ char buf[255];
+ int fntSize = 0;
+ BOOL fntBold = FALSE, fntItalic = FALSE, fntUnderline = FALSE;
+ LOGFONTA logfont = {0};
+ logfont.lfCharSet = DEFAULT_CHARSET;
+ logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
+ logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ logfont.lfQuality = DEFAULT_QUALITY;
+ logfont.lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
+
+ strncpy(logfont.lfFaceName,GetParamN(szDefineString,buf,sizeof(buf),0,',',TRUE),32);
+ logfont.lfHeight = atoi(GetParamN(szDefineString,buf,sizeof(buf),1,',',TRUE));
+ if (logfont.lfHeight < 0)
+ {
+ HDC hdc = CreateCompatibleDC(NULL);
+ logfont.lfHeight = (long)-MulDiv(logfont.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+ mod_DeleteDC(hdc);
+ }
+ logfont.lfHeight = -logfont.lfHeight;
+ GetParamN(szDefineString,buf,sizeof(buf),2,',',TRUE);
+ buf[0] &= 95; buf[1] &= 95; buf[2] &= 95;
+ logfont.lfWeight = (buf[0] == 'B')?FW_BOLD:FW_NORMAL;
+ logfont.lfItalic = (buf[1] == 'I')?1:0;
+ logfont.lfUnderline = (buf[2] == 'U')?1:0;
+
+ sf->hFont = CreateFontIndirectA(&logfont);
+ if (sf->hFont)
+ {
+ sf->szFontID = mir_strdup(szFontID);
+ if ( !gl_plSkinFonts)
+ gl_plSkinFonts = List_Create(0,1);
+ if (gl_plSkinFonts)
+ {
+ List_Insert(gl_plSkinFonts,(void*)sf,gl_plSkinFonts->realCount);
+ }
+ }
+
+ }
+ }
+
+}
+
+/*
+HICON ske_CreateJoinedIcon_Old(HICON hBottom, HICON hTop,BYTE alpha)
+{
+HDC tempDC;
+HICON res = NULL;
+HBITMAP oImage,nImage;
+HBITMAP nMask;
+ICONINFO iNew = {0};
+ICONINFO iciBottom = {0};
+ICONINFO iciTop = {0};
+BITMAP bmp = {0};
+SIZE sz = {0};
+{
+if ( !GetIconInfo(hBottom,&iciBottom)) return NULL;
+GetObject(iciBottom.hbmColor,sizeof(BITMAP),&bmp);
+sz.cx = bmp.bmWidth; sz.cy = bmp.bmHeight;
+if (iciBottom.hbmColor) DeleteObject(iciBottom.hbmColor);
+if (iciBottom.hbmMask) DeleteObject(iciBottom.hbmMask);
+}
+if (sz.cx == 0 || sz.cy == 0) return NULL;
+tempDC = CreateCompatibleDC(NULL);
+nImage = ske_CreateDIB32(sz.cx,sz.cy);
+oImage = SelectObject(tempDC,nImage);
+ske_DrawIconEx(tempDC,0,0,hBottom,sz.cx,sz.cy,0,NULL,DI_NORMAL);
+ske_DrawIconEx(tempDC,0,0,hTop,sz.cx,sz.cy,0,NULL,DI_NORMAL|(alpha << 24));
+SelectObject(tempDC,oImage);
+DeleteDC(tempDC);
+{
+BYTE * p = malloc(sz.cx*sz.cy/8+10);
+nMask = CreateBitmap(sz.cx,sz.cy,1,1,(void*)p);
+iNew.fIcon = TRUE;
+iNew.hbmColor = nImage;
+iNew.hbmMask = nMask;
+res = CreateIconIndirect(&iNew);
+if ( !res)
+TRACE_ERROR();
+DeleteObject(nImage);
+DeleteObject(nMask);
+free(p);
+}
+return res;
+}
+*/
+
+
+/*
+* ske_CheckHasAlfaChannel - checks if image has at least one BYTE in alpha chennel
+* that is not a 0. (is image real 32 bit or just 24 bit)
+*/
+static BOOL ske_CheckHasAlfaChannel(BYTE * from, int widthByte, int height)
+{
+ int i=0,j = 0;
+ DWORD * pt = (DWORD*)from;
+ while (j < height)
+ {
+ BYTE * add = (BYTE*)pt+widthByte;
+ while (pt < (DWORD*)add)
+ {
+ if ((*pt&0xFF000000) != 0) return TRUE;
+ pt++;
+ }
+ pt = (DWORD*)(from+widthByte*j);
+ j++;
+ }
+ return FALSE;
+}
+
+/*
+* ske_CheckIconHasMask - checks if mask image has at least one that is not a 0.
+* Not sure is ir required or not
+*/
+static BOOL ske_CheckIconHasMask(BYTE * from)
+{
+ int i=0;
+ for (i=0; i < 16*16/8; i++)
+ {
+ if (from[i] != 0) return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+* ske_GetMaskBit - return value of apropriate mask bit in line at x position
+*/
+static BOOL ske_GetMaskBit(BYTE *line, int x)
+{
+ return ((*(line+(x>>3)))&(0x01 << (7-(x&0x07)))) != 0;
+}
+/*
+* ske_Blend - alpha ske_Blend ARGB values of 2 pixels. X1 - underlaying,
+* X2 - overlaying points.
+*/
+
+static DWORD ske_Blend(DWORD X1,DWORD X2, BYTE alpha)
+{
+ BYTE a1 = (BYTE)(X1>>24);
+ BYTE a2 = (BYTE)(((X2>>24)*alpha)>>8);
+ BYTE r1 = (BYTE)(X1>>16);
+ BYTE r2 = (BYTE)(X2>>16);
+ BYTE g1 = (BYTE)(X1>>8);
+ BYTE g2 = (BYTE)(X2>>8);
+ BYTE b1 = (BYTE)(X1);
+ BYTE b2 = (BYTE)(X2);
+
+ BYTE a_1 = ~a1;
+ BYTE a_2 = ~a2;
+ WORD am = (WORD)a1*a_2;
+
+ /* it is possible to use >>8 instead of /255 but it is require additional
+ * checking of alphavalues
+ */
+ WORD ar = a1+(((WORD)a_1*a2)/255);
+ // if a2 more than 0 than result should be more
+ // or equal (if a1 == 0) to a2, else in combination
+ // with mask we can get here black points
+
+ ar = (a2>ar)?a2:ar;
+
+ if (ar == 0) return 0;
+
+ //else
+ {
+ WORD arm = ar*255;
+ WORD rr = (((WORD)r1*am+(WORD)r2*a2*255))/arm;
+ WORD gr = (((WORD)g1*am+(WORD)g2*a2*255))/arm;
+ WORD br = (((WORD)b1*am+(WORD)b2*a2*255))/arm;
+ return (ar << 24)|(rr << 16)|(gr << 8)|br;
+ }
+
+}
+/*
+* CreateJoinedIcon - creates new icon by drawing hTop over hBottom.
+*/
+HICON ske_CreateJoinedIcon(HICON hBottom, HICON hTop, BYTE alpha)
+{
+ HDC tempDC;
+ HICON res = NULL;
+ HBITMAP oImage,nImage;
+ HBITMAP nMask;
+ BITMAP bmp = {0};
+ BYTE *ptPixels;
+ ICONINFO iNew = {0};
+ ICONINFO iciBottom = {0};
+ ICONINFO iciTop = {0};
+
+ BITMAP bmp_top = {0};
+ BITMAP bmp_top_mask = {0};
+
+ BITMAP bmp_bottom = {0};
+ BITMAP bmp_bottom_mask = {0};
+
+ tempDC = CreateCompatibleDC(NULL);
+ nImage = ske_CreateDIB32Point(16,16,(void**)&ptPixels);
+ oImage = (HBITMAP)SelectObject(tempDC,nImage);
+
+ GetIconInfo(hBottom,&iciBottom);
+ GetObject(iciBottom.hbmColor,sizeof(BITMAP),&bmp_bottom);
+ GetObject(iciBottom.hbmMask,sizeof(BITMAP),&bmp_bottom_mask);
+
+ GetIconInfo(hTop,&iciTop);
+ GetObject(iciTop.hbmColor,sizeof(BITMAP),&bmp_top);
+ GetObject(iciTop.hbmMask,sizeof(BITMAP),&bmp_top_mask);
+
+ if (bmp_bottom.bmBitsPixel == 32 && bmp_top.bmBitsPixel == 32 && IsWinVerXPPlus())
+ {
+ BYTE * BottomBuffer, * TopBuffer, * BottomMaskBuffer, * TopMaskBuffer;
+ BYTE * bb, * tb, * bmb, * tmb;
+ BYTE * db = ptPixels;
+ int vstep_d = 16*4;
+ int vstep_b = bmp_bottom.bmWidthBytes;
+ int vstep_t = bmp_top.bmWidthBytes;
+ int vstep_bm = bmp_bottom_mask.bmWidthBytes;
+ int vstep_tm = bmp_top_mask.bmWidthBytes;
+ alpha = alpha?alpha:255;
+ if (bmp_bottom.bmBits) bb = BottomBuffer = (BYTE*)bmp_bottom.bmBits;
+ else
+ {
+ BottomBuffer = (BYTE*)malloc(bmp_bottom.bmHeight*bmp_bottom.bmWidthBytes);
+ GetBitmapBits(iciBottom.hbmColor,bmp_bottom.bmHeight*bmp_bottom.bmWidthBytes,BottomBuffer);
+ bb = BottomBuffer+vstep_b*(bmp_bottom.bmHeight-1);
+ vstep_b = -vstep_b;
+ }
+ if (bmp_top.bmBits) tb = TopBuffer = (BYTE*)bmp_top.bmBits;
+ else
+ {
+ TopBuffer = (BYTE*)malloc(bmp_top.bmHeight*bmp_top.bmWidthBytes);
+ GetBitmapBits(iciTop.hbmColor,bmp_top.bmHeight*bmp_top.bmWidthBytes,TopBuffer);
+ tb = TopBuffer+vstep_t*(bmp_top.bmHeight-1);
+ vstep_t = -vstep_t;
+ }
+ if (bmp_bottom_mask.bmBits)
+ {
+ BottomMaskBuffer = (BYTE*)bmp_bottom_mask.bmBits;
+ bmb = BottomMaskBuffer;
+ }
+ else
+ {
+ BottomMaskBuffer = (BYTE*)malloc(bmp_bottom_mask.bmHeight*bmp_bottom_mask.bmWidthBytes);
+ GetBitmapBits(iciBottom.hbmMask,bmp_bottom_mask.bmHeight*bmp_bottom_mask.bmWidthBytes,BottomMaskBuffer);
+ bmb = BottomMaskBuffer+vstep_bm*(bmp_bottom_mask.bmHeight-1);
+ vstep_bm = -vstep_bm;
+
+ }
+ if (bmp_top_mask.bmBits)
+ {
+ TopMaskBuffer = (BYTE*)bmp_top_mask.bmBits;
+ tmb = TopMaskBuffer;
+
+ }
+ else
+ {
+ TopMaskBuffer = (BYTE*)malloc(bmp_top_mask.bmHeight*bmp_top_mask.bmWidthBytes);
+ GetBitmapBits(iciTop.hbmMask,bmp_top_mask.bmHeight*bmp_top_mask.bmWidthBytes,TopMaskBuffer);
+ tmb = TopMaskBuffer+vstep_tm*(bmp_top_mask.bmHeight-1);
+ vstep_tm = -vstep_tm;
+ }
+ {
+ int x = 0; int y = 0;
+ BOOL topHasAlpha = ske_CheckHasAlfaChannel(TopBuffer,bmp_top.bmWidthBytes,bmp_top.bmHeight);
+ BOOL bottomHasAlpha = ske_CheckHasAlfaChannel(BottomBuffer,bmp_bottom.bmWidthBytes,bmp_bottom.bmHeight);
+ BOOL topHasMask = ske_CheckIconHasMask(TopMaskBuffer);
+ BOOL bottomHasMask = ske_CheckIconHasMask(BottomMaskBuffer);
+ for (y = 0; y < 16; y++)
+ {
+ for (x = 0; x < 16; x++)
+ {
+ BOOL mask_b = ske_GetMaskBit(bmb,x);
+ BOOL mask_t = ske_GetMaskBit(tmb,x);
+ DWORD bottom_d = ((DWORD*)bb)[x];
+ DWORD top_d = ((DWORD*)tb)[x];
+ if (topHasMask)
+ {
+ if (mask_t == 1 && !topHasAlpha ) top_d &= 0xFFFFFF;
+ else if ( !topHasAlpha) top_d |= 0xFF000000;
+ }
+ if (bottomHasMask)
+ {
+ if (mask_b == 1 && !bottomHasAlpha) bottom_d &= 0xFFFFFF;
+ else if ( !bottomHasAlpha) bottom_d |= 0xFF000000;
+ }
+ ((DWORD*)db)[x] = ske_Blend(bottom_d,top_d,alpha);
+ }
+ bb += vstep_b;
+ tb += vstep_t;
+ bmb += vstep_bm;
+ tmb += vstep_tm;
+ db += vstep_d;
+ }
+ }
+ if ( !bmp_bottom.bmBits) free(BottomBuffer);
+ if ( !bmp_top.bmBits) free(TopBuffer);
+ if ( !bmp_bottom_mask.bmBits) free(BottomMaskBuffer);
+ if ( !bmp_top_mask.bmBits) free(TopMaskBuffer);
+ }
+ else
+ {
+ ske_DrawIconEx(tempDC,0,0,hBottom,16,16,0,NULL,DI_NORMAL);
+ ske_DrawIconEx(tempDC,0,0,hTop,16,16,0,NULL,DI_NORMAL|(alpha << 24));
+ }
+ DeleteObject(iciBottom.hbmColor);
+ DeleteObject(iciTop.hbmColor);
+ DeleteObject(iciBottom.hbmMask);
+ DeleteObject(iciTop.hbmMask);
+
+ SelectObject(tempDC,oImage);
+ DeleteDC(tempDC);
+ {
+ //BYTE *p = malloc(32);
+ //memset(p,0,32);
+ BYTE p[32] = {0};
+ nMask = CreateBitmap(16,16,1,1,(void*)&p);
+ {
+ HDC tempDC2 = CreateCompatibleDC(NULL);
+ HDC tempDC3 = CreateCompatibleDC(NULL);
+ HBITMAP hbm = CreateCompatibleBitmap(tempDC3,16,16);
+ HBITMAP obmp = (HBITMAP)SelectObject(tempDC2,nMask);
+ HBITMAP obmp2 = (HBITMAP)SelectObject(tempDC3,hbm);
+ DrawIconEx(tempDC2,0,0,hBottom,16,16,0,NULL,DI_MASK);
+ DrawIconEx(tempDC3,0,0,hTop,16,16,0,NULL,DI_MASK);
+ BitBlt(tempDC2,0,0,16,16,tempDC3,0,0,SRCAND);
+ SelectObject(tempDC2,obmp);
+ SelectObject(tempDC3,obmp2);
+ DeleteObject(hbm);
+ DeleteDC(tempDC2);
+ DeleteDC(tempDC3);
+ }
+ iNew.fIcon = TRUE;
+ iNew.hbmColor = nImage;
+ iNew.hbmMask = nMask;
+ res = CreateIconIndirect(&iNew);
+ DeleteObject(nImage);
+ DeleteObject(nMask);
+ }
+ return res;
+}
+
+#define NEWJOINEDSTR( destination, first, separator, last) \
+ destination = (char*)alloca(strlen(first)+strlen(separator)+strlen(last)+1); \
+ if (destination) { \
+ *destination = '\0'; \
+ strcat(destination,first); \
+ strcat(destination,separator); \
+ strcat(destination,last); \
+ }
+
+#define SKINSETSECTION "SkinnedSettings"
+
+BOOL SkinDBGetContactSetting(HANDLE hContact, const char* szSection, const char*szKey, DBVARIANT * retdbv, BOOL * bSkined )
+{
+ if ( !hContact) { //only for not contact settings
+ char * szSkinKey;
+ NEWJOINEDSTR(szSkinKey,szSection,"@",szKey);
+ if ( !db_get(hContact, SKINSETSECTION, szSkinKey, retdbv)) {
+ if (bSkined) *bSkined = TRUE;
+ return FALSE;
+ } }
+ // not skinned
+ if (bSkined) bSkined = FALSE;
+ return db_get(hContact, szSection, szKey, retdbv);
+}
+
+BYTE SkinDBGetContactSettingByte(HANDLE hContact, const char* szSection, const char*szKey, BYTE bDefault)
+{
+ DBVARIANT dbv = {0};
+ BOOL bSkined = FALSE;
+ if ( !SkinDBGetContactSetting(hContact, szSection, szKey, &dbv, &bSkined)) {
+ if (dbv.type == DBVT_BYTE)
+ {
+ BYTE retVal = dbv.bVal;
+ db_free(&dbv);
+ return retVal;
+ } else {
+ db_free(&dbv);
+ if ( !bSkined) return db_get_b(hContact, szSection, szKey, bDefault);
+ }
+ }
+ return bDefault;
+}
+
+WORD SkinDBGetContactSettingWord(HANDLE hContact, const char* szSection, const char*szKey, WORD wDefault)
+{
+ BOOL bSkined = FALSE;
+ DBVARIANT dbv = {0};
+ if ( !SkinDBGetContactSetting(hContact, szSection, szKey, &dbv, &bSkined)) {
+ if (dbv.type == DBVT_WORD) {
+ WORD retVal = dbv.wVal;
+ db_free(&dbv);
+ return retVal;
+ } else {
+ db_free(&dbv);
+ if ( !bSkined) return db_get_w(hContact, szSection, szKey, wDefault);
+ }
+ }
+ return wDefault;
+}
+
+DWORD SkinDBGetContactSettingDword(HANDLE hContact, const char* szSection, const char*szKey, DWORD dwDefault)
+{
+ DBVARIANT dbv = {0};
+ BOOL bSkined = FALSE;
+ if ( !SkinDBGetContactSetting(hContact, szSection, szKey, &dbv, &bSkined)) {
+ if (dbv.type == DBVT_DWORD) {
+ DWORD retVal = dbv.dVal;
+ db_free(&dbv);
+ return retVal;
+ } else {
+ db_free(&dbv);
+ if ( !bSkined) return db_get_dw(hContact, szSection, szKey, dwDefault);
+ }
+ }
+ return dwDefault;
+}
diff --git a/plugins/Clist_modern/src/modern_skinned_profile.cpp b/plugins/Clist_modern/src/modern_skinned_profile.cpp
new file mode 100644
index 0000000000..d31fe7d18f
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_skinned_profile.cpp
@@ -0,0 +1,115 @@
+
+
+#include "hdr/modern_commonheaders.h"
+
+#ifdef _DEBUG // REMOVE ME, as soon as ghazan will implement msvcprt.lib msvcrt.lib analogs to vc6tovc7.lib
+#include "hdr/modern_skinned_profile.h"
+
+
+//need to be linked in: atls.lib msvcprt.lib msvcrt.lib
+
+CSkinnedProfile CSkinnedProfile::_me;
+
+
+CSkinnedProfile::CSkinnedProfile()
+{
+ Init();
+}
+
+CSkinnedProfile::~CSkinnedProfile()
+{
+
+}
+
+HRESULT CSkinnedProfile::Init()
+{
+ CAutoCriticalSection Lock( SkinProfile()->_Lock, true );
+ SkinnedProfile.clear();
+ return S_OK;
+}
+
+HRESULT CSkinnedProfile::Clear()
+{
+ CAutoCriticalSection Lock( SkinProfile()->_Lock, true );
+ SkinnedProfile.clear();
+ return S_OK;
+}
+
+
+ValueVariant* CSkinnedProfile::_GetValue( const char * szSection, const char * szKey )
+{
+ KeyList_t::iterator k_it = SkinnedProfile.find( szSection );
+ if ( k_it == SkinnedProfile.end() )
+ return NULL; // Not skinned
+
+ ValueList_t::iterator v_it = k_it->second.find( szKey );
+ if ( v_it == k_it->second.end() )
+ return NULL; // Not skinned
+
+ return &( v_it->second );
+};
+
+BYTE CSkinnedProfile::SpiGetSkinByte( HANDLE hContact, const char * szSection, const char * szKey, const BYTE defValue )
+{
+ if ( hContact )
+ return ModernGetSettingByte( hContact, szSection, szKey, defValue ); //per-contact settings are not skinnablr at all
+
+ CAutoCriticalSection Lock( SkinProfile()->_Lock, true );
+
+ ValueVariant* value = SkinProfile()->_GetValue( szSection, szKey );
+
+ if ( value == NULL ) // not skinned => return DB
+ return ModernGetSettingWord( hContact, szSection, szKey, defValue );
+
+ else if ( !value->IsEmpty() )
+ return value->GetByte();
+
+ return defValue; // skinned but empty => return default value
+}
+
+WORD CSkinnedProfile::SpiGetSkinWord( HANDLE hContact, const char * szSection, const char * szKey, const WORD defValue )
+{
+ if ( hContact )
+ return ModernGetSettingWord( hContact, szSection, szKey, defValue ); //per-contact settings are not skinnablr at all
+
+ CAutoCriticalSection Lock( SkinProfile()->_Lock, true );
+
+ ValueVariant* value = SkinProfile()->_GetValue( szSection, szKey );
+
+ if ( value == NULL ) // not skinned => return DB
+ return ModernGetSettingWord( hContact, szSection, szKey, defValue );
+
+ else if ( !value->IsEmpty() )
+ return value->GetWord();
+
+ return defValue; // skinned but empty => return default value
+}
+
+DWORD CSkinnedProfile::SpiGetSkinDword( HANDLE hContact, const char * szSection, const char * szKey, const DWORD defValue )
+{
+ if ( hContact )
+ return ModernGetSettingDword( hContact, szSection, szKey, defValue ); //per-contact settings are not skinnablr at all
+
+ CAutoCriticalSection Lock( SkinProfile()->_Lock, true );
+
+ ValueVariant* value = SkinProfile()->_GetValue( szSection, szKey );
+
+ if ( value == NULL ) // not skinned => return DB
+ return ModernGetSettingDword( hContact, szSection, szKey, defValue );
+
+ else if ( !value->IsEmpty() )
+ return value->GetDword();
+
+ return defValue; // skinned but empty => return default value
+}
+
+BOOL CSkinnedProfile::SpiCheckSkinned( HANDLE hContact, const char * szSection, const char * szKey )
+{
+ if ( hContact )
+ return FALSE;
+
+ CAutoCriticalSection Lock( SkinProfile()->_Lock, true );
+
+ return ( SkinProfile()->_GetValue( szSection, szKey ) == NULL );
+}
+#endif // _DEBUG // REMOVE ME, as soon as ghazan will implement msvcprt.lib msvcrt.lib analogs to vc6tovc7.lib \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_skinopt.cpp b/plugins/Clist_modern/src/modern_skinopt.cpp
new file mode 100644
index 0000000000..1ffb72804c
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_skinopt.cpp
@@ -0,0 +1,771 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "m_clc.h"
+#include "io.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_sync.h"
+#include <m_utils.h>
+#include <m_database.h>
+#include <m_modernopt.h>
+
+/*******************************/
+// Main skin selection routine //
+/*******************************/
+#define MAX_NAME 100
+typedef struct _SkinListData
+{
+ TCHAR Name[MAX_NAME];
+ TCHAR File[MAX_PATH];
+} SkinListData;
+
+HBITMAP hPreviewBitmap = NULL;
+HTREEITEM AddItemToTree( HWND hTree, TCHAR * folder, TCHAR * itemName, void * data );
+HTREEITEM AddSkinToListFullName( HWND hwndDlg, TCHAR * fullName );
+HTREEITEM AddSkinToList( HWND hwndDlg, TCHAR * path, TCHAR* file );
+HTREEITEM FillAvailableSkinList( HWND hwndDlg );
+
+INT_PTR CALLBACK DlgSkinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+int SkinOptInit( WPARAM wParam, LPARAM lParam )
+{
+ OPTIONSDIALOGPAGE odp;
+ if ( !g_CluiData.fDisableSkinEngine )
+ {
+ //Tabbed settings
+ ZeroMemory( &odp, sizeof( odp ));
+ odp.cbSize = sizeof( odp );
+ odp.position = -200000000;
+ odp.hInstance = g_hInst;
+ odp.pfnDlgProc = DlgSkinOpts;
+ odp.pszTemplate = MAKEINTRESOURCEA( IDD_OPT_SKIN );
+ odp.pszGroup = LPGEN( "Skins" );
+ odp.pszTitle = LPGEN( "Contact List" );
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.pszTab = LPGEN( "Load/Save" );
+ Options_AddPage(wParam, &odp);
+
+ if ( db_get_b( NULL, "ModernData", "EnableSkinEditor", SETTING_ENABLESKINEDITOR_DEFAULT )) {
+ odp.flags |= ODPF_EXPERTONLY;
+ odp.pfnDlgProc = DlgSkinEditorOpts;
+ odp.pszTemplate = MAKEINTRESOURCEA( IDD_OPT_SKINEDITOR );
+ odp.pszTab = LPGEN( "Object Editor" );
+ Options_AddPage(wParam, &odp);
+ }
+ }
+ return 0;
+}
+
+int ModernSkinOptInit( WPARAM wParam, LPARAM lParam )
+{
+ 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_SELECTORPAGE;
+ obj.lptzSubsection = _T("Contact List");
+ obj.lpzThemeExtension = ".msf";
+ obj.lpzThemeModuleName = "ModernSkinSel";
+ CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj);
+ return 0;
+}
+INT_PTR CALLBACK DlgSkinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch ( msg )
+ {
+ case WM_DESTROY:
+ {
+ if ( hPreviewBitmap ) ske_UnloadGlyphImage( hPreviewBitmap );
+ break;
+ }
+
+ case WM_INITDIALOG:
+ {
+ HTREEITEM it;
+ TranslateDialogDefault( hwndDlg );
+ it = FillAvailableSkinList( hwndDlg );
+ HWND wnd = GetDlgItem( hwndDlg, IDC_TREE1 );
+ TreeView_SelectItem( wnd, it );
+ }
+ return 0;
+ case WM_COMMAND:
+ {
+ int isLoad = 0;
+ switch ( LOWORD( wParam ))
+ {
+ case IDC_COLOUR_MENUNORMAL:
+ case IDC_COLOUR_MENUSELECTED:
+ case IDC_COLOUR_FRAMES:
+ case IDC_COLOUR_STATUSBAR:
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+
+ case IDC_BUTTON_INFO:
+ {
+ TCHAR Author[255];
+ TCHAR URL[MAX_PATH];
+ TCHAR Contact[255];
+ TCHAR Description[400];
+ TCHAR text[2000];
+ SkinListData *sd = NULL;
+ HTREEITEM hti = TreeView_GetSelection( GetDlgItem( hwndDlg, IDC_TREE1 ));
+ if ( hti == 0 ) return 0;
+ {
+ TVITEM tvi = {0};
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ TreeView_GetItem( GetDlgItem( hwndDlg, IDC_TREE1 ), &tvi );
+ sd = ( SkinListData* )( tvi.lParam );
+ }
+ if ( !sd ) return 0;
+ if ( sd->File && !_tcschr( sd->File, _T('%')))
+ {
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Author" ), TranslateT( "( unknown )" ), Author, SIZEOF( Author ), sd->File );
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "URL" ), _T( "" ), URL, SIZEOF( URL ), sd->File );
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Contact" ), _T( "" ), Contact, SIZEOF( Contact ), sd->File );
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Description" ), _T( "" ), Description, SIZEOF( Description ), sd->File );
+ _sntprintf( text, SIZEOF( text ), TranslateT( "%s\n\n%s\n\nAuthor(s):\t %s\nContact:\t %s\nWeb:\t %s\n\nFile:\t %s" ),
+ sd->Name, Description, Author, Contact, URL, sd->File );
+ }
+ else
+ {
+ _sntprintf( text, SIZEOF( text ), TranslateT( "%s\n\n%s\n\nAuthor(s): %s\nContact:\t %s\nWeb:\t %s\n\nFile:\t %s" ),
+ TranslateT( "reVista for Modern v0.5" ),
+ TranslateT( "This is second default Modern Contact list skin in Vista Aero style" ),
+ TranslateT( "Angeli-Ka (graphics), FYR (template)" ),
+ _T( "JID: fyr@jabber.ru" ),
+ _T("fyr.mirandaim.ru"),
+ TranslateT( "Inside library" ));
+ }
+ MessageBox( hwndDlg, text, TranslateT( "Skin Information" ), MB_OK|MB_ICONINFORMATION );
+ }
+ break;
+ case IDC_BUTTON_APPLY_SKIN:
+ if ( HIWORD( wParam ) == BN_CLICKED )
+ {
+ SkinListData *sd = NULL;
+ HTREEITEM hti = TreeView_GetSelection( GetDlgItem( hwndDlg, IDC_TREE1 ));
+ if ( hti == 0 ) return 0;
+ {
+ TVITEM tvi = {0};
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ TreeView_GetItem( GetDlgItem( hwndDlg, IDC_TREE1 ), &tvi );
+ sd = ( SkinListData* )( tvi.lParam );
+ }
+ if ( !sd ) return 0;
+ if ( glSkinWasModified>0 )
+ {
+ int res = 0;
+ if ( glSkinWasModified == 1 )
+ res = MessageBox( hwndDlg, TranslateT( "Skin editor contains not stored changes.\n\nAll changes will be lost.\n\n Continue to load new skin?" ), TranslateT( "Warning!" ), MB_OKCANCEL|MB_ICONWARNING|MB_DEFBUTTON2|MB_TOPMOST );
+ else
+ res = MessageBox( hwndDlg, TranslateT( "Current skin was not saved to file.\n\nAll changes will be lost.\n\n Continue to load new skin?" ), TranslateT( "Warning!" ), MB_OKCANCEL|MB_ICONWARNING|MB_DEFBUTTON2|MB_TOPMOST );
+ if ( res != IDOK ) return 0;
+ }
+ ske_LoadSkinFromIniFile( sd->File, FALSE );
+ ske_LoadSkinFromDB( );
+ glOtherSkinWasLoaded = TRUE;
+ pcli->pfnClcBroadcast( INTM_RELOADOPTIONS, 0, 0 );
+ Sync( CLUIFrames_OnClistResize_mod, 0, 0 );
+ ske_RedrawCompleteWindow( );
+ Sync( CLUIFrames_OnClistResize_mod, 0, 0 );
+ {
+ HWND hwnd = pcli->hwndContactList;
+ RECT rc = {0};
+ GetWindowRect( hwnd, &rc );
+ Sync( CLUIFrames_OnMoving, hwnd, &rc );
+ }
+ if ( g_hCLUIOptionsWnd )
+ {
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_LEFTMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "LeftClientMargin", SETTING_LEFTCLIENTMARIGN_DEFAULT ));
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_RIGHTMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "RightClientMargin", SETTING_RIGHTCLIENTMARIGN_DEFAULT ));
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_TOPMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "TopClientMargin", SETTING_TOPCLIENTMARIGN_DEFAULT ));
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_BOTTOMMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "BottomClientMargin", SETTING_BOTTOMCLIENTMARIGN_DEFAULT ));
+ }
+ }
+ break;
+ case IDC_BUTTON_LOAD:
+ isLoad = 1;
+ if ( HIWORD( wParam ) == BN_CLICKED )
+ {
+ {
+ TCHAR str[MAX_PATH] = {0};
+ OPENFILENAME ofn = {0};
+ TCHAR filter[512] = {0};
+ int res = 0;
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = hwndDlg;
+ ofn.hInstance = NULL;
+
+ mir_sntprintf(filter, SIZEOF(filter), _T("%s (*.msf)%c*.MSF%c%c"), TranslateT("Miranda skin file"), 0, 0, 0);
+ ofn.lpstrFilter = filter;
+ ofn.lpstrFile = str;
+ ofn.Flags = isLoad?( OFN_FILEMUSTEXIST | OFN_HIDEREADONLY ) : ( OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY ) | OFN_DONTADDTORECENT;
+ ofn.nMaxFile = sizeof( str );
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.lpstrDefExt = _T( "msf" );
+
+ {
+ DWORD tick = GetTickCount( );
+ res = GetOpenFileName( &ofn );
+ if ( !res )
+ if ( GetTickCount( )-tick < 100 )
+ {
+ res = GetOpenFileName( &ofn );
+ if ( !res ) break;
+ }
+ else break;
+ }
+ if ( res )
+ {
+ HTREEITEM it = AddSkinToListFullName( hwndDlg, ofn.lpstrFile );
+ TreeView_SelectItem( GetDlgItem( hwndDlg, IDC_TREE1 ), it );
+ //SendDlgItemMessage( hwndDlg, IDC_SKINS_LIST, LB_SETCURSEL, it, 0 );
+ //SendMessage( hwndDlg, WM_COMMAND, MAKEWPARAM( IDC_SKINS_LIST, LBN_SELCHANGE ), 0 );
+ }
+ }
+ }
+ }
+ break;
+ }
+ case WM_DRAWITEM:
+ if ( wParam == IDC_PREVIEW )
+ {
+ //TODO:Draw hPreviewBitmap here
+ HDC memDC, imgDC;
+ HBITMAP hbmp, holdbmp, imgOldbmp;
+ int mWidth, mHeight;
+ RECT workRect = {0};
+ HBRUSH hbr = CreateSolidBrush( GetSysColor( COLOR_3DFACE ));
+ DRAWITEMSTRUCT *dis = ( DRAWITEMSTRUCT * )lParam;
+ mWidth = dis->rcItem.right-dis->rcItem.left;
+ mHeight = dis->rcItem.bottom-dis->rcItem.top;
+ memDC = CreateCompatibleDC( dis->hDC );
+ hbmp = ske_CreateDIB32( mWidth, mHeight );
+ holdbmp = ( HBITMAP )SelectObject( memDC, hbmp );
+ workRect = dis->rcItem;
+ OffsetRect( &workRect, -workRect.left, -workRect.top );
+ FillRect( memDC, &workRect, hbr );
+ DeleteObject( hbr );
+ if ( hPreviewBitmap )
+ {
+ //variables
+ BITMAP bmp = {0};
+ POINT imgPos = {0};
+ int wWidth, wHeight;
+ int dWidth, dHeight;
+ float xScale = 1, yScale = 1;
+ //GetSize
+ GetObject( hPreviewBitmap, sizeof( BITMAP ), &bmp );
+ wWidth = workRect.right-workRect.left;
+ wHeight = workRect.bottom-workRect.top;
+ if ( wWidth < bmp.bmWidth ) xScale = ( float )wWidth/bmp.bmWidth;
+ if ( wHeight < bmp.bmHeight ) yScale = ( float )wHeight/bmp.bmHeight;
+ xScale = min( xScale, yScale );
+ yScale = xScale;
+ dWidth = ( int )( xScale*bmp.bmWidth );
+ dHeight = ( int )( yScale*bmp.bmHeight );
+ //CalcPosition
+ imgPos.x = workRect.left+(( wWidth-dWidth )>>1 );
+ imgPos.y = workRect.top+(( wHeight-dHeight )>>1 );
+ //DrawImage
+ if ( !g_CluiData.fGDIPlusFail ) //Use gdi+ engine
+ {
+ DrawAvatarImageWithGDIp( memDC, imgPos.x, imgPos.y, dWidth, dHeight, hPreviewBitmap, 0, 0, bmp.bmWidth, bmp.bmHeight, 8, 255 );
+ }
+ else
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ imgDC = CreateCompatibleDC( dis->hDC );
+ imgOldbmp = ( HBITMAP )SelectObject( imgDC, hPreviewBitmap );
+ ske_AlphaBlend( memDC, imgPos.x, imgPos.y, dWidth, dHeight, imgDC, 0, 0, bmp.bmWidth, bmp.bmHeight, bf );
+ SelectObject( imgDC, imgOldbmp );
+ mod_DeleteDC( imgDC );
+ }
+ }
+ BitBlt( dis->hDC, dis->rcItem.left, dis->rcItem.top, mWidth, mHeight, memDC, 0, 0, SRCCOPY );
+ SelectObject( memDC, holdbmp );
+ DeleteObject( hbmp );
+ mod_DeleteDC( memDC );
+ }
+ break;
+
+ case WM_NOTIFY:
+ switch (( ( LPNMHDR )lParam )->idFrom )
+ {
+ case IDC_TREE1:
+ {
+ NMTREEVIEW * nmtv = ( NMTREEVIEW * ) lParam;
+ if ( !nmtv ) return 0;
+ if ( nmtv->hdr.code == TVN_SELCHANGEDA
+ || nmtv->hdr.code == TVN_SELCHANGEDW )
+ {
+ SkinListData * sd = NULL;
+ if ( hPreviewBitmap )
+ {
+ ske_UnloadGlyphImage( hPreviewBitmap );
+ hPreviewBitmap = NULL;
+ }
+ if ( nmtv->itemNew.lParam )
+ {
+ sd = ( SkinListData* )nmtv->itemNew.lParam;
+ {
+ TCHAR buf[MAX_PATH];
+ CallService( MS_UTILS_PATHTORELATIVET, ( WPARAM )sd->File, ( LPARAM )buf );
+ SendDlgItemMessage( hwndDlg, IDC_EDIT_SKIN_FILENAME, WM_SETTEXT, 0, ( LPARAM )buf );
+ }
+ {
+ TCHAR prfn[MAX_PATH] = {0};
+ TCHAR imfn[MAX_PATH] = {0};
+ TCHAR skinfolder[MAX_PATH] = {0};
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Preview" ), _T( "" ), imfn, SIZEOF( imfn ), sd->File );
+ IniParser::GetSkinFolder( sd->File, skinfolder );
+ _sntprintf( prfn, SIZEOF( prfn ), _T("%s\\%s"), skinfolder, imfn );
+ CallService( MS_UTILS_PATHTOABSOLUTET, ( WPARAM )prfn, ( LPARAM ) imfn );
+ char * imfn_ch = mir_t2a( imfn );
+ hPreviewBitmap = ske_LoadGlyphImage( imfn_ch );
+ mir_free( imfn_ch );
+ }
+ EnableWindow( GetDlgItem( hwndDlg, IDC_BUTTON_APPLY_SKIN ), TRUE );
+ EnableWindow( GetDlgItem( hwndDlg, IDC_BUTTON_INFO ), TRUE );
+ if ( hPreviewBitmap )
+ InvalidateRect( GetDlgItem( hwndDlg, IDC_PREVIEW ), NULL, TRUE );
+ else //prepare text
+ {
+ TCHAR Author[255];
+ TCHAR URL[MAX_PATH];
+ TCHAR Contact[255];
+ TCHAR Description[400];
+ TCHAR text[2000];
+ SkinListData* sd = NULL;
+ HTREEITEM hti = TreeView_GetSelection( GetDlgItem( hwndDlg, IDC_TREE1 ));
+ if ( hti == 0 ) return 0;
+ {
+ TVITEM tvi = {0};
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ TreeView_GetItem( GetDlgItem( hwndDlg, IDC_TREE1 ), &tvi );
+ sd = ( SkinListData* )( tvi.lParam );
+ }
+ if ( !sd ) return 0;
+
+ if ( sd->File && !_tcschr( sd->File, _T('%')))
+ {
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Author" ), TranslateT( "( unknown )" ), Author, SIZEOF( Author ), sd->File );
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "URL" ), _T( "" ), URL, SIZEOF( URL ), sd->File );
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Contact" ), _T( "" ), Contact, SIZEOF( Contact ), sd->File );
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Description" ), _T( "" ), Description, SIZEOF( Description ), sd->File );
+ _sntprintf( text, SIZEOF( text ), TranslateT( "Preview is not available\n\n%s\n----------------------\n\n%s\n\nAUTHOR(S):\n%s\n\nCONTACT:\n%s\n\nHOMEPAGE:\n%s" ),
+ sd->Name, Description, Author, Contact, URL );
+ }
+ else
+ {
+ _sntprintf( text, SIZEOF( text ), TranslateT( "%s\n\n%s\n\nAUTHORS:\n%s\n\nCONTACT:\n%s\n\nWEB:\n%s\n\n\n" ),
+ TranslateT( "reVista for Modern v0.5" ),
+ TranslateT( "This is second default Modern Contact list skin in Vista Aero style" ),
+ TranslateT( "graphics by Angeli-Ka\ntemplate by FYR" ),
+ _T("JID: fyr@jabber.ru"),
+ _T("fyr.mirandaim.ru"));
+ }
+ ShowWindow( GetDlgItem( hwndDlg, IDC_PREVIEW ), SW_HIDE );
+ ShowWindow( GetDlgItem( hwndDlg, IDC_STATIC_INFO ), SW_SHOW );
+ SendDlgItemMessage( hwndDlg, IDC_STATIC_INFO, WM_SETTEXT, 0, ( LPARAM )text );
+ }
+ }
+ else
+ {
+ //no selected
+ SendDlgItemMessage( hwndDlg, IDC_EDIT_SKIN_FILENAME, WM_SETTEXT, 0, ( LPARAM )TranslateT( "Select skin from list" ));
+ EnableWindow( GetDlgItem( hwndDlg, IDC_BUTTON_APPLY_SKIN ), FALSE );
+ EnableWindow( GetDlgItem( hwndDlg, IDC_BUTTON_INFO ), FALSE );
+ SendDlgItemMessage( hwndDlg, IDC_STATIC_INFO, WM_SETTEXT, 0, ( LPARAM )TranslateT( "Please select skin to apply" ));
+ ShowWindow( GetDlgItem( hwndDlg, IDC_PREVIEW ), SW_HIDE );
+ }
+ ShowWindow( GetDlgItem( hwndDlg, IDC_PREVIEW ), hPreviewBitmap?SW_SHOW:SW_HIDE );
+ return 0;
+ }
+ else if ( nmtv->hdr.code == TVN_DELETEITEMA || nmtv->hdr.code == TVN_DELETEITEMW )
+ {
+ mir_free_and_nil( nmtv->itemOld.lParam );
+ return 0;
+ }
+ break;
+ }
+ case 0:
+ switch (( ( LPNMHDR )lParam )->code )
+ {
+ case PSN_APPLY:
+ {
+ {
+ DWORD tick = GetTickCount( );
+ pcli->pfnClcBroadcast( INTM_RELOADOPTIONS, 0, 0 );
+ NotifyEventHooks( g_CluiData.hEventBkgrChanged, 0, 0 );
+ pcli->pfnClcBroadcast( INTM_INVALIDATE, 0, 0 );
+ RedrawWindow( GetParent( pcli->hwndContactTree ), NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_ALLCHILDREN );
+ }
+ return 0;
+ }
+ break;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+int SearchSkinFiles( HWND hwndDlg, TCHAR * Folder )
+{
+ struct _tfinddata_t fd = {0};
+ TCHAR mask[MAX_PATH];
+ long hFile;
+ _sntprintf( mask, SIZEOF( mask ), _T("%s\\*.msf"), Folder );
+ //fd.attrib = _A_SUBDIR;
+ hFile = _tfindfirst( mask, &fd );
+ if ( hFile != -1 )
+ {
+ do {
+ AddSkinToList( hwndDlg, Folder, fd.name );
+ }while ( !_tfindnext( hFile, &fd ));
+ _findclose( hFile );
+ }
+ _sntprintf( mask, SIZEOF( mask ), _T("%s\\*"), Folder );
+ hFile = _tfindfirst( mask, &fd );
+ {
+ do {
+ if ( fd.attrib&_A_SUBDIR && !( _tcsicmp( fd.name, _T(".")) == 0 || _tcsicmp( fd.name, _T("..")) == 0 ))
+ {//Next level of subfolders
+ TCHAR path[MAX_PATH];
+ _sntprintf( path, SIZEOF( path ), _T("%s\\%s"), Folder, fd.name );
+ SearchSkinFiles( hwndDlg, path );
+ }
+ }while ( !_tfindnext( hFile, &fd ));
+ _findclose( hFile );
+ }
+ return 0;
+}
+HTREEITEM FillAvailableSkinList( HWND hwndDlg )
+{
+ struct _finddata_t fd = {0};
+ //long hFile;
+ HTREEITEM res = (HTREEITEM)-1;
+ TCHAR path[MAX_PATH];//, mask[MAX_PATH];
+ int attrib;
+ TCHAR *SkinsFolder = DBGetStringT( NULL, "ModernData", "SkinsFolder" );
+ if ( !SkinsFolder ) SkinsFolder = mir_tstrdup( _T("Skins"));
+
+ CallService( MS_UTILS_PATHTOABSOLUTET, ( WPARAM )SkinsFolder, ( LPARAM )path );
+ mir_free_and_nil( SkinsFolder );
+
+ AddSkinToList( hwndDlg, TranslateT( "Default Skin" ), _T("%Default Skin%"));
+ attrib = GetFileAttributes( path );
+ if ( attrib != INVALID_FILE_ATTRIBUTES && ( attrib & FILE_ATTRIBUTE_DIRECTORY ))
+ SearchSkinFiles( hwndDlg, path );
+ {
+ TCHAR * skinfile;
+ TCHAR skinfull[MAX_PATH];
+ skinfile = DBGetStringT( NULL, SKIN, "SkinFile" );
+ if ( skinfile )
+ {
+ CallService( MS_UTILS_PATHTOABSOLUTET, ( WPARAM )skinfile, ( LPARAM )skinfull );
+ res = AddSkinToListFullName( hwndDlg, skinfull );
+
+ mir_free( skinfile );
+ }
+ }
+ return res;
+}
+HTREEITEM AddSkinToListFullName( HWND hwndDlg, TCHAR * fullName )
+{
+ TCHAR path[MAX_PATH] = {0};
+ TCHAR file[MAX_PATH] = {0};
+ TCHAR *buf;
+ _tcsncpy( path, fullName, SIZEOF( path ));
+ buf = path + _tcslen( path );
+ while ( buf > path )
+ {
+ if ( *buf == _T( '\\' ))
+ {
+ *buf = _T( '\0' );
+ break;
+ }
+ buf--;
+ }
+ buf++;
+ _tcsncpy( file, buf, SIZEOF( file ));
+ return AddSkinToList( hwndDlg, path, file );
+}
+
+
+HTREEITEM AddSkinToList( HWND hwndDlg, TCHAR * path, TCHAR* file )
+{
+ {
+ TCHAR buf[MAX_PATH];
+ _sntprintf( buf, SIZEOF( buf ), _T("%s\\%s"), path, file );
+
+ }
+ {
+ TCHAR fullName[MAX_PATH] = {0};
+ TCHAR defskinname[MAX_PATH] = {0};
+ SkinListData * sd = NULL;
+ sd = ( SkinListData * )mir_alloc( sizeof( SkinListData ));
+ if ( !sd ) return 0;
+ _sntprintf( fullName, SIZEOF( fullName ), _T("%s\\%s"), path, file );
+ memmove( defskinname, file, (_tcslen( file )-4) * sizeof(TCHAR));
+ defskinname[_tcslen( file )+1] = _T('\0');
+ if ( !file || _tcschr( file, _T('%')))
+ {
+ //sd->File = "%Default Skin%";
+ _sntprintf( sd->File, MAX_PATH, _T("%%Default Skin%%"));
+ _sntprintf( sd->Name, 100, TranslateT( "%Default Skin%" ));
+ return AddItemToTree( GetDlgItem( hwndDlg, IDC_TREE1 ), TranslateT( "Default Skin" ), sd->Name, sd );
+ }
+ else
+ {
+ GetPrivateProfileString( _T("Skin_Description_Section"), _T("Name"), defskinname, sd->Name, SIZEOF( sd->Name ), fullName );
+ _tcscpy( sd->File, fullName );
+ }
+ return AddItemToTree( GetDlgItem( hwndDlg, IDC_TREE1 ), fullName, sd->Name, sd );
+ }
+ return (HTREEITEM)-1;
+}
+
+
+
+HTREEITEM FindChild( HWND hTree, HTREEITEM Parent, TCHAR * Caption, void * data )
+{
+ HTREEITEM res = NULL, tmp = NULL;
+ if ( Parent )
+ tmp = TreeView_GetChild( hTree, Parent );
+ else
+ tmp = TreeView_GetRoot( hTree );
+ while ( tmp )
+ {
+ TVITEM tvi;
+ TCHAR buf[255];
+ tvi.hItem = tmp;
+ tvi.mask = TVIF_TEXT|TVIF_HANDLE;
+ tvi.pszText = (LPTSTR)&buf;
+ tvi.cchTextMax = 254;
+ TreeView_GetItem( hTree, &tvi );
+ if ( _tcsicmp( Caption, tvi.pszText ) == 0 )
+ {
+ if ( data )
+ {
+ SkinListData * sd = NULL;
+ TVITEM tvi = {0};
+ tvi.hItem = tmp;
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ TreeView_GetItem( hTree, &tvi );
+ sd = ( SkinListData* )( tvi.lParam );
+ if ( sd )
+ if ( !_tcsicmp( sd->File, (( SkinListData* )data )->File ))
+ return tmp;
+ }
+ else
+ return tmp;
+ }
+ tmp = TreeView_GetNextSibling( hTree, tmp );
+ }
+ return tmp;
+}
+
+
+HTREEITEM AddItemToTree( HWND hTree, TCHAR * folder, TCHAR * itemName, void * data )
+{
+ HTREEITEM rootItem = NULL;
+ HTREEITEM cItem = NULL;
+ TCHAR path[MAX_PATH];//, mask[MAX_PATH];
+ TCHAR * ptr;
+ TCHAR * ptrE;
+ BOOL ext = FALSE;
+ CallService( MS_UTILS_PATHTORELATIVET, ( WPARAM )folder, ( LPARAM )path );
+ ptrE = path;
+ while ( *ptrE != _T('\\') && *ptrE != _T('\0') && *ptrE != _T(':')) ptrE++;
+ if ( *ptrE == _T('\\'))
+ {
+ *ptrE = _T('\0');
+ ptrE++;
+ }
+ else ptrE = path;
+ ptr = ptrE;
+ do
+ {
+
+ while ( *ptrE != _T('\\') && *ptrE != _T('\0')) ptrE++;
+ if ( *ptrE == _T('\\'))
+ {
+ *ptrE = _T('\0');
+ ptrE++;
+ // find item if not - create;
+ {
+ cItem = FindChild( hTree, rootItem, ptr, NULL );
+ if ( !cItem ) // not found - create node
+ {
+ TVINSERTSTRUCT tvis;
+ tvis.hParent = rootItem;
+ tvis.hInsertAfter = TVI_ROOT;
+ tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_PARAM;
+ tvis.item.pszText = ptr;
+ {
+ tvis.item.lParam = ( LPARAM )NULL;
+ }
+ cItem = TreeView_InsertItem( hTree, &tvis );
+
+ }
+ rootItem = cItem;
+ }
+ ptr = ptrE;
+ }
+ else ext = TRUE;
+ }while ( !ext );
+ //Insert item node
+ cItem = FindChild( hTree, rootItem, itemName, data );
+ if ( !cItem )
+ {
+ TVINSERTSTRUCT tvis;
+ tvis.hParent = rootItem;
+ tvis.hInsertAfter = TVI_SORT;
+ tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_PARAM;
+ tvis.item.pszText = itemName;
+ tvis.item.lParam = ( LPARAM )data;
+ return TreeView_InsertItem( hTree, &tvis );
+ }
+ else
+ {
+ mir_free( data ); //need to free otherwise memory leak
+ return cItem;
+ }
+ return 0;
+}
+
+INT_PTR SvcActiveSkin(WPARAM wParam, LPARAM lParam)
+{
+ TCHAR *skinfile;
+ TCHAR skinfull[MAX_PATH];
+ skinfile = DBGetStringT( NULL, SKIN, "SkinFile" );
+ if ( skinfile ) {
+ CallService( MS_UTILS_PATHTOABSOLUTET, ( WPARAM )skinfile, ( LPARAM )skinfull );
+ mir_free(skinfile);
+ return (INT_PTR)mir_tstrdup(skinfull);
+ }
+
+ return NULL;
+}
+
+INT_PTR SvcApplySkin(WPARAM wParam, LPARAM lParam)
+{
+ ske_LoadSkinFromIniFile((TCHAR *)lParam, FALSE );
+ ske_LoadSkinFromDB( );
+ glOtherSkinWasLoaded = TRUE;
+ pcli->pfnClcBroadcast( INTM_RELOADOPTIONS, 0, 0 );
+ Sync( CLUIFrames_OnClistResize_mod, 0, 0 );
+ ske_RedrawCompleteWindow( );
+ Sync( CLUIFrames_OnClistResize_mod, 0, 0 );
+ {
+ HWND hwnd = pcli->hwndContactList;
+ RECT rc = {0};
+ GetWindowRect( hwnd, &rc );
+ Sync( CLUIFrames_OnMoving, hwnd, &rc );
+ }
+ if ( g_hCLUIOptionsWnd )
+ {
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_LEFTMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "LeftClientMargin", SETTING_LEFTCLIENTMARIGN_DEFAULT ));
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_RIGHTMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "RightClientMargin", SETTING_RIGHTCLIENTMARIGN_DEFAULT ));
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_TOPMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "TopClientMargin", SETTING_TOPCLIENTMARIGN_DEFAULT ));
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_BOTTOMMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "BottomClientMargin", SETTING_BOTTOMCLIENTMARIGN_DEFAULT ));
+ }
+ return 0;
+}
+
+INT_PTR SvcPreviewSkin(WPARAM wParam, LPARAM lParam)
+{
+ DRAWITEMSTRUCT *dis = ( DRAWITEMSTRUCT * )wParam;
+
+ HDC imgDC;
+ HBITMAP imgOldbmp;
+ int mWidth, mHeight;
+ RECT workRect = {0};
+ mWidth = dis->rcItem.right-dis->rcItem.left;
+ mHeight = dis->rcItem.bottom-dis->rcItem.top;
+ workRect = dis->rcItem;
+ OffsetRect( &workRect, -workRect.left, -workRect.top );
+
+ if (lParam)
+ {
+ TCHAR prfn[MAX_PATH] = {0};
+ TCHAR imfn[MAX_PATH] = {0};
+ TCHAR skinfolder[MAX_PATH] = {0};
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Preview" ), _T( "" ), imfn, SIZEOF( imfn ), (LPCTSTR)lParam );
+ IniParser::GetSkinFolder((LPCTSTR)lParam, skinfolder );
+ _sntprintf( prfn, SIZEOF( prfn ), _T("%s\\%s"), skinfolder, imfn );
+ CallService( MS_UTILS_PATHTOABSOLUTET, ( WPARAM )prfn, ( LPARAM ) imfn );
+ char * imfn_ch = mir_t2a( imfn );
+ hPreviewBitmap = ske_LoadGlyphImage( imfn_ch );
+ mir_free( imfn_ch );
+
+ if ( hPreviewBitmap )
+ {
+ //variables
+ BITMAP bmp = {0};
+ POINT imgPos = {0};
+ int wWidth, wHeight;
+ int dWidth, dHeight;
+ float xScale = 1, yScale = 1;
+ //GetSize
+ GetObject( hPreviewBitmap, sizeof( BITMAP ), &bmp );
+ wWidth = workRect.right-workRect.left;
+ wHeight = workRect.bottom-workRect.top;
+ if ( wWidth < bmp.bmWidth ) xScale = ( float )wWidth/bmp.bmWidth;
+ if ( wHeight < bmp.bmHeight ) yScale = ( float )wHeight/bmp.bmHeight;
+ xScale = min( xScale, yScale );
+ yScale = xScale;
+ dWidth = ( int )( xScale*bmp.bmWidth );
+ dHeight = ( int )( yScale*bmp.bmHeight );
+ //CalcPosition
+ imgPos.x = workRect.left+(( wWidth-dWidth )>>1 );
+ imgPos.y = workRect.top+(( wHeight-dHeight )>>1 );
+ //DrawImage
+ if ( !g_CluiData.fGDIPlusFail ) //Use gdi+ engine
+ {
+ DrawAvatarImageWithGDIp( dis->hDC, imgPos.x, imgPos.y, dWidth, dHeight, hPreviewBitmap, 0, 0, bmp.bmWidth, bmp.bmHeight, 8, 255 );
+ }
+ else
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ imgDC = CreateCompatibleDC( dis->hDC );
+ imgOldbmp = ( HBITMAP )SelectObject( imgDC, hPreviewBitmap );
+ ske_AlphaBlend( dis->hDC, imgPos.x, imgPos.y, dWidth, dHeight, imgDC, 0, 0, bmp.bmWidth, bmp.bmHeight, bf );
+ SelectObject( imgDC, imgOldbmp );
+ mod_DeleteDC( imgDC );
+ }
+ ske_UnloadGlyphImage(hPreviewBitmap);
+ }
+ }
+
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_skinselector.cpp b/plugins/Clist_modern/src/modern_skinselector.cpp
new file mode 100644
index 0000000000..2500bc3ac6
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_skinselector.cpp
@@ -0,0 +1,792 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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.
+*/
+
+///// structures and services to manage modern skin objects (mask mechanism)
+
+//#include "windows.h"
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_skinselector.h"
+#include "hdr/modern_skinengine.h"
+#include "m_api/m_skin_eng.h"
+#include "m_api/m_skinbutton.h"
+#include "hdr/modern_commonprototypes.h"
+LISTMODERNMASK * MainModernMaskList = NULL;
+
+
+/// IMPLEMENTATIONS
+char * ModernMaskToString(MODERNMASK * mm, char * buf, UINT bufsize)
+{
+ int i=0;
+ for (i=0; i < (int)mm->dwParamCnt;i++)
+ {
+ if (mm->pl_Params[i].bMaskParamFlag)
+ {
+ if (i>0) _snprintf(buf,bufsize,"%s%%",buf);
+ if (mm->pl_Params[i].bMaskParamFlag &MPF_DIFF)
+ _snprintf(buf,bufsize,"%s = %s",mm->pl_Params[i].szName,mm->pl_Params[i].szValue);
+ else
+ _snprintf(buf,bufsize,"%s^%s",mm->pl_Params[i].szName,mm->pl_Params[i].szValue);
+ }
+ else break;
+ }
+ return buf;
+}
+int SkinSelector_DeleteMask(MODERNMASK * mm)
+{
+ int i;
+ if ( !mm->pl_Params) return 0;
+ for (i=0;i < (int)mm->dwParamCnt;i++)
+ {
+ if (mm->pl_Params[i].szName) free(mm->pl_Params[i].szName);
+ if (mm->pl_Params[i].szValue) free(mm->pl_Params[i].szValue);
+ }
+ free(mm->pl_Params);
+ return 1;
+}
+
+#define _qtoupper(_c) (((_c) >= 'a' && (_c) <= 'z')?((_c)-('a'+'A')):(_c))
+BOOL wildcmpi(TCHAR* name, TCHAR* mask)
+{
+ TCHAR* last = '\0';
+ for (;; mask++, name++)
+ {
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break;
+ if (*name == '\0') return ((BOOL)!*mask);
+ }
+ if (*mask != '*') return FALSE;
+ for (;; mask++, name++)
+ {
+ while(*mask == '*')
+ {
+ last = mask++;
+ if (*mask == '\0') return ((BOOL)!*mask); /* true */
+ }
+ if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last;
+ }
+}
+
+BOOL wildcmpi(char * name, char * mask)
+{
+ char * last = '\0';
+ for (;; mask++, name++)
+ {
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break;
+ if (*name == '\0') return ((BOOL)!*mask);
+ }
+ if (*mask != '*') return FALSE;
+ for (;; mask++, name++)
+ {
+ while(*mask == '*')
+ {
+ last = mask++;
+ if (*mask == '\0') return ((BOOL)!*mask); /* true */
+ }
+ if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last;
+ }
+}
+
+BOOL __inline wildcmp(const char * name, const char * mask, BYTE option)
+{
+ const char * last = '\0';
+ for (;; mask++, name++)
+ {
+ if (*mask != '?' && *mask != *name) break;
+ if (*name == '\0') return ((BOOL)!*mask);
+ }
+ if (*mask != '*') return FALSE;
+ for (;; mask++, name++)
+ {
+ while(*mask == '*')
+ {
+ last = mask++;
+ if (*mask == '\0') return ((BOOL)!*mask); /* true */
+ }
+ if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
+ if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last;
+ }
+}
+
+BOOL MatchMask(char * name, char * mask)
+{
+ if ( !mask || !name) return mask == name;
+ if (*mask != '|') return wildcmpi(name,mask);
+ {
+ int s = 1,e = 1;
+ char * temp;
+ while (mask[e] != '\0')
+ {
+ s = e;
+ while(mask[e] != '\0' && mask[e] != '|') e++;
+ temp = (char*)malloc(e-s+1);
+ memcpy(temp,mask+s,e-s);
+ temp[e-s] = '\0';
+ if (wildcmpi(name,temp))
+ {
+ free(temp);
+ return TRUE;
+ }
+ free(temp);
+ if (mask[e] != '\0') e++;
+ else return FALSE;
+ }
+ return FALSE;
+ }
+ return FALSE;
+}
+#if __GNUC__
+#define NOINLINEASM
+#endif
+
+DWORD mod_CalcHash(const char *szStr)
+{
+#if defined _M_IX86 && !defined _NUMEGA_BC_FINALCHECK && !defined NOINLINEASM
+ __asm { //this breaks if szStr is empty
+ xor edx,edx
+ xor eax,eax
+ mov esi,szStr
+ mov al,[esi]
+ xor cl,cl
+lph_top: //only 4 of 9 instructions in here don't use AL, so optimal pipe use is impossible
+ xor edx,eax
+ inc esi
+ xor eax,eax
+ and cl,31
+ mov al,[esi]
+ add cl,5
+ test al,al
+ rol eax,cl //rol is u-pipe only, but pairable
+ //rol doesn't touch z-flag
+ jnz lph_top //5 clock tick loop. not bad.
+
+ xor eax,edx
+ }
+#else
+ DWORD hash = 0;
+ int i;
+ int shift = 0;
+ for (i=0;szStr[i];i++) {
+ hash ^= szStr[i] << shift;
+ if (shift>24) hash ^= (szStr[i]>>(32-shift))&0x7F;
+ shift = (shift+5)&0x1F;
+ }
+ return hash;
+#endif
+}
+
+/*
+DWORD mod_CalcHash(const char * a)
+{
+ DWORD Val = 0;
+ BYTE N;
+ DWORD k = mir_strlen(a);
+ if (k < 23) N = (BYTE)k; else N = 23;
+ while (N>0)
+ {
+ Val = Val << 1;
+ Val ^= ((DWORD)*a++)-31;
+ N--;
+ }
+ return Val;
+}
+*/
+int AddModernMaskToList(MODERNMASK * mm, LISTMODERNMASK * mmTemplateList)
+{
+ if ( !mmTemplateList || !mm) return -1;
+ mmTemplateList->pl_Masks = (MODERNMASK *)mir_realloc(mmTemplateList->pl_Masks,sizeof(MODERNMASK)*(mmTemplateList->dwMaskCnt+1));
+ memmove(&(mmTemplateList->pl_Masks[mmTemplateList->dwMaskCnt]),mm,sizeof(MODERNMASK));
+ mmTemplateList->dwMaskCnt++;
+ return mmTemplateList->dwMaskCnt-1;
+}
+
+int ClearMaskList(LISTMODERNMASK * mmTemplateList)
+{
+ int i;
+ if ( !mmTemplateList) return -1;
+ if ( !mmTemplateList->pl_Masks) return -1;
+ for (i=0; i < (int)mmTemplateList->dwMaskCnt; i++)
+ SkinSelector_DeleteMask(&(mmTemplateList->pl_Masks[i]));
+ mir_free_and_nil(mmTemplateList->pl_Masks);
+ mmTemplateList->dwMaskCnt = 0;
+ return 0;
+}
+int DeleteMaskByItID(DWORD mID,LISTMODERNMASK * mmTemplateList)
+{
+ if ( !mmTemplateList) return -1;
+ if (mID < 0 || mID >= mmTemplateList->dwMaskCnt) return -1;
+ if (mmTemplateList->dwMaskCnt == 1)
+ {
+ SkinSelector_DeleteMask(&(mmTemplateList->pl_Masks[0]));
+ mir_free_and_nil(mmTemplateList->pl_Masks);
+ mmTemplateList->pl_Masks = NULL;
+ mmTemplateList->dwMaskCnt;
+ }
+ else
+ {
+ MODERNMASK * newAlocation;
+ DWORD i;
+ SkinSelector_DeleteMask(&(mmTemplateList->pl_Masks[mID]));
+ newAlocation = (MODERNMASK *)mir_alloc(sizeof(MODERNMASK)*mmTemplateList->dwMaskCnt-1);
+ memmove(newAlocation,mmTemplateList->pl_Masks,sizeof(MODERNMASK)*(mID+1));
+ for (i = mID; i < mmTemplateList->dwMaskCnt-1; i++)
+ {
+ newAlocation[i] = mmTemplateList->pl_Masks[i+1];
+ newAlocation[i].dwMaskId = i;
+ }
+ mir_free_and_nil(mmTemplateList->pl_Masks);
+ mmTemplateList->pl_Masks = newAlocation;
+ mmTemplateList->dwMaskCnt--;
+ }
+ return mmTemplateList->dwMaskCnt;
+}
+
+
+int ExchangeMasksByID(DWORD mID1, DWORD mID2, LISTMODERNMASK * mmTemplateList)
+{
+ if ( !mmTemplateList) return 0;
+ if (mID1 < 0 || mID1 >= mmTemplateList->dwMaskCnt) return 0;
+ if (mID2 < 0 || mID2 >= mmTemplateList->dwMaskCnt) return 0;
+ if (mID1 == mID2) return 0;
+ {
+ MODERNMASK mm;
+ mm = mmTemplateList->pl_Masks[mID1];
+ mmTemplateList->pl_Masks[mID1] = mmTemplateList->pl_Masks[mID2];
+ mmTemplateList->pl_Masks[mID2] = mm;
+ }
+ return 1;
+}
+int SortMaskList(LISTMODERNMASK * mmList)
+{
+ DWORD pos = 1;
+ if (mmList->dwMaskCnt < 2) return 0;
+ do {
+ if (mmList->pl_Masks[pos].dwMaskId < mmList->pl_Masks[pos-1].dwMaskId)
+ {
+ ExchangeMasksByID(pos, pos-1, mmList);
+ pos--;
+ if (pos < 1)
+ pos = 1;
+ }
+ else
+ pos++;
+ } while(pos < mmList->dwMaskCnt);
+
+ return 1;
+}
+
+enum
+{
+ EXCEPTION_EQUAL,
+ EXCEPTION_NOT_EQUAL = 1,
+ EXCEPTION_WILD = 2,
+};
+static BOOL _GetParamValue( char * szText, unsigned int& start, unsigned int length, char* &param, unsigned int& paramlen, char* &value, unsigned int& valuelen, int& except )
+{
+ char * curChar = szText + start;
+ char * lastChar = szText + length;
+
+ enum { STATE_PARAM, STATE_VALUE };
+ int state = STATE_PARAM;
+ if ( start >= length ) return FALSE;
+
+ paramlen = 0;
+ valuelen = 0;
+ value = NULL;
+ param = NULL;
+
+ except = EXCEPTION_EQUAL;
+ param = curChar;
+
+
+ BOOL exitLoop = false;
+ while ( !exitLoop )
+ {
+ switch ( *curChar )
+ {
+
+ case '^':
+ if ( state == STATE_VALUE ) break;
+ except |= EXCEPTION_NOT_EQUAL;
+ exitLoop = TRUE;
+ //fall trough
+ case '=':
+ if ( state == STATE_VALUE ) break;
+ //search value end
+ paramlen = curChar - param;
+ exitLoop = TRUE;
+ break;
+
+ case ',':
+ default:
+ if ( *curChar != ',' && curChar < lastChar ) break;
+ if ( state == STATE_PARAM )
+ {
+ // no parameter name only value
+ value = param;
+ param = NULL;
+ paramlen = 0;
+ state = STATE_VALUE;
+ }
+ exitLoop = TRUE;
+ break;
+ case '*': case '?':
+ if (state == STATE_PARAM ) break;
+ except |= EXCEPTION_WILD;
+ break;
+ }
+ if ( exitLoop)
+ {
+ if (state == STATE_PARAM )
+ {
+ paramlen = curChar - param;
+ state = STATE_VALUE;
+ curChar++; //skip Sign
+ value = curChar;
+ exitLoop = FALSE;
+ }
+ else if ( state == STATE_VALUE )
+ {
+ valuelen = curChar - value;
+ }
+ }
+ else
+ {
+ curChar++;
+ }
+ }
+
+
+ start = curChar - szText + 1;
+ // skip spaces
+ if ( value && valuelen )
+ {
+ while ( *value == ' ' || *value == '\t' )
+ {
+ value++;
+ valuelen--;
+ }
+ while ( *( value + valuelen - 1) == ' ' || *( value + valuelen -1 ) == '\t' )
+ valuelen--;
+ }
+
+ if ( param && paramlen )
+ {
+ while (*param == ' ' || *param == '\t' )
+ {
+ param++;
+ paramlen--;
+ }
+ while (*(param+paramlen-1) == ' ' || *(param+paramlen-1) == '\t' )
+ paramlen--;
+ }
+
+ return ( value || param );
+}
+
+int ParseToModernMask(MODERNMASK * mm, char * szText)
+{
+ if ( !mm || !szText) return -1;
+
+ unsigned int textLen = mir_strlen(szText);
+ BYTE curParam = 0;
+
+ MASKPARAM param = {0};
+
+ unsigned int startPos = 0;
+ char * pszParam;
+ char * pszValue;
+ unsigned int paramlen;
+ unsigned int valuelen;
+ int except;
+
+ while ( _GetParamValue( szText, startPos, textLen, pszParam, paramlen, pszValue, valuelen, except))
+ {
+ if ( except & EXCEPTION_NOT_EQUAL )
+ param.bMaskParamFlag = MPF_NOT_EQUAL;
+ else
+ param.bMaskParamFlag = MPF_EQUAL;
+
+ //Get param name
+ if ( pszParam && paramlen )
+ {
+ param.szName = strdupn( pszParam, paramlen);
+ param.dwId = mod_CalcHash( param.szName );
+ }
+ else //ParamName = 'Module'
+ {
+ param.szName = _strdup( "Module");
+ param.dwId = mod_CalcHash( param.szName );
+ }
+
+
+ param.szValue = strdupn( pszValue, valuelen );
+
+ if ( !(except & EXCEPTION_WILD))
+ {
+ param.dwValueHash = mod_CalcHash( param.szValue );
+ param.bMaskParamFlag |= MPF_HASHED;
+ }
+ if (curParam >= mm->dwParamCnt)
+ {
+ mm->pl_Params = (MASKPARAM*)realloc(mm->pl_Params,(mm->dwParamCnt+1)*sizeof(MASKPARAM));
+ mm->dwParamCnt++;
+ }
+ memmove(&(mm->pl_Params[curParam]),&param,sizeof(MASKPARAM));
+ curParam++;
+ memset(&param,0,sizeof(MASKPARAM));
+ }
+ return 0;
+};
+
+BOOL CompareModernMask(MODERNMASK * mmValue,MODERNMASK * mmTemplate)
+{
+ //TODO
+ BOOL res = TRUE;
+ BOOL exit = FALSE;
+ BYTE pVal = 0, pTemp = 0;
+ while (pTemp < mmTemplate->dwParamCnt && pVal < mmValue->dwParamCnt && !exit)
+ {
+ // find pTemp parameter in mValue
+ DWORD vh, ph;
+ BOOL finded = 0;
+ MASKPARAM p = mmTemplate->pl_Params[pTemp];
+ ph = p.dwId;
+ vh = p.dwValueHash;
+ pVal = 0;
+ if ( p.bMaskParamFlag& MPF_HASHED ) //compare by hash
+ while (pVal < mmValue->dwParamCnt && mmValue->pl_Params[pVal].bMaskParamFlag != 0)
+ {
+ if (mmValue->pl_Params[pVal].dwId == ph)
+ {
+ if (mmValue->pl_Params[pVal].dwValueHash == vh){finded = 1; break;}
+ else {finded = 0; break;}
+ }
+ pVal++;
+ }
+ else
+ while (mmValue->pl_Params[pVal].bMaskParamFlag != 0)
+ {
+ if (mmValue->pl_Params[pVal].dwId == ph)
+ {
+ if (wildcmp(mmValue->pl_Params[pVal].szValue,p.szValue,0)){finded = 1; break;}
+ else {finded = 0; break;}
+ }
+ pVal++;
+ }
+ if ( !((finded && !(p.bMaskParamFlag&MPF_DIFF)) || (!finded && (p.bMaskParamFlag&MPF_DIFF))))
+ {res = FALSE; break;}
+ pTemp++;
+ }
+ return res;
+};
+
+BOOL CompareStrWithModernMask(char * szValue,MODERNMASK * mmTemplate)
+{
+ MODERNMASK mmValue = {0};
+ int res;
+ if ( !ParseToModernMask(&mmValue, szValue))
+ {
+ res = CompareModernMask(&mmValue,mmTemplate);
+ SkinSelector_DeleteMask(&mmValue);
+ return res;
+ }
+ else return 0;
+};
+
+//AddingMask
+int AddStrModernMaskToList(DWORD maskID, char * szStr, char * objectName, LISTMODERNMASK * mmTemplateList, void * pObjectList)
+{
+ if ( !szStr || !mmTemplateList) return -1;
+
+ MODERNMASK mm = {0};
+ if (ParseToModernMask(&mm,szStr)) return -1;
+
+ mm.bObjectFound = FALSE;
+ mm.szObjectName = mir_strdup(objectName);
+ //mm.pObject = (void*) ske_FindObjectByName(objectName, OT_ANY, (SKINOBJECTSLIST*) pObjectList);
+ mm.dwMaskId = maskID;
+ return AddModernMaskToList(&mm,mmTemplateList);
+}
+
+//Searching
+MODERNMASK * FindMaskByStr(char * szValue,LISTMODERNMASK * mmTemplateList)
+{
+ //TODO
+ return NULL;
+}
+
+SKINOBJECTDESCRIPTOR * skin_FindObjectByMask (MODERNMASK * mm,LISTMODERNMASK * mmTemplateList)
+{
+ SKINOBJECTDESCRIPTOR * res = NULL;
+ DWORD i=0;
+ while (i < mmTemplateList->dwMaskCnt)
+ {
+ if (CompareModernMask(mm,&(mmTemplateList->pl_Masks[i])))
+ {
+ res = (SKINOBJECTDESCRIPTOR*) mmTemplateList->pl_Masks[i].pObject;
+ return res;
+ }
+ i++;
+ }
+ return res;
+}
+
+SKINOBJECTDESCRIPTOR * skin_FindObjectByRequest(char * szValue,LISTMODERNMASK * mmTemplateList)
+{
+ MODERNMASK mm = {0};
+ SKINOBJECTDESCRIPTOR * res = NULL;
+ if ( !mmTemplateList)
+ if (g_SkinObjectList.pMaskList)
+ mmTemplateList = g_SkinObjectList.pMaskList;
+ else
+ return NULL;
+
+ if ( !mmTemplateList) return NULL;
+ ParseToModernMask(&mm,szValue);
+ res = skin_FindObjectByMask(&mm,mmTemplateList);
+ SkinSelector_DeleteMask(&mm);
+ return res;
+}
+
+TCHAR * GetParamNT(char * string, TCHAR * buf, int buflen, BYTE paramN, char Delim, BOOL SkipSpaces)
+{
+ char *ansibuf = (char*)mir_alloc(buflen/sizeof(TCHAR));
+ GetParamN(string, ansibuf, buflen/sizeof(TCHAR), paramN, Delim, SkipSpaces);
+ MultiByteToWideChar(CP_UTF8,0,ansibuf,-1,buf,buflen);
+ mir_free(ansibuf);
+ return buf;
+}
+
+char * GetParamN(char * string, char * buf, int buflen, BYTE paramN, char Delim, BOOL SkipSpaces)
+{
+ int i=0;
+ DWORD start = 0;
+ DWORD end = 0;
+ DWORD CurentCount = 0;
+ DWORD len;
+ while (i < mir_strlen(string))
+ {
+ if (string[i] == Delim)
+ {
+ if (CurentCount == paramN) break;
+ start = i+1;
+ CurentCount++;
+ }
+ i++;
+ }
+ if (CurentCount == paramN)
+ {
+ if (SkipSpaces)
+ { //remove spaces
+ while (string[start] == ' ' && (int)start < mir_strlen(string))
+ start++;
+ while (i>1 && string[i-1] == ' ' && i>(int)start)
+ i--;
+ }
+ len = ((int)(i-start) < buflen)?i-start:buflen;
+ strncpy(buf,string+start,len);
+ buf[len] = '\0';
+ }
+ else buf[0] = '\0';
+ return buf;
+}
+
+//Parse DB string and add buttons
+int RegisterButtonByParce(char * ObjectName, char * Params)
+{
+ char buf [255];
+ int res;
+ GetParamN(Params,buf, SIZEOF(buf),0,',',0);
+ // if (boolstrcmpi("Push",buf)
+ { //Push type
+ char buf2[20] = {0};
+ char pServiceName[255] = {0};
+ char pStatusServiceName[255] = {0};
+ int Left, Top,Right,Bottom;
+ int MinWidth, MinHeight;
+ char TL[9] = {0};
+ TCHAR Hint[250] = {0};
+ char Section[250] = {0};
+ char Type[250] = {0};
+
+ DWORD alingnto;
+ int a = ((int)mir_bool_strcmpi(buf,"Switch"))*2;
+
+ GetParamN(Params,pServiceName, SIZEOF(pServiceName),1,',',0);
+ // if (a) GetParamN(Params,pStatusServiceName, sizeof(pStatusServiceName),a+1,',',0);
+ Left = atoi(GetParamN(Params,buf2, SIZEOF(buf2),a+2,',',0));
+ Top = atoi(GetParamN(Params,buf2, SIZEOF(buf2),a+3,',',0));
+ Right = atoi(GetParamN(Params,buf2, SIZEOF(buf2),a+4,',',0));
+ Bottom = atoi(GetParamN(Params,buf2, SIZEOF(buf2),a+5,',',0));
+ GetParamN(Params,TL, SIZEOF(TL),a+6,',',0);
+
+ MinWidth = atoi(GetParamN(Params,buf2, SIZEOF(buf2),a+7,',',0));
+ MinHeight = atoi(GetParamN(Params,buf2, SIZEOF(buf2),a+8,',',0));
+ GetParamNT(Params,Hint, SIZEOF(Hint),a+9,',',0);
+ if (a)
+ {
+ GetParamN(Params,Section, SIZEOF(Section),2,',',0);
+ GetParamN(Params,Type, SIZEOF(Type),3,',',0);
+ }
+ alingnto = ((TL[0] == 'R') ? SBF_ALIGN_TL_RIGHT : 0 )
+ +((TL[0] == 'C') ? SBF_ALIGN_TL_HCENTER : 0 )
+ +((TL[1] == 'B') ? SBF_ALIGN_TL_BOTTOM : 0 )
+ +((TL[1] == 'C') ? SBF_ALIGN_TL_VCENTER : 0 )
+ +((TL[2] == 'R') ? SBF_ALIGN_BR_RIGHT : 0 )
+ +((TL[2] == 'C') ? SBF_ALIGN_BR_HCENTER : 0 )
+ +((TL[3] == 'B') ? SBF_ALIGN_BR_BOTTOM : 0 )
+ +((TL[3] == 'C') ? SBF_ALIGN_BR_VCENTER : 0 )
+ +((TL[4] == 'I') ? SBF_CALL_ON_PRESS : 0 );
+ if (a) res = ModernSkinButton_AddButton(pcli->hwndContactList,ObjectName+1,pServiceName,pStatusServiceName,"\0",Left,Top,Right,Bottom,alingnto,TranslateTS(Hint),Section,Type,MinWidth,MinHeight);
+ else res = ModernSkinButton_AddButton(pcli->hwndContactList,ObjectName+1,pServiceName,pStatusServiceName,"\0",Left,Top,Right,Bottom,alingnto,TranslateTS(Hint),NULL,NULL,MinWidth,MinHeight);
+ }
+ return res;
+}
+
+//Parse DB string and add object
+// Params is:
+// Glyph,None
+// Glyph,Solid, < ColorR>, < ColorG>, < ColorB>, < Alpha>
+// Glyph,Image,Filename,(TileBoth|TileVert|TileHor|StretchBoth), < MarginLeft>, < MarginTop>, < MarginRight>, < MarginBottom>, < Alpha>
+int RegisterObjectByParce(char * ObjectName, char * Params)
+{
+ if ( !ObjectName || !Params) return 0;
+ {
+ int res = 0;
+ SKINOBJECTDESCRIPTOR obj = {0};
+ char buf[250];
+ obj.szObjectID = mir_strdup(ObjectName);
+ GetParamN(Params,buf, SIZEOF(buf),0,',',0);
+ if (mir_bool_strcmpi(buf,"Glyph"))
+ obj.bType = OT_GLYPHOBJECT;
+ else if (mir_bool_strcmpi(buf,"Font"))
+ obj.bType = OT_FONTOBJECT;
+
+ switch (obj.bType)
+ {
+ case OT_GLYPHOBJECT:
+ {
+ GLYPHOBJECT gl = {0};
+ GetParamN(Params,buf, SIZEOF(buf),1,',',0);
+ if (mir_bool_strcmpi(buf,"Solid"))
+ {
+ //Solid
+ int r,g,b;
+ gl.Style = ST_BRUSH;
+ r = atoi(GetParamN(Params,buf, SIZEOF(buf),2,',',0));
+ g = atoi(GetParamN(Params,buf, SIZEOF(buf),3,',',0));
+ b = atoi(GetParamN(Params,buf, SIZEOF(buf),4,',',0));
+ gl.dwAlpha = atoi(GetParamN(Params,buf, SIZEOF(buf),5,',',0));
+ gl.dwColor = RGB(r,g,b);
+ }
+ else if (mir_bool_strcmpi(buf,"Image"))
+ {
+ //Image
+ gl.Style = ST_IMAGE;
+ gl.szFileName = mir_strdup(GetParamN(Params,buf, SIZEOF(buf),2,',',0));
+ gl.dwLeft = atoi(GetParamN(Params,buf, SIZEOF(buf),4,',',0));
+ gl.dwTop = atoi(GetParamN(Params,buf, SIZEOF(buf),5,',',0));
+ gl.dwRight = atoi(GetParamN(Params,buf, SIZEOF(buf),6,',',0));
+ gl.dwBottom = atoi(GetParamN(Params,buf, SIZEOF(buf),7,',',0));
+ gl.dwAlpha = atoi(GetParamN(Params,buf, SIZEOF(buf),8,',',0));
+ GetParamN(Params,buf, SIZEOF(buf),3,',',0);
+ if (mir_bool_strcmpi(buf,"TileBoth")) gl.FitMode = FM_TILE_BOTH;
+ else if (mir_bool_strcmpi(buf,"TileVert")) gl.FitMode = FM_TILE_VERT;
+ else if (mir_bool_strcmpi(buf,"TileHorz")) gl.FitMode = FM_TILE_HORZ;
+ else gl.FitMode = 0;
+ }
+ else if (mir_bool_strcmpi(buf,"Fragment"))
+ {
+ //Image
+ gl.Style = ST_FRAGMENT;
+ gl.szFileName = mir_strdup(GetParamN(Params,buf, SIZEOF(buf),2,',',0));
+
+ gl.clipArea.x = atoi(GetParamN(Params,buf, SIZEOF(buf),3,',',0));
+ gl.clipArea.y = atoi(GetParamN(Params,buf, SIZEOF(buf),4,',',0));
+ gl.szclipArea.cx = atoi(GetParamN(Params,buf, SIZEOF(buf),5,',',0));
+ gl.szclipArea.cy = atoi(GetParamN(Params,buf, SIZEOF(buf),6,',',0));
+
+ gl.dwLeft = atoi(GetParamN(Params,buf, SIZEOF(buf),8,',',0));
+ gl.dwTop = atoi(GetParamN(Params,buf, SIZEOF(buf),9,',',0));
+ gl.dwRight = atoi(GetParamN(Params,buf, SIZEOF(buf),10,',',0));
+ gl.dwBottom = atoi(GetParamN(Params,buf, SIZEOF(buf),11,',',0));
+ gl.dwAlpha = atoi(GetParamN(Params,buf, SIZEOF(buf),12,',',0));
+ GetParamN(Params,buf, SIZEOF(buf),7,',',0);
+ if (mir_bool_strcmpi(buf,"TileBoth")) gl.FitMode = FM_TILE_BOTH;
+ else if (mir_bool_strcmpi(buf,"TileVert")) gl.FitMode = FM_TILE_VERT;
+ else if (mir_bool_strcmpi(buf,"TileHorz")) gl.FitMode = FM_TILE_HORZ;
+ else gl.FitMode = 0;
+ }
+ else
+ {
+ //None
+ gl.Style = ST_SKIP;
+ }
+ obj.Data = &gl;
+ res = ske_AddDescriptorToSkinObjectList(&obj,NULL);
+ mir_free_and_nil(obj.szObjectID);
+ mir_free_and_nil(gl.szFileName);
+ return res;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+
+int SkinDrawGlyphMask(HDC hdc, RECT * rcSize, RECT * rcClip, MODERNMASK * ModernMask)
+{
+ if ( !ModernMask) return 0;
+
+ SKINDRAWREQUEST rq;
+ rq.hDC = hdc;
+ rq.rcDestRect = *rcSize;
+ rq.rcClipRect = *rcClip;
+ strncpy(rq.szObjectID,"Masked draw",SIZEOF("Masked draw"));
+ return ske_Service_DrawGlyph((WPARAM)&rq,(LPARAM)ModernMask);
+}
+
+
+int __inline SkinDrawWindowBack(HWND hwndIn, HDC hdc, RECT * rcClip, char * objectID)
+{
+ SKINDRAWREQUEST rq;
+ POINT pt = {0};
+ RECT rc,r1;
+
+ HWND hwnd = (HWND)CallService(MS_CLUI_GETHWND,0,0);
+ if ( !objectID) return 0;
+ GetWindowRect(hwndIn,&r1);
+ pt.x = r1.left;
+ pt.y = r1.top;
+ //ClientToScreen(hwndIn,&pt);
+ GetWindowRect(hwnd,&rc);
+ OffsetRect(&rc,-pt.x ,-pt.y);
+ rq.hDC = hdc;
+ rq.rcDestRect = rc;
+ rq.rcClipRect = *rcClip;
+ strncpy(rq.szObjectID,objectID,SIZEOF(rq.szObjectID));
+ ///ske_Service_DrawGlyph((WPARAM)&rq,0); //$$$
+ return CallService(MS_SKIN_DRAWGLYPH,(WPARAM)&rq,0);
+}
diff --git a/plugins/Clist_modern/src/modern_statusbar.cpp b/plugins/Clist_modern/src/modern_statusbar.cpp
new file mode 100644
index 0000000000..f7e61abab1
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_statusbar.cpp
@@ -0,0 +1,1136 @@
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_statusbar.h"
+#include "./m_api/m_skin_eng.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_clcpaint.h"
+#include "hdr/modern_sync.h"
+
+BOOL tooltipshoing;
+POINT lastpnt;
+
+#define TM_STATUSBAR 23435234
+#define TM_STATUSBARHIDE 23435235
+
+HWND hModernStatusBar = NULL;
+HANDLE hFramehModernStatusBar = NULL;
+extern void ApplyViewMode(const char *Name, bool onlySelector = false );
+extern void SaveViewMode(const char *name, const TCHAR *szGroupFilter, const char *szProtoFilter, DWORD statusMask, DWORD stickyStatusMask, unsigned int options, unsigned int stickies, unsigned int operators, unsigned int lmdat);
+
+//int FindFrameID(HWND FrameHwnd);
+COLORREF sttGetColor(char * module, char * color, COLORREF defColor);
+
+#define DBFONTF_BOLD 1
+#define DBFONTF_ITALIC 2
+#define DBFONTF_UNDERLINE 4
+
+typedef struct _ProtoItemData
+{
+ HICON icon;
+ HICON extraIcon;
+ int iconIndex;
+ char * ProtoName;
+ char * AccountName;
+ int ProtoStatus;
+ TCHAR *ProtoHumanName;
+ char *ProtoEMailCount;
+ char * ProtoStatusText;
+ TCHAR * ProtoXStatus;
+ int ProtoPos;
+ int fullWidth;
+ RECT protoRect;
+ BOOL DoubleIcons;
+
+ BYTE showProtoIcon;
+ BYTE showProtoName;
+ BYTE showStatusName;
+ BYTE xStatusMode; // 0-only main, 1-xStatus, 2-main as overlay
+ BYTE connectingIcon;
+ BYTE showProtoEmails;
+ BYTE SBarRightClk;
+ int PaddingLeft;
+ int PaddingRight;
+
+ bool isDimmed;
+
+} ProtoItemData;
+
+ProtoItemData *ProtosData = NULL;
+int allocedItemData = 0;
+STATUSBARDATA g_StatusBarData = {0};
+
+
+char * ApendSubSetting(char * buf, int size, char *first, char *second)
+{
+ _snprintf(buf,size,"%sFont%s",first,second);
+ return buf;
+}
+
+int LoadStatusBarData()
+{
+ g_StatusBarData.perProtoConfig = db_get_b(NULL,"CLUI","SBarPerProto",SETTING_SBARPERPROTO_DEFAULT);
+ g_StatusBarData.showProtoIcon = db_get_b(NULL,"CLUI","SBarShow",SETTING_SBARSHOW_DEFAULT)&1;
+ g_StatusBarData.showProtoName = db_get_b(NULL,"CLUI","SBarShow",SETTING_SBARSHOW_DEFAULT)&2;
+ g_StatusBarData.showStatusName = db_get_b(NULL,"CLUI","SBarShow",SETTING_SBARSHOW_DEFAULT)&4;
+ g_StatusBarData.xStatusMode = (BYTE)(db_get_b(NULL,"CLUI","ShowXStatus",SETTING_SHOWXSTATUS_DEFAULT));
+ g_StatusBarData.connectingIcon = db_get_b(NULL,"CLUI","UseConnectingIcon",SETTING_USECONNECTINGICON_DEFAULT);
+ g_StatusBarData.showProtoEmails = db_get_b(NULL,"CLUI","ShowUnreadEmails",SETTING_SHOWUNREADEMAILS_DEFAULT);
+ g_StatusBarData.SBarRightClk = db_get_b(NULL,"CLUI","SBarRightClk",SETTING_SBARRIGHTCLK_DEFAULT);
+
+ g_StatusBarData.nProtosPerLine = db_get_b(NULL,"CLUI","StatusBarProtosPerLine",SETTING_PROTOSPERLINE_DEFAULT);
+ g_StatusBarData.Align = db_get_b(NULL,"CLUI","Align",SETTING_ALIGN_DEFAULT);
+ g_StatusBarData.VAlign = db_get_b(NULL,"CLUI","VAlign",SETTING_VALIGN_DEFAULT);
+ g_StatusBarData.sameWidth = db_get_b(NULL,"CLUI","EqualSections",SETTING_EQUALSECTIONS_DEFAULT);
+ g_StatusBarData.rectBorders.left = db_get_dw(NULL,"CLUI","LeftOffset",SETTING_LEFTOFFSET_DEFAULT);
+ g_StatusBarData.rectBorders.right = db_get_dw(NULL,"CLUI","RightOffset",SETTING_RIGHTOFFSET_DEFAULT);
+ g_StatusBarData.rectBorders.top = db_get_dw(NULL,"CLUI","TopOffset",SETTING_TOPOFFSET_DEFAULT);
+ g_StatusBarData.rectBorders.bottom = db_get_dw(NULL,"CLUI","BottomOffset",SETTING_BOTTOMOFFSET_DEFAULT);
+ g_StatusBarData.extraspace = (BYTE)db_get_dw(NULL,"CLUI","SpaceBetween",SETTING_SPACEBETWEEN_DEFAULT);
+
+ if (g_StatusBarData.BarFont) DeleteObject(g_StatusBarData.BarFont);
+ g_StatusBarData.BarFont = NULL;//LoadFontFromDB("ModernData","StatusBar",&g_StatusBarData.fontColor);
+ {
+ int vis = db_get_b(NULL,"CLUI","ShowSBar",SETTING_SHOWSBAR_DEFAULT);
+ int frameopt;
+ int frameID = Sync( FindFrameID, hModernStatusBar );
+ frameopt = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,frameID),0);
+ frameopt = frameopt & (~F_VISIBLE);
+ if (vis)
+ {
+ ShowWindow(hModernStatusBar,SW_SHOW);
+ frameopt |= F_VISIBLE;
+ }
+ else
+ {
+ ShowWindow(hModernStatusBar,SW_HIDE);
+ };
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,frameID),frameopt);
+ }
+ g_StatusBarData.TextEffectID = db_get_b(NULL,"StatusBar","TextEffectID",SETTING_TEXTEFFECTID_DEFAULT);
+ g_StatusBarData.TextEffectColor1 = db_get_dw(NULL,"StatusBar","TextEffectColor1",SETTING_TEXTEFFECTCOLOR1_DEFAULT);
+ g_StatusBarData.TextEffectColor2 = db_get_dw(NULL,"StatusBar","TextEffectColor2",SETTING_TEXTEFFECTCOLOR2_DEFAULT);
+
+ if (g_StatusBarData.hBmpBackground) {DeleteObject(g_StatusBarData.hBmpBackground); g_StatusBarData.hBmpBackground = NULL;}
+
+ if (g_CluiData.fDisableSkinEngine)
+ {
+ DBVARIANT dbv;
+ g_StatusBarData.bkColour = sttGetColor("StatusBar","BkColour",CLCDEFAULT_BKCOLOUR);
+ if (db_get_b(NULL,"StatusBar","UseBitmap",CLCDEFAULT_USEBITMAP)) {
+ if ( !DBGetContactSettingString(NULL,"StatusBar","BkBitmap",&dbv)) {
+ g_StatusBarData.hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ }
+ g_StatusBarData.bkUseWinColors = db_get_b(NULL,"StatusBar", "UseWinColours", CLCDEFAULT_USEWINDOWSCOLOURS);
+ g_StatusBarData.backgroundBmpUse = db_get_w(NULL,"StatusBar","BkBmpUse",CLCDEFAULT_BKBMPUSE);
+ }
+ SendMessage(pcli->hwndContactList,WM_SIZE,0,0);
+
+ return 1;
+}
+
+int BgStatusBarChange(WPARAM wParam,LPARAM lParam)
+{
+ if (MirandaExiting()) return 0;
+ LoadStatusBarData();
+ return 0;
+}
+
+//ProtocolData;
+int NewStatusPaintCallbackProc(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData)
+{
+ return ModernDrawStatusBar(hWnd,hDC);
+}
+
+int ModernDrawStatusBar(HWND hwnd, HDC hDC)
+{
+ if (hwnd == (HWND)-1) return 0;
+ if (GetParent(hwnd) == pcli->hwndContactList)
+ return ModernDrawStatusBarWorker(hwnd,hDC);
+ else
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ return 0;
+}
+
+int ModernDrawStatusBarWorker(HWND hWnd, HDC hDC)
+{
+ int line;
+ int iconHeight = GetSystemMetrics(SM_CYSMICON)+2;
+ int protosperline = 0;
+ int visProtoCount = 0;
+ int protoCount;
+ int SumWidth = 0;
+ int rectwidth = 0;
+ int aligndx = 0;
+ int * ProtoWidth = NULL;
+ int i,j,po = 0;
+
+ char servName[40];
+ char protoNameExt[40];
+ // Count visible protos
+ PROTOACCOUNT **accs;
+ RECT rc;
+ HFONT hOldFont;
+ int iconY, textY;
+ int spaceWidth;
+ int maxwidth = 0;
+ int xstatus = 0;
+ SIZE textSize = {0};
+ GetClientRect(hWnd,&rc);
+ if (g_CluiData.fDisableSkinEngine) {
+ if (g_StatusBarData.bkUseWinColors && xpt_IsThemed(g_StatusBarData.hTheme))
+ xpt_DrawTheme(g_StatusBarData.hTheme, hWnd, hDC, 0, 0, &rc, &rc);
+ else
+ DrawBackGround(hWnd, hDC, g_StatusBarData.hBmpBackground, g_StatusBarData.bkColour, g_StatusBarData.backgroundBmpUse );
+ }
+ else SkinDrawGlyph(hDC,&rc,&rc,"Main,ID=StatusBar"); //TBD
+
+ g_StatusBarData.nProtosPerLine = db_get_b(NULL,"CLUI","StatusBarProtosPerLine",SETTING_PROTOSPERLINE_DEFAULT);
+ hOldFont = g_clcPainter.ChangeToFont(hDC,NULL,FONTID_STATUSBAR_PROTONAME,NULL);
+
+ // hOldFont = SelectObject(hDC,g_StatusBarData.BarFont);
+ // SetTextColor(hDC,g_StatusBarData.fontColor);
+ {
+
+ GetTextExtentPoint32A(hDC," ",1,&textSize);
+ spaceWidth = textSize.cx;
+ textY = rc.top+((rc.bottom-rc.top-textSize.cy)>>1);
+ }
+ iconY = rc.top+((rc.bottom-rc.top-GetSystemMetrics(SM_CXSMICON))>>1);
+
+ {
+ ProtoEnumAccounts( &protoCount, &accs );
+ if (allocedItemData && ProtosData) {
+ for (int k = 0; k < allocedItemData; k++) {
+ mir_free(ProtosData[k].ProtoXStatus);
+ mir_free(ProtosData[k].ProtoName);
+ mir_free(ProtosData[k].AccountName);
+ mir_free(ProtosData[k].ProtoHumanName);
+ mir_free(ProtosData[k].ProtoEMailCount);
+ mir_free(ProtosData[k].ProtoStatusText);
+ }
+ mir_free_and_nil(ProtosData);
+ allocedItemData = 0;
+ }
+ if ( protoCount == 0 )
+ return 0;
+
+ ProtosData = (ProtoItemData*)mir_alloc(sizeof(ProtoItemData)*protoCount);
+ memset(ProtosData,0,sizeof(ProtoItemData)*protoCount);
+ for (j = 0; j < protoCount; j++)
+ {
+ int vis;
+ char buf[256];
+
+ i = pcli->pfnGetAccountIndexByPos(j);
+ if (i == -1)
+ vis = FALSE;
+ else
+ vis = pcli->pfnGetProtocolVisibility(accs[i]->szModuleName);
+ if ( !vis) continue;
+
+ mir_snprintf(buf, SIZEOF(buf), "SBarAccountIsCustom_%s", accs[i]->szModuleName);
+
+ if (g_StatusBarData.perProtoConfig && db_get_b(NULL, "CLUI", buf, SETTING_SBARACCOUNTISCUSTOM_DEFAULT))
+ {
+ mir_snprintf(buf, SIZEOF(buf), "HideAccount_%s", accs[i]->szModuleName);
+ if (db_get_b(NULL, "CLUI", buf, SETTING_SBARHIDEACCOUNT_DEFAULT))
+ continue;
+
+ mir_snprintf(buf, SIZEOF(buf), "SBarShow_%s", accs[i]->szModuleName);
+ {
+ BYTE showOps = db_get_b(NULL,"CLUI", buf, SETTING_SBARSHOW_DEFAULT);
+ ProtosData[visProtoCount].showProtoIcon = showOps&1;
+ ProtosData[visProtoCount].showProtoName = showOps&2;
+ ProtosData[visProtoCount].showStatusName = showOps&4;
+ }
+
+ mir_snprintf(buf, SIZEOF(buf), "ShowXStatus_%s", accs[i]->szModuleName);
+ ProtosData[visProtoCount].xStatusMode = db_get_b(NULL,"CLUI", buf, SETTING_SBARSHOW_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "UseConnectingIcon_%s", accs[i]->szModuleName);
+ ProtosData[visProtoCount].connectingIcon = db_get_b(NULL,"CLUI", buf, SETTING_USECONNECTINGICON_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "ShowUnreadEmails_%s", accs[i]->szModuleName);
+ ProtosData[visProtoCount].showProtoEmails = db_get_b(NULL,"CLUI", buf, SETTING_SHOWUNREADEMAILS_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "SBarRightClk_%s", accs[i]->szModuleName);
+ ProtosData[visProtoCount].SBarRightClk = db_get_b(NULL,"CLUI", buf, SETTING_SBARRIGHTCLK_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "PaddingLeft_%s", accs[i]->szModuleName);
+ ProtosData[visProtoCount].PaddingLeft = db_get_dw(NULL,"CLUI", buf, SETTING_PADDINGLEFT_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "PaddingRight_%s", accs[i]->szModuleName);
+ ProtosData[visProtoCount].PaddingRight = db_get_dw(NULL,"CLUI", buf, SETTING_PADDINGRIGHT_DEFAULT);
+ }
+ else
+ {
+ ProtosData[visProtoCount].showProtoIcon = g_StatusBarData.showProtoIcon;
+ ProtosData[visProtoCount].showProtoName = g_StatusBarData.showProtoName;
+ ProtosData[visProtoCount].showStatusName = g_StatusBarData.showStatusName;
+ ProtosData[visProtoCount].xStatusMode = g_StatusBarData.xStatusMode;
+ ProtosData[visProtoCount].connectingIcon = g_StatusBarData.connectingIcon;
+ ProtosData[visProtoCount].showProtoEmails = g_StatusBarData.showProtoEmails;
+ ProtosData[visProtoCount].SBarRightClk = 0;
+ ProtosData[visProtoCount].PaddingLeft = 0;
+ ProtosData[visProtoCount].PaddingRight = 0;
+ }
+
+ ProtosData[visProtoCount].ProtoStatus = CallProtoService(accs[i]->szModuleName,PS_GETSTATUS,0,0);
+
+ ProtosData[visProtoCount].ProtoEMailCount = NULL;
+ if (ProtosData[visProtoCount].ProtoStatus > ID_STATUS_OFFLINE)
+ {
+ // create service name
+ mir_snprintf(servName, SIZEOF(servName), "%s/GetUnreadEmailCount", accs[i]->szModuleName);
+ if (ProtosData[visProtoCount].showProtoEmails == 1 && ServiceExists(servName))
+ {
+ mir_snprintf(protoNameExt, SIZEOF(protoNameExt),"[%d]", (int) CallService(servName, 0, 0));
+ ProtosData[visProtoCount].ProtoEMailCount = mir_strdup(protoNameExt);
+ }
+ }
+
+ ProtosData[visProtoCount].ProtoHumanName = mir_tstrdup(accs[i]->tszAccountName);
+ ProtosData[visProtoCount].AccountName = mir_strdup(accs[i]->szModuleName);
+ ProtosData[visProtoCount].ProtoName = mir_strdup(accs[i]->szProtoName);
+ ProtosData[visProtoCount].ProtoStatusText = mir_strdup((char*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION,(WPARAM)ProtosData[visProtoCount].ProtoStatus,0));
+ ProtosData[visProtoCount].ProtoPos = visProtoCount;
+
+ ProtosData[visProtoCount].isDimmed = 0;
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_PROTOS)
+ {
+ char szTemp[2048];
+ mir_snprintf(szTemp, SIZEOF(szTemp), "%s|", ProtosData[visProtoCount].AccountName );
+ ProtosData[visProtoCount].isDimmed = strstr(g_CluiData.protoFilter, szTemp) ? 0 : 1;
+ }
+
+ visProtoCount++;
+ allocedItemData++;
+ }
+
+ // Calculate rects
+
+ //START MULTILINE HERE
+ {
+ int orig_protoCount = protoCount;
+ int orig_visProtoCount = visProtoCount;
+ ProtoItemData * orig_ProtosData = ProtosData;
+ int linecount;
+ if (g_StatusBarData.nProtosPerLine)
+ protosperline = g_StatusBarData.nProtosPerLine;
+ else if (orig_visProtoCount)
+ protosperline = orig_visProtoCount;
+ else if (protoCount)
+ {
+ protosperline = protoCount;
+ orig_visProtoCount = protoCount;
+ }
+ else
+ {
+ protosperline = 1;
+ orig_visProtoCount = 1;
+ }
+ protosperline = min(protosperline,orig_visProtoCount);
+ linecount = protosperline ? (orig_visProtoCount+(protosperline-1))/protosperline : 1; //divide with rounding to up
+ for (line = 0; line < linecount; line++)
+ {
+ int height;
+ int rowsdy;
+ int rowheight = max(textSize.cy+2,iconHeight);
+ protoCount = min(protosperline,(orig_protoCount-line*protosperline));
+ visProtoCount = min(protosperline,(orig_visProtoCount-line*protosperline));
+ ProtosData += line*protosperline;
+ GetClientRect(hWnd,&rc);
+
+ rc.top += g_StatusBarData.rectBorders.top;
+ rc.bottom -= g_StatusBarData.rectBorders.bottom;
+
+ aligndx = 0;
+ maxwidth = 0;
+ xstatus = 0;
+ SumWidth = 0;
+ height = (rowheight*linecount);
+
+ if (height > (rc.bottom - rc.top))
+ {
+ rowheight = (rc.bottom - rc.top) / linecount;
+ height = (rowheight*linecount);
+ }
+
+ rowsdy = ((rc.bottom-rc.top)-height)/2;
+ if (rowheight*(line)+rowsdy < rc.top-rowheight) continue;
+ if (rowheight*(line+1)+rowsdy>rc.bottom+rowheight)
+ {
+ ProtosData = orig_ProtosData;
+ break;
+ }
+ if (g_StatusBarData.VAlign == 0) //top
+ {
+ rc.bottom = rc.top+rowheight*(line+1);
+ rc.top = rc.top+rowheight*line+1;
+ }
+ else if (g_StatusBarData.VAlign == 1) //center
+ {
+ rc.bottom = rc.top+rowsdy+rowheight*(line+1);
+ rc.top = rc.top+rowsdy+rowheight*line+1;
+ }
+ else if (g_StatusBarData.VAlign == 2) //bottom
+ {
+ rc.top = rc.bottom - (rowheight*(linecount - line));
+ rc.bottom = rc.bottom - (rowheight*(linecount - line - 1)+1);
+ }
+
+ textY = rc.top+(((rc.bottom-rc.top)-textSize.cy)/2);
+ iconY = rc.top+(((rc.bottom-rc.top)-iconHeight)/2);
+
+ { //Code for each line
+ {
+ DWORD sw;
+ rectwidth = rc.right-rc.left-g_StatusBarData.rectBorders.left-g_StatusBarData.rectBorders.right;
+ if (visProtoCount>1) sw = (rectwidth-(g_StatusBarData.extraspace*(visProtoCount-1)))/visProtoCount;
+ else sw = rectwidth;
+ mir_free(ProtoWidth);
+ ProtoWidth = (int*)mir_alloc(sizeof(int)*visProtoCount);
+ for (i=0; i < visProtoCount; i++)
+ {
+ SIZE textSize;
+ DWORD w = 0;
+ // FIXME strange error occurs here due to Dimon log
+ w = ProtosData[i].PaddingLeft;
+ w += ProtosData[i].PaddingRight;
+
+ if ( ProtosData[i].showProtoIcon )
+ {
+
+ w += GetSystemMetrics(SM_CXSMICON)+1;
+
+ ProtosData[i].extraIcon = NULL;
+ if ((ProtosData[i].xStatusMode&8) && ProtosData[i].ProtoStatus>ID_STATUS_OFFLINE)
+ {
+ char str[MAXMODULELABELLENGTH];
+ mir_snprintf(str, SIZEOF(str), "%s/GetXStatus", ProtosData[i].AccountName);
+ if (ServiceExists(str))
+ {
+ char * dbTitle = "XStatusName";
+ char * dbTitle2 = NULL;
+ xstatus = CallProtoService(ProtosData[i].AccountName,"/GetXStatus",(WPARAM)&dbTitle,(LPARAM)&dbTitle2);
+ if (dbTitle && xstatus)
+ {
+ DBVARIANT dbv = {0};
+ if ( !DBGetContactSettingTString(NULL,ProtosData[i].AccountName,dbTitle,&dbv))
+ {
+ ProtosData[i].ProtoXStatus = mir_tstrdup(dbv.ptszVal);
+ db_free(&dbv);
+ }
+ }
+ }
+ }
+ if ((ProtosData[i].xStatusMode&3))
+ {
+ if (ProtosData[i].ProtoStatus>ID_STATUS_OFFLINE)
+ {
+ char str[MAXMODULELABELLENGTH];
+ mir_snprintf(str, SIZEOF(str), "%s/GetXStatusIcon", ProtosData[i].AccountName);
+ if (ServiceExists(str))
+ ProtosData[i].extraIcon = (HICON)CallService(str,0,0);
+ if (ProtosData[i].extraIcon && (ProtosData[i].xStatusMode&3) == 3)
+ w += GetSystemMetrics(SM_CXSMICON)+1;
+
+ }
+ }
+ }
+
+ if (ProtosData[i].showProtoName)
+ {
+ GetTextExtentPoint32(hDC,ProtosData[i].ProtoHumanName,lstrlen(ProtosData[i].ProtoHumanName),&textSize);
+ w += textSize.cx + 3 + spaceWidth;
+ }
+
+ if (ProtosData[i].showProtoEmails && ProtosData[i].ProtoEMailCount )
+ {
+ GetTextExtentPoint32A(hDC,ProtosData[i].ProtoEMailCount,lstrlenA(ProtosData[i].ProtoEMailCount),&textSize);
+ w += textSize.cx+3+spaceWidth;
+ }
+
+ if (ProtosData[i].showStatusName)
+ {
+ GetTextExtentPoint32A(hDC,ProtosData[i].ProtoStatusText,lstrlenA(ProtosData[i].ProtoStatusText),&textSize);
+ w += textSize.cx + 3 + spaceWidth;
+ }
+
+ if ((ProtosData[i].xStatusMode&8) && ProtosData[i].ProtoXStatus)
+ {
+ GetTextExtentPoint32(hDC,ProtosData[i].ProtoXStatus,lstrlen(ProtosData[i].ProtoXStatus),&textSize);
+ w += textSize.cx + 3 + spaceWidth;
+ }
+
+ if (( ProtosData[i].showProtoName) ||
+ (ProtosData[i].showProtoEmails && ProtosData[i].ProtoEMailCount ) ||
+ (ProtosData[i].showStatusName) ||
+ ((ProtosData[i].xStatusMode&8) && ProtosData[i].ProtoXStatus))
+ w -= spaceWidth;
+
+ ProtosData[i].fullWidth = w;
+ if (g_StatusBarData.sameWidth)
+ {
+ ProtoWidth[i] = sw;
+ SumWidth += w;
+ }
+ else
+ {
+ ProtoWidth[i] = w;
+ SumWidth += w;
+ }
+ }
+
+ // Reposition rects
+ for (i=0; i < visProtoCount; i++)
+ if (ProtoWidth[i]>maxwidth) maxwidth = ProtoWidth[i];
+
+ if (g_StatusBarData.sameWidth)
+ {
+ for (i=0; i < visProtoCount; i++)
+ ProtoWidth[i] = maxwidth;
+ SumWidth = maxwidth*visProtoCount;
+ }
+ SumWidth += (visProtoCount-1)*(g_StatusBarData.extraspace+1);
+
+ if (SumWidth>rectwidth)
+ {
+ float f = (float)rectwidth/SumWidth;
+ //dx = (int)(0.5+(float)dx/visProtoCount);
+ //SumWidth -= dx*visProtoCount;
+ SumWidth = 0;
+ for (i=0; i < visProtoCount; i++)
+ {
+ ProtoWidth[i] = (int)((float)ProtoWidth[i]*f);
+ SumWidth += ProtoWidth[i];
+ }
+ SumWidth += (visProtoCount-1)*(g_StatusBarData.extraspace+1);
+ }
+ }
+ if (g_StatusBarData.Align == 1) //center
+ aligndx = (rectwidth-SumWidth)>>1;
+ else if (g_StatusBarData.Align == 2) //right
+ aligndx = (rectwidth-SumWidth);
+ // Draw in rects
+ //ske_SelectTextEffect(hDC,g_StatusBarData.TextEffectID,g_StatusBarData.TextEffectColor1,g_StatusBarData.TextEffectColor2);
+ {
+ RECT r = rc;
+// r.top += g_StatusBarData.rectBorders.top;
+// r.bottom -= g_StatusBarData.rectBorders.bottom;
+ r.left += g_StatusBarData.rectBorders.left+aligndx;
+ for (i=0; i < visProtoCount; i++)
+ {
+ HRGN rgn;
+ int x = r.left;
+ HICON hIcon = NULL;
+ HICON hxIcon = NULL;
+ BOOL NeedDestroy = FALSE;
+ x = r.left;
+ x += ProtosData[i].PaddingLeft;
+ r.right = r.left+ProtoWidth[i];
+
+ if ( ProtosData[i].showProtoIcon )
+ {
+ if (ProtosData[i].ProtoStatus>ID_STATUS_OFFLINE && ((ProtosData[i].xStatusMode)&3)>0)
+ {
+ char str[MAXMODULELABELLENGTH];
+ mir_snprintf(str, SIZEOF(str), "%s/GetXStatusIcon", ProtosData[i].AccountName);
+ if (ServiceExists(str))
+ {
+ hxIcon = ProtosData[i].extraIcon;
+ if (hxIcon)
+ {
+ if (((ProtosData[i].xStatusMode)&3) == 2)
+ {
+ hIcon = GetMainStatusOverlay(ProtosData[i].ProtoStatus);
+ NeedDestroy = TRUE;
+ }
+ else if (((ProtosData[i].xStatusMode)&3) == 1)
+ {
+ hIcon = hxIcon;
+ NeedDestroy = TRUE;
+ hxIcon = NULL;
+ }
+
+ }
+ }
+ }
+ if (hIcon == NULL && (hxIcon == NULL || (((ProtosData[i].xStatusMode)&3) == 3)))
+ {
+ if (hIcon == NULL && (ProtosData[i].connectingIcon == 1) && ProtosData[i].ProtoStatus >= ID_STATUS_CONNECTING && ProtosData[i].ProtoStatus <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES)
+ {
+ hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)ProtosData[i].AccountName,0);
+ if (hIcon) NeedDestroy = TRUE;
+ else hIcon = LoadSkinnedProtoIcon(ProtosData[i].AccountName,ProtosData[i].ProtoStatus);
+ }
+ else hIcon = LoadSkinnedProtoIcon(ProtosData[i].AccountName,ProtosData[i].ProtoStatus);
+ }
+
+
+ rgn = CreateRectRgn(r.left,r.top,r.right,r.bottom);
+ //
+ {
+ if (g_StatusBarData.sameWidth)
+ {
+ int fw = ProtosData[i].fullWidth;
+ int rw = r.right-r.left;
+ if (g_StatusBarData.Align == 1)
+ {
+ x = r.left+((rw-fw)/2);
+ }
+ else if (g_StatusBarData.Align == 2)
+ {
+ x = r.left+((rw-fw));
+ }
+ else x = r.left;
+ }
+ }
+
+
+ SelectClipRgn(hDC,rgn);
+ ProtosData[i].DoubleIcons = FALSE;
+
+ DWORD dim = ProtosData[i].isDimmed ? (( 64 << 24 ) | 0x80 ) : 0;
+
+ if ((ProtosData[i].xStatusMode&3) == 3)
+ {
+ if (hIcon) mod_DrawIconEx_helper(hDC,x,iconY,hIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL, DI_NORMAL|dim );
+ if (hxIcon)
+ {
+ mod_DrawIconEx_helper(hDC,x+GetSystemMetrics(SM_CXSMICON)+1,iconY,hxIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL|dim);
+ x += GetSystemMetrics(SM_CXSMICON)+1;
+ }
+ ProtosData[i].DoubleIcons = hIcon && hxIcon;
+ }
+ else
+ {
+ if (hxIcon) mod_DrawIconEx_helper(hDC,x,iconY,hxIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL|dim);
+ if (hIcon) mod_DrawIconEx_helper(hDC,x,iconY,hIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL| ((hxIcon && (ProtosData[i].xStatusMode&4))?(192 << 24):0 ) | dim );
+ }
+
+ if (( hxIcon || hIcon) && TRUE /* TODO g_StatusBarData.bDrawLockOverlay options to draw locked proto*/ )
+ {
+ if ( db_get_b( NULL,ProtosData[i].AccountName,"LockMainStatus",0 ))
+ {
+ HICON hLockOverlay = LoadSkinnedIcon(SKINICON_OTHER_STATUS_LOCKED);
+ if (hLockOverlay != NULL)
+ {
+ mod_DrawIconEx_helper(hDC, x, iconY, hLockOverlay, GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL | dim);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hLockOverlay, 0); }
+ }
+ }
+ if (hxIcon) DestroyIcon_protect(hxIcon);
+ if (NeedDestroy) DestroyIcon_protect(hIcon);
+ else CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ x += GetSystemMetrics(SM_CXSMICON)+1;
+ }
+ if (ProtosData[i].showProtoName)
+ {
+ SIZE textSize;
+ RECT rt = r;
+ rt.left = x+(spaceWidth>>1);
+ rt.top = textY;
+ ske_DrawText(hDC,ProtosData[i].ProtoHumanName,lstrlen(ProtosData[i].ProtoHumanName),&rt,0);
+
+ if ((ProtosData[i].showProtoEmails && ProtosData[i].ProtoEMailCount != NULL) || ProtosData[i].showStatusName || ((ProtosData[i].xStatusMode&8) && ProtosData[i].ProtoXStatus))
+ {
+ GetTextExtentPoint32(hDC, ProtosData[i].ProtoHumanName, lstrlen(ProtosData[i].ProtoHumanName), &textSize);
+ x += textSize.cx + 3;
+ }
+ }
+
+ if (ProtosData[i].showProtoEmails && ProtosData[i].ProtoEMailCount != NULL)
+ {
+ SIZE textSize;
+ RECT rt = r;
+ rt.left = x+(spaceWidth>>1);
+ rt.top = textY;
+ ske_DrawTextA(hDC,ProtosData[i].ProtoEMailCount,lstrlenA(ProtosData[i].ProtoEMailCount),&rt,0);
+ //TextOutS(hDC,x,textY,ProtosData[i].ProtoName,lstrlenA(ProtosData[i].ProtoName));
+ if (ProtosData[i].showStatusName || ((ProtosData[i].xStatusMode&8) && ProtosData[i].ProtoXStatus))
+ {
+ GetTextExtentPoint32A(hDC,ProtosData[i].ProtoEMailCount,lstrlenA(ProtosData[i].ProtoEMailCount),&textSize);
+ x += textSize.cx+3;
+ }
+ }
+
+ if (ProtosData[i].showStatusName)
+ {
+ SIZE textSize;
+ RECT rt = r;
+ rt.left = x+(spaceWidth>>1);
+ rt.top = textY;
+ ske_DrawTextA(hDC, ProtosData[i].ProtoStatusText, lstrlenA(ProtosData[i].ProtoStatusText),&rt,0);
+ if (((ProtosData[i].xStatusMode&8) && ProtosData[i].ProtoXStatus))
+ {
+ GetTextExtentPoint32A(hDC,ProtosData[i].ProtoStatusText,lstrlenA(ProtosData[i].ProtoStatusText),&textSize);
+ x += textSize.cx+3;
+ }
+ //TextOutS(hDC,x,textY,ProtosData[i].ProtoStatusText,lstrlenA(ProtosData[i].ProtoStatusText));
+ }
+
+ if ((ProtosData[i].xStatusMode&8) && ProtosData[i].ProtoXStatus)
+ {
+ RECT rt = r;
+ rt.left = x+(spaceWidth>>1);
+ rt.top = textY;
+ ske_DrawText(hDC,ProtosData[i].ProtoXStatus,lstrlen(ProtosData[i].ProtoXStatus),&rt,0);
+ //TextOutS(hDC,x,textY,ProtosData[i].ProtoStatusText,lstrlenA(ProtosData[i].ProtoStatusText));
+ }
+
+ ProtosData[i].protoRect = r;
+
+ r.left = r.right+g_StatusBarData.extraspace;
+ //SelectClipRgn(hDC,NULL);
+ DeleteObject(rgn);
+
+ }
+ }
+
+ mir_free_and_nil(ProtoWidth);
+ } //code for each line
+ ProtosData = orig_ProtosData;
+ }
+ }
+ }
+
+ SelectObject(hDC,hOldFont);
+ ske_ResetTextEffect(hDC);
+ return 0;
+}
+
+static BOOL _ModernStatus_OnExtraIconClick( int protoIndex )
+{
+ /** FIXME
+ Create Protocol services and
+ move This portion of code to related Protocols
+ */
+
+ if ( !mir_strcmpi( ProtosData[protoIndex].ProtoName, "ICQ" ))
+ {
+ if ( ProtosData[protoIndex].ProtoStatus < ID_STATUS_ONLINE ) return FALSE;
+
+ HMENU hMainStatusMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ if ( !hMainStatusMenu ) return FALSE;
+
+ HMENU hProtoStatusMenu = GetSubMenu( hMainStatusMenu, protoIndex );
+ if ( !hProtoStatusMenu ) return FALSE;
+
+ int extraStatusMenuIndex = 1;
+ HMENU hExtraStatusMenu = GetSubMenu( hProtoStatusMenu, extraStatusMenuIndex );
+ if ( !hExtraStatusMenu ) return FALSE;
+
+ POINT pt; GetCursorPos( &pt );
+ {
+ HWND hWnd = (HWND) CallService( MS_CLUI_GETHWND, 0 ,0 );
+ TrackPopupMenu( hExtraStatusMenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hWnd, NULL );
+ }
+ return TRUE;
+ }
+ else if ( !mir_strcmpi( ProtosData[protoIndex].ProtoName, "JABBER" ))
+ {
+ if ( ProtosData[protoIndex].ProtoStatus < ID_STATUS_ONLINE ) return FALSE;
+ // Show Moods
+ char szService[128];
+ mir_snprintf(szService, SIZEOF(szService), "%s/AdvStatusSet/Mood", ProtosData[protoIndex].AccountName );
+ if ( ServiceExists( szService ))
+ {
+ CallService( szService, 0 ,0 );
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+#define TOOLTIP_TOLERANCE 5
+LRESULT CALLBACK ModernStatusProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ static POINT ptToolTipShow = {0};
+ switch (msg)
+ {
+ case WM_CREATE:
+ g_StatusBarData.hTheme = xpt_AddThemeHandle(hwnd,L"STATUS");
+ break;
+ case WM_DESTROY:
+ xpt_FreeThemeForWindow(hwnd);
+ if (allocedItemData && ProtosData) {
+ for (int k = 0; k < allocedItemData; k++) {
+ mir_free(ProtosData[k].AccountName);
+ mir_free(ProtosData[k].ProtoName);
+ mir_free(ProtosData[k].ProtoEMailCount);
+ mir_free(ProtosData[k].ProtoHumanName);
+ mir_free(ProtosData[k].ProtoStatusText);
+ mir_free(ProtosData[k].ProtoEMailCount);
+ mir_free(ProtosData[k].ProtoXStatus);
+ }
+ mir_free_and_nil(ProtosData);
+ allocedItemData = 0;
+ }
+ break;
+ case WM_SIZE:
+ if ( !g_CluiData.fLayered || GetParent(hwnd) != pcli->hwndContactList)
+ InvalidateRect(hwnd,NULL,FALSE);
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ case WM_ERASEBKGND:
+ return 1;
+ case WM_PAINT:
+ if (GetParent(hwnd) == pcli->hwndContactList && g_CluiData.fLayered)
+ CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,(WPARAM)hwnd,0);
+ else if (GetParent(hwnd) == pcli->hwndContactList && !g_CluiData.fLayered)
+ {
+ HDC hdc, hdc2;
+ HBITMAP hbmp,hbmpo;
+ RECT rc = {0};
+ GetClientRect(hwnd,&rc);
+ rc.right++;
+ rc.bottom++;
+ hdc = GetDC(hwnd);
+ hdc2 = CreateCompatibleDC(hdc);
+ hbmp = ske_CreateDIB32(rc.right,rc.bottom);
+ hbmpo = (HBITMAP)SelectObject(hdc2,hbmp);
+ SetBkMode(hdc2,TRANSPARENT);
+ ske_BltBackImage(hwnd,hdc2,&rc);
+ ModernDrawStatusBarWorker(hwnd,hdc2);
+ BitBlt(hdc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,
+ hdc2,rc.left,rc.top,SRCCOPY);
+ SelectObject(hdc2,hbmpo);
+ DeleteObject(hbmp);
+ mod_DeleteDC(hdc2);
+
+ SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
+ ReleaseDC(hwnd,hdc);
+ ValidateRect(hwnd,NULL);
+ }
+ else
+ {
+ HDC hdc, hdc2;
+ HBITMAP hbmp, hbmpo;
+ RECT rc;
+ PAINTSTRUCT ps;
+ HBRUSH br = GetSysColorBrush(COLOR_3DFACE);
+ GetClientRect(hwnd,&rc);
+ hdc = BeginPaint(hwnd,&ps);
+ hdc2 = CreateCompatibleDC(hdc);
+ hbmp = ske_CreateDIB32(rc.right,rc.bottom);
+ hbmpo = (HBITMAP) SelectObject(hdc2,hbmp);
+ FillRect(hdc2,&ps.rcPaint,br);
+ ModernDrawStatusBarWorker(hwnd,hdc2);
+ //BitBlt(hdc,ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right-ps.rcPaint.left,ps.rcPaint.bottom-ps.rcPaint.top,
+ // hdc2,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY);
+ BitBlt(hdc,ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right-ps.rcPaint.left,ps.rcPaint.bottom-ps.rcPaint.top,
+ hdc2,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY);
+ SelectObject(hdc2,hbmpo);
+ DeleteObject(hbmp);
+ mod_DeleteDC(hdc2);
+ ps.fErase = FALSE;
+ EndPaint(hwnd,&ps);
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ case WM_GETMINMAXINFO:{
+ RECT rct;
+ GetWindowRect(hwnd,&rct);
+ memset((LPMINMAXINFO)lParam,0,sizeof(MINMAXINFO));
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = 16;
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = 16;
+ ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = 1600;
+ ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = 1600;
+ return(0);
+ }
+
+ case WM_SHOWWINDOW:
+ {
+ int res;
+ int ID;
+ if (tooltipshoing){
+ NotifyEventHooks(g_CluiData.hEventStatusBarHideToolTip,0,0);
+ tooltipshoing = FALSE;
+ };
+ ID=Sync( FindFrameID, hwnd );
+ if (ID)
+ {
+ res = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS,ID),0);
+ if (res >= 0) db_set_b(0,"CLUI","ShowSBar",(BYTE)(wParam/*(res&F_VISIBLE)*/?1:0));
+ }
+ }
+ break;
+ case WM_TIMER:
+ {
+ if (wParam == TM_STATUSBARHIDE)
+ {
+ KillTimer(hwnd,TM_STATUSBARHIDE);
+ if (tooltipshoing)
+ {
+ NotifyEventHooks(g_CluiData.hEventStatusBarHideToolTip,0,0);
+ tooltipshoing = FALSE;
+ ReleaseCapture();
+ };
+ }
+ else if (wParam == TM_STATUSBAR)
+ {
+ POINT pt;
+ KillTimer(hwnd,TM_STATUSBAR);
+ GetCursorPos(&pt);
+ if (pt.x == lastpnt.x && pt.y == lastpnt.y)
+ {
+ int i;
+ RECT rc;
+ ScreenToClient(hwnd,&pt);
+ for (i=0; i < allocedItemData; i++)
+ {
+ rc = ProtosData[i].protoRect;
+ if (PtInRect(&rc,pt))
+ {
+ NotifyEventHooks(g_CluiData.hEventStatusBarShowToolTip,(WPARAM)ProtosData[i].AccountName,0);
+ CLUI_SafeSetTimer(hwnd,TM_STATUSBARHIDE,db_get_w(NULL,"CLUIFrames","HideToolTipTime",SETTING_HIDETOOLTIPTIME_DEFAULT),0);
+ tooltipshoing = TRUE;
+ ClientToScreen(hwnd,&pt);
+ ptToolTipShow = pt;
+ SetCapture(hwnd);
+ return 0;
+ }
+ }
+ return 0;
+ }
+ }
+ return 0;
+ }
+ case WM_MOUSEMOVE:
+ if (tooltipshoing)
+ {
+ POINT pt;
+ GetCursorPos(&pt);
+ if (abs(pt.x-ptToolTipShow.x)>TOOLTIP_TOLERANCE || abs(pt.y-ptToolTipShow.y)>TOOLTIP_TOLERANCE)
+ {
+ KillTimer(hwnd,TM_STATUSBARHIDE);
+ NotifyEventHooks(g_CluiData.hEventStatusBarHideToolTip,0,0);
+ tooltipshoing = FALSE;
+ ReleaseCapture();
+ }
+ }
+ break;
+ case WM_SETCURSOR:
+ {
+ if (g_CluiData.bBehindEdgeSettings) CLUI_UpdateTimer(0);
+ {
+ POINT pt;
+ GetCursorPos(&pt);
+ SendMessage(GetParent(hwnd),msg,wParam,lParam);
+ if (pt.x == lastpnt.x && pt.y == lastpnt.y)
+ {
+ return(CLUI_TestCursorOnBorders());
+ };
+ lastpnt = pt;
+ if (tooltipshoing)
+ if (abs(pt.x-ptToolTipShow.x)>TOOLTIP_TOLERANCE || abs(pt.y-ptToolTipShow.y)>TOOLTIP_TOLERANCE)
+ {
+ KillTimer(hwnd,TM_STATUSBARHIDE);
+ NotifyEventHooks(g_CluiData.hEventStatusBarHideToolTip,0,0);
+ tooltipshoing = FALSE;
+ ReleaseCapture();
+ };
+ KillTimer(hwnd,TM_STATUSBAR);
+ CLUI_SafeSetTimer(hwnd,TM_STATUSBAR,db_get_w(NULL,"CLC","InfoTipHoverTime",CLCDEFAULT_INFOTIPTIME),0);
+
+ return(CLUI_TestCursorOnBorders());
+ }
+ }
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ {
+ RECT rc;
+ POINT pt;
+ int i;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ KillTimer(hwnd,TM_STATUSBARHIDE);
+ KillTimer(hwnd,TM_STATUSBAR);
+
+ if (tooltipshoing){
+ NotifyEventHooks(g_CluiData.hEventStatusBarHideToolTip,0,0);
+ };
+ tooltipshoing = FALSE;
+ for (i=0; i < allocedItemData; i++)
+ {
+ RECT rc1;
+ BOOL isOnExtra = FALSE;
+
+ rc = ProtosData[i].protoRect;
+ rc1 = rc;
+ rc1.left = rc.left+16;
+ rc1.right = rc1.left+16;
+ if (PtInRect(&rc,pt) && PtInRect(&rc1,pt) && ProtosData[i].DoubleIcons)
+ isOnExtra = TRUE;
+ if (PtInRect(&rc,pt))
+ {
+ HMENU hMenu = NULL;
+
+ BOOL bShift = ( GetKeyState( VK_SHIFT )&0x8000 );
+ BOOL bCtrl = ( GetKeyState( VK_CONTROL )&0x8000 );
+
+ if (( msg == WM_MBUTTONDOWN || ( msg == WM_RBUTTONDOWN && bCtrl ) || isOnExtra) && _ModernStatus_OnExtraIconClick( i ))
+ {
+ return TRUE;
+ }
+ if ( msg == WM_LBUTTONDOWN && bCtrl )
+ {
+ if ( g_CluiData.bFilterEffective != CLVM_FILTER_PROTOS || !bShift )
+ {
+ ApplyViewMode( "" );
+ mir_snprintf( g_CluiData.protoFilter, SIZEOF(g_CluiData.protoFilter), "%s|", ProtosData[i].AccountName );
+ g_CluiData.bFilterEffective = CLVM_FILTER_PROTOS;
+ }
+ else
+ {
+ char protoF[ sizeof(g_CluiData.protoFilter) ];
+ mir_snprintf( protoF, SIZEOF(protoF), "%s|", ProtosData[i].AccountName );
+ char * pos = strstri( g_CluiData.protoFilter, ProtosData[i].AccountName );
+ if ( pos )
+ {
+ // remove filter
+ int len = strlen( protoF );
+ memmove( pos, pos + len, strlen( pos + len ) + 1 );
+
+ if ( strlen( g_CluiData.protoFilter ) == 0 )
+ ApplyViewMode( "" );
+ else
+ g_CluiData.bFilterEffective = CLVM_FILTER_PROTOS;
+ }
+ else
+ {
+ //add filter
+ mir_snprintf( g_CluiData.protoFilter, SIZEOF(g_CluiData.protoFilter), "%s%s", g_CluiData.protoFilter, protoF );
+ g_CluiData.bFilterEffective = CLVM_FILTER_PROTOS;
+ }
+ }
+ if ( g_CluiData.bFilterEffective == CLVM_FILTER_PROTOS)
+ {
+ char filterName[ sizeof(g_CluiData.protoFilter) ] = { 0 };
+ filterName[0] = (char)13;
+
+ int protoCount;
+ PROTOACCOUNT ** accs;
+ ProtoEnumAccounts( &protoCount, &accs );
+
+ bool first = true;
+ for ( int pos = 0; pos < protoCount; pos++ )
+ {
+ int i = pcli->pfnGetAccountIndexByPos( pos );
+
+ if ( i < 0 && i >= protoCount )
+ continue;
+
+ char protoF[ sizeof(g_CluiData.protoFilter) ];
+ mir_snprintf( protoF, SIZEOF(protoF), "%s|", accs[i]->szModuleName );
+ if ( strstri( g_CluiData.protoFilter, protoF ))
+ {
+ char * temp = mir_utf8encodeT( accs[i]->tszAccountName );
+ if ( !first )
+ strncat( filterName, "; ", SIZEOF(filterName) - strlen(filterName));
+ strncat( filterName, temp, SIZEOF(filterName) - strlen(filterName));
+ first = false;
+ mir_free( temp );
+ }
+ }
+
+ SaveViewMode( filterName, _T(""), g_CluiData.protoFilter, 0, -1, 0, 0, 0, 0 );
+
+ ApplyViewMode( filterName );
+ }
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ CLUI__cliInvalidateRect( hwnd, NULL, FALSE );
+ SetCapture( NULL );
+ return 0;
+ }
+ if ( !hMenu)
+ {
+ if (msg == WM_RBUTTONDOWN)
+ {
+ BOOL a = ((g_StatusBarData.perProtoConfig && ProtosData[i].SBarRightClk) || g_StatusBarData.SBarRightClk );
+ if ( a ^ bShift )
+ hMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0);
+ else
+ hMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ }
+ else
+ {
+ hMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ unsigned int cpnl = 0;
+ int mcnt = GetMenuItemCount(hMenu);
+ for (int j = 0; j < mcnt; ++j) {
+ HMENU hMenus = GetSubMenu(hMenu, j);
+ if (hMenus && cpnl++ == i) {
+ hMenu = hMenus;
+ break;
+ }
+ }
+ }
+ }
+ ClientToScreen(hwnd,&pt);
+ {
+ HWND parent = GetParent(hwnd);
+ if (parent != pcli->hwndContactList) parent = GetParent(parent);
+ TrackPopupMenu(hMenu,TPM_TOPALIGN|TPM_LEFTALIGN|TPM_LEFTBUTTON,pt.x,pt.y,0,parent,NULL);
+ }
+ return 0;
+ }
+ }
+ GetClientRect( hwnd, &rc );
+ if ( PtInRect( &rc, pt ) && msg == WM_LBUTTONDOWN && g_CluiData.bFilterEffective == CLVM_FILTER_PROTOS )
+ {
+ ApplyViewMode( "" );
+ CLUI__cliInvalidateRect( hwnd, NULL, FALSE );
+ SetCapture( NULL );
+ return 0;
+ }
+ return SendMessage(GetParent(hwnd), msg, wParam, lParam );
+ }
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+HWND StatusBar_Create(HWND parent)
+{
+ WNDCLASS wndclass = {0};
+ TCHAR pluginname[] = _T("ModernStatusBar");
+ int h = GetSystemMetrics(SM_CYSMICON)+2;
+ if (GetClassInfo(g_hInst,pluginname,&wndclass) == 0)
+ {
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = ModernStatusProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = pluginname;
+ RegisterClass(&wndclass);
+ }
+ hModernStatusBar = CreateWindow(pluginname,pluginname,WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN,
+ 0,0,0,h,parent,NULL,g_hInst,NULL);
+ // register frame
+ {
+ CLISTFrame Frame;
+ memset(&Frame,0,sizeof(Frame));
+ Frame.cbSize = sizeof(CLISTFrame);
+ Frame.hWnd = hModernStatusBar;
+ Frame.align = alBottom;
+ Frame.hIcon = LoadSkinnedIcon (SKINICON_OTHER_MIRANDA);
+ Frame.Flags = (db_get_b(NULL,"CLUI","ShowSBar",SETTING_SHOWSBAR_DEFAULT)?F_VISIBLE:0)|F_LOCKED|F_NOBORDER|F_NO_SUBCONTAINER|F_TCHAR;
+ Frame.height = h;
+ Frame.tname = _T("Status Bar");
+ Frame.TBtname = TranslateT("Status Bar");
+ hFramehModernStatusBar = (HANDLE)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&Frame,(LPARAM)0);
+ CallService(MS_SKINENG_REGISTERPAINTSUB,(WPARAM)Frame.hWnd,(LPARAM)NewStatusPaintCallbackProc); //$$$$$ register sub for frame
+ }
+
+ LoadStatusBarData();
+ CLUIServices_ProtocolStatusChanged(0,0);
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME,-1,0);
+ return hModernStatusBar;
+}
diff --git a/plugins/Clist_modern/src/modern_statusbar_options.cpp b/plugins/Clist_modern/src/modern_statusbar_options.cpp
new file mode 100644
index 0000000000..7b9ac4b895
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_statusbar_options.cpp
@@ -0,0 +1,541 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_defsettings.h"
+//#include "hdr/modern_effectenum.h"
+
+typedef struct _StatusBarProtocolOptions
+{
+ char *szName;
+ BOOL AccountIsCustomized;
+ BOOL HideAccount;
+ BYTE SBarShow;
+ BYTE SBarRightClk;
+ BYTE UseConnectingIcon;
+ BYTE ShowUnreadEmails;
+ BYTE ShowXStatus;
+ int PaddingLeft;
+ int PaddingRight;
+}
+ StatusBarProtocolOptions;
+
+static StatusBarProtocolOptions _GlobalOptions = {0};
+
+static void UpdateXStatusIconOptions(HWND hwndDlg, BOOL perProto, StatusBarProtocolOptions* dat, int curSelProto)
+{
+ int en = IsDlgButtonChecked(hwndDlg,IDC_SHOWSBAR) && IsDlgButtonChecked(hwndDlg,IDC_SHOWICON );
+
+ if (IsDlgButtonChecked(hwndDlg,IDC_SHOWBOTH)) CheckDlgButton(hwndDlg,IDC_SHOWNORMAL,FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWBOTH),en && IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && !IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL));
+
+ if (IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL)) CheckDlgButton(hwndDlg,IDC_SHOWBOTH,FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWNORMAL),en && IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && !IsDlgButtonChecked(hwndDlg,IDC_SHOWBOTH));
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSPARENTOVERLAY),en && IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL) && !IsDlgButtonChecked(hwndDlg,IDC_SHOWBOTH));
+
+ BYTE val = 0;
+ if (IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS)) {
+ if (IsDlgButtonChecked(hwndDlg,IDC_SHOWBOTH)) val = 3;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL)) val = 2;
+ else val = 1;
+ val += IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENTOVERLAY)?4:0;
+ }
+ val += IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUSNAME)?8:0;
+ if (perProto)
+ dat[curSelProto].ShowXStatus = val;
+ else
+ _GlobalOptions.ShowXStatus = val;
+}
+
+static void UpdateStatusBarOptionsDisplay(HWND hwndDlg)
+{
+ StatusBarProtocolOptions *dat = (StatusBarProtocolOptions*)GetWindowLongPtr(GetDlgItem(hwndDlg,IDC_STATUSBAR_PROTO_LIST),GWLP_USERDATA);
+ BOOL perProto = (BOOL)IsDlgButtonChecked(hwndDlg,IDC_STATUSBAR_PER_PROTO);
+ HWND hwndComboBox = GetDlgItem( hwndDlg, IDC_STATUSBAR_PROTO_LIST );
+ StatusBarProtocolOptions sbpo;
+ int curSelProto = SendMessage(hwndComboBox, CB_GETITEMDATA, SendMessage(hwndComboBox, CB_GETCURSEL, 0, 0), NULL) - 1; //first entry is the combo box is a constant.
+ if (curSelProto < 0)
+ perProto = FALSE;
+
+ if (perProto)
+ sbpo = dat[curSelProto];
+ else
+ sbpo = _GlobalOptions;
+
+ if (perProto) {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SBAR_USE_ACCOUNT_SETTINGS), TRUE);
+ CheckDlgButton(hwndDlg, IDC_SBAR_USE_ACCOUNT_SETTINGS, sbpo.AccountIsCustomized ? BST_CHECKED : BST_UNCHECKED);
+ }
+ else EnableWindow(GetDlgItem(hwndDlg, IDC_SBAR_USE_ACCOUNT_SETTINGS), FALSE);
+
+ CheckDlgButton(hwndDlg, IDC_SBAR_HIDE_ACCOUNT_COMPLETELY, sbpo.HideAccount ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_USECONNECTINGICON, sbpo.UseConnectingIcon ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWXSTATUSNAME, ((sbpo.ShowXStatus&8)>0) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWXSTATUS, ((sbpo.ShowXStatus&3)>0) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWNORMAL, ((sbpo.ShowXStatus&3) == 2) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWBOTH, ((sbpo.ShowXStatus&3) == 3) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWUNREADEMAIL, (sbpo.ShowUnreadEmails == 1) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_TRANSPARENTOVERLAY, ((sbpo.ShowXStatus&4)) ? BST_CHECKED : BST_UNCHECKED);
+ {
+ BYTE showOpts = sbpo.SBarShow;
+ 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, sbpo.SBarRightClk ? BST_UNCHECKED : BST_CHECKED);
+ CheckDlgButton(hwndDlg, IDC_RIGHTMIRANDA, !IsDlgButtonChecked(hwndDlg,IDC_RIGHTSTATUS) ? BST_CHECKED : BST_UNCHECKED);
+
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_LEFT,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_LEFT,UDM_SETPOS,0,MAKELONG(sbpo.PaddingLeft,2));
+
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_RIGHT,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_RIGHT,UDM_SETPOS,0,MAKELONG(sbpo.PaddingRight,2));
+
+ if ( !sbpo.AccountIsCustomized)
+ UpdateXStatusIconOptions(hwndDlg, perProto, dat, curSelProto);
+
+ {
+ BOOL enableIcons = IsDlgButtonChecked(hwndDlg,IDC_SHOWICON );
+ BOOL enableOptions = !perProto || sbpo.AccountIsCustomized;
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SBAR_HIDE_ACCOUNT_COMPLETELY), enableOptions && perProto);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_USECONNECTINGICON), enableOptions && enableIcons);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWXSTATUSNAME), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWXSTATUS), enableOptions && enableIcons);
+
+ if ( !enableOptions) {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWNORMAL), enableOptions && enableIcons);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWBOTH), enableOptions && enableIcons );
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TRANSPARENTOVERLAY), enableOptions && enableIcons);
+ }
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWUNREADEMAIL), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWICON), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWPROTO), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSTATUS), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHTSTATUS), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHTMIRANDA), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_OFFSETICON_LEFT), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_OFFSETSPIN_LEFT), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_OFFSETICON_RIGHT), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_OFFSETSPIN_RIGHT), enableOptions);
+ }
+
+ if ( !perProto || sbpo.AccountIsCustomized)
+ UpdateXStatusIconOptions(hwndDlg, perProto, dat, curSelProto);
+}
+
+INT_PTR CALLBACK DlgProcSBarOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ StatusBarProtocolOptions *dat = (StatusBarProtocolOptions*)GetWindowLongPtr(GetDlgItem(hwndDlg,IDC_STATUSBAR_PROTO_LIST),GWLP_USERDATA);
+ LOGFONTA lf;
+ BOOL perProto = IsDlgButtonChecked(hwndDlg, IDC_STATUSBAR_PER_PROTO);
+ HWND hwndComboBox = GetDlgItem( hwndDlg, IDC_STATUSBAR_PROTO_LIST );
+ int curSelProto = SendMessage(hwndComboBox, CB_GETITEMDATA, SendMessage(hwndComboBox, CB_GETCURSEL, 0, 0), NULL) - 1; //first entry is the combo box is a constant.
+ if (curSelProto < 0)
+ perProto = FALSE;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ perProto = (BOOL)db_get_b(NULL,"CLUI","SBarPerProto",SETTING_SBARPERPROTO_DEFAULT);
+
+ TranslateDialogDefault(hwndDlg);
+
+ CheckDlgButton(hwndDlg, IDC_SHOWSBAR, db_get_b(NULL,"CLUI","ShowSBar",SETTING_SHOWSBAR_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_STATUSBAR_PER_PROTO, perProto ? BST_CHECKED : BST_UNCHECKED);
+ {
+ // populate per-proto list box.
+ char *szName;
+ char buf[256];
+ int count;
+
+ SendMessage(hwndComboBox, CB_RESETCONTENT, 0, 0);
+
+ PROTOACCOUNT **accs;
+ ProtoEnumAccounts( &count, &accs );
+
+ dat = (StatusBarProtocolOptions*)mir_alloc(sizeof(StatusBarProtocolOptions)*count);
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_STATUSBAR_PROTO_LIST),GWLP_USERDATA,(LONG_PTR)dat);
+
+ SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM)TranslateT( " << Global>>" ));
+ SendMessage(hwndComboBox, CB_SETITEMDATA, 0, (LPARAM)0);
+
+ for (int i=0; i < count; i++ ) {
+ szName = accs[i]->szModuleName;
+ dat[i].szName = szName;
+
+ DWORD dwNewId = SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM)accs[i]->tszAccountName);
+ SendMessage(hwndComboBox, CB_SETITEMDATA, dwNewId, (LPARAM)(i+1));
+
+ mir_snprintf(buf, SIZEOF(buf), "SBarAccountIsCustom_%s", szName);
+ dat[i].AccountIsCustomized = db_get_b(NULL,"CLUI", buf, SETTING_SBARACCOUNTISCUSTOM_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "HideAccount_%s", szName);
+ dat[i].HideAccount = db_get_b(NULL,"CLUI", buf, SETTING_SBARHIDEACCOUNT_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "SBarShow_%s", szName);
+ dat[i].SBarShow = db_get_b(NULL,"CLUI", buf, SETTING_SBARSHOW_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "SBarRightClk_%s", szName);
+ dat[i].SBarRightClk = db_get_b(NULL,"CLUI", buf, SETTING_SBARRIGHTCLK_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "ShowUnreadEmails_%s", szName);
+ dat[i].ShowUnreadEmails = db_get_b(NULL,"CLUI", buf, SETTING_SHOWUNREADEMAILS_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "ShowXStatus_%s", szName);
+ dat[i].ShowXStatus = db_get_b(NULL,"CLUI", buf, SETTING_SHOWXSTATUS_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "UseConnectingIcon_%s", szName);
+ dat[i].UseConnectingIcon = db_get_b(NULL,"CLUI", buf, SETTING_USECONNECTINGICON_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "PaddingLeft_%s", szName);
+ dat[i].PaddingLeft = db_get_dw(NULL,"CLUI", buf, SETTING_PADDINGLEFT_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "PaddingRight_%s", szName);
+ dat[i].PaddingRight = db_get_dw(NULL,"CLUI", buf, SETTING_PADDINGRIGHT_DEFAULT);
+ }
+
+ if (count)
+ SendMessage(hwndComboBox, CB_SETCURSEL, 0, 0);
+ }
+
+ _GlobalOptions.AccountIsCustomized = TRUE;
+ _GlobalOptions.SBarRightClk = db_get_b(NULL,"CLUI", "SBarRightClk", SETTING_SBARRIGHTCLK_DEFAULT);
+ _GlobalOptions.ShowUnreadEmails = db_get_b(NULL,"CLUI", "ShowUnreadEmails", SETTING_SHOWUNREADEMAILS_DEFAULT);
+ _GlobalOptions.ShowXStatus = db_get_b(NULL,"CLUI", "ShowXStatus", SETTING_SHOWXSTATUS_DEFAULT);
+ _GlobalOptions.UseConnectingIcon = db_get_b(NULL,"CLUI", "UseConnectingIcon", SETTING_USECONNECTINGICON_DEFAULT);
+ _GlobalOptions.SBarShow = db_get_b(NULL,"CLUI","SBarShow",SETTING_SBARSHOW_DEFAULT);
+
+ CheckDlgButton(hwndDlg, IDC_EQUALSECTIONS, db_get_b(NULL,"CLUI","EqualSections",SETTING_EQUALSECTIONS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+
+ SendDlgItemMessage(hwndDlg,IDC_MULTI_SPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_MULTI_SPIN,UDM_SETPOS,0,MAKELONG(db_get_b(NULL,"CLUI","StatusBarProtosPerLine",SETTING_PROTOSPERLINE_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN,UDM_SETPOS,0,MAKELONG(db_get_dw(NULL,"CLUI","LeftOffset",SETTING_LEFTOFFSET_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN2,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN2,UDM_SETPOS,0,MAKELONG(db_get_dw(NULL,"CLUI","RightOffset",SETTING_RIGHTOFFSET_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_SBAR_BORDER_TOP_SPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_SBAR_BORDER_TOP_SPIN,UDM_SETPOS,0,MAKELONG(db_get_dw(NULL,"CLUI","TopOffset",SETTING_TOPOFFSET_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_SBAR_BORDER_BOTTOM_SPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_SBAR_BORDER_BOTTOM_SPIN,UDM_SETPOS,0,MAKELONG(db_get_dw(NULL,"CLUI","BottomOffset",SETTING_BOTTOMOFFSET_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN3,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN3,UDM_SETPOS,0,MAKELONG(db_get_dw(NULL,"CLUI","SpaceBetween",SETTING_SPACEBETWEEN_DEFAULT),2));
+
+ {
+ int i, item;
+ TCHAR *align[] = {_T("Left"), _T("Center"), _T("Right")};
+ for (i=0; i < SIZEOF(align); i++) {
+ item = SendDlgItemMessage(hwndDlg,IDC_SBAR_HORIZ_ALIGN,CB_ADDSTRING,0,(LPARAM)TranslateTS(align[i]));
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_SBAR_HORIZ_ALIGN, CB_SETCURSEL, db_get_b(NULL, "CLUI", "Align", SETTING_ALIGN_DEFAULT), 0);
+ }
+
+ {
+ int i, item;
+ TCHAR *align[] = {_T("Top"), _T("Center"), _T("Bottom")};
+ for (i=0; i < SIZEOF(align); i++) {
+ item = SendDlgItemMessage(hwndDlg,IDC_SBAR_VERT_ALIGN,CB_ADDSTRING,0,(LPARAM)TranslateTS(align[i]));
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_SBAR_VERT_ALIGN, CB_SETCURSEL, db_get_b(NULL, "CLUI", "VAlign", SETTING_VALIGN_DEFAULT), 0);
+ }
+
+ {
+ int en = IsDlgButtonChecked(hwndDlg,IDC_SHOWSBAR);
+ int en_icons = IsDlgButtonChecked(hwndDlg,IDC_SHOWICON );
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWICON),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWPROTO),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWSTATUS),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_RIGHTSTATUS),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_RIGHTMIRANDA),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_EQUALSECTIONS),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USECONNECTINGICON),en && en_icons);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USEOWNERDRAW),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN2),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON2),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN3),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON3),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_BROWSE),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_ONLY_IF_DIFFERENT),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_COLOUR),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWXSTATUSNAME),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWXSTATUS),en && en_icons);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWBOTH),en && en_icons && IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && !IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWNORMAL),en && en_icons && IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && !IsDlgButtonChecked(hwndDlg,IDC_SHOWBOTH));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSPARENTOVERLAY),en && en_icons && IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL) && !IsDlgButtonChecked(hwndDlg,IDC_SHOWBOTH));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWUNREADEMAIL),en);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON_LEFT),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN_LEFT),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON_RIGHT),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN_RIGHT),en);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI_2),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI_COUNT),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI_SPIN),en);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUSBAR_PER_PROTO),en);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_STATUSBAR_PROTO_LIST), en && IsDlgButtonChecked(hwndDlg, IDC_STATUSBAR_PER_PROTO));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SBAR_USE_ACCOUNT_SETTINGS), FALSE);
+ }
+
+ UpdateStatusBarOptionsDisplay(hwndDlg);
+ return TRUE;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_BUTTON1)
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ CHOOSEFONTA fnt;
+ memset(&fnt,0,sizeof(CHOOSEFONTA));
+ fnt.lStructSize = sizeof(CHOOSEFONTA);
+ fnt.hwndOwner = hwndDlg;
+ fnt.Flags = CF_SCREENFONTS|CF_INITTOLOGFONTSTRUCT;
+ fnt.lpLogFont = &lf;
+ ChooseFontA(&fnt);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ return 0;
+ }
+ }
+ else if (LOWORD(wParam) == IDC_COLOUR || (LOWORD(wParam) == IDC_SBAR_HORIZ_ALIGN && HIWORD(wParam) == CBN_SELCHANGE)) SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ else if (LOWORD(wParam) == IDC_SHOWSBAR) {
+ int en = IsDlgButtonChecked(hwndDlg,IDC_SHOWSBAR);
+ int en_icons = IsDlgButtonChecked(hwndDlg,IDC_SHOWICON );
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWICON),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWPROTO),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWSTATUS),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_RIGHTSTATUS),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_RIGHTMIRANDA),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_EQUALSECTIONS),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USECONNECTINGICON),en && en_icons);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USEOWNERDRAW),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN2),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON2),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN3),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON3),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_BORDER_TOP),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_BORDER_TOP_SPIN),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_BORDER_BOTTOM),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_BORDER_BOTTOM_SPIN),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_HORIZ_ALIGN),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_COLOUR),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON1),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWXSTATUSNAME),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWXSTATUS),en && en_icons);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWUNREADEMAIL),en);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI_2),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI_COUNT),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI_SPIN),en);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUSBAR_PER_PROTO),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUSBAR_PROTO_LIST),en && IsDlgButtonChecked(hwndDlg,IDC_STATUSBAR_PER_PROTO));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_USE_ACCOUNT_SETTINGS),en && IsDlgButtonChecked(hwndDlg,IDC_STATUSBAR_PER_PROTO));
+
+ UpdateStatusBarOptionsDisplay(hwndDlg);
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ }
+ else if (LOWORD(wParam) == IDC_STATUSBAR_PER_PROTO)
+ {
+ int en = IsDlgButtonChecked(hwndDlg,IDC_STATUSBAR_PER_PROTO);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUSBAR_PROTO_LIST),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_HIDE_ACCOUNT_COMPLETELY), en && perProto);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_USE_ACCOUNT_SETTINGS), en);
+
+ UpdateStatusBarOptionsDisplay(hwndDlg);
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ }
+ else if (
+ LOWORD(wParam) == IDC_SHOWXSTATUS ||
+ LOWORD(wParam) == IDC_SHOWBOTH ||
+ LOWORD(wParam) == IDC_SHOWNORMAL ||
+ LOWORD(wParam) == IDC_TRANSPARENTOVERLAY ||
+ LOWORD(wParam) == IDC_SHOWXSTATUSNAME
+ )
+ {
+ UpdateXStatusIconOptions(hwndDlg, perProto, dat, curSelProto);
+ }
+ else if (LOWORD(wParam) == IDC_SBAR_USE_ACCOUNT_SETTINGS)
+ {
+ if (perProto) {
+ dat[curSelProto].AccountIsCustomized = IsDlgButtonChecked(hwndDlg, IDC_SBAR_USE_ACCOUNT_SETTINGS);
+ UpdateStatusBarOptionsDisplay(hwndDlg);
+ }
+ }
+ else if (LOWORD(wParam) == IDC_SBAR_HIDE_ACCOUNT_COMPLETELY)
+ {
+ if (perProto)
+ dat[curSelProto].HideAccount = IsDlgButtonChecked(hwndDlg, IDC_SBAR_HIDE_ACCOUNT_COMPLETELY);
+ }
+ else if (LOWORD(wParam) == IDC_USECONNECTINGICON)
+ {
+ if (perProto)
+ dat[curSelProto].UseConnectingIcon = IsDlgButtonChecked(hwndDlg, IDC_USECONNECTINGICON);
+ else
+ _GlobalOptions.UseConnectingIcon = IsDlgButtonChecked(hwndDlg, IDC_USECONNECTINGICON);
+ }
+ else if (LOWORD(wParam) == IDC_SHOWUNREADEMAIL)
+ {
+ if (perProto)
+ dat[curSelProto].ShowUnreadEmails = IsDlgButtonChecked(hwndDlg, IDC_SHOWUNREADEMAIL);
+ else
+ _GlobalOptions.ShowUnreadEmails = IsDlgButtonChecked(hwndDlg, IDC_SHOWUNREADEMAIL);
+ }
+ else if (LOWORD(wParam) == IDC_SHOWICON || LOWORD(wParam) == IDC_SHOWPROTO || LOWORD(wParam) == IDC_SHOWSTATUS)
+ {
+ BYTE val = (IsDlgButtonChecked(hwndDlg, IDC_SHOWICON)?1:0)|(IsDlgButtonChecked(hwndDlg, IDC_SHOWPROTO)?2:0)|(IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUS)?4:0);
+ if (perProto)
+ dat[curSelProto].SBarShow = val;
+ else
+ _GlobalOptions.SBarShow = val;
+
+ UpdateStatusBarOptionsDisplay(hwndDlg);
+ }
+ else if (LOWORD(wParam) == IDC_RIGHTSTATUS || LOWORD(wParam) == IDC_RIGHTMIRANDA)
+ {
+ if (perProto)
+ dat[curSelProto].SBarRightClk = IsDlgButtonChecked(hwndDlg,IDC_RIGHTMIRANDA);
+ else
+ _GlobalOptions.SBarRightClk = IsDlgButtonChecked(hwndDlg,IDC_RIGHTMIRANDA);
+ }
+ else if (LOWORD(wParam) == IDC_OFFSETICON_LEFT)
+ {
+ if (perProto)
+ dat[curSelProto].PaddingLeft = (DWORD)SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_LEFT,UDM_GETPOS,0,0);
+ else
+ _GlobalOptions.PaddingLeft = (DWORD)SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_LEFT,UDM_GETPOS,0,0);
+ }
+ else if (LOWORD(wParam) == IDC_OFFSETICON_RIGHT)
+ {
+ if (perProto)
+ dat[curSelProto].PaddingRight = (DWORD)SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_RIGHT,UDM_GETPOS,0,0);
+ else
+ _GlobalOptions.PaddingRight = (DWORD)SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_RIGHT,UDM_GETPOS,0,0);
+ }
+ else if (
+ (
+ LOWORD(wParam) == IDC_MULTI_COUNT ||
+ LOWORD(wParam) == IDC_OFFSETICON ||
+ LOWORD(wParam) == IDC_OFFSETICON2 ||
+ LOWORD(wParam) == IDC_OFFSETICON3 ||
+ LOWORD(wParam) == IDC_SBAR_BORDER_BOTTOM ||
+ LOWORD(wParam) == IDC_SBAR_BORDER_TOP
+ ) && (
+ HIWORD(wParam) != EN_CHANGE ||
+ (HWND)lParam != GetFocus()
+ ))
+ return 0; // dont make apply enabled during buddy set crap
+ else if ( LOWORD(wParam) == IDC_STATUSBAR_PROTO_LIST )
+ {
+ UpdateStatusBarOptionsDisplay(hwndDlg);
+ return 0;
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ {
+ int count = db_get_dw(0,"Protocols","ProtoCount",-1);
+ db_set_b(NULL, "CLUI", "SBarPerProto", IsDlgButtonChecked(hwndDlg, IDC_STATUSBAR_PER_PROTO));
+
+ for (int i=0; i < count; i++) {
+ HWND hwndComboBox = GetDlgItem( hwndDlg, IDC_STATUSBAR_PROTO_LIST );
+ StatusBarProtocolOptions sbpo = dat[i];
+ char *defProto = sbpo.szName;
+
+ char settingBuf[256];
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "SBarAccountIsCustom_%s", defProto);
+ db_set_b(NULL,"CLUI",settingBuf,(BYTE)sbpo.AccountIsCustomized);
+
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "HideAccount_%s", defProto);
+ db_set_b(NULL,"CLUI",settingBuf,(BYTE)sbpo.HideAccount);
+
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "SBarShow_%s", defProto);
+ db_set_b(NULL,"CLUI",settingBuf,(BYTE)sbpo.SBarShow);
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "SBarRightClk_%s", defProto);
+ db_set_b(NULL,"CLUI",settingBuf,(BYTE)sbpo.SBarRightClk);
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "UseConnectingIcon_%s", defProto);
+ db_set_b(NULL,"CLUI",settingBuf,(BYTE)sbpo.UseConnectingIcon);
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "ShowUnreadEmails_%s", defProto);
+ db_set_b(NULL,"CLUI",settingBuf,(BYTE)sbpo.ShowUnreadEmails);
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "ShowXStatus_%s", defProto);
+ db_set_b(NULL,"CLUI",settingBuf,sbpo.ShowXStatus);
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "PaddingLeft_%s", defProto);
+ db_set_dw(NULL,"CLUI",settingBuf,sbpo.PaddingLeft);
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "PaddingRight_%s", defProto);
+ db_set_dw(NULL,"CLUI",settingBuf,sbpo.PaddingRight);
+ }
+
+ db_set_b(NULL,"CLUI","SBarShow",(BYTE)_GlobalOptions.SBarShow);
+ db_set_b(NULL,"CLUI","SBarRightClk",(BYTE)_GlobalOptions.SBarRightClk);
+ db_set_b(NULL,"CLUI","UseConnectingIcon",(BYTE)_GlobalOptions.UseConnectingIcon);
+ db_set_b(NULL,"CLUI","ShowUnreadEmails",(BYTE)_GlobalOptions.ShowUnreadEmails);
+ db_set_b(NULL,"CLUI","ShowXStatus",_GlobalOptions.ShowXStatus);
+ db_set_dw(NULL,"CLUI","PaddingLeft",_GlobalOptions.PaddingLeft);
+ db_set_dw(NULL,"CLUI","PaddingRight",_GlobalOptions.PaddingRight);
+
+
+ db_set_b(NULL,"CLUI","StatusBarProtosPerLine",(BYTE)SendDlgItemMessage(hwndDlg,IDC_MULTI_SPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CLUI","EqualSections",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_EQUALSECTIONS));
+ db_set_b(NULL,"CLUI","Align",(BYTE)SendDlgItemMessage(hwndDlg,IDC_SBAR_HORIZ_ALIGN,CB_GETCURSEL,0,0));
+ db_set_b(NULL,"CLUI","VAlign",(BYTE)SendDlgItemMessage(hwndDlg,IDC_SBAR_VERT_ALIGN,CB_GETCURSEL,0,0));
+ db_set_dw(NULL,"CLUI","LeftOffset",(DWORD)SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN,UDM_GETPOS,0,0));
+ db_set_dw(NULL,"CLUI","RightOffset",(DWORD)SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN2,UDM_GETPOS,0,0));
+ db_set_dw(NULL,"CLUI","TopOffset",(DWORD)SendDlgItemMessage(hwndDlg,IDC_SBAR_BORDER_TOP_SPIN,UDM_GETPOS,0,0));
+ db_set_dw(NULL,"CLUI","BottomOffset",(DWORD)SendDlgItemMessage(hwndDlg,IDC_SBAR_BORDER_BOTTOM_SPIN,UDM_GETPOS,0,0));
+ db_set_dw(NULL,"CLUI","SpaceBetween",(DWORD)SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN3,UDM_GETPOS,0,0));
+ db_set_dw(NULL,"ModernData","StatusBarFontCol",SendDlgItemMessage(hwndDlg,IDC_COLOUR,CPM_GETCOLOUR,0,0));
+ db_set_b(NULL,"CLUI","ShowSBar",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOWSBAR));
+
+ LoadStatusBarData();
+ CLUIServices_ProtocolStatusChanged(0,0);
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ mir_free(dat);
+ break;
+ }
+ return FALSE;
+}
diff --git a/plugins/Clist_modern/src/modern_sync.cpp b/plugins/Clist_modern/src/modern_sync.cpp
new file mode 100644
index 0000000000..df3572766e
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_sync.cpp
@@ -0,0 +1,147 @@
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_sync.h"
+
+struct SYNCCALLITEM
+{
+ WPARAM wParam;
+ LPARAM lParam;
+ int nResult;
+ HANDLE hDoneEvent;
+ PSYNCCALLBACKPROC pfnProc;
+};
+
+static void CALLBACK _SyncCallerUserAPCProc(void* param)
+{
+ SYNCCALLITEM* item = (SYNCCALLITEM*)param;
+ item->nResult = item->pfnProc(item->wParam, item->lParam);
+ SetEvent(item->hDoneEvent);
+}
+
+static INT_PTR SyncCaller(WPARAM proc, LPARAM lParam)
+{
+ typedef int (*P0PARAMFUNC)();
+ typedef int (*P1PARAMFUNC)(WPARAM);
+ typedef int (*P2PARAMFUNC)(WPARAM, LPARAM);
+ typedef int (*P3PARAMFUNC)(WPARAM, LPARAM, LPARAM);
+ typedef int (*P4PARAMFUNC)(WPARAM, LPARAM, LPARAM, LPARAM);
+
+ LPARAM * params = (LPARAM *)lParam;
+ int count = params[0];
+ switch (count) {
+ case 0:
+ return ((P0PARAMFUNC)proc)();
+
+ case 1:
+ return ((P1PARAMFUNC)proc)((WPARAM)params[1]);
+
+ case 2:
+ return ((P2PARAMFUNC)proc)((WPARAM)params[1],(LPARAM)params[2]);
+
+ case 3:
+ return ((P3PARAMFUNC)proc)((WPARAM)params[1],(LPARAM)params[2], (LPARAM)params[3]);
+
+ case 4:
+ return ((P4PARAMFUNC)proc)((WPARAM)params[1],(LPARAM)params[2], (LPARAM)params[3], (LPARAM)params[4]);
+ }
+ return 0;
+}
+
+int SyncCall(void * vproc, int count, ... )
+{
+ LPARAM params[5];
+ va_list va;
+ int i;
+ params[0] = (LPARAM)count;
+ va_start(va, count);
+ for (i=0; i < count && i < SIZEOF(params)-1; i++)
+ params[i+1] = va_arg(va,LPARAM);
+
+ va_end(va);
+ return SyncCallProxy(SyncCaller, (WPARAM)vproc, (LPARAM) params);
+}
+
+int SyncCallProxy(PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam, CRITICAL_SECTION * cs /*= NULL */)
+{
+ SYNCCALLITEM item = {0};
+
+ int nReturn = 0;
+
+ if ( cs != NULL ) {
+ if ( !fnTryEnterCriticalSection ) { // for poor OSes like Win98
+ EnterCriticalSection( cs );
+ int result = pfnProc( wParam, lParam );
+ LeaveCriticalSection( cs );
+ return result;
+ }
+
+ if ( fnTryEnterCriticalSection( cs )) { //simple call (Fastest)
+ int result = pfnProc(wParam,lParam);
+ LeaveCriticalSection( cs );
+ return result;
+ }
+ else { //Window SendMessage Call(Middle)
+ if ( SyncCallWinProcProxy( pfnProc, wParam, lParam, nReturn ) == S_OK)
+ return nReturn;
+ }
+ }
+ if ( SyncCallAPCProxy( pfnProc, wParam, lParam, nReturn ) == S_OK)
+ return nReturn;
+
+ return NULL;
+}
+
+HRESULT SyncCallWinProcProxy( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam, int& nReturn )
+{
+ nReturn = 0;
+ if (pcli->hwndContactList == NULL )
+ return E_FAIL;
+
+ SYNCCALLITEM item = {0};
+ item.wParam = wParam;
+ item.lParam = lParam;
+ item.pfnProc = pfnProc;
+ nReturn = SendMessage(pcli->hwndContactList, UM_SYNCCALL, (WPARAM)&item,0);
+ return S_OK;
+}
+
+HRESULT SyncCallAPCProxy( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam, int& hReturn )
+{
+ hReturn = 0;
+
+ if (pfnProc == NULL)
+ return E_FAIL;
+
+ if (GetCurrentThreadId() != g_dwMainThreadID) {
+ SYNCCALLITEM item = {0};
+ item.wParam = wParam;
+ item.lParam = lParam;
+ item.pfnProc = pfnProc;
+ item.hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ CallFunctionAsync(_SyncCallerUserAPCProc, &item);
+
+ WaitForSingleObject(item.hDoneEvent, INFINITE);
+ CloseHandle(item.hDoneEvent);
+
+ hReturn = item.nResult;
+
+ return S_OK;
+ }
+ /* else */
+
+ hReturn = pfnProc(wParam, lParam);
+ return S_OK;
+}
+
+LRESULT SyncOnWndProcCall( WPARAM wParam )
+{
+ SYNCCALLITEM *psci = (SYNCCALLITEM *)wParam;
+ if (psci)
+ return psci->pfnProc( psci->wParam, psci->lParam );
+ return 0;
+}
+
+int DoCall( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam )
+{
+ return SyncCallProxy( pfnProc, 0, lParam );
+}
diff --git a/plugins/Clist_modern/src/modern_tbbutton.cpp b/plugins/Clist_modern/src/modern_tbbutton.cpp
new file mode 100644
index 0000000000..9d0402324e
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_tbbutton.cpp
@@ -0,0 +1,503 @@
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_commonprototypes.h"
+#include "m_api/m_skinbutton.h"
+#include "hdr/modern_clcpaint.h"
+
+#include <m_button_int.h>
+#include <m_toptoolbar.h>
+
+#ifdef __MINGW32__
+#include <ctype.h>
+#endif
+
+#define BUTTON_POLLID 100
+#define BUTTON_POLLDELAY 50
+#define b2str(a) ((a) ? "True" : "False")
+
+void CustomizeToolbar(HWND);
+
+struct TBBUTTONDATA : public MButtonCtrl
+{
+ char *szButtonID; // button id
+ BOOL fSendOnDown; // send event on button pushed
+ BOOL fHotMark; // button is hot marked (e.g. current state)
+ BOOL fFocused;
+ int nFontID; // internal font ID
+ HANDLE ttbID; // control ID
+ TCHAR szText[128]; // text on the button
+ RECT rcMargins; // margins of inner content
+
+ HANDLE hIcolibHandle; // handle of icon in iconlib
+
+ XPTHANDLE hThemeButton;
+ XPTHANDLE hThemeToolbar;
+};
+
+static CRITICAL_SECTION csTips;
+static HWND hwndToolTips = NULL;
+static BOOL bThemed = FALSE;
+
+static HANDLE hButtonWindowList = NULL;
+static HANDLE hBkgChangedHook = NULL;
+
+static int OnIconLibIconChanged(WPARAM wParam, LPARAM lParam)
+{
+ WindowList_BroadcastAsync(hButtonWindowList, MBM_REFRESHICOLIBICON,0,0);
+ return 0;
+}
+
+static void InvalidateParentRect(HWND hwndChild, RECT * lpRect, BOOL fErase)
+{
+ LONG lExStyle = GetWindowLongPtr(hwndChild,GWL_EXSTYLE);
+ if (lExStyle & WS_EX_TRANSPARENT) {
+ NMHDR hdr;
+ hdr.hwndFrom = hwndChild;
+ hdr.idFrom = 0;
+ hdr.code = BUTTONNEEDREDRAW;
+ SendMessage(GetParent(hwndChild),WM_NOTIFY,(WPARAM)hwndChild,(LPARAM)&hdr);
+ }
+ else InvalidateRect(hwndChild,lpRect,fErase);
+}
+
+static int TBStateConvert2Flat(int state)
+{
+ switch (state) {
+ case PBS_NORMAL:
+ return TS_NORMAL;
+ case PBS_HOT:
+ return TS_HOT;
+ case PBS_PRESSED:
+ return TS_PRESSED;
+ case PBS_DISABLED:
+ return TS_DISABLED;
+ case PBS_DEFAULTED:
+ return TS_NORMAL;
+ }
+ return TS_NORMAL;
+}
+
+static void PaintWorker(TBBUTTONDATA *bct, HDC hdcPaint , POINT *pOffset)
+{
+ POINT offset = {0};
+ if (pOffset)
+ offset = *pOffset;
+
+ if ( !hdcPaint)
+ return; //early exit
+
+ RECT rcClient;
+ GetClientRect(bct->hwnd, &rcClient);
+ int width = rcClient.right - rcClient.left;
+ int height = rcClient.bottom - rcClient.top;
+
+ HBITMAP hbmMem;
+ HBITMAP hbmOld = NULL;
+ HDC hdcMem = pOffset ? hdcPaint : CreateCompatibleDC(hdcPaint);
+ HFONT hOldFont = (HFONT)SelectObject(hdcMem, bct->hFont);
+ if ( !pOffset) {
+ hbmMem = ske_CreateDIB32(width, height);
+ hbmOld = (HBITMAP)SelectObject(hdcMem, hbmMem);
+ }
+ else OffsetRect(&rcClient,offset.x,offset.y);
+
+ if ( !g_CluiData.fDisableSkinEngine) {
+ char szRequest[128];
+ /* painting */
+ mir_snprintf(szRequest,SIZEOF(szRequest),"Button,ID=%s,Hovered=%s,Pressed=%s,Focused=%s",
+ bct->szButtonID, // ID
+ b2str(bct->stateId == PBS_HOT), // Hovered
+ b2str(bct->stateId == PBS_PRESSED || bct->bIsPushed == TRUE), // Pressed
+ b2str(bct->fFocused)); // Focused
+
+ SkinDrawGlyph(hdcMem,&rcClient,&rcClient,szRequest);
+ }
+ else if (xpt_IsThemed(bct->hThemeToolbar)) {
+ RECT *rc = &rcClient;
+ int state = IsWindowEnabled(bct->hwnd) ? /*(bct->stateId == PBS_PRESSED || bct->bIsPushed == TRUE) ? PBS_PRESSED :*/ (bct->stateId == PBS_NORMAL && bct->bIsDefault ? PBS_DEFAULTED : bct->stateId) : PBS_DISABLED;
+ xpt_DrawTheme(bct->hThemeToolbar,bct->hwnd,hdcMem,TP_BUTTON, TBStateConvert2Flat(state), rc, rc);
+ }
+ else {
+ HBRUSH hbr = NULL;
+
+ if (bct->stateId == PBS_PRESSED || bct->stateId == PBS_HOT)
+ hbr = GetSysColorBrush(COLOR_3DLIGHT);
+ else {
+ RECT btnRect;
+ POINT pt = {0};
+ int ret;
+ HWND hwndParent = GetParent(bct->hwnd);
+ HDC dc = CreateCompatibleDC(NULL);
+ HBITMAP memBM, oldBM;
+ GetWindowRect(hwndParent,&btnRect);
+ memBM = ske_CreateDIB32( btnRect.right-btnRect.left, btnRect.bottom-btnRect.top );
+ oldBM = (HBITMAP)SelectObject ( dc, memBM );
+ ret = SendMessage(hwndParent,WM_ERASEBKGND,(WPARAM)dc,0);
+ GetWindowRect(bct->hwnd,&btnRect);
+ ClientToScreen(hwndParent,&pt);
+ OffsetRect(&btnRect,-pt.x,-pt.y);
+ if (ret)
+ BitBlt(hdcMem,0,0,btnRect.right-btnRect.left,btnRect.bottom-btnRect.top,dc,btnRect.left,btnRect.top,SRCCOPY);
+ oldBM = (HBITMAP)SelectObject ( dc, oldBM );
+ DeleteObject(memBM);
+ DeleteDC(dc);
+ if ( !ret) { //WM_ERASEBKG return false need to paint
+ HDC pdc = GetDC(hwndParent);
+ HBRUSH oldBrush = (HBRUSH)GetCurrentObject( pdc, OBJ_BRUSH );
+ hbr = (HBRUSH)SendMessage(hwndParent, WM_CTLCOLORDLG, (WPARAM)pdc, (LPARAM)hwndParent);
+ SelectObject(pdc,oldBrush);
+ ReleaseDC(hwndParent,pdc);
+ }
+ }
+ if (hbr) {
+ FillRect(hdcMem, &rcClient, hbr);
+ DeleteObject(hbr);
+ }
+ if (bct->stateId == PBS_HOT || bct->fFocused) {
+ if (bct->bIsPushed)
+ DrawEdge(hdcMem,&rcClient, EDGE_ETCHED,BF_RECT|BF_SOFT);
+ else
+ DrawEdge(hdcMem,&rcClient, BDR_RAISEDOUTER,BF_RECT|BF_SOFT|BF_FLAT);
+ }
+ else if (bct->stateId == PBS_PRESSED)
+ DrawEdge(hdcMem, &rcClient, BDR_SUNKENOUTER,BF_RECT|BF_SOFT);
+ }
+
+ RECT rcTemp = rcClient; //content rect
+ BYTE bPressed = (bct->stateId == PBS_PRESSED || bct->bIsPushed == TRUE)?1:0;
+ HICON hHasIcon = bct->hIcon ? bct->hIcon : NULL;
+ BOOL fHasText = (bct->szText[0] != '\0');
+
+ /* formatter */
+ RECT rcIcon;
+ RECT rcText;
+
+ if ( !g_CluiData.fDisableSkinEngine) {
+ /* correct rect according to rcMargins */
+
+ rcTemp.left += bct->rcMargins.left;
+ rcTemp.top += bct->rcMargins.top;
+ rcTemp.bottom -= bct->rcMargins.bottom;
+ rcTemp.right -= bct->rcMargins.right;
+ }
+
+ rcIcon = rcTemp;
+ rcText = rcTemp;
+
+ /* reposition button items */
+ if (hHasIcon && fHasText ) {
+ rcIcon.right = rcIcon.left+16; /* CXSM_ICON */
+ rcText.left = rcIcon.right+2;
+ }
+ else if (hHasIcon) {
+ rcIcon.left += (rcIcon.right-rcIcon.left)/2-8;
+ rcIcon.right = rcIcon.left+16;
+ }
+
+ /* Check sizes*/
+ if (hHasIcon && (rcIcon.right>rcTemp.right || rcIcon.bottom>rcTemp.bottom || rcIcon.left < rcTemp.left || rcIcon.top < rcTemp.top))
+ hHasIcon = NULL;
+
+ if (fHasText && (rcText.right>rcTemp.right || rcText.bottom>rcTemp.bottom || rcText.left < rcTemp.left || rcText.top < rcTemp.top))
+ fHasText = FALSE;
+
+ if (hHasIcon) {
+ /* center icon vertically */
+ rcIcon.top += (rcClient.bottom-rcClient.top)/2 - 8; /* CYSM_ICON/2 */
+ rcIcon.bottom = rcIcon.top + 16; /* CYSM_ICON */
+ /* draw it */
+ ske_DrawIconEx(hdcMem, rcIcon.left+bPressed, rcIcon.top+bPressed, hHasIcon,
+ 16, 16, 0, NULL, DI_NORMAL);
+ }
+
+ if (fHasText) {
+ BOOL bCentered = TRUE;
+ SetBkMode(hdcMem,TRANSPARENT);
+ if (bct->nFontID >= 0)
+ g_clcPainter.ChangeToFont(hdcMem,NULL,bct->nFontID,NULL);
+
+ RECT TextRequiredRect = rcText;
+ ske_DrawText(hdcMem, bct->szText, -1, &TextRequiredRect, DT_CENTER | DT_VCENTER | DT_CALCRECT | DT_SINGLELINE);
+ if (TextRequiredRect.right-TextRequiredRect.left>rcText.right-rcText.left)
+ bCentered = FALSE;
+
+ ske_DrawText(hdcMem, bct->szText, -1, &rcText, (bCentered ? DT_CENTER: 0) | DT_VCENTER | DT_SINGLELINE);
+ ske_ResetTextEffect(hdcMem);
+ }
+ if ( !pOffset)
+ BitBlt(hdcPaint,0,0,width,height,hdcMem,0,0,SRCCOPY);
+
+ // better to use try/finally but looks like last one is Microsoft specific
+ SelectObject(hdcMem,hOldFont);
+ if ( !pOffset) {
+ SelectObject(hdcMem,hbmOld);
+ DeleteObject(hbmMem);
+ DeleteDC(hdcMem);
+ }
+}
+
+static LRESULT CALLBACK ToolbarButtonProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TBBUTTONDATA *bct = (TBBUTTONDATA *) GetWindowLongPtr(hwndDlg, 0);
+ switch (msg) {
+ case WM_DESTROY:
+ xpt_FreeThemeForWindow(hwndDlg);
+ WindowList_Remove(hButtonWindowList, hwndDlg);
+ break; // DONT! fall thru
+
+ case WM_SETTEXT:
+ lstrcpyn(bct->szText, (TCHAR *)lParam, SIZEOF(bct->szText)-1);
+ bct->szText[SIZEOF(bct->szText)-1] = '\0';
+ break;
+
+ case WM_SETFONT:
+ // remember the font so we can use it later
+ bct->hFont = (HFONT) wParam; // maybe we should redraw?
+ bct->nFontID = (int) lParam - 1;
+ break;
+
+ case BUTTONSETSENDONDOWN:
+ bct->fSendOnDown = (BOOL) lParam;
+ break;
+
+ case BUTTONSETMARGINS:
+ if (lParam) bct->rcMargins = *(RECT*)lParam;
+ else {
+ RECT nillRect = {0};
+ bct->rcMargins = nillRect;
+ }
+ break;
+
+ case BUTTONSETID:
+ bct->szButtonID = (char *)lParam;
+ break;
+
+ case BUTTONDRAWINPARENT:
+ if (IsWindowVisible(hwndDlg))
+ PaintWorker(bct, (HDC) wParam, (POINT*) lParam);
+ break;
+
+ case WM_NCPAINT:
+ case WM_PAINT:
+ if (g_CluiData.fDisableSkinEngine) {
+ PAINTSTRUCT ps;
+ HDC hdcPaint = BeginPaint(hwndDlg, &ps);
+ if (hdcPaint) {
+ PaintWorker(bct, hdcPaint, NULL);
+ EndPaint(hwndDlg, &ps);
+ }
+ }
+ ValidateRect(hwndDlg,NULL);
+ bct->lResult = 0;
+ return 1;
+
+ case WM_CAPTURECHANGED:
+ if ((HWND)lParam != bct->hwnd && bct->stateId != PBS_DISABLED) {
+ // don't change states if disabled
+ bct->stateId = PBS_NORMAL;
+ InvalidateParentRect(bct->hwnd, NULL, TRUE);
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ {
+ int xPos = (( int )( short ) LOWORD( lParam ));
+ int yPos = (( int )( short ) HIWORD( lParam ));
+ POINT ptMouse = { xPos, yPos };
+
+ RECT rcClient;
+ GetClientRect( bct->hwnd, &rcClient );
+ if ( !PtInRect( &rcClient, ptMouse )) {
+ bct->fHotMark = FALSE;
+ ReleaseCapture();
+ }
+ else {
+ if (bct->stateId != PBS_DISABLED && bct->stateId != PBS_PRESSED) {
+ bct->stateId = PBS_PRESSED;
+ bct->fHotMark = TRUE;
+ InvalidateParentRect(bct->hwnd, NULL, TRUE);
+ if (bct->fSendOnDown) {
+ SendMessage(GetParent(hwndDlg), WM_COMMAND, MAKELONG(GetDlgCtrlID(hwndDlg), BN_CLICKED), (LPARAM) hwndDlg);
+ bct->stateId = PBS_NORMAL;
+ InvalidateParentRect(bct->hwnd, NULL, TRUE);
+ }
+ }
+ SetCapture( bct->hwnd );
+ }
+ }
+ bct->lResult = 0;
+ return 1;
+
+ case WM_LBUTTONUP:
+ if ( GetCapture() == bct->hwnd ) {
+ POINT ptMouse = { LOWORD(lParam), HIWORD(lParam) };
+
+ RECT rcClient;
+ GetClientRect( bct->hwnd, &rcClient );
+
+ if ( !PtInRect( &rcClient, ptMouse )) {
+ bct->fHotMark = FALSE;
+ ReleaseCapture();
+ break;
+ }
+
+ if (bct->bIsPushBtn)
+ bct->bIsPushed = !bct->bIsPushed;
+
+ if (bct->stateId != PBS_DISABLED) {
+ // don't change states if disabled
+ bct->stateId = PBS_HOT;
+ InvalidateParentRect(bct->hwnd, NULL, TRUE);
+ }
+ if ( !bct->fSendOnDown)
+ SendMessage(GetParent(hwndDlg), WM_COMMAND, MAKELONG(GetDlgCtrlID(hwndDlg), BN_CLICKED), (LPARAM) hwndDlg);
+ }
+ bct->fHotMark = FALSE;
+ bct->lResult = 0;
+ return 1;
+
+ case WM_MOUSEMOVE:
+ {
+ RECT rc;
+ POINT pt;
+ BOOL bPressed = (wParam & MK_LBUTTON) != 0;
+ if ( bPressed && !bct->fHotMark )
+ break;
+ GetWindowRect(hwndDlg, &rc);
+ GetCursorPos(&pt);
+ BOOL inClient = PtInRect(&rc, pt);
+ if ( inClient ) {
+ SetCapture( bct->hwnd );
+ if ( bct->stateId == PBS_NORMAL ) {
+ bct->stateId = PBS_HOT;
+ InvalidateParentRect(bct->hwnd, NULL, TRUE);
+ }
+ }
+
+ if ( !inClient && bct->stateId == PBS_PRESSED ) {
+ bct->stateId = PBS_HOT;
+ InvalidateParentRect(bct->hwnd, NULL, TRUE);
+ }
+ else if ( inClient && bct->stateId == PBS_HOT && bPressed ) {
+ if ( bct->fHotMark ) {
+ bct->stateId = PBS_PRESSED;
+ InvalidateParentRect(bct->hwnd, NULL, TRUE);
+ }
+ }
+ else if ( !inClient && !bPressed) {
+ bct->fHotMark = FALSE;
+ ReleaseCapture();
+ }
+ }
+ bct->lResult = 0;
+ return 1;
+
+ case WM_NCHITTEST:
+ {
+ LRESULT lr = SendMessage(GetParent(hwndDlg), WM_NCHITTEST, wParam, lParam);
+ if (lr == HTLEFT || lr == HTRIGHT || lr == HTBOTTOM || lr == HTTOP || lr == HTTOPLEFT || lr == HTTOPRIGHT
+ || lr == HTBOTTOMLEFT || lr == HTBOTTOMRIGHT) {
+ bct->lResult = HTTRANSPARENT;
+ return 1;
+ }
+ }
+ break;
+
+ case BM_SETCHECK:
+ if ( !bct->bIsPushBtn) break;
+ if (wParam == BST_CHECKED)
+ bct->bIsPushed = 1;
+ else if (wParam == BST_UNCHECKED)
+ bct->bIsPushed = 0;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ bct->lResult = 0;
+ return 1;
+
+ case WM_ERASEBKGND:
+ bct->lResult = 1;
+ return 1;
+
+ case MBM_SETICOLIBHANDLE:
+ bct->hIcolibHandle = (HANDLE)lParam;
+ bct->hIcon = (bct->hIcolibHandle) ? Skin_GetIconByHandle(bct->hIcolibHandle) : NULL;
+ return 1;
+
+ case MBM_REFRESHICOLIBICON:
+ if (bct->hIcolibHandle)
+ bct->hIcon = (HICON)CallService(MS_SKIN2_GETICONBYHANDLE, 0 , (LPARAM) bct->hIcolibHandle);
+ else
+ bct->hIcon = NULL;
+ InvalidateRect(hwndDlg,NULL,TRUE);
+ pcli->pfnInvalidateRect(GetParent(GetParent(hwndDlg)),NULL,TRUE);
+ return 1;
+
+ case MBM_UPDATETRANSPARENTFLAG:
+ {
+ LONG flag = GetWindowLongPtr(hwndDlg,GWL_EXSTYLE);
+ LONG oldFlag = flag;
+ if (lParam == 2)
+ lParam = (g_CluiData.fDisableSkinEngine)?0:1;
+ flag &= ~WS_EX_TRANSPARENT;
+ if (lParam) flag |= WS_EX_TRANSPARENT;
+ if (flag != oldFlag) {
+ SetWindowLongPtr(hwndDlg,GWL_EXSTYLE,flag);
+ RedrawWindow(hwndDlg,NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW);
+ }
+ }
+ return 1;
+ }
+ return 0;
+}
+
+void MakeButtonSkinned(HWND hWnd)
+{
+ MButtonCustomize Custom;
+ Custom.cbLen = sizeof(TBBUTTONDATA);
+ Custom.fnPainter = (pfnPainterFunc)PaintWorker;
+ Custom.fnWindowProc = ToolbarButtonProc;
+ SendMessage(hWnd, BUTTONSETCUSTOM, 0, (LPARAM)&Custom);
+
+ TBBUTTONDATA* p = (TBBUTTONDATA*)GetWindowLongPtr(hWnd, 0);
+ p->nFontID = -1;
+ p->hThemeButton = xpt_AddThemeHandle(p->hwnd, L"BUTTON");
+ p->hThemeToolbar = xpt_AddThemeHandle(p->hwnd, L"TOOLBAR");
+ WindowList_Add(hButtonWindowList, hWnd, NULL);
+}
+
+static void CustomizeButton(HANDLE ttbid, HWND hWnd, LPARAM lParam)
+{
+ if (ttbid == TTB_WINDOW_HANDLE) {
+ CustomizeToolbar(hWnd);
+ return;
+ }
+
+ MakeButtonSkinned(hWnd);
+
+ TBBUTTONDATA* p = (TBBUTTONDATA*)GetWindowLongPtr(hWnd, 0);
+ p->szButtonID, "Toolbar.MissingID";
+ p->ttbID = ttbid;
+ SendMessage(hWnd, MBM_UPDATETRANSPARENTFLAG, 0, 2);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+int Buttons_ModuleLoaded(WPARAM wParam, LPARAM lParam)
+{
+ TopToolbar_SetCustomProc(CustomizeButton, 0);
+ return 0;
+}
+
+int Buttons_OnSkinModeSettingsChanged(WPARAM wParam, LPARAM lParam)
+{
+ WindowList_BroadcastAsync(hButtonWindowList, MBM_UPDATETRANSPARENTFLAG,0,2);
+ return 0;
+}
+
+HRESULT ToolbarButtonLoadModule()
+{
+ HookEvent(ME_SYSTEM_MODULESLOADED, Buttons_ModuleLoaded);
+
+ hButtonWindowList = (HANDLE) CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0);
+ hIconChangedHook = HookEvent(ME_SKIN2_ICONSCHANGED,OnIconLibIconChanged);
+ hBkgChangedHook = HookEvent(ME_BACKGROUNDCONFIG_CHANGED,Buttons_OnSkinModeSettingsChanged);
+ return S_OK;
+}
diff --git a/plugins/Clist_modern/src/modern_toolbar.cpp b/plugins/Clist_modern/src/modern_toolbar.cpp
new file mode 100644
index 0000000000..92a46dcd46
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_toolbar.cpp
@@ -0,0 +1,357 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+
+Copyright 2007 Artem Shpynov
+Copyright 2000-2008 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 "hdr/modern_commonheaders.h"
+#include "hdr/modern_commonprototypes.h"
+#include "./m_api/m_skinbutton.h"
+#include <m_toptoolbar.h>
+#include "hdr/modern_sync.h"
+
+struct
+{
+ char *pszButtonID, *pszButtonName, *pszServiceName;
+ char *pszTooltipUp, *pszTooltipDn;
+ int icoDefIdx, defResource, defResource2;
+ BOOL bVisByDefault;
+ HANDLE hButton;
+}
+static BTNS[] =
+{
+ { "MainMenu", "Main Menu", "CList/ShowMainMenu", "Main menu", NULL, 100 , IDI_RESETVIEW, IDI_RESETVIEW, TRUE },
+ { "StatusMenu", "Status Menu", "CList/ShowStatusMenu", "Status menu", NULL, 105 , IDI_RESETVIEW, IDI_RESETVIEW, TRUE },
+ { "AccoMgr", "Accounts", MS_PROTO_SHOWACCMGR, "Accounts...", NULL, 282 , IDI_ACCMGR, IDI_ACCMGR, TRUE },
+ { "ShowHideOffline","Show/Hide offline contacts", MS_CLIST_TOGGLEHIDEOFFLINE, "Hide offline contacts", "Show offline contacts", 110, IDI_RESETVIEW, IDI_RESETVIEW, TRUE },
+ { "FindUser","Find User", "FindAdd/FindAddCommand", "Find User", NULL, 140 , IDI_RESETVIEW, IDI_RESETVIEW, TRUE },
+ { "Options","Options", "Options/OptionsCommand", "Options", NULL, 150 , IDI_RESETVIEW, IDI_RESETVIEW, TRUE },
+ { "UseGroups","Use/Disable groups", MS_CLIST_TOGGLEGROUPS, "Use groups", "Disable Groups", 160, IDI_RESETVIEW, IDI_RESETVIEW, FALSE },
+ { "EnableSounds","Enable/Disable sounds", MS_CLIST_TOGGLESOUNDS, "Enable sounds", "Disable Sounds", 170, IDI_RESETVIEW, IDI_RESETVIEW, FALSE },
+ { "Minimize","Minimize", "CList/ShowHide", "Minimize", NULL, 180 , IDI_RESETVIEW, IDI_RESETVIEW, FALSE }
+};
+
+static void SetButtonPressed(int i, int state)
+{
+ CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)BTNS[i].hButton, state ? TTBST_PUSHED : TTBST_RELEASED);
+}
+
+static int Modern_InitButtons(WPARAM, LPARAM)
+{
+ for (int i=0; i < SIZEOF(BTNS); i++) {
+ TTBButton tbb = { 0 };
+ tbb.cbSize = sizeof(tbb);
+
+ if (BTNS[i].pszButtonID) {
+ tbb.name = LPGEN(BTNS[i].pszButtonID);
+ tbb.pszService = BTNS[i].pszServiceName;
+ tbb.pszTooltipUp = LPGEN(BTNS[i].pszTooltipUp);
+ tbb.pszTooltipDn = LPGEN(BTNS[i].pszTooltipDn);
+
+ char buf[255];
+ mir_snprintf(buf,SIZEOF(buf),"%s%s%s", TTB_OPTDIR, BTNS[i].pszButtonID, "_dn");
+ tbb.hIconHandleUp = RegisterIcolibIconHandle( buf, "Toolbar", BTNS[i].pszTooltipUp, _T("icons\\toolbar_icons.dll"),-BTNS[i].icoDefIdx, g_hInst, BTNS[i].defResource );
+
+ if (BTNS[i].pszTooltipDn) {
+ tbb.dwFlags |= TTBBF_ASPUSHBUTTON;
+
+ mir_snprintf(buf,SIZEOF(buf),"%s%s%s", TTB_OPTDIR, BTNS[i].pszButtonID, "_up");
+ tbb.hIconHandleDn = RegisterIcolibIconHandle( buf, "Toolbar", BTNS[i].pszTooltipDn, _T("icons\\toolbar_icons.dll"),-(BTNS[i].icoDefIdx+1), g_hInst, BTNS[i].defResource2 );
+ }
+ else tbb.hIconHandleDn = NULL;
+ }
+ else tbb.dwFlags |= TTBBF_ISSEPARATOR;
+
+ tbb.dwFlags |= (BTNS[i].bVisByDefault ? TTBBF_VISIBLE :0 );
+ BTNS[i].hButton = TopToolbar_AddButton(&tbb);
+ }
+
+ SetButtonPressed(3, db_get_b(NULL, "CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT));
+ SetButtonPressed(6, db_get_b(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT));
+ SetButtonPressed(7, db_get_b(NULL, "Skin", "UseSound", SETTING_ENABLESOUNDS_DEFAULT));
+ return 1;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define MTBM_LAYEREDPAINT (WM_USER+20)
+
+struct ModernToolbarCtrl : public TTBCtrl
+{
+ XPTHANDLE mtbXPTheme;
+};
+
+struct MTB_BUTTONINFO
+{
+ HWND hWindow;
+};
+
+struct
+{
+ HBITMAP mtb_hBmpBackground;
+ COLORREF mtb_bkColour;
+ WORD mtb_backgroundBmpUse;
+ BOOL mtb_useWinColors;
+}
+static tbdat = { 0 };
+
+COLORREF sttGetColor(char * module, char * color, COLORREF defColor);
+
+static int ehhToolBarSettingsChanged(WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam;
+ if ((HANDLE)wParam != NULL)
+ return 0;
+
+ if (!mir_strcmp(cws->szModule,"CList")) {
+ if (!mir_strcmp(cws->szSetting,"HideOffline"))
+ SetButtonPressed(3, cws->value.bVal);
+ else if (!mir_strcmp(cws->szSetting,"UseGroups"))
+ SetButtonPressed(6, cws->value.bVal);
+ }
+ else if (!mir_strcmp(cws->szModule,"Skin")) {
+ if (!mir_strcmp(cws->szSetting,"UseSound"))
+ SetButtonPressed(7, cws->value.bVal);
+ }
+
+ return 0;
+}
+
+static int ehhToolBarBackgroundSettingsChanged(WPARAM wParam, LPARAM lParam)
+{
+ if ( tbdat.mtb_hBmpBackground) {
+ DeleteObject(tbdat.mtb_hBmpBackground);
+ tbdat.mtb_hBmpBackground = NULL;
+ }
+ if (g_CluiData.fDisableSkinEngine) {
+ DBVARIANT dbv;
+ tbdat.mtb_bkColour = sttGetColor("ToolBar","BkColour",CLCDEFAULT_BKCOLOUR);
+ if ( db_get_b(NULL,"ToolBar","UseBitmap",CLCDEFAULT_USEBITMAP)) {
+ if ( !db_get_s(NULL, "ToolBar", "BkBitmap", &dbv, DBVT_TCHAR)) {
+ tbdat.mtb_hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.ptszVal);
+ db_free(&dbv);
+ }
+ }
+ tbdat.mtb_useWinColors = db_get_b(NULL, "ToolBar", "UseWinColours", CLCDEFAULT_USEWINDOWSCOLOURS);
+ tbdat.mtb_backgroundBmpUse = db_get_b(NULL, "ToolBar", "BkBmpUse", CLCDEFAULT_BKBMPUSE);
+ }
+ PostMessage(pcli->hwndContactList,WM_SIZE,0,0);
+ return 0;
+}
+
+static BOOL sttDrawToolBarBackground(HWND hwnd, HDC hdc, RECT * rect, ModernToolbarCtrl* pMTBInfo)
+{
+ BOOL bFloat = (GetParent(hwnd)!=pcli->hwndContactList);
+ if (g_CluiData.fDisableSkinEngine || !g_CluiData.fLayered || bFloat) {
+ HBRUSH hbr;
+
+ RECT rc;
+ if (rect)
+ rc=*rect;
+ else
+ GetClientRect(hwnd,&rc);
+
+ if ( !(tbdat.mtb_backgroundBmpUse && tbdat.mtb_hBmpBackground) && tbdat.mtb_useWinColors) {
+ if (xpt_IsThemed(pMTBInfo->mtbXPTheme))
+ xpt_DrawTheme(pMTBInfo->mtbXPTheme, pMTBInfo->hWnd, hdc, 0, 0, &rc, &rc);
+ else {
+ hbr = GetSysColorBrush(COLOR_3DFACE);
+ FillRect(hdc, &rc, hbr);
+ }
+ }
+ else if (!tbdat.mtb_hBmpBackground && !tbdat.mtb_useWinColors) {
+ hbr = CreateSolidBrush(tbdat.mtb_bkColour);
+ FillRect(hdc, &rc, hbr);
+ DeleteObject(hbr);
+ }
+ else DrawBackGround(hwnd, hdc, tbdat.mtb_hBmpBackground, tbdat.mtb_bkColour, tbdat.mtb_backgroundBmpUse);
+ }
+ return TRUE;
+}
+
+static void sttDrawNonLayeredSkinedBar(HWND hwnd, HDC hdc)
+{
+ RECT rc = {0};
+ GetClientRect(hwnd, &rc);
+ rc.right++;
+ rc.bottom++;
+ HDC hdc2 = CreateCompatibleDC(hdc);
+ HBITMAP hbmp = ske_CreateDIB32(rc.right, rc.bottom);
+ HBITMAP hbmpo = (HBITMAP)SelectObject(hdc2, hbmp);
+ if (GetParent(hwnd) != pcli->hwndContactList) {
+ HBRUSH br = GetSysColorBrush(COLOR_3DFACE);
+ FillRect(hdc2, &rc, br);
+ }
+ else ske_BltBackImage(hwnd, hdc2, &rc);
+
+ SendMessage(hwnd, MTBM_LAYEREDPAINT, (WPARAM)hdc2, 0);
+ BitBlt(hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, hdc2, rc.left, rc.top, SRCCOPY);
+ SelectObject(hdc2, hbmpo);
+ DeleteObject(hbmp);
+ mod_DeleteDC(hdc2);
+
+ SelectObject(hdc, (HFONT)GetStockObject(DEFAULT_GUI_FONT));
+ ValidateRect(hwnd, NULL);
+}
+
+static LRESULT CALLBACK toolbarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ ModernToolbarCtrl* pMTBInfo = (ModernToolbarCtrl*)GetWindowLongPtr(hwnd, 0);
+
+ switch( msg ) {
+ case WM_ERASEBKGND:
+ pMTBInfo->lResult = (g_CluiData.fDisableSkinEngine) ? sttDrawToolBarBackground(hwnd, (HDC)wParam, NULL, pMTBInfo) : 0;
+ return 1;
+
+ case WM_NCPAINT:
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ BOOL bFloat = (GetParent(hwnd) != pcli->hwndContactList);
+ if (g_CluiData.fDisableSkinEngine|| !g_CluiData.fLayered || bFloat ) {
+ BeginPaint(hwnd,&ps);
+ if ((!g_CluiData.fLayered || bFloat) && !g_CluiData.fDisableSkinEngine)
+ sttDrawNonLayeredSkinedBar(hwnd, ps.hdc);
+ else
+ sttDrawToolBarBackground(hwnd, ps.hdc, &ps.rcPaint, pMTBInfo);
+ EndPaint(hwnd,&ps);
+ }
+ }
+
+ pMTBInfo->lResult = DefWindowProc(hwnd, msg, wParam, lParam);
+ return 1;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR) lParam)->code == BUTTONNEEDREDRAW)
+ pcli->pfnInvalidateRect(hwnd, NULL, FALSE);
+ pMTBInfo->lResult = 0;
+ return 1;
+
+ case MTBM_LAYEREDPAINT:
+ {
+ RECT MyRect={0};
+ HDC hDC=(HDC)wParam;
+ GetWindowRect(hwnd,&MyRect);
+
+ RECT rcClient;
+ GetClientRect(hwnd, &rcClient);
+ SkinDrawGlyph(hDC, &rcClient, &rcClient, "Bar,ID=ToolBar,Part=Background");
+
+ for (int i=0; i < pMTBInfo->pButtonList->realCount; i++) {
+ RECT childRect;
+ POINT Offset;
+ TTBCtrlButton* mtbi = (TTBCtrlButton*)pMTBInfo->pButtonList->items[i];
+ GetWindowRect(mtbi->hWindow, &childRect);
+ Offset.x = childRect.left - MyRect.left;;
+ Offset.y = childRect.top - MyRect.top;
+ SendMessage(mtbi->hWindow, BUTTONDRAWINPARENT, (WPARAM)hDC, (LPARAM)&Offset);
+ }
+ }
+ pMTBInfo->lResult = 0;
+ return 1;
+
+ case WM_DESTROY:
+ xpt_FreeThemeForWindow(hwnd);
+
+ default:
+ return 0;
+ }
+
+ pMTBInfo->lResult = TRUE;
+ return 1;
+}
+
+static int ToolBar_LayeredPaintProc(HWND hWnd, HDC hDC, RECT *rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData)
+{
+ return SendMessage(hWnd, MTBM_LAYEREDPAINT,(WPARAM)hDC,0);
+}
+
+void CustomizeToolbar(HWND hwnd)
+{
+ TTBCtrlCustomize custData = { sizeof(ModernToolbarCtrl), toolbarWndProc };
+ SendMessage(hwnd, TTB_SETCUSTOM, 0, (LPARAM)&custData);
+
+ ModernToolbarCtrl* pMTBInfo = (ModernToolbarCtrl*)GetWindowLongPtr(hwnd, 0);
+
+ CLISTFrame Frame = { 0 };
+ Frame.cbSize = sizeof(Frame);
+ Frame.tname = _T("Toolbar");
+ Frame.hWnd = hwnd;
+ Frame.align = alTop;
+ Frame.Flags = F_VISIBLE | F_NOBORDER | F_LOCKED | F_TCHAR | F_NO_SUBCONTAINER;
+ Frame.height = 18;
+ pMTBInfo->hFrame = (HANDLE)CallService(MS_CLIST_FRAMES_ADDFRAME, (WPARAM)&Frame, 0);
+
+ CallService(MS_SKINENG_REGISTERPAINTSUB,(WPARAM)hwnd,(LPARAM)ToolBar_LayeredPaintProc);
+
+ pMTBInfo->mtbXPTheme = xpt_AddThemeHandle(hwnd, L"TOOLBAR");
+}
+
+static int Toolbar_ModulesLoaded(WPARAM, LPARAM)
+{
+ CallService(MS_BACKGROUNDCONFIG_REGISTER, (WPARAM)"ToolBar Background/ToolBar",0);
+ HookEvent(ME_DB_CONTACT_SETTINGCHANGED, ehhToolBarSettingsChanged);
+ HookEvent(ME_BACKGROUNDCONFIG_CHANGED, ehhToolBarBackgroundSettingsChanged);
+ HookEvent(ME_TTB_INITBUTTONS, Modern_InitButtons);
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define TTB_OPTDIR "TopToolBar"
+
+#if defined(WIN64)
+ static char szUrl[] = "http://nightly.miranda.im/x64/toptoolbar.zip";
+#else
+ static char szUrl[] = "http://nightly.miranda.im/x32/toptoolbar.zip";
+#endif
+
+static TCHAR szWarning[] = LPGENT("To view a toolbar in Clist Modern you need the TopToolBar plugin. Click Yes to download it or Cancel to continue");
+
+static void CopySettings(const char* to, const char* from)
+{
+ db_set_b(NULL, TTB_OPTDIR, to, db_get_b(NULL,"ModernToolBar",from, 0));
+}
+
+HRESULT ToolbarLoadModule()
+{
+ BYTE bOldSetting = db_get_b(NULL, "CLUI", "ShowButtonBar", 255);
+ if (bOldSetting != 255) {
+ CopySettings("BUTTWIDTH", "option_Bar0_BtnWidth");
+ CopySettings("BUTTHEIGHT", "option_Bar0_BtnHeight");
+ CopySettings("BUTTGAP", "option_Bar0_BtnSpace");
+ CopySettings("BUTTAUTOSIZE", "option_Bar0_Autosize");
+ CopySettings("BUTTMULTI", "option_Bar0_Multiline");
+
+ db_unset(NULL, "CLUI", "ShowButtonBar");
+
+ CallService(MS_DB_MODULE_DELETE, 0, (LPARAM)"ModernToolBar");
+
+ if (bOldSetting == 1)
+ if (IDYES == MessageBox(NULL, TranslateTS(szWarning), TranslateT("Toolbar upgrade"), MB_ICONQUESTION | MB_YESNO))
+ CallService(MS_UTILS_OPENURL, 0, (LPARAM)szUrl);
+ }
+
+ ehhToolBarBackgroundSettingsChanged(0,0);
+ HookEvent(ME_SYSTEM_MODULESLOADED, Toolbar_ModulesLoaded);
+ return S_OK;
+}
diff --git a/plugins/Clist_modern/src/modern_viewmodebar.cpp b/plugins/Clist_modern/src/modern_viewmodebar.cpp
new file mode 100644
index 0000000000..ed156c8496
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_viewmodebar.cpp
@@ -0,0 +1,1574 @@
+/*
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2003 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.
+
+contact list view modes (CLVM)
+
+$Id: viewmodes.c 2998 2006-06-01 07:11:52Z nightwish2004 $
+
+*/
+
+#include "hdr/modern_commonheaders.h"
+#include "m_variables.h"
+#include "hdr/modern_cluiframes.h"
+#include "m_api/m_skinbutton.h"
+
+#define TIMERID_VIEWMODEEXPIRE 100
+
+void MakeButtonSkinned(HWND hWnd);
+
+typedef int (__cdecl *pfnEnumCallback)(char *szName);
+static HWND clvmHwnd = 0;
+static int clvm_curItem = 0;
+HMENU hViewModeMenu = 0;
+
+static HWND hwndSelector = 0;
+static HIMAGELIST himlViewModes = 0;
+static HANDLE hInfoItem = 0;
+static int nullImage;
+static DWORD stickyStatusMask = 0;
+static char g_szModename[2048];
+
+static int g_ViewModeOptDlg = FALSE;
+
+static UINT _page1Controls[] = {IDC_STATIC1, IDC_STATIC2, IDC_STATIC3, IDC_STATIC5, IDC_STATIC4,
+ IDC_STATIC8, IDC_ADDVIEWMODE, IDC_DELETEVIEWMODE, IDC_NEWVIEMODE, IDC_GROUPS, IDC_PROTOCOLS,
+ IDC_VIEWMODES, IDC_STATUSMODES, IDC_STATIC12, IDC_STATIC13, IDC_STATIC14, IDC_PROTOGROUPOP, IDC_GROUPSTATUSOP,
+ IDC_AUTOCLEAR, IDC_AUTOCLEARVAL, IDC_AUTOCLEARSPIN, IDC_STATIC15, IDC_STATIC16,
+ IDC_LASTMESSAGEOP, IDC_LASTMESSAGEUNIT, IDC_LASTMSG, IDC_LASTMSGVALUE, IDC_USEGROUPS, 0};
+
+static UINT _page2Controls[] = {IDC_CLIST, IDC_STATIC9, IDC_STATIC8, IDC_CLEARALL, IDC_CURVIEWMODE2, 0};
+
+void ApplyViewMode(const char *Name, bool onlySelector = false );
+static UINT _buttons[] = {IDC_RESETMODES, IDC_SELECTMODE, IDC_CONFIGUREMODES, 0};
+
+static BOOL sttDrawViewModeBackground(HWND hwnd, HDC hdc, RECT * rect);
+static void DeleteViewMode( char * szName );
+
+static int DrawViewModeBar(HWND hWnd, HDC hDC)
+{
+ RECT rc;
+ GetClientRect(hWnd, &rc);
+ SkinDrawGlyph(hDC,&rc,&rc,"ViewMode,ID=Background");
+ return 0;
+}
+
+static int ViewModePaintCallbackProc(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData)
+{
+ int i;
+ RECT MyRect = {0};
+ GetWindowRect(hWnd,&MyRect);
+ DrawViewModeBar(hWnd,hDC);
+ for (i=0; _buttons[i] != 0; i++)
+ {
+ RECT childRect;
+ POINT Offset;
+ GetWindowRect(GetDlgItem(hWnd, _buttons[i]),&childRect);
+ Offset.x = childRect.left-MyRect.left;
+ Offset.y = childRect.top-MyRect.top;
+ SendMessage(GetDlgItem(hWnd, _buttons[i]),BUTTONDRAWINPARENT,(WPARAM)hDC,(LPARAM)&Offset);
+
+ }
+ return 0;
+}
+
+/*
+ * enumerate all view modes, call the callback function with the mode name
+ * useful for filling lists, menus and so on..
+ */
+
+int CLVM_EnumProc(const char *szSetting, LPARAM lParam)
+{
+ pfnEnumCallback EnumCallback = (pfnEnumCallback)lParam;
+ if (szSetting != NULL)
+ EnumCallback((char *)szSetting);
+ return(0);
+}
+
+void CLVM_EnumModes(pfnEnumCallback EnumCallback)
+{
+ DBCONTACTENUMSETTINGS dbces;
+ dbces.pfnEnumProc = CLVM_EnumProc;
+ dbces.szModule = CLVM_MODULE;
+ dbces.ofsSettings = 0;
+ dbces.lParam = (LPARAM)EnumCallback;
+ CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces);
+}
+
+int FillModes(char *szsetting)
+{
+ if (szsetting[0] == (char)246)
+ return 1;
+ if (szsetting[0] == (char)13)
+ return 1;
+
+ TCHAR * temp;
+ mir_utf8decode(szsetting,&temp);
+ if (temp) {
+ SendDlgItemMessage(clvmHwnd, IDC_VIEWMODES, LB_INSERTSTRING, -1, (LPARAM)temp);
+ mir_free(temp);
+ }
+
+ return 1;
+}
+
+static void ShowPage(HWND hwnd, int page)
+{
+ int i=0;
+ int pageChange = 0;
+
+ if (page == 0 && IsWindowVisible(GetDlgItem(hwnd, _page2Controls[0])))
+ pageChange = 1;
+
+ if (page == 1 && IsWindowVisible(GetDlgItem(hwnd, _page1Controls[0])))
+ pageChange = 1;
+
+ if (pageChange)
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+
+ switch(page) {
+ case 0:
+ while(_page1Controls[i] != 0)
+ ShowWindow(GetDlgItem(hwnd, _page1Controls[i++]), SW_SHOW);
+ i=0;
+ while(_page2Controls[i] != 0)
+ ShowWindow(GetDlgItem(hwnd, _page2Controls[i++]), SW_HIDE);
+ break;
+ case 1:
+ while(_page1Controls[i] != 0)
+ ShowWindow(GetDlgItem(hwnd, _page1Controls[i++]), SW_HIDE);
+ i=0;
+ while(_page2Controls[i] != 0)
+ ShowWindow(GetDlgItem(hwnd, _page2Controls[i++]), SW_SHOW);
+ break;
+ }
+ if (pageChange) {
+ SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
+ RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
+ }
+}
+
+static int UpdateClistItem(HANDLE hContact, DWORD mask)
+{
+ for (int i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++)
+ SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETEXTRAIMAGE, (WPARAM)hContact, MAKELONG(i - ID_STATUS_OFFLINE,
+ (1 << (i - ID_STATUS_OFFLINE)) & mask ? i - ID_STATUS_OFFLINE : nullImage));
+
+ return 0;
+}
+
+static DWORD GetMaskForItem(HANDLE hItem)
+{
+ DWORD dwMask = 0;
+
+ for (int i=0; i <= ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE; i++)
+ dwMask |= (SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_GETEXTRAIMAGE, (WPARAM)hItem, i) == nullImage ? 0 : 1 << i);
+
+ return dwMask;
+}
+
+static void UpdateStickies()
+{
+ DWORD localMask;
+ int i;
+ HANDLE hItem;
+
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while(hContact)
+ {
+ hItem = (HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM)hItem, (BYTE)db_get_dw(hContact, CLVM_MODULE, g_szModename, 0) ? 1 : 0);
+ localMask = HIWORD(db_get_dw(hContact, CLVM_MODULE, g_szModename, 0));
+ UpdateClistItem(hItem, (localMask == 0 || localMask == stickyStatusMask) ? stickyStatusMask : localMask);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+
+ for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++)
+ SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETEXTRAIMAGE, (WPARAM)hInfoItem, MAKELONG(i - ID_STATUS_OFFLINE, (1 << (i - ID_STATUS_OFFLINE)) & stickyStatusMask ? i - ID_STATUS_OFFLINE : ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE + 1));
+
+ hItem = (HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_GETNEXTITEM,CLGN_ROOT,0);
+ hItem = (HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST,CLM_GETNEXTITEM,CLGN_NEXTGROUP, (LPARAM)hItem);
+ while(hItem) {
+ for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++)
+ SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELONG(i - ID_STATUS_OFFLINE, nullImage));
+ hItem = (HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hItem);
+ }
+ ShowPage(clvmHwnd, 0);
+}
+
+static int FillDialog(HWND hwnd)
+{
+ LVCOLUMN lvc = {0};
+ HWND hwndList = GetDlgItem(hwnd, IDC_PROTOCOLS);
+ LVITEMA item = {0};
+ int protoCount = 0, i, newItem;
+ PROTOACCOUNT **accs;
+
+ CLVM_EnumModes(FillModes);
+ ListView_SetExtendedListViewStyle(GetDlgItem(hwnd, IDC_PROTOCOLS), LVS_EX_CHECKBOXES);
+ lvc.mask = LVCF_FMT;
+ lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT;
+ ListView_InsertColumn(GetDlgItem(hwnd, IDC_PROTOCOLS), 0, &lvc);
+
+ // fill protocols...
+ ProtoEnumAccounts( &protoCount, &accs );
+
+ item.mask = LVIF_TEXT;
+ item.iItem = 1000;
+ for (i=0; i < protoCount; i++)
+ {
+ item.pszText = accs[i]->szModuleName;
+ newItem = SendMessageA(hwndList, LVM_INSERTITEMA, 0, (LPARAM)&item);
+ }
+
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);
+ ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP);
+
+ // fill groups
+ {
+ LVITEM item = {0};
+ char buf[20];
+ DBVARIANT dbv = {0};
+
+ hwndList = GetDlgItem(hwnd, IDC_GROUPS);
+
+ ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES);
+ lvc.mask = LVCF_FMT;
+ lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT;
+ ListView_InsertColumn(hwndList, 0, &lvc);
+
+ item.mask = LVIF_TEXT;
+ item.iItem = 1000;
+
+ item.pszText = TranslateT("Ungrouped contacts");
+ newItem = SendMessage(hwndList, LVM_INSERTITEM, 0, (LPARAM)&item);
+
+ for (i=0;;i++)
+ {
+ mir_snprintf(buf, 20, "%d", i);
+ if (DBGetContactSettingTString(NULL, "CListGroups", buf, &dbv))
+ break;
+
+ item.pszText = &dbv.ptszVal[1];
+ newItem = SendMessage(hwndList, LVM_INSERTITEM, 0, (LPARAM)&item);
+ db_free(&dbv);
+ }
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);
+ ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP);
+ }
+ hwndList = GetDlgItem(hwnd, IDC_STATUSMODES);
+ ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES);
+ lvc.mask = LVCF_FMT;
+ lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT;
+ ListView_InsertColumn(hwndList, 0, &lvc);
+ for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++)
+ {
+ LVITEM item = {0};
+ item.mask = LVIF_TEXT;
+ item.pszText = TranslateTS((TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)i, GSMDF_TCHAR_MY));
+ item.iItem = i - ID_STATUS_OFFLINE;
+ newItem = SendMessage(hwndList, LVM_INSERTITEM, 0, (LPARAM)&item);
+ }
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);
+ ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP);
+
+ SendDlgItemMessage(hwnd, IDC_PROTOGROUPOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("And"));
+ SendDlgItemMessage(hwnd, IDC_PROTOGROUPOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Or"));
+ SendDlgItemMessage(hwnd, IDC_GROUPSTATUSOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("And"));
+ SendDlgItemMessage(hwnd, IDC_GROUPSTATUSOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Or"));
+
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Older than"));
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Newer than"));
+
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Minutes"));
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Hours"));
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Days"));
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEOP, CB_SETCURSEL, 0, 0);
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_SETCURSEL, 0, 0);
+ SetDlgItemInt(hwnd, IDC_LASTMSGVALUE, 0, 0);
+ return 0;
+}
+
+static void SetAllChildIcons(HWND hwndList,HANDLE hFirstItem,int iColumn,int iImage)
+{
+ int typeOfFirst,iOldIcon;
+ HANDLE hItem,hChildItem;
+
+ typeOfFirst = SendMessage(hwndList,CLM_GETITEMTYPE,(WPARAM)hFirstItem,0);
+ //check groups
+ if (typeOfFirst == CLCIT_GROUP) hItem = hFirstItem;
+ else hItem = (HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hFirstItem);
+ while(hItem)
+ {
+ hChildItem = (HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_CHILD,(LPARAM)hItem);
+ if (hChildItem)
+ SetAllChildIcons(hwndList,hChildItem,iColumn,iImage);
+ hItem = (HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hItem);
+ }
+ //check contacts
+ if (typeOfFirst == CLCIT_CONTACT) hItem = hFirstItem;
+ else hItem = (HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hFirstItem);
+ while(hItem) {
+ iOldIcon = SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn);
+ if (iOldIcon != 0xFF && iOldIcon != iImage) SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage));
+ hItem = (HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hItem);
+ }
+}
+
+static void SetIconsForColumn(HWND hwndList,HANDLE hItem,HANDLE hItemAll,int iColumn,int iImage)
+{
+ int itemType;
+
+ itemType = SendMessage(hwndList,CLM_GETITEMTYPE,(WPARAM)hItem,0);
+ if (itemType == CLCIT_CONTACT) {
+ int oldiImage = SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn);
+ if (oldiImage != 0xFF && oldiImage != iImage)
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage));
+ }
+ else if (itemType == CLCIT_INFO) {
+ int oldiImage = SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn);
+ if (oldiImage != 0xFF && oldiImage != iImage)
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage));
+ if (hItem == hItemAll)
+ SetAllChildIcons(hwndList,hItem,iColumn,iImage);
+ else
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage)); //hItemUnknown
+ }
+ else if (itemType == CLCIT_GROUP) {
+ int oldiImage = SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn);
+ if (oldiImage != 0xFF && oldiImage != iImage)
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage));
+ hItem = (HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_CHILD,(LPARAM)hItem);
+ if (hItem)
+ SetAllChildIcons(hwndList,hItem,iColumn,iImage);
+ }
+}
+
+static int DeleteAutoModesCallback(char *szsetting)
+{
+ if ( szsetting[0] == (char)13 )
+ DeleteViewMode( szsetting );
+ return 1;
+}
+
+
+void SaveViewMode(const char *name, const TCHAR *szGroupFilter, const char *szProtoFilter, DWORD statusMask, DWORD stickyStatusMask, unsigned int options,
+ unsigned int stickies, unsigned int operators, unsigned int lmdat)
+{
+ CLVM_EnumModes( DeleteAutoModesCallback );
+
+ char szSetting[512];
+ mir_snprintf(szSetting, 512, "%c%s_PF", 246, name);
+ db_set_s(NULL, CLVM_MODULE, szSetting, szProtoFilter);
+ mir_snprintf(szSetting, 512, "%c%s_GF", 246, name);
+ db_set_ws(NULL, CLVM_MODULE, szSetting, szGroupFilter);
+ mir_snprintf(szSetting, 512, "%c%s_SM", 246, name);
+ db_set_dw(NULL, CLVM_MODULE, szSetting, statusMask);
+ mir_snprintf(szSetting, 512, "%c%s_SSM", 246, name);
+ db_set_dw(NULL, CLVM_MODULE, szSetting, stickyStatusMask);
+ mir_snprintf(szSetting, 512, "%c%s_OPT", 246, name);
+ db_set_dw(NULL, CLVM_MODULE, szSetting, options);
+ mir_snprintf(szSetting, 512, "%c%s_LM", 246, name);
+ db_set_dw(NULL, CLVM_MODULE, szSetting, lmdat);
+
+ db_set_dw(NULL, CLVM_MODULE, name, MAKELONG((unsigned short)operators, (unsigned short)stickies));
+}
+
+/*
+ * saves the state of the filter definitions for the current item
+ */
+
+void SaveState()
+{
+ TCHAR newGroupFilter[2048] = _T("|");
+ char newProtoFilter[2048] = "|";
+ int i, iLen;
+ HWND hwndList;
+ TCHAR *szTempModeName = NULL;
+ char *szModeName = NULL;
+ DWORD statusMask = 0;
+ HANDLE hContact, hItem;
+ DWORD operators = 0;
+
+ if (clvm_curItem == -1)
+ return;
+
+ {
+ LVITEMA item = {0};
+ char szTemp[256];
+
+ hwndList = GetDlgItem(clvmHwnd, IDC_PROTOCOLS);
+ for (i=0; i < ListView_GetItemCount(hwndList); i++) {
+ if (ListView_GetCheckState(hwndList, i)) {
+ item.mask = LVIF_TEXT;
+ item.pszText = szTemp;
+ item.cchTextMax = 255;
+ item.iItem = i;
+ SendMessageA(hwndList, LVM_GETITEMA, 0, (LPARAM)&item);
+ strncat(newProtoFilter, szTemp, 2048);
+ strncat(newProtoFilter, "|", 2048);
+ newProtoFilter[2047] = 0;
+ }
+ }
+ }
+
+ {
+ LVITEM item = {0};
+ TCHAR szTemp[256];
+
+ hwndList = GetDlgItem(clvmHwnd, IDC_GROUPS);
+
+ operators |= ListView_GetCheckState(hwndList, 0) ? CLVM_INCLUDED_UNGROUPED : 0;
+
+ for (i=0; i < ListView_GetItemCount(hwndList); i++) {
+ if (ListView_GetCheckState(hwndList, i)) {
+ item.mask = LVIF_TEXT;
+ item.pszText = szTemp;
+ item.cchTextMax = 255;
+ item.iItem = i;
+ SendMessage(hwndList, LVM_GETITEM, 0, (LPARAM)&item);
+ _tcsncat(newGroupFilter, szTemp, 2048);
+ _tcsncat(newGroupFilter, _T("|"), 2048);
+ newGroupFilter[2047] = 0;
+ }
+ }
+ }
+ hwndList = GetDlgItem(clvmHwnd, IDC_STATUSMODES);
+ for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ if (ListView_GetCheckState(hwndList, i - ID_STATUS_OFFLINE))
+ statusMask |= (1 << (i - ID_STATUS_OFFLINE));
+ }
+ iLen = SendMessage(GetDlgItem(clvmHwnd, IDC_VIEWMODES), LB_GETTEXTLEN, clvm_curItem, 0);
+ if (iLen) {
+ unsigned int stickies = 0;
+ DWORD dwGlobalMask, dwLocalMask;
+ BOOL translated;
+
+ szTempModeName = ( TCHAR* )mir_alloc((iLen + 1)*sizeof(TCHAR));
+ if (szTempModeName)
+ {
+ DWORD options, lmdat;
+ //char *vastring = NULL;
+ //int len = GetWindowTextLengthA(GetDlgItem(clvmHwnd, IDC_VARIABLES)) + 1;
+
+ //vastring = (char *)malloc(len);
+ //if (vastring)
+ //GetDlgItemTextA(clvmHwnd, IDC_VARIABLES, vastring, len);
+ SendDlgItemMessage(clvmHwnd, IDC_VIEWMODES, LB_GETTEXT, clvm_curItem, (LPARAM)szTempModeName);
+
+ {
+ szModeName = mir_utf8encodeT(szTempModeName);
+ }
+
+ dwGlobalMask = GetMaskForItem(hInfoItem);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while(hContact)
+ {
+ hItem = (HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ {
+ if (SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM)hItem, 0))
+ {
+ dwLocalMask = GetMaskForItem(hItem);
+ db_set_dw(hContact, CLVM_MODULE, szModeName, MAKELONG(1, (unsigned short)dwLocalMask));
+ stickies++;
+ }
+ else
+ {
+ if (db_get_dw(hContact, CLVM_MODULE, szModeName, 0))
+ db_set_dw(hContact, CLVM_MODULE, szModeName, 0);
+ }
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ operators |= ((SendDlgItemMessage(clvmHwnd, IDC_PROTOGROUPOP, CB_GETCURSEL, 0, 0) == 1 ? CLVM_PROTOGROUP_OP : 0) |
+ (SendDlgItemMessage(clvmHwnd, IDC_GROUPSTATUSOP, CB_GETCURSEL, 0, 0) == 1 ? CLVM_GROUPSTATUS_OP : 0) |
+ (IsDlgButtonChecked(clvmHwnd, IDC_AUTOCLEAR) ? CLVM_AUTOCLEAR : 0) |
+ (IsDlgButtonChecked(clvmHwnd, IDC_LASTMSG) ? CLVM_USELASTMSG : 0)|
+ (IsDlgButtonChecked(clvmHwnd, IDC_USEGROUPS) == BST_CHECKED ? CLVM_USEGROUPS : 0)|
+ (IsDlgButtonChecked(clvmHwnd, IDC_USEGROUPS) == BST_UNCHECKED ? CLVM_DONOTUSEGROUPS : 0)
+ );
+
+ options = SendDlgItemMessage(clvmHwnd, IDC_AUTOCLEARSPIN, UDM_GETPOS, 0, 0);
+
+ lmdat = MAKELONG(GetDlgItemInt(clvmHwnd, IDC_LASTMSGVALUE, &translated, FALSE),
+ MAKEWORD(SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEOP, CB_GETCURSEL, 0, 0),
+ SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEUNIT, CB_GETCURSEL, 0, 0)));
+
+ SaveViewMode(szModeName, newGroupFilter, newProtoFilter, statusMask, dwGlobalMask, options,
+ stickies, operators, lmdat);
+ //free(vastring);
+ if (szModeName && szModeName != (char*)szTempModeName)
+ mir_free(szModeName);
+ mir_free(szTempModeName);
+ szTempModeName = NULL;
+ szModeName = NULL;
+ }
+ }
+ EnableWindow(GetDlgItem(clvmHwnd, IDC_APPLY), FALSE);
+}
+
+/*
+ * updates the filter list boxes with the data taken from the filtering string
+ */
+
+static void UpdateFilters()
+{
+ DBVARIANT dbv_pf = {0};
+ DBVARIANT dbv_gf = {0};
+ char szSetting[128];
+ TCHAR *szTempBuf = NULL;
+ char *szBuf = NULL;
+ int iLen;
+ DWORD statusMask = 0, localMask = 0;
+ DWORD dwFlags;
+ DWORD opt;
+ TCHAR szTemp[100];
+
+ if (clvm_curItem == LB_ERR)
+ return;
+
+ iLen = SendDlgItemMessageA(clvmHwnd, IDC_VIEWMODES, LB_GETTEXTLEN, clvm_curItem, 0);
+
+ if ( iLen == 0 )
+ return;
+
+ szTempBuf = (TCHAR *)mir_alloc((iLen + 1)*sizeof(TCHAR));
+ SendDlgItemMessage(clvmHwnd, IDC_VIEWMODES, LB_GETTEXT, clvm_curItem, (LPARAM)szTempBuf);
+
+ szBuf = mir_utf8encodeT(szTempBuf);
+ strncpy(g_szModename, szBuf, SIZEOF(g_szModename));
+ g_szModename[SIZEOF(g_szModename) - 1] = 0;
+ mir_sntprintf(szTemp, 100, TranslateT("Configuring view mode: %s"), szTempBuf);
+ SetDlgItemText(clvmHwnd, IDC_CURVIEWMODE2, szTemp);
+ mir_snprintf(szSetting, 128, "%c%s_PF", 246, szBuf);
+ if (DBGetContactSettingString(NULL, CLVM_MODULE, szSetting, &dbv_pf))
+ goto cleanup;
+ mir_snprintf(szSetting, 128, "%c%s_GF", 246, szBuf);
+ if (DBGetContactSettingTString(NULL, CLVM_MODULE, szSetting, &dbv_gf))
+ goto cleanup;
+ mir_snprintf(szSetting, 128, "%c%s_OPT", 246, szBuf);
+ if ((opt = db_get_dw(NULL, CLVM_MODULE, szSetting, -1)) != -1)
+ {
+ SendDlgItemMessage(clvmHwnd, IDC_AUTOCLEARSPIN, UDM_SETPOS, 0, MAKELONG(LOWORD(opt), 0));
+ }
+ mir_snprintf(szSetting, 128, "%c%s_SM", 246, szBuf);
+ statusMask = db_get_dw(NULL, CLVM_MODULE, szSetting, 0);
+ mir_snprintf(szSetting, 128, "%c%s_SSM", 246, szBuf);
+ stickyStatusMask = db_get_dw(NULL, CLVM_MODULE, szSetting, -1);
+ dwFlags = db_get_dw(NULL, CLVM_MODULE, szBuf, 0);
+ {
+ LVITEMA item = {0};
+ char szTemp[256];
+ char szMask[256];
+ int i;
+ HWND hwndList = GetDlgItem(clvmHwnd, IDC_PROTOCOLS);
+
+ item.mask = LVIF_TEXT;
+ item.pszText = szTemp;
+ item.cchTextMax = 255;
+
+ for (i=0; i < ListView_GetItemCount(hwndList); i++)
+ {
+ item.iItem = i;
+ SendMessageA(hwndList, LVM_GETITEMA, 0, (LPARAM)&item);
+ mir_snprintf(szMask, 256, "%s|", szTemp);
+ if (dbv_pf.pszVal && strstr(dbv_pf.pszVal, szMask))
+ ListView_SetCheckState(hwndList, i, TRUE)
+ else
+ ListView_SetCheckState(hwndList, i, FALSE);
+ }
+ }
+ {
+ LVITEM item = {0};
+ TCHAR szTemp[256];
+ TCHAR szMask[256];
+ int i;
+ HWND hwndList = GetDlgItem(clvmHwnd, IDC_GROUPS);
+
+ item.mask = LVIF_TEXT;
+ item.pszText = szTemp;
+ item.cchTextMax = 255;
+
+ ListView_SetCheckState(hwndList, 0, dwFlags & CLVM_INCLUDED_UNGROUPED ? TRUE : FALSE);
+
+ for (i = 1; i < ListView_GetItemCount(hwndList); i++)
+ {
+ item.iItem = i;
+ SendMessage(hwndList, LVM_GETITEM, 0, (LPARAM)&item);
+ _sntprintf(szMask, 256, _T("%s|"), szTemp);
+ if (dbv_gf.ptszVal && _tcsstr(dbv_gf.ptszVal, szMask))
+ ListView_SetCheckState(hwndList, i, TRUE)
+ else
+ ListView_SetCheckState(hwndList, i, FALSE);
+ }
+ }
+ {
+ HWND hwndList = GetDlgItem(clvmHwnd, IDC_STATUSMODES);
+
+ for (int i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ if ((1 << (i - ID_STATUS_OFFLINE)) & statusMask)
+ ListView_SetCheckState(hwndList, i - ID_STATUS_OFFLINE, TRUE)
+ else
+ ListView_SetCheckState(hwndList, i - ID_STATUS_OFFLINE, FALSE);
+ }
+ }
+ SendDlgItemMessage(clvmHwnd, IDC_PROTOGROUPOP, CB_SETCURSEL, dwFlags & CLVM_PROTOGROUP_OP ? 1 : 0, 0);
+ SendDlgItemMessage(clvmHwnd, IDC_GROUPSTATUSOP, CB_SETCURSEL, dwFlags & CLVM_GROUPSTATUS_OP ? 1 : 0, 0);
+ CheckDlgButton(clvmHwnd, IDC_AUTOCLEAR, dwFlags & CLVM_AUTOCLEAR ? 1 : 0);
+ UpdateStickies();
+
+ {
+ int useLastMsg = dwFlags & CLVM_USELASTMSG;
+
+ int useGroupsState = (dwFlags & CLVM_USEGROUPS) ? BST_CHECKED : (dwFlags & CLVM_DONOTUSEGROUPS) ? BST_UNCHECKED : BST_INDETERMINATE ;
+
+ DWORD lmdat;
+ BYTE bTmp;
+
+ CheckDlgButton(clvmHwnd, IDC_LASTMSG, useLastMsg);
+ CheckDlgButton(clvmHwnd, IDC_USEGROUPS, useGroupsState);
+
+ EnableWindow(GetDlgItem(clvmHwnd, IDC_LASTMESSAGEOP), useLastMsg);
+ EnableWindow(GetDlgItem(clvmHwnd, IDC_LASTMSGVALUE), useLastMsg);
+ EnableWindow(GetDlgItem(clvmHwnd, IDC_LASTMESSAGEUNIT), useLastMsg);
+
+ mir_snprintf(szSetting, 128, "%c%s_LM", 246, szBuf);
+ lmdat = db_get_dw(NULL, CLVM_MODULE, szSetting, 0);
+
+ SetDlgItemInt(clvmHwnd, IDC_LASTMSGVALUE, LOWORD(lmdat), FALSE);
+ bTmp = LOBYTE(HIWORD(lmdat));
+ SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEOP, CB_SETCURSEL, bTmp, 0);
+ bTmp = HIBYTE(HIWORD(lmdat));
+ SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEUNIT, CB_SETCURSEL, bTmp, 0);
+ }
+
+ ShowPage(clvmHwnd, 0);
+cleanup:
+ db_free(&dbv_pf);
+ db_free(&dbv_gf);
+ mir_free(szBuf);
+ mir_free(szTempBuf);
+}
+
+void DeleteViewMode( char * szName )
+{
+ char szSetting[256];
+
+ mir_snprintf(szSetting, 256, "%c%s_PF", 246, szName);
+ db_unset(NULL, CLVM_MODULE, szSetting);
+ mir_snprintf(szSetting, 256, "%c%s_GF", 246, szName);
+ db_unset(NULL, CLVM_MODULE, szSetting);
+ mir_snprintf(szSetting, 256, "%c%s_SM", 246, szName);
+ db_unset(NULL, CLVM_MODULE, szSetting);
+ mir_snprintf(szSetting, 256, "%c%s_VA", 246, szName);
+ db_unset(NULL, CLVM_MODULE, szSetting);
+ mir_snprintf(szSetting, 256, "%c%s_SSM", 246, szName);
+ db_unset(NULL, CLVM_MODULE, szSetting);
+ db_unset(NULL, CLVM_MODULE, szName);
+
+ if ( !strcmp(g_CluiData.current_viewmode, szName) && lstrlenA(szName) == lstrlenA(g_CluiData.current_viewmode)) {
+ g_CluiData.bFilterEffective = 0;
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ SetWindowText(hwndSelector, TranslateT("All contacts"));
+ }
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while(hContact)
+ {
+ if (db_get_dw(hContact, CLVM_MODULE, szName, -1) != -1)
+ db_set_dw(hContact, CLVM_MODULE, szName, 0);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+}
+
+#define IDI_SMALLDOT 211 //from miranda.exe
+INT_PTR CALLBACK DlgProcViewModesSetup(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ clvmHwnd = hwndDlg;
+
+ switch(msg) {
+ case WM_INITDIALOG:
+ {
+ int i=0;
+ TCITEM tci;
+ RECT rcClient;
+ CLCINFOITEM cii = {0};
+ HICON hIcon;
+
+ xpt_EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB);
+
+ himlViewModes = ImageList_Create(16, 16, ILC_MASK | (IsWinVerXPPlus() ? ILC_COLOR32 : ILC_COLOR16), 12, 0);
+ for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ hIcon = LoadSkinnedProtoIcon(NULL, i);
+ ImageList_AddIcon(himlViewModes, hIcon);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ }
+
+ hIcon = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_SMALLDOT), IMAGE_ICON, 16, 16, 0);
+ nullImage = ImageList_AddIcon(himlViewModes, hIcon);
+ DestroyIcon(hIcon);
+ GetClientRect(hwndDlg, &rcClient);
+
+ tci.mask = TCIF_PARAM|TCIF_TEXT;
+ tci.lParam = 0;
+ tci.pszText = TranslateT("Sticky contacts");
+ SendMessage(GetDlgItem(hwndDlg, IDC_TAB), TCM_INSERTITEM, (WPARAM)0, (LPARAM)&tci);
+
+ tci.pszText = TranslateT("Filtering");
+ SendMessage(GetDlgItem(hwndDlg, IDC_TAB), TCM_INSERTITEM, (WPARAM)0, (LPARAM)&tci);
+
+ TabCtrl_SetCurSel(GetDlgItem(hwndDlg, IDC_TAB), 0);
+
+ TranslateDialogDefault(hwndDlg);
+ FillDialog(hwndDlg);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADDVIEWMODE), FALSE);
+ {
+ LONG style = GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CLIST),GWL_STYLE);
+ style &= (~CLS_SHOWHIDDEN);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CLIST),GWL_STYLE,style);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)himlViewModes);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETEXTRACOLUMNS, ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE, 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_SETGREYOUTFLAGS,0,0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETLEFTMARGIN,2,0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETINDENT,10,0);
+ for (i=0;i <= FONTID_MAX;i++)
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETTEXTCOLOR,i,GetSysColor(COLOR_WINDOWTEXT));
+ cii.cbSize = sizeof(cii);
+ cii.hParentGroup = 0;
+ cii.pszText = TranslateT("*** All contacts ***");
+ hInfoItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_ADDINFOITEM, 0, (LPARAM)&cii);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETHIDEEMPTYGROUPS, 1, 0);
+
+ int index = 0;
+
+ if ( g_CluiData.current_viewmode[0] != '\0' )
+ {
+ TCHAR * temp = mir_utf8decodeW( g_CluiData.current_viewmode );
+
+ if (temp) {
+ index = SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_FINDSTRING, -1, (LPARAM)temp );
+ mir_free(temp);
+ }
+ if ( index == -1 )
+ index = 0;
+ }
+
+ if (SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_SETCURSEL, index, 0) != LB_ERR)
+ {
+ clvm_curItem = index;
+ UpdateFilters();
+ }
+ else
+ clvm_curItem = -1;
+ g_ViewModeOptDlg = TRUE;
+ i=0;
+ while(_page2Controls[i] != 0)
+ ShowWindow(GetDlgItem(hwndDlg, _page2Controls[i++]), SW_HIDE);
+ ShowWindow(hwndDlg, SW_SHOWNORMAL);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), FALSE);
+ //EnableWindow(GetDlgItem(hwndDlg, IDC_VARIABLES), FALSE);
+ //EnableWindow(GetDlgItem(hwndDlg, IDC_VARIABLES), ServiceExists(MS_VARS_FORMATSTRING));
+ SendDlgItemMessage(hwndDlg, IDC_AUTOCLEARSPIN, UDM_SETRANGE, 0, MAKELONG(1000, 0));
+ SetWindowText(hwndDlg, TranslateT("Configure view modes"));
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDC_PROTOGROUPOP:
+ case IDC_GROUPSTATUSOP:
+ case IDC_LASTMESSAGEUNIT:
+ case IDC_LASTMESSAGEOP:
+ if (HIWORD(wParam) == CBN_SELCHANGE)
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), TRUE);
+ break;
+ case IDC_USEGROUPS:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), TRUE);
+ break;
+ case IDC_AUTOCLEAR:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), TRUE);
+ break;
+ case IDC_LASTMSG:
+ {
+ int bUseLastMsg = IsDlgButtonChecked(hwndDlg, IDC_LASTMSG);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LASTMESSAGEOP), bUseLastMsg);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LASTMESSAGEUNIT), bUseLastMsg);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LASTMSGVALUE), bUseLastMsg);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), TRUE);
+ break;
+ }
+ case IDC_AUTOCLEARVAL:
+ case IDC_LASTMSGVALUE:
+ if (HIWORD(wParam) == EN_CHANGE && GetFocus() == (HWND)lParam)
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), TRUE);
+ break;
+ case IDC_DELETEVIEWMODE:
+ {
+ if (MessageBox(0, TranslateT("Really delete this view mode? This cannot be undone"), TranslateT("Delete a view mode"), MB_YESNO | MB_ICONQUESTION) == IDYES)
+ {
+
+ int iLen = SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETTEXTLEN, SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0), 0);
+ if (iLen)
+ {
+ //TODO: UNICODE
+ TCHAR *szTempBuf = ( TCHAR* )malloc((iLen + 1)*sizeof(TCHAR));
+ char *szBuf = NULL;
+ if (szTempBuf)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETTEXT, SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0), (LPARAM)szTempBuf);
+ szBuf = mir_utf8encodeT(szTempBuf);
+ DeleteViewMode( szBuf );
+
+ SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_DELETESTRING, SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0), 0);
+ if (SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_SETCURSEL, 0, 0) != LB_ERR)
+ {
+ clvm_curItem = 0;
+ UpdateFilters();
+ }
+ else
+ clvm_curItem = -1;
+
+ if (szBuf && szBuf != (char*)szTempBuf) mir_free(szBuf);
+ if (szTempBuf) free(szTempBuf);
+ szTempBuf = NULL;
+ szBuf = NULL;
+ }
+ }
+ }
+ break;
+ }
+ case IDC_ADDVIEWMODE:
+ {
+ TCHAR szBuf[256];
+ szBuf[0] = 0;
+ GetDlgItemText(hwndDlg, IDC_NEWVIEMODE, szBuf, 256);
+ szBuf[255] = 0;
+
+ if (lstrlen(szBuf) > 0)
+ {
+ char *szUTF8Buf = mir_utf8encodeT(szBuf);
+
+ if (db_get_dw(NULL, CLVM_MODULE, szUTF8Buf, -1) != -1)
+ MessageBox(0, TranslateT("A view mode with this name does alredy exist"), TranslateT("Duplicate name"), MB_OK);
+ else
+ {
+ int iNewItem = SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_INSERTSTRING, -1, (LPARAM)szBuf);
+ if (iNewItem != LB_ERR)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_SETCURSEL, (WPARAM)iNewItem, 0);
+ SaveViewMode(szUTF8Buf, _T(""), "", 0, -1, 0, 0, 0, 0);
+ clvm_curItem = iNewItem;
+ UpdateStickies();
+ SendDlgItemMessage(hwndDlg, IDC_PROTOGROUPOP, CB_SETCURSEL, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_GROUPSTATUSOP, CB_SETCURSEL, 0, 0);
+ }
+ }
+ SetDlgItemText(hwndDlg, IDC_NEWVIEMODE, _T(""));
+ mir_free(szUTF8Buf);
+ }
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADDVIEWMODE), FALSE);
+ UpdateFilters();
+ break;
+ }
+ case IDC_CLEARALL:
+ {
+ HANDLE hItem;
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+
+ while(hContact)
+ {
+ hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM)hItem, 0);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ }
+ case IDOK:
+ case IDC_APPLY:
+ SaveState();
+ if (g_CluiData.bFilterEffective)
+ ApplyViewMode(g_CluiData.current_viewmode);
+ if (LOWORD(wParam) == IDOK)
+ DestroyWindow(hwndDlg);
+ break;
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ if (LOWORD(wParam) == IDC_NEWVIEMODE && HIWORD(wParam) == EN_CHANGE)
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADDVIEWMODE), TRUE);
+ if (LOWORD(wParam) == IDC_VIEWMODES && HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ SaveState();
+ clvm_curItem = SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0);
+ UpdateFilters();
+ //EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), TRUE);
+ //SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ break;
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR) lParam)->idFrom) {
+ case IDC_GROUPS:
+ case IDC_STATUSMODES:
+ case IDC_PROTOCOLS:
+ case IDC_CLIST:
+ if (((LPNMHDR) lParam)->code == NM_CLICK || ((LPNMHDR) lParam)->code == CLN_CHECKCHANGED)
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), TRUE);
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case CLN_NEWCONTACT:
+ case CLN_LISTREBUILT:
+ //SetAllContactIcons(GetDlgItem(hwndDlg,IDC_CLIST));
+ //fall through
+ /*
+ case CLN_CONTACTMOVED:
+ SetListGroupIcons(GetDlgItem(hwndDlg,IDC_LIST),(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETNEXTITEM,CLGN_ROOT,0),hItemAll,NULL);
+ break;
+ case CLN_OPTIONSCHANGED:
+ ResetListOptions(GetDlgItem(hwndDlg,IDC_LIST));
+ break;
+ case CLN_CHECKCHANGED:
+ {
+ HANDLE hItem;
+ NMCLISTCONTROL *nm = (NMCLISTCONTROL*)lParam;
+ int typeOfItem = SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETITEMTYPE,(WPARAM)nm->hItem, 0);
+ break;
+ }*/
+ case NM_CLICK:
+ {
+ HANDLE hItem;
+ NMCLISTCONTROL *nm = (NMCLISTCONTROL*)lParam;
+ DWORD hitFlags;
+ int iImage;
+
+ if (nm->iColumn == -1)
+ break;
+ hItem = (HANDLE)SendDlgItemMessage(hwndDlg,IDC_CLIST,CLM_HITTEST,(WPARAM)&hitFlags,MAKELPARAM(nm->pt.x,nm->pt.y));
+ if (hItem == NULL) break;
+
+ if ( !(hitFlags&CLCHT_ONITEMEXTRA))
+ break;
+ iImage = SendDlgItemMessage(hwndDlg,IDC_CLIST,CLM_GETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(nm->iColumn,0));
+ if (iImage == nullImage)
+ iImage = nm->iColumn;
+ else if (iImage != 0xFF)
+ iImage = nullImage;
+ SetIconsForColumn(GetDlgItem(hwndDlg,IDC_CLIST),hItem,hInfoItem,nm->iColumn,iImage);
+ //SetListGroupIcons(GetDlgItem(hwndDlg,IDC_CLIST),(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETNEXTITEM,CLGN_ROOT,0),hInfoItem,NULL);
+ break;
+ }
+ }
+ break;
+ case IDC_TAB:
+ if (((LPNMHDR) lParam)->code == TCN_SELCHANGE) {
+ int id = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB));
+ if (id == 0)
+ ShowPage(hwndDlg, 0);
+ else
+ ShowPage(hwndDlg, 1);
+ break;
+ }
+
+ }
+ break;
+ }
+ case WM_DESTROY:
+ ImageList_RemoveAll(himlViewModes);
+ ImageList_Destroy(himlViewModes);
+ g_ViewModeOptDlg = FALSE;
+ break;
+ }
+ return FALSE;
+}
+
+static int menuCounter = 0;
+
+static int FillMenuCallback(char *szSetting)
+{
+ if (szSetting[0] == (char)246)
+ return 1;
+ if (szSetting[0] == (char)13)
+ return 1;
+
+ TCHAR * temp;
+ mir_utf8decode(szSetting,&temp);
+ if (temp) {
+ AppendMenu(hViewModeMenu, MFT_STRING, menuCounter++, temp);
+ mir_free(temp);
+ }
+ return 1;
+}
+
+void BuildViewModeMenu()
+{
+ if (hViewModeMenu)
+ DestroyMenu(hViewModeMenu);
+
+ menuCounter = 100;
+ hViewModeMenu = CreatePopupMenu();
+
+ AppendMenu(hViewModeMenu, MFT_STRING, 10002, TranslateT("All Contacts"));
+
+ AppendMenu(hViewModeMenu, MF_SEPARATOR, 0, NULL);
+
+ CLVM_EnumModes(FillMenuCallback);
+
+ if (GetMenuItemCount(hViewModeMenu) > 2)
+ AppendMenu(hViewModeMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(hViewModeMenu, MFT_STRING, 10001, TranslateT("Setup View Modes..."));
+}
+
+LRESULT CALLBACK ViewModeFrameWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_CREATE:
+ {
+ RECT rcMargins = {12,0,2,0};
+ hwndSelector = CreateWindow( MIRANDABUTTONCLASS, _T(""), BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP , 0, 0, 20, 20,
+ hwnd, (HMENU) IDC_SELECTMODE, g_hInst, NULL);
+ MakeButtonSkinned(hwndSelector);
+ SendMessage(hwndSelector, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Select a view mode"), BATF_TCHAR);
+ SendMessage(hwndSelector, BUTTONSETMARGINS,0 ,(LPARAM) &rcMargins);
+ SendMessage(hwndSelector, BUTTONSETID,0 ,(LPARAM) "ViewMode.Select" );
+ SendMessage(hwndSelector, WM_SETFONT,0 ,(LPARAM) FONTID_VIEMODES+1 );
+ SendMessage(hwndSelector, BUTTONSETASFLATBTN, TRUE, 0 );
+ SendMessage(hwndSelector, MBM_UPDATETRANSPARENTFLAG, 0, 2);
+ SendMessage(hwndSelector, BUTTONSETSENDONDOWN, 0 ,(LPARAM) 1 );
+
+ //SendMessage(hwndSelector, BM_SETASMENUACTION, 1, 0);
+ HWND hwndButton = CreateWindow( MIRANDABUTTONCLASS, _T(""), BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 0, 0, 20, 20,
+ hwnd, (HMENU) IDC_CONFIGUREMODES, g_hInst, NULL);
+ MakeButtonSkinned(hwndButton);
+ SendMessage(hwndButton, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Setup view modes"), BATF_TCHAR);
+ SendMessage(hwndButton, BUTTONSETID,0 ,(LPARAM) "ViewMode.Setup" );
+ SendMessage(hwndButton, BUTTONSETASFLATBTN, TRUE, 0 );
+ SendMessage(hwndButton, MBM_UPDATETRANSPARENTFLAG, 0, 2);
+
+ hwndButton = CreateWindow( MIRANDABUTTONCLASS, _T(""), BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 0, 0, 20, 20,
+ hwnd, (HMENU) IDC_RESETMODES, g_hInst, NULL);
+ MakeButtonSkinned(hwndButton);
+ SendMessage(hwndButton, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Clear view mode and return to default display"), BATF_TCHAR);
+ SendMessage(hwndButton, BUTTONSETID,0 ,(LPARAM) "ViewMode.Clear" );
+ SendMessage(hwnd, WM_USER + 100, 0, 0);
+ SendMessage(hwndButton, BUTTONSETASFLATBTN, TRUE, 0 );
+ SendMessage(hwndButton, MBM_UPDATETRANSPARENTFLAG, 0, 2);
+ return FALSE;
+ }
+ case WM_NCCALCSIZE:
+ return 18;// FrameNCCalcSize(hwnd, DefWindowProc, wParam, lParam, hasTitleBar);
+ case WM_SIZE:
+ {
+ RECT rcCLVMFrame;
+ HDWP PosBatch = BeginDeferWindowPos(3);
+ GetClientRect(hwnd, &rcCLVMFrame);
+ PosBatch = DeferWindowPos(PosBatch, GetDlgItem(hwnd, IDC_RESETMODES), 0,
+ rcCLVMFrame.right - 23, 1, 22, 18, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS);
+ PosBatch = DeferWindowPos(PosBatch, GetDlgItem(hwnd, IDC_CONFIGUREMODES), 0,
+ rcCLVMFrame.right - 45, 1, 22, 18, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS);
+ PosBatch = DeferWindowPos(PosBatch, GetDlgItem(hwnd, IDC_SELECTMODE), 0,
+ 1, 1, rcCLVMFrame.right - 46, 18, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS);
+ EndDeferWindowPos(PosBatch);
+ }
+ break;
+
+ case WM_USER + 100:
+ SendMessage(GetDlgItem(hwnd, IDC_RESETMODES), MBM_SETICOLIBHANDLE, 0,
+ (LPARAM) RegisterIcolibIconHandle("CLN_CLVM_reset", "Contact List",Translate("Reset view mode"), _T("clisticons.dll"),9, g_hInst, IDI_RESETVIEW ));
+
+ SendMessage(GetDlgItem(hwnd, IDC_CONFIGUREMODES), MBM_SETICOLIBHANDLE, 0,
+ (LPARAM) RegisterIcolibIconHandle("CLN_CLVM_set", "Contact List",Translate("Setup view modes"), _T("clisticons.dll"), 10, g_hInst, IDI_SETVIEW ));
+
+ {
+ int bSkinned = db_get_b(NULL, "CLCExt", "bskinned", 0);
+ int i=0;
+
+ while(_buttons[i] != 0) {
+ //SendMessage(GetDlgItem(hwnd, _buttons[i]), BM_SETSKINNED, 0, bSkinned);
+ if (1 && bSkinned) {
+ SendDlgItemMessage(hwnd, _buttons[i], BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwnd, _buttons[i], BUTTONSETASFLATBTN + 10, 0, 0);
+ }
+ else {
+ SendDlgItemMessage(hwnd, _buttons[i], BUTTONSETASFLATBTN, TRUE, 1);
+ SendDlgItemMessage(hwnd, _buttons[i], BUTTONSETASFLATBTN + 10, 0, 1);
+ }
+ i++;
+ }
+ }
+
+ if (g_CluiData.bFilterEffective) {
+ TCHAR * temp;
+ //temp = alloca((strlen(szSetting)+1)*sizeof(TCHAR));
+ mir_utf8decode(g_CluiData.current_viewmode,&temp);
+ if (temp) {
+ SetWindowText(GetDlgItem(hwnd, IDC_SELECTMODE), temp );
+ mir_free(temp);
+ }
+ }
+ else SetWindowText(GetDlgItem(hwnd, IDC_SELECTMODE), TranslateT("All contacts"));
+ break;
+
+ case WM_ERASEBKGND:
+ if (g_CluiData.fDisableSkinEngine)
+ return sttDrawViewModeBackground(hwnd, (HDC)wParam, NULL);
+ else
+ return 0;
+
+ case WM_NCPAINT:
+ case WM_PAINT:
+ if (GetParent(hwnd) == pcli->hwndContactList && g_CluiData.fLayered)
+ ValidateRect(hwnd,NULL);
+
+ else if (GetParent(hwnd) != pcli->hwndContactList || !g_CluiData.fLayered) {
+ HDC hdc, hdc2;
+ HBITMAP hbmp,hbmpo;
+ RECT rc = {0};
+ GetClientRect(hwnd,&rc);
+ rc.right++;
+ rc.bottom++;
+ hdc = GetDC(hwnd);
+ hdc2 = CreateCompatibleDC(hdc);
+ hbmp = ske_CreateDIB32(rc.right,rc.bottom);
+ hbmpo = (HBITMAP)SelectObject(hdc2,hbmp);
+
+ if ( g_CluiData.fDisableSkinEngine )
+ sttDrawViewModeBackground( hwnd, hdc2, &rc );
+ else {
+ if (GetParent(hwnd) != pcli->hwndContactList) {
+ HBRUSH br = GetSysColorBrush(COLOR_3DFACE);
+ FillRect(hdc2,&rc,br);
+ }
+ else ske_BltBackImage(hwnd,hdc2,&rc);
+
+ DrawViewModeBar(hwnd,hdc2);
+ }
+
+ for (int i=0; _buttons[i] != 0; i++) {
+ RECT childRect;
+ RECT MyRect;
+ POINT Offset;
+ GetWindowRect(hwnd,&MyRect);
+ GetWindowRect(GetDlgItem(hwnd, _buttons[i]),&childRect);
+ Offset.x = childRect.left-MyRect.left;;
+ Offset.y = childRect.top-MyRect.top;
+ SendMessage(GetDlgItem(hwnd, _buttons[i]),BUTTONDRAWINPARENT,(WPARAM)hdc2,(LPARAM)&Offset);
+ }
+
+ BitBlt(hdc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,hdc2,rc.left,rc.top,SRCCOPY);
+ SelectObject(hdc2,hbmpo);
+ DeleteObject(hbmp);
+ mod_DeleteDC(hdc2);
+
+ SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
+
+ ReleaseDC(hwnd,hdc);
+ ValidateRect(hwnd,NULL);
+ }
+ return 0;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR) lParam)->code == BUTTONNEEDREDRAW)
+ pcli->pfnInvalidateRect(hwnd, NULL, FALSE);
+ return 0;
+
+ case WM_TIMER:
+ if (wParam == TIMERID_VIEWMODEEXPIRE) {
+ POINT pt;
+ RECT rcCLUI;
+
+ GetWindowRect(pcli->hwndContactList, &rcCLUI);
+ GetCursorPos(&pt);
+ if (PtInRect(&rcCLUI, pt))
+ break;
+
+ KillTimer(hwnd, wParam);
+ if ( !g_CluiData.old_viewmode[0])
+ SendMessage(hwnd, WM_COMMAND, IDC_RESETMODES, 0);
+ else
+ ApplyViewMode((const char *)g_CluiData.old_viewmode);
+ }
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDC_SELECTMODE:
+ {
+ RECT rc;
+ POINT pt;
+ int selection;
+ MENUITEMINFO mii = {0};
+ TCHAR szTemp[256];
+
+ BuildViewModeMenu();
+ GetWindowRect((HWND)lParam, &rc);
+ pt.x = rc.left;
+ pt.y = rc.bottom;
+ selection = TrackPopupMenu(hViewModeMenu,TPM_RETURNCMD|TPM_TOPALIGN|TPM_LEFTALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, GetParent(hwnd), NULL);
+ PostMessage(hwnd, WM_NULL, 0, 0);
+ if (selection)
+ {
+
+ if (selection == 10001)
+ goto clvm_config_command;
+ else if (selection == 10002)
+ goto clvm_reset_command;
+
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_STRING;
+ mii.dwTypeData = szTemp;
+ mii.cch = 256;
+ GetMenuItemInfo(hViewModeMenu, selection, FALSE, &mii);
+
+ char * temp = mir_utf8encodeT(szTemp);
+ ApplyViewMode(temp);
+ if (temp)
+ mir_free(temp);
+ }
+ break;
+ }
+ case IDC_RESETMODES:
+clvm_reset_command:
+ ApplyViewMode( "" );
+ break;
+
+ case IDC_CONFIGUREMODES:
+clvm_config_command:
+ if ( !g_ViewModeOptDlg)
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_OPT_VIEWMODES), 0, DlgProcViewModesSetup, 0);
+ break;
+ }
+
+ default:
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return TRUE;
+}
+
+static HWND hCLVMFrame;
+HWND g_hwndViewModeFrame;
+
+struct view_mode_t
+{
+ HBITMAP hBmpBackground;
+ COLORREF bkColour;
+ int useWinColors;
+ int backgroundBmpUse;
+
+ view_mode_t():
+ hBmpBackground( NULL),
+ bkColour( CLCDEFAULT_BKCOLOUR ),
+ useWinColors( CLCDEFAULT_USEWINDOWSCOLOURS ),
+ backgroundBmpUse( CLCDEFAULT_USEBITMAP )
+ {}
+};
+
+static view_mode_t view_mode;
+
+static BOOL sttDrawViewModeBackground(HWND hwnd, HDC hdc, RECT * rect)
+{
+ BOOL bFloat = (GetParent(hwnd) != pcli->hwndContactList);
+ if (g_CluiData.fDisableSkinEngine || !g_CluiData.fLayered || bFloat)
+ {
+ RECT rc;
+
+ if (rect) rc = *rect;
+ else GetClientRect(hwnd,&rc);
+
+ if ( !view_mode.hBmpBackground && !view_mode.useWinColors)
+ {
+ HBRUSH hbr = CreateSolidBrush(view_mode.bkColour);
+ FillRect(hdc, &rc, hbr);
+ DeleteObject(hbr);
+ }
+ else
+ {
+ DrawBackGround(hwnd,hdc,view_mode.hBmpBackground,view_mode.bkColour,view_mode.backgroundBmpUse);
+ }
+ }
+ return TRUE;
+}
+
+COLORREF sttGetColor(char * module, char * color, COLORREF defColor); //clcutils
+
+static int ehhViewModeBackgroundSettingsChanged(WPARAM wParam, LPARAM lParam)
+{
+ if (view_mode.hBmpBackground)
+ {
+ DeleteObject(view_mode.hBmpBackground);
+ view_mode.hBmpBackground = NULL;
+ }
+ if (g_CluiData.fDisableSkinEngine)
+ {
+ DBVARIANT dbv;
+ view_mode.bkColour = sttGetColor("ViewMode","BkColour",CLCDEFAULT_BKCOLOUR);
+ if (db_get_b(NULL,"ViewMode","UseBitmap",CLCDEFAULT_USEBITMAP)) {
+ if ( !DBGetContactSettingString(NULL,"ViewMode","BkBitmap",&dbv)) {
+ view_mode.hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ }
+ view_mode.useWinColors = db_get_b(NULL, "ViewMode", "UseWinColours", CLCDEFAULT_USEWINDOWSCOLOURS);
+ view_mode.backgroundBmpUse = db_get_w(NULL, "ViewMode", "BkBmpUse", CLCDEFAULT_BKBMPUSE);
+ }
+ PostMessage(pcli->hwndContactList,WM_SIZE,0,0);
+ return 0;
+}
+
+void CreateViewModeFrame()
+{
+ CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"View Mode Background/ViewMode",0);
+ HookEvent(ME_BACKGROUNDCONFIG_CHANGED,ehhViewModeBackgroundSettingsChanged);
+ ehhViewModeBackgroundSettingsChanged(0,0);
+
+ CLISTFrame frame = {0};
+ WNDCLASS wndclass = {0};
+
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = ViewModeFrameWndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInst;
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = (HBRUSH) GetSysColorBrush(COLOR_3DFACE);
+ wndclass.lpszMenuName = 0;
+ wndclass.lpszClassName = _T("CLVMFrameWindow");
+
+ RegisterClass(&wndclass);
+
+ ZeroMemory(&frame, sizeof(frame));
+ frame.cbSize = sizeof(frame);
+ frame.tname = _T("View modes");
+ frame.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);/*0;*/
+ frame.height = 18;
+ frame.TBtname = TranslateT("View Modes");
+ frame.Flags = F_VISIBLE|F_SHOWTBTIP|F_NOBORDER|F_NO_SUBCONTAINER|F_TCHAR;
+ frame.align = alBottom;
+ frame.hWnd = CreateWindowEx(0, _T("CLVMFrameWindow"), _T(CLVM_MODULE), WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_CLIPCHILDREN, 0, 0, 20, 20, pcli->hwndContactList, (HMENU) 0, g_hInst, NULL);
+ g_hwndViewModeFrame = frame.hWnd;
+ hCLVMFrame = (HWND)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&frame,(LPARAM)0);
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)hCLVMFrame, FU_FMPOS);
+ CallService(MS_SKINENG_REGISTERPAINTSUB,(WPARAM)frame.hWnd,(LPARAM)ViewModePaintCallbackProc); //$$$$$ register sub for frame
+
+ ApplyViewMode(NULL); //Apply last selected view mode
+}
+
+const char *MakeVariablesString(const char *src, const char *UIN);
+
+void ApplyViewMode(const char *Name, bool onlySelector )
+{
+ char szSetting[256];
+ char * name = (char*)Name;
+ DBVARIANT dbv = {0};
+
+ BOOL wasNotViewMode = ( Name != NULL && g_CluiData.current_viewmode[0] == '\0' );
+
+ g_CluiData.bFilterEffective = 0;
+
+ mir_snprintf(szSetting, 256, "%c_LastMode", 246);
+
+ if ( !name) // Name is null - apply last stored view mode
+ {
+ if ( !DBGetContactSettingString(NULL, CLVM_MODULE, szSetting, &dbv))
+ {
+ name = (char*)_alloca(strlen(dbv.pszVal)+1);
+ strcpy(name,dbv.pszVal);
+ mir_free(dbv.pszVal);
+ }
+ else return;
+ }
+
+ if ( name[0] == '\0' )
+ {
+ // Reset View Mode
+ g_CluiData.bFilterEffective = 0;
+
+ { // remove last applied view mode
+ char szSetting[256];
+ mir_snprintf(szSetting, 256, "%c_LastMode", 246);
+ db_unset(NULL,CLVM_MODULE,szSetting);
+ }
+ if ( g_CluiData.bOldUseGroups != (BYTE) -1 )
+ CallService( MS_CLIST_SETUSEGROUPS, (WPARAM)g_CluiData.bOldUseGroups, 0 );
+
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ KillTimer(g_hwndViewModeFrame, TIMERID_VIEWMODEEXPIRE);
+ SetWindowText(GetDlgItem(g_hwndViewModeFrame, IDC_SELECTMODE), TranslateT("All contacts"));
+ if (g_CluiData.boldHideOffline != (BYTE)-1) CallService(MS_CLIST_SETHIDEOFFLINE, (WPARAM)g_CluiData.boldHideOffline, 0);
+ if (g_CluiData.bOldUseGroups != (BYTE)-1) CallService(MS_CLIST_SETUSEGROUPS, (WPARAM)g_CluiData.bOldUseGroups, 0);
+ g_CluiData.boldHideOffline = (BYTE)-1;
+ g_CluiData.bOldUseGroups = (BYTE) -1;
+ g_CluiData.current_viewmode[0] = 0;
+ g_CluiData.old_viewmode[0] = 0;
+ return;
+ }
+
+ if ( !onlySelector )
+ {
+ mir_snprintf(szSetting, 256, "%c%s_PF", 246, name);
+ if ( !DBGetContactSettingString(NULL, CLVM_MODULE, szSetting, &dbv)) {
+ if (lstrlenA(dbv.pszVal) >= 2)
+ {
+ strncpy(g_CluiData.protoFilter, dbv.pszVal, SIZEOF(g_CluiData.protoFilter));
+ g_CluiData.protoFilter[SIZEOF(g_CluiData.protoFilter) - 1] = 0;
+ g_CluiData.bFilterEffective |= CLVM_FILTER_PROTOS;
+ }
+ mir_free(dbv.pszVal);
+ }
+ mir_snprintf(szSetting, 256, "%c%s_GF", 246, name);
+ if ( !DBGetContactSettingTString(NULL, CLVM_MODULE, szSetting, &dbv))
+ {
+ if (lstrlen(dbv.ptszVal) >= 2)
+ {
+ _tcsncpy(g_CluiData.groupFilter, dbv.ptszVal, SIZEOF(g_CluiData.groupFilter));
+ g_CluiData.groupFilter[SIZEOF(g_CluiData.groupFilter) - 1] = 0;
+ g_CluiData.bFilterEffective |= CLVM_FILTER_GROUPS;
+ }
+ mir_free(dbv.ptszVal);
+ }
+ mir_snprintf(szSetting, 256, "%c%s_SM", 246, name);
+ g_CluiData.statusMaskFilter = db_get_dw(NULL, CLVM_MODULE, szSetting, -1);
+ if (g_CluiData.statusMaskFilter >= 1)
+ g_CluiData.bFilterEffective |= CLVM_FILTER_STATUS;
+
+ mir_snprintf(szSetting, 256, "%c%s_SSM", 246, name);
+ g_CluiData.stickyMaskFilter = db_get_dw(NULL, CLVM_MODULE, szSetting, -1);
+ if (g_CluiData.stickyMaskFilter != -1)
+ g_CluiData.bFilterEffective |= CLVM_FILTER_STICKYSTATUS;
+
+ g_CluiData.filterFlags = db_get_dw(NULL, CLVM_MODULE, name, 0);
+
+ KillTimer(g_hwndViewModeFrame, TIMERID_VIEWMODEEXPIRE);
+
+ if (g_CluiData.filterFlags & CLVM_AUTOCLEAR)
+ {
+ DWORD timerexpire;
+ mir_snprintf(szSetting, 256, "%c%s_OPT", 246, name);
+ timerexpire = LOWORD(db_get_dw(NULL, CLVM_MODULE, szSetting, 0));
+ strncpy(g_CluiData.old_viewmode, g_CluiData.current_viewmode, 256);
+ g_CluiData.old_viewmode[255] = 0;
+ CLUI_SafeSetTimer(g_hwndViewModeFrame, TIMERID_VIEWMODEEXPIRE, timerexpire * 1000, NULL);
+ }
+ else //store last selected view mode only if it is not autoclear
+ {
+ mir_snprintf(szSetting, 256, "%c_LastMode", 246);
+ db_set_s(NULL, CLVM_MODULE, szSetting, name);
+ }
+ strncpy(g_CluiData.current_viewmode, name, 256);
+ g_CluiData.current_viewmode[255] = 0;
+
+ if (g_CluiData.filterFlags & CLVM_USELASTMSG)
+ {
+ DWORD unit;
+ int i;
+ BYTE bSaved = g_CluiData.bSortByOrder[0];
+
+ g_CluiData.bSortByOrder[0] = SORTBY_LASTMSG;
+ for (i=0; i < clistCache->realCount; i++)
+ {
+ PDNCE pdnce = (PDNCE)clistCache->items[i];
+ pdnce->dwLastMsgTime = CompareContacts2_getLMTime(pdnce->hContact);
+ }
+ g_CluiData.bSortByOrder[0] = bSaved;
+
+ g_CluiData.bFilterEffective |= CLVM_FILTER_LASTMSG;
+ mir_snprintf(szSetting, 256, "%c%s_LM", 246, name);
+ g_CluiData.lastMsgFilter = db_get_dw(NULL, CLVM_MODULE, szSetting, 0);
+ if (LOBYTE(HIWORD(g_CluiData.lastMsgFilter)))
+ g_CluiData.bFilterEffective |= CLVM_FILTER_LASTMSG_NEWERTHAN;
+ else
+ g_CluiData.bFilterEffective |= CLVM_FILTER_LASTMSG_OLDERTHAN;
+ unit = LOWORD(g_CluiData.lastMsgFilter);
+ switch(HIBYTE(HIWORD(g_CluiData.lastMsgFilter))) {
+ case 0:
+ unit *= 60;
+ break;
+ case 1:
+ unit *= 3600;
+ break;
+ case 2:
+ unit *= 86400;
+ break;
+ }
+ g_CluiData.lastMsgFilter = unit;
+ }
+
+ if (HIWORD(g_CluiData.filterFlags) > 0)
+ g_CluiData.bFilterEffective |= CLVM_STICKY_CONTACTS;
+
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_STATUS)
+ {
+ if (g_CluiData.boldHideOffline == (BYTE)-1)
+ g_CluiData.boldHideOffline = db_get_b(NULL, "CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT);
+
+ CallService(MS_CLIST_SETHIDEOFFLINE, 0, 0);
+ }
+ else if ( g_CluiData.boldHideOffline != (BYTE)-1 )
+ {
+ CallService(MS_CLIST_SETHIDEOFFLINE, g_CluiData.boldHideOffline, 0);
+ g_CluiData.boldHideOffline = -1;
+ }
+
+ int bUseGroups = -1;
+
+ if (g_CluiData.filterFlags & CLVM_USEGROUPS)
+ bUseGroups = 1;
+ else if (g_CluiData.filterFlags & CLVM_DONOTUSEGROUPS)
+ bUseGroups = 0;
+
+ if (bUseGroups != -1)
+ {
+ if (g_CluiData.bOldUseGroups == (BYTE)-1)
+ g_CluiData.bOldUseGroups = db_get_b(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT);
+
+ CallService(MS_CLIST_SETUSEGROUPS, bUseGroups, 0);
+ }
+ else if (g_CluiData.bOldUseGroups != (BYTE)-1)
+ {
+ CallService(MS_CLIST_SETUSEGROUPS, g_CluiData.bOldUseGroups, 0);
+ g_CluiData.bOldUseGroups = -1;
+ }
+ }
+
+ TCHAR * temp = mir_utf8decodeW(( name[0] == (char)13 ) ? name + 1 : name );
+ SetWindowText(hwndSelector, temp);
+ mir_free(temp);
+
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ CLUI__cliInvalidateRect(pcli->hwndStatus, NULL, FALSE);
+ //SetButtonStates(pcli->hwndContactList);
+}
+
+static int SkinSetViewMode(WPARAM wParam /*char * name*/, LPARAM lParam /*int index*/)
+{
+ if (wParam == 0 && lParam == 0)
+ {
+ ApplyViewMode( NULL );
+ }
+ else
+ {
+ if (wParam && !IsBadStringPtrA((const char*)wParam, -1))
+ ApplyViewMode((const char*)wParam);
+ }
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_xptheme.cpp b/plugins/Clist_modern/src/modern_xptheme.cpp
new file mode 100644
index 0000000000..0e1e9dddde
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_xptheme.cpp
@@ -0,0 +1,265 @@
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_commonprototypes.h"
+#include "m_api/m_xpTheme.h"
+
+
+//statical
+
+typedef struct _tagXPTObject
+{
+ HANDLE hThemeHandle;
+ HWND hOwnerWindow;
+ LPCWSTR lpcwClassObject;
+} XPTObject;
+
+static SortedList * xptObjectList = NULL;
+static CRITICAL_SECTION xptCS;
+static BOOL xptModuleLoaded = FALSE;
+
+
+static HMODULE _xpt_ThemeAPIHandle = NULL; // handle to uxtheme.dll
+static HANDLE (WINAPI *_xpt_OpenThemeData)(HWND, LPCWSTR) = NULL;
+static HRESULT (WINAPI *_xpt_CloseThemeData)(HANDLE) = NULL;
+static BOOL (WINAPI *_xpt_IsThemeBackgroundPartiallyTransparent)(HANDLE, int,int) = NULL;
+static BOOL (WINAPI *_xpt_EnableThemeDialogTexture)(HANDLE, DWORD) = NULL;
+static HRESULT (WINAPI *_xpt_GetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT *prc, int eSize, SIZE *psz ) = NULL;
+static HRESULT (WINAPI *_xpt_DrawThemeParentBackground)(HWND, HDC, const RECT *) = NULL;
+static HRESULT (WINAPI *_xpt_DrawThemeBackground)(HANDLE, HDC, int, int,const RECT *, const RECT *) = NULL;
+static HRESULT (WINAPI *_xpt_DrawThemeText)(HANDLE, HDC, int, int, LPCWSTR, int,DWORD, DWORD, const RECT *) = NULL;
+
+
+#undef MGPROC
+#define MGPROC(x) GetProcAddress(_xpt_ThemeAPIHandle,x)
+
+#define xptcheck if ( !xptModuleLoaded) return
+#define xptlock() EnterCriticalSection(&xptCS)
+#define xptunlock() LeaveCriticalSection(&xptCS)
+
+static void _sttXptObjectDestructor (void * pt)
+{
+ mir_free(pt);
+}
+
+static int _xpt_ThemeSupport()
+{
+ if (IsWinVerXPPlus()) {
+ if ( !_xpt_ThemeAPIHandle) {
+ _xpt_ThemeAPIHandle = GetModuleHandleA("uxtheme");
+ if (_xpt_ThemeAPIHandle) {
+ _xpt_OpenThemeData = (HANDLE(WINAPI *)(HWND, LPCWSTR))MGPROC("OpenThemeData");
+ _xpt_CloseThemeData = (HRESULT(WINAPI *)(HANDLE))MGPROC("CloseThemeData");
+ _xpt_IsThemeBackgroundPartiallyTransparent = (BOOL(WINAPI *)(HANDLE, int, int))MGPROC("IsThemeBackgroundPartiallyTransparent");
+ _xpt_DrawThemeParentBackground = (HRESULT(WINAPI *)(HWND, HDC, const RECT *))MGPROC("DrawThemeParentBackground");
+ _xpt_DrawThemeBackground = (HRESULT(WINAPI *)(HANDLE, HDC, int, int, const RECT *, const RECT *))MGPROC("DrawThemeBackground");
+ _xpt_DrawThemeText = (HRESULT(WINAPI *)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, DWORD, const RECT *))MGPROC("DrawThemeText");
+ _xpt_GetThemePartSize = (HRESULT(WINAPI *)(HTHEME , HDC , int , int , RECT *, int , SIZE * ))MGPROC("GetThemePartSize");
+ _xpt_EnableThemeDialogTexture = (BOOL (WINAPI *)(HANDLE, DWORD)) MGPROC("EnableThemeDialogTexture");
+ }
+ }
+ // Make sure all of these methods are valid (i would hope either all or none work)
+ if (_xpt_OpenThemeData &&
+ _xpt_CloseThemeData &&
+ _xpt_IsThemeBackgroundPartiallyTransparent &&
+ _xpt_DrawThemeParentBackground &&
+ _xpt_DrawThemeBackground &&
+ _xpt_DrawThemeText &&
+ _xpt_GetThemePartSize)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void _sttXptCloseThemeData(XPTObject * xptObject)
+{
+ _xpt_CloseThemeData(xptObject->hThemeHandle);
+ xptObject->hThemeHandle = NULL;
+}
+static void _sttXptReloadThemeData(XPTObject * xptObject)
+{
+ _xpt_CloseThemeData(xptObject->hThemeHandle);
+ xptObject->hThemeHandle = _xpt_OpenThemeData(xptObject->hOwnerWindow, xptObject->lpcwClassObject);
+}
+
+
+HRESULT XPThemesLoadModule()
+{
+ if (_xpt_ThemeSupport())
+ {
+ InitializeCriticalSection(&xptCS);
+ xptObjectList = List_Create(0,1);
+ xptModuleLoaded = TRUE;
+ }
+ return S_OK;
+}
+
+void XPThemesUnloadModule()
+{
+ xptcheck;
+ xptlock();
+ xptModuleLoaded = FALSE;
+ xptunlock();
+ li_ListDestruct(xptObjectList,_sttXptObjectDestructor);
+ DeleteCriticalSection(&xptCS);
+ FreeLibrary(_xpt_ThemeAPIHandle);
+}
+
+
+BOOL xpt_IsThemed(XPTHANDLE xptHandle)
+{
+ BOOL res = FALSE;
+ xptcheck FALSE;
+ if ( !xptHandle) return FALSE;
+ xptlock();
+ {
+ if (xpt_IsValidHandle(xptHandle) && ((XPTObject*) xptHandle)->hThemeHandle)
+ res = TRUE;
+ }
+ xptunlock();
+ return res;
+}
+
+BOOL xpt_IsValidHandle(XPTHANDLE xptHandle)
+{
+ BOOL res = FALSE;
+ xptcheck FALSE;
+ if ( !xptHandle) return FALSE;
+ xptlock();
+ {
+ if (List_IndexOf(xptObjectList, (void*)xptHandle) != -1)
+ res = TRUE;
+ }
+ xptunlock();
+ return res;
+}
+
+XPTHANDLE xpt_AddThemeHandle(HWND hwnd, LPCWSTR className)
+{
+ XPTHANDLE res = NULL;
+ xptcheck NULL;
+ xptlock();
+ {
+ XPTObject* xptObject = (XPTObject*)mir_calloc(sizeof(XPTObject));
+ xptObject->lpcwClassObject = className;
+ xptObject->hOwnerWindow = hwnd;
+ _sttXptReloadThemeData(xptObject);
+ List_InsertPtr(xptObjectList, (void*)xptObject);
+ res = (XPTHANDLE)xptObject;
+ }
+ xptunlock();
+ return res;
+}
+
+void xpt_FreeThemeHandle(XPTHANDLE xptHandle)
+{
+ xptcheck;
+ xptlock();
+ if (xpt_IsValidHandle(xptHandle))
+ {
+ XPTObject* xptObject = (XPTObject*)xptHandle;
+ _sttXptCloseThemeData(xptObject);
+ _sttXptObjectDestructor((void *) xptHandle);
+ List_Remove(xptObjectList, List_IndexOf(xptObjectList,(void *) xptHandle));
+ }
+ xptunlock();
+}
+void xpt_FreeThemeForWindow(HWND hwnd)
+{
+ xptcheck;
+ xptlock();
+ {
+ int i=0;
+ while (i < xptObjectList->realCount)
+ {
+ XPTObject* xptObject = (XPTObject*)xptObjectList->items[i];
+ if (xptObject->hOwnerWindow == hwnd)
+ {
+ _sttXptCloseThemeData(xptObject);
+ _sttXptObjectDestructor((void *) xptObject);
+ List_Remove(xptObjectList, i);
+ }
+ else
+ i++;
+ }
+ }
+ xptunlock();
+}
+
+void xpt_OnWM_THEMECHANGED()
+{
+ xptcheck;
+ xptlock();
+ {
+ int i;
+ for (i=0; i < xptObjectList->realCount; i++)
+ _sttXptReloadThemeData((XPTObject*)xptObjectList->items[i]);
+ }
+ xptunlock();
+}
+HRESULT xpt_DrawThemeBackground(XPTHANDLE xptHandle, HDC hdc, int type, int state, const RECT * sizeRect, const RECT * clipRect)
+{
+ HRESULT res = S_FALSE;
+ xptcheck S_FALSE;
+ xptlock();
+ if (xpt_IsThemed(xptHandle))
+ res = _xpt_DrawThemeBackground(((XPTObject*)xptHandle)->hThemeHandle, hdc, type, state, sizeRect, clipRect);
+ xptunlock();
+ return res;
+}
+HRESULT xpt_DrawThemeParentBackground(HWND hWnd, HDC hdc, const RECT * sizeRect)
+{
+ xptcheck S_FALSE;
+ return xpt_DrawThemeParentBackground(hWnd, hdc, sizeRect);
+}
+BOOL xpt_IsThemeBackgroundPartiallyTransparent(XPTHANDLE xptHandle, int type, int state)
+{
+ BOOL res = FALSE;
+ xptcheck FALSE;
+ xptlock();
+ if (xpt_IsThemed(xptHandle))
+ res = _xpt_IsThemeBackgroundPartiallyTransparent(((XPTObject*)xptHandle)->hThemeHandle, type, state);
+ xptunlock();
+ return res;
+}
+HRESULT xpt_DrawTheme(XPTHANDLE xptHandle, HWND hwnd, HDC hdc, int type, int state, const RECT *sizeRect, const RECT * clipRect)
+{
+ HRESULT res = S_FALSE;
+ xptcheck S_FALSE;
+ xptlock();
+ if (xpt_IsThemed(xptHandle))
+ {
+ if (_xpt_IsThemeBackgroundPartiallyTransparent(((XPTObject*)xptHandle)->hThemeHandle, type, state))
+ res = _xpt_DrawThemeParentBackground(hwnd,hdc,sizeRect);
+ res = _xpt_DrawThemeBackground(((XPTObject*)xptHandle)->hThemeHandle, hdc, type, state, sizeRect, clipRect);
+ }
+ xptunlock();
+ return res;
+}
+
+HRESULT xpt_DrawThemeText(XPTHANDLE xptHandle, HDC hdc, int type, int state, LPCTSTR lpStr, int len, DWORD flag1, DWORD flag2, const RECT * textRect)
+{
+ HRESULT res = S_FALSE;
+ xptcheck S_FALSE;
+ xptlock();
+ if (xpt_IsThemed(xptHandle))
+ _xpt_DrawThemeText(((XPTObject*)xptHandle)->hThemeHandle, hdc, type, state, (LPCWSTR)lpStr, len, flag1, flag2, textRect);
+ else
+ ske_DrawText(hdc,lpStr,len, (RECT*)textRect, flag1);
+ xptunlock();
+ return S_OK;
+}
+BOOL xpt_EnableThemeDialogTexture(HWND hwnd, DWORD flags)
+{
+ BOOL res = FALSE;
+ xptcheck res;
+ xptlock();
+ res = _xpt_EnableThemeDialogTexture(hwnd, flags);
+ xptunlock();
+ return res;
+}
+//usage outside
+// add theme data
+// in WM_DESTROY - release theme data
+// in paint xpt_DrawTheme
+
diff --git a/plugins/Clist_modern/src/resource.h b/plugins/Clist_modern/src/resource.h
new file mode 100644
index 0000000000..e9e7a01b5f
--- /dev/null
+++ b/plugins/Clist_modern/src/resource.h
@@ -0,0 +1,1053 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by resource.rc
+//
+#define IDC_ALWAYS_VISIBLEICON 0
+#define IDC_APPLY 3
+#define IDI_MIRANDA 102
+#define IDD_OPT_ITEM_CONTACT_TIME 102
+#define IDI_SMS 103
+#define IDD_OPT_ROWTMPL 103
+#define IDD_OPT_CLIST 126
+#define IDD_OPT_SOUND 134
+#define IDD_OPT_HOTKEYS 134
+#define IDD_OPT_CLIST_LISTBKG 135
+#define IDI_URL 138
+#define IDI_FINDUSER 161
+#define IDI_OPTIONS 163
+#define IDI_RENAME 173
+#define IDI_DELETE 175
+#define IDR_CONTEXT 180
+#define IDC_DROP 183
+#define IDI_SENDEMAIL 193
+#define IDR_CLISTMENU 199
+#define IDI_BLANK 200
+#define IDI_NOTICK 205
+#define IDI_TICK 206
+#define IDD_OPT_ICONS 207
+#define IDI_FILE 207
+#define IDI_TIMESTAMP 208
+#define IDI_CHANGEFONT 209
+#define IDI_ADDCONTACT 210
+#define IDI_SMALLDOT 211
+#define IDI_FILLEDBLOB 212
+#define IDD_READAWAYMSG 213
+#define IDI_EMPTYBLOB 213
+#define IDD_OPT_IGNORE 214
+#define IDC_DROPUSER 215
+#define IDD_OPT_VISIBILITY 215
+#define IDD_SETAWAYMSG 216
+#define IDI_DETAILSLOGO 216
+#define IDI_HIDE_AVATAR 217
+#define IDD_OPT_AWAYMSG 217
+#define IDI_SHOW_AVATAR 218
+#define IDD_OPT_CLUI 218
+#define IDD_INFO_SUMMARY 220
+#define IDD_INFO_CONTACT 221
+#define IDD_INFO_BACKGROUND 222
+#define IDD_INFO_NOTES 223
+#define IDD_ADDEMAIL 226
+#define IDD_ICONINDEX 227
+#define IDD_OPT_CLC 228
+#define IDD_OPT_CLCTEXT 229
+#define IDD_OPT_TRAY 229
+#define IDD_INFO_LOCATION 231
+#define IDD_INFO_WORK 232
+#define IDD_ADDPHONE 233
+#define IDD_OPT_SBAR 234
+#define IDD_INSTALLINI 235
+#define IDD_WARNINICHANGE 236
+#define IDD_INIIMPORTDONE 237
+#define IDB_SORTCOLUP 239
+#define IDB_SORTCOLDOWN 240
+#define IDD_OPT_NETLIB 246
+#define IDD_NETLIBLOGOPTS 247
+#define IDD_FILETRANSFERINFO 249
+#define IDD_OPT_FILETRANSFER 250
+#define IDD_FILEEXISTS 251
+#define IDD_OPT_SKIN 251
+#define IDD_DELETECONTACT 254
+#define IDD_DENYREASON 256
+#define IDD_ADDCONTACT 257
+#define IDD_OPT_CONTACT 261
+#define IDD_OPT_PROTOCOLORDER 262
+#define IDI_MULTISEND 263
+#define IDI_DOWNARROW 264
+#define IDD_CREDITS 265
+#define IDD_OPT_IDLE 268
+#define IDD_OPT_META_CLC 279
+#define IDI_ACCMGR 281
+#define IDI_NEWGROUP 282
+#define IDI_NEWGROUP2 283
+#define IDD_MODERNOPTS 288
+#define IDI_ICON1 290
+#define IDC_DEFAULTSUB 293
+#define IDC_DROPMETA 295
+#define IDC_CURSOR1 296
+#define IDC_REGROUP 296
+#define IDI_MIRANDA2 307
+#define IDI_CLIENTICQL5 315
+#define IDI_AVATAR_OVERLAY_NA 357
+#define IDI_AVATAR_OVERLAY_OCCUPIED 358
+#define IDI_AVATAR_OVERLAY_OFFLINE 359
+#define IDI_AVATAR_OVERLAY_ONLINE 360
+#define IDI_AVATAR_OVERLAY_PHONE 361
+#define IDI_ICON9 362
+#define IDI_AVATAR_OVERLAY_AWAY 362
+#define IDI_AVATAR_OVERLAY_DND 363
+#define IDI_AVATAR_OVERLAY_INVISIBLE 364
+#define IDI_AVATAR_OVERLAY_LUNCH 365
+#define IDI_ICON4 366
+#define IDI_AVATAR_OVERLAY_CHAT 366
+#define IDI_ICQC1 367
+#define IDI_ICQC2 368
+#define IDI_ICQC3 369
+#define IDI_ICQC4 370
+#define IDI_ICQC5 371
+#define IDI_ICQC6 372
+#define IDI_ICQC7 373
+#define IDI_ICQC8 374
+#define IDD_OPT_ITEMS 385
+#define IDD_OPT_ITEM_ROW 386
+#define IDD_OPT_ITEM_AVATAR 387
+#define IDD_OPT_ITEM_ICON 388
+#define IDD_OPT_ITEM_TEXT 389
+#define IDD_OPT_ITEM_SECOND_LINE 390
+#define IDD_OPT_ITEM_THIRD_LINE 391
+#define IDI_ICON2 396
+#define IDI_ICON3 397
+#define IDD_OPT_SKINEDITOR 398
+#define IDI_STATUS_OVERLAY_NA 400
+#define IDI_STATUS_OVERLAY_OCCUPIED 401
+#define IDI_STATUS_OVERLAY_OFFLINE 402
+#define IDI_STATUS_OVERLAY_ONLINE 403
+#define IDI_STATUS_OVERLAY_PHONE 404
+#define IDI_STATUS_OVERLAY_AWAY 405
+#define IDI_STATUS_OVERLAY_DND 406
+#define IDI_STATUS_OVERLAY_INVISIBLE 407
+#define IDI_STATUS_OVERLAY_LUNCH 408
+#define IDI_STATUS_OVERLAY_CHAT 409
+#define IDR_TGA_DEFAULT_SKIN 413
+#define IDR_MSF_DEFAULT_SKIN 413
+#define IDD_SKIN_TAB 415
+#define IDI_ROWCONT1 416
+#define IDI_ROWCONT2 417
+#define IDI_ROWCONT3 418
+#define IDD_TAB 450
+#define IDD_OPT_CLUI_2 451
+#define IDI_ALWAYSVIS 453
+#define IDI_ICON6 454
+#define IDI_NEVERVIS 454
+#define IDI_ICON5 455
+#define IDI_CHAT 455
+#define IDI_LISTENING_TO 456
+#define IDD_OPT_ITEM_EXTRAICONS 461
+#define IDD_OPT_CLCBKG 462
+#define IDI_FAVORITE_0 500
+#define IDI_FAVORITE_1 501
+#define IDI_FAVORITE_2 502
+#define IDI_FAVORITE_3 503
+#define IDI_SETVIEW 504
+#define IDI_RESETVIEW 505
+#define IDD_OPT_TOOLBAR 507
+#define IDC_RESETPROTOCOLDATA 1000
+#define IDC_SAVE 1001
+#define IDC_DEFBKCOLOR 1001
+#define IDI_ONTHEPHONE 1002
+#define IDC_MESSAGE 1002
+#define IDI_OUTTOLUNCH 1003
+#define IDC_AUTOCLOSE 1004
+#define IDC_FROM 1005
+#define IDC_AUTOMIN 1005
+#define IDC_DATE 1006
+#define IDC_DUMPRECV 1006
+#define IDC_MSG 1008
+#define IDC_PROXYDNS 1008
+#define IDC_NAME 1009
+#define IDC_PROXYTYPE 1009
+#define IDC_STATIC23 1010
+#define IDC_NAMEVAL 1010
+#define IDC_SPECIFYPORTS 1013
+#define IDC_ST_ENTERMSG 1013
+#define IDC_ST_ENTERURL 1014
+#define IDC_SPECIFYPORTSO 1014
+#define IDC_TEXT 1019
+#define IDC_SHOWNAMES 1024
+#define IDC_ABOUT 1032
+#define IDC_MYNOTES 1033
+#define IDC_URLS 1037
+#define IDC_REPLY 1039
+#define IDC_URL 1041
+#define IDC_REASON 1046
+#define IDC_EMAIL 1048
+#define IDC_NAMENICK 1049
+#define IDC_NAMEFIRST 1050
+#define IDC_NAMELAST 1051
+#define IDC_NICK 1053
+#define IDC_GENDER 1060
+#define IDC_CITY 1061
+#define IDC_STATE 1062
+#define IDC_COUNTRY 1063
+#define IDC_AGE 1064
+#define IDC_ZIP 1064
+#define IDC_PHONE 1065
+#define IDC_STREET 1065
+#define IDC_COMPANY 1066
+#define IDC_LANGUAGE1 1066
+#define IDC_TIMEZONE 1067
+#define IDC_DEPARTMENT 1067
+#define IDC_LOCALTIME 1068
+#define IDC_DETAILS 1069
+#define IDC_POSITION 1069
+#define IDC_LANGUAGE2 1069
+#define IDC_ADD 1070
+#define IDC_LANGUAGE3 1070
+#define IDC_MOREOPTIONS 1071
+#define IDC_USERMENU 1071
+#define IDC_DN 1072
+#define IDC_MIN2TRAY 1073
+#define IDC_ONTOP 1074
+#define IDC_SHOWMAINMENU 1075
+#define IDC_CLIENTDRAG 1076
+#define IDC_EVENTAREA 1077
+#define IDC_EDIT 1078
+#define IDC_LIST 1079
+#define IDC_HISTORY 1080
+#define IDC_USESOUND 1085
+#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_EXTRA_PROTO 1104
+#define IDC_SORTBYPROTO 1105
+#define IDC_SHOWOPTIONS 1105
+#define IDC_EXTRA_EMAIL 1105
+#define IDC_SEARCHURL 1106
+#define IDC_EXTRA_CELLULAR 1106
+#define IDC_EXTRA_ADV2 1107
+#define IDC_BUILDTIME 1108
+#define IDC_EXTRA_ADV1 1108
+#define IDC_EXTRA_WEB 1109
+#define IDC_EXTRA_CLIENT 1110
+#define IDC_LOCKSIZING 1111
+#define IDC_CHECKKEYCOLOR 1112
+#define IDC_NUMBER 1113
+#define IDC_UIN 1123
+#define IDC_TRANSPARENT 1124
+#define IDC_TRANSINACTIVE 1126
+#define IDC_TRANSACTIVE 1128
+#define IDC_FINDWHAT 1131
+#define IDC_FIND 1132
+#define IDC_FILE 1133
+#define IDC_PROFILELIST 1134
+#define IDC_NEWPROFILE 1135
+#define IDC_NEWPROFILENAME 1136
+#define IDC_TABS 1141
+#define IDC_RESULTS 1142
+#define IDC_STATUS 1144
+#define IDC_SCREENSAVE 1145
+#define IDC_TIMED 1146
+#define IDC_AWAYTIME 1147
+#define IDC_USEPROXY 1148
+#define IDC_SETNA 1148
+#define IDC_PROXYAUTH 1149
+#define IDC_NATIME 1149
+#define IDC_PROXYHOST 1150
+#define IDC_PROXYPORT 1151
+#define IDC_PROXYUSER 1152
+#define IDC_PROXYPASS 1153
+#define IDC_STATIC11 1154
+#define IDC_STATIC12 1155
+#define IDC_STATIC21 1156
+#define IDC_STATIC22 1157
+#define IDC_STATIC31 1158
+#define IDC_STATIC24 1158
+#define IDC_STATIC32 1159
+#define IDC_PROXYAUTHNTLM 1160
+#define IDC_HKSHOWHIDE 1162
+#define IDC_HKREADMSG 1163
+#define IDC_SOUNDLIST 1163
+#define IDC_HKSEARCH 1164
+#define IDC_CHANGE 1164
+#define IDC_PREVIEW 1165
+#define IDC_HKSHOWOPTIONS 1165
+#define IDC_PLUGINLIST 1167
+#define IDC_FEATURENAME 1168
+#define IDC_CHOOSE 1169
+#define IDC_TO 1170
+#define IDC_ABOUTGROUP 1175
+#define IDC_DESCRIPTION 1176
+#define IDC_AUTHOR 1177
+#define IDC_COPYRIGHT 1178
+#define IDC_VERSION 1179
+#define IDC_HOMEPAGE 1181
+#define IDC_RESTARTREQD 1182
+#define IDC_ICONSET 1183
+#define IDC_BROWSE 1184
+#define IDC_RUNATSTARTBROWSE 1185
+#define IDC_PAGETREE 1186
+#define IDC_RUNNOW 1186
+#define IDC_INACTIVEPERC 1187
+#define IDC_ACTIVEPERC 1188
+#define IDC_SEARCHNEWWND 1188
+#define IDC_RETRIEVING 1193
+#define IDC_TITLETEXT 1196
+#define IDC_GETMORE 1200
+#define IDC_VISIBLEICON 1204
+#define IDC_INVISIBLEICON 1205
+#define IDC_FILEICON 1206
+#define IDC_ONLINEICON 1207
+#define IDC_FILENAMES 1208
+#define IDC_ALLICON 1208
+#define IDC_DONTREPLY 1209
+#define IDC_NONEICON 1209
+#define IDC_USEPREVIOUS 1210
+#define IDC_NODIALOG 1211
+#define IDC_BORDER 1211
+#define IDC_USESPECIFIC 1212
+#define IDC_NOBORDERWND 1212
+#define IDC_FILEDIR 1213
+#define IDC_BORDER2 1213
+#define IDC_ROUNDCORNERS 1213
+#define IDC_ALLFILESPROGRESS 1217
+#define IDC_CURRENTSPEED 1219
+#define IDC_STAWAYTYPE 1220
+#define IDC_WHITERECT 1221
+#define IDC_ALLSPEED 1221
+#define IDC_CURRENTFILEPROGRESS 1222
+#define IDC_CURRENTFILEGROUP 1223
+#define IDC_FIRSTNAME 1224
+#define IDC_LASTNAME 1225
+#define IDC_CURRENTTRANSFERRED 1225
+#define IDC_DOBDAY 1226
+#define IDC_DOBMONTH 1227
+#define IDC_WEBPAGE 1228
+#define IDC_DOBYEAR 1228
+#define IDC_UPDATING 1231
+#define IDC_NAMEORDER 1234
+#define IDC_AUTOHIDE 1235
+#define IDC_HIDETIME 1236
+#define IDC_FRAMESGAP 1237
+#define IDC_CAPTIONSGAP 1238
+#define IDC_RECONNECTREQD 1239
+#define IDC_HIDETIME2 1239
+#define IDC_SHOWDELAY 1239
+#define IDC_HIDEDELAY 1240
+#define IDC_IMPORT 1241
+#define IDC_HIDEDELAY2 1241
+#define IDC_TOMAIN 1243
+#define IDC_TOPROTO 1244
+#define IDC_PROTOLIST 1245
+#define IDC_TODEFICON 1246
+#define IDC_IMPORTMULTI 1247
+#define IDC_MAXSIZEHEIGHT 1254
+#define IDC_MAXSIZESPIN 1255
+#define IDC_FONTID 1256
+#define IDC_MINSIZEHEIGHT 1256
+#define IDC_SAMETYPE 1257
+#define IDC_MAXSIZESPIN2 1257
+#define IDC_MINSIZESPIN 1257
+#define IDC_SAMESTYLE 1258
+#define IDC_SAMECOLOUR 1259
+#define IDC_SAMEAS 1260
+#define IDC_TYPEFACE 1261
+#define IDC_BOLD 1262
+#define IDC_ITALIC 1263
+#define IDC_COLOUR 1264
+#define IDC_UNDERLINE 1265
+#define IDC_COLOUR_MENUNORMAL 1265
+#define IDC_NOTCHECKFONTSIZE 1266
+#define IDC_COLOUR_MENU_SELECTED 1266
+#define IDC_COLOUR_MENUSELECTED 1266
+#define IDC_EFFECT_COLOUR1 1266
+#define IDC_HOTCOLOUR 1267
+#define IDC_COLOUR_FRAMES 1267
+#define IDC_VARIABLE_ROW_HEIGHT 1267
+#define IDC_SAMESIZE 1268
+#define IDC_COLOUR_STATUSBAR 1268
+#define IDC_VARIABLE_ROW_HEIGHT2 1268
+#define IDC_BKGCOLOUR 1269
+#define IDC_VARIABLE_ROW_HEIGHT3 1269
+#define IDC_EFFECT_COLOUR2 1269
+#define IDC_TXTCOLOUR 1270
+#define IDC_SAMECOLOUR2 1270
+#define IDC_SAMEEFFECT 1270
+#define IDC_FILENAME 1271
+#define IDC_SCROLL 1277
+#define IDC_PROPORTIONAL 1278
+#define IDC_SELCOLOUR 1281
+#define IDC_QUICKCOLOUR 1282
+#define IDC_SELCOLOUR2 1282
+#define IDC_SELTXTCOLOUR 1282
+#define IDC_SMOOTHTIME 1283
+#define IDC_SMOOTHTIMESPIN 1284
+#define IDC_GREYOUT 1285
+#define IDC_ROWHEIGHT 1285
+#define IDC_ROWHEIGHTSPIN 1286
+#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_LEFTMARGINSPIN2 1294
+#define IDC_LEFTMARGIN3 1295
+#define IDC_LEFTMARGINSPIN3 1296
+#define IDC_LEFTMARGIN4 1297
+#define IDC_STRETCHH 1298
+#define IDC_STRETCHV 1299
+#define IDC_TILEH 1300
+#define IDC_SCRIPT 1300
+#define IDC_TILEV 1301
+#define IDC_EFFECT_NAME 1301
+#define IDC_GAMMACORRECT 1302
+#define IDC_TILEVROWH 1302
+#define IDC_INTERESTS 1305
+#define IDC_EMAILS 1306
+#define IDC_PAST 1307
+#define IDC_HIDEOFFLINEOPTS 1308
+#define IDC_PHONES 1308
+#define IDC_SMS 1310
+#define IDC_AREA 1312
+#define IDC_UPDATE 1313
+#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_FRAMESSPIN 1321
+#define IDC_ALWAYSMULTI 1322
+#define IDC_CAPTIONSSPIN 1322
+#define IDC_SHOWICON 1323
+#define IDC_HIDETIMESPIN2 1323
+#define IDC_ALWAYSMULTI2 1323
+#define IDC_ALWAYSPRIMARY 1323
+#define IDC_SHOWPROTO 1324
+#define IDC_HIDETIMESPIN3 1324
+#define IDC_SHOWSTATUS 1325
+#define IDC_HIDETIMESPIN4 1325
+#define IDC_EQUALSECTIONS 1326
+#define IDC_SHOWSIZEGRIP 1327
+#define IDC_SHOWXSTATUS 1327
+#define IDC_USEOWNERDRAW 1328
+#define IDC_SHOWNORMAL 1328
+#define IDC_SHOWSBAR 1329
+#define IDC_RIGHTMIRANDA 1330
+#define IDC_RIGHTSTATUS 1331
+#define IDC_SHOWNORMAL2 1332
+#define IDC_SHOWBOTH 1332
+#define IDC_ININAME 1333
+#define IDC_VIEWINI 1334
+#define IDC_SECURITYINFO 1335
+#define IDC_SHOWXSTATUSNAME 1335
+#define IDC_SETTINGNAME 1336
+#define IDC_NEWVALUE 1337
+#define IDC_WARNNOMORE 1338
+#define IDC_DELETE 1339
+#define IDC_RECYCLE 1340
+#define IDC_NEWNAME 1341
+#define IDC_MOVE 1342
+#define IDC_LEAVE 1343
+#define IDC_DISABLEENGINE 1343
+#define IDC_EXPERT 1346
+#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_STWINDOWGROUP3 1365
+#define IDC_CATEGORYLIST 1366
+#define IDC_STATIC2 1366
+#define IDC_STATIC3 1367
+#define IDC_STWINDOWGROUP2 1368
+#define IDC_LOADICONS 1369
+#define IDC_STATIC4 1369
+#define IDC_STATIC5 1370
+#define IDC_STICONSGROUP 1371
+#define IDC_STATIC6 1371
+#define IDC_STATIC7 1372
+#define IDC_STATIC8 1373
+#define IDC_STATIC9 1374
+#define IDC_MSGICON 1375
+#define IDC_STATIC10 1375
+#define IDC_URLICON 1376
+#define IDC_STATIC13 1376
+#define IDC_STNOPAGE 1377
+#define IDC_STCHECKMARKS 1380
+#define IDC_STSAMETEXT 1382
+#define IDC_STASTEXT 1383
+#define IDC_STSIZETEXT 1384
+#define IDC_STSAMETEXT2 1384
+#define IDC_STCOLOURTEXT 1385
+#define IDC_STSAMETEXT3 1385
+#define IDC_STHORZBAR 1386
+#define IDC_MIRANDA 1388
+#define IDC_STATUSBAR 1389
+#define IDC_PROTOIDGROUP 1392
+#define IDC_BYPROTOID 1393
+#define IDC_PROTOID 1394
+#define IDC_EMAILGROUP 1395
+#define IDC_BYEMAIL 1396
+#define IDC_STNAMENICK 1397
+#define IDC_NAMEGROUP 1398
+#define IDC_BYNAME 1399
+#define IDC_STNAMEFIRST 1400
+#define IDC_STNAMELAST 1401
+#define IDC_ADVANCEDGROUP 1402
+#define IDC_BYADVANCED 1403
+#define IDC_ADVANCED 1404
+#define IDC_CHECK13 1434
+#define IDC_STSIMPLERIGHT 1440
+#define IDC_NETLIBUSERS 1443
+#define IDC_STOFTENPORT 1445
+#define IDC_STATIC51 1446
+#define IDC_STATIC52 1447
+#define IDC_STATIC43 1448
+#define IDC_LOGOPTIONS 1449
+#define IDC_PORTSRANGE 1450
+#define IDC_TOCONSOLE 1451
+#define IDC_STATIC53 1451
+#define IDC_SHOWCONSOLEATSTART 1452
+#define IDC_PORTSRANGEO 1452
+#define IDC_STATIC54 1453
+#define IDC_SHOWCONSOLE 1454
+#define IDC_TOOUTPUTDEBUGSTRING 1455
+#define IDC_TOFILE 1456
+#define IDC_CLEARCONSOLE 1457
+#define IDC_RUNATSTART 1458
+#define IDC_DUMPSENT 1464
+#define IDC_DUMPPROXY 1466
+#define IDC_TEXTDUMPS 1467
+#define IDC_AUTODETECTTEXT 1468
+#define IDC_TIMEFORMAT 1469
+#define IDC_FILENAMEBROWSE 1470
+#define IDC_SHOWTHISDLGATSTART 1471
+#define IDC_FILEDIRBROWSE 1475
+#define IDC_ALLFILESGROUP 1476
+#define IDC_SCANCMDLINEBROWSE 1476
+#define IDC_ALLTRANSFERRED 1477
+#define IDC_OPENFOLDER 1478
+#define IDC_OPENFILE 1479
+#define IDC_TOTALSIZE 1480
+#define IDC_APPENDNICKTODIR 1483
+#define IDC_AUTOACCEPT 1484
+#define IDC_SCANCMDLINE 1485
+#define IDC_WARNBEFOREOPENING 1488
+#define IDC_SCANDURINGDL 1489
+#define IDC_SCANAFTERDL 1490
+#define IDC_NOSCANNER 1491
+#define IDC_ST_CMDLINE 1492
+#define IDC_ST_CMDLINEHELP 1493
+#define IDC_PROPERTIES 1496
+#define IDC_RESUME 1497
+#define IDC_EXISTINGICON 1499
+#define IDC_RESUMEALL 1500
+#define IDC_OVERWRITE 1501
+#define IDC_OVERWRITEALL 1502
+#define IDC_AVATAR_OVERLAY_ICON_CONTACT 1502
+#define IDC_SKIP 1503
+#define IDC_EXISTINGSIZE 1506
+#define IDC_EXISTINGDATE 1507
+#define IDC_EXISTINGTYPE 1508
+#define IDC_NEWICON 1509
+#define IDC_NEWSIZE 1510
+#define IDC_NEWDATE 1511
+#define IDC_NEWTYPE 1512
+#define IDC_SAVEAS 1513
+#define IDC_ASK 1516
+#define IDC_RENAME 1519
+#define IDC_VIRUSSCANNERGROUP 1520
+#define IDC_HIDE 1534
+#define IDC_TOPLINE 1535
+#define IDC_GPLBTN 1536
+#define IDC_MAIL 1536
+#define IDC_MYHANDLE 1540
+#define IDC_GROUP 1541
+#define IDC_ADDED 1542
+#define IDC_AUTH 1543
+#define IDC_PLUGINSTATIC1 1559
+#define IDC_DELETEHISTORY 1560
+#define IDC_HOTKEYURLSTR 1567
+#define IDC_SETNASTR 1568
+#define IDC_AAUTHOR 1569
+#define IDC_AHOMEPAGE 1570
+#define IDC_AVERSION 1571
+#define IDC_ACOPYRIGHT 1572
+#define IDC_ADESCRIPTION 1573
+#define IDC_PLUGINENABLE 1574
+#define IDC_AUTHREQ 1577
+#define IDC_AUTHGB 1578
+#define IDC_BRINGTOFRONT 1579
+#define IDC_PROTOCOL 1580
+#define IDC_CONTRIBLINK 1586
+#define IDC_HOMELINK 1587
+#define IDC_SUPPORTLINK 1588
+#define IDC_DEVS 1589
+#define IDC_GPL 1590
+#define IDC_LOGO 1591
+#define IDC_PROTOCOLORDER 1591
+#define IDC_PROTOCOLORDERWARNING 1592
+#define IDC_CREDITSTEXT 1595
+#define IDC_WSLOCK 1599
+#define IDC_BLINKTIME 1607
+#define IDC_BLINKSPIN 1608
+#define IDC_DISABLEBLINK 1609
+#define IDC_IDLE 1610
+#define IDC_SBPANELBEVEL 1611
+#define IDC_META 1611
+#define IDC_DROPSHADOW 1612
+#define IDC_METADBLCLK 1612
+#define IDC_NOSCROLLBAR 1613
+#define IDC_METAEXPAND 1613
+#define IDC_AEROGLASS 1613
+#define IDC_METASUBEXTRA 1614
+#define IDC_METASUBEXTRA_IGN 1615
+#define IDC_METASUB_HIDEOFFLINE 1616
+#define IDC_MIN_ROW_HEIGHT 1616
+#define IDC_MIN_ROW_HEIGHT_SPIN 1617
+#define IDC_TXT_TITLE1 1617
+#define IDC_ROW_BORDER 1618
+#define IDC_TXT_TITLE2 1618
+#define IDC_ROW_BORDER_SPIN 1619
+#define IDC_AVATAR_SIZE 1620
+#define IDC_TXT_TITLE4 1620
+#define IDC_AVATAR_SIZE_SPIN 1621
+#define IDC_ROW_BORDER2 1622
+#define IDC_AVATAR_CUSTOM_CORNER_SIZE 1622
+#define IDC_TXT_TITLE5 1622
+#define IDC_ROW_BORDER3 1623
+#define IDC_AVATAR_SIZE_SPIN2 1623
+#define IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN 1623
+#define IDC_TXT_TITLE3 1623
+#define IDC_ROW_BORDER_SPIN2 1624
+#define IDC_AVATAR_WIDTH 1624
+#define IDC_ROW_BORDER_SPIN3 1625
+#define IDC_AVATAR_SIZE_SPIN3 1625
+#define IDC_AVATAR_WIDTH_SPIN 1625
+#define IDC_BUTTON1 1633
+#define IDC_BUTTON_BROWSE 1633
+#define IDC_UP 1633
+#define IDC_BUTTON_UP 1633
+#define IDC_DOWN 1634
+#define IDC_C_SPLIT 1634
+#define IDC_PASTE 1634
+#define IDC_BUTTON4 1634
+#define IDC_BUTTON_DOWN 1634
+#define IDC_IDLECHECK 1636
+#define IDC_IDLEONWINDOWS 1637
+#define IDC_IDLEONMIRANDA 1638
+#define IDC_IDLEUSEGLI 1639
+#define IDC_SCREENSAVER 1642
+#define IDC_LOCKED 1643
+#define IDC_IDLESHORT 1644
+#define IDC_IDLELONG 1645
+#define IDC_IDLE1STTIME 1646
+#define IDC_IDLE2NDTIME 1647
+#define IDC_IDLEPRIVATE 1649
+#define IDC_AASTATUS 1650
+#define IDC_AASHORTIDLE 1651
+#define IDC_AALONGSTATUS 1652
+#define IDC_AALONGIDLE 1656
+#define IDC_NOOFFLINEMOVE 1657
+#define IDC_HOTKEYTREE 1657
+#define IDC_HILIGHTMODE 1658
+#define IDC_OFFLINETOROOT 1658
+#define IDC_HILIGHTMODE2 1659
+#define IDC_LOCATION 1659
+#define IDC_HILIGHTMODE1 1660
+#define IDC_SGROUP 1660
+#define IDC_HILIGHTMODE3 1661
+#define IDC_SLOC 1661
+#define IDC_ONDESKTOP 1662
+#define IDC_HILIGHTMODE4 1663
+#define IDC_SETHOTKEY 1759
+#define IDC_HKTITLE 1760
+#define IDC_CHECK1 1761
+#define IDC_USECONNECTINGICON 1761
+#define IDC_CHECK_METHOD 1761
+#define IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK 1761
+#define IDC_XSTATUS_HAS_PRIORITY 1761
+#define IDC_CONTLAYER 1761
+#define IDC_FRAME_META_CAPT 1762
+#define IDC_OFFSETICON 1762
+#define IDC_CHECK_COLOR 1762
+#define IDC_SHOW_STATUS_IF_NOAWAY 1762
+#define IDC_CHECK6 1762
+#define IDC_CHECK_AUTOSIZE 1762
+#define IDC_DISCOVER_AWAYMSG 1763
+#define IDC_OFFSETSPIN 1763
+#define IDC_CHECK_IMAGE 1763
+#define IDC_XSTATUS_HAS_PRIORITY2 1763
+#define IDC_USE_NAME_AND_MESSAGE 1763
+#define IDC_STATUSTEXT 1763
+#define IDC_CHECK9 1763
+#define IDC_DRAGTOSCROLL 1764
+#define IDC_OFFSETSUB 1764
+#define IDC_SUBINDENT 1764
+#define IDC_CHECK_ALPHA 1764
+#define IDC_AVATAR_DRAW_BORDER 1764
+#define IDC_OFFSETICON2 1764
+#define IDC_SHOW_STATUS_IF_NOAWAY2 1764
+#define IDC_SHOW_LISTENING_IF_NOAWAY 1764
+#define IDC_CHECK10 1764
+#define IDC_COMBO1 1765
+#define IDC_SUBINDENTSPIN 1765
+#define IDC_HIDEMETHOD 1765
+#define IDC_OFFSETSPIN2 1765
+#define IDC_ALIGNGROUPCOMBO 1765
+#define IDC_CHECK11 1765
+#define IDC_BKGRLIST 1766
+#define IDC_SUBIDENTCAPT 1766
+#define IDC_COMBO_FIT 1766
+#define IDC_OFFSETICON3 1766
+#define IDC_H_ALIGN 1766
+#define IDC_BC_STATIC 1767
+#define IDC_OBJECTSTREE 1767
+#define IDC_OFFSETSPIN3 1767
+#define IDC_REMOVE_OFFLINE_AWAYMSG 1767
+#define IDC_V_ALIGN 1767
+#define IDC_SC_STATIC 1768
+#define IDC_COMBO_SAME 1768
+#define IDC_TRANSPARENTOVERLAY 1768
+#define IDC_SHOWUNREADEMAIL 1769
+#define IDC_IDC_MULTI_COUNT 1771
+#define IDC_MULTI_COUNT 1771
+#define IDC_MULTI_SPIN 1772
+#define IDC_EDIT_FILENAME 1773
+#define IDC_EDIT_FILENAME2 1774
+#define IDC_EDIT_SKIN_FILENAME 1774
+#define IDC_OFFSETICON4 1774
+#define IDC_EDIT_LEFT 1775
+#define IDC_EDIT_RIGHT 1776
+#define IDC_EDIT_TOP 1777
+#define IDC_EDIT_BOTTOM 1778
+#define IDC_SPIN_LEFT 1779
+#define IDC_EDIT_ALPHA 1780
+#define IDC_SPIN_RIGHT 1781
+#define IDC_SPIN_TOP 1782
+#define IDC_SPIN_BOTTOM 1783
+#define IDC_SPIN_ALPHA 1784
+#define IDC_BUTTON_LOAD 1785
+#define IDC_BUTTON_SAVE 1786
+#define IDC_FRAME_GLYPH 1787
+#define IDC_BUTTON_LOAD2 1787
+#define IDC_BUTTON_APPLY_SKIN 1787
+#define IDC_STATIC_SAME 1788
+#define IDC_STATIC_MARGINS 1788
+#define IDC_FRAME_BACKGROUND 1789
+#define IDC_BUTTON_LOAD3 1789
+#define IDC_BUTTON_INFO 1789
+#define IDC_STATIC_STYLE 1790
+#define IDC_COMBO_STYLE 1791
+#define IDC_STATIC_COLOR 1792
+#define IDC_STATIC_ALPHA 1793
+#define IDC_FRAME_IMAGE 1794
+#define IDC_STATIC_LEFT 1795
+#define IDC_STATIC_RIGHT 1796
+#define IDC_STATIC_TOP 1797
+#define IDC_STATIC_BOTTOM 1798
+#define IDC_STATIC_FIT 1799
+#define IDC_STATIC_COLOR2 1800
+#define IDC_AVATAR_ROUND_CORNERS 1800
+#define IDC_STATIC_COLOR3 1801
+#define IDC_AVATAR_ALIGN_LEFT 1801
+#define IDC_DRAW_ON_AVATAR_SPACE 1801
+#define IDC_STATIC_COLOR4 1802
+#define IDC_AVATAR_OVERLAY_ICONS 1802
+#define IDC_STATIC_COLOR5 1803
+#define IDC_AVATAR_SIZE_L 1803
+#define IDC_AVATAR_SIZE_PIXELS 1804
+#define IDC_COLOUR_KEYCOLOR 1805
+#define IDC_COLOUR_KEY 1805
+#define IDC_IGNORE_SIZE 1805
+#define IDC_AVATAR_SIZE_PIXELS2 1805
+#define IDC_LIST1 1806
+#define IDC_OBJECTSLIST 1806
+#define IDC_IGNORE_SIZE2 1806
+#define IDC_ALIGN_RIGHT 1806
+#define IDC_AVATAR_SIZE_PIXELS3 1806
+#define IDC_CHECK2 1807
+#define IDC_OBJECTSLIST2 1807
+#define IDC_SKINS_LIST 1807
+#define IDC_LAYERENGINE 1807
+#define IDC_CHECK3 1808
+#define IDC_SNAPTOEDGES 1808
+#define IDC_LAYERENGINE2 1808
+#define IDC_CHECK4 1809
+#define IDC_SNAPTOEDGES2 1809
+#define IDC_DOCKTOSIDES 1809
+#define IDC_CHECK5 1810
+#define IDC_RADIO1 1811
+#define IDC_AVATAR_OVERLAY_ICON_NORMAL 1811
+#define IDC_EVENTAREA_NONE 1811
+#define IDC_RADIO2 1812
+#define IDC_AVATAR_OVERLAY_ICON_PROTOCOL 1812
+#define IDC_RADIO3 1813
+#define IDC_OVERLAY_ICON3 1813
+#define IDC_EVENTAREA_ALWAYS 1813
+#define IDC_RADIO4 1814
+#define IDC_RADIO5 1815
+#define IDC_CHECK7 1816
+#define IDC_TAB1 1816
+#define IDC_TAB 1816
+#define IDC_RADIO6 1817
+#define IDC_RADIO7 1818
+#define IDC_ALIGN_TO_LEFT 1818
+#define IDC_RADIO8 1819
+#define IDC_ALIGN_TO_RIGHT 1819
+#define IDC_CHECK8 1820
+#define IDC_LIST_ORDER 1820
+#define IDC_RADIO9 1820
+#define IDC_AVATAR_IGNORE_SIZE 1821
+#define IDC_RADIO10 1821
+#define IDC_NOTCHECKICONSIZE 1822
+#define IDC_RADIO11 1822
+#define IDC_RTL 1823
+#define IDC_RADIO12 1823
+#define IDC_REPLACE_SMILEYS 1824
+#define IDC_RADIO13 1824
+#define IDC_USE_PROTOCOL_SMILEYS 1825
+#define IDC_DRAW_SMILEYS_ON_FIRST_LINE 1826
+#define IDC_TOP_SPACE 1827
+#define IDC_RESIZE_SMILEYS 1827
+#define IDC_TOP_SPACE_SPIN 1828
+#define IDC_DRAW_SMILEYS_ON_FIRST_LINE2 1828
+#define IDC_APPEND_NICK 1828
+#define IDC_DRAW_SMILEYS 1829
+#define IDC_TRIM_TEXT 1829
+#define IDC_EMPTY 1830
+#define IDC_NICKNAME 1831
+#define IDC_STATUS_MESSAGE 1832
+#define IDC_VARIABLE_TEXT 1833
+#define IDC_DRAW_SMILEYS2 1834
+#define IDC_SHOW 1834
+#define IDC_CONTACT_TIME 1835
+#define IDC_LISTENING_TO 1836
+#define IDC_STATIC_PIXELS 1837
+#define IDC_STATIC_TEXT 1838
+#define IDC_AVATAR_BORDER_COLOR_L 1839
+#define IDC_AVATAR_BORDER_COLOR 1840
+#define IDC_VARIABLES_L 1841
+#define IDC_SHOW_ONLY_IF_DIFFERENT 1842
+#define IDC_COMBO2 1842
+#define IDC_EDIT1 1843
+#define IDC_CONTWIDTH 1843
+#define IDC_HIDE_GROUPSICON 1844
+#define IDC_STATIC_INFO 1845
+#define IDC_USEXSTATUS 1845
+#define IDC_HIDE_GROUPSICON3 1846
+#define IDC_DRAWSTATUSOVERLAY 1846
+#define IDC_DESIGNTREE 1848
+#define IDC_TYPE 1849
+#define IDC_R_SPLIT 1850
+#define IDC_PREVIEW_IMAGE 1851
+#define IDC_TITLEBAR_STATIC 1852
+#define IDC_EFFECT_COLOUR_TEXT1 1853
+#define IDC_EFFECT_COLOUR_SPIN1 1854
+#define IDC_OBJECT_TREE 1856
+#define IDC_FIT 1858
+#define IDC_E_X 1862
+#define IDC_E_Y 1863
+#define IDC_E_W 1864
+#define IDC_E_H 1865
+#define IDC_E_LEFT 1866
+#define IDC_E_TOP 1867
+#define IDC_E_RIGHT 1868
+#define IDC_E_BOTTOM 1869
+#define IDC_TREE1 1871
+#define IDC_SPIN_POSLEFT 1875
+#define IDC_SPIN_POSTOP 1876
+#define IDC_SPIN_WIDTH 1877
+#define IDC_SPIN_HEIGHT 1878
+#define IDC_GROUP_0 1879
+#define IDC_GROUP_1 1880
+#define IDC_GROUP_2 1881
+#define IDC_GROUP_3 1883
+#define IDC_COLOR 1884
+#define IDC_COPY 1885
+#define IDC_ST_COLOUR 1886
+#define IDC_ST_ALPHA 1887
+#define IDC_S_SIZE 1888
+#define IDC_EXTRAORDER 1889
+#define IDC_SKIN_TAB 1890
+#define IDC_ROWTREE 1955
+#define IDC_ADDCONTAINER 1956
+#define IDC_BUTTON2 1957
+#define IDC_DELCONTAINER 1957
+#define IDC_VALIGN 1958
+#define IDC_HALIGN 1959
+#define IDC_CONTTYPE 1960
+#define IDC_SPINCONTWIDTH 1966
+#define IDC_CONTHEIGHT 1967
+#define IDC_SPINCONTHEIGHT 1968
+#define IDC_CONTUP 1969
+#define IDC_BUTTON3 1970
+#define IDC_CONTDOWN 1970
+#define IDC_MULTI 2000
+#define IDC_MULTI_2 2001
+#define IDC_FRAMESORDER 2002
+#define IDC_USEWINCOL 2004
+#define IDC_MINIMODE 2005
+#define IDC_BTNORDER 2006
+#define IDC_TBSHOW 2007
+#define IDC_STATIC_W 2008
+#define IDC_STATIC_H 2009
+#define IDC_STATIC_S 2010
+#define IDC_TEXT_W 2011
+#define IDC_TEXT_H 2012
+#define IDC_TEXT_S 2013
+#define IDC_SPIN_W 2014
+#define IDC_SPIN_H 2015
+#define IDC_SPIN_S 2016
+#define IDC_CHECK_MULTILINE 2017
+#define IDC_CHECK_ATOSIZE 2018
+#define IDC_SBAR_HORIZ_ALIGN 2019
+#define IDC_SBAR_TOP_BORDER 2020
+#define IDC_SBAR_BOTTOM_BORDER 2021
+#define IDC_STATUSBAR_PER_PROTO 2022
+#define IDC_OFFSETICON_RIGHT 2023
+#define IDC_OFFSETSPIN_RIGHT 2024
+#define IDC_OFFSETICON_LEFT 2025
+#define IDC_OFFSETSPIN_LEFT 2026
+#define IDC_STATUSBAR_PROTO_LIST 2027
+#define IDC_SBAR_USE_ACCOUNT_SETTINGS 2028
+#define IDC_SBAR_HIDE_ACCOUNT_COMPLETELY 2029
+#define IDC_SBAR_BORDER_TOP 2030
+#define IDC_SBAR_BORDER_TOP_SPIN 2031
+#define IDC_SBAR_BORDER_BOTTOM 2032
+#define IDC_SBAR_BORDER_BOTTOM_SPIN 2033
+#define IDC_SBAR_VERT_ALIGN 2034
+#define IDC_CLSORT1 6666
+#define IDC_CLSORT2 6667
+#define IDC_CLSORT3 6668
+#define IDC_WINCOLOUR 6669
+#define IDD_OPT_CLCBKG3 11268
+#define IDD_OPT_EXTFRAMES 11269
+#define IDC_MENUITEMS 11710
+#define IDC_MENUOBJECTS 11711
+#define IDC_NOTSUPPORTWARNING 11712
+#define IDC_INSERTSEPARATOR 11715
+#define IDC_GENMENU_SERVICE 11716
+#define IDC_GENMENU_CUSTOMNAME 11717
+#define IDC_GENMENU_SET 11718
+#define IDC_GENMENU_SET2 11719
+#define IDC_GENMENU_DEFAULT 11719
+#define IDC_ICONBLINK 11720
+#define IDC_ICONBLINK2 11721
+#define IDC_SHOW_AVATARS 11721
+#define IDC_SHOW_AVATARS2 11722
+#define IDC_SHOW_ANIAVATARS 11722
+#define IDC_SHOW_STATUSMSG 11723
+#define IDC_HIDE_ICON_ON_AVATAR 11723
+#define IDC_SHOW_ANIAVATARS2 11723
+#define IDC_AVATAR_FASTDRAW 11723
+#define IDC_SHOW_STATUSMSG2 11724
+#define IDC_SHOW_STATUS_MSG 11724
+#define IDC_SUBIDENTCAPT2 11767
+#define IDC_SUBIDENTCAPT3 11768
+#define IDC_SUBIDENTCAPT4 11769
+#define IDC_RIGHTMARGIN 11800
+#define IDC_TOPMARGIN 11801
+#define IDC_BOTTOMMARGIN 11802
+#define IDC_RIGHTMARGINSPIN 11803
+#define IDC_EFFECT_COLOUR_TEXT2 11803
+#define IDC_TOPMARGINSPIN 11804
+#define IDC_BOTTOMMARGINSPIN 11805
+#define IDC_EFFECT_COLOUR_SPIN2 11806
+#define IDC_LEFTMARGIN2 12931
+#define IDC_LEFTMARGINSPIN4 12981
+#define IDD_OPT_VIEWMODES 19100
+#define IDC_VIEWMODES 19102
+#define IDC_PROTOCOLS 19103
+#define IDC_ADDVIEWMODE 19104
+#define IDC_DELETEVIEWMODE 19105
+#define IDC_NEWVIEMODE 19106
+#define IDC_GROUPS 19107
+#define IDC_STATUSMODES 19108
+#define IDC_CLIST 19109
+#define IDC_CLEARALL 19110
+#define IDC_PROTOGROUPOP 19111
+#define IDC_GROUPSTATUSOP 19112
+#define IDC_STATIC14 19113
+#define IDC_AUTOCLEAR 19114
+#define IDC_AUTOCLEARVAL 19115
+#define IDC_AUTOCLEARSPIN 19116
+#define IDC_STATIC15 19117
+#define IDC_STATIC16 19118
+#define IDC_CURVIEWMODE2 19119
+#define IDC_LASTMSG 19120
+#define IDC_LASTMESSAGEOP 19121
+#define IDC_LASTMSGVALUE 19122
+#define IDC_LASTMESSAGEUNIT 19123
+#define IDC_STATIC1 19124
+#define IDC_RESETMODES 19125
+#define IDC_LASTMSG2 19125
+#define IDC_SELECTMODE 19126
+#define IDC_CONFIGUREMODES 19127
+#define IDC_USEGROUPS 19128
+#define IDI_SEARCHALL 32548
+#define ID_ICQ_EXIT 40001
+#define IDM_COPY 40001
+#define ID_RESET 40002
+#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 IDC_SENDMESSAGE 40009
+#define IDM_COPYALL 40011
+#define IDM_SELECTALL 40012
+#define IDM_CLEAR 40013
+#define IDM_OPENNEW 40014
+#define IDM_OPENEXISTING 40015
+#define IDM_COPYLINK 40016
+#define POPUP_HIDEMIRANDA 40017
+#define POPUP_GROUPSHOWOFFLINE 40019
+#define ID_MINIMIZE 40021
+#define ID_TRAY_HIDE 40038
+#define ID_TRAY_EXIT 40040
+#define POPUP_NEWGROUP 40050
+#define POPUP_RENAMEGROUP 40052
+#define POPUP_DELETEGROUP 40053
+#define IDC_FRAME_META 40054
+#define IDC_FRAME_META2 40055
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 509
+#define _APS_NEXT_COMMAND_VALUE 40022
+#define _APS_NEXT_CONTROL_VALUE 2024
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/Clist_modern/src/version.h b/plugins/Clist_modern/src/version.h
new file mode 100644
index 0000000000..73152f4f57
--- /dev/null
+++ b/plugins/Clist_modern/src/version.h
@@ -0,0 +1,15 @@
+#define BUILD_NUM 11
+#define BUILD_NUM_STR "11"
+
+#define COREVERSION_NUM 0, 9, 0,
+#define COREVERSION_NUM_STR "0, 9, 0 "
+
+#define MINIMAL_COREVERSION_NUM PLUGIN_MAKE_VERSION(0, 9, 0, 0)
+#define MINIMAL_COREVERSION 0, 9, 0, 0
+#define MINIMAL_COREVERSION_STR "0, 9, 0, 0 "
+
+#define FILE_VERSION COREVERSION_NUM BUILD_NUM
+#define FILE_VERSION_STR COREVERSION_NUM_STR " build " BUILD_NUM_STR " "
+
+#define PRODUCT_VERSION FILE_VERSION
+#define PRODUCT_VERSION_STR FILE_VERSION_STR