summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Volinsky <mataes2007@gmail.com>2012-05-17 17:37:22 +0000
committerKirill Volinsky <mataes2007@gmail.com>2012-05-17 17:37:22 +0000
commit78d71d2cad6f243c6ff31d41380b8c5b58407de5 (patch)
treed0c05983b315352c5e66d23420da4b8fd8b5aff4
parenta9e8daee448c229aa3f8ded0c5f5c0fe7aa42529 (diff)
added some plugins
git-svn-id: http://svn.miranda-ng.org/main/trunk@20 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
-rw-r--r--plugins/Autorun/autorun.h14
-rw-r--r--plugins/Autorun/autorun.rc83
-rw-r--r--plugins/Autorun/autorun.sln26
-rw-r--r--plugins/Autorun/autorun.txt50
-rw-r--r--plugins/Autorun/autorun.vcxproj230
-rw-r--r--plugins/Autorun/autorun.vcxproj.filters40
-rw-r--r--plugins/Autorun/main.c165
-rw-r--r--plugins/Autorun/resource.h15
-rw-r--r--plugins/Boltun/Boltun.rc155
-rw-r--r--plugins/Boltun/Boltun2.gifbin0 -> 13171 bytes
-rw-r--r--plugins/Boltun/Boltun_10.sln19
-rw-r--r--plugins/Boltun/Boltun_10.vcxproj197
-rw-r--r--plugins/Boltun/Boltun_10.vcxproj.filters110
-rw-r--r--plugins/Boltun/Engine/COPYING.txt339
-rw-r--r--plugins/Boltun/Engine/CriticalSection.h56
-rw-r--r--plugins/Boltun/Engine/Mind.cpp448
-rw-r--r--plugins/Boltun/Engine/Mind.h89
-rw-r--r--plugins/Boltun/Engine/MyCodeCvt.cpp85
-rw-r--r--plugins/Boltun/Engine/MyCodeCvt.h59
-rw-r--r--plugins/Boltun/Engine/PerContactData.h173
-rw-r--r--plugins/Boltun/Engine/TalkEngine.cpp609
-rw-r--r--plugins/Boltun/Engine/TalkEngine.h112
-rw-r--r--plugins/Boltun/Engine/UnrecentChooser.cpp100
-rw-r--r--plugins/Boltun/Engine/UnrecentChooser.h47
-rw-r--r--plugins/Boltun/Engine/ValueChooser.h88
-rw-r--r--plugins/Boltun/Engine/WordsList.cpp169
-rw-r--r--plugins/Boltun/Engine/WordsList.h56
-rw-r--r--plugins/Boltun/Engine/boltun.mindwbin0 -> 342176 bytes
-rw-r--r--plugins/Boltun/Engine/tstring.h34
-rw-r--r--plugins/Boltun/TODO.txt35
-rw-r--r--plugins/Boltun/actionQueue.cpp256
-rw-r--r--plugins/Boltun/actionQueue.h30
-rw-r--r--plugins/Boltun/boltun.cpp718
-rw-r--r--plugins/Boltun/boltun.h80
-rw-r--r--plugins/Boltun/config.cpp159
-rw-r--r--plugins/Boltun/config.h157
-rw-r--r--plugins/Boltun/lang_pack.txt64
-rw-r--r--plugins/Boltun/mind.txt142
-rw-r--r--plugins/Boltun/readme.txt124
-rw-r--r--plugins/Boltun/res/boltun.icobin0 -> 766 bytes
-rw-r--r--plugins/Boltun/res/smiles.datbin0 -> 3394 bytes
-rw-r--r--plugins/Boltun/resource.h46
-rw-r--r--plugins/CountryFlags/Info_Src.txt32
-rw-r--r--plugins/CountryFlags/License_Appendix.txt64
-rw-r--r--plugins/CountryFlags/countrylistext.c345
-rw-r--r--plugins/CountryFlags/docs/Flags-Developer.txt48
-rw-r--r--plugins/CountryFlags/docs/Flags-License.txt278
-rw-r--r--plugins/CountryFlags/docs/Flags-Readme.txt140
-rw-r--r--plugins/CountryFlags/docs/Flags-Translation.txt74
-rw-r--r--plugins/CountryFlags/extraimg.c495
-rw-r--r--plugins/CountryFlags/flags.def11
-rw-r--r--plugins/CountryFlags/flags.h89
-rw-r--r--plugins/CountryFlags/flags.sln29
-rw-r--r--plugins/CountryFlags/flags.vcxproj408
-rw-r--r--plugins/CountryFlags/flags.vcxproj.filters138
-rw-r--r--plugins/CountryFlags/huffman.c506
-rw-r--r--plugins/CountryFlags/icons.c284
-rw-r--r--plugins/CountryFlags/ip2country.c327
-rw-r--r--plugins/CountryFlags/main.c163
-rw-r--r--plugins/CountryFlags/res/flags.bmpbin0 -> 122022 bytes
-rw-r--r--plugins/CountryFlags/res/ip-to-country.binbin0 -> 647987 bytes
-rw-r--r--plugins/CountryFlags/resource.h25
-rw-r--r--plugins/CountryFlags/resource.rc128
-rw-r--r--plugins/CountryFlags/utils.c162
-rw-r--r--plugins/CountryFlags/version.h38
-rw-r--r--plugins/CountryFlags/version.rc47
-rw-r--r--plugins/FavContacts/favcontacts.sln19
-rw-r--r--plugins/FavContacts/favcontacts.vcxproj131
-rw-r--r--plugins/FavContacts/favcontacts.vcxproj.filters76
-rw-r--r--plugins/FavContacts/res/favlist.icobin0 -> 2550 bytes
-rw-r--r--plugins/FavContacts/res/favorite.icobin0 -> 2550 bytes
-rw-r--r--plugins/FavContacts/res/regular.icobin0 -> 2550 bytes
-rw-r--r--plugins/FavContacts/res/userprefs.icobin0 -> 2550 bytes
-rw-r--r--plugins/FavContacts/resource.h39
-rw-r--r--plugins/FavContacts/resource.rc166
-rw-r--r--plugins/FavContacts/src/contact_cache.cpp231
-rw-r--r--plugins/FavContacts/src/contact_cache.h61
-rw-r--r--plugins/FavContacts/src/cserver.cpp82
-rw-r--r--plugins/FavContacts/src/cserver.h42
-rw-r--r--plugins/FavContacts/src/csocket.cpp22
-rw-r--r--plugins/FavContacts/src/csocket.h16
-rw-r--r--plugins/FavContacts/src/favlist.cpp0
-rw-r--r--plugins/FavContacts/src/favlist.h134
-rw-r--r--plugins/FavContacts/src/headers.h94
-rw-r--r--plugins/FavContacts/src/http_api.cpp165
-rw-r--r--plugins/FavContacts/src/http_api.h7
-rw-r--r--plugins/FavContacts/src/main.cpp1453
-rw-r--r--plugins/FloatingContacts/FltCont_10.sln26
-rw-r--r--plugins/FloatingContacts/FltCont_10.vcxproj254
-rw-r--r--plugins/FloatingContacts/FltCont_10.vcxproj.filters76
-rw-r--r--plugins/FloatingContacts/Script.rc2
-rw-r--r--plugins/FloatingContacts/bitmap_funcs.cpp1239
-rw-r--r--plugins/FloatingContacts/bitmap_funcs.h127
-rw-r--r--plugins/FloatingContacts/docs/fltcontacts_langpack.txt68
-rw-r--r--plugins/FloatingContacts/docs/fltcontacts_readme.txt91
-rw-r--r--plugins/FloatingContacts/docs/fltcontacts_russian_langpack.txt70
-rw-r--r--plugins/FloatingContacts/filedrop.cpp368
-rw-r--r--plugins/FloatingContacts/filedrop.h26
-rw-r--r--plugins/FloatingContacts/fltcnt.rc232
-rw-r--r--plugins/FloatingContacts/fltcont.h191
-rw-r--r--plugins/FloatingContacts/hide.icobin0 -> 2550 bytes
-rw-r--r--plugins/FloatingContacts/main.cpp1331
-rw-r--r--plugins/FloatingContacts/options.cpp1179
-rw-r--r--plugins/FloatingContacts/resource.h75
-rw-r--r--plugins/FloatingContacts/show.icobin0 -> 2550 bytes
-rw-r--r--plugins/FloatingContacts/stdhdr.h64
-rw-r--r--plugins/FloatingContacts/thumbs.cpp1013
-rw-r--r--plugins/FloatingContacts/thumbs.h74
-rw-r--r--plugins/FloatingContacts/version.h29
-rw-r--r--plugins/FloatingContacts/version.rc36
-rw-r--r--plugins/Gender/commonheaders.h63
-rw-r--r--plugins/Gender/docs/gender-readme.txt62
-rw-r--r--plugins/Gender/docs/gender-translate.txt24
-rw-r--r--plugins/Gender/gender.rc129
-rw-r--r--plugins/Gender/gender_10.sln31
-rw-r--r--plugins/Gender/gender_10.vcxproj263
-rw-r--r--plugins/Gender/icons/female.icobin0 -> 2550 bytes
-rw-r--r--plugins/Gender/icons/gender.icobin0 -> 2550 bytes
-rw-r--r--plugins/Gender/icons/male.icobin0 -> 2550 bytes
-rw-r--r--plugins/Gender/main.cpp474
-rw-r--r--plugins/Gender/options.cpp167
-rw-r--r--plugins/Gender/resource.h25
-rw-r--r--plugins/ProfileManager/pmanagerEx.c109
-rw-r--r--plugins/ProfileManager/pmanagerEx.vcproj247
-rw-r--r--plugins/ProfileManager/res/ChangePM.icobin0 -> 1150 bytes
-rw-r--r--plugins/ProfileManager/res/LoadPM.icobin0 -> 1150 bytes
-rw-r--r--plugins/ProfileManager/resource.h17
-rw-r--r--plugins/ProfileManager/resource.rc46
-rw-r--r--plugins/Rate/commonheaders.h78
-rw-r--r--plugins/Rate/docs/Rate-readme.txt49
-rw-r--r--plugins/Rate/docs/rate.txt1
-rw-r--r--plugins/Rate/icons/rate_high.icobin0 -> 1150 bytes
-rw-r--r--plugins/Rate/icons/rate_low.icobin0 -> 1150 bytes
-rw-r--r--plugins/Rate/icons/rate_med.icobin0 -> 1150 bytes
-rw-r--r--plugins/Rate/main.cpp289
-rw-r--r--plugins/Rate/options.cpp224
-rw-r--r--plugins/Rate/rate.rc124
-rw-r--r--plugins/Rate/rate_10.sln26
-rw-r--r--plugins/Rate/rate_10.vcxproj180
-rw-r--r--plugins/Rate/rate_10.vcxproj.filters58
-rw-r--r--plugins/Rate/resource.h22
-rw-r--r--plugins/TooltipNotify/doc/todo.txt0
-rw-r--r--plugins/TooltipNotify/doc/tt_wnd_def_style.txt9
-rw-r--r--plugins/TooltipNotify/doc/ttnotify-readme.txt128
-rw-r--r--plugins/TooltipNotify/doc/ttnotify_translation.txt47
-rw-r--r--plugins/TooltipNotify/src/DbHelpers.cpp120
-rw-r--r--plugins/TooltipNotify/src/DbHelpers.h9
-rw-r--r--plugins/TooltipNotify/src/Settings.h42
-rw-r--r--plugins/TooltipNotify/src/Tooltip.cpp219
-rw-r--r--plugins/TooltipNotify/src/Tooltip.h55
-rw-r--r--plugins/TooltipNotify/src/TooltipNotify.cpp1114
-rw-r--r--plugins/TooltipNotify/src/TooltipNotify.h143
-rw-r--r--plugins/TooltipNotify/src/Utils.cpp32
-rw-r--r--plugins/TooltipNotify/src/Utils.h8
-rw-r--r--plugins/TooltipNotify/src/main.cpp218
-rw-r--r--plugins/TooltipNotify/src/main.rc204
-rw-r--r--plugins/TooltipNotify/src/resource.h47
-rw-r--r--plugins/TooltipNotify/src/stdafx.cpp8
-rw-r--r--plugins/TooltipNotify/src/stdafx.h37
-rw-r--r--plugins/TooltipNotify/src/version.h11
-rw-r--r--plugins/TooltipNotify/src/version.rc52
-rw-r--r--plugins/TooltipNotify/ttnotify_10.sln25
-rw-r--r--plugins/TooltipNotify/ttnotify_10.vcxproj262
-rw-r--r--plugins/TooltipNotify/ttnotify_10.vcxproj.filters79
-rw-r--r--plugins/UserGuide/UserGuide_10.sln25
-rw-r--r--plugins/UserGuide/UserGuide_10.vcxproj285
-rw-r--r--plugins/UserGuide/UserGuide_10.vcxproj.filters27
-rw-r--r--plugins/UserGuide/commonheaders.h10
-rw-r--r--plugins/UserGuide/main.c130
-rw-r--r--plugins/w7ui/clistproxywindow.cpp292
-rw-r--r--plugins/w7ui/clistproxywindow.h64
-rw-r--r--plugins/w7ui/dwmwindow.cpp209
-rw-r--r--plugins/w7ui/dwmwindow.h59
-rw-r--r--plugins/w7ui/headers.h81
-rw-r--r--plugins/w7ui/jumplist.cpp123
-rw-r--r--plugins/w7ui/jumplist.h7
-rw-r--r--plugins/w7ui/jumplistarray.cpp214
-rw-r--r--plugins/w7ui/jumplistarray.h29
-rw-r--r--plugins/w7ui/jumplistbuilder.cpp127
-rw-r--r--plugins/w7ui/jumplistbuilder.h47
-rw-r--r--plugins/w7ui/main.cpp93
-rw-r--r--plugins/w7ui/srmmproxywindow.cpp374
-rw-r--r--plugins/w7ui/srmmproxywindow.h42
-rw-r--r--plugins/w7ui/subclassmgr.cpp0
-rw-r--r--plugins/w7ui/subclassmgr.h71
-rw-r--r--plugins/w7ui/w7ui.cpp180
-rw-r--r--plugins/w7ui/w7ui_10.sln37
-rw-r--r--plugins/w7ui/w7ui_10.vcxproj364
-rw-r--r--plugins/w7ui/win7api.cpp25
-rw-r--r--plugins/w7ui/win7api.h38
-rw-r--r--plugins/w7ui/win7api_ICustomDestinationList.h34
-rw-r--r--plugins/w7ui/win7api_IObjectArray.h15
-rw-r--r--plugins/w7ui/win7api_IObjectCollection.h16
-rw-r--r--plugins/w7ui/win7api_ITaskbarList3.h65
194 files changed, 27179 insertions, 0 deletions
diff --git a/plugins/Autorun/autorun.h b/plugins/Autorun/autorun.h
new file mode 100644
index 0000000000..4452ef7a4a
--- /dev/null
+++ b/plugins/Autorun/autorun.h
@@ -0,0 +1,14 @@
+#define IDD_OPT_AUTORUN 101
+#define IDC_AUTORUN 102
+
+#define SUB_KEY "Software\\Microsoft\\Windows\\CurrentVersion\\Run"
+#define ModuleName "Autorun"
+
+// Plugin UUID for New plugin loader
+// req. 0.7.18+ core
+// {EB0465E2-CEEE-11DB-83EF-C1BF55D89593}
+
+#define MIID_AUTORUN {0xeb0465e2, 0xceee, 0x11db, { 0x83, 0xef, 0xc1, 0xbf, 0x55, 0xd8, 0x95, 0x93}}
+
+HKEY ROOT_KEY = HKEY_CURRENT_USER;
+
diff --git a/plugins/Autorun/autorun.rc b/plugins/Autorun/autorun.rc
new file mode 100644
index 0000000000..b643834124
--- /dev/null
+++ b/plugins/Autorun/autorun.rc
@@ -0,0 +1,83 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "autorun.h"
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Russian resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
+#ifdef _WIN32
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_OPT_AUTORUN DIALOGEX 0, 0, 200, 90
+STYLE DS_3DLOOK | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "Autorun",0,3,3,193,60
+ CONTROL "Launch Miranda IM at system startup",IDC_AUTORUN,"Button",
+ BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,15,20,165,10
+ LTEXT "Note: At startup Miranda IM will use current profile",
+ IDC_STATIC,15,35,165,20,NOT WS_GROUP
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""autorun.h""\r\n"
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Russian resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/Autorun/autorun.sln b/plugins/Autorun/autorun.sln
new file mode 100644
index 0000000000..0c93ceee03
--- /dev/null
+++ b/plugins/Autorun/autorun.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "autorun", "autorun.vcxproj", "{CC905A6E-3CCF-DB35-B1BD-0E0D0E5635B9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CC905A6E-3CCF-DB35-B1BD-0E0D0E5635B9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CC905A6E-3CCF-DB35-B1BD-0E0D0E5635B9}.Debug|Win32.Build.0 = Debug|Win32
+ {CC905A6E-3CCF-DB35-B1BD-0E0D0E5635B9}.Debug|x64.ActiveCfg = Debug|x64
+ {CC905A6E-3CCF-DB35-B1BD-0E0D0E5635B9}.Debug|x64.Build.0 = Debug|x64
+ {CC905A6E-3CCF-DB35-B1BD-0E0D0E5635B9}.Release|Win32.ActiveCfg = Release|Win32
+ {CC905A6E-3CCF-DB35-B1BD-0E0D0E5635B9}.Release|Win32.Build.0 = Release|Win32
+ {CC905A6E-3CCF-DB35-B1BD-0E0D0E5635B9}.Release|x64.ActiveCfg = Release|x64
+ {CC905A6E-3CCF-DB35-B1BD-0E0D0E5635B9}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/plugins/Autorun/autorun.txt b/plugins/Autorun/autorun.txt
new file mode 100644
index 0000000000..cec7052075
--- /dev/null
+++ b/plugins/Autorun/autorun.txt
@@ -0,0 +1,50 @@
+Autorun 0.1.0.0
+
+Written by and copyright (c) Sergey V. Gershovich a.k.a. Jazzy$, March 2003
+ e-mail: jazzy@arcticsu.ru
+
+This plugin is a simple way to enable/disable to launch Miranda IM
+with system startup.
+
+
+***** DISCLAIMER OF WARRANTY *****
+
+This software and the accompanying files are presented "AS IS" and without
+warranties whether expressed or implied. Use it at your own risk.
+
+**********************************
+
+Usage
+------
+Goto: Options->Plugins->Autorun
+
+
+Version history
+----------------------
+0.1.0.0: - Preparation for 0.8.x.x plugin loader
+ MIID_AUTORUN {EB0465E2-CEEE-11DB-83EF-C1BF55D89593}
+0.0.0.3: - Decrease size of plugin to 3 kb
+ - Change image base address to: 0x30040000
+ - Miranda IM v0.3alpha build 040303 or higher is required!
+ - Language strings updated
+
+0.0.0.2: - Some bugfix with long path & DB-filename
+
+0.0.0.1: - Initial release
+
+
+Translation
+-----------
+"Autorun" can be translated with the Miranda IM language files
+
+
+;; == Autorun v0.0.0.3 ==
+
+;Name of plugin
+;[Autorun]
+
+;Options page string
+;[Launch Miranda IM at system startup]
+
+;Options page string
+;[Note: At startup Miranda IM will use current profile] \ No newline at end of file
diff --git a/plugins/Autorun/autorun.vcxproj b/plugins/Autorun/autorun.vcxproj
new file mode 100644
index 0000000000..4c24b4cfc4
--- /dev/null
+++ b/plugins/Autorun/autorun.vcxproj
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <SccProjectName />
+ <SccLocalPath />
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <OutDir>$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <FunctionLevelLinking>false</FunctionLevelLinking>
+ <Optimization>Disabled</Optimization>
+ <WarningLevel>Level3</WarningLevel>
+ <MinimalRebuild>true</MinimalRebuild>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;autorun_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ </ClCompile>
+ <Midl>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <TypeLibraryName>.\Debug\autorun.tlb</TypeLibraryName>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Bscmake />
+ <Link>
+ <LinkDLL>true</LinkDLL>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <BaseAddress>0x30040000</BaseAddress>
+ <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <FunctionLevelLinking>false</FunctionLevelLinking>
+ <Optimization>Disabled</Optimization>
+ <WarningLevel>Level3</WarningLevel>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;autorun_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ </ClCompile>
+ <Midl>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <TypeLibraryName>.\Debug\autorun.tlb</TypeLibraryName>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Bscmake />
+ <Link>
+ <LinkDLL>true</LinkDLL>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <BaseAddress>0x30040000</BaseAddress>
+ <AdditionalDependencies>odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <Optimization>Full</Optimization>
+ <WarningLevel>Level3</WarningLevel>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;autorun_EXPORTS; _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </ClCompile>
+ <Midl>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <TypeLibraryName>.\Release\autorun.tlb</TypeLibraryName>
+ <MkTypLibCompatible>false</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Bscmake />
+ <Link>
+ <LinkDLL>true</LinkDLL>
+ <SubSystem>Windows</SubSystem>
+ <BaseAddress>0x30040000</BaseAddress>
+ <AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalOptions> /FILEALIGN:512 /SECTION:.text,ER /IGNORE:4078 /IGNORE:4078 </AdditionalOptions>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <Optimization>Full</Optimization>
+ <WarningLevel>Level3</WarningLevel>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;autorun_EXPORTS; _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ </ClCompile>
+ <Midl>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <TypeLibraryName>.\Release\autorun.tlb</TypeLibraryName>
+ <MkTypLibCompatible>false</MkTypLibCompatible>
+ </Midl>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Bscmake />
+ <Link>
+ <LinkDLL>true</LinkDLL>
+ <SubSystem>Windows</SubSystem>
+ <BaseAddress>0x30040000</BaseAddress>
+ <AdditionalDependencies>kernel32.lib;user32.lib;advapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalOptions> /FILEALIGN:512 /SECTION:.text,ER /IGNORE:4078 /IGNORE:4078 </AdditionalOptions>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="main.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="autorun.h" />
+ <ClInclude Include="resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="autorun.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="hsp.ico" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Autorun/autorun.vcxproj.filters b/plugins/Autorun/autorun.vcxproj.filters
new file mode 100644
index 0000000000..2977fdc693
--- /dev/null
+++ b/plugins/Autorun/autorun.vcxproj.filters
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{08a21636-368d-4feb-8d0d-0a27f237e1a2}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{9e6f20dc-3391-4299-9f74-e91d4f984ad3}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{18fd6180-ebb2-4558-b945-c4dac823f11b}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="autorun.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="autorun.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="hsp.ico">
+ <Filter>Resource Files</Filter>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="main.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Autorun/main.c b/plugins/Autorun/main.c
new file mode 100644
index 0000000000..c5a498afa1
--- /dev/null
+++ b/plugins/Autorun/main.c
@@ -0,0 +1,165 @@
+#include <windows.h>
+#include "autorun.h"
+
+#include "newpluginapi.h"
+#include "m_langpack.h"
+#include "m_options.h"
+#include "m_database.h"
+#pragma hdrstop
+
+
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+HANDLE hHookOptionInit = NULL;
+
+PLUGININFOEX pluginInfoEx=
+{ // about plugin
+ sizeof(PLUGININFOEX),
+ "Autorun",
+ PLUGIN_MAKE_VERSION(0,1,0,1),
+ "This plugin is a simple way to enable/disable to launch Miranda IM with system startup.",
+ "Sergey V. Gershovich a.k.a. Jazzy$ (fixed by Wolfram3D)",
+ "",
+ "Copyright 2002-2007 Sergey V. Gershovich a.k.a. Jazzy$",
+ "http://miranda-im.org/download/index.php?action=viewfile&id=285",
+ 0, 0,
+ MIID_AUTORUN
+};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ // plugin entry point
+ if (fdwReason == DLL_PROCESS_ATTACH)
+ {
+ hInst = hinstDLL;
+ DisableThreadLibraryCalls(hinstDLL);
+ }
+ return TRUE;
+}
+void GetProfilePath(char *res)
+{
+ char dbname[MAX_PATH], dbpath[MAX_PATH], exename[MAX_PATH];
+ CallService(MS_DB_GETPROFILENAME,sizeof(dbname),(LPARAM)(char*) dbname);
+ CallService(MS_DB_GETPROFILEPATH,sizeof(dbpath),(LPARAM)(char*) dbpath);
+ GetModuleFileName(NULL,exename,sizeof(exename));
+ lstrcat(dbpath,"\\");
+ lstrcpyn(dbpath+lstrlen(dbpath),dbname,lstrlen(dbname)-3);
+ strcat(dbpath, "\\");
+ strcat(dbpath, dbname); // path + profile name
+ wsprintf(res,"\"%s\" \"%s\"",exename, dbpath);
+}
+
+static void SetAutorun(BOOL autorun)
+{
+ HKEY hKey;
+ DWORD dw;
+ switch (autorun)
+ {
+ case TRUE:
+ if (RegCreateKeyEx(ROOT_KEY, SUB_KEY,0,NULL,0,KEY_CREATE_SUB_KEY|KEY_SET_VALUE,NULL,&hKey,&dw) == ERROR_SUCCESS)
+ {
+ char result[MAX_PATH];
+ GetProfilePath (result);
+ RegSetValueEx(hKey,"MirandaIM",0,REG_SZ,result,lstrlen(result)+1);
+ RegCloseKey(hKey);
+ break;
+ }
+ case FALSE:
+ if (RegOpenKey(ROOT_KEY,SUB_KEY,&hKey) == ERROR_SUCCESS)
+ {
+ RegDeleteValue(hKey,"MirandaIM");
+ RegCloseKey(hKey);
+ break;
+ }
+ }
+}
+
+
+static BOOL CmpCurrentAndRegistry()
+{
+ HKEY hKey;
+ DWORD dwBufLen = MAX_PATH;
+ char result[MAX_PATH], dbpath[MAX_PATH];
+ GetProfilePath (result);
+
+ if (RegOpenKeyEx(ROOT_KEY, SUB_KEY, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
+ {
+ if (RegQueryValueEx(hKey,"MirandaIM",NULL,NULL,(LPBYTE)dbpath,&dwBufLen) == ERROR_SUCCESS)
+ {
+ return (lstrcmpi(result,dbpath) == 0 ? TRUE : FALSE);
+ }
+ else
+ return FALSE;
+ }
+ else
+ return FALSE;
+}
+
+static INT_PTR CALLBACK DlgProcAutorunOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg,IDC_AUTORUN,CmpCurrentAndRegistry()); // Check chekbox if Registry value exists
+ return TRUE;
+ case WM_COMMAND:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); // Send message to activate "Apply" button
+ return TRUE;
+ break;
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY: // if "Apply" pressed then...
+ SetAutorun(IsDlgButtonChecked(hwndDlg,IDC_AUTORUN)); //Save changes to registry;
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+static int AutorunOptInitialise(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp;
+ odp.cbSize=sizeof(odp);
+ odp.position=100100000;
+ odp.hInstance=hInst;
+ odp.pszTemplate=MAKEINTRESOURCE(IDD_OPT_AUTORUN);
+ odp.pszTitle=Translate(ModuleName);
+ odp.pszGroup=Translate("Plugins");
+ odp.pfnDlgProc=DlgProcAutorunOpts;
+ odp.flags=ODPF_BOLDGROUPS;
+ CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
+ return 0;
+}
+//==========================================================================
+__declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfoEx;
+}
+
+static const MUUID interfaces[] = {MIID_AUTORUN, MIID_LAST};
+__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ pluginLink = link;
+ hHookOptionInit = HookEvent(ME_OPT_INITIALISE,AutorunOptInitialise);
+ return 0;
+}
+
+int __declspec(dllexport) Unload(void)
+{
+ if (hHookOptionInit)
+ UnhookEvent(hHookOptionInit);
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/Autorun/resource.h b/plugins/Autorun/resource.h
new file mode 100644
index 0000000000..c5b53f192c
--- /dev/null
+++ b/plugins/Autorun/resource.h
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by autorun.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/Boltun/Boltun.rc b/plugins/Boltun/Boltun.rc
new file mode 100644
index 0000000000..4ae46eea47
--- /dev/null
+++ b/plugins/Boltun/Boltun.rc
@@ -0,0 +1,155 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (Canada) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENC)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_CAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_MAINBOLTUN ICON "res\\boltun.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// SMILES
+//
+
+IDR_SMILES SMILES "res\\smiles.dat"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_MAIN DIALOGEX 0, 0, 307, 231
+STYLE DS_SETFONT | WS_CHILD | WS_BORDER
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Boltun",IDC_PLUGINRM,5,2,297,222
+ CONTROL "Boltun Autochat everybody",IDC_EVERYBODY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,20,230,10
+ CONTROL "Boltun Autochat everybody not in contact list",IDC_NOTINLIST,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,33,230,10
+ CONTROL "Boltun Autochat everybody while away",IDC_AUTOAWAY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,46,230,10
+ CONTROL "Warn contacts Boltun is chatting",IDC_WARN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,59,230,10
+ CONTROL "Mark replied messages as read",IDC_MARKREAD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,72,230,10
+ EDITTEXT IDC_WAITTIME,26,161,24,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "sec",IDC_LSEC,53,161,72,8
+ EDITTEXT IDC_WARNTXT,17,97,272,31,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL
+ GROUPBOX "Warning text",IDC_LWARN,12,85,283,50
+ GROUPBOX "Time before the answer",IDC_LWAITTIME,12,138,283,72
+ CONTROL "Typing time depends on message length (in chars)",IDC_PAUSEDEPENDS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,178,270,11
+ CONTROL "Typing and thinking time can be much longer",IDC_PAUSERANDOM,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,193,270,10
+ LTEXT "Typing time (for a message of 4 words):",IDC_STATIC,21,148,145,8
+ LTEXT "Thinking time:",IDC_STATIC,173,148,111,8
+ EDITTEXT IDC_THINKTIME,177,161,24,12,ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "sec",IDC_LSEC2,205,161,72,8
+END
+
+IDD_ENGINE DIALOGEX 0, 0, 307, 231
+STYLE DS_SETFONT | WS_CHILD | WS_BORDER
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Engine",IDC_PLUGINRM,5,48,297,174
+ EDITTEXT IDC_MINDFILE,12,19,210,14,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP
+ PUSHBUTTON "...",IDC_BTNPATH,226,18,16,16
+ GROUPBOX "Base of remarks",IDC_TXTREPLICPATH,5,6,297,36
+ PUSHBUTTON "Reload",IDC_BTNRELOAD,246,18,52,16
+ CONTROL "Stay silent, if have no good aswers",IDC_ENGINE_SILENT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,62,283,10
+ CONTROL "Start answers with a lowercase letter",IDC_ENGINE_LOWERCASE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,94,282,10
+ CONTROL "Don't use ""I don't understand""-like answers",IDC_ENGINE_UNDERSTAND_ALWAYS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,27,78,248,10
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_MAIN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 300
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 224
+ END
+
+ IDD_ENGINE, DIALOG
+ BEGIN
+ RIGHTMARGIN, 306
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (Canada) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/Boltun/Boltun2.gif b/plugins/Boltun/Boltun2.gif
new file mode 100644
index 0000000000..fc2b4a93df
--- /dev/null
+++ b/plugins/Boltun/Boltun2.gif
Binary files differ
diff --git a/plugins/Boltun/Boltun_10.sln b/plugins/Boltun/Boltun_10.sln
new file mode 100644
index 0000000000..9f1aa3541d
--- /dev/null
+++ b/plugins/Boltun/Boltun_10.sln
@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Boltun_10", "Boltun_10.vcxproj", "{98DF7761-41D7-4C5C-9FFE-E5CCB3997783}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug Unicode|Win32 = Debug Unicode|Win32
+ Release Unicode|Win32 = Release Unicode|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {98DF7761-41D7-4C5C-9FFE-E5CCB3997783}.Debug Unicode|Win32.ActiveCfg = Debug Unicode|Win32
+ {98DF7761-41D7-4C5C-9FFE-E5CCB3997783}.Debug Unicode|Win32.Build.0 = Debug Unicode|Win32
+ {98DF7761-41D7-4C5C-9FFE-E5CCB3997783}.Release Unicode|Win32.ActiveCfg = Release Unicode|Win32
+ {98DF7761-41D7-4C5C-9FFE-E5CCB3997783}.Release Unicode|Win32.Build.0 = Release Unicode|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/plugins/Boltun/Boltun_10.vcxproj b/plugins/Boltun/Boltun_10.vcxproj
new file mode 100644
index 0000000000..0f05bca890
--- /dev/null
+++ b/plugins/Boltun/Boltun_10.vcxproj
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug Unicode|Win32">
+ <Configuration>Debug Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release Unicode|Win32">
+ <Configuration>Release Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{98DF7761-41D7-4C5C-9FFE-E5CCB3997783}</ProjectGuid>
+ <RootNamespace>Boltun</RootNamespace>
+ <ProjectName>boltun</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">$(ProjectName)w</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">$(ProjectName)w</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release/Boltun.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;BOLTUN_EXPORTS;WIN32;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_UNICODE;UNICODE;_WIN32_WINNT=0x0501;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">
+ <CustomBuildStep>
+ <Command>copy Engine\boltun.mindw "$(SolutionDir)$(Configuration)\Plugins"
+</Command>
+ <Outputs>$(OutDir)boltun.mindw;%(Outputs)</Outputs>
+ </CustomBuildStep>
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Debug/Boltun.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;WIN32;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;BOLTUN_EXPORTS;_UNICODE;UNICODE;_WIN32_WINNT=0x0501;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>odbc32.lib;odbccp32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="actionQueue.cpp" />
+ <ClCompile Include="boltun.cpp">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="config.cpp" />
+ <ClCompile Include="Engine\Mind.cpp" />
+ <ClCompile Include="Engine\MyCodeCvt.cpp" />
+ <ClCompile Include="Engine\TalkEngine.cpp" />
+ <ClCompile Include="Engine\UnrecentChooser.cpp" />
+ <ClCompile Include="Engine\WordsList.cpp">
+ <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">Full</Optimization>
+ <InlineFunctionExpansion Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">AnySuitable</InlineFunctionExpansion>
+ <IntrinsicFunctions Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">true</IntrinsicFunctions>
+ <FavorSizeOrSpeed Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">Speed</FavorSizeOrSpeed>
+ <OmitFramePointers Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">true</OmitFramePointers>
+ <EnableFiberSafeOptimizations Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">true</EnableFiberSafeOptimizations>
+ <WholeProgramOptimization Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">true</WholeProgramOptimization>
+ <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">Default</BasicRuntimeChecks>
+ <DebugInformationFormat Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="actionQueue.h" />
+ <ClInclude Include="boltun.h" />
+ <ClInclude Include="config.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="Engine\CriticalSection.h" />
+ <ClInclude Include="Engine\Mind.h" />
+ <ClInclude Include="Engine\MyCodeCvt.h" />
+ <ClInclude Include="Engine\PerContactData.h" />
+ <ClInclude Include="Engine\TalkEngine.h" />
+ <ClInclude Include="Engine\tstring.h" />
+ <ClInclude Include="Engine\UnrecentChooser.h" />
+ <ClInclude Include="Engine\ValueChooser.h" />
+ <ClInclude Include="Engine\WordsList.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\boltun.ico" />
+ <None Include="res\smiles.dat" />
+ <None Include="Engine\boltun.mindw" />
+ <None Include="lang_pack.txt" />
+ <None Include="mind.txt" />
+ <None Include="readme.txt" />
+ <None Include="TODO.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="boltun.rc">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Boltun/Boltun_10.vcxproj.filters b/plugins/Boltun/Boltun_10.vcxproj.filters
new file mode 100644
index 0000000000..e025146d37
--- /dev/null
+++ b/plugins/Boltun/Boltun_10.vcxproj.filters
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{053e819b-1bb3-488b-8dbd-f6b29640c30c}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Source Files\Enigne">
+ <UniqueIdentifier>{e94debaf-39e5-4d66-95b0-b02f301c140c}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{db6f678c-e69c-4576-819a-360e80ffc84c}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Header Files\Engine">
+ <UniqueIdentifier>{614d736c-849c-4a07-ba4e-a6c9b895154b}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{c04447a2-5567-4425-92b8-a4a1267e7e32}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="actionQueue.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="boltun.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="config.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Engine\Mind.cpp">
+ <Filter>Source Files\Enigne</Filter>
+ </ClCompile>
+ <ClCompile Include="Engine\MyCodeCvt.cpp">
+ <Filter>Source Files\Enigne</Filter>
+ </ClCompile>
+ <ClCompile Include="Engine\TalkEngine.cpp">
+ <Filter>Source Files\Enigne</Filter>
+ </ClCompile>
+ <ClCompile Include="Engine\UnrecentChooser.cpp">
+ <Filter>Source Files\Enigne</Filter>
+ </ClCompile>
+ <ClCompile Include="Engine\WordsList.cpp">
+ <Filter>Source Files\Enigne</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="actionQueue.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="boltun.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="config.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="Engine\CriticalSection.h">
+ <Filter>Header Files\Engine</Filter>
+ </ClInclude>
+ <ClInclude Include="Engine\Mind.h">
+ <Filter>Header Files\Engine</Filter>
+ </ClInclude>
+ <ClInclude Include="Engine\MyCodeCvt.h">
+ <Filter>Header Files\Engine</Filter>
+ </ClInclude>
+ <ClInclude Include="Engine\PerContactData.h">
+ <Filter>Header Files\Engine</Filter>
+ </ClInclude>
+ <ClInclude Include="Engine\TalkEngine.h">
+ <Filter>Header Files\Engine</Filter>
+ </ClInclude>
+ <ClInclude Include="Engine\tstring.h">
+ <Filter>Header Files\Engine</Filter>
+ </ClInclude>
+ <ClInclude Include="Engine\UnrecentChooser.h">
+ <Filter>Header Files\Engine</Filter>
+ </ClInclude>
+ <ClInclude Include="Engine\ValueChooser.h">
+ <Filter>Header Files\Engine</Filter>
+ </ClInclude>
+ <ClInclude Include="Engine\WordsList.h">
+ <Filter>Header Files\Engine</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\boltun.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\smiles.dat">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="lang_pack.txt" />
+ <None Include="mind.txt" />
+ <None Include="readme.txt" />
+ <None Include="TODO.txt" />
+ <None Include="Engine\boltun.mindw">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="boltun.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Boltun/Engine/COPYING.txt b/plugins/Boltun/Engine/COPYING.txt
new file mode 100644
index 0000000000..82fa1daad4
--- /dev/null
+++ b/plugins/Boltun/Engine/COPYING.txt
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/plugins/Boltun/Engine/CriticalSection.h b/plugins/Boltun/Engine/CriticalSection.h
new file mode 100644
index 0000000000..59bc91beb9
--- /dev/null
+++ b/plugins/Boltun/Engine/CriticalSection.h
@@ -0,0 +1,56 @@
+//***********************************************************
+// Copyright 2008 Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#ifndef CriticalSectionH
+#define CriticalSectionH
+
+#include <windows.h>
+
+class CriticalSection
+{
+ CRITICAL_SECTION csQueue;
+public:
+ inline CriticalSection()
+ {
+ InitializeCriticalSection(&csQueue);
+ }
+
+ inline ~CriticalSection()
+ {
+ DeleteCriticalSection(&csQueue);
+ }
+
+ inline void Enter()
+ {
+ EnterCriticalSection(&csQueue);
+ }
+
+ inline void Leave()
+ {
+ LeaveCriticalSection(&csQueue);
+ }
+
+ inline bool TryEnter()
+ {
+ return TryEnterCriticalSection(&csQueue) != 0;
+ }
+};
+
+#endif /* CriticalSectionH */ \ No newline at end of file
diff --git a/plugins/Boltun/Engine/Mind.cpp b/plugins/Boltun/Engine/Mind.cpp
new file mode 100644
index 0000000000..6260177095
--- /dev/null
+++ b/plugins/Boltun/Engine/Mind.cpp
@@ -0,0 +1,448 @@
+//***********************************************************
+// Copyright 2008 Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#include "Mind.h"
+#include <fstream>
+#include <algorithm>
+#include "tstring.h"
+#include "assert.h"
+
+#include <windows.h>
+
+#ifdef UNICODE
+#include "MyCodeCvt.h"
+#endif
+
+using namespace std;
+
+typedef vector<tstring> string_vec;
+typedef multimap<tstring,tstring> string_mmap;
+
+Mind::Mind()
+{
+ data = new MindData();
+ data->referenceCount = 1;
+ data->maxSmileLen = 0;
+}
+
+Mind::~Mind()
+{
+ if (--data->referenceCount == 0)
+ delete data;
+}
+
+Mind::Mind(const Mind& mind)
+{
+ mind.data->referenceCount++;
+ data = mind.data;
+}
+
+const MindData *Mind::GetData() const
+{
+ return data;
+}
+
+Mind& Mind::operator= (const Mind& mind)
+{
+ if (--data->referenceCount == 0)
+ delete data;
+ mind.data->referenceCount++;
+ data = mind.data;
+ return *this;
+}
+
+inline void format(tstring& s)
+{
+ int pos = s.length() - 1;
+ if (s[pos] == _T('\r'))
+ s.resize(pos);
+}
+
+void toLowerStr(TCHAR* ch)
+{
+ CharLower(ch);
+}
+
+vector<tstring> Mind::Parse(tstring s)
+{
+ int len = s.length() - 1;
+ vector <tstring> res;
+ while (len != -1 && _istspace(s[len]))
+ len--;
+ if (len < 0)
+ return res;
+ s.resize(len);
+ int it = 0;
+ while (it != len)
+ {
+ while (it != len && _istspace(s[it]))
+ it++;
+ if (it == len)
+ break;
+ int start = it;
+ while (it != len && !_istspace(s[it]))
+ it++;
+ res.push_back(s.substr(start, it - start));
+ }
+ return res;
+}
+
+void Mind::Load(tstring filename)
+{
+ basic_ifstream<TCHAR, char_traits<TCHAR> > file;
+ setlocale(LC_ALL, "");
+#ifdef UNICODE
+ locale ulocale(locale(), new MyCodeCvt);
+ file.imbue(ulocale);
+#endif
+ file.open(filename.c_str(), ios_base::in | ios_base::binary);
+ tstring s1, st;
+ TCHAR *c, *co;
+ size_t count;
+ int error = 0;
+ int line = 1;
+#ifdef UNICODE
+ bool start = true;
+#endif
+ try
+ {
+ while (file.good())
+ {
+ getline(file, st);
+ if (st.empty())
+ break;
+ line++;
+#ifdef UNICODE
+ if (start)
+ {
+ if (st[0] == 65279)
+ {
+ st.erase(0, 1);
+ fileTypeMark = true;
+ }
+ else
+ fileTypeMark = false;
+ start = false;
+ }
+#endif
+ format(st);
+ count = st.length();
+ c = co = new TCHAR[count+1];
+ _tcscpy(c, st.c_str());
+ size_t pos = 0;
+ while (pos < count && _istspace(*c))
+ {
+ ++pos;
+ ++c;
+ }
+ count -= pos;
+ if (count > 2)
+ {
+ switch (*c)
+ {
+ case '(':
+ if (c[count - 1] != ')')
+ abort();
+ if (file.eof())
+ throw error;
+ getline(file, s1);
+ line++;
+ format(s1);
+ ++c;
+ count -= 2;
+ c[count] = '\0';
+ toLowerStr(c);
+ {
+ WordsList l(c);
+ if (!l.IsEmpty())
+ if (l.IsQuestion())
+ data->qkeywords.insert(make_pair(l, s1));
+ else
+ data->keywords.insert(make_pair(l, s1));
+ }
+ break;
+ case '{':
+ if (c[count - 1] != '}')
+ abort();
+ if (file.eof())
+ throw error;
+ getline(file, s1);
+ line++;
+ format(s1);
+ ++c;
+ count -= 2;
+ c[count] = '\0';
+ toLowerStr(c);
+ {
+ WordsList l(c);
+ if (!l.IsEmpty())
+ if (l.IsQuestion())
+ data->qspecialEscapes.insert(make_pair(l, s1));
+ else
+ data->specialEscapes.insert(make_pair(l, s1));
+ }
+ break;
+ case '[':
+ if (c[count - 1] != ']')
+ throw error;
+ if (file.eof())
+ throw error;
+ getline(file, s1);
+ line++;
+ format(s1);
+ ++c;
+ count -= 2;
+ c[count] = '\0';
+ toLowerStr(c);
+ data->widelyUsed.insert(make_pair(c, s1));
+ break;
+ case '<':
+ if (c[count - 1] != '>')
+ throw error;
+ if (file.eof())
+ throw error;
+ getline(file, s1);
+ line++;
+ format(s1);
+ ++c;
+ count -= 2;
+ c[count] = '\0';
+ if (_tcscmp(c,_T("QUESTION")) == 0)
+ {
+ toLowerStr(c);
+ data->question.insert(s1);
+ }
+ else
+ if (_tcscmp(c,_T("IGNORED")) == 0)
+ {
+ toLowerStr(c);
+ data->special.insert(s1);
+ }
+ else
+ if (_tcscmp(c,_T("ESCAPE")) == 0)
+ {
+ data->escape.push_back(s1);
+ }
+ else
+ if (_tcscmp(c,_T("FAILURE")) == 0)
+ {
+ data->failure.push_back(s1);
+ }
+ else
+ if (_tcscmp(c,_T("REPEAT")) == 0)
+ {
+ data->repeats.push_back(s1);
+ }
+ else
+ {
+ if (_tcscmp(c,_T("INITIAL")) != 0)
+ throw error;
+ data->initial.push_back(s1);
+ }
+ break;
+ case '@':
+ {
+ if (file.eof())
+ throw error;
+ getline(file, s1);
+ line++;
+ format(s1);
+ ++c;
+ count -= 1;
+ toLowerStr(c);
+ tstring sc(c);
+ int count1 = s1.length();
+ TCHAR *c = new TCHAR[count1 + 1];
+ _tcscpy(c, s1.c_str());
+ CharLower(c);
+ s1 = c;
+ delete c;
+ vector<tstring> strs = Parse(s1);
+ data->raliases.insert(make_pair(sc, strs));
+ for (vector<tstring>::const_iterator it = strs.begin(); it != strs.end(); it++)
+ data->aliases.insert(make_pair(*it, sc));
+ }
+ break;
+ default:
+ if (file.eof())
+ throw error;
+ getline(file, s1);
+ line++;
+ format(s1);
+ toLowerStr(c);
+ data->study.insert(make_pair(c, s1));
+ }
+ }
+ else
+ if (count)
+ {
+ if (file.eof())
+ throw error;
+ getline(file, s1);
+ line++;
+ format(s1);
+ data->study.insert(make_pair(c, s1));
+ }
+ }
+ if (!file.eof())
+ {
+ throw error;
+ }
+ delete co;
+ }
+ catch(...)
+ {
+ throw CorruptedMind(line);
+ delete co;
+ }
+}
+
+void Mind::Save(tstring filename) const
+{
+ basic_ofstream<TCHAR, char_traits<TCHAR> > file;
+#ifdef UNICODE
+ locale ulocale(locale(), new MyCodeCvt);
+ file.imbue(ulocale);
+#endif
+ file.open(filename.c_str(), ios_base::out | ios_base::binary);
+#ifdef UNICODE
+ if (fileTypeMark)
+ file << TCHAR(65279);
+#endif
+ for (string_mmap::iterator it = data->study.begin(); it != data->study.end(); it++)
+ {
+ file << (*it).first << _T('\r') << endl;
+ file << (*it).second << _T('\r') << endl;
+ }
+ for (multimap<WordsList, tstring>::iterator it = data->keywords.begin(); it != data->keywords.end(); it++)
+ {
+ file << _T(" (") << (tstring)(*it).first << _T(")") << _T('\r') << endl;
+ file << (*it).second << _T('\r') << endl;
+ }
+ for (multimap<WordsList, tstring>::iterator it = data->qkeywords.begin(); it != data->qkeywords.end(); it++)
+ {
+ file << _T(" (") << (tstring)(*it).first << _T(")") << _T('\r') << endl;
+ file << (*it).second << _T('\r') << endl;
+ }
+ for (multimap<WordsList, tstring>::iterator it = data->specialEscapes.begin(); it != data->specialEscapes.end(); it++)
+ {
+ file << _T(" {") << (tstring)(*it).first << _T("}") << _T('\r') << endl;
+ file << (*it).second << _T('\r') << endl;
+ }
+ for (multimap<WordsList, tstring>::iterator it = data->qspecialEscapes.begin(); it != data->qspecialEscapes.end(); it++)
+ {
+ file << _T(" {") << (tstring)(*it).first << _T("}") << _T('\r') << endl;
+ file << (*it).second << _T('\r') << endl;
+ }
+ for (string_mmap::iterator it = data->widelyUsed.begin(); it != data->widelyUsed.end(); it++)
+ {
+ file << _T(" [") << (*it).first << _T("]") << _T('\r') << endl;
+ file << (*it).second << _T('\r') << endl;
+ }
+ for (set<tstring>::iterator it = data->question.begin(); it != data->question.end(); it++)
+ {
+ file << _T(" <QUESTION>") << _T('\r') << endl;
+ file << (*it) << _T('\r') << endl;
+ }
+ for (set<tstring>::iterator it = data->special.begin(); it != data->special.end(); it++)
+ {
+ file << _T(" <IGNORED>") << _T('\r') << endl;
+ file << (*it) << _T('\r') << endl;
+ }
+ for (string_vec::iterator it = data->escape.begin(); it != data->escape.end(); it++)
+ {
+ file << _T(" <ESCAPE>") << _T('\r') << endl;
+ file << (*it) << _T('\r') << endl;
+ }
+ for (string_vec::iterator it = data->initial.begin(); it != data->initial.end(); it++)
+ {
+ file << _T(" <INITIAL>") << _T('\r') << endl;
+ file << (*it) << _T('\r') << endl;
+ }
+ for (string_vec::iterator it = data->failure.begin(); it != data->failure.end(); it++)
+ {
+ file << _T(" <FAILURE>") << _T('\r') << endl;
+ file << (*it) << _T('\r') << endl;
+ }
+ for (string_vec::iterator it = data->repeats.begin(); it != data->repeats.end(); it++)
+ {
+ file << _T(" <REPEAT>") << _T('\r') << endl;
+ file << (*it) << _T('\r') << endl;
+ }
+ for (map<tstring,vector<tstring>>::const_iterator it = data->raliases.begin(); it != data->raliases.end(); it++)
+ {
+ tstring s;
+ const vector<tstring>& v = (*it).second;
+ bool first = true;
+ for (vector<tstring>::const_iterator it1 = v.begin(); it1 != v.end(); it1++)
+ {
+ if (first)
+ {
+ first = false;
+ s = *it1;
+ }
+ else
+ {
+ s += _T(" ") + *it1;
+ }
+ }
+ file << _T('@') << (*it).first << _T('\r') << endl;
+ file << s << _T('\r') << endl;
+ }
+}
+
+void Mind::LoadSmiles(tstring filename)
+{
+ basic_ifstream<TCHAR, char_traits<TCHAR> > file;
+ file.open(filename.c_str());
+ data->smiles.clear();
+ tstring s;
+ unsigned int l = 0;
+ while (!file.eof())
+ {
+ getline(file, s);
+ if (s.length() > l)
+ l = s.length();
+ data->smiles.insert(s);
+ }
+ data->maxSmileLen = l;
+}
+
+void Mind::LoadSmiles(void *smiles, size_t size)
+{
+ data->smiles.clear();
+ TCHAR* buf = (TCHAR*)smiles;
+ unsigned l = 0;
+ TCHAR* end = buf + size;
+ while (buf != end)
+ {
+ TCHAR *lend = buf;
+ while (lend != end && *lend != _T('\r'))
+ lend++;
+ tstring s(buf, lend - buf);
+ if ((unsigned)(lend - buf) > l)
+ l = s.length();
+ data->smiles.insert(s);
+ if (lend == end)
+ break;
+ buf = lend + 2;
+ }
+ data->maxSmileLen = l;
+}
diff --git a/plugins/Boltun/Engine/Mind.h b/plugins/Boltun/Engine/Mind.h
new file mode 100644
index 0000000000..ecf3f5d199
--- /dev/null
+++ b/plugins/Boltun/Engine/Mind.h
@@ -0,0 +1,89 @@
+//***********************************************************
+// Copyright 2008 Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#ifndef MindH
+#define MindH
+
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+#include "WordsList.h"
+#include <tchar.h>
+#include "tstring.h"
+
+
+class Mind;
+
+typedef struct
+{
+ friend class Mind;
+ std::vector<tstring> initial;
+ std::set<tstring> question;
+ std::set<tstring> special;
+ std::vector<tstring> escape;
+ std::vector<tstring> failure;
+ std::vector<tstring> repeats;
+ unsigned int maxSmileLen;
+ std::set<tstring> smiles;
+ std::multimap<WordsList, tstring> keywords;
+ std::multimap<WordsList, tstring> qkeywords;
+ std::multimap<tstring, tstring> widelyUsed;
+ std::multimap<WordsList, tstring> specialEscapes;
+ std::multimap<WordsList, tstring> qspecialEscapes;
+ std::multimap<tstring, tstring> study;
+ std::map<tstring, tstring> aliases;
+ std::map<tstring, std::vector<tstring>> raliases;
+private:
+ int referenceCount;
+} MindData;
+
+class Mind
+{
+private:
+ MindData *data;
+#ifdef UNICODE
+ bool fileTypeMark;
+#endif
+ std::vector<tstring> Parse(tstring s);
+public:
+ Mind();
+ ~Mind();
+ Mind(const Mind& mind);
+ Mind& operator= (const Mind& mind);
+
+ class CorruptedMind
+ {
+ public:
+ int line;
+ CorruptedMind(int aline)
+ : line(aline)
+ {
+ };
+ };
+
+ const MindData *GetData() const;
+ void Load(tstring filename);
+ void Save(tstring filename) const;
+ void LoadSmiles(tstring filename);
+ void LoadSmiles(void* smiles, size_t size);
+};
+
+#endif
diff --git a/plugins/Boltun/Engine/MyCodeCvt.cpp b/plugins/Boltun/Engine/MyCodeCvt.cpp
new file mode 100644
index 0000000000..71e056291a
--- /dev/null
+++ b/plugins/Boltun/Engine/MyCodeCvt.cpp
@@ -0,0 +1,85 @@
+//***********************************************************
+// Copyright 2008 Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#ifdef UNICODE
+
+#include "MyCodeCvt.h"
+
+using namespace std;
+
+MyCodeCvt::MyCodeCvt(size_t _R)
+ : MyCodeCvtBase(_R)
+{
+}
+
+MyCodeCvt::result MyCodeCvt::do_in(_St& _State ,
+ const _To* _F1, const _To* _L1, const _To*& _Mid1,
+ _E* F2, _E* _L2, _E*& _Mid2) const
+{
+ return noconv;
+}
+
+#ifdef MSVC
+MyCodeCvt::result MyCodeCvt::do_out(_St& _State,
+ const _E* _F1, const _E* _L1, const _E*& _Mid1,
+ _To* F2, _E* _L2, _To*& _Mid2) const
+#else
+MyCodeCvt::result MyCodeCvt::do_out(_St& _State,
+ const _E* _F1, const _E* _L1, const _E*& _Mid1,
+ _To* F2, _To* _L2, _To*& _Mid2) const
+#endif
+{
+ return noconv;
+}
+
+MyCodeCvt::result MyCodeCvt::do_unshift( _St& _State,
+ _To* _F2, _To* _L2, _To*& _Mid2) const
+{
+ return noconv;
+}
+
+#ifdef MSVC
+int MyCodeCvt::do_length(_St& _State, const _To* _F1,
+ const _To* _L1, size_t _N2) const _THROW0()
+#else
+int MyCodeCvt::do_length(const _St& _State, const _To* _F1,
+ const _To* _L1, size_t _N2) const _THROW0()
+#endif
+
+{
+ return (_N2 < (size_t)(_L1 - _F1)) ? _N2 : _L1 - _F1;
+}
+
+bool MyCodeCvt::do_always_noconv() const _THROW0()
+{
+ return true;
+}
+
+int MyCodeCvt::do_max_length() const _THROW0()
+{
+ return 2;
+}
+
+int MyCodeCvt::do_encoding() const _THROW0()
+{
+ return 2;
+}
+
+#endif \ No newline at end of file
diff --git a/plugins/Boltun/Engine/MyCodeCvt.h b/plugins/Boltun/Engine/MyCodeCvt.h
new file mode 100644
index 0000000000..b4508c66de
--- /dev/null
+++ b/plugins/Boltun/Engine/MyCodeCvt.h
@@ -0,0 +1,59 @@
+//***********************************************************
+// Copyright 2008 Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#ifndef MYCODECVT_H
+#define MYCODECVT_H
+
+#include <locale>
+#include <xlocale>
+#include <cwchar>
+
+typedef std::codecvt<wchar_t, char, std::mbstate_t> MyCodeCvtBase;
+
+class MyCodeCvt
+ : public MyCodeCvtBase
+{
+public:
+ typedef wchar_t _E;
+ typedef char _To;
+ typedef std::mbstate_t _St;
+ explicit MyCodeCvt( size_t _R=0 );
+protected:
+ virtual result do_in(_St& _State, const _To* _F1, const _To* _L1, const _To*& _Mid1,
+ _E* F2 , _E* _L2 , _E*& _Mid2) const;
+#ifdef MSVC
+ virtual result do_out(_St& _State, const _E* _F1, const _E* _L1, const _E*& _Mid1,
+ _To* F2, _E* _L2 , _To*& _Mid2) const;
+#else
+ virtual result do_out(_St& _State, const _E* _F1, const _E* _L1, const _E*& _Mid1,
+ _To* F2, _To* _L2 , _To*& _Mid2) const;
+#endif
+ virtual result do_unshift(_St& _State, _To* _F2, _To* _L2, _To*& _Mid2) const;
+#ifdef MSVC
+ virtual int do_length(_St& _State, const _To* _F1, const _To* _L1, size_t _N2) const _THROW0();
+#else
+ virtual int do_length(const _St& _State, const _To* _F1, const _To* _L1, size_t _N2) const _THROW0();
+#endif
+ virtual bool do_always_noconv() const _THROW0();
+ virtual int do_max_length() const _THROW0();
+ virtual int do_encoding() const _THROW0();
+} ;
+
+#endif /* MYCODECVT_H */ \ No newline at end of file
diff --git a/plugins/Boltun/Engine/PerContactData.h b/plugins/Boltun/Engine/PerContactData.h
new file mode 100644
index 0000000000..14b17784b9
--- /dev/null
+++ b/plugins/Boltun/Engine/PerContactData.h
@@ -0,0 +1,173 @@
+//***********************************************************
+// Copyright 2008 Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#ifndef PerContactDataH
+#define PerContactDataH
+
+#include <map>
+#include <time.h>
+#include <assert.h>
+
+#include "CriticalSection.h"
+
+static std::map<unsigned, void*> perContactDataObjects;
+
+template <class Source, class Data, class ContactHandle>
+class PerContactData
+{
+ template <class Source, class Data>
+ struct InternalData
+ {
+ CriticalSection lock;
+ Data *data;
+ time_t time;
+ inline InternalData(const Source& src)
+ :time(0)
+ {
+ data = new Data(src);
+ }
+
+ inline InternalData()
+ :data(NULL)
+ {
+ assert(false);
+ }
+
+ inline ~InternalData()
+ {
+ delete data;
+ }
+ };
+ CriticalSection mapLock;
+ unsigned timerID;
+ std::map<ContactHandle, InternalData<Source, Data>* > datas;
+ typedef typename std::map<ContactHandle, InternalData<Source, Data>* >::iterator mapIt;
+ const Source& source;
+ void CleanupData();
+ template <class Source, class Data, class ContactHandle>
+ friend VOID CALLBACK RunTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
+public:
+ PerContactData(const Source& src);
+ ~PerContactData();
+ Data* GetData(ContactHandle Contact);
+ void PutData(ContactHandle Contact);
+};
+
+template <class Source, class Data, class ContactHandle>
+PerContactData<Source, Data, ContactHandle>::PerContactData(const Source& src)
+ :source(src), timerID(0)
+{
+}
+
+template <class Source, class Data, class ContactHandle>
+PerContactData<Source, Data, ContactHandle>::~PerContactData()
+{
+ mapLock.Enter();
+ if (timerID)
+ {
+ KillTimer(NULL, timerID);
+ perContactDataObjects.erase(timerID);
+ }
+ while (!datas.empty())
+ {
+ while (!(*datas.begin()).second->lock.TryEnter())
+ {
+ mapLock.Leave();
+ Sleep(10);
+ mapLock.Enter();
+ }
+ //Now we know exactly that no-one onws a contact lock
+ InternalData<Source, Data>* data = (*datas.begin()).second;
+ data->lock.Leave();
+ delete data;
+ datas.erase(datas.begin());
+ }
+ mapLock.Leave();
+}
+
+template <class Source, class Data, class ContactHandle>
+Data* PerContactData<Source, Data, ContactHandle>::GetData(ContactHandle Contact)
+{
+ mapLock.Enter();
+ mapIt it;
+ if ((it = datas.find(Contact)) == datas.end())
+ it = datas.insert(make_pair(Contact, new InternalData<Source, Data>(source))).first;
+ (*it).second->lock.Enter();
+ (*it).second->time = 0;
+ Data* data = (*it).second->data;
+ mapLock.Leave();
+ return data;
+}
+
+template <class Source, class Data, class ContactHandle>
+void PerContactData<Source, Data, ContactHandle>::PutData(ContactHandle Contact)
+{
+ mapLock.Enter();
+ datas[Contact]->lock.Leave();
+ ::time(&(datas[Contact]->time));
+ if (!timerID)
+ {
+ timerID = SetTimer(NULL, 0, 30000, RunTimerProc<Source, Data, ContactHandle>);
+ assert(timerID);
+ perContactDataObjects[timerID] = this;
+ }
+ mapLock.Leave();
+}
+
+template <class Source, class Data, class ContactHandle>
+void PerContactData<Source, Data, ContactHandle>::CleanupData()
+{
+ mapLock.Enter();
+ time_t now;
+ time(&now);
+ for (mapIt it = datas.begin(); it != datas.end(); )
+ {
+ if ((*it).second->time) //it's being in use
+ {
+ int diff = (int)difftime(now, (*it).second->time);
+ if (diff >= 30*60) //half of an hour
+ {
+ mapIt tmp = it;
+ it++;
+ delete (*tmp).second;
+ datas.erase(tmp);
+ }
+ else
+ it++;
+ }
+ else
+ it++;
+ }
+ if (timerID && datas.empty()) //timerID may become NULL before locking, so should check
+ {
+ KillTimer(NULL, timerID);
+ perContactDataObjects.erase(timerID);
+ }
+ mapLock.Leave();
+}
+
+template <class Source, class Data, class ContactHandle>
+VOID CALLBACK RunTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ PerContactData<Source, Data, ContactHandle>* val = (PerContactData<Source, Data, ContactHandle>*)perContactDataObjects[idEvent];
+ val->CleanupData();
+}
+
+#endif /* PerContactDataH */ \ No newline at end of file
diff --git a/plugins/Boltun/Engine/TalkEngine.cpp b/plugins/Boltun/Engine/TalkEngine.cpp
new file mode 100644
index 0000000000..a9625dffd2
--- /dev/null
+++ b/plugins/Boltun/Engine/TalkEngine.cpp
@@ -0,0 +1,609 @@
+//***********************************************************
+// Copyright 2008 Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#include "TalkEngine.h"
+#include <fstream>
+#include <windows.h>
+
+#ifdef _DEBUG
+
+//#define DEBUG_PREFIXES
+//#define DEBUG_SHOW_LEVEL
+//#define DEBUG_SHOW_VARIANTS
+//#define DEBUG_SHOW_SOLUTION_REASON
+
+#endif
+
+//Enabling next define will make a bot more stupid:
+//#define EXCLUDE_SPECIAL_WORDS
+
+#ifdef DEBUG_SHOW_VARIANTS
+extern void AddBotMessage(tstring s);
+#endif
+
+using namespace std;
+
+void TalkBot::UpdateStartChar(tstring& str)
+{
+ if (!makeLowercase)
+ return;
+ size_t l = str.length();
+ if (l)
+ {
+ //Answers starting with ' ' must remain unchanged.
+ if (str[0] == _T(' '))
+ {
+ str = str.substr(1);
+ return;
+ }
+ for (size_t i = 0; i < l; i++)
+ {
+ TCHAR cl = (TCHAR)CharLower((LPTSTR)(void*)(long)str[i]);
+ TCHAR cu = (TCHAR)CharUpper((LPTSTR)(void*)(long)str[i]);
+ if (i != l - 1)
+ {
+ //Do not react to BLONDE ANSWERS
+ TCHAR ncl = (TCHAR)CharLower((LPTSTR)(void*)(long)str[i + 1]);
+ TCHAR ncu = (TCHAR)CharUpper((LPTSTR)(void*)(long)str[i + 1]);
+ if (ncl != ncu && str[i + 1] == ncu)
+ break;
+ }
+ if (cl != cu)
+ {
+ str[i] = cl;
+ break;
+ }
+ }
+ }
+}
+
+TalkBot::TalkBot(const Mind& goodMind)
+ :mind(goodMind), beSilent(false), makeLowercase(false),
+ understandAlways(false)
+{
+ contactDatas = new PerContactData<Mind, ContactData, void*>(mind);
+}
+
+TalkBot::~TalkBot()
+{
+ delete contactDatas;
+}
+
+tstring TalkBot::GetInitMessage(void* contact)
+{
+ ContactData* d = contactDatas->GetData(contact);
+ tstring s = d->initial.GetString();
+ contactDatas->PutData(contact);
+ return s;
+}
+
+tstring TalkBot::ReplaceAliases(const tstring &message)
+{
+ const TCHAR dividers[] = _T(" \t\n\r,./?\\|;:'\"~!#^&*()_-+=[{]}\1");
+ tstring sentence = message;
+ tstring result;
+ int len = sentence.length();
+ vector<tstring> words;
+ map<int, tstring> sm;
+ //Find smiles
+ for (size_t i = 0; i < sentence.length() - 1; i++)
+ {
+ unsigned max = sentence.length() - i;
+ if (max > mind.GetData()->maxSmileLen)
+ max = mind.GetData()->maxSmileLen;
+ for (unsigned j = max; j > 0; j--)
+ {
+ tstring item = sentence.substr(i, j);
+ if (mind.GetData()->smiles.find(item)
+ != mind.GetData()->smiles.end())
+ {
+ sm[i] = item;
+ sentence.replace(i, j, _T("\1"));
+ break;
+ }
+ }
+ }
+ len = sentence.length();
+ bool hadQuestionSigns = false;
+ int it = 0;
+ while (it != len)
+ {
+ while (it != len && _tcschr(dividers, sentence[it]))
+ {
+ if (sentence[it] == _T('?'))
+ hadQuestionSigns = true;
+ map<int, tstring>::iterator smit;
+ if (sentence[it] == '\1')
+ {
+ smit = sm.find(it);
+ result.append((*smit).second);
+ }
+ else
+ result.push_back(sentence[it]);
+ it++;
+ }
+ if (it == len)
+ break;
+ int start = it;
+ while (true)
+ {
+ while (it != len && !_tcschr(dividers, sentence[it]))
+ it++;
+ if (it == len || sentence[it] != _T('-'))
+ break;
+ //If we have-a-word-with-minus, we shouldn't split it
+ if (_tcschr(dividers, sentence[it + 1]))
+ break;
+ it += 2;
+ }
+ tstring str = sentence.substr(start, it - start);
+ map<tstring, tstring>::const_iterator al = mind.GetData()->aliases.find(str);
+ if (al != mind.GetData()->aliases.end())
+ result.append((*al).second);
+ else
+ result.append(str);
+ }
+ return result;
+}
+
+tstring TalkBot::AllReplies(const tstring &incomingMessage, ContactData* contactData, Level &maxValue, std::multimap<Level, tstring> &mm)
+{
+ tstring res;
+ //Part 1
+ if (FindExact(contactData, incomingMessage, mind.GetData()->widelyUsed, res)) //widelyUsed
+ {
+ return res;
+ }
+ //Part 2
+ if (FindExact(contactData, incomingMessage, mind.GetData()->study, res)) //study
+ {
+#ifdef DEBUG_PREFIXES
+ mm.insert(make_pair(LOOKSLIKE, _T("(study_all) ")+res));
+#else
+ mm.insert(make_pair(LOOKSLIKE, res));
+#endif
+ maxValue = LOOKSLIKE;
+ }
+ //Part 3
+ vector<tstring> sentences;
+ SplitSectences(incomingMessage, sentences);
+ ValueChooser<> ch(sentences, true); //Using random order of sentences.
+ while ((res = ch.GetString()) != _T(""))
+ {
+ //Part 4
+ if (FindExact(contactData, res, mind.GetData()->widelyUsed, res)) //widelyUsed
+ {
+#ifdef DEBUG_PREFIXES
+ mm.insert(make_pair(BEST, _T("(widelyused_sent) ")+res));
+#else
+ mm.insert(make_pair(BEST, res));
+#endif
+ if (maxValue > BEST)
+ maxValue = BEST;
+ }
+ //Part 5
+ if (FindExact(contactData, res, mind.GetData()->study, res)) //study
+ {
+#ifdef DEBUG_PREFIXES
+ mm.insert(make_pair(LOOKSLIKE, _T("(study_sent) ")+res));
+#else
+ mm.insert(make_pair(LOOKSLIKE, res));
+#endif
+ if (maxValue > LOOKSLIKE)
+ maxValue = LOOKSLIKE;
+ }
+ //Part 6
+ vector<tstring> keywords, otherwords;
+ bool isQuestion;
+ SplitAndSortWords(res, keywords, otherwords, isQuestion);
+ //Part 7, 8
+ res = _T("");
+ FindByKeywords(contactData, keywords, res/*, ures*/, isQuestion); //keywords
+ if (res != _T(""))
+ {
+#ifdef DEBUG_PREFIXES
+ mm.insert(make_pair(LOOKSLIKE, _T("(keywords) ")+res));
+#else
+ mm.insert(make_pair(LOOKSLIKE, res));
+#endif
+ if (maxValue > LOOKSLIKE)
+ maxValue = LOOKSLIKE;
+ }
+/* if (ures != _T(""))
+ {
+#ifdef DEBUG_PREFIXES
+ mm.insert(make_pair(LOOKSLIKE2, _T("(keywords_unstrict) ")+ures));
+#else
+ mm.insert(make_pair(LOOKSLIKE2, ures));
+#endif
+ if (maxValue > LOOKSLIKE2)
+ maxValue = LOOKSLIKE2;
+ }*/
+ //Part 9
+ if (FindByOthers(contactData, otherwords, res, isQuestion)) //specialEscapes
+ {
+#ifdef DEBUG_PREFIXES
+ mm.insert(make_pair(BAD, _T("(otherwords) ")+res));
+#else
+ mm.insert(make_pair(BAD, res));
+#endif
+ if (maxValue > BAD)
+ maxValue = BAD;
+ }
+ }
+ if (!beSilent)
+ {
+ //Part 10
+ if (FindAny(contactData->escape, res)) //escape
+ {
+#ifdef DEBUG_PREFIXES
+ mm.insert(make_pair(FAIL, _T("(escape) ") + res));
+#else
+ mm.insert(make_pair(FAIL, res));
+#endif
+ if (maxValue > FAIL)
+ maxValue = FAIL;
+ }
+ //Part 11
+ if (!understandAlways && FindAny(contactData->failure, res)) //failure
+ {
+#ifdef DEBUG_PREFIXES
+ mm.insert(make_pair(FAIL, _T("(failure) ") + res));
+#else
+ mm.insert(make_pair(FAIL, res));
+#endif
+ if (maxValue > FAIL)
+ maxValue = FAIL;
+ }
+ }
+ return tstring();
+}
+
+TalkBot::MessageInfo* TalkBot::Reply(void* contact, tstring incomingMessage, bool saveChoice)
+{
+ TCHAR* str = new TCHAR[incomingMessage.length()+1];
+ _tcscpy(str, incomingMessage.c_str());
+ CharLower(str);
+ incomingMessage = str;
+ delete str;
+ ContactData* contactData = contactDatas->GetData(contact);
+
+ if (incomingMessage == contactData->lastMessage && GetTickCount() < contactData->lastMessageTime + 30*60*1000)
+ {
+ MessageInfo *info;
+ //only 2-3 repeats
+ if (contactData->repeatCount < 2 || contactData->repeatCount == 2 && (rand() % 2))
+ {
+ const vector<tstring>& v = mind.GetData()->repeats;
+ tstring res = v[rand() % v.size()];
+#ifdef DEBUG_PREFIXES
+ info = new MessageInfo(incomingMessage, _T("(repeat_norm) ") + res);
+#else
+ info = new MessageInfo(incomingMessage, res);
+#endif
+ }
+ else
+#ifdef DEBUG_PREFIXES
+ info = new MessageInfo(incomingMessage, _T("(repeat_silence)"));
+#else
+ info = new MessageInfo(incomingMessage, _T(""));
+#endif
+ if (saveChoice)
+ RecordAnswer(contactData, *info);
+ contactDatas->PutData(contact);
+ return info;
+ }
+
+ multimap<Level, tstring> mm;
+ Level maxValue = NOTHING;
+
+ tstring res = AllReplies(incomingMessage, contactData, maxValue, mm);
+ if (!res.empty())
+ {
+ UpdateStartChar(res);
+#ifdef DEBUG_PREFIXES
+ MessageInfo *info = new MessageInfo(incomingMessage, _T("(widelyused_all) ") + res);
+#else
+ MessageInfo *info = new MessageInfo(incomingMessage, res);
+#endif
+ if (saveChoice)
+ RecordAnswer(contactData, *info);
+ contactDatas->PutData(contact);
+ return info;
+ }
+
+ incomingMessage = ReplaceAliases(incomingMessage);
+
+ res = AllReplies(incomingMessage, contactData, maxValue, mm);
+ if (!res.empty())
+ {
+ UpdateStartChar(res);
+#ifdef DEBUG_PREFIXES
+ MessageInfo *info = new MessageInfo(incomingMessage, _T("(widelyused_all) ") + res);
+#else
+ MessageInfo *info = new MessageInfo(incomingMessage, res);
+#endif
+ if (saveChoice)
+ RecordAnswer(contactData, *info);
+ contactDatas->PutData(contact);
+ return info;
+ }
+
+ //Also does Part 12
+ tstring final = ChooseResult(contactData, maxValue, mm);
+ MessageInfo *info = new MessageInfo(incomingMessage, final);
+ UpdateStartChar(final);
+ if (saveChoice)
+ RecordAnswer(contactData, *info);
+ contactDatas->PutData(contact);
+ return info;
+}
+
+bool TalkBot::FindExact(ContactData* contactData, const tstring &incomingMessage,
+ const multimap<tstring, tstring>& map, tstring& res)
+{
+ int max = map.count(incomingMessage);
+ if (!max)
+ {
+ TCHAR c = incomingMessage[incomingMessage.length() - 1];
+ if (c != _T('?') && c != _T('.') && c != _T('!'))
+ return FindExact(contactData, incomingMessage + _T('.'), map, res);
+ return false;
+ }
+ pair<mm_cit, mm_cit> range = map.equal_range(incomingMessage);
+ for (mm_cit it = range.first; it != range.second; it++)
+ contactData->chooser.AddChoice((*it).second);
+ res = contactData->chooser.Choose();
+ return true;
+}
+
+void TalkBot::AnswerGiven(void* contact, const TalkBot::MessageInfo& info)
+{
+ ContactData* contactData = contactDatas->GetData(contact);
+ RecordAnswer(contactData, info);
+ contactDatas->PutData(contact);
+}
+
+void TalkBot::RecordAnswer(ContactData *contactData, const TalkBot::MessageInfo& info)
+{
+ contactData->chooser.SaveChoice(info.Answer);
+ if (contactData->lastMessage == info.Question)
+ contactData->repeatCount++;
+ else
+ contactData->repeatCount = 0;
+ contactData->lastMessageTime = GetTickCount();
+ contactData->lastMessage = info.Question;
+}
+
+bool TalkBot::FindAny(ValueChooser<> &ch, tstring& res)
+{
+ if (!ch.GetContainer().size())
+ return false;
+ res = ch.GetString();
+ return true;
+}
+
+void TalkBot::SplitSectences(const tstring &incomingMessage, vector<tstring>& vec)
+{
+ //FIXME: (THINK ABOUT IT:-) )these chars not always mark the end of sentence.
+ const TCHAR symbols[] = _T(".?!");
+ int it = 0, len = incomingMessage.length();
+ while (it != len)
+ {
+ while (it != len && _istspace(incomingMessage[it]))
+ it++;
+ int start = it;
+ while (it != len)
+ {
+ if (_tcschr(symbols, incomingMessage[it++]))
+ {
+ //Test for a :-! smile
+ if (it > 2 && incomingMessage[it-1] == _T('!')
+ && incomingMessage[it-2] == _T('-')
+ && incomingMessage[it-3] == _T(':'))
+ continue;
+ while (it != len && _tcschr(symbols, incomingMessage[it]))
+ it++;
+ break;
+ }
+ }
+ vec.insert(vec.end(), incomingMessage.substr(start, it - start));
+ }
+}
+
+#ifdef _DEBUG
+tstring LevelToStr(TalkBot::Level target)
+{
+ tstring lev;
+ switch (target)
+ {
+ case TalkBot::BEST: lev = _T("BEST(0)"); break;
+ case TalkBot::LOOKSLIKE: lev = _T("LOOKSLIKE(1)"); break;
+ case TalkBot::BAD: lev = _T("BAD(2)"); break;
+ case TalkBot::FAIL: lev = _T("FAIL(3)"); break;
+ case TalkBot::NOTHING: lev = _T("NOTHING(4)"); break;
+ }
+ return lev;
+}
+#endif
+
+tstring TalkBot::ChooseResult(ContactData* contactData, Level maxValue, const multimap<Level, tstring> &mm)
+{
+#ifdef DEBUG_SHOW_VARIANTS
+ AddBotMessage(_T(">>Availabe:"));
+ for (multimap<Level, tstring>::iterator it = mm.begin(); it != mm.end(); it++)
+ AddBotMessage(LevelToStr((*it).first) + _T(": ") + (*it).second);
+ AddBotMessage(_T(">>Result:"));
+#endif
+ if (maxValue == NOTHING)
+ return _T("");
+ Level target = maxValue;
+ int num = mm.count(target);
+/* if (!num)
+ {
+ target = maxValue;
+ num = mm.count(target);
+ }*/
+ typedef multimap<Level, tstring>::const_iterator lt_cit;
+ pair<lt_cit,lt_cit> range = mm.equal_range(target);
+ for (lt_cit it = range.first; it != range.second; it++)
+ contactData->chooser.AddChoice((*it).second);
+#ifdef DEBUG_SHOW_LEVEL
+ tstring lev = LevelToStr(target);
+ return lev + _T(": ") + contactData->chooser.Choose();
+#else
+ return contactData->chooser.Choose();
+#endif
+}
+
+void TalkBot::FindByKeywords(ContactData* contactData, const vector<tstring> &keywords, tstring& res/*, tstring& ures*/,
+ bool isQuestion)
+{
+ if (keywords.size() == 0)
+ return;
+ const multimap<WordsList, tstring> &keys = isQuestion ? mind.GetData()->qkeywords :
+ mind.GetData()->keywords;
+ for (multimap<WordsList, tstring>::const_iterator it = keys.begin(); it != keys.end(); it++)
+ {
+ float prio;
+ if ((*it).first.MatchesAll(keywords/*, strict*/, prio))
+#ifdef DEBUG_SHOW_SOLUTION_REASON
+ contactData->chooser.AddChoice((tstring)(*it).first + _T(": - ") + (*it).second, prio);
+#else
+ contactData->chooser.AddChoice((*it).second, prio);
+#endif
+ }
+ res = contactData->chooser.Choose();
+}
+
+bool TalkBot::FindByOthers(ContactData* contactData, const vector<tstring> &otherwords, tstring& res, bool isQuestion)
+{
+ //vector<tstring> results;
+ const multimap<WordsList, tstring> &specs = isQuestion ? mind.GetData()->qspecialEscapes :
+ mind.GetData()->specialEscapes;
+ for (multimap<WordsList, tstring>::const_iterator it = specs.begin();
+ it != specs.end(); it++)
+ if ((*it).first.MatchesAny(otherwords))
+ {
+#ifdef DEBUG_SHOW_SOLUTION_REASON
+ contactData->chooser.AddChoice((tstring)(*it).first + _T(": - ") + (*it).second);
+#else
+ contactData->chooser.AddChoice((*it).second);
+#endif
+ }
+ res = contactData->chooser.Choose();
+ if (res.empty())
+ return false;
+ return true;
+}
+
+const Mind& TalkBot::GetMind() const
+{
+ return mind;
+}
+
+void TalkBot::SplitAndSortWords(tstring sentence, vector<tstring>& keywords,
+ vector<tstring>& otherwords, bool& isQuestion)
+{
+ const TCHAR dividers[] = _T(" \t\n\r,./?\\|;:'\"~!#^&*()_-+=[{]}");
+ int len = sentence.length();
+ vector<tstring> words;
+ map<int, tstring> sm;
+ //Find smiles
+ for (size_t i = 0; i < sentence.length() - 1; i++)
+ {
+ unsigned max = sentence.length() - i;
+ if (max > mind.GetData()->maxSmileLen)
+ max = mind.GetData()->maxSmileLen;
+ for (unsigned j = max; j > 0; j--)
+ {
+ tstring item = sentence.substr(i, j);
+ if (mind.GetData()->smiles.find(item)
+ != mind.GetData()->smiles.end())
+ {
+ sm[i] = item;
+ sentence.replace(i, j, _T(" "));
+ break;
+ }
+ }
+ }
+ len = sentence.length();
+ bool hadQuestionSigns = false;
+ int it = 0;
+ while (it != len)
+ {
+ while (it != len && _tcschr(dividers, sentence[it]))
+ {
+ if (sentence[it] == _T('?'))
+ hadQuestionSigns = true;
+ map<int, tstring>::iterator smit;
+ if (_istspace(sentence[it]) && (smit = sm.find(it)) != sm.end())
+ words.push_back((*smit).second);
+ it++;
+ }
+ if (it == len)
+ break;
+ hadQuestionSigns = false;
+ int start = it;
+ while (true)
+ {
+ while (it != len && !_tcschr(dividers, sentence[it]))
+ it++;
+ if (it == len || sentence[it] != _T('-'))
+ break;
+ //If we have-a-word-with-minus, we shouldn't split it
+ if (_tcschr(dividers, sentence[it + 1]))
+ break;
+ it += 2;
+ }
+ tstring str = sentence.substr(start, it - start);
+ words.push_back(str);
+ }
+ isQuestion = hadQuestionSigns;
+ for (vector<tstring>::iterator it = words.begin(); it != words.end(); it++)
+ {
+ if (!isQuestion)
+ {
+ if (mind.GetData()->question.find(*it) != mind.GetData()->question.end())
+ isQuestion = true;
+ }
+ if (mind.GetData()->special.find(*it) != mind.GetData()->special.end())
+ otherwords.push_back(*it);
+#ifdef EXCLUDE_SPECIAL_WORDS
+ else
+#endif
+ keywords.push_back(*it);
+ }
+}
+
+void TalkBot::SetSilent(const bool isSilent)
+{
+ beSilent = isSilent;
+}
+
+void TalkBot::SetLowercase(const bool isLowercase)
+{
+ makeLowercase = isLowercase;
+}
+
+void TalkBot::SetUnderstandAlways(const bool understandAlways)
+{
+ this->understandAlways = understandAlways;
+} \ No newline at end of file
diff --git a/plugins/Boltun/Engine/TalkEngine.h b/plugins/Boltun/Engine/TalkEngine.h
new file mode 100644
index 0000000000..364f4193d1
--- /dev/null
+++ b/plugins/Boltun/Engine/TalkEngine.h
@@ -0,0 +1,112 @@
+//***********************************************************
+// Copyright 2008 Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#ifndef TalkEngineH
+#define TalkEngineH
+
+#include "Mind.h"
+#include "ValueChooser.h"
+#include "PerContactData.h"
+#include "UnrecentChooser.h"
+
+class TalkBot
+{
+public:
+ struct MessageInfo
+ {
+ private:
+ tstring Question;
+ MessageInfo(tstring q, tstring a)
+ :Question(q), Answer(a)
+ {
+ }
+ public:
+ tstring Answer;
+ MessageInfo(tstring q)
+ :Question(q)
+ {
+ }
+ friend class TalkBot;
+ };
+private:
+ typedef enum
+ {
+ BEST, LOOKSLIKE/*, LOOKSLIKE2*/, BAD, FAIL, NOTHING
+ } Level;
+ friend tstring LevelToStr(TalkBot::Level target);
+
+ struct ContactData
+ {
+ ValueChooser<> initial;
+ //ValueChooser<std::set<tstring> > question;
+ //ValueChooser<std::set<tstring> > special;
+ ValueChooser<> escape;
+ ValueChooser<> failure;
+ UnRecentChooser chooser;
+ tstring lastMessage;
+ long long lastMessageTime;
+ int repeatCount;
+ inline ContactData(const Mind& mind)
+ :initial(mind.GetData()->initial),
+ //question(mind.GetData()->question),
+ //special(mind.GetData()->special),
+ escape(mind.GetData()->escape),
+ failure(mind.GetData()->failure),
+ repeatCount(0)
+ {
+ }
+ };
+
+ PerContactData<Mind, ContactData, void*>* contactDatas;
+ const Mind mind;
+ bool beSilent;
+ bool makeLowercase;
+ bool understandAlways;
+ void UpdateStartChar(tstring& str);
+ typedef std::multimap<tstring, tstring>::const_iterator mm_cit;
+ bool FindExact(ContactData* contactData, const tstring &incomingMessage,
+ const std::multimap<tstring, tstring>& map, tstring& res);
+ bool FindAny(ValueChooser<> &ch, tstring& res);
+ void FindByKeywords(ContactData* contactData, const std::vector<tstring> &keywords, tstring& res/*, tstring& ures*/, bool isQuestion);
+ bool FindByOthers(ContactData* contactData, const std::vector<tstring> &otherwords, tstring& res, bool isQuestion);
+ tstring AllReplies(const tstring &incomingMessage, ContactData* contactData, Level &maxValue, std::multimap<Level, tstring> &mm);
+ tstring ReplaceAliases(const tstring &message);
+ tstring ChooseResult(ContactData* contactData, Level maxValue, const std::multimap<Level, tstring> &mm);
+ void RecordAnswer(ContactData *contactData, const TalkBot::MessageInfo& info);
+#ifdef _DEBUG
+public:
+#endif
+ void SplitSectences(const tstring &incomingMessage, std::vector<tstring>& vec);
+ void SplitAndSortWords(tstring sentence, std::vector<tstring>& keywords,
+ std::vector<tstring>& otherwords, bool& isQuestion);
+public:
+ TalkBot(const Mind& goodMind);
+ ~TalkBot();
+ const Mind& GetMind() const;
+ void SetSilent(const bool isSilent);
+ void SetLowercase(const bool isLowercase);
+ void SetUnderstandAlways(const bool understandAlways);
+ //const MindData *GetData();
+ tstring GetInitMessage(void* contact);
+ MessageInfo* Reply(void* contact, const tstring incomingMessage, bool saveChoice);
+ void AnswerGiven(void* contact, const MessageInfo& info);
+};
+
+#endif
diff --git a/plugins/Boltun/Engine/UnrecentChooser.cpp b/plugins/Boltun/Engine/UnrecentChooser.cpp
new file mode 100644
index 0000000000..069d84f377
--- /dev/null
+++ b/plugins/Boltun/Engine/UnrecentChooser.cpp
@@ -0,0 +1,100 @@
+//***********************************************************
+// Copyright 2008 Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#include "UnrecentChooser.h"
+
+using namespace std;
+
+UnRecentChooser::UnRecentChooser()
+ :last(-1), min(-1), newItemsPrio(-1), maxOldPrio(-1)
+{
+}
+
+void UnRecentChooser::AddChoice(tstring value, float prio)
+{
+ if (items.count(value) != 0)
+ {
+ int val = items[value];
+ oldItems.insert(make_pair(val, value));
+ oldPrios.insert(make_pair(value, prio));
+ if (min > val || min == -1)
+ min = val;
+ if (maxOldPrio < prio)
+ maxOldPrio = prio;
+ }
+ else
+ {
+ if (prio > newItemsPrio)
+ {
+ newItems.push_back(value);
+ newItemsPrio = prio;
+ }
+ }
+}
+
+tstring UnRecentChooser::Choose()
+{
+ tstring res;
+ //Find answer
+ if (newItemsPrio != -1)
+ {
+ int num = rand() % newItems.size();
+ res = newItems[num];
+ }
+ else
+ if (min == -1)
+ res = _T("");
+ else
+ {
+ float minprio = maxOldPrio / 1.5F;
+ while (oldPrios[oldItems[min]] < minprio)
+ min++;
+ res = oldItems[min];
+ }
+ //Clean items
+ min = -1;
+ newItemsPrio = -1;
+ maxOldPrio = -1;
+ oldItems.clear();
+ oldPrios.clear();
+ newItems.clear();
+ return res;
+}
+
+void UnRecentChooser::SaveChoice(tstring choice)
+{
+ //Add answer
+ if (items.find(choice) != items.end())
+ {
+ for (vector<tstring>::iterator it = itemsList.begin(); it != itemsList.end(); it++)
+ if (*it == choice)
+ {
+ itemsList.erase(it);
+ break;
+ }
+ }
+ items[choice] = ++last;
+ itemsList.push_back(choice);
+ if (itemsList.size() > maxItems)
+ {
+ items.erase(*itemsList.begin());
+ itemsList.erase(itemsList.begin());
+ }
+} \ No newline at end of file
diff --git a/plugins/Boltun/Engine/UnrecentChooser.h b/plugins/Boltun/Engine/UnrecentChooser.h
new file mode 100644
index 0000000000..91a961e307
--- /dev/null
+++ b/plugins/Boltun/Engine/UnrecentChooser.h
@@ -0,0 +1,47 @@
+//***********************************************************
+// Copyright 2008 Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#ifndef UnRecentChooserH
+#define UnRecentChooserH
+
+#include <map>
+#include <vector>
+#include <string>
+#include "tstring.h"
+
+class UnRecentChooser
+{
+ std::map<tstring, size_t> items;
+ std::vector<tstring> itemsList;
+ std::vector<tstring> newItems;
+ float newItemsPrio, maxOldPrio;
+ std::map<size_t, tstring> oldItems;
+ std::map<tstring, float> oldPrios;
+ size_t last;
+ int min;
+ static const size_t maxItems = 100;
+public:
+ UnRecentChooser();
+ void AddChoice(tstring value, float prio = 1.0);
+ tstring Choose();
+ void SaveChoice(tstring choice);
+};
+
+#endif /* UnRecentChooserH */ \ No newline at end of file
diff --git a/plugins/Boltun/Engine/ValueChooser.h b/plugins/Boltun/Engine/ValueChooser.h
new file mode 100644
index 0000000000..3fb1510609
--- /dev/null
+++ b/plugins/Boltun/Engine/ValueChooser.h
@@ -0,0 +1,88 @@
+//***********************************************************
+// Copyright 2008 Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#ifndef StringChooserH
+#define StringChooserH
+
+#include <vector>
+#include <string>
+
+template<class container = std::vector<tstring> >
+class ValueChooser
+{
+private:
+ int freeNumbers;
+ bool *numbers;
+ const container data;
+ bool notifyOnReset;
+public:
+ ValueChooser(const container& vec, bool NotifyOnReset = false)
+ :data(vec), notifyOnReset(NotifyOnReset)
+ {
+ //randomize();
+ numbers = NULL;
+ UpdateLength();
+ }
+
+ ~ValueChooser()
+ {
+ delete numbers;
+ }
+
+ void UpdateLength()
+ {
+ delete numbers; //normal if numbers == NULL
+ numbers = new bool[data.size()];
+ Reset();
+ }
+
+ void Reset()
+ {
+ for (size_t i = 0; i < data.size(); i++)
+ numbers[i] = false;
+ freeNumbers = data.size();
+ }
+
+ typename container::value_type GetString()
+ {
+ if (!freeNumbers)
+ {
+ Reset();
+ if (notifyOnReset)
+ return _T("");
+ }
+ int result;
+ while (numbers[result = rand() % data.size()])
+ ;
+ freeNumbers--;
+ numbers[result] = true;
+ return data[result];
+ }
+
+ container GetContainer() const;
+};
+
+template<class container>
+container ValueChooser<container>::GetContainer() const
+{
+ return data;
+}
+
+#endif
diff --git a/plugins/Boltun/Engine/WordsList.cpp b/plugins/Boltun/Engine/WordsList.cpp
new file mode 100644
index 0000000000..5e5d0c37a5
--- /dev/null
+++ b/plugins/Boltun/Engine/WordsList.cpp
@@ -0,0 +1,169 @@
+//***********************************************************
+// Copyright 2008 Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#include "WordsList.h"
+
+using namespace std;
+
+WordsList::WordsList(const tstring &data/*, bool allowUnstrict*/)
+{
+ Parse(data/*, allowUnstrict*/);
+}
+
+WordsList::operator tstring() const
+{
+ tstring res;
+ //if (unstrict)
+ // res = _T("~");
+ set<tstring>::const_iterator it = words.begin();
+ if (!words.empty())
+ while (true)
+ {
+ res += *it;
+ it++;
+ if (it != words.end())
+ res += _T(" ");
+ else
+ break;
+ }
+ res += isQuestion ? _T("?") : _T(".");
+ return res;
+}
+
+WordsList& WordsList::operator= (const tstring& s)
+{
+ Parse(s);
+ return *this;
+};
+
+void WordsList::Parse(tstring s/*, bool allowUnstrict*/)
+{
+ isQuestion = false;
+ /*if (allowUnstrict && s.length() && s[0] == _T('~'))
+ {
+ s = s.substr(1, s.npos);
+ unstrict = true;
+ }
+ else
+ unstrict = false;*/
+ int len = s.length() - 1;
+ while (len != -1 && _istspace(s[len]))
+ len--;
+ if (len < 0)
+ return;
+ if (s[len] == '?')
+ isQuestion = true;
+ else
+ if (s[len] != '.')
+ return;
+ s.resize(len);
+ int it = 0;
+ while (it != len)
+ {
+ while (it != len && _istspace(s[it]))
+ it++;
+ if (it == len)
+ break;
+ int start = it;
+ while (it != len && !_istspace(s[it]))
+ it++;
+ words.insert(s.substr(start, it - start));
+ }
+}
+
+bool WordsList::MatchesAll(const vector<tstring>& s/*, bool& WasStrict*/, float& priority) const
+{
+ std::set<tstring> temp;
+ //WasStrict = true;
+ for (vector<tstring>::const_iterator it = s.begin(); it != s.end(); it++)
+ {
+/* if (words.find(*it) == words.end())
+ if (unstrict)
+ {
+ WasStrict = false;
+ continue;
+ }
+ else
+ return false;
+ temp.insert((*it));*/
+ if (words.find(*it) != words.end())
+ temp.insert((*it));
+ }
+ if (temp.size() != words.size())
+ return false;
+ priority = words.size() * words.size() / (float)s.size();
+ return temp.size() == words.size();
+}
+
+bool WordsList::MatchesAny(const vector<tstring>& s) const
+{
+ for (vector<tstring>::const_iterator it = s.begin(); it != s.end(); it++)
+ if (words.find(*it) != words.end())
+ return true;
+ return false;
+}
+
+vector<tstring> WordsList::ConsistsOf(const set<tstring>& list) const
+{
+ vector<tstring> res;
+ for (set<tstring>::const_iterator it = words.begin(); it != words.end(); it++)
+ if (list.find(*it) == list.end())
+ res.push_back(*it);
+ return res;
+}
+
+vector<tstring> WordsList::DoesntIncludeAny(const set<tstring>& list) const
+{
+ vector<tstring> res;
+ for (set<tstring>::const_iterator it = words.begin(); it != words.end(); it++)
+ if (list.find(*it) != list.end())
+ res.push_back(*it);
+ return res;
+}
+
+bool WordsList::operator<(const WordsList& value) const
+{
+ return (tstring)*this < (tstring)value;
+}
+
+bool WordsList::operator!=(const WordsList& value) const
+{
+ return (tstring)*this != (tstring)value;
+}
+
+bool WordsList::operator==(const WordsList& value) const
+{
+ return (tstring)*this == (tstring)value;
+}
+
+size_t WordsList::Size() const
+{
+ return words.size();
+}
+
+bool WordsList::IsQuestion() const
+{
+ return isQuestion;
+}
+
+bool WordsList::IsEmpty() const
+{
+ return words.size() == 0;
+} \ No newline at end of file
diff --git a/plugins/Boltun/Engine/WordsList.h b/plugins/Boltun/Engine/WordsList.h
new file mode 100644
index 0000000000..bd74b2007b
--- /dev/null
+++ b/plugins/Boltun/Engine/WordsList.h
@@ -0,0 +1,56 @@
+//***********************************************************
+// Copyright 2008 Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#ifndef WordsListH
+#define WordsListH
+
+#include <set>
+#include <vector>
+#include <string>
+#include "tchar.h"
+#include "tstring.h"
+
+class WordsList
+{
+ WordsList();
+ void Parse(tstring s/*, bool allowUnstrict = false*/);
+ //bool unstrict;
+#ifdef _DEBUG
+public:
+#endif
+ std::set<tstring> words;
+ bool isQuestion;
+public:
+ WordsList(const tstring &data/*, bool allowUnstrict = false*/);
+ operator tstring() const;
+ bool MatchesAll(const std::vector<tstring>& s/*, bool& WasStrict*/, float& priority) const;
+ bool MatchesAny(const std::vector<tstring>& s) const;
+ std::vector<tstring> ConsistsOf(const std::set<tstring>& list) const;
+ std::vector<tstring> DoesntIncludeAny(const std::set<tstring>& list) const;
+ WordsList& operator= (const tstring& s);
+ bool operator<(const WordsList& value) const;
+ bool operator==(const WordsList& value) const;
+ bool operator!=(const WordsList& value) const;
+ bool IsQuestion() const;
+ bool IsEmpty() const;
+ size_t Size() const;
+};
+
+#endif
diff --git a/plugins/Boltun/Engine/boltun.mindw b/plugins/Boltun/Engine/boltun.mindw
new file mode 100644
index 0000000000..a6f9f2103d
--- /dev/null
+++ b/plugins/Boltun/Engine/boltun.mindw
Binary files differ
diff --git a/plugins/Boltun/Engine/tstring.h b/plugins/Boltun/Engine/tstring.h
new file mode 100644
index 0000000000..e21984a12c
--- /dev/null
+++ b/plugins/Boltun/Engine/tstring.h
@@ -0,0 +1,34 @@
+//***********************************************************
+// Copyright 2008 Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#ifndef TSTRING_H
+#define TSTRING_H
+
+#include <tchar.h>
+#include <string>
+
+#ifndef TCHAR
+#define TCHAR _TCHAR
+#endif
+
+typedef std::basic_string<TCHAR, std::char_traits<TCHAR>,
+ std::allocator<TCHAR> > tstring;
+
+#endif
diff --git a/plugins/Boltun/TODO.txt b/plugins/Boltun/TODO.txt
new file mode 100644
index 0000000000..6ea2151d2d
--- /dev/null
+++ b/plugins/Boltun/TODO.txt
@@ -0,0 +1,35 @@
+TODO list:
+
+--------------------------------------------------------
+Release-critical:
+
+- Add study capability to engine
+
+Done:
+- Add reaction for duplicate phrases.
+- Add aliases.
+- Check for critical section double enter
+- Multicontact talk support in engine
+- Add "Start talking" option to cantact menu.
+- Check bot warning.
+- Add "be silent, not stupid" to options
+- Add start answers with a little letter.
+- Add README about bot algorithm.
+- Add README for mind file format.
+- Add "don't use "don't understand"" option
+- Division between question and non-question sentenses
+- Empty keywords or specials should not be loaded
+- Check "-"
+- Check :-) on ""
+- Add answer-on status info to the readme.
+- Make AI options dependent.
+- Update mind.txt with UpdateStartChar
+- Sort keywords matches by priority
+- Use chooser everywhere
+
+--------------------------------------------------------
+Future:
+- Speed-up loading
+- Load mind from UTF8 files
+- Expert mode support
+- Add different choises of reaction for message series.
diff --git a/plugins/Boltun/actionQueue.cpp b/plugins/Boltun/actionQueue.cpp
new file mode 100644
index 0000000000..7040778c85
--- /dev/null
+++ b/plugins/Boltun/actionQueue.cpp
@@ -0,0 +1,256 @@
+//***********************************************************
+// Copyright 2003-2008 Alexander S. Kiselev, Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#include "actionQueue.h"
+#include "config.h"
+#include "boltun.h"
+#include "Engine/tstring.h"
+#include "Engine/TalkEngine.h"
+
+#include <list>
+#include <set>
+#include <time.h>
+#include "Engine/CriticalSection.h"
+#ifdef _DEBUG
+#include <assert.h>
+#endif
+
+#define MIRANDA_VER 0x0700
+#include "newpluginapi.h"
+#include "m_database.h"
+#include "m_system.h"
+#include "m_protosvc.h"
+
+using namespace std;
+
+extern TalkBot* bot;
+
+typedef void (*ActionHandler)(HANDLE hContact, const TalkBot::MessageInfo *inf);
+
+typedef struct _QueueElement {
+ HANDLE hContact;
+ const TalkBot::MessageInfo *inf;
+ ActionHandler Handler;
+ bool Sticky;
+ int TimeOffset;
+ _QueueElement(HANDLE contact, ActionHandler handler, int timeOffset, const TalkBot::MessageInfo *info = NULL, bool sticky = false)
+ :hContact(contact), Handler(handler), TimeOffset(timeOffset), inf(info), Sticky(sticky)
+ {
+ }
+} QueueElement;
+
+static list<QueueElement> actionQueue;
+static set<HANDLE> typingContacts;
+UINT_PTR timerID = 0;
+
+CriticalSection cs;
+CriticalSection typingContactsLock;
+
+void UpdateTimer();
+
+VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ cs.Enter();
+ QueueElement q = actionQueue.front();
+ actionQueue.pop_front();
+ UpdateTimer();
+ cs.Leave();
+ q.Handler(q.hContact, q.inf);
+}
+
+void UpdateTimer()
+{
+ if (timerID)
+ KillTimer(NULL, timerID);
+ if (actionQueue.size())
+ timerID = SetTimer(NULL, 0, actionQueue.front().TimeOffset, TimerProc);
+ else
+ timerID = 0;
+}
+
+static bool NotifyTyping(HANDLE hContact)
+{
+ int res = DBGetContactSettingByte(hContact, "SRMsg", "SupportTyping", 2);
+ if (res == 2)
+ res = DBGetContactSettingByte(NULL, "SRMsg", "DefaultTyping", 1);
+ return res != 0;
+}
+
+static char *MsgServiceName(HANDLE hContact)
+{
+#ifdef _UNICODE
+ char szServiceName[100];
+ char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (szProto == NULL)
+ return PSS_MESSAGE;
+
+ mir_snprintf(szServiceName, sizeof(szServiceName), "%s%sW", szProto, PSS_MESSAGE);
+ if (ServiceExists(szServiceName))
+ return PSS_MESSAGE "W";
+#endif
+ return PSS_MESSAGE;
+}
+
+static void TimerAnswer(HANDLE hContact, const TalkBot::MessageInfo* info)
+{
+ DBEVENTINFO ldbei;
+ int size = info->Answer.length() + 1;
+ int bufsize = size;
+ char* msg;
+#ifdef UNICODE
+ bufsize *= sizeof(TCHAR) + 1;
+ msg = new char[bufsize];
+ //msg[size - 1] = '\0';
+
+ if (!WideCharToMultiByte(CP_ACP, 0, info->Answer.c_str(), -1, msg, size,
+ NULL, NULL))
+ FillMemory(msg, size - 1, '-'); //In case of fault return "----" in ANSI part
+ CopyMemory(msg + size, info->Answer.c_str(), size * 2);
+#else
+ msg = respItem->szMes;
+#endif
+
+ CallContactService(hContact, MsgServiceName(hContact), PREF_TCHAR, (LPARAM)msg);
+
+ ZeroMemory(&ldbei, sizeof(ldbei));
+ ldbei.cbSize = sizeof(ldbei);
+ //FIXME: Error may happen
+ ldbei.cbBlob = bufsize;
+ ldbei.pBlob = (PBYTE)(void*)msg;
+ ldbei.eventType = EVENTTYPE_MESSAGE;
+ ldbei.flags = DBEF_SENT;
+ ldbei.szModule = BOLTUN_NAME;
+ ldbei.timestamp = (DWORD)time(NULL);
+
+ CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&ldbei);
+ bot->AnswerGiven(hContact, *info);
+ delete info;
+#ifdef UNICODE
+ delete msg;
+#endif
+ typingContactsLock.Enter();
+ typingContacts.erase(hContact);
+ typingContactsLock.Leave();
+}
+
+static void StartTyping(HANDLE hContact, const TalkBot::MessageInfo*)
+{
+ CallService(MS_PROTO_SELFISTYPING, (WPARAM)hContact,
+ (LPARAM)PROTOTYPE_SELFTYPING_ON);
+ typingContactsLock.Enter();
+ typingContacts.insert(hContact);
+ typingContactsLock.Leave();
+}
+
+void DoAnswer(HANDLE hContact, const TalkBot::MessageInfo *info, bool sticky = false)
+{
+ if (info->Answer[0] == _T('\0'))
+ return;
+ int waitTime, thinkTime = 0;
+ int defWaitTime = Config.AnswerPauseTime * 1000;
+ if (Config.PauseDepends)
+ waitTime = defWaitTime * info->Answer.length() / 25;
+ else
+ waitTime = defWaitTime;
+ if (Config.PauseRandom)
+ {
+ //Let it be up to 4 times longer.
+ waitTime = waitTime * (rand() % 300) / 100 + waitTime;
+ }
+ if (waitTime == 0)
+ waitTime = 50; //it's essential, because otherwise message will be added later
+ //then its response, that will cause incorrect ordering of
+ //messages in the opened history (reopening will
+ //help, but anyway it's no good)
+ if (NotifyTyping(hContact) && Config.AnswerThinkTime)
+ {
+ thinkTime = Config.AnswerThinkTime * 1000;
+ if (Config.PauseRandom)
+ {
+ //Let it be up to 4 times longer.
+ thinkTime = thinkTime * (rand() % 300) / 100 + thinkTime;
+ }
+ }
+ cs.Enter();
+ //Check if this contact's timer handler is now waiting for a cs.
+ bool needTimerRearrange = false;
+ if (!actionQueue.empty() && actionQueue.front().hContact == hContact)
+ {
+ needTimerRearrange = true;
+ KillTimer(NULL, timerID);
+ cs.Leave();
+ cs.Enter();
+ }
+ if (!actionQueue.empty())
+ {
+ list<QueueElement>::iterator it = actionQueue.end();
+ it--;
+ while (true)
+ {
+ if ((*it).hContact == hContact)
+ {
+ if ((*it).Sticky)
+ break;
+ list<QueueElement>::iterator tmp = it;
+ if (tmp != actionQueue.begin())
+ tmp--;
+ actionQueue.erase(it);
+ it = tmp;
+ if (actionQueue.empty())
+ break;
+ }
+ if (it == actionQueue.begin())
+ break;
+ it--;
+ }
+ }
+ typingContactsLock.Enter();
+ if (typingContacts.find(hContact) != typingContacts.end())
+ {
+ CallService(MS_PROTO_SELFISTYPING, (WPARAM)hContact, (LPARAM)PROTOTYPE_SELFTYPING_OFF);
+ typingContacts.erase(hContact);
+ }
+ typingContactsLock.Leave();
+ if (actionQueue.empty())
+ needTimerRearrange = true;
+ if (thinkTime)
+ actionQueue.push_back(QueueElement(hContact, StartTyping, thinkTime, NULL, sticky));
+ actionQueue.push_back(QueueElement(hContact, TimerAnswer, waitTime, info, sticky));
+ if (needTimerRearrange)
+ UpdateTimer();
+ cs.Leave();
+}
+
+void AnswerToContact(HANDLE hContact, const TCHAR* messageToAnswer)
+{
+ if (Config.TalkWarnContacts && DBGetContactSettingByte(hContact, BOLTUN_KEY,
+ DB_CONTACT_WARNED, FALSE) == FALSE)
+ {
+ DoAnswer(hContact, new TalkBot::MessageInfo((const TCHAR*)Config.WarnText), true);
+ DBWriteContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_WARNED, TRUE);
+ }
+ else
+ DoAnswer(hContact, bot->Reply(hContact, messageToAnswer, false));
+}
+
+void StartChatting(HANDLE hContact)
+{
+ DoAnswer(hContact, new TalkBot::MessageInfo(bot->GetInitMessage(hContact)), true);
+}
diff --git a/plugins/Boltun/actionQueue.h b/plugins/Boltun/actionQueue.h
new file mode 100644
index 0000000000..78f6ce5f9e
--- /dev/null
+++ b/plugins/Boltun/actionQueue.h
@@ -0,0 +1,30 @@
+//***********************************************************
+// Copyright 2003-2008 Alexander S. Kiselev, Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#ifndef ACTIONQUEUE_H
+#define ACTIONQUEUE_H
+
+#include <windows.h>
+
+void AnswerToContact(HANDLE hContact, const TCHAR* messageToAnswer);
+
+void StartChatting(HANDLE hContact);
+
+#endif /* ACTIONQUEUE_H */ \ No newline at end of file
diff --git a/plugins/Boltun/boltun.cpp b/plugins/Boltun/boltun.cpp
new file mode 100644
index 0000000000..e0f85661b0
--- /dev/null
+++ b/plugins/Boltun/boltun.cpp
@@ -0,0 +1,718 @@
+//***********************************************************
+// Copyright 2003-2008 Alexander S. Kiselev, Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#define MIRANDA_VER 0x0700
+
+#include "Engine/TalkEngine.h"
+
+#include <windows.h>
+#include <time.h>
+#include <string>
+
+#include "newpluginapi.h"
+#include "m_clist.h"
+#include "m_skin.h"
+#include "m_database.h"
+#include "m_system.h"
+#include "m_protosvc.h"
+#include "m_options.h"
+#include "m_langpack.h"
+#include "resource.h"
+
+#include "resource.h"
+
+#include "boltun.h"
+#include "config.h"
+#include "actionQueue.h"
+
+//#define DEBUG_LOAD_TIME
+
+struct MM_INTERFACE mmi;
+
+TalkBot* bot = NULL;
+
+
+#define MAX_WARN_TEXT 1024
+#define MAX_MIND_FILE 1024
+
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+BOOL blInit = FALSE;
+UINT pTimer = 0;
+TCHAR *path;
+
+PLUGININFO pluginInfo={
+ sizeof(PLUGININFO),
+ BOLTUN_NAME,
+ PLUGIN_MAKE_VERSION(0,0,3,0),
+ PLUGIN_DESCRIPTION,
+ "Alexander S. Kiselev, Valentin Pavlyuchenko",
+ "Valentin.Pavlyuchenko@gmail.com",
+ " 2003-2008 Alexander S. Kiselev A.K.A. KAS, Valentin Pavlyuchenko",
+ "http://miranda-im.org",
+ UNICODE_AWARE,
+ 0
+};
+
+static HANDLE hEventDbEventAdded;
+static HANDLE hEventOptInitialise;
+static HANDLE hEventPrebuild;
+static HANDLE hMenuItemAutoChat;
+static HANDLE hMenuItemNotToChat;
+static HANDLE hMenuItemStartChatting;
+
+#ifdef UNICODE
+#define MIND_DIALOG_FILTER _T("%s (*.mindw)\1*.mindw\1%s (*.*)\1*.*\1")
+#else
+#define MIND_DIALOG_FILTER "%s (*.mind)\1*.mind\1%s (*.*)\1*.*\1"
+#endif
+
+#ifdef DEBUG_LOAD_TIME
+#include <intrin.h>
+#endif
+
+void UpdateEngine()
+{
+ if (bot)
+ {
+ bot->SetSilent(Config.EngineStaySilent);
+ bot->SetLowercase(Config.EngineMakeLowerCase);
+ bot->SetUnderstandAlways(Config.EngineUnderstandAlways);
+ }
+}
+
+TCHAR* GetFullName(const TCHAR* filename)
+{
+ size_t flen = _tcslen(filename);
+ TCHAR* fullname = const_cast<TCHAR*>(filename);
+ if (!_tcschr(filename, _T(':')))
+ {
+ size_t plen = _tcslen(path);
+ fullname = new TCHAR[plen+flen+1];
+ fullname[0] = NULL;
+ _tcscat(fullname, path);
+ _tcscat(fullname, filename);
+ }
+ return fullname;
+}
+
+static bool LoadMind(const TCHAR* filename, int &line)
+{
+ TCHAR* fullname = GetFullName(filename);
+ HCURSOR newCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT));
+ HCURSOR oldCur = SetCursor(newCur);
+#ifdef DEBUG_LOAD_TIME
+ unsigned __int64 t = __rdtsc();
+#endif
+ Mind* mind = new Mind();
+ line = -1;
+ try
+ {
+ mind->Load(fullname);
+ }
+ catch(Mind::CorruptedMind c)
+ {
+ line = c.line;
+ delete mind;
+ if (fullname != filename)
+ delete[] fullname;
+ SetCursor(oldCur);
+ return false;
+ }
+ catch(...)
+ {
+ delete mind;
+ if (fullname != filename)
+ delete[] fullname;
+ SetCursor(oldCur);
+ return false;
+ }
+ if (fullname != filename)
+ delete[] fullname;
+
+#ifdef DEBUG_LOAD_TIME
+ t = __rdtsc() - t;
+ char dest[101];
+ sprintf_s(dest, 100, "%I64d ticks\n", t / 3200000);
+ MessageBoxA(NULL, dest, NULL, 0);
+ //exit(0);
+#endif
+ SetCursor(oldCur);
+ HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(IDR_SMILES), _T("SMILES"));
+ if (!hRes)
+ {
+ delete mind;
+ return false;
+ }
+ DWORD size = SizeofResource(hInst, hRes);
+ if (!size)
+ {
+ delete mind;
+ return false;
+ }
+ HGLOBAL hGlob = LoadResource(hInst, hRes);
+ if (!hGlob)
+ {
+ delete mind;
+ return false;
+ }
+ void *data = LockResource(hGlob);
+ if (!data)
+ {
+ FreeResource(hGlob);
+ delete mind;
+ return false;
+ }
+ bool res = true;
+ try
+ {
+ mind->LoadSmiles(data, size);
+ }
+ catch(...)
+ {
+ res = false;
+ }
+ UnlockResource(data);
+ FreeResource(hGlob);
+ if (!res)
+ {
+ delete mind;
+ return false;
+ }
+ if (bot)
+ delete bot;
+ bot = new TalkBot(*mind);
+ delete mind;
+ UpdateEngine();
+ return true;
+}
+
+/*static bool SaveMind(const TCHAR* filename)
+{
+ if (!bot)
+ return false;
+ bot->GetMind().Save(filename);
+ return true;
+}*/
+
+static bool BoltunAutoChat(HANDLE hContact)
+{
+ if (DBGetContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_NOT_TO_CHAT
+ , FALSE) == TRUE)
+ return false;
+
+ if (Config.TalkWithEverybody)
+ return true;
+
+ if (Config.TalkEveryoneWhileAway)
+ {
+ int status = CallService(MS_CLIST_GETSTATUSMODE, 0, 0);
+ if (status == ID_STATUS_AWAY ||
+ status == ID_STATUS_DND ||
+ status == ID_STATUS_NA ||
+ status == ID_STATUS_OCCUPIED ||
+ status == ID_STATUS_ONTHEPHONE ||
+ status == ID_STATUS_OUTTOLUNCH)
+ return true;
+ }
+
+ if ((DBGetContactSettingByte(hContact,"CList","NotOnList",0) == 1) &&
+ Config.TalkWithNotInList)
+ return true;
+
+ if (DBGetContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_AUTO_CHAT,
+ FALSE) == TRUE)
+ return true;
+
+ return false;
+}
+
+static int MessageEventAdded(WPARAM wParam, LPARAM lParam)
+{
+ //DBEVENTINFO ldbei;
+ HANDLE hContact = (HANDLE)wParam;
+ if (!BoltunAutoChat(hContact))
+ return 0;
+
+ DBEVENTINFO dbei;
+ ZeroMemory(&dbei, sizeof(dbei));
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = 0;
+
+ dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, lParam, 0);
+ if (dbei.cbBlob == -1)
+ return 0;
+
+ dbei.pBlob = (PBYTE)malloc(dbei.cbBlob);
+ if (dbei.pBlob == NULL)
+ return 0;
+
+ CallService(MS_DB_EVENT_GET, lParam, (LPARAM)&dbei);
+ if (dbei.flags & DBEF_SENT || dbei.flags & DBEF_READ || dbei.eventType != EVENTTYPE_MESSAGE)
+ return 0;
+ DBEVENTGETTEXT egt;
+ egt.codepage = CP_ACP;
+ egt.datatype = DBVT_TCHAR;
+ egt.dbei = &dbei;
+ TCHAR* s = (TCHAR*)(void*)CallService(MS_DB_EVENT_GETTEXT, 0, (LPARAM)&egt);
+ free(dbei.pBlob);
+ if (Config.MarkAsRead)
+ CallService(MS_DB_EVENT_MARKREAD, wParam, lParam);
+
+ AnswerToContact(hContact, s);
+ mir_free(s);
+ return 0;
+}
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInst = hinstDLL;
+ return TRUE;
+}
+
+void UpdateEverybodyCheckboxes(HWND hwndDlg)
+{
+ bool Enable = !IsDlgButtonChecked(hwndDlg, IDC_EVERYBODY) == BST_CHECKED;
+ HWND wnd;
+ wnd = GetDlgItem(hwndDlg, IDC_NOTINLIST);
+ EnableWindow(wnd, Enable);
+ wnd = GetDlgItem(hwndDlg, IDC_AUTOAWAY);
+ EnableWindow(wnd, Enable);
+}
+
+static int CALLBACK MainDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ BOOL bTranslated = FALSE;
+ static bool loading = true;
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ loading = true;
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_EVERYBODY, Config.TalkWithEverybody ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_NOTINLIST, Config.TalkWithNotInList ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_AUTOAWAY, Config.TalkEveryoneWhileAway ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_WARN, Config.TalkWarnContacts ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_MARKREAD, Config.MarkAsRead ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_PAUSEDEPENDS, Config.PauseDepends ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_PAUSERANDOM, Config.PauseRandom ? BST_CHECKED : BST_UNCHECKED);
+ SendDlgItemMessage(hwndDlg, IDC_WAITTIME, EM_SETLIMITTEXT, 3, 0);
+ SetDlgItemInt(hwndDlg, IDC_WAITTIME, Config.AnswerPauseTime, FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_THINKTIME, EM_SETLIMITTEXT, 3, 0);
+ SetDlgItemInt(hwndDlg, IDC_THINKTIME, Config.AnswerThinkTime, FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_WARNTXT, EM_SETLIMITTEXT, MAX_WARN_TEXT, 0);
+ SetDlgItemText(hwndDlg, IDC_WARNTXT, Config.WarnText);
+ UpdateEverybodyCheckboxes(hwndDlg);
+ loading = false;
+ return TRUE;
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_EVERYBODY && HIWORD(wParam) == BN_CLICKED)
+ UpdateEverybodyCheckboxes(hwndDlg);
+ if (!loading)
+ {
+ bool notify = true;
+ switch (LOWORD(wParam))
+ {
+ case IDC_WARNTXT:
+ case IDC_WAITTIME:
+ case IDC_THINKTIME:
+ if (HIWORD(wParam) != EN_CHANGE)
+ notify = false;
+ break;
+ }
+ if (notify)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ break;
+ case WM_NOTIFY:
+ {
+ NMHDR* nmhdr = (NMHDR*)lParam;
+ switch (nmhdr->code)
+ {
+ case PSN_APPLY:
+ case PSN_KILLACTIVE:
+ {
+ Config.TalkWithEverybody = IsDlgButtonChecked(hwndDlg, IDC_EVERYBODY) == BST_CHECKED ? TRUE : FALSE;
+ Config.TalkWithNotInList = IsDlgButtonChecked(hwndDlg, IDC_NOTINLIST) == BST_CHECKED ? TRUE : FALSE;
+ Config.TalkEveryoneWhileAway = IsDlgButtonChecked(hwndDlg, IDC_AUTOAWAY) == BST_CHECKED ? TRUE : FALSE;
+ Config.TalkWarnContacts = IsDlgButtonChecked(hwndDlg, IDC_WARN) == BST_CHECKED ? TRUE : FALSE;
+ Config.MarkAsRead = IsDlgButtonChecked(hwndDlg, IDC_MARKREAD) == BST_CHECKED ? TRUE : FALSE;
+ Config.PauseDepends = IsDlgButtonChecked(hwndDlg, IDC_PAUSEDEPENDS) == BST_CHECKED ? TRUE : FALSE;
+ Config.PauseRandom = IsDlgButtonChecked(hwndDlg, IDC_PAUSERANDOM) == BST_CHECKED ? TRUE : FALSE;
+ Config.AnswerPauseTime = GetDlgItemInt(hwndDlg, IDC_WAITTIME, &bTranslated, FALSE);
+ if(!bTranslated)
+ Config.AnswerPauseTime = 2;
+ Config.AnswerThinkTime = GetDlgItemInt(hwndDlg, IDC_THINKTIME, &bTranslated, FALSE);
+ if(!bTranslated)
+ Config.AnswerThinkTime = 4;
+ TCHAR c[MAX_WARN_TEXT];
+ bTranslated = GetDlgItemText(hwndDlg, IDC_WARNTXT, c, MAX_WARN_TEXT);
+ if(bTranslated)
+ Config.WarnText = c;
+ else
+ Config.WarnText = TranslateTS(DEFAULT_WARN_TEXT);
+ }
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+ return 0;
+}
+
+void UpdateUnderstandAlwaysCheckbox(HWND hwndDlg)
+{
+ bool Enable = !IsDlgButtonChecked(hwndDlg, IDC_ENGINE_SILENT) == BST_CHECKED;
+ HWND wnd;
+ wnd = GetDlgItem(hwndDlg, IDC_ENGINE_UNDERSTAND_ALWAYS);
+ EnableWindow(wnd, Enable);
+}
+
+static int CALLBACK EngineDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ WORD param;
+ BOOL bTranslated = FALSE;
+ static bool loading = true;
+ static int changeCount = 0;
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ loading = true;
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_ENGINE_SILENT, Config.EngineStaySilent ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_ENGINE_LOWERCASE, Config.EngineMakeLowerCase ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_ENGINE_UNDERSTAND_ALWAYS, Config.EngineUnderstandAlways ? BST_CHECKED : BST_UNCHECKED);
+ SetDlgItemText(hwndDlg, IDC_MINDFILE, Config.MindFileName);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BTNSAVE), blInit);
+ UpdateUnderstandAlwaysCheckbox(hwndDlg);
+ loading = false;
+ return TRUE;
+ case WM_COMMAND:
+ param = LOWORD(wParam);
+ if (param == IDC_ENGINE_SILENT && HIWORD(wParam) == BN_CLICKED)
+ UpdateUnderstandAlwaysCheckbox(hwndDlg);
+ OPENFILENAME ofn;
+ switch(param)
+ {
+ case IDC_BTNPATH:
+ {
+ const size_t fileNameSize = 5000;
+ TCHAR *filename = new TCHAR[fileNameSize];
+ TCHAR *fullname = GetFullName(Config.MindFileName);
+ _tcscpy(filename, fullname);
+ if (fullname != Config.MindFileName)
+ delete[] fullname;
+
+ ZeroMemory(&ofn, sizeof(ofn));
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = GetParent(hwndDlg);
+
+ TCHAR* mind = TranslateTS(MIND_FILE_DESC);
+ TCHAR* anyfile = TranslateTS(ALL_FILES_DESC);
+ size_t l = _tcslen(MIND_DIALOG_FILTER)
+ + _tcslen(mind) + _tcslen(anyfile);
+ TCHAR *filt = new TCHAR[l];
+ wsprintf(filt, MIND_DIALOG_FILTER, mind, anyfile);
+ for (size_t i = 0; i < l; i++)
+ if (filt[i] == '\1')
+ filt[i] = '\0';
+ ofn.lpstrFilter = filt;
+
+ ofn.lpstrFile = filename;
+ ofn.nMaxFile = fileNameSize;
+ ofn.Flags = OFN_FILEMUSTEXIST;
+ ofn.lpstrInitialDir = path;
+ if(!GetOpenFileName(&ofn))
+ {
+ delete filename;
+ delete[] filt;
+ break;
+ }
+ delete[] filt;
+ TCHAR* origf = filename;
+ TCHAR* f = filename;
+ TCHAR* p = path;
+ while (*p && *f)
+ {
+ TCHAR p1 = (TCHAR)CharLower((TCHAR*)(long)*p++);
+ TCHAR f1 = (TCHAR)CharLower((TCHAR*)(long)*f++);
+ if (p1 != f1)
+ break;
+ }
+ if (!*p)
+ filename = f;
+ Config.MindFileName = filename;
+ SetDlgItemText(hwndDlg, IDC_MINDFILE, filename);
+ delete origf;
+ }
+ case IDC_BTNRELOAD:
+ {
+ const TCHAR *c = Config.MindFileName;
+ int line;
+ bTranslated = blInit = LoadMind(c, line);
+ if(!bTranslated)
+ {
+ TCHAR* message = new TCHAR[5000];
+ wsprintf(message, TranslateTS(FAILED_TO_LOAD_BASE), line, c);
+ MessageBox(NULL, message, TranslateTS(BOLTUN_ERROR), MB_ICONERROR|MB_TASKMODAL|MB_OK);
+ delete[] message;
+ }
+ break;
+ }
+ default:
+ if (!loading)
+ {
+ if (param == IDC_MINDFILE/* && HIWORD(wParam) != EN_CHANGE*/)
+ break;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+ break;
+ case WM_NOTIFY:
+ {
+ NMHDR* nmhdr = (NMHDR*)lParam;
+ switch (nmhdr->code)
+ {
+ case PSN_APPLY:
+ case PSN_KILLACTIVE:
+ {
+ Config.EngineStaySilent = IsDlgButtonChecked(hwndDlg, IDC_ENGINE_SILENT) == BST_CHECKED ? TRUE : FALSE;
+ Config.EngineMakeLowerCase = IsDlgButtonChecked(hwndDlg, IDC_ENGINE_LOWERCASE) == BST_CHECKED ? TRUE : FALSE;
+ Config.EngineUnderstandAlways = IsDlgButtonChecked(hwndDlg, IDC_ENGINE_UNDERSTAND_ALWAYS) == BST_CHECKED ? TRUE : FALSE;
+ UpdateEngine();
+ TCHAR c[MAX_MIND_FILE];
+ bTranslated = GetDlgItemText(hwndDlg, IDC_MINDFILE, c, MAX_MIND_FILE);
+ if (bTranslated)
+ Config.MindFileName = c;
+ else
+ Config.MindFileName = DEFAULT_MIND_FILE;
+ }
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+ return 0;
+}
+
+static int MessageOptInit(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp;
+
+ ZeroMemory(&odp, sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.position = 910000000;
+ odp.hInstance = hInst;
+ odp.pszGroup = BOLTUN_GROUP;
+ odp.pszTitle = BOLTUN_NAME;
+ odp.pfnDlgProc = MainDlgProc;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_MAIN);
+ odp.pszTab = TAB_GENERAL;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp);
+ odp.pfnDlgProc = EngineDlgProc;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_ENGINE);
+ odp.pszTab = TAB_ENGINE;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp);
+ return 0;
+}
+
+static int ContactClick(WPARAM wParam, LPARAM lParam, BOOL clickNotToChat)
+{
+ HANDLE hContact = (HANDLE)wParam;
+
+ BOOL boltunautochat = DBGetContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_AUTO_CHAT, FALSE);
+ BOOL boltunnottochat = DBGetContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_NOT_TO_CHAT, FALSE);
+
+ if (clickNotToChat)
+ {
+ boltunnottochat = !boltunnottochat;
+ if(boltunnottochat)
+ {
+ boltunautochat = FALSE;
+ }
+ }
+ else
+ {
+ boltunautochat = !boltunautochat;
+ if(boltunautochat)
+ {
+ boltunnottochat = FALSE;
+ }
+ else
+ {
+ DBWriteContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_WARNED, FALSE);
+ }
+ }
+
+ DBWriteContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_AUTO_CHAT, (BYTE)boltunautochat);
+ DBWriteContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_NOT_TO_CHAT, (BYTE)boltunnottochat);
+
+ return 0;
+}
+
+static int ContactClickAutoChat(WPARAM wParam, LPARAM lParam)
+{
+ return ContactClick(wParam, lParam, 0);
+}
+
+static int ContactClickNotToChat(WPARAM wParam, LPARAM lParam)
+{
+ return ContactClick(wParam, lParam, 1);
+}
+
+static int ContactClickStartChatting(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ StartChatting(hContact);
+ return 0;
+}
+
+static int MessagePrebuild(WPARAM wParam, LPARAM lParam)
+{
+ CLISTMENUITEM clmi;
+ HANDLE hContact = (HANDLE)wParam;
+
+ if (!blInit || (DBGetContactSettingByte(hContact,"CList","NotOnList",0) == 1))
+ {
+ ZeroMemory(&clmi, sizeof(clmi));
+ clmi.cbSize = sizeof(clmi);
+ clmi.flags = CMIM_FLAGS | CMIF_GRAYED;
+
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItemAutoChat, (LPARAM)&clmi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItemNotToChat, (LPARAM)&clmi);
+ }
+ else
+ {
+ BOOL boltunautochat = DBGetContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_AUTO_CHAT, FALSE);
+ BOOL boltunnottochat = DBGetContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_NOT_TO_CHAT, FALSE);
+ ZeroMemory(&clmi, sizeof(clmi));
+ clmi.cbSize = sizeof(clmi);
+ clmi.flags = CMIM_FLAGS | CMIM_ICON | (boltunautochat ? CMIF_CHECKED : 0);
+ clmi.hIcon = LoadIcon( GetModuleHandle(NULL), MAKEINTRESOURCE((boltunautochat ? IDI_TICK : IDI_NOTICK)) );
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItemAutoChat, (LPARAM)&clmi);
+
+ clmi.flags = CMIM_FLAGS | CMIM_ICON | (boltunnottochat ? CMIF_CHECKED : 0);
+ clmi.hIcon = LoadIcon( GetModuleHandle(NULL), MAKEINTRESOURCE((boltunnottochat ? IDI_TICK : IDI_NOTICK)) );
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItemNotToChat, (LPARAM)&clmi);
+ }
+ return 0;
+}
+
+extern "C" __declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+extern "C" int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ pluginLink = link;
+
+ mmi.cbSize=sizeof(struct MM_INTERFACE);
+ CallService(MS_SYSTEM_GET_MMI,0,(LPARAM)&mmi);
+
+ path = new TCHAR[MAX_PATH];
+ int len = GetModuleFileName(hInst, path, MAX_PATH);
+ if (len > MAX_PATH)
+ {
+ delete[] path;
+ TCHAR *path = new TCHAR[len];
+ int len2 = GetModuleFileName(hInst, path, len);
+ if (len2 != len)
+ {
+ delete[] path;
+ return false;
+ }
+ }
+ *(_tcsrchr(path, _T('\\'))+1) = _T('\0');
+
+ /*initialize miranda hooks and services on options dialog*/
+ hEventOptInitialise = HookEvent(ME_OPT_INITIALISE, MessageOptInit);
+ /*initialize miranda hooks and services*/
+ hEventDbEventAdded = HookEvent(ME_DB_EVENT_ADDED, MessageEventAdded);
+ hEventPrebuild = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, MessagePrebuild);
+
+ CreateServiceFunction(SERV_CONTACT_AUTO_CHAT, ContactClickAutoChat);
+ CreateServiceFunction(SERV_CONTACT_NOT_TO_CHAT, ContactClickNotToChat);
+ CreateServiceFunction(SERV_CONTACT_START_CHATTING, ContactClickStartChatting);
+ {
+ CLISTMENUITEM mi;
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = -50010002; //TODO: check the warning
+ mi.flags = 0;
+ mi.hIcon = NULL;
+ mi.pszContactOwner = NULL;
+ mi.pszName = BOLTUN_AUTO_CHAT;
+ mi.pszService = SERV_CONTACT_AUTO_CHAT;
+ hMenuItemAutoChat = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);
+
+ mi.position = -50010001; //TODO: check the warning
+ mi.pszName = BOLTUN_NOT_TO_CHAT;
+ mi.pszService = SERV_CONTACT_NOT_TO_CHAT;
+ hMenuItemNotToChat = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);
+
+ mi.flags = CMIF_NOTOFFLINE;
+ mi.position = -50010000; //TODO: check the warning
+ mi.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_RECVMSG));
+ mi.pszName = BOLTUN_START_CHATTING;
+ mi.pszService = SERV_CONTACT_START_CHATTING;
+ hMenuItemStartChatting = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);
+ }
+ int line;
+ blInit = LoadMind(Config.MindFileName, line);
+ if(!blInit)
+ {
+ TCHAR path[2000];
+ wsprintf(path, TranslateTS(FAILED_TO_LOAD_BASE), line, (const TCHAR*)Config.MindFileName);
+ MessageBox(NULL, path, TranslateTS(BOLTUN_ERROR), MB_ICONERROR|MB_TASKMODAL|MB_OK);
+ }
+ /*record for Uninstall plugin*/
+ DBWriteContactSettingString(NULL, "Uninstall", BOLTUN_NAME, BOLTUN_KEY);
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ if (pTimer)
+ KillTimer(NULL, pTimer);
+ if(blInit)
+ {
+#if 0 //No need to save, we don't have studying algorithm
+ if(Config.MindFileName && !SaveMind(Config.MindFileName))
+ {
+//This causes errors with development core when calling MessageBox.
+//It seems that it's now a Boltun problem.
+//So in case of saving error we will remain silent
+#if 0
+ TCHAR path[MAX_PATH];
+ wsprintf(path, TranslateTS(FAILED_TO_SAVE_BASE), (const TCHAR*)Config.MindFileName);
+ TCHAR* err = TranslateTS(BOLTUN_ERROR);
+ MessageBox(NULL, path, err, MB_ICONERROR|MB_TASKMODAL|MB_OK);*/
+#endif
+ }
+#endif
+ delete bot;
+ }
+ delete[] path;
+ return 0;
+}
diff --git a/plugins/Boltun/boltun.h b/plugins/Boltun/boltun.h
new file mode 100644
index 0000000000..6063dc2310
--- /dev/null
+++ b/plugins/Boltun/boltun.h
@@ -0,0 +1,80 @@
+//***********************************************************
+// Copyright 2003-2008 Alexander S. Kiselev, Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#ifndef _BOLTUN_H
+#define _BOLTUN_H
+
+//Should use different keys in UNICODE and ANSI builds, because usage of plugin
+//with old (another) configs will cause crashes.
+#ifdef _UNICODE
+#define BOLTUN_KEY "BoltunW"
+#else
+#define BOLTUN_KEY "Boltun"
+#endif
+
+//Service names
+#define SERV_CONTACT_AUTO_CHAT "Boltun/ContactAutoChat"
+#define SERV_CONTACT_NOT_TO_CHAT "Boltun/ContactNotToChat"
+#define SERV_CONTACT_START_CHATTING "Boltun/ContactStartChatting"
+
+//Database keys
+#define DB_CONTACT_BOLTUN_NOT_TO_CHAT "BoltunNotToChat"
+#define DB_CONTACT_BOLTUN_AUTO_CHAT "BoltunAutoChat"
+#define DB_CONTACT_WARNED "Warned"
+
+//Plugin group in settings
+#define BOLTUN_GROUP "Message sessions"
+
+//Filename depends on UNICODE
+#ifdef UNICODE
+#define DEFAULT_MIND_FILE _T("boltun.mindw")
+#else
+#define DEFAULT_MIND_FILE _T("boltun.mind")
+#endif
+
+//===============================================
+// These are strings for translation:
+//===============================================
+
+//Plugin name
+#define BOLTUN_NAME "Boltun"
+
+#define PLUGIN_DESCRIPTION "Boltun, the chat bot in the russian language."
+
+#define MIND_FILE_DESC _T("Mind Files")
+#define ALL_FILES_DESC _T("All Files")
+
+//UI strings
+#define BOLTUN_AUTO_CHAT "Boltun/Auto Chat"
+#define BOLTUN_NOT_TO_CHAT "Boltun/Not to Chat"
+#define BOLTUN_START_CHATTING "Boltun/Start Chatting"
+
+#define DEFAULT_WARN_TEXT _T("Hello. I'm Boltun! I'll talk to you, while my owner is away. Please write without mistakes!")
+
+// Error messages
+#define BOLTUN_ERROR _T("Boltun Error")
+#define FAILED_TO_LOAD_BASE _T("Failed to load base of remarks. Error at line %d of %s. (Or few lines before).")
+#define FAILED_TO_SAVE_BASE _T("Failed to save base of remarks to %s")
+
+//Settings tab names
+#define TAB_GENERAL "General Settings"
+#define TAB_ENGINE "Engine Settings"
+
+#endif /*_BOLTUN_H*/
diff --git a/plugins/Boltun/config.cpp b/plugins/Boltun/config.cpp
new file mode 100644
index 0000000000..a59fc89d56
--- /dev/null
+++ b/plugins/Boltun/config.cpp
@@ -0,0 +1,159 @@
+//***********************************************************
+// Copyright 2003-2008 Alexander S. Kiselev, Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#include "config.h"
+
+#include <windows.h>
+#include <time.h>
+#include <string>
+
+#include "newpluginapi.h"
+#include "m_database.h"
+#include "m_langpack.h"
+#include "boltun.h"
+
+//Database keys
+#define DB_EVERYBODY "Everybody"
+#define DB_NOT_IN_LIST "NotInList"
+#define DB_AUTOAWAY "AutoAway"
+#define DB_WARN "Warn"
+#define DB_MARK_READ "MarkRead"
+#define DB_WAIT_TIME "WaitTime"
+#define DB_THINK_TIME "ThinkTime"
+#define DB_PAUSE_DEPENDS "PauseDepends"
+#define DB_PAUSE_RANDOM "PauseRandom"
+#define DB_WARN_TEXT "WarnText"
+#define DB_MIND_FILE_NAME "MindFileName"
+#define DB_ENGINE_SILENT "SilentEngine"
+#define DB_ENGINE_LOWERCASE "MakeLowerCase"
+#define DB_ENGINE_UNDERSTAND_ALWAYS "UnderstandAlways"
+
+inline TCHAR* GetString(char* key, const TCHAR* def)
+{
+ DBVARIANT dbv;
+ TCHAR* val;
+ if(!DBGetContactSettingTString(NULL, BOLTUN_KEY, key, &dbv))
+ {
+ size_t len = wcslen(dbv.ptszVal) + 1;
+ val = new TCHAR[len];
+ _tcscpy_s(val, len, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ else
+ {
+ size_t len = wcslen(def) + 1;
+ val = new TCHAR[len];
+ _tcscpy_s(val, len, def);
+ }
+ return val;
+}
+
+inline const TCHAR* SetString(char* key, const TCHAR* value)
+{
+ size_t len = _tcslen(value) + 1;
+ TCHAR* val = new TCHAR[len];
+ _tcscpy_s(val, len, value);
+ DBWriteContactSettingTString(NULL, BOLTUN_KEY, key, val);
+ return val;
+}
+
+#define BUILDETTERS(x, str, def) \
+ const bool BoltunConfig::Get##x() { \
+ return DBGetContactSettingDword(NULL, BOLTUN_KEY, str, def) != 0; } \
+ const bool BoltunConfig::Set##x(const bool value) { \
+ DBWriteContactSettingDword(NULL, BOLTUN_KEY, str, value); \
+ return value; }
+
+#define BUILDINTETTERS(x, str, def) \
+ const int BoltunConfig::Get##x() { \
+ return DBGetContactSettingDword(NULL, BOLTUN_KEY, str, def); } \
+ const int BoltunConfig::Set##x(const int value) { \
+ DBWriteContactSettingDword(NULL, BOLTUN_KEY, str, value); \
+ return value; }
+
+#define BUILDSTRETTERS(x, str, def) \
+ const TCHAR* BoltunConfig::Get##x() { \
+ return GetString(str, def); } \
+ const TCHAR* BoltunConfig::Set##x(const TCHAR* value) { \
+ return SetString(str, value); }
+
+#define BUILDINIT(x) \
+ x(&BoltunConfig::Get##x, &BoltunConfig::Set##x)
+
+BUILDETTERS(TalkWithNotInList, DB_NOT_IN_LIST, false);
+BUILDETTERS(TalkWithEverybody, DB_EVERYBODY, false);
+BUILDETTERS(TalkWarnContacts, DB_WARN, false);
+BUILDETTERS(TalkEveryoneWhileAway, DB_AUTOAWAY, false);
+BUILDETTERS(MarkAsRead, DB_MARK_READ, true);
+BUILDINTETTERS(AnswerPauseTime, DB_WAIT_TIME, 2);
+BUILDINTETTERS(AnswerThinkTime, DB_THINK_TIME, 4);
+BUILDETTERS(PauseDepends, DB_PAUSE_DEPENDS, TRUE);
+BUILDETTERS(PauseRandom, DB_PAUSE_RANDOM, TRUE);
+BUILDSTRETTERS(WarnText, DB_WARN_TEXT, TranslateTS(DEFAULT_WARN_TEXT));
+BUILDSTRETTERS(MindFileName, DB_MIND_FILE_NAME, DEFAULT_MIND_FILE);
+BUILDETTERS(EngineStaySilent, DB_ENGINE_SILENT, FALSE);
+BUILDETTERS(EngineMakeLowerCase, DB_ENGINE_LOWERCASE, FALSE);
+BUILDETTERS(EngineUnderstandAlways, DB_ENGINE_UNDERSTAND_ALWAYS, FALSE);
+
+BoltunConfig::BoltunConfig()
+ :BUILDINIT(TalkWithEverybody),
+ BUILDINIT(TalkWithNotInList),
+ BUILDINIT(TalkWarnContacts),
+ BUILDINIT(TalkEveryoneWhileAway),
+ BUILDINIT(MarkAsRead),
+ BUILDINIT(AnswerPauseTime),
+ BUILDINIT(AnswerThinkTime),
+ BUILDINIT(PauseDepends),
+ BUILDINIT(PauseRandom),
+ BUILDINIT(WarnText),
+ BUILDINIT(MindFileName),
+ BUILDINIT(EngineStaySilent),
+ BUILDINIT(EngineMakeLowerCase),
+ BUILDINIT(EngineUnderstandAlways)
+{
+ TalkWithEverybody.SetOwner(this);
+ TalkWithNotInList.SetOwner(this);
+ TalkWarnContacts.SetOwner(this);
+ TalkEveryoneWhileAway.SetOwner(this);
+ MarkAsRead.SetOwner(this);
+ AnswerPauseTime.SetOwner(this);
+ AnswerThinkTime.SetOwner(this);
+ PauseDepends.SetOwner(this);
+ PauseRandom.SetOwner(this);
+ WarnText.SetOwner(this);
+ MindFileName.SetOwner(this);
+ EngineStaySilent.SetOwner(this);
+ EngineMakeLowerCase.SetOwner(this);
+ EngineUnderstandAlways.SetOwner(this);
+}
+
+BoltunConfig::~BoltunConfig()
+{
+}
+
+class _BoltunConfigInit
+{
+public:
+ BoltunConfig cfg;
+};
+
+_BoltunConfigInit inst;
+
+BoltunConfig &Config = inst.cfg; \ No newline at end of file
diff --git a/plugins/Boltun/config.h b/plugins/Boltun/config.h
new file mode 100644
index 0000000000..c5bb20e700
--- /dev/null
+++ b/plugins/Boltun/config.h
@@ -0,0 +1,157 @@
+//***********************************************************
+// Copyright 2003-2008 Alexander S. Kiselev, Valentin Pavlyuchenko
+//
+// This file is part of Boltun.
+//
+// Boltun 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.
+//
+// Boltun 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 Boltun. If not, see <http://www.gnu.org/licenses/>.
+//
+//***********************************************************
+
+#ifndef _CONFIG_H
+#define _CONFIG_H
+
+#include <tchar.h>
+
+class BoltunConfig;
+
+template <class T, class BaseClass>
+class Property
+{
+public:
+ typedef const T (__thiscall BaseClass::*Getter)();
+ typedef const T (__thiscall BaseClass::*Setter)(const T);
+private:
+ const Getter getter;
+ const Setter setter;
+ BaseClass* owner;
+ bool cacheValid;
+ T cached;
+public:
+ Property(Getter g, Setter s)
+ :getter(g), setter(s), cacheValid(false)
+ {
+ }
+
+ void SetOwner(BaseClass* o)
+ {
+ owner = o;
+ }
+
+ inline operator const T()
+ {
+ if (cacheValid)
+ return cached;
+ cached = (owner->*getter)();
+ cacheValid = true;
+ return cached;
+ }
+
+ inline const T operator= (const T& value)
+ {
+ cacheValid = true;
+ return (owner->*setter)(cached = value);
+ }
+};
+
+template <class T, class BaseClass>
+class PtrProperty
+{
+public:
+ typedef const T* (__thiscall BaseClass::*Getter)();
+ typedef const T* (__thiscall BaseClass::*Setter)(const T*);
+private:
+ const Getter getter;
+ const Setter setter;
+ BaseClass* owner;
+ bool cacheValid;
+ const T* cached;
+public:
+ PtrProperty(Getter g, Setter s)
+ :getter(g), setter(s), cacheValid(false), cached(NULL)
+ {
+ }
+
+ ~PtrProperty()
+ {
+ delete cached;
+ }
+
+ void SetOwner(BaseClass* o)
+ {
+ owner = o;
+ }
+
+ inline operator const T*()
+ {
+ if (cacheValid)
+ return cached;
+ cached = (owner->*getter)();
+ cacheValid = true;
+ return cached;
+ }
+
+ inline const T* operator= (const T* value)
+ {
+ cacheValid = true;
+ delete cached;
+ cached = (owner->*setter)(value);
+ return cached;
+ }
+};
+
+class _BoltunConfigInit;
+
+#define BUILDDEFETTERS(x, typ) \
+ const typ Get##x(); \
+ const typ Set##x(const typ value);
+
+class BoltunConfig
+{
+ BUILDDEFETTERS(TalkWithEverybody, bool);
+ BUILDDEFETTERS(TalkWithNotInList, bool);
+ BUILDDEFETTERS(TalkWarnContacts, bool);
+ BUILDDEFETTERS(TalkEveryoneWhileAway, bool);
+ BUILDDEFETTERS(MarkAsRead, bool);
+ BUILDDEFETTERS(AnswerPauseTime, int);
+ BUILDDEFETTERS(AnswerThinkTime, int);
+ BUILDDEFETTERS(PauseDepends, bool);
+ BUILDDEFETTERS(PauseRandom, bool);
+ BUILDDEFETTERS(WarnText, TCHAR*);
+ BUILDDEFETTERS(MindFileName, TCHAR*);
+ BUILDDEFETTERS(EngineStaySilent, bool);
+ BUILDDEFETTERS(EngineMakeLowerCase, bool);
+ BUILDDEFETTERS(EngineUnderstandAlways, bool);
+ BoltunConfig();
+ ~BoltunConfig();
+ friend class _BoltunConfigInit;
+public:
+ Property<bool, BoltunConfig> TalkWithEverybody;
+ Property<bool, BoltunConfig> TalkWithNotInList;
+ Property<bool, BoltunConfig> TalkWarnContacts;
+ Property<bool, BoltunConfig> TalkEveryoneWhileAway;
+ Property<bool, BoltunConfig> MarkAsRead;
+ Property<int, BoltunConfig> AnswerPauseTime;
+ Property<int, BoltunConfig> AnswerThinkTime;
+ Property<bool, BoltunConfig> PauseDepends;
+ Property<bool, BoltunConfig> PauseRandom;
+ PtrProperty<TCHAR, BoltunConfig> WarnText;
+ PtrProperty<TCHAR, BoltunConfig> MindFileName;
+ Property<bool, BoltunConfig> EngineStaySilent;
+ Property<bool, BoltunConfig> EngineMakeLowerCase;
+ Property<bool, BoltunConfig> EngineUnderstandAlways;
+};
+
+extern BoltunConfig &Config;
+
+#endif /* _CONFIG_H */ \ No newline at end of file
diff --git a/plugins/Boltun/lang_pack.txt b/plugins/Boltun/lang_pack.txt
new file mode 100644
index 0000000000..79b33c35f6
--- /dev/null
+++ b/plugins/Boltun/lang_pack.txt
@@ -0,0 +1,64 @@
+[Boltun]
+
+[Boltun, the chat bot in the russian language.]
+, - .
+[All Files]
+
+[Mind Files]
+
+[Boltun/Auto Chat]
+/
+[Boltun/Not to Chat]
+/
+[Boltun/Start Chatting]
+/
+[Hello. I'm Boltun! I'll talk to you, while my owner is away. Please write without mistakes!]
+. ! , . , !
+[Boltun Error]
+
+[Failed to load base of remarks. Error at line %d of %s. (Or few lines before).]
+ . %d %s. ( ).
+[Failed to save base of remarks to %s]
+ %s
+[Boltun Autochat everybody]
+
+[Boltun Autochat everybody not in contact list]
+ ,
+[Boltun Autochat everybody while away]
+ ,
+[Warn contacts Boltun is chatting]
+
+[Mark replied messages as read]
+
+[sec]
+
+[Warning text]
+
+[Time before the answer]
+
+[Typing time depends on message length (in chars)]
+ ( )
+[Typing time (for a message of 4 words):]
+ ( 4- ):
+[Thinking time:]
+ :
+[Typing and thinking time can be much longer]
+
+[Engine]
+
+[Base of remarks]
+
+[Save]
+
+[Reload]
+
+[Stay silent, if have no good aswers]
+,
+[Start answers with a lowercase letter]
+ .
+[General Settings]
+
+[Engine Settings]
+ ""
+[Don't use "I don't understand"-like answers]
+ " ?" \ No newline at end of file
diff --git a/plugins/Boltun/mind.txt b/plugins/Boltun/mind.txt
new file mode 100644
index 0000000000..01dcd6e5ba
--- /dev/null
+++ b/plugins/Boltun/mind.txt
@@ -0,0 +1,142 @@
+ .
+
+==============================================================
+ .
+ UNICODE .
+ :
+
+1) :
+
+""
+""
+
+2) :
+
+ (" ")
+""
+
+ ,
+ ('?' - , '.' - ).
+ '~', .
+
+3) :
+
+ {" "}
+""
+
+4) :
+
+ [""]
+""
+
+5) - :
+
+ <QUESTION>
+""
+
+6) :
+
+ <IGNORED>
+" "
+
+7) :
+
+ <ESCAPE>
+" "
+
+8) ( ):
+
+ <INITIAL>
+" "
+
+9) ( , 7):
+
+ <FAILURE>
+" "
+
+10)
+
+@""
+" "
+
+11)
+
+<REPEAT>
+" ."
+
+==============================================================
+
+ :
+
+ , .
+ :
+
+0) ( ), 30 .
+- - (11). 2-3
+ . 30
+, . ,
+.
+
+1) (4) .
+ . ,
+ .
+
+ (4), .
+
+. 0 - .
+
+2) (1) 1).
+ 1.
+
+3) .
+'.' '!' '?', '!' ':-!'.
+
+ :
+
+ 4) (4) .
+ 0.
+
+ 5) (1). 1.
+
+ 6) .
+ , ( "))" ).
+ : .
+ , ,
+ (5).
+ , (6).
+
+ 7) (2).
+ . 1.
+ .
+
+ 8) (3). - (6).
+ ,
+ .
+ ( , ). , .
+ 2.
+
+, ,
+ .
+
+ 9 10 , ", "
+(aka " ") .
+
+9) (7). 3.
+
+10) (9). (9) -
+ " ". 3.
+
+ , 9 10 .
+
+ (10)
+ 1-10 .
+
+ .
+ ,
+( 30 ).
+ (, ),
+.
+
+ ,
+ . , .
+ . \ No newline at end of file
diff --git a/plugins/Boltun/readme.txt b/plugins/Boltun/readme.txt
new file mode 100644
index 0000000000..f20c3ec466
--- /dev/null
+++ b/plugins/Boltun/readme.txt
@@ -0,0 +1,124 @@
+ 0.3.0 Unicode Alpha 7
+
+08.01.2009.
+
+ .
+ "beta"
+
+================================================
+
+ :
+
+readme.txt -
+boltunw.dll -
+boltun.mindw -
+lang_pack.txt - .
+mind.txt - .
+
+================================================
+
+:
+
+ boltunw.dll boltun.mindw Plugins .
+ lang_pack.txt .
+
+================================================
+
+ :
+
+ :
+" " -
+" , " - ,
+" , " - , "" " "
+" " - .
+" " - , , . .
+" " - , .
+" " - , .
+" ( )" - . " " 25 .
+" " - , .
+" " - 4- .
+
+ :
+" " - , .
+ "..." - .
+ "" - , .
+ "" - .
+", " - , .
+" " - . , , .
+" " ?"" - .
+
+================================================
+
+ :
+
+08.01.2009:
+-
+- .
+- ( !!!!).
+
+04.01.2009:
+-
+-
+-
+
+30.09.2008:
+- , .
+- (.. ).
+
+29.09.2008:
+- .
+- .
+
+28.09.2008:
+- .
+- .
+- , .
+
+19.09.2008:
+- .
+
+14.09.2008:
+- .
+
+13.09.2008:
+- .
+- , .
+- , .
+- .
+
+12.09.2008:
+- , MRA.
+
+10.08.2008:
+- " "
+- , .
+- "" .
+- .
+- ", "
+- " "
+- .
+- .
+- .
+- .
+- .
+- .
+- "-".
+- , .
+- .
+- .
+
+28.07.2008:
+- ( , ).
+- Unicode ( )
+- "" , .
+- " " .
+- "" .
+-
+- , ( ).
+- - ( ...). , Unicode-.
+
+================================================
+
+:
+
+valentin.pavlyuchenko@gmail.com \ No newline at end of file
diff --git a/plugins/Boltun/res/boltun.ico b/plugins/Boltun/res/boltun.ico
new file mode 100644
index 0000000000..e6e619f9f2
--- /dev/null
+++ b/plugins/Boltun/res/boltun.ico
Binary files differ
diff --git a/plugins/Boltun/res/smiles.dat b/plugins/Boltun/res/smiles.dat
new file mode 100644
index 0000000000..10bd2b0d5b
--- /dev/null
+++ b/plugins/Boltun/res/smiles.dat
Binary files differ
diff --git a/plugins/Boltun/resource.h b/plugins/Boltun/resource.h
new file mode 100644
index 0000000000..b4fa069c0e
--- /dev/null
+++ b/plugins/Boltun/resource.h
@@ -0,0 +1,46 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Boltun.rc
+//
+#define IDM_HIDE 0x0010
+#define IDD_MAIN 101
+#define IDI_MAINBOLTUN 102
+#define IDD_ENGINE 103
+#define IDR_SMILES 105
+#define IDI_TICK 106
+#define IDI_NOTICK 107
+#define IDI_RECVMSG 108
+#define IDC_EVERYBODY 1000
+#define IDC_NOTINLIST 1001
+#define IDC_AUTOAWAY 1002
+#define IDC_WARN 1003
+#define IDC_MARKREAD 1004
+#define IDC_LWAITTIME 1005
+#define IDC_WAITTIME 1006
+#define IDC_LSEC 1007
+#define IDC_LWARN 1008
+#define IDC_WARNTXT 1009
+#define IDC_PLUGINRM 1010
+#define IDC_TXTREPLICPATH 1011
+#define IDC_MINDFILE 1012
+#define IDC_BTNPATH 1013
+#define IDC_BTNSAVE 1014
+#define IDC_BTNRELOAD 1015
+#define IDC_PAUSEDEPENDS 1016
+#define IDC_PAUSERANDOM 1017
+#define IDC_THINKTIME 1018
+#define IDC_LSEC2 1019
+#define IDC_ENGINE_SILENT 1020
+#define IDC_ENGINE_LOWERCASE 1021
+#define IDC_ENGINE_UNDERSTAND_ALWAYS 1022
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 106
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1023
+#define _APS_NEXT_SYMED_VALUE 102
+#endif
+#endif
diff --git a/plugins/CountryFlags/Info_Src.txt b/plugins/CountryFlags/Info_Src.txt
new file mode 100644
index 0000000000..5c1b19be88
--- /dev/null
+++ b/plugins/CountryFlags/Info_Src.txt
@@ -0,0 +1,32 @@
+
+Country Flags Plugin 0.1.0.3 for Miranda IM 0.7+
+------------------------------------------------------------------------
+ Source Code
+
+Reminder:
+'Country Flags' is released under the terms of the
+GNU General Public License.
+See 'Flags-License.txt' for more details.
+'Country Flags' is copyright 2006-2007 by H. Herkenrath.
+
+Please notify me of any changes that improve
+'Country Flags' or add new features.
+If you have any questions on the code, feel free
+to contact me at my email address.
+
+ H. Herkenrath (hrathh at users.sourceforge.net)
+
+
+Notes
+------------------------------------------------------------------------
+The following files need to be changed to bump the version number:
+
+Info_Src.txt (1 place)
+version.h (4 places)
+m_flags.h (1 place)
+m_flags.inc (1 place)
+docs\Flags-Readme.txt (3 places)
+docs\Flags-Translation.txt (2 or 3 places)
+docs\Flags-Developer.txt (1 place)
+
+
diff --git a/plugins/CountryFlags/License_Appendix.txt b/plugins/CountryFlags/License_Appendix.txt
new file mode 100644
index 0000000000..c590c3f5fb
--- /dev/null
+++ b/plugins/CountryFlags/License_Appendix.txt
@@ -0,0 +1,64 @@
+
+Excecpt of GNU General Public License (Appendix):
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/plugins/CountryFlags/countrylistext.c b/plugins/CountryFlags/countrylistext.c
new file mode 100644
index 0000000000..50978fdb97
--- /dev/null
+++ b/plugins/CountryFlags/countrylistext.c
@@ -0,0 +1,345 @@
+/*
+Miranda IM Country Flags Plugin
+Copyright (C) 2006-2007 H. Herkenrath
+
+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 (Flags-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "flags.h"
+
+static HANDLE hServiceGetList,hServiceGetByNumber;
+
+/************************* Services *******************************/
+
+static struct CountryListEntry countries[]={
+ {0 ,"Unspecified"},
+ {9999,"Other"},
+ {0xFFFF,"Unknown"},
+ {93 ,"Afghanistan"},
+ {355 ,"Albania"},
+ {213 ,"Algeria"},
+ {684 ,"American Samoa"},
+ {376 ,"Andorra"},
+ {244 ,"Angola"},
+ {101 ,"Anguilla"},
+ {102 ,"Antigua and Barbuda"},
+ //{5902,"Antilles"}, /* removed */
+ {54 ,"Argentina"},
+ {374 ,"Armenia"},
+ {297 ,"Aruba"},
+ {247 ,"Ascension Island"},
+ {61 ,"Australia"},
+ {6721,"Australian Antarctic Territory"}, /* was missing */
+ {43 ,"Austria"},
+ {994 ,"Azerbaijan"},
+ {103 ,"Bahamas"},
+ {973 ,"Bahrain"},
+ {880 ,"Bangladesh"},
+ {104 ,"Barbados"},
+ {120 ,"Barbuda"},
+ {375 ,"Belarus"},
+ {32 ,"Belgium"},
+ {501 ,"Belize"},
+ {229 ,"Benin"},
+ {105 ,"Bermuda"},
+ {975 ,"Bhutan"},
+ {591 ,"Bolivia"},
+ {387 ,"Bosnia and Herzegovina"},
+ {267 ,"Botswana"},
+ {55 ,"Brazil"},
+ {106 ,"British Virgin Islands"},
+ {673 ,"Brunei"},
+ {359 ,"Bulgaria"},
+ {226 ,"Burkina Faso"},
+ {257 ,"Burundi"},
+ {855 ,"Cambodia"},
+ {237 ,"Cameroon"},
+ {107 ,"Canada"},
+ {178 ,"Canary Islands"},
+ {238 ,"Cape Verde Islands"},
+ {108 ,"Cayman Islands"},
+ {236 ,"Central African Republic"},
+ {235 ,"Chad"},
+ {56 ,"Chile, Republic of"},
+ {86 ,"China"},
+ {672 ,"Christmas Island"},
+ {6101,"Cocos-Keeling Islands"},
+ //{6102,"Cocos (Keeling) Islands"}, /* removed */
+ {57 ,"Colombia"},
+ {2691,"Comoros"},
+ {243 ,"Congo, Democratic Republic of (Zaire)"},
+ {242 ,"Congo, Republic of the"},
+ {682 ,"Cook Islands"},
+ {506 ,"Costa Rica"},
+ {225 ,"Cote d'Ivoire (Ivory Coast)"},
+ {385 ,"Croatia"},
+ {53 ,"Cuba"},
+ {357 ,"Cyprus"},
+ {420 ,"Czech Republic"},
+ {45 ,"Denmark"},
+ {246 ,"Diego Garcia"},
+ {253 ,"Djibouti"},
+ {109 ,"Dominica"},
+ {110 ,"Dominican Republic"},
+ {593 ,"Ecuador"},
+ {20 ,"Egypt"},
+ {503 ,"El Salvador"},
+ {240 ,"Equatorial Guinea"},
+ {291 ,"Eritrea"},
+ {372 ,"Estonia"},
+ {251 ,"Ethiopia"},
+ {500 ,"Falkland Islands (Malvinas)"}, /* was "Falkland Islands" */
+ {298 ,"Faroe Islands"}, /* was "Faeroe Islands" */
+ {679 ,"Fiji"},
+ {358 ,"Finland"},
+ {33 ,"France"},
+ {5901,"French Antilles"},
+ {594 ,"French Guiana"},
+ {689 ,"French Polynesia"},
+ {241 ,"Gabon"},
+ {220 ,"Gambia"},
+ {995 ,"Georgia"},
+ {49 ,"Germany"},
+ {233 ,"Ghana"},
+ {350 ,"Gibraltar"},
+ {30 ,"Greece"},
+ {299 ,"Greenland"},
+ {111 ,"Grenada"},
+ {590 ,"Guadeloupe"},
+ {671 ,"Guam, US Territory of"},
+ {5399,"Guantanamo Bay"}, /* was missing */
+ {502 ,"Guatemala"},
+ {224 ,"Guinea"},
+ {245 ,"Guinea-Bissau"},
+ {592 ,"Guyana"},
+ {509 ,"Haiti"},
+ {504 ,"Honduras"},
+ {852 ,"Hong Kong"},
+ {36 ,"Hungary"},
+ {354 ,"Iceland"},
+ {91 ,"India"},
+ {62 ,"Indonesia"},
+ {98 ,"Iran (Islamic Republic of)"},
+ {964 ,"Iraq"},
+ {353 ,"Ireland"},
+ {972 ,"Israel"},
+ {39 ,"Italy"},
+ {112 ,"Jamaica"},
+ {81 ,"Japan"},
+ {962 ,"Jordan"},
+ {705 ,"Kazakhstan"},
+ {254 ,"Kenya"},
+ {686 ,"Kiribati"},
+ {850 ,"Korea, North"},
+ {82 ,"Korea, South"},
+ {965 ,"Kuwait"},
+ {706 ,"Kyrgyzstan"},
+ {856 ,"Laos"},
+ {371 ,"Latvia"},
+ {961 ,"Lebanon"},
+ {266 ,"Lesotho"},
+ {231 ,"Liberia"},
+ {218 ,"Libyan Arab Jamahiriya"},
+ {4101,"Liechtenstein"},
+ {370 ,"Lithuania"},
+ {352 ,"Luxembourg"},
+ {853 ,"Macau"},
+ {389 ,"Macedonia (F.Y.R.O.M.)"},
+ {261 ,"Madagascar"},
+ {265 ,"Malawi"},
+ {60 ,"Malaysia"},
+ {960 ,"Maldives"},
+ {223 ,"Mali"},
+ {356 ,"Malta"},
+ {692 ,"Marshall Islands"},
+ {596 ,"Martinique"},
+ {222 ,"Mauritania"},
+ {230 ,"Mauritius"},
+ {269 ,"Mayotte Island"},
+ {52 ,"Mexico"},
+ {691 ,"Micronesia, Federated States of"},
+ {373 ,"Moldova, Republic of"},
+ {377 ,"Monaco"},
+ {976 ,"Mongolia"},
+ {382 ,"Montenegro, Republic of"}, /* was "Yugoslavia - Montenegro" */
+ {113 ,"Montserrat"},
+ {212 ,"Morocco"},
+ {258 ,"Mozambique"},
+ {95 ,"Myanmar"},
+ {264 ,"Namibia"},
+ {674 ,"Nauru"},
+ {977 ,"Nepal"},
+ {31 ,"Netherlands"},
+ {599 ,"Netherlands Antilles"},
+ {114 ,"Nevis"},
+ {687 ,"New Caledonia"},
+ {64 ,"New Zealand"},
+ {505 ,"Nicaragua"},
+ {227 ,"Niger"},
+ {234 ,"Nigeria"},
+ {683 ,"Niue"},
+ {6722,"Norfolk Island"},
+ {47 ,"Norway"},
+ {968 ,"Oman"},
+ {92 ,"Pakistan"},
+ {680 ,"Palau"},
+ {507 ,"Panama"},
+ {675 ,"Papua New Guinea"},
+ {595 ,"Paraguay"},
+ {51 ,"Peru"},
+ {63 ,"Philippines"},
+ {48 ,"Poland"},
+ {351 ,"Portugal"},
+ {121 ,"Puerto Rico"},
+ {974 ,"Qatar"},
+ {262 ,"Reunion Island"},
+ {40 ,"Romania"},
+ {6701,"Rota Island"},
+ {7 ,"Russia"},
+ {250 ,"Rwanda"},
+ {290 ,"Saint Helena"},
+ {115 ,"Saint Kitts"},
+ {1141,"Saint Kitts and Nevis"},
+ {122 ,"Saint Lucia"},
+ {508 ,"Saint Pierre and Miquelon"},
+ {116 ,"Saint Vincent and the Grenadines"},
+ {670 ,"Saipan Island (Northern Mariana Islands)"}, /* was "Saipan Island" */
+ {685 ,"Samoa"}, /* was "Western Samoa" */
+ {378 ,"San Marino"},
+ {239 ,"Sao Tome and Principe"},
+ {966 ,"Saudi Arabia"},
+ {442 ,"Scotland"},
+ {221 ,"Senegal"},
+ {381 ,"Serbia, Republic of"}, /* was "Yugoslavia" */
+ {248 ,"Seychelles"},
+ {232 ,"Sierra Leone"},
+ {65 ,"Singapore"},
+ {421 ,"Slovakia"},
+ {386 ,"Slovenia"},
+ {677 ,"Solomon Islands"},
+ {252 ,"Somalia"},
+ {27 ,"South Africa"},
+ {34 ,"Spain"},
+ {94 ,"Sri Lanka"},
+ {249 ,"Sudan"},
+ {597 ,"Suriname"},
+ {268 ,"Swaziland"},
+ {46 ,"Sweden"},
+ {41 ,"Switzerland"},
+ {963 ,"Syrian Arab Republic"},
+ {886 ,"Taiwan"},
+ {708 ,"Tajikistan"},
+ {255 ,"Tanzania"},
+ {66 ,"Thailand"},
+ {6702,"Tinian Island"},
+ {228 ,"Togo"},
+ {690 ,"Tokelau"},
+ {676 ,"Tonga"},
+ {117 ,"Trinidad and Tobago"},
+ {216 ,"Tunisia"},
+ {90 ,"Turkey"},
+ {709 ,"Turkmenistan"},
+ {118 ,"Turks and Caicos Islands"},
+ {688 ,"Tuvalu"},
+ {256 ,"Uganda"},
+ {380 ,"Ukraine"},
+ {971 ,"United Arab Emirates"},
+ {44 ,"United Kingdom"},
+ {598 ,"Uruguay"},
+ {1 ,"USA"},
+ {711 ,"Uzbekistan"},
+ {678 ,"Vanuatu"},
+ {379 ,"Vatican City"},
+ {58 ,"Venezuela"},
+ {84 ,"Vietnam"},
+ {123 ,"Virgin Islands (USA)"},
+ {441 ,"Wales"},
+ {681 ,"Wallis and Futuna Islands"},
+ {967 ,"Yemen"},
+ //{3811,"Yugoslavia - Serbia"}, /* removed */
+ {260 ,"Zambia"},
+ {263 ,"Zimbabwe"},
+};
+
+static int ServiceGetCountryByNumber(WPARAM wParam,LPARAM lParam)
+{
+ int i;
+ UNREFERENCED_PARAMETER(lParam);
+ for(i=0; i<SIZEOF(countries); ++i)
+ if((int)wParam==countries[i].id)
+ return (int)countries[i].szName;
+ return (int)(char*)NULL;
+}
+
+static int ServiceGetCountryList(WPARAM wParam,LPARAM lParam)
+{
+ if((int*)wParam==NULL || (void*)lParam==NULL) return 1;
+ *(int*)wParam=SIZEOF(countries);
+ *(struct CountryListEntry**)lParam=countries;
+ return 0;
+}
+
+/************************* Misc ***********************************/
+
+static DWORD NameHashFunction(const char *szStr)
+{
+#if defined _M_IX86 && !defined _NUMEGA_BC_FINALCHECK && !defined NOINLINEASM
+ __asm {
+ xor edx,edx
+ xor eax,eax
+ mov esi,szStr
+ mov al,[esi]
+ dec 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
+ and cl,31
+ movzx eax,byte ptr [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
+}
+
+void InitCountryListExt(void)
+{
+ /* hack to replace built-in country list */
+ DestroyServiceFunction((HANDLE)NameHashFunction(MS_UTILS_GETCOUNTRYLIST));
+ DestroyServiceFunction((HANDLE)NameHashFunction(MS_UTILS_GETCOUNTRYBYNUMBER));
+ hServiceGetList=CreateServiceFunction(MS_UTILS_GETCOUNTRYLIST,ServiceGetCountryList);
+ hServiceGetByNumber=CreateServiceFunction(MS_UTILS_GETCOUNTRYBYNUMBER,ServiceGetCountryByNumber);
+}
+
+void UninitCountryListExt(void)
+{
+ DestroyServiceFunction(hServiceGetList);
+ DestroyServiceFunction(hServiceGetByNumber);
+}
diff --git a/plugins/CountryFlags/docs/Flags-Developer.txt b/plugins/CountryFlags/docs/Flags-Developer.txt
new file mode 100644
index 0000000000..68c51a6d7c
--- /dev/null
+++ b/plugins/CountryFlags/docs/Flags-Developer.txt
@@ -0,0 +1,48 @@
+
+Country Flags 0.1.0.3 for Miranda IM 0.7+
+------------------------------------------------------------------------
+ Developer Information
+
+ Contents: -------------------------------
+ | Translation, Services (API),
+ | Debug Symbols, Coding Language, Rebase Info
+
+Translation
+-----------------
+ The translation string listing can be found in
+ 'Flags-Translation.txt'.
+
+Services (API)
+-----------------
+ For more information about which service functions are offered by
+ 'Country Flags' and about how they can be used by your plugin,
+ please refer to 'm_flags.h'.
+ If you would like to use Delphi/Pascal please refer to 'm_flags.inc'.
+
+ Please redirect any questions or extension whishes to me by e-mail:
+ hrathh at users.sourceforge.net
+
+Debug Symbols
+-----------------
+ Debug symbols are also available for debugging purposes.
+ Copy the PDB-files in the SDK-zip into the same directory as the
+ corresponding DLL-files.
+ To debug crashes the supplied MAP-file file might be helpful.
+
+Coding Language
+-----------------
+ 'Country Flags' was written using Microsoft Visual C++ 6.0 SP6
+ and the Microsoft Platform SDK shipped along with it.
+
+Rebase Info
+-----------------
+ 'Country Flags' has set its base address to:
+ 0x24200000
+
+ Please avoid using this base address for your plugins because it will
+ slow down the startup of Miranda IM.
+
+ Using Microsoft Visual C++, the base address can be configured at:
+ 'Project' -> 'Settings' -> 'Linker' -> 'Output' -> 'Base Address'
+
+H. Herkenrath (hrathh at users.sourceforge.net)
diff --git a/plugins/CountryFlags/docs/Flags-License.txt b/plugins/CountryFlags/docs/Flags-License.txt
new file mode 100644
index 0000000000..a726a52df1
--- /dev/null
+++ b/plugins/CountryFlags/docs/Flags-License.txt
@@ -0,0 +1,278 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
diff --git a/plugins/CountryFlags/docs/Flags-Readme.txt b/plugins/CountryFlags/docs/Flags-Readme.txt
new file mode 100644
index 0000000000..d6a2182fc6
--- /dev/null
+++ b/plugins/CountryFlags/docs/Flags-Readme.txt
@@ -0,0 +1,140 @@
+
+Country Flags 0.1.0.3
+------------------------------------------------------------------------
+ Plugin for Miranda IM 0.7 and +
+
+ Plugin Info: ----------------------------
+ | Version: 0.1.0.3
+ | Filename: flags.dll
+ | Author: H. Herkenrath (hrathh at users.sourceforge.net)
+ | Description: Service offering misc country utilities as
+ | flag icons and a IP-to-Country database.
+
+ Contents: -------------------------------
+ | Features, Requirements, Usage, Installation,
+ | Bugs and Wishes, Version History, License and Copyright
+
+Features
+----------------------
+ + Provides country utility services for other plugins (Flag Icons, IP-To-Country)
+ + Shows country flags as extra images on contact list
+ + Shows country flags as status icons on message windows
+ + Flag icon can be hidden if no country can be determined
+ + Flag icon is automatically refreshed when user details are updated
+ + Unicode compatible
+ + Automatic installation of all files, just unzip into Plugins directory
+
+Requirements
+----------------------
+ -> Miranda IM 0.7+:
+ Miranda IM is needed in version 0.7 or greater.
+
+Usage
+----------------------
+ Country Flags Provider does not add much functionality by itself.
+ It offers services for other plugins to use.
+
+ To show country flags on your contact list or
+ on your message window open the options and go here:
+ 'Contact List' -> 'Country Flags'
+
+ The country flag icons can be viewed here:
+ 'Customize' -> 'Icons'
+
+Installation
+----------------------
+ Find 'miranda32.exe' on your computer.
+
+ Just copy all the contents of the zip-file as they are into the 'Plugins' directory
+ in the Miranda IM folder.
+ 'Country Flags' will detect the files and move them into the appropriate
+ directories on it's first run.
+
+ You can also do all the installation by hand, if you want to:
+
+ Main Plugin: Copy the file 'flags.dll' into the 'Plugins' directory
+ in the Miranda IM folder.
+
+ The Unicode version of the plugin will only work on Windows NT/2000/XP,
+ Windows Server 2003, Windows Vista or later with an installed
+ Unicode version of Miranda IM.
+ To use it on Windows 95/98/Me, please download the ANSI version of the plugin.
+
+ Documentation: The txt-files should be moved along with the SDK-zip into the
+ 'Docs' directory in the Miranda IM folder.
+
+ That's it!
+
+Bugs and Wishes
+----------------------
+ Feel free to mail me your wishes about 'Language Pack Manager' and tell
+ me all the bugs you may find.
+ My email address is: hrathh at users.sourceforge.net
+
+Version History
+----------------------
+ 0.1.0.3 - really fixed those nasty crashes
+ - lightning-like speed due to buffered IP-database access
+ - option to turn-off usage of ip-to-country database
+ 0.1.0.2 - another try to fix those crashes
+ - refreshs icons on user details update
+ - optionally shows nothing if no country can be determined for a contact
+ 0.1.0.1 - try to fix those extraimg crashes
+ - fixed: implemented extra image column selector properly
+ - fixed: heavy crash on Unicode startup
+ (search on garbage might cross page-boundary)
+ - rewritten flags as status icons
+ - reimplemented country lookup
+ - added map-file to SDK package
+ 0.1.0.0 - Initial release
+
+License and Copyright
+----------------------
+ 'Country Flags' is released under the terms of the
+ GNU General Public License.
+ See 'Flags-License.txt' for more details.
+
+ Copyright (c) 2006-2007 by H. Herkenrath. All rights reserved.
+
+ This service includes the IP-to-Country Database
+ provided by WebHosting.info (http://www.webhosting.info),
+ available from http://ip-to-country.webhosting.info.
+ Copyright (c) 2003 Direct Information Pvt. Ltd. All rights Reserved.
+ Included Version: 05-03-2007, will be updated regularly.
+
+ The included Huffman encodig algorithm is
+ Copyright (c) 2003-2006 Marcus Geelnard.
+
+ The included default flag icons are public domain.
+ Flag Icons - http://www.famfamfam.com (created by Mark James)
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. The origin of this software must not be misrepresented; you must
+ not claim that you wrote the original software. If you use this
+ software in a product, an acknowledgment in the product
+ documentation would be appreciated but is not required.
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+H. Herkenrath (hrathh at users.sourceforge.net)
diff --git a/plugins/CountryFlags/docs/Flags-Translation.txt b/plugins/CountryFlags/docs/Flags-Translation.txt
new file mode 100644
index 0000000000..15c1728c0d
--- /dev/null
+++ b/plugins/CountryFlags/docs/Flags-Translation.txt
@@ -0,0 +1,74 @@
+Country Flags 0.1.0.3 for Miranda IM 0.7+
+------------------------------------------------------------------------
+ Translator Information
+
+ Contents: -------------------------------
+ | General Info, String Listing
+
+General Info
+-----------------------------
+ 'Country Flags' can be translated using Miranda IM
+ language files.
+
+ Put the following strings in a file called 'langpack_<language>.txt'
+ in the Miranda IM directory and translate them into your
+ language.
+ If you need more info on Miranda IM language files visit:
+ http://miranda.svn.sourceforge.net/viewvc/*checkout*/miranda/trunk/miranda/i18n/readme.txt
+
+String Listing
+-----------------------------
+
+; --- Plugin: Country Flags 0.1.0.3 (German) ---
+; Translation by hrathh
+; Please report any mistakes or missing strings in here.
+
+[Country Flags]
+Lnderflaggen
+[Service offering misc country utilities as flag icons and a IP-to-Country database.]
+Bietet verschiedene lnderspezifische Dienste wie Flaggensymbole und IP-to-Country.
+[Country Flags Plugin]
+Lnderflaggen-Plugin
+[The Country Flags Plugin can not be loaded. It requires Miranda IM %hs or later.]
+Der Lnderflaggen-Plugin kann nicht geladen werden. Er bentigt Miranda IM %hs oder neuer.
+
+; Countries
+; Most country names are the same as used in miranda32.exe,
+; except the following corrections:
+[Australian Antarctic Territory]
+Australisches Antarktis-Territorium
+[Falkland Islands (Malvinas)]
+Falklandinseln (Malwinen)
+[Faroe Islands]
+Frer-Inseln
+[Guantanamo Bay]
+Guantanamo-Bucht
+[Montenegro, Republic of]
+Montenegro
+[Saipan Island (Northern Mariana Islands)]
+Saipan Insel (Nrdliche Marianen)
+;[Samoa]
+[Serbia, Republic of]
+Serbien
+
+; Options
+;[Contact List]
+;[Country Flags]
+[Show country flag as &status icon on message window]
+Zeige Lnderflagge in der Statuszeile im Nachrichtenfenster
+[Show country flag as &extra image on contact list]
+Zeige Lnderflagge als Spalte in der &Kontaktliste
+[In following contact list &column:]
+Verwende folgende &Spalte:
+[Advanced #%u]
+Erweitert #%u
+[Use &IP-to-country database for country detection]
+IP-Datenbank zur Bestimmung des Landes verwenden
+[Use &unknown flag if the country can not be determined]
+"Unbekannt" anzeigen, wenn Land nicht bestimmbar
+
+
+; ---
+
+
+H. Herkenrath (hrathh at users.sourceforge.net)
diff --git a/plugins/CountryFlags/extraimg.c b/plugins/CountryFlags/extraimg.c
new file mode 100644
index 0000000000..cd50cc2ccb
--- /dev/null
+++ b/plugins/CountryFlags/extraimg.c
@@ -0,0 +1,495 @@
+/*
+Miranda IM Country Flags Plugin
+Copyright (C) 2006-1007 H. Herkenrath
+
+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 (Flags-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "flags.h"
+
+/* Services */
+static HANDLE hServiceDetectContactOrigin;
+/* Extra Image */
+static HANDLE hHookExtraRebuild,hHookExtraApply;
+/* Status Icon */
+static HANDLE hHookMsgWndEvent,hHookIconsChanged;
+/* Options */
+static HANDLE hHookOptInit,hHookSettingChanged;
+/* Misc */
+extern HINSTANCE hInst;
+extern int nCountriesCount;
+extern struct CountryListEntry *countries;
+static HANDLE hHookModulesLoaded;
+
+/************************* Services *******************************/
+
+static int ServiceDetectContactOriginCountry(WPARAM wParam,LPARAM lParam)
+{
+ int countryNumber=0xFFFF;
+ char *pszProto;
+ UNREFERENCED_PARAMETER(lParam);
+ pszProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,wParam,0);
+ /* ip detect */
+ if(DBGetContactSettingByte(NULL,"Flags","UseIpToCountry",SETTING_USEIPTOCOUNTRY_DEFAULT))
+ countryNumber=ServiceIpToCountry(DBGetContactSettingDword((HANDLE)wParam,pszProto,"RealIP",0),0);
+ /* fallback */
+ if(countryNumber==0xFFFF)
+ countryNumber=DBGetContactSettingWord((HANDLE)wParam,pszProto,"Country",0);
+ if(countryNumber==0 || countryNumber==0xFFFF)
+ countryNumber=DBGetContactSettingWord((HANDLE)wParam,pszProto,"CompanyCountry",0);
+ return (countryNumber==0)?0xFFFF:countryNumber;
+}
+
+/************************* Extra Image ****************************/
+
+#define EXTRAIMAGE_REFRESHDELAY 100 /* time for which setting changes are buffered */
+
+static HANDLE *phExtraImages;
+static BYTE idExtraColumn;
+
+static void CALLBACK SetExtraImage(LPARAM lParam)
+{
+ IconExtraColumn iec;
+ int countryNumber,index;
+ if(DBGetContactSettingByte(NULL,"Flags","ShowExtraImgFlag",SETTING_SHOWEXTRAIMGFLAG_DEFAULT)) {
+ /* get contact's country */
+ iec.hImage=INVALID_HANDLE_VALUE;
+ countryNumber=ServiceDetectContactOriginCountry((WPARAM)lParam,0);
+ /* get icon */
+ if(phExtraImages!=NULL) /* too early? */
+ if(countryNumber!=0xFFFF || DBGetContactSettingByte(NULL,"Flags","UseUnknownFlag",SETTING_USEUNKNOWNFLAG_DEFAULT)) {
+ index=CountryNumberToIndex(countryNumber);
+ /* icon not yet loaded? */
+ if(phExtraImages[index]==INVALID_HANDLE_VALUE) {
+ HICON hIcon;
+ hIcon=LoadFlagIcon(countryNumber);
+ if(hIcon!=NULL) phExtraImages[index]=(HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON,(WPARAM)hIcon,0);
+ CallService(MS_SKIN2_RELEASEICON,(WPARAM)hIcon,0); /* does NULL check */
+ }
+ iec.hImage=phExtraImages[index];
+ }
+ /* choose column */
+ iec.cbSize=sizeof(iec);
+ iec.ColumnType=idExtraColumn;
+ CallService(MS_CLIST_EXTRA_SET_ICON,(WPARAM)lParam,(LPARAM)&iec);
+ }
+}
+
+// always call in context of main thread
+static void RemoveExtraImages(void)
+{
+ IconExtraColumn iec;
+ register HANDLE hContact;
+ /* choose column */
+ iec.cbSize=sizeof(iec);
+ iec.ColumnType=idExtraColumn;
+ iec.hImage=INVALID_HANDLE_VALUE;
+ /* enum all contacts */
+ hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ while(hContact!=NULL) {
+ /* invalidate icon */
+ CallService(MS_CLIST_EXTRA_SET_ICON,(WPARAM)hContact,(LPARAM)&iec);
+ hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0);
+ }
+}
+
+// always call in context of main thread
+static void EnsureExtraImages(void)
+{
+ register HANDLE hContact;
+ BYTE idMaxExtraCol,idExtraColumnNew;
+ /* choose column */
+ idMaxExtraCol=(BYTE)CallService(MS_CLUI_GETCAPS,0,CLUIF2_EXTRACOLUMNCOUNT); /* 1-based count */
+ if(idMaxExtraCol==(BYTE)CallService(MS_CLUI_GETCAPS,0,CLUIF2_USEREXTRASTART)) /* same flags if not present */
+ idMaxExtraCol=EXTRA_ICON_ADV2; /* zero if not present */
+ idExtraColumnNew=DBGetContactSettingRangedByte(NULL,"Flags","ExtraImgFlagColumn",SETTING_EXTRAIMGFLAGCOLUMN_DEFAULT,1,idMaxExtraCol);
+ /* clear previous column */
+ if(idExtraColumnNew!=idExtraColumn) RemoveExtraImages();
+ idExtraColumn=idExtraColumnNew;
+ /* enum all contacts */
+ hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ while(hContact!=NULL) {
+ CallFunctionBuffered(SetExtraImage,(LPARAM)hContact,TRUE,EXTRAIMAGE_REFRESHDELAY);
+ hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0);
+ }
+}
+
+static void CALLBACK UpdateExtraImages(LPARAM lParam)
+{
+ UNREFERENCED_PARAMETER(lParam);
+ if(DBGetContactSettingByte(NULL,"Flags","ShowExtraImgFlag",SETTING_SHOWEXTRAIMGFLAG_DEFAULT))
+ EnsureExtraImages();
+ else RemoveExtraImages();
+}
+
+static int ExtraListRebuild(WPARAM wParam,LPARAM lParam)
+{
+ BYTE idMaxExtraCol;
+ int i;
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+ OutputDebugStringA("REBUILD EXTRA\n");
+ /* invalidate icons */
+ if(phExtraImages!=NULL)
+ for(i=0;i<nCountriesCount;++i)
+ phExtraImages[i]=INVALID_HANDLE_VALUE;
+ /* choose column */
+ idMaxExtraCol=(BYTE)CallService(MS_CLUI_GETCAPS,0,CLUIF2_EXTRACOLUMNCOUNT); /* 1-based count */
+ if(idMaxExtraCol==(BYTE)CallService(MS_CLUI_GETCAPS,0,CLUIF2_USEREXTRASTART)) /* same flags if not present */
+ idMaxExtraCol=EXTRA_ICON_ADV2; /* zero if not present */
+ idExtraColumn=DBGetContactSettingRangedByte(NULL,"Flags","ExtraImgFlagColumn",SETTING_EXTRAIMGFLAGCOLUMN_DEFAULT,1,idMaxExtraCol);
+ return 0;
+}
+
+static int ExtraImageApply(WPARAM wParam,LPARAM lParam)
+{
+ UNREFERENCED_PARAMETER(lParam);
+ OutputDebugStringA("APPLY EXTRA\n");
+ if(DBGetContactSettingByte(NULL,"Flags","ShowExtraImgFlag",SETTING_SHOWEXTRAIMGFLAG_DEFAULT))
+ SetExtraImage((LPARAM)wParam); /* unbuffered */
+ return 0;
+}
+
+/************************* Status Icon ****************************/
+
+#define STATUSICON_REFRESHDELAY 100 /* time for which setting changes are buffered */
+
+// always call in context of main thread
+static void FASTCALL SetStatusIcon(HANDLE hContact,int countryNumber)
+{
+ int i;
+ HICON hIcon=NULL;
+ StatusIconData sid;
+
+ if(countryNumber!=0xFFFF || DBGetContactSettingByte(NULL,"Flags","UseUnknownFlag",SETTING_USEUNKNOWNFLAG_DEFAULT)) {
+ /* copy icon as status icon API will call DestroyIcon() on it */
+ hIcon=LoadFlagIcon(countryNumber);
+ sid.hIcon=(hIcon!=NULL)?CopyIcon(hIcon):NULL;
+ CallService(MS_SKIN2_RELEASEICON,(WPARAM)hIcon,0); /* does NULL check */
+ hIcon=sid.hIcon;
+ /* ensure status icon is registered */
+ sid.cbSize=sizeof(sid);
+ sid.szModule="Flags";
+ sid.dwId=countryNumber;
+ sid.hIconDisabled=NULL;
+ sid.flags=0;
+ sid.szTooltip=Translate((char*)CallService(MS_UTILS_GETCOUNTRYBYNUMBER,countryNumber,0));
+ if(CallService(MS_MSG_MODIFYICON,0,(LPARAM)&sid)) /* not yet registered? */
+ CallService(MS_MSG_ADDICON,0,(LPARAM)&sid);
+ }
+ /* disable all other flags for this contact */
+ sid.hIcon=NULL;
+ sid.szTooltip=NULL;
+ sid.flags=MBF_HIDDEN;
+ for(i=0;i<nCountriesCount;++i) {
+ sid.dwId=countries[i].id;
+ if(countryNumber==countries[i].id && hIcon!=NULL) sid.flags=0;
+ else sid.flags=MBF_HIDDEN;
+ CallService(MS_MSG_MODIFYICON,(WPARAM)hContact,(LPARAM)&sid);
+ }
+}
+
+// always call in context of main thread
+static void FASTCALL UnsetStatusIcon(HANDLE hContact,int countryNumber)
+{
+ StatusIconData sid;
+ sid.cbSize=sizeof(sid);
+ sid.szModule="Flags";
+ sid.dwId=countryNumber;
+ sid.hIconDisabled=sid.hIcon=NULL;
+ sid.szTooltip=NULL;
+ sid.flags=MBF_HIDDEN;
+ CallService(MS_MSG_MODIFYICON,(WPARAM)hContact,(LPARAM)&sid); /* registered? */
+ /* can't call MS_MSG_REMOVEICON here as the icon might be
+ * in use by other contacts simultanously, removing them all at exit */
+}
+
+static int MsgWndEvent(WPARAM wParam,LPARAM lParam)
+{
+ MessageWindowEventData *msgwe=(MessageWindowEventData*)lParam;
+ UNREFERENCED_PARAMETER(wParam);
+ switch(msgwe->uType) {
+ case MSG_WINDOW_EVT_OPENING:
+ case MSG_WINDOW_EVT_CLOSE:
+ { int countryNumber;
+ if(msgwe->hContact==NULL || !ServiceExists(MS_MSG_ADDICON)) break; /* sanity check */
+ countryNumber=ServiceDetectContactOriginCountry((WPARAM)msgwe->hContact,0);
+ if(DBGetContactSettingByte(NULL,"Flags","ShowStatusIconFlag",SETTING_SHOWSTATUSICONFLAG_DEFAULT)) {
+ if(msgwe->uType==MSG_WINDOW_EVT_OPENING) SetStatusIcon(msgwe->hContact,countryNumber);
+ else UnsetStatusIcon(msgwe->hContact,countryNumber);
+ }
+ /* ensure it is hidden, RemoveStatusIcons() only enums currently opened ones */
+ else UnsetStatusIcon(msgwe->hContact,countryNumber);
+ }
+ }
+ return 0;
+}
+
+static void CALLBACK UpdateStatusIcons(LPARAM lParam)
+{
+ MessageWindowInputData msgwi; /* input */
+ MessageWindowData msgw; /* output */
+ BOOL fShow;
+ int countryNumber;
+ UNREFERENCED_PARAMETER(lParam);
+
+ msgwi.cbSize=sizeof(msgwi);
+ msgw.cbSize=sizeof(msgw);
+ msgwi.uFlags=MSG_WINDOW_UFLAG_MSG_BOTH;
+ /* enum all opened message windows */
+ fShow=DBGetContactSettingByte(NULL,"Flags","ShowStatusIconFlag",SETTING_SHOWSTATUSICONFLAG_DEFAULT);
+ msgwi.hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ while(msgwi.hContact!=NULL) {
+ /* is a message window opened for this contact? */
+ if(!CallService(MS_MSG_GETWINDOWDATA,(WPARAM)&msgwi,(LPARAM)&msgw) && msgw.uState&MSG_WINDOW_STATE_EXISTS) {
+ countryNumber=ServiceDetectContactOriginCountry((WPARAM)msgwi.hContact,0);
+ if(fShow) SetStatusIcon(msgwi.hContact,countryNumber);
+ else UnsetStatusIcon(msgwi.hContact,countryNumber);
+ }
+ msgwi.hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)msgw.hContact,0);
+ }
+}
+
+static int StatusIconsChanged(WPARAM wParam,LPARAM lParam)
+{
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+ if(ServiceExists(MS_MSG_ADDICON))
+ if(DBGetContactSettingByte(NULL,"Flags","ShowStatusIconFlag",SETTING_SHOWSTATUSICONFLAG_DEFAULT))
+ CallFunctionBuffered(UpdateStatusIcons,0,FALSE,STATUSICON_REFRESHDELAY);
+ return 0;
+}
+
+/************************* Options ************************************/
+
+#define M_ENABLE_SUBCTLS (WM_APP+1)
+
+static int CALLBACK ExtraImgOptDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ UNREFERENCED_PARAMETER(wParam);
+ switch(msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ /* init checkboxes */
+ { BOOL val;
+ /* Status Icon */
+ if(ServiceExists(MS_MSG_ADDICON)) val=DBGetContactSettingByte(NULL,"Flags","ShowStatusIconFlag",SETTING_SHOWSTATUSICONFLAG_DEFAULT)!=0;
+ else EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK_SHOWSTATUSICONFLAG),val=FALSE);
+ CheckDlgButton(hwndDlg,IDC_CHECK_SHOWSTATUSICONFLAG,val);
+ /* Extra Image */
+ if(ServiceExists(MS_CLIST_EXTRA_ADD_ICON)) val=DBGetContactSettingByte(NULL,"Flags","ShowExtraImgFlag",SETTING_SHOWEXTRAIMGFLAG_DEFAULT)!=0;
+ else EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK_SHOWEXTRAIMGFLAG),val=FALSE);
+ CheckDlgButton(hwndDlg,IDC_CHECK_SHOWEXTRAIMGFLAG,val);
+ /* Unknown Flag */
+ val=DBGetContactSettingByte(NULL,"Flags","UseUnknownFlag",SETTING_USEUNKNOWNFLAG_DEFAULT)!=0;
+ CheckDlgButton(hwndDlg,IDC_CHECK_USEUNKNOWNFLAG,val);
+ /* IP-to-country */
+ val=DBGetContactSettingByte(NULL,"Flags","UseIpToCountry",SETTING_USEIPTOCOUNTRY_DEFAULT)!=0;
+ CheckDlgButton(hwndDlg,IDC_CHECK_USEIPTOCOUNTRY,val);
+ }
+ /* init combobox */
+ { HWND hwndCombo;
+ TCHAR szItem[64];
+ BYTE idColumn,idSavedColumn;
+ BYTE idMaxExtraCol,idAdvExtraColStart;
+ int index;
+ hwndCombo=GetDlgItem(hwndDlg,IDC_COMBO_EXTRAIMGFLAGCOLUMN);
+ idSavedColumn=DBGetContactSettingByte(NULL,"Flags","ExtraImgFlagColumn",SETTING_EXTRAIMGFLAGCOLUMN_DEFAULT);
+ idMaxExtraCol=(BYTE)CallService(MS_CLUI_GETCAPS,0,CLUIF2_EXTRACOLUMNCOUNT); /* 1-based count */
+ idAdvExtraColStart=(BYTE)CallService(MS_CLUI_GETCAPS,0,CLUIF2_USEREXTRASTART); /* 1-based id */
+ /* init */
+ SendMessage(hwndCombo,CB_SETLOCALE,(LCID)CallService(MS_LANGPACK_GETLOCALE,0,0),0); /* for sort order */
+ SendMessage(hwndCombo,CB_INITSTORAGE,idMaxExtraCol-idAdvExtraColStart+3,(idMaxExtraCol-idAdvExtraColStart+3)*SIZEOF(szItem));
+ /* Advanced #1,#2 */
+ { const BYTE columnIds[]={EXTRA_ICON_ADV1,EXTRA_ICON_ADV2};
+ for(idColumn=0;idColumn<SIZEOF(columnIds);++idColumn) {
+ mir_sntprintf(szItem,SIZEOF(szItem),TranslateT("Advanced #%u"),idColumn+1); /* buffer safe */
+ index=SendMessage(hwndCombo,CB_ADDSTRING,0,(LPARAM)szItem);
+ if(index!=LB_ERR) {
+ SendMessage(hwndCombo,CB_SETITEMDATA,index,columnIds[idColumn]);
+ if(idColumn==0 || columnIds[idColumn]==idSavedColumn) SendMessage(hwndCombo,CB_SETCURSEL,index,0);
+ }
+ }
+ }
+ /* Advanced #3+: clist_modern */
+ if(idMaxExtraCol!=idAdvExtraColStart) /* same flags if not present */
+ for(idColumn=idAdvExtraColStart;idColumn<=idMaxExtraCol;++idColumn) {
+ mir_sntprintf(szItem,SIZEOF(szItem),TranslateT("Advanced #%u"),idColumn-idAdvExtraColStart+3); /* buffer safe */
+ index=SendMessage(hwndCombo,CB_ADDSTRING,0,(LPARAM)szItem);
+ if(index!=LB_ERR) {
+ SendMessage(hwndCombo,CB_SETITEMDATA,index,idColumn);
+ if(idColumn==idSavedColumn) SendMessage(hwndCombo,CB_SETCURSEL,index,0);
+ }
+ }
+ }
+ SendMessage(hwndDlg,M_ENABLE_SUBCTLS,0,0);
+ return TRUE; /* default focus */
+ case M_ENABLE_SUBCTLS:
+ { BOOL checked=IsDlgButtonChecked(hwndDlg,IDC_CHECK_SHOWEXTRAIMGFLAG);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TEXT_EXTRAIMGFLAGCOLUMN),checked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_COMBO_EXTRAIMGFLAGCOLUMN),checked);
+ if(!checked) checked=IsDlgButtonChecked(hwndDlg,IDC_CHECK_SHOWSTATUSICONFLAG);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK_USEUNKNOWNFLAG),checked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CHECK_USEIPTOCOUNTRY),checked);
+ return TRUE;
+ }
+ case WM_COMMAND:
+ PostMessage(hwndDlg,M_ENABLE_SUBCTLS,0,0);
+ PostMessage(GetParent(hwndDlg),PSM_CHANGED,0,0); /* enable apply */
+ return FALSE;
+ case WM_NOTIFY:
+ switch(((NMHDR*)lParam)->code) {
+ case PSN_APPLY: /* setting change hook will pick these up */
+ DBWriteContactSettingByte(NULL,"Flags","UseUnknownFlag",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_CHECK_USEUNKNOWNFLAG)!=0));
+ DBWriteContactSettingByte(NULL,"Flags","UseIpToCountry",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_CHECK_USEIPTOCOUNTRY)!=0));
+ /* Status Icon */
+ if(IsWindowEnabled(GetDlgItem(hwndDlg,IDC_CHECK_SHOWSTATUSICONFLAG)))
+ DBWriteContactSettingByte(NULL,"Flags","ShowStatusIconFlag",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_CHECK_SHOWSTATUSICONFLAG)!=0));
+ /* Extra Image */
+ if(IsWindowEnabled(GetDlgItem(hwndDlg,IDC_CHECK_SHOWEXTRAIMGFLAG)))
+ DBWriteContactSettingByte(NULL,"Flags","ShowExtraImgFlag",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_CHECK_SHOWEXTRAIMGFLAG)!=0));
+ { int index;
+ index=SendDlgItemMessage(hwndDlg,IDC_COMBO_EXTRAIMGFLAGCOLUMN,CB_GETCURSEL,0,0);
+ if(index!=LB_ERR) DBWriteContactSettingByte(NULL,"Flags","ExtraImgFlagColumn",(BYTE)SendDlgItemMessage(hwndDlg,IDC_COMBO_EXTRAIMGFLAGCOLUMN,CB_GETITEMDATA,index,0));
+ }
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static int ExtraImgOptInit(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp;
+ static UINT expertOnlyControls[]={IDC_CHECK_USEIPTOCOUNTRY};
+ UNREFERENCED_PARAMETER(lParam);
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize=sizeof(odp);
+ odp.hInstance=hInst;
+ odp.pszTemplate=MAKEINTRESOURCEA(IDD_OPT_EXTRAIMG);
+ odp.position=900000002;
+ odp.ptszGroup=_T("Contact List"); /* autotranslated */
+ odp.ptszTitle=_T("Country Flags"); /* autotranslated */
+ odp.ptszTab=_T("Country Flags"); /* autotranslated, can be made a tab */
+ odp.flags=ODPF_BOLDGROUPS|ODPF_TCHAR;
+ odp.pfnDlgProc=ExtraImgOptDlgProc;
+ odp.expertOnlyControls=expertOnlyControls;
+ odp.nExpertOnlyControls=SIZEOF(expertOnlyControls);
+ CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
+ return 0;
+}
+
+static int ExtraImgSettingChanged(WPARAM wParam,LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *dbcws=(DBCONTACTWRITESETTING*)lParam;
+ if((HANDLE)wParam==NULL) {
+ if(!lstrcmpA(dbcws->szModule,"Flags")) {
+ /* Extra Image */
+ if(!lstrcmpA(dbcws->szSetting,"ShowExtraImgFlag") ||
+ !lstrcmpA(dbcws->szSetting,"ExtraImgFlagColumn") ||
+ !lstrcmpA(dbcws->szSetting,"UseUnknownFlag") ||
+ !lstrcmpA(dbcws->szSetting,"UseIpToCountry"))
+ if(ServiceExists(MS_CLIST_EXTRA_SET_ICON))
+ CallFunctionBuffered(UpdateExtraImages,0,FALSE,EXTRAIMAGE_REFRESHDELAY);
+ /* Status Icon */
+ if(!lstrcmpA(dbcws->szSetting,"ShowStatusIconFlag") ||
+ !lstrcmpA(dbcws->szSetting,"UseUnknownFlag") ||
+ !lstrcmpA(dbcws->szSetting,"UseIpToCountry"))
+ if(ServiceExists(MS_MSG_ADDICON))
+ CallFunctionBuffered(UpdateStatusIcons,0,FALSE,STATUSICON_REFRESHDELAY);
+ }
+ }
+ /* user details update */
+ else if(!lstrcmpA(dbcws->szSetting,"RealIP") ||
+ !lstrcmpA(dbcws->szSetting,"Country") ||
+ !lstrcmpA(dbcws->szSetting,"CompanyCountry")) {
+ /* Extra Image */
+ if(ServiceExists(MS_CLIST_EXTRA_SET_ICON))
+ CallFunctionBuffered(SetExtraImage,(LPARAM)wParam,TRUE,EXTRAIMAGE_REFRESHDELAY);
+ /* Status Icon */
+ if(ServiceExists(MS_MSG_ADDICON))
+ CallFunctionBuffered(UpdateStatusIcons,0,FALSE,STATUSICON_REFRESHDELAY);
+ }
+ return 0;
+}
+
+/************************* Misc ***********************************/
+
+static int ExtraImgModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+ /* Options */
+ if(ServiceExists("DBEditorpp/RegisterSingleModule"))
+ CallService("DBEditorpp/RegisterSingleModule",(WPARAM)"Flags",0);
+ /* Extra Image */
+ if(ServiceExists(MS_CLIST_EXTRA_SET_ICON)) {
+ int i;
+ BYTE idMaxExtraCol;
+ phExtraImages=(HANDLE*)mir_alloc(nCountriesCount*sizeof(HANDLE));
+ /* invalidate icons */
+ if(phExtraImages!=NULL)
+ for(i=0;i<nCountriesCount;++i)
+ phExtraImages[i]=INVALID_HANDLE_VALUE;
+ /* choose column */
+ idMaxExtraCol=(BYTE)CallService(MS_CLUI_GETCAPS,0,CLUIF2_EXTRACOLUMNCOUNT); /* 1-based count */
+ if(idMaxExtraCol==(BYTE)CallService(MS_CLUI_GETCAPS,0,CLUIF2_USEREXTRASTART)) /* same flags if not present */
+ idMaxExtraCol=EXTRA_ICON_ADV2; /* zero if not present */
+ idExtraColumn=DBGetContactSettingRangedByte(NULL,"Flags","ExtraImgFlagColumn",SETTING_EXTRAIMGFLAGCOLUMN_DEFAULT,1,idMaxExtraCol);
+ /* hook */
+ hHookExtraRebuild=HookEvent(ME_CLIST_EXTRA_LIST_REBUILD,ExtraListRebuild);
+ hHookExtraApply=HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY,ExtraImageApply);
+ }
+ /* Status Icon */
+ hHookMsgWndEvent=HookEvent(ME_MSG_WINDOWEVENT,MsgWndEvent);
+ return 0;
+}
+
+void InitExtraImg(void)
+{
+ /* Services */
+ hServiceDetectContactOrigin=CreateServiceFunction(MS_FLAGS_DETECTCONTACTORIGINCOUNTRY,ServiceDetectContactOriginCountry);
+ /* Misc */
+ hHookModulesLoaded=HookEvent(ME_SYSTEM_MODULESLOADED,ExtraImgModulesLoaded);
+ /* Extra Image */
+ phExtraImages=NULL;
+ hHookExtraRebuild=hHookExtraApply=NULL;
+ /* Status icon */
+ hHookMsgWndEvent=NULL;
+ hHookIconsChanged=HookEvent(ME_SKIN2_ICONSCHANGED,StatusIconsChanged);
+ /* Options */
+ hHookOptInit=HookEvent(ME_OPT_INITIALISE,ExtraImgOptInit);
+ hHookSettingChanged=HookEvent(ME_DB_CONTACT_SETTINGCHANGED,ExtraImgSettingChanged);
+}
+
+void UninitExtraImg(void)
+{
+ /* Services */
+ DestroyServiceFunction(hServiceDetectContactOrigin);
+ /* Misc */
+ UnhookEvent(hHookModulesLoaded);
+ /* Extra Image */
+ UnhookEvent(hHookSettingChanged);
+ UnhookEvent(hHookExtraRebuild);
+ UnhookEvent(hHookExtraApply);
+ mir_free(phExtraImages); /* does NULL check */
+ /* Status icon */
+ UnhookEvent(hHookMsgWndEvent);
+ UnhookEvent(hHookIconsChanged);
+ /* Options */
+ UnhookEvent(hHookOptInit);
+ UnhookEvent(hHookSettingChanged);
+}
diff --git a/plugins/CountryFlags/flags.def b/plugins/CountryFlags/flags.def
new file mode 100644
index 0000000000..fb2cd5c0ef
--- /dev/null
+++ b/plugins/CountryFlags/flags.def
@@ -0,0 +1,11 @@
+LIBRARY flags BASE=0x24200000
+SECTIONS
+ ; obfuscated email address
+ .rdata READ WRITE
+EXPORTS
+ MirandaPluginInfo PRIVATE
+ Load PRIVATE
+ Unload PRIVATE
+ ; v0.8 support
+ MirandaPluginInfoEx PRIVATE
+ MirandaPluginInterfaces PRIVATE
diff --git a/plugins/CountryFlags/flags.h b/plugins/CountryFlags/flags.h
new file mode 100644
index 0000000000..cd7837e3d4
--- /dev/null
+++ b/plugins/CountryFlags/flags.h
@@ -0,0 +1,89 @@
+/*
+Miranda IM Country Flags Plugin
+Copyright (C) 2006-2007 H. Herkenrath
+
+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 (Flags-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#define NONAMELESSUNION
+#include <commctrl.h> /* for ImageList functions */
+#define NOWIN2K
+#include <win2k.h>
+#define MIRANDA_VER 0x0700
+#include <stdio.h>
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_utils.h>
+#include <m_langpack.h>
+#include <m_icolib.h>
+#include <m_clui.h>
+#include <m_cluiframes.h>
+#include <m_message.h>
+#include <m_database.h>
+#include <m_options.h>
+#include <m_contacts.h>
+#include <m_protocols.h>
+#define FLAGS_NOHELPERFUNCTIONS
+#include "m_flags.h"
+#include "resource.h"
+
+#if defined(_MSC_VER) && !defined(FASTCALL)
+ #define FASTCALL __fastcall
+#else
+ #define FASTCALL
+#endif
+#if defined(_DEBUG)
+ #undef FASTCALL
+ #define FASTCALL
+#endif
+
+/* countrylistext.c */
+void InitCountryListExt(void);
+void UninitCountryListExt(void);
+
+/* huffman.c */
+#ifdef HUFFMAN_ENCODE
+ int Huffman_Compress(unsigned char *in,unsigned char *out,unsigned int insize );
+#endif
+void Huffman_Uncompress(unsigned char *in,unsigned char *out,unsigned int insize,unsigned int outsize);
+
+/* icons.c */
+HICON FASTCALL LoadFlagIcon(int countryNumber);
+int FASTCALL CountryNumberToIndex(int countryNumber);
+void InitIcons(void);
+void UninitIcons(void);
+
+/* ip2country.c */
+int ServiceIpToCountry(WPARAM wParam,LPARAM lParam);
+void InitIpToCountry(void);
+void UninitIpToCountry(void);
+
+/* extraimg.c */
+void InitExtraImg(void);
+void UninitExtraImg(void);
+
+/* utils.c */
+typedef void (CALLBACK *BUFFEREDPROC)(LPARAM lParam);
+#ifdef _DEBUG
+ void _CallFunctionBuffered(BUFFEREDPROC pfnBuffProc,const char *pszProcName,LPARAM lParam,BOOL fAccumulateSameParam,UINT uElapse);
+ #define CallFunctionBuffered(proc,param,acc,elapse) _CallFunctionBuffered(proc,#proc,param,acc,elapse)
+#else
+ void _CallFunctionBuffered(BUFFEREDPROC pfnBuffProc,LPARAM lParam,BOOL fAccumulateSameParam,UINT uElapse);
+ #define CallFunctionBuffered(proc,param,acc,elapse) _CallFunctionBuffered(proc,param,acc,elapse)
+#endif
+void PrepareBufferedFunctions(void);
+void KillBufferedFunctions(void);
diff --git a/plugins/CountryFlags/flags.sln b/plugins/CountryFlags/flags.sln
new file mode 100644
index 0000000000..1903a8eb95
--- /dev/null
+++ b/plugins/CountryFlags/flags.sln
@@ -0,0 +1,29 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flags", "flags.vcxproj", "{0966244A-B8FD-FF88-DA2F-6A8332BCD82F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Bin Converter|Win32 = Bin Converter|Win32
+ Debug Unicode|Win32 = Debug Unicode|Win32
+ Debug|Win32 = Debug|Win32
+ Release Unicode|Win32 = Release Unicode|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {0966244A-B8FD-FF88-DA2F-6A8332BCD82F}.Bin Converter|Win32.ActiveCfg = Bin Converter|Win32
+ {0966244A-B8FD-FF88-DA2F-6A8332BCD82F}.Bin Converter|Win32.Build.0 = Bin Converter|Win32
+ {0966244A-B8FD-FF88-DA2F-6A8332BCD82F}.Debug Unicode|Win32.ActiveCfg = Debug Unicode|Win32
+ {0966244A-B8FD-FF88-DA2F-6A8332BCD82F}.Debug Unicode|Win32.Build.0 = Debug Unicode|Win32
+ {0966244A-B8FD-FF88-DA2F-6A8332BCD82F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0966244A-B8FD-FF88-DA2F-6A8332BCD82F}.Debug|Win32.Build.0 = Debug|Win32
+ {0966244A-B8FD-FF88-DA2F-6A8332BCD82F}.Release Unicode|Win32.ActiveCfg = Release Unicode|Win32
+ {0966244A-B8FD-FF88-DA2F-6A8332BCD82F}.Release Unicode|Win32.Build.0 = Release Unicode|Win32
+ {0966244A-B8FD-FF88-DA2F-6A8332BCD82F}.Release|Win32.ActiveCfg = Release|Win32
+ {0966244A-B8FD-FF88-DA2F-6A8332BCD82F}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/plugins/CountryFlags/flags.vcxproj b/plugins/CountryFlags/flags.vcxproj
new file mode 100644
index 0000000000..18ab33ade6
--- /dev/null
+++ b/plugins/CountryFlags/flags.vcxproj
@@ -0,0 +1,408 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Bin Converter|Win32">
+ <Configuration>Bin Converter</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug Unicode|Win32">
+ <Configuration>Debug Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release Unicode|Win32">
+ <Configuration>Release Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <SccProjectName />
+ <SccLocalPath />
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Bin Converter|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Bin Converter|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">
+ <OutDir>$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental>true</LinkIncremental>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Bin Converter|Win32'">
+ <OutDir>$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental>true</LinkIncremental>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental>false</LinkIncremental>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
+ <OutDir>$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental>false</LinkIncremental>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir>$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental>true</LinkIncremental>
+ <IgnoreImportLibrary>true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+ <FunctionLevelLinking>false</FunctionLevelLinking>
+ <Optimization>Disabled</Optimization>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;UNICODE;WIN32;_WINDOWS;_USRDLL;STRICT;FLAGS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <UndefinePreprocessorDefinitions>_MBCS;NO_STRICT;%(UndefinePreprocessorDefinitions)</UndefinePreprocessorDefinitions>
+ <BrowseInformation>true</BrowseInformation>
+ <PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ </ClCompile>
+ <Midl>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <TypeLibraryName>.\temp/Debug/Unicode\flags.tlb</TypeLibraryName>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ </Midl>
+ <ResourceCompile>
+ <Culture>0x0809</Culture>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </Bscmake>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <LinkDLL>true</LinkDLL>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>uuid.lib;OLDNAMES;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <ModuleDefinitionFile>flags.def</ModuleDefinitionFile>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <BaseAddress>0x24200000</BaseAddress>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalOptions> /mapinfo:lines /mapinfo:lines </AdditionalOptions>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Bin Converter|Win32'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+ <FunctionLevelLinking>false</FunctionLevelLinking>
+ <Optimization>Disabled</Optimization>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>BINCONV;HUFFMAN_ENCODE;_DEBUG;WIN32;_WINDOWS;_USRDLL;STRICT;FLAGS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <UndefinePreprocessorDefinitions>NO_STRICT;%(UndefinePreprocessorDefinitions)</UndefinePreprocessorDefinitions>
+ <BrowseInformation>true</BrowseInformation>
+ <PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ </ClCompile>
+ <Midl>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <TypeLibraryName>.\temp/BinConv\flags.tlb</TypeLibraryName>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ </Midl>
+ <ResourceCompile>
+ <Culture>0x0809</Culture>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </Bscmake>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <LinkDLL>true</LinkDLL>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>uuid.lib;OLDNAMES;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <ModuleDefinitionFile>flags.def</ModuleDefinitionFile>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <BaseAddress>0x25000000</BaseAddress>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalOptions> /mapinfo:lines</AdditionalOptions>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <Optimization>Full</Optimization>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;_USRDLL;STRICT;ASSOCMGR_EXPORTS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <UndefinePreprocessorDefinitions>NO_STRICT;%(UndefinePreprocessorDefinitions)</UndefinePreprocessorDefinitions>
+ <BrowseInformation>true</BrowseInformation>
+ <AdditionalOptions> /opt:nowin98 </AdditionalOptions>
+ <PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ </ClCompile>
+ <Midl>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <TypeLibraryName>.\temp/Release/ANSI\flags.tlb</TypeLibraryName>
+ <MkTypLibCompatible>false</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ </Midl>
+ <ResourceCompile>
+ <Culture>0x0809</Culture>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </Bscmake>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <LinkDLL>true</LinkDLL>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>uuid.lib;OLDNAMES;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <ModuleDefinitionFile>flags.def</ModuleDefinitionFile>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SetChecksum>true</SetChecksum>
+ <BaseAddress>0x24200000</BaseAddress>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalOptions>/ignore:4078 </AdditionalOptions>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <Optimization>Full</Optimization>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;UNICODE;WIN32;_WINDOWS;_USRDLL;STRICT;ASSOCMGR_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <UndefinePreprocessorDefinitions>_MBCS;NO_STRICT;%(UndefinePreprocessorDefinitions)</UndefinePreprocessorDefinitions>
+ <BrowseInformation>true</BrowseInformation>
+ <PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AdditionalOptions> /opt:nowin98 </AdditionalOptions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ </ClCompile>
+ <Midl>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <TypeLibraryName>.\temp/Release/Unicode\flags.tlb</TypeLibraryName>
+ <MkTypLibCompatible>false</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ </Midl>
+ <ResourceCompile>
+ <Culture>0x0809</Culture>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>NDEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </Bscmake>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <LinkDLL>true</LinkDLL>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>uuid.lib;OLDNAMES;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <ModuleDefinitionFile>flags.def</ModuleDefinitionFile>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <SetChecksum>true</SetChecksum>
+ <BaseAddress>0x24200000</BaseAddress>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalOptions>/ignore:4078 </AdditionalOptions>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+ <FunctionLevelLinking>false</FunctionLevelLinking>
+ <Optimization>Disabled</Optimization>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <WarningLevel>Level4</WarningLevel>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;WIN32;_WINDOWS;_USRDLL;STRICT;FLAGS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <UndefinePreprocessorDefinitions>NO_STRICT;%(UndefinePreprocessorDefinitions)</UndefinePreprocessorDefinitions>
+ <BrowseInformation>true</BrowseInformation>
+ <PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ </ClCompile>
+ <Midl>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <TypeLibraryName>.\temp/Debug/ANSI\flags.tlb</TypeLibraryName>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ </Midl>
+ <ResourceCompile>
+ <Culture>0x0809</Culture>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </Bscmake>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <LinkDLL>true</LinkDLL>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <IgnoreSpecificDefaultLibraries>uuid.lib;OLDNAMES;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <ModuleDefinitionFile>flags.def</ModuleDefinitionFile>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <BaseAddress>0x24200000</BaseAddress>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalOptions> /mapinfo:lines</AdditionalOptions>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="countrylistext.c">
+ <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> /opt:nowin98 /opt:nowin98 </AdditionalOptions>
+ <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'"> /opt:ref /opt:nowin98 /opt:ref /opt:nowin98 </AdditionalOptions>
+ </ClCompile>
+ <ClCompile Include="extraimg.c">
+ <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> /opt:nowin98 /opt:nowin98 </AdditionalOptions>
+ <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'"> /opt:ref /opt:nowin98 /opt:ref /opt:nowin98 </AdditionalOptions>
+ </ClCompile>
+ <ClCompile Include="huffman.c">
+ <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> /opt:nowin98 /opt:nowin98 </AdditionalOptions>
+ <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'"> /opt:ref /opt:nowin98 /opt:ref /opt:nowin98 </AdditionalOptions>
+ </ClCompile>
+ <ClCompile Include="icons.c">
+ <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> /opt:nowin98 /opt:nowin98 </AdditionalOptions>
+ <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'"> /opt:ref /opt:nowin98 /opt:ref /opt:nowin98 </AdditionalOptions>
+ </ClCompile>
+ <ClCompile Include="ip2country.c">
+ <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> /opt:nowin98 /opt:nowin98 </AdditionalOptions>
+ <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'"> /opt:ref /opt:nowin98 /opt:ref /opt:nowin98 </AdditionalOptions>
+ </ClCompile>
+ <ClCompile Include="main.c">
+ <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> /opt:nowin98 /opt:nowin98 </AdditionalOptions>
+ <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'"> /opt:ref /opt:nowin98 /opt:ref /opt:nowin98 </AdditionalOptions>
+ </ClCompile>
+ <ClCompile Include="utils.c">
+ <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> /opt:nowin98 /opt:nowin98 </AdditionalOptions>
+ <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'"> /opt:ref /opt:nowin98 /opt:ref /opt:nowin98 </AdditionalOptions>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="flags.h" />
+ <ClInclude Include="m_flags.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="version.h" />
+ <ClInclude Include="include\m_clui.h" />
+ <ClInclude Include="include\m_cluiframes.h" />
+ <ClInclude Include="include\m_database.h" />
+ <ClInclude Include="include\m_icolib.h" />
+ <ClInclude Include="include\m_langpack.h" />
+ <ClInclude Include="include\m_message.h" />
+ <ClInclude Include="include\m_options.h" />
+ <ClInclude Include="include\m_plugins.h" />
+ <ClInclude Include="include\m_skin.h" />
+ <ClInclude Include="include\m_system.h" />
+ <ClInclude Include="include\m_utils.h" />
+ <ClInclude Include="include\newpluginapi.h" />
+ <ClInclude Include="include\statusmodes.h" />
+ <ClInclude Include="include\win2k.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="res\flags.bmp" />
+ <CustomBuild Include="res\ip-to-country.bin">
+ <FileType>Document</FileType>
+ </CustomBuild>
+ <CustomBuild Include="docs\Flags-Developer.txt" />
+ <CustomBuild Include="docs\Flags-License.txt" />
+ <CustomBuild Include="docs\Flags-Readme.txt" />
+ <CustomBuild Include="docs\Flags-Translation.txt" />
+ <CustomBuild Include="m_flags.inc">
+ <FileType>Document</FileType>
+ </CustomBuild>
+ <CustomBuild Include="Info_Src.txt" />
+ <CustomBuild Include="License_Appendix.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resource.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/CountryFlags/flags.vcxproj.filters b/plugins/CountryFlags/flags.vcxproj.filters
new file mode 100644
index 0000000000..c06f9db005
--- /dev/null
+++ b/plugins/CountryFlags/flags.vcxproj.filters
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{2e34a165-959f-4051-80ea-a8e9d3ffe09a}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{d5658bf6-af27-43e5-b3f8-4bc19ac22032}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{d26bc05b-c5a5-4dfc-88a9-1c9e7da444ad}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ <Filter Include="Documentation">
+ <UniqueIdentifier>{71089b54-009a-4229-868a-c90b5e0b350e}</UniqueIdentifier>
+ <Extensions>txt</Extensions>
+ </Filter>
+ <Filter Include="SDK">
+ <UniqueIdentifier>{0b81b17c-89f3-4558-a861-4385827dddb3}</UniqueIdentifier>
+ <Extensions>*.h</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="countrylistext.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="extraimg.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="huffman.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="icons.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ip2country.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="main.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="utils.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="flags.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="m_flags.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Resource Files</Filter>
+ </ClInclude>
+ <ClInclude Include="version.h">
+ <Filter>Resource Files</Filter>
+ </ClInclude>
+ <ClInclude Include="include\m_clui.h">
+ <Filter>SDK</Filter>
+ </ClInclude>
+ <ClInclude Include="include\m_cluiframes.h">
+ <Filter>SDK</Filter>
+ </ClInclude>
+ <ClInclude Include="include\m_database.h">
+ <Filter>SDK</Filter>
+ </ClInclude>
+ <ClInclude Include="include\m_icolib.h">
+ <Filter>SDK</Filter>
+ </ClInclude>
+ <ClInclude Include="include\m_langpack.h">
+ <Filter>SDK</Filter>
+ </ClInclude>
+ <ClInclude Include="include\m_message.h">
+ <Filter>SDK</Filter>
+ </ClInclude>
+ <ClInclude Include="include\m_options.h">
+ <Filter>SDK</Filter>
+ </ClInclude>
+ <ClInclude Include="include\m_plugins.h">
+ <Filter>SDK</Filter>
+ </ClInclude>
+ <ClInclude Include="include\m_skin.h">
+ <Filter>SDK</Filter>
+ </ClInclude>
+ <ClInclude Include="include\m_system.h">
+ <Filter>SDK</Filter>
+ </ClInclude>
+ <ClInclude Include="include\m_utils.h">
+ <Filter>SDK</Filter>
+ </ClInclude>
+ <ClInclude Include="include\newpluginapi.h">
+ <Filter>SDK</Filter>
+ </ClInclude>
+ <ClInclude Include="include\statusmodes.h">
+ <Filter>SDK</Filter>
+ </ClInclude>
+ <ClInclude Include="include\win2k.h">
+ <Filter>SDK</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resource.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="res\flags.bmp">
+ <Filter>Resource Files</Filter>
+ </CustomBuild>
+ <CustomBuild Include="res\ip-to-country.bin">
+ <Filter>Resource Files</Filter>
+ </CustomBuild>
+ <CustomBuild Include="docs\Flags-Developer.txt">
+ <Filter>Documentation</Filter>
+ </CustomBuild>
+ <CustomBuild Include="docs\Flags-License.txt">
+ <Filter>Documentation</Filter>
+ </CustomBuild>
+ <CustomBuild Include="docs\Flags-Readme.txt">
+ <Filter>Documentation</Filter>
+ </CustomBuild>
+ <CustomBuild Include="docs\Flags-Translation.txt">
+ <Filter>Documentation</Filter>
+ </CustomBuild>
+ <CustomBuild Include="m_flags.inc">
+ <Filter>Documentation</Filter>
+ </CustomBuild>
+ <CustomBuild Include="Info_Src.txt">
+ <Filter>Documentation</Filter>
+ </CustomBuild>
+ <CustomBuild Include="License_Appendix.txt">
+ <Filter>Documentation</Filter>
+ </CustomBuild>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/CountryFlags/huffman.c b/plugins/CountryFlags/huffman.c
new file mode 100644
index 0000000000..f05e82113e
--- /dev/null
+++ b/plugins/CountryFlags/huffman.c
@@ -0,0 +1,506 @@
+/*************************************************************************
+* Name: huffman.c
+* Author: Marcus Geelnard
+* Description: Huffman coder/decoder implementation.
+* Reentrant: Yes
+*
+* This is a very straight forward implementation of a Huffman coder and
+* decoder.
+*
+* Primary flaws with this primitive implementation are:
+* - Slow bit stream implementation
+* - Maximum tree depth of 32 (the coder aborts if any code exceeds a
+* size of 32 bits). If I'm not mistaking, this should not be possible
+* unless the input buffer is larger than 2^32 bytes, which is not
+* supported by the coder anyway (max 2^32-1 bytes can be specified with
+* an unsigned 32-bit integer).
+*
+* On the other hand, there are a few advantages of this implementation:
+* - The Huffman tree is stored in a very compact form, requiring only
+* 10 bits per symbol (for 8 bit symbols), meaning a maximum of 320
+* bytes overhead.
+* - The code should be fairly easy to follow, if you are familiar with
+* how the Huffman compression algorithm works.
+*
+* Possible improvements (probably not worth it):
+* - Partition the input data stream into blocks, where each block has
+* its own Huffman tree. With variable block sizes, it should be
+* possible to find locally optimal Huffman trees, which in turn could
+* reduce the total size.
+* - Allow for a few different predefined Huffman trees, which could
+* reduce the size of a block even further.
+*-------------------------------------------------------------------------
+* Copyright (c) 2003-2006 Marcus Geelnard
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would
+* be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not
+* be misrepresented as being the original software.
+*
+* 3. This notice may not be removed or altered from any source
+* distribution.
+*
+* Marcus Geelnard
+* marcus.geelnard at home.se
+*************************************************************************/
+
+
+/*************************************************************************
+* Types used for Huffman coding
+*************************************************************************/
+
+typedef struct {
+ unsigned char *BytePtr;
+ unsigned int BitPos;
+} huff_bitstream_t;
+
+typedef struct {
+ int Symbol;
+ unsigned int Count;
+ unsigned int Code;
+ unsigned int Bits;
+} huff_sym_t;
+
+typedef struct huff_encodenode_struct huff_encodenode_t;
+
+struct huff_encodenode_struct {
+ huff_encodenode_t *ChildA, *ChildB;
+ int Count;
+ int Symbol;
+};
+
+typedef struct huff_decodenode_struct huff_decodenode_t;
+
+struct huff_decodenode_struct {
+ huff_decodenode_t *ChildA, *ChildB;
+ int Symbol;
+};
+
+
+/*************************************************************************
+* Constants for Huffman decoding
+*************************************************************************/
+
+/* The maximum number of nodes in the Huffman tree is 2^(8+1)-1 = 511 */
+#define MAX_TREE_NODES 511
+
+
+/*************************************************************************
+* _Huffman_InitBitstream() - Initialize a bitstream.
+*************************************************************************/
+
+static void _Huffman_InitBitstream( huff_bitstream_t *stream,
+ unsigned char *buf )
+{
+ stream->BytePtr = buf;
+ stream->BitPos = 0;
+}
+
+
+/*************************************************************************
+* _Huffman_ReadBit() - Read one bit from a bitstream.
+*************************************************************************/
+
+static unsigned int _Huffman_ReadBit( huff_bitstream_t *stream )
+{
+ unsigned int x, bit;
+ unsigned char *buf;
+
+ /* Get current stream state */
+ buf = stream->BytePtr;
+ bit = stream->BitPos;
+
+ /* Extract bit */
+ x = (*buf & (1<<(7-bit))) ? 1 : 0;
+ bit = (bit+1) & 7;
+ if( !bit )
+ {
+ ++ buf;
+ }
+
+ /* Store new stream state */
+ stream->BitPos = bit;
+ stream->BytePtr = buf;
+
+ return x;
+}
+
+
+/*************************************************************************
+* _Huffman_Read8Bits() - Read eight bits from a bitstream.
+*************************************************************************/
+
+static unsigned int _Huffman_Read8Bits( huff_bitstream_t *stream )
+{
+ unsigned int x, bit;
+ unsigned char *buf;
+
+ /* Get current stream state */
+ buf = stream->BytePtr;
+ bit = stream->BitPos;
+
+ /* Extract byte */
+ x = (*buf << bit) | (buf[1] >> (8-bit));
+ ++ buf;
+
+ /* Store new stream state */
+ stream->BytePtr = buf;
+
+ return x;
+}
+
+
+/*************************************************************************
+* _Huffman_WriteBits() - Write bits to a bitstream.
+*************************************************************************/
+
+#ifdef HUFFMAN_ENCODE
+static void _Huffman_WriteBits( huff_bitstream_t *stream, unsigned int x,
+ unsigned int bits )
+{
+ unsigned int bit, count;
+ unsigned char *buf;
+ unsigned int mask;
+
+ /* Get current stream state */
+ buf = stream->BytePtr;
+ bit = stream->BitPos;
+
+ /* Append bits */
+ mask = 1 << (bits-1);
+ for( count = 0; count < bits; ++ count )
+ {
+ *buf = (unsigned char)((*buf & (0xff^(1<<(7-bit)))) +
+ ((x & mask ? 1 : 0) << (7-bit)));
+ x <<= 1;
+ bit = (bit+1) & 7;
+ if( !bit )
+ {
+ ++ buf;
+ }
+ }
+
+ /* Store new stream state */
+ stream->BytePtr = buf;
+ stream->BitPos = bit;
+}
+#endif
+
+
+/*************************************************************************
+* _Huffman_Hist() - Calculate (sorted) histogram for a block of data.
+*************************************************************************/
+
+#ifdef HUFFMAN_ENCODE
+static void _Huffman_Hist( unsigned char *in, huff_sym_t *sym,
+ unsigned int size )
+{
+ int k;
+
+ /* Clear/init histogram */
+ for( k = 0; k < 256; ++ k )
+ {
+ sym[k].Symbol = k;
+ sym[k].Count = 0;
+ sym[k].Code = 0;
+ sym[k].Bits = 0;
+ }
+
+ /* Build histogram */
+ for( k = size; k; -- k )
+ {
+ sym[*in ++].Count ++;
+ }
+}
+#endif
+
+
+/*************************************************************************
+* _Huffman_StoreTree() - Store a Huffman tree in the output stream and
+* in a look-up-table (a symbol array).
+*************************************************************************/
+
+#ifdef HUFFMAN_ENCODE
+static void _Huffman_StoreTree( huff_encodenode_t *node, huff_sym_t *sym,
+ huff_bitstream_t *stream, unsigned int code, unsigned int bits )
+{
+ unsigned int sym_idx;
+
+ /* Is this a leaf node? */
+ if( node->Symbol >= 0 )
+ {
+ /* Append symbol to tree description */
+ _Huffman_WriteBits( stream, 1, 1 );
+ _Huffman_WriteBits( stream, node->Symbol, 8 );
+
+ /* Find symbol index */
+ for( sym_idx = 0; sym_idx < 256; ++ sym_idx )
+ {
+ if( sym[sym_idx].Symbol == node->Symbol ) break;
+ }
+
+ /* Store code info in symbol array */
+ sym[sym_idx].Code = code;
+ sym[sym_idx].Bits = bits;
+ return;
+ }
+ else
+ {
+ /* This was not a leaf node */
+ _Huffman_WriteBits( stream, 0, 1 );
+ }
+
+ /* Branch A */
+ _Huffman_StoreTree( node->ChildA, sym, stream, (code<<1)+0, bits+1 );
+
+ /* Branch B */
+ _Huffman_StoreTree( node->ChildB, sym, stream, (code<<1)+1, bits+1 );
+}
+#endif
+
+
+/*************************************************************************
+* _Huffman_MakeTree() - Generate a Huffman tree.
+*************************************************************************/
+
+#ifdef HUFFMAN_ENCODE
+static void _Huffman_MakeTree( huff_sym_t *sym, huff_bitstream_t *stream )
+{
+ huff_encodenode_t nodes[MAX_TREE_NODES], *node_1, *node_2, *root;
+ unsigned int k, num_symbols, nodes_left, next_idx;
+
+ /* Initialize all leaf nodes */
+ num_symbols = 0;
+ for( k = 0; k < 256; ++ k )
+ {
+ if( sym[k].Count > 0 )
+ {
+ nodes[num_symbols].Symbol = sym[k].Symbol;
+ nodes[num_symbols].Count = sym[k].Count;
+ nodes[num_symbols].ChildA = (huff_encodenode_t *) 0;
+ nodes[num_symbols].ChildB = (huff_encodenode_t *) 0;
+ ++ num_symbols;
+ }
+ }
+
+ /* Build tree by joining the lightest nodes until there is only
+ one node left (the root node). */
+ root = (huff_encodenode_t *) 0;
+ nodes_left = num_symbols;
+ next_idx = num_symbols;
+ while( nodes_left > 1 )
+ {
+ /* Find the two lightest nodes */
+ node_1 = (huff_encodenode_t *) 0;
+ node_2 = (huff_encodenode_t *) 0;
+ for( k = 0; k < next_idx; ++ k )
+ {
+ if( nodes[k].Count > 0 )
+ {
+ if( !node_1 || (nodes[k].Count <= node_1->Count) )
+ {
+ node_2 = node_1;
+ node_1 = &nodes[k];
+ }
+ else if( !node_2 || (nodes[k].Count <= node_2->Count) )
+ {
+ node_2 = &nodes[k];
+ }
+ }
+ }
+
+ /* Join the two nodes into a new parent node */
+ root = &nodes[next_idx];
+ root->ChildA = node_1;
+ root->ChildB = node_2;
+ root->Count = node_1->Count + node_2->Count;
+ root->Symbol = -1;
+ node_1->Count = 0;
+ node_2->Count = 0;
+ ++ next_idx;
+ -- nodes_left;
+ }
+
+ /* Store the tree in the output stream, and in the sym[] array (the
+ latter is used as a look-up-table for faster encoding) */
+ if( root )
+ {
+ _Huffman_StoreTree( root, sym, stream, 0, 0 );
+ }
+ else
+ {
+ /* Special case: only one symbol => no binary tree */
+ root = &nodes[0];
+ _Huffman_StoreTree( root, sym, stream, 0, 1 );
+ }
+}
+#endif
+
+
+/*************************************************************************
+* _Huffman_RecoverTree() - Recover a Huffman tree from a bitstream.
+*************************************************************************/
+
+static huff_decodenode_t * _Huffman_RecoverTree( huff_decodenode_t *nodes,
+ huff_bitstream_t *stream, unsigned int *nodenum )
+{
+ huff_decodenode_t * this_node;
+
+ /* Pick a node from the node array */
+ this_node = &nodes[*nodenum];
+ *nodenum = *nodenum + 1;
+
+ /* Clear the node */
+ this_node->Symbol = -1;
+ this_node->ChildA = (huff_decodenode_t *) 0;
+ this_node->ChildB = (huff_decodenode_t *) 0;
+
+ /* Is this a leaf node? */
+ if( _Huffman_ReadBit( stream ) )
+ {
+ /* Get symbol from tree description and store in lead node */
+ this_node->Symbol = _Huffman_Read8Bits( stream );
+
+ return this_node;
+ }
+
+ /* Get branch A */
+ this_node->ChildA = _Huffman_RecoverTree( nodes, stream, nodenum );
+
+ /* Get branch B */
+ this_node->ChildB = _Huffman_RecoverTree( nodes, stream, nodenum );
+
+ return this_node;
+}
+
+
+
+/*************************************************************************
+* PUBLIC FUNCTIONS *
+*************************************************************************/
+
+
+/*************************************************************************
+* Huffman_Compress() - Compress a block of data using a Huffman coder.
+* in - Input (uncompressed) buffer.
+* out - Output (compressed) buffer. This buffer must be 384 bytes
+* larger than the input buffer.
+* insize - Number of input bytes.
+* The function returns the size of the compressed data.
+*************************************************************************/
+
+#ifdef HUFFMAN_ENCODE
+int Huffman_Compress( unsigned char *in, unsigned char *out,
+ unsigned int insize )
+{
+ huff_sym_t sym[256], tmp;
+ huff_bitstream_t stream;
+ unsigned int k, total_bytes, swaps, symbol;
+
+ /* Do we have anything to compress? */
+ if( insize < 1 ) return 0;
+
+ /* Initialize bitstream */
+ _Huffman_InitBitstream( &stream, out );
+
+ /* Calculate and sort histogram for input data */
+ _Huffman_Hist( in, sym, insize );
+
+ /* Build Huffman tree */
+ _Huffman_MakeTree( sym, &stream );
+
+ /* Sort histogram - first symbol first (bubble sort) */
+ do
+ {
+ swaps = 0;
+ for( k = 0; k < 255; ++ k )
+ {
+ if( sym[k].Symbol > sym[k+1].Symbol )
+ {
+ tmp = sym[k];
+ sym[k] = sym[k+1];
+ sym[k+1] = tmp;
+ swaps = 1;
+ }
+ }
+ }
+ while( swaps );
+
+ /* Encode input stream */
+ for( k = 0; k < insize; ++ k )
+ {
+ symbol = in[k];
+ _Huffman_WriteBits( &stream, sym[symbol].Code,
+ sym[symbol].Bits );
+ }
+
+ /* Calculate size of output data */
+ total_bytes = (int)(stream.BytePtr - out);
+ if( stream.BitPos > 0 )
+ {
+ ++ total_bytes;
+ }
+
+ return total_bytes;
+}
+#endif
+
+
+/*************************************************************************
+* Huffman_Uncompress() - Uncompress a block of data using a Huffman
+* decoder.
+* in - Input (compressed) buffer.
+* out - Output (uncompressed) buffer. This buffer must be large
+* enough to hold the uncompressed data.
+* insize - Number of input bytes.
+* outsize - Number of output bytes.
+*************************************************************************/
+
+void Huffman_Uncompress( unsigned char *in, unsigned char *out,
+ unsigned int insize, unsigned int outsize )
+{
+ huff_decodenode_t nodes[MAX_TREE_NODES], *root, *node;
+ huff_bitstream_t stream;
+ unsigned int k, node_count;
+ unsigned char *buf;
+
+ /* Do we have anything to decompress? */
+ if( insize < 1 ) return;
+
+ /* Initialize bitstream */
+ _Huffman_InitBitstream( &stream, in );
+
+ /* Recover Huffman tree */
+ node_count = 0;
+ root = _Huffman_RecoverTree( nodes, &stream, &node_count );
+
+ /* Decode input stream */
+ buf = out;
+ for( k = 0; k < outsize; ++ k )
+ {
+ /* Traverse tree until we find a matching leaf node */
+ node = root;
+ while( node->Symbol < 0 )
+ {
+ /* Get next node */
+ if( _Huffman_ReadBit( &stream ) )
+ node = node->ChildB;
+ else
+ node = node->ChildA;
+ }
+
+ /* We found the matching leaf node and have the symbol */
+ *buf ++ = (unsigned char) node->Symbol;
+ }
+}
diff --git a/plugins/CountryFlags/icons.c b/plugins/CountryFlags/icons.c
new file mode 100644
index 0000000000..9611eb0b78
--- /dev/null
+++ b/plugins/CountryFlags/icons.c
@@ -0,0 +1,284 @@
+/*
+Miranda IM Country Flags Plugin
+Copyright (C) 2006-1007 H. Herkenrath
+
+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 (Flags-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "flags.h"
+
+extern HINSTANCE hInst;
+extern int nCountriesCount;
+extern struct CountryListEntry *countries;
+static HANDLE hServiceLoadIcon,hServiceCreateMergedIcon;
+
+/************************* Bitmap Access **************************/
+
+static HANDLE *phIconHandles;
+
+static int FASTCALL CountryNumberToBitmapIndex(int countryNumber)
+{
+ /* country number indices (same order as in flags.bmp) */
+ const int BitmapIndexMap[232]={
+ 0, 1, 7, 20, 27, 30, 31, 32, 33, 34, 36, 39, 40, 41, 43, 44, 45, 46, 47, 48,
+ 49, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 62, 63, 64, 65, 66, 81, 82, 84, 86,
+ 90, 91, 92, 93, 94, 95, 98, 101, 102, 103, 104, 105, 106, 107, 178, 108, 109, 110, 111, 112,
+ 113, 116, 117, 118, 121, 122, 123, 212, 213, 216, 218, 220, 221, 222, 223, 224, 225, 226, 227, 228,
+ 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 248, 249,
+ 250, 251, 252, 253, 254, 255, 256, 257, 258, 260, 261, 263, 264, 265, 266, 267, 268, 269, 290, 291,
+ 297, 298, 299, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 370, 371, 372, 373, 374, 375, 376,
+ 377, 378, 379, 380, 381, 382, 385, 386, 387, 389, 420, 421, 441, 442, 500, 501, 502, 503, 504, 505,
+ 506, 507, 508, 509, 590, 591, 592, 593, 595, 596, 597, 598, 599, 670, 671, 672, 673, 674, 675, 676,
+ 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 705, 706, 708, 709,
+ 711, 850, 852, 853, 855, 856, 880, 886, 960, 961, 962, 963, 964, 965, 966, 967, 968, 971, 972, 973,
+ 974, 975, 976, 977, 994, 995,1141,2691,3811,4101,6101,6722
+ };
+ /* shared flags by multiple countries */
+ switch(countryNumber) {
+ case 262: /* Reunion Island */
+ case 594: /* French Guiana */
+ case 5901: /* French Antilles */
+ countryNumber=33; /* France */
+ break;
+ case 120: /* Barbuda */
+ countryNumber=102; /* Antigua and Barbuda */
+ break;
+ case 6702: /* Tinian Island */
+ case 6701: /* Rota Island */
+ countryNumber=670; /* Saipan Island (Northern Mariana Islands) */
+ break;
+ case 115: /* Saint Kitts */
+ case 114: /* Nevis */
+ countryNumber=1141; /* Saint Kitts and Nevis */
+ break;
+ case 247: /* Ascension Island */
+ countryNumber=44; /* United Kingdom */
+ break;
+ case 6721: /* Australian Antarctic Territory */
+ countryNumber=61; /* Australia */
+ break;
+ case 5399: /* Guantanamo Bay */
+ countryNumber=1; /* USA */
+ }
+ /* binary search in index array */
+ { int low=0,i,high;
+ high=SIZEOF(BitmapIndexMap)-1;
+ if(countryNumber<=BitmapIndexMap[high])
+ while(low<=high) {
+ i=low+((high-low)/2);
+ /* never happens */
+ if(i<0 || i>=SIZEOF(BitmapIndexMap)) DebugBreak();
+ if(BitmapIndexMap[i]==countryNumber) return i;
+ if(countryNumber>BitmapIndexMap[i]) low=i+1;
+ else high=i-1;
+ }
+ }
+ /* Other,Unknown,Unspecified */
+ return 0;
+}
+
+// return value needs to be released using DestroyIcon()
+// only operates on color icons, which isn't a problem here
+static HICON FASTCALL ResizeIconCentered(HICON hIcon,int cx,int cy)
+{
+ HICON hResIcon=NULL;
+ ICONINFO icoi;
+ BITMAP bm;
+ register HDC hdc;
+ HBITMAP hbmPrev,hbm;
+ POINT pt;
+ hdc=CreateCompatibleDC(NULL);
+ if(hdc!=NULL) {
+ if(GetIconInfo(hIcon,&icoi)) {
+ if(GetObject(icoi.hbmColor,sizeof(bm),&bm) && bm.bmWidth<=cx && bm.bmHeight<=cy) {
+ pt.x=(cx-bm.bmWidth)/2;
+ pt.y=(cy-bm.bmHeight)/2;
+ hbmPrev=SelectObject(hdc,icoi.hbmColor);
+ if(hbmPrev!=NULL) { /* error on select? */
+ hbm=icoi.hbmColor;
+ icoi.hbmColor=CreateCompatibleBitmap(hdc,cx,cy);
+ if(icoi.hbmColor!=NULL)
+ if(SelectObject(hdc,icoi.hbmColor)!=NULL) { /* error on select? */
+ DeleteObject(hbm); /* delete prev color (XOR) */
+ if(BitBlt(hdc,0,0,cx,cy,NULL,0,0,BLACKNESS)) /* transparency: AND=0, XOR=1 */
+ if(DrawIconEx(hdc,pt.x,pt.y,hIcon,bm.bmWidth,bm.bmHeight,0,NULL,DI_IMAGE|DI_NOMIRROR)) {
+ if(SelectObject(hdc,icoi.hbmMask)!=NULL) { /* error on select? */
+ hbm=icoi.hbmMask;
+ icoi.hbmMask=CreateBitmap(cx,cy,1,1,NULL); /* mono */
+ if(icoi.hbmMask!=NULL)
+ if(SelectObject(hdc,icoi.hbmMask)!=NULL) { /* error on select? */
+ DeleteObject(hbm); /* delete prev mask (AND) */
+ if(BitBlt(hdc,0,0,cx,cy,NULL,0,0,WHITENESS)) /* transparency: AND=0, XOR=1 */
+ if(DrawIconEx(hdc,pt.x,pt.y,hIcon,0,0,0,NULL,DI_MASK|DI_NOMIRROR)) {
+ SelectObject(hdc,hbmPrev);
+ hResIcon=CreateIconIndirect(&icoi); /* bitmaps must not be selected */
+ }
+ }
+ }
+ }
+ }
+ SelectObject(hdc,hbmPrev);
+ }
+ }
+ DeleteObject(icoi.hbmColor);
+ DeleteObject(icoi.hbmMask);
+ }
+ DeleteDC(hdc);
+ }
+ return hResIcon;
+}
+
+/************************* Utils **********************************/
+
+HICON FASTCALL LoadFlagIcon(int countryNumber)
+{
+ char szId[20],*szCountry;
+ /* create identifier */
+ szCountry=(char*)CallService(MS_UTILS_GETCOUNTRYBYNUMBER,countryNumber,0);
+ if(szCountry==NULL) szCountry=(char*)CallService(MS_UTILS_GETCOUNTRYBYNUMBER,countryNumber=0xFFFF,0);
+ wsprintfA(szId,(countryNumber==0xFFFF)?"%s0x%X":"%s%i","flags_",countryNumber); /* buffer safe */
+ return (HICON)CallService(MS_SKIN2_GETICON,0,(LPARAM)szId);
+}
+
+int FASTCALL CountryNumberToIndex(int countryNumber)
+{
+ int i,nf=0;
+ for(i=0;i<nCountriesCount;++i) {
+ if(countries[i].id==countryNumber) return i;
+ if(countries[i].id==0xFFFF) nf=i;
+ }
+ return nf; /* Unknown */
+
+}
+
+/************************* Services *******************************/
+
+static int ServiceLoadFlagIcon(WPARAM wParam,LPARAM lParam)
+{
+ /* return handle */
+ if((BOOL)lParam) {
+ if(phIconHandles==NULL) return (int)(HANDLE)NULL;
+ return (int)phIconHandles[CountryNumberToIndex((int)wParam)];
+ }
+ /* return icon */
+ return (int)LoadFlagIcon(wParam);
+}
+
+static int ServiceCreateMergedFlagIcon(WPARAM wParam,LPARAM lParam)
+{
+ HICON hUpperIcon,hLowerIcon;
+ ICONINFO icoi;
+ BITMAP bm;
+ HDC hdc;
+ POINT aptTriangle[3];
+ HICON hIcon=NULL;
+ HRGN hrgn;
+ HBITMAP hbmPrev;
+ /* load both icons */
+ hLowerIcon=(HICON)ServiceLoadFlagIcon((WPARAM)lParam,0);
+ if(hLowerIcon==NULL) return (int)(HICON)NULL;
+ hUpperIcon=(HICON)ServiceLoadFlagIcon(wParam,0);
+ /* merge them */
+ if(GetIconInfo(hLowerIcon,&icoi)) {
+ if(hUpperIcon!=NULL && GetObject(icoi.hbmColor,sizeof(bm),&bm)) {
+ hdc=CreateCompatibleDC(NULL);
+ if(hdc!=NULL) {
+ ZeroMemory(&aptTriangle,sizeof(aptTriangle));
+ aptTriangle[1].y=bm.bmHeight-1;
+ aptTriangle[2].x=bm.bmWidth-1;
+ hrgn=CreatePolygonRgn(aptTriangle,SIZEOF(aptTriangle),WINDING);
+ if(hrgn!=NULL) {
+ SelectClipRgn(hdc,hrgn);
+ DeleteObject(hrgn);
+ hbmPrev=SelectObject(hdc,icoi.hbmColor);
+ if(hbmPrev!=NULL) { /* error on select? */
+ if(DrawIconEx(hdc,0,0,hUpperIcon,bm.bmWidth,bm.bmHeight,0,NULL,DI_NOMIRROR|DI_IMAGE))
+ if(SelectObject(hdc,icoi.hbmMask)!=NULL) /* error on select? */
+ DrawIconEx(hdc,0,0,hUpperIcon,bm.bmWidth,bm.bmHeight,0,NULL,DI_NOMIRROR|DI_MASK);
+ SelectObject(hdc,hbmPrev);
+ }
+ DeleteObject(hrgn);
+ }
+ DeleteDC(hdc);
+ }
+ }
+ /* create icon */
+ hIcon=CreateIconIndirect(&icoi);
+ DeleteObject(icoi.hbmColor);
+ DeleteObject(icoi.hbmMask);
+ }
+ return (int)hIcon;
+}
+
+/************************* Misc ***********************************/
+
+void InitIcons(void)
+{
+ HIMAGELIST himl;
+ SKINICONDESC sid;
+ char szId[20];
+ int i,index;
+ HICON hIcon;
+#if defined(_UNICODE)
+ WCHAR szName[64];
+ LCID locale;
+ locale=(LCID)CallService(MS_LANGPACK_GETLOCALE,0,0);
+#endif
+
+ /* register icons */
+ ZeroMemory(&sid,sizeof(sid));
+ sid.cbSize=sizeof(sid);
+ sid.pszName=szId;
+ sid.cx=GetSystemMetrics(SM_CXSMICON);
+ sid.cy=GetSystemMetrics(SM_CYSMICON);
+ sid.flags=SIDF_SORTED|SIDF_TCHAR;
+ sid.ptszSection=TranslateT("Country Flags");
+ /* all those flag icons do not need any transparency mask (flags are always opaque),
+ * storing them in a large bitmap to reduce file size */
+ himl=ImageList_LoadImage(hInst,MAKEINTRESOURCE(IDB_FLAGS),sid.cx,0,CLR_NONE,IMAGE_BITMAP,LR_CREATEDIBSECTION);
+ if(himl!=NULL) {
+ phIconHandles=(HANDLE*)mir_alloc(nCountriesCount*sizeof(HANDLE));
+ if(phIconHandles!=NULL)
+ for(i=0;i<nCountriesCount;++i) {
+#if defined(_UNICODE)
+ MultiByteToWideChar(locale,0,countries[i].szName,-1,szName,SIZEOF(szName));
+ szName[SIZEOF(szName)-1]=L'\0';
+ sid.pwszDescription=TranslateW(szName);
+#else
+ sid.pszDescription=Translate(countries[i].szName);
+#endif
+ /* create identifier */
+ wsprintfA(szId,(countries[i].id==0xFFFF)?"%s0x%X":"%s%i","flags_",countries[i].id); /* buffer safe */
+ index=CountryNumberToBitmapIndex(countries[i].id);
+ /* create icon */
+ hIcon=ImageList_GetIcon(himl,index,ILD_NORMAL);
+ sid.hDefaultIcon=(hIcon!=NULL)?ResizeIconCentered(hIcon,sid.cx,sid.cy):NULL;
+ if(hIcon!=NULL) DestroyIcon(hIcon);
+ index=CountryNumberToIndex(countries[i].id);
+ phIconHandles[index]=(HANDLE)CallService(MS_SKIN2_ADDICON,0,(LPARAM)&sid);
+ if(sid.hDefaultIcon!=NULL) DestroyIcon(sid.hDefaultIcon);
+ }
+ ImageList_Destroy(himl);
+ }
+ /* create services */
+ hServiceLoadIcon=CreateServiceFunction(MS_FLAGS_LOADFLAGICON,ServiceLoadFlagIcon);
+ hServiceCreateMergedIcon=CreateServiceFunction(MS_FLAGS_CREATEMERGEDFLAGICON,ServiceCreateMergedFlagIcon);
+}
+
+void UninitIcons(void)
+{
+ DestroyServiceFunction(hServiceLoadIcon);
+ DestroyServiceFunction(hServiceCreateMergedIcon);
+}
diff --git a/plugins/CountryFlags/ip2country.c b/plugins/CountryFlags/ip2country.c
new file mode 100644
index 0000000000..eae267aaa0
--- /dev/null
+++ b/plugins/CountryFlags/ip2country.c
@@ -0,0 +1,327 @@
+/*
+Miranda IM Country Flags Plugin
+Copyright (C) 2006-2007 H. Herkenrath
+
+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 (Flags-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "flags.h"
+
+extern HINSTANCE hInst;
+extern int nCountriesCount;
+extern struct CountryListEntry *countries;
+static HANDLE hServiceIpToCountry;
+
+/************************* Bin Records ****************************/
+
+#define DATARECORD_SIZE (sizeof(DWORD)+sizeof(DWORD)+sizeof(WORD))
+
+// mir_free() the return value
+static BYTE* GetDataHeader(BYTE *data,DWORD cbDataSize,DWORD *pnDataRecordCount)
+{
+ BYTE *recordData;
+ /* uncompressed size stored in first DWORD */
+ *pnDataRecordCount=(*(DWORD*)data)/DATARECORD_SIZE;
+ recordData=(BYTE*)mir_alloc(*(DWORD*)data);
+ if(recordData!=NULL)
+ Huffman_Uncompress(data+sizeof(DWORD),recordData,cbDataSize-sizeof(DWORD),*(DWORD*)data);
+ return recordData;
+}
+
+static int GetDataRecord(BYTE *data,DWORD index,DWORD *pdwFrom,DWORD *pdwTo)
+{
+ data+=index*DATARECORD_SIZE;
+ *pdwFrom=*(DWORD*)data;
+ data+=sizeof(DWORD);
+ if(pdwTo!=NULL) *pdwTo=*(DWORD*)data;
+ data+=sizeof(DWORD);
+ return (int)*(WORD*)data;
+}
+
+/************************* Record Cache ***************************/
+
+static CRITICAL_SECTION csRecordCache;
+static DWORD nDataRecordsCount; /* protected by csRecordCache */
+static BYTE *dataRecords; /* protected by csRecordCache */
+
+#define UNLOADDELAY 30*1000 /* time after which the data records are being unloaded */
+
+static void CALLBACK UnloadRecordCache(LPARAM lParam)
+{
+ UNREFERENCED_PARAMETER(lParam);
+ EnterCriticalSection(&csRecordCache);
+ mir_free(dataRecords);
+ dataRecords=NULL;
+ LeaveCriticalSection(&csRecordCache);
+}
+
+// function assumes it has got the csRecordCache mutex
+static BOOL EnsureRecordCacheLoaded(BYTE **pdata,DWORD *pcount)
+{
+ HRSRC hrsrc;
+ DWORD cb;
+ EnterCriticalSection(&csRecordCache);
+ if(dataRecords==NULL) {
+ /* load record data list from resources */
+ hrsrc=FindResource(hInst,MAKEINTRESOURCE(IDR_IPTOCOUNTRY),_T("BIN"));
+ cb=SizeofResource(hInst,hrsrc);
+ dataRecords=(BYTE*)LockResource(LoadResource(hInst,hrsrc));
+ if(cb<=sizeof(DWORD) || dataRecords==NULL) { LeaveCriticalSection(&csRecordCache); return FALSE; }
+ /* uncompress record data */
+ dataRecords=GetDataHeader(dataRecords,cb,&nDataRecordsCount);
+ if(dataRecords==NULL || !nDataRecordsCount) { LeaveCriticalSection(&csRecordCache); return FALSE; }
+ }
+ *pdata=dataRecords;
+ *pcount=nDataRecordsCount;
+ return TRUE;
+}
+
+static void LeaveRecordCache(void)
+{
+ /* mark for unload */
+ CallFunctionBuffered(UnloadRecordCache,0,FALSE,UNLOADDELAY);
+ LeaveCriticalSection(&csRecordCache);
+}
+
+/************************* Services *******************************/
+
+
+int ServiceIpToCountry(WPARAM wParam,LPARAM lParam)
+{
+ BYTE *data;
+ DWORD dwFrom,dwTo;
+ DWORD low=0,i,high;
+ int id;
+ UNREFERENCED_PARAMETER(lParam);
+ if(EnsureRecordCacheLoaded(&data,&high)) {
+ /* binary search in record data */
+ GetDataRecord(data,low,&dwFrom,NULL);
+ --high;
+ if(wParam>=dwFrom) /* only search if wParam valid */
+ while(low<=high) {
+ i=low+((high-low)/2);
+ /* never happens */
+ if(i<0) DebugBreak();
+ /* analyze record */
+ id=GetDataRecord(data,i,&dwFrom,&dwTo);
+ if(dwFrom<=wParam && dwTo>=wParam) { LeaveRecordCache(); return id; }
+ if(wParam>dwTo) low=i+1;
+ else high=i-1;
+ }
+ LeaveRecordCache();
+ }
+ return 0xFFFF; /* Unknown */
+}
+
+/************************* Bin Converter **************************/
+
+#ifdef BINCONV
+#include <stdio.h>
+#include <stdlib.h>
+
+struct {
+ const char *szMir;
+ const char *szCSV;
+} static const differentCountryNames[]={
+ {"British Virgin Islands","VIRGIN ISLANDS, BRITISH"},
+ {"Brunei","BRUNEI DARUSSALAM"},
+ {"Cape Verde Islands","CAPE VERDE"},
+ {"Cocos-Keeling Islands","COCOS (KEELING) ISLANDS"},
+ {"Chile, Republic of","CHILE"},
+ {"Congo, Democratic Republic of (Zaire)","THE DEMOCRATIC REPUBLIC OF THE CONGO"},
+ {"Congo, Republic of the","CONGO"},
+ {"Cote d'Ivoire (Ivory Coast)","COTE D'IVOIRE"},
+ {"Diego Garcia","BRITISH INDIAN OCEAN TERRITORY"},
+ {"Guam, US Territory of","GUAM"},
+ {"Iran (Islamic Republic of)","ISLAMIC REPUBLIC OF IRAN"},
+ {"Korea, North","REPUBLIC OF KOREA"},
+ {"Laos","LAO PEOPLE'S DEMOCRATIC REPUBLIC"},
+ {"Reunion Island","REUNION"},
+ {"Russia","RUSSIAN FEDERATION"},
+ {"Saipan Island (Northern Mariana Islands)","NORTHERN MARIANA ISLANDS"},
+ {"Tanzania","UNITED REPUBLIC OF TANZANIA"},
+ {"USA","UNITED STATES"},
+ {"Macau","MACAO"},
+ {"Macedonia (F.Y.R.O.M.)","THE FORMER YUGOSLAV REPUBLIC OF MACEDONIA"},
+ {"Micronesia, Federated States of","FEDERATED STATES OF MICRONESIA"},
+ {"Mayotte Island","MAYOTTE"},
+ {"Moldova, Republic of","REPUBLIC OF MOLDOVA"},
+ {"Vietnam","VIET NAM"},
+ {"Virgin Islands (USA)","VIRGIN ISLANDS, U.S."},
+ {"Vatican City","HOLY SEE (VATICAN CITY STATE)"},
+ {"Serbia, Republic of","SERBIA"},
+ {"Montenegro, Republic of","MONTENEGRO"},
+};
+
+#define ALLOC_STEP (800*1024) /* approx. size of data output */
+
+struct ResizableByteBuffer {
+ BYTE *buf;
+ DWORD cbLength,cbAlloced;
+};
+
+static void AppendToByteBuffer(struct ResizableByteBuffer *buffer,const void *append,DWORD cbAppendSize)
+{
+ if(buffer->cbAlloced<=buffer->cbLength+cbAppendSize) {
+ BYTE* buf=(BYTE*)mir_realloc(buffer->buf,buffer->cbAlloced+ALLOC_STEP+cbAppendSize);
+ if(buf==NULL) return;
+ buffer->buf=buf;
+ buffer->cbAlloced+=ALLOC_STEP+cbAppendSize;
+ OutputDebugStringA("reallocating memory...\n"); /* all ascii */
+ }
+ CopyMemory(&buffer->buf[buffer->cbLength],append,cbAppendSize);
+ buffer->cbLength+=cbAppendSize;
+}
+
+static int EnumIpDataLines(const char *pszFileCSV,const char *pszFileOut)
+{
+ FILE *fp;
+ char line[1024],out[512],*pszFrom,*pszTo,*pszTwo,*pszCountry,*buf;
+ int i,j;
+ DWORD dwOut;
+ WORD wOut;
+ struct ResizableByteBuffer buffer;
+
+ ZeroMemory(&buffer,sizeof(buffer));
+ fp=fopen(pszFileCSV,"rt");
+ if(fp!=NULL) {
+ OutputDebugStringA("Running IP data convert...\n"); /* all ascii */
+ while(!feof(fp)) {
+ if(fgets(line,sizeof(line),fp)==NULL) break;
+ /* get line data */
+ pszFrom=line+1;
+ pszTo=strchr(pszFrom,',');
+ *(pszTo-1)='\0'; pszTo+=2;
+ pszTwo=strchr(pszTo,',');
+ *(pszTwo-1)='\0'; pszTwo+=2;
+ pszCountry=strchr(pszTwo,',')+1;
+ pszCountry=strchr(pszCountry,',')+2;
+ buf=strchr(pszCountry,'"');
+ *buf=pszTwo[2]='\0';
+ /* corrections */
+ if(!lstrcmpi(pszCountry,"ANTARCTICA")) continue;
+ if(!lstrcmpi(pszCountry,"TIMOR-LESTE")) continue;
+ if(!lstrcmpi(pszCountry,"PALESTINIAN TERRITORY, OCCUPIED"))
+ lstrcpy(pszCountry,"ISRAEL");
+ else if(!lstrcmpi(pszCountry,"UNITED STATES MINOR OUTLYING ISLANDS"))
+ lstrcpy(pszCountry,"UNITED STATES");
+ else if(!lstrcmpi(pszCountry,"SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS"))
+ lstrcpy(pszCountry,"UNITED KINGDOM");
+ else if(!lstrcmpi(pszTwo,"JE")) /* map error */
+ lstrcpy(pszCountry,"UNITED KINGDOM");
+ else if(!lstrcmpi(pszTwo,"AX")) /* land Island belongs to Finland */
+ lstrcpy(pszCountry,"FINLAND");
+ else if(!lstrcmpi(pszTwo,"ME"))
+ lstrcpy(pszCountry,"MONTENEGRO");
+ else if(!lstrcmpi(pszTwo,"RS") || !lstrcmpi(pszTwo,"CS"))
+ lstrcpy(pszCountry,"SERBIA");
+ /* convert */
+ for(i=0;i<nCountriesCount;i++) {
+ /* map different writings */
+ for(j=0;j<SIZEOF(differentCountryNames);j++)
+ if(!lstrcmpi(countries[i].szName,differentCountryNames[j].szMir)) {
+ buf=(char*)differentCountryNames[j].szCSV;
+ break;
+ }
+ if(j==SIZEOF(differentCountryNames))
+ buf=(char*)countries[i].szName;
+ /* check country */
+ if(!lstrcmpiA(pszCountry,buf)) {
+ dwOut=(DWORD)atoi(pszFrom);
+ AppendToByteBuffer(&buffer,(void*)&dwOut,sizeof(DWORD));
+ dwOut=(DWORD)atoi(pszTo);
+ AppendToByteBuffer(&buffer,(void*)&dwOut,sizeof(DWORD));
+ wOut=(WORD)countries[i].id;
+ AppendToByteBuffer(&buffer,(void*)&wOut,sizeof(WORD));
+ break;
+ }
+ }
+ /* not in list */
+ if(i==nCountriesCount) {
+ wsprintfA(out,"Unknown: %s-%s [%s, %s]\n",pszFrom,pszTo,pszTwo,pszCountry);
+ OutputDebugStringA(out); /* all ascii */
+ }
+ }
+ fclose(fp);
+ OutputDebugStringA("Done!\n"); /* all ascii */
+ if(buffer.buf!=NULL) {
+ HANDLE hFileOut;
+ DWORD cbWritten=0;
+ BYTE *compressed;
+ DWORD cbCompressed;
+ /* compress whole data */
+ OutputDebugStringA("Compressing...\n"); /* all ascii */
+ compressed=(BYTE*)mir_alloc(buffer.cbAlloced+384);
+ if(compressed!=NULL) {
+ cbCompressed=Huffman_Compress(buffer.buf,compressed,buffer.cbLength);
+ OutputDebugStringA("Done!\n"); /* all ascii */
+ OutputDebugStringA("Writing to file...\n"); /* all ascii */
+ hFileOut=CreateFile(pszFileOut,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
+ if(hFileOut!=INVALID_HANDLE_VALUE) {
+ /* store data length count at beginning */
+ dwOut=buffer.cbLength;
+ WriteFile(hFileOut,&dwOut,sizeof(DWORD),&cbWritten,NULL);
+ /* store compressed data records */
+ WriteFile(hFileOut,compressed,cbCompressed,&cbWritten,NULL);
+ CloseHandle(hFileOut);
+ }
+ OutputDebugStringA("Done!\n"); /* all ascii */
+ mir_free(compressed);
+ }
+ mir_free(buffer.buf);
+ }
+ return 0;
+ }
+ return 1;
+}
+
+static void BinConvThread(void *unused)
+{
+ UNREFERENCED_PARAMETER(unused);
+ /* debug version only */
+ if(MessageBox(NULL,_T("Looking for 'ip-to-country.csv' in current directory.\n"
+ "It will be converted into 'ip-to-country.bin'.\n"
+ "See debug output for more details.\n"
+ "This process may take very long."),_T("Bin Converter"),MB_OKCANCEL|MB_ICONINFORMATION|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL)==IDOK) {
+ EnumIpDataLines("ip-to-country.csv","ip-to-country.bin");
+ MessageBox(NULL,_T("Done!\n'ip-to-country.bin' has been created in current directory."),_T("Bin Converter"),MB_OK|MB_ICONINFORMATION|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL);
+ }
+}
+
+#endif // BINCONV
+
+/************************* Misc ***********************************/
+
+void InitIpToCountry(void)
+{
+ /* Record Cache */
+ InitializeCriticalSection(&csRecordCache);
+ nDataRecordsCount=0;
+ dataRecords=NULL;
+ /* Services */
+ hServiceIpToCountry=CreateServiceFunction(MS_FLAGS_IPTOCOUNTRY,ServiceIpToCountry);
+#ifdef BINCONV
+ mir_forkthread(BinConvThread,NULL);
+#endif
+}
+
+void UninitIpToCountry(void)
+{
+ /* Record Cache */
+ DeleteCriticalSection(&csRecordCache);
+ mir_free(dataRecords); /* does NULL check */
+ /* Servcies */
+ DestroyServiceFunction(hServiceIpToCountry);
+}
diff --git a/plugins/CountryFlags/main.c b/plugins/CountryFlags/main.c
new file mode 100644
index 0000000000..2da90447c2
--- /dev/null
+++ b/plugins/CountryFlags/main.c
@@ -0,0 +1,163 @@
+/*
+Miranda IM Country Flags Plugin
+Copyright (C) 2006-2007 H. Herkenrath
+
+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 (Flags-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "flags.h"
+#include "version.h"
+
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+struct MM_INTERFACE mmi;
+int nCountriesCount;
+struct CountryListEntry *countries;
+
+static PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ "Country Flags",
+ PLUGIN_VERSION,
+#if defined(_DEBUG)
+ "Development build not intended for release. ("__DATE__")", /* autotranslated */
+#else
+ "Service offering misc country utilities as flag icons and a IP-to-Country database.", /* autotranslated */
+#endif
+ "H. Herkenrath",
+ PLUGIN_EMAIL, /* @ will be set later */
+ " 2006-2007 H. Herkenrath",
+ PLUGIN_WEBSITE,
+ UNICODE_AWARE,
+ 0,
+#if defined(_UNICODE)
+ // {68C36842-3D95-4f4a-AB81-014D6593863B}
+ {0x68c36842,0x3d95,0x4f4a,{0xab,0x81,0x1,0x4d,0x65,0x93,0x86,0x3b}},
+#else
+ // {E0C4681C-E680-4262-8B44-7A9540C064FF}
+ {0xe0c4681c,0xe680,0x4262,{0x8b,0x44,0x7a,0x95,0x40,0xc0,0x64,0xff}}
+#endif
+};
+static const MUUID interfaces[]={MIID_FLAGS,MIID_LAST};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,void *pReserved)
+{
+ UNREFERENCED_PARAMETER(pReserved);
+ if(fdwReason==DLL_PROCESS_ATTACH)
+ /* Do not call this function from a DLL that is linked to the static C run-time library (CRT).
+ * The static CRT requires DLL_THREAD_ATTACH and DLL_THREAD_DETATCH notifications to function properly. */
+ DisableThreadLibraryCalls(hInst=hinstDLL);
+ return TRUE;
+}
+
+static void InstallFile(const TCHAR *pszFileName,const TCHAR *pszDestSubDir)
+{
+ TCHAR szFileFrom[MAX_PATH+1],szFileTo[MAX_PATH+1],*p;
+ HANDLE hFile;
+
+ if(!GetModuleFileName(hInst,szFileFrom,SIZEOF(szFileFrom)-lstrlen(pszFileName)))
+ return;
+ p=_tcsrchr(szFileFrom,_T('\\'));
+ if(p!=NULL) *(++p)=0;
+ lstrcat(szFileFrom,pszFileName); /* buffer safe */
+
+ hFile=CreateFile(szFileFrom,0,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
+ if(hFile==INVALID_HANDLE_VALUE) return;
+ CloseHandle(hFile);
+
+ if(!GetModuleFileName(NULL,szFileTo,SIZEOF(szFileTo)-lstrlen(pszDestSubDir)-lstrlen(pszFileName)))
+ return;
+ p=_tcsrchr(szFileTo,_T('\\'));
+ if(p!=NULL) *(++p)=0;
+ lstrcat(szFileTo,pszDestSubDir); /* buffer safe */
+ CreateDirectory(szFileTo,NULL);
+ lstrcat(szFileTo,pszFileName); /* buffer safe */
+
+ if(!MoveFile(szFileFrom,szFileTo) && GetLastError()==ERROR_ALREADY_EXISTS) {
+ DeleteFile(szFileTo);
+ MoveFile(szFileFrom,szFileTo);
+ }
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+__declspec(dllexport) const PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
+{
+ if(mirandaVersion<PLUGIN_MAKE_VERSION(0,1,0,1)) return NULL;
+ pluginInfo.cbSize=sizeof(PLUGININFO); /* needed as v0.6 does equality check */
+ /* email obfuscated, made .rdata writable */
+ pluginInfo.authorEmail[PLUGIN_EMAIL_ATT_POS-1]='@';
+ return (PLUGININFO*)&pluginInfo; /* header is the same */
+}
+
+__declspec(dllexport) const PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ UNREFERENCED_PARAMETER(mirandaVersion);
+ pluginInfo.cbSize=sizeof(PLUGININFOEX);
+ /* email obfuscated, made .rdata writable */
+ pluginInfo.authorEmail[PLUGIN_EMAIL_ATT_POS-1]='@';
+ return &pluginInfo;
+}
+
+__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+__declspec(dllexport) int Load(PLUGINLINK *link)
+{
+ pluginLink=link;
+
+ /* existance of MS_SYSTEM_GETVERSION and MS_LANGPACK_TRANSLATESTRING
+ * is checked in MirandaPluginInfo().
+ * Not placed in MirandaPluginInfo() to avoid MessageBoxes on plugin options.
+ * Using ANSI as LANG_UNICODE might not be supported. */
+ if(CallService(MS_SYSTEM_GETVERSION,0,0)<NEEDED_MIRANDA_VERSION) {
+ char szText[256];
+ mir_snprintf(szText,SIZEOF(szText),Translate("The Country Flags Plugin can not be loaded. It requires Miranda IM %hs or later."),NEEDED_MIRANDA_VERSION_STR);
+ MessageBoxA(NULL,szText,Translate("Country Flags Plugin"),MB_OK|MB_ICONINFORMATION|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL);
+ return 1;
+ }
+ if(mir_getMMI(&mmi)) return 1;
+
+ PrepareBufferedFunctions();
+ InitCountryListExt();
+ if(CallService(MS_UTILS_GETCOUNTRYLIST,(WPARAM)&nCountriesCount,(LPARAM)&countries))
+ nCountriesCount=0;
+ InitIcons();
+ InitIpToCountry();
+ InitExtraImg();
+
+ /* installation */
+ InstallFile(_T("Flags-Readme.txt"),_T("Docs\\"));
+ InstallFile(_T("Flags-License.txt"),_T("Docs\\"));
+ InstallFile(_T("Flags-SDK.zip"),_T("Docs\\"));
+ return 0;
+}
+
+__declspec(dllexport) int Unload(void)
+{
+ KillBufferedFunctions();
+ UninitExtraImg();
+ UninitIpToCountry();
+ UninitIcons();
+ UninitCountryListExt();
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/plugins/CountryFlags/res/flags.bmp b/plugins/CountryFlags/res/flags.bmp
new file mode 100644
index 0000000000..bfbf4a70e6
--- /dev/null
+++ b/plugins/CountryFlags/res/flags.bmp
Binary files differ
diff --git a/plugins/CountryFlags/res/ip-to-country.bin b/plugins/CountryFlags/res/ip-to-country.bin
new file mode 100644
index 0000000000..a43e8663e6
--- /dev/null
+++ b/plugins/CountryFlags/res/ip-to-country.bin
Binary files differ
diff --git a/plugins/CountryFlags/resource.h b/plugins/CountryFlags/resource.h
new file mode 100644
index 0000000000..a2cd0496d8
--- /dev/null
+++ b/plugins/CountryFlags/resource.h
@@ -0,0 +1,25 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by resource.rc
+//
+#define IDB_FLAGS 101
+#define IDR_IPTOCOUNTRY 102
+#define IDD_OPT_EXTRAIMG 103
+#define IDC_CHECK_SHOWSTATUSICONFLAG 1001
+#define IDC_CHECK_SHOWEXTRAIMGFLAG 1002
+#define IDC_TEXT_EXTRAIMGFLAGCOLUMN 1003
+#define IDC_COMBO_EXTRAIMGFLAGCOLUMN 1004
+#define IDC_CHECK_USEUNKNOWNFLAG 1005
+#define IDC_CHECK_USEIPTOCOUNTRY 1006
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 104
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1007
+#define _APS_NEXT_SYMED_VALUE 2001
+#endif
+#endif
diff --git a/plugins/CountryFlags/resource.rc b/plugins/CountryFlags/resource.rc
new file mode 100644
index 0000000000..eba35cb8e3
--- /dev/null
+++ b/plugins/CountryFlags/resource.rc
@@ -0,0 +1,128 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include <winres.h>
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Englisch (GB) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE MOVEABLE PURE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE MOVEABLE PURE
+BEGIN
+ "#include <winres.h>\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE MOVEABLE PURE
+BEGIN
+ "#include ""version.rc""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_FLAGS BITMAP DISCARDABLE "res/flags.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// BIN
+//
+
+IDR_IPTOCOUNTRY BIN DISCARDABLE "res/ip-to-country.bin"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_OPT_EXTRAIMG DIALOGEX 0, 0, 223, 93
+STYLE DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "Country Flags",-1,3,0,220,93
+ CONTROL "Show country flag as &status icon on message window",
+ IDC_CHECK_SHOWSTATUSICONFLAG,"Button",BS_AUTOCHECKBOX |
+ WS_GROUP | WS_TABSTOP,12,14,206,10
+ CONTROL "Show country flag as &extra image on contact list",
+ IDC_CHECK_SHOWEXTRAIMGFLAG,"Button",BS_AUTOCHECKBOX |
+ WS_GROUP | WS_TABSTOP,12,27,206,10
+ LTEXT "In following contact list &column:",
+ IDC_TEXT_EXTRAIMGFLAGCOLUMN,24,42,110,8
+ COMBOBOX IDC_COMBO_EXTRAIMGFLAGCOLUMN,135,40,77,117,
+ CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Use &unknown flag if the country can not be determined",
+ IDC_CHECK_USEUNKNOWNFLAG,"Button",BS_AUTOCHECKBOX |
+ WS_GROUP | WS_TABSTOP,12,77,206,10
+ CONTROL "Use &IP-to-country database for country detection",
+ IDC_CHECK_USEIPTOCOUNTRY,"Button",BS_AUTOCHECKBOX |
+ WS_GROUP | WS_TABSTOP,12,64,206,10
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_OPT_EXTRAIMG, DIALOG
+ BEGIN
+ VERTGUIDE, 3
+ VERTGUIDE, 12
+ VERTGUIDE, 24
+ VERTGUIDE, 218
+ HORZGUIDE, 42
+ HORZGUIDE, 52
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // Englisch (GB) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#include "version.rc"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/CountryFlags/utils.c b/plugins/CountryFlags/utils.c
new file mode 100644
index 0000000000..d71b0acde3
--- /dev/null
+++ b/plugins/CountryFlags/utils.c
@@ -0,0 +1,162 @@
+/*
+Miranda IM Country Flags Plugin
+Copyright (C) 2006-1007 H. Herkenrath
+
+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 (Flags-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "flags.h"
+
+/************************* Buffered Functions *********************/
+
+struct BufferedCallData {
+ DWORD startTick;
+ UINT uElapse;
+ BUFFEREDPROC pfnBuffProc;
+ LPARAM lParam;
+ #ifdef _DEBUG
+ const char *pszProcName;
+ #endif
+};
+
+static UINT idBufferedTimer;
+static struct BufferedCallData *callList;
+static int nCallListCount;
+
+// always gets called in main message loop
+static void CALLBACK BufferedProcTimer(HWND hwnd,UINT msg,UINT idTimer,DWORD currentTick)
+{
+ int i;
+ struct BufferedCallData *buf;
+ UINT uElapsed,uElapseNext=USER_TIMER_MAXIMUM;
+ BUFFEREDPROC pfnBuffProc;
+ LPARAM lParam;
+ #ifdef _DEBUG
+ char szDbgLine[256];
+ const char *pszProcName;
+ #endif
+ UNREFERENCED_PARAMETER(msg);
+
+ for(i=0;i<nCallListCount;++i) {
+ /* find elapsed procs */
+ uElapsed=currentTick-callList[i].startTick; /* wraparound works */
+ if((uElapsed+USER_TIMER_MINIMUM)>=callList[i].uElapse) {
+ /* call elapsed proc */
+ pfnBuffProc=callList[i].pfnBuffProc;
+ lParam=callList[i].lParam;
+ #ifdef _DEBUG
+ pszProcName=callList[i].pszProcName;
+ #endif
+ /* resize storage array */
+ if((i+1)<nCallListCount)
+ MoveMemory(&callList[i],&callList[i+1],((nCallListCount-i-1)*sizeof(struct BufferedCallData)));
+ --nCallListCount;
+ --i; /* reiterate current */
+ if(nCallListCount) {
+ buf=(struct BufferedCallData*)mir_realloc(callList,nCallListCount*sizeof(struct BufferedCallData));
+ if(buf!=NULL) callList=buf;
+ } else {
+ mir_free(callList);
+ callList=NULL;
+ }
+ #ifdef _DEBUG
+ mir_snprintf(szDbgLine,sizeof(szDbgLine),"buffered call: %s(0x%X)\n",pszProcName,lParam); /* all ascii */
+ OutputDebugStringA(szDbgLine);
+ #endif
+ CallFunctionAsync((void (CALLBACK *)(void*))pfnBuffProc,(void*)lParam); /* compatible */
+ }
+ /* find next timer delay */
+ else if((callList[i].uElapse-uElapsed)<uElapseNext)
+ uElapseNext=callList[i].uElapse-uElapsed;
+ }
+
+ /* set next timer */
+ if(nCallListCount) {
+ #ifdef _DEBUG
+ mir_snprintf(szDbgLine,sizeof(szDbgLine),"next buffered timeout: %ums\n",uElapseNext); /* all ascii */
+ OutputDebugStringA(szDbgLine);
+ #endif
+ idBufferedTimer=SetTimer(hwnd,idBufferedTimer,uElapseNext,BufferedProcTimer); /* will be reset */
+ } else {
+ KillTimer(hwnd,idTimer);
+ idBufferedTimer=0;
+ #ifdef _DEBUG
+ OutputDebugStringA("empty buffered queue\n");
+ #endif
+ }
+}
+
+// assumes to be called in context of main thread
+#ifdef _DEBUG
+void _CallFunctionBuffered(BUFFEREDPROC pfnBuffProc,const char *pszProcName,LPARAM lParam,BOOL fAccumulateSameParam,UINT uElapse)
+#else
+void _CallFunctionBuffered(BUFFEREDPROC pfnBuffProc,LPARAM lParam,BOOL fAccumulateSameParam,UINT uElapse)
+#endif
+{
+ struct BufferedCallData *data=NULL;
+ int i;
+
+ /* find existing */
+ for(i=0;i<nCallListCount;++i)
+ if(callList[i].pfnBuffProc==pfnBuffProc)
+ if(!fAccumulateSameParam || callList[i].lParam==lParam) {
+ data=&callList[i];
+ break;
+ }
+ /* append new */
+ if(data==NULL) {
+ /* resize storage array */
+ data=(struct BufferedCallData*)mir_realloc(callList,(nCallListCount+1)*sizeof(struct BufferedCallData));
+ if(data==NULL) return;
+ callList=data;
+ data=&callList[nCallListCount];
+ ++nCallListCount;
+ }
+ /* set delay */
+ data->startTick=GetTickCount();
+ data->uElapse=uElapse;
+ data->lParam=lParam;
+ data->pfnBuffProc=pfnBuffProc;
+ #ifdef _DEBUG
+ { char szDbgLine[256];
+ data->pszProcName=pszProcName;
+ mir_snprintf(szDbgLine,sizeof(szDbgLine),"buffered queue: %s(0x%X)\n",pszProcName,lParam); /* all ascii */
+ OutputDebugStringA(szDbgLine);
+ if(!idBufferedTimer) {
+ mir_snprintf(szDbgLine,sizeof(szDbgLine),"next buffered timeout: %ums\n",uElapse); /* all ascii */
+ OutputDebugStringA(szDbgLine);
+ }
+ }
+ #endif
+ /* set next timer */
+ if(idBufferedTimer) uElapse=USER_TIMER_MINIMUM; /* will get recalculated */
+ idBufferedTimer=SetTimer(NULL,idBufferedTimer,uElapse,BufferedProcTimer);
+}
+
+// assumes to be called in context of main thread
+void PrepareBufferedFunctions(void)
+{
+ idBufferedTimer=0;
+ nCallListCount=0;
+ callList=NULL;
+}
+
+// assumes to be called in context of main thread
+void KillBufferedFunctions(void)
+{
+ if(idBufferedTimer) KillTimer(NULL,idBufferedTimer);
+ nCallListCount=0;
+ mir_free(callList); /* does NULL check */
+}
diff --git a/plugins/CountryFlags/version.h b/plugins/CountryFlags/version.h
new file mode 100644
index 0000000000..b1c58f55cc
--- /dev/null
+++ b/plugins/CountryFlags/version.h
@@ -0,0 +1,38 @@
+/*
+Miranda IM Country Flags Plugin
+Copyright (C) 2006-2007 H. Herkenrath
+
+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 (Flags-License.txt); if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#define NEEDED_MIRANDA_VERSION PLUGIN_MAKE_VERSION(0,7,0,10)
+#define NEEDED_MIRANDA_VERSION_STR "0.7 alpha build #10"
+#define PLUGIN_VERSION PLUGIN_MAKE_VERSION(0,1,0,3)
+#define FILE_VERSION 0,1,0,3
+
+#ifdef _DEBUG
+ #define FILE_VERSION_STR "0.1.0.4 alpha"
+#else
+ #define FILE_VERSION_STR "0.1.0.3"
+#endif
+
+#define PLUGIN_EMAIL "hrathh users.sourceforge.net"
+#define PLUGIN_EMAIL_ATT_POS 7 /* position of the @-sign in the email adress above */
+
+#ifdef _UNICODE
+ #define PLUGIN_WEBSITE "http://addons.miranda-im.org/details.php?action=viewfile&id=3463"
+#else
+ #define PLUGIN_WEBSITE "http://addons.miranda-im.org/details.php?action=viewfile&id=3462"
+#endif
diff --git a/plugins/CountryFlags/version.rc b/plugins/CountryFlags/version.rc
new file mode 100644
index 0000000000..8694503dee
--- /dev/null
+++ b/plugins/CountryFlags/version.rc
@@ -0,0 +1,47 @@
+#ifndef _MAC
+
+#include <version.h>
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION FILE_VERSION
+ PRODUCTVERSION FILE_VERSION
+ FILEFLAGSMASK 0x0L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Comments", "Licensed under the terms of the GNU General Public License"
+ VALUE "FileDescription", "Country Flags Plugin for Miranda IM"
+ VALUE "FileVersion", FILE_VERSION_STR
+ VALUE "InternalName", "CountryUtils"
+ VALUE "LegalCopyright", "Copyright 2006-2007 H. Herkenrath"
+ VALUE "OriginalFilename", "flags.dll"
+ VALUE "ProductName", "Country Flags"
+ VALUE "ProductVersion", FILE_VERSION_STR
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+
+
diff --git a/plugins/FavContacts/favcontacts.sln b/plugins/FavContacts/favcontacts.sln
new file mode 100644
index 0000000000..4572aa3063
--- /dev/null
+++ b/plugins/FavContacts/favcontacts.sln
@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual C++ Express 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "favcontacts", "favcontacts.vcxproj", "{2D0B4CB0-3ACA-4612-B745-FF3050E1500A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug Unicode|Win32 = Debug Unicode|Win32
+ Release Unicode|Win32 = Release Unicode|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {2D0B4CB0-3ACA-4612-B745-FF3050E1500A}.Debug Unicode|Win32.ActiveCfg = Debug Unicode|Win32
+ {2D0B4CB0-3ACA-4612-B745-FF3050E1500A}.Debug Unicode|Win32.Build.0 = Debug Unicode|Win32
+ {2D0B4CB0-3ACA-4612-B745-FF3050E1500A}.Release Unicode|Win32.ActiveCfg = Release Unicode|Win32
+ {2D0B4CB0-3ACA-4612-B745-FF3050E1500A}.Release Unicode|Win32.Build.0 = Release Unicode|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/plugins/FavContacts/favcontacts.vcxproj b/plugins/FavContacts/favcontacts.vcxproj
new file mode 100644
index 0000000000..8c99da3f7b
--- /dev/null
+++ b/plugins/FavContacts/favcontacts.vcxproj
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug Unicode|Win32">
+ <Configuration>Debug Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release Unicode|Win32">
+ <Configuration>Release Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{2D0B4CB0-3ACA-4612-B745-FF3050E1500A}</ProjectGuid>
+ <RootNamespace>favcontacts</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">true</GenerateManifest>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;FAVCONTACTS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;FAVCONTACTS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <EntryPointSymbol>
+ </EntryPointSymbol>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="src\contact_cache.cpp" />
+ <ClCompile Include="src\favlist.cpp" />
+ <ClCompile Include="src\main.cpp" />
+ <ClCompile Include="src\cserver.cpp" />
+ <ClCompile Include="src\csocket.cpp" />
+ <ClCompile Include="src\http_api.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\contact_cache.h" />
+ <ClInclude Include="src\favlist.h" />
+ <ClInclude Include="src\headers.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="src\cserver.h" />
+ <ClInclude Include="src\csocket.h" />
+ <ClInclude Include="src\http_api.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\favorite.ico" />
+ <None Include="res\regular.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resource.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/FavContacts/favcontacts.vcxproj.filters b/plugins/FavContacts/favcontacts.vcxproj.filters
new file mode 100644
index 0000000000..81cec32c10
--- /dev/null
+++ b/plugins/FavContacts/favcontacts.vcxproj.filters
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+ </Filter>
+ <Filter Include="http">
+ <UniqueIdentifier>{190cde56-eadb-44f2-a0cd-1cb46fe8de29}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\contact_cache.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\favlist.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\main.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\cserver.cpp">
+ <Filter>http</Filter>
+ </ClCompile>
+ <ClCompile Include="src\csocket.cpp">
+ <Filter>http</Filter>
+ </ClCompile>
+ <ClCompile Include="src\http_api.cpp">
+ <Filter>http</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\contact_cache.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\favlist.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\headers.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="src\cserver.h">
+ <Filter>http</Filter>
+ </ClInclude>
+ <ClInclude Include="src\csocket.h">
+ <Filter>http</Filter>
+ </ClInclude>
+ <ClInclude Include="src\http_api.h">
+ <Filter>http</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="res\favorite.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="res\regular.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resource.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/FavContacts/res/favlist.ico b/plugins/FavContacts/res/favlist.ico
new file mode 100644
index 0000000000..9b55cd0afa
--- /dev/null
+++ b/plugins/FavContacts/res/favlist.ico
Binary files differ
diff --git a/plugins/FavContacts/res/favorite.ico b/plugins/FavContacts/res/favorite.ico
new file mode 100644
index 0000000000..4b0bff0f6b
--- /dev/null
+++ b/plugins/FavContacts/res/favorite.ico
Binary files differ
diff --git a/plugins/FavContacts/res/regular.ico b/plugins/FavContacts/res/regular.ico
new file mode 100644
index 0000000000..6ddb31921a
--- /dev/null
+++ b/plugins/FavContacts/res/regular.ico
Binary files differ
diff --git a/plugins/FavContacts/res/userprefs.ico b/plugins/FavContacts/res/userprefs.ico
new file mode 100644
index 0000000000..7028f10d03
--- /dev/null
+++ b/plugins/FavContacts/res/userprefs.ico
Binary files differ
diff --git a/plugins/FavContacts/resource.h b/plugins/FavContacts/resource.h
new file mode 100644
index 0000000000..4e3f557cf7
--- /dev/null
+++ b/plugins/FavContacts/resource.h
@@ -0,0 +1,39 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by resource.rc
+//
+#define IDI_FAVOURITE 101
+#define IDI_ICON1 102
+#define IDI_REGULAR 102
+#define IDD_DIALOG1 103
+#define IDD_LIST 103
+#define IDD_PROPPAGE_LARGE 107
+#define IDD_OPTIONS 107
+#define IDC_CLIST 1001
+#define IDC_CHK_SECONDLINE 1003
+#define IDC_CHK_AVATARS 1004
+#define IDC_CHK_AVATARBORDER 1005
+#define IDC_TXT_RADIUS 1007
+#define IDC_CHK_NOTRANSPARENTBORDER 1008
+#define IDC_CHK_CENTERHOTKEY 1009
+#define IDC_CHK_SYSCOLORS 1010
+#define IDC_CANVAS 1011
+#define IDC_CHK_DIMIDLE 1012
+#define IDC_CHK_GROUPS 1013
+#define IDC_CHK_GROUPCOLUMS 1014
+#define IDC_BTN_FONTS 1015
+#define IDC_TXT_RADIUS2 1016
+#define IDC_TXT_MAXRECENT 1016
+#define IDC_BTN_HOTKEYS 1018
+#define IDC_CHK_RIGHTAVATARS 1019
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 104
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1016
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/FavContacts/resource.rc b/plugins/FavContacts/resource.rc
new file mode 100644
index 0000000000..a96aabaf04
--- /dev/null
+++ b/plugins/FavContacts/resource.rc
@@ -0,0 +1,166 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Neutral resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
+#ifdef _WIN32
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+#pragma code_page(1251)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_FAVOURITE ICON "res\\favorite.ico"
+IDI_REGULAR ICON "res\\regular.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_OPTIONS DIALOGEX 0, 0, 316, 251
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Customize",IDC_STATIC,5,5,149,241
+ CONTROL "Show second line",IDC_CHK_SECONDLINE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,43,137,10
+ CONTROL "Show avatars",IDC_CHK_AVATARS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,56,137,10
+ CONTROL "Draw avatar border",IDC_CHK_AVATARBORDER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,26,82,122,10
+ RTEXT "Round corners by",IDC_STATIC,26,95,71,10,SS_CENTERIMAGE
+ EDITTEXT IDC_TXT_RADIUS,99,94,29,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "px.",IDC_STATIC,132,95,16,10,SS_CENTERIMAGE
+ CONTROL "Hide for transparent avatars",IDC_CHK_NOTRANSPARENTBORDER,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,40,108,108,10
+ CONTROL "Use system colors and fonts",IDC_CHK_SYSCOLORS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,134,137,10
+ CONTROL "Hotkey shows menu centered on screen",IDC_CHK_CENTERHOTKEY,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,147,139,10
+ LTEXT "Menu item preview:",IDC_STATIC,11,177,137,8
+ CONTROL "",IDC_CANVAS,"Static",SS_OWNERDRAW,26,189,122,26
+ GROUPBOX "Favourite Contacts",IDC_STATIC,161,5,150,241
+ CONTROL "",IDC_CLIST,"CListControl",WS_TABSTOP | 0x1,167,17,138,223,WS_EX_CLIENTEDGE
+ CONTROL "Enable groups",IDC_CHK_GROUPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,17,137,10
+ CONTROL "Multicolumn menu",IDC_CHK_GROUPCOLUMS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,26,30,122,10
+ CONTROL "Configure fonts and colors...",IDC_BTN_FONTS,"Hyperlink",WS_TABSTOP,11,229,137,11
+ CONTROL "Set up menu hotkey...",IDC_BTN_HOTKEYS,"Hyperlink",WS_TABSTOP,11,218,137,11
+ CONTROL "Align to the right",IDC_CHK_RIGHTAVATARS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,26,69,122,10
+ CONTROL "Dim idle contact icons",IDC_CHK_DIMIDLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,121,139,10
+ RTEXT "Show",IDC_STATIC,12,160,34,10,SS_CENTERIMAGE
+ EDITTEXT IDC_TXT_MAXRECENT,50,159,29,12,ES_CENTER | ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "recent contacts",IDC_STATIC,84,160,65,10,SS_CENTERIMAGE
+END
+
+IDD_LIST DIALOGEX 0, 0, 316, 183
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_BORDER | WS_SYSMENU
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_OPTIONS, DIALOG
+ BEGIN
+ VERTGUIDE, 5
+ VERTGUIDE, 11
+ VERTGUIDE, 26
+ VERTGUIDE, 148
+ VERTGUIDE, 154
+ VERTGUIDE, 161
+ VERTGUIDE, 167
+ VERTGUIDE, 305
+ VERTGUIDE, 311
+ HORZGUIDE, 5
+ HORZGUIDE, 17
+ HORZGUIDE, 229
+ HORZGUIDE, 240
+ HORZGUIDE, 246
+ END
+
+ IDD_LIST, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 309
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 176
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // Neutral resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Ukrainian resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_UKR)
+#ifdef _WIN32
+LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Ukrainian resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/FavContacts/src/contact_cache.cpp b/plugins/FavContacts/src/contact_cache.cpp
new file mode 100644
index 0000000000..c61635cc26
--- /dev/null
+++ b/plugins/FavContacts/src/contact_cache.cpp
@@ -0,0 +1,231 @@
+#include "headers.h"
+#include <time.h>
+#include <math.h>
+
+int __cdecl CContactCache::OnDbEventAdded(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ HANDLE hEvent = (HANDLE)lParam;
+
+ DBEVENTINFO dbei = {0};
+ dbei.cbSize = sizeof(dbei);
+ CallService(MS_DB_EVENT_GET, (WPARAM)hEvent, (LPARAM)&dbei);
+ if (dbei.eventType != EVENTTYPE_MESSAGE) return 0;
+
+ float weight = GetEventWeight(time(NULL) - dbei.timestamp);
+ float q = GetTimeWeight(time(NULL) - m_lastUpdate);
+ m_lastUpdate = time(NULL);
+ if (!weight) return 0;
+
+ Lock();
+ bool found = false;
+ for (int i = 0; i < m_cache.getCount(); ++i)
+ {
+ m_cache[i].rate *= q;
+ if (m_cache[i].hContact == hContact)
+ {
+ found = true;
+ m_cache[i].rate += weight;
+ }
+ }
+
+ if (!found)
+ {
+ TContactInfo *info = new TContactInfo;
+ info->hContact = hContact;
+ info->rate = weight;
+ m_cache.insert(info);
+ } else
+ {
+ qsort(m_cache.getArray(), m_cache.getCount(), sizeof(TContactInfo *), TContactInfo::cmp2);
+ }
+
+ Unlock();
+ return 0;
+}
+
+float CContactCache::GetEventWeight(unsigned long age)
+{
+ const float ceil = 1000.f;
+ const float floor = 0.0001f;
+ const int depth = 60 * 60 * 24 * 30;
+ if (age > depth) return 0;
+ return exp(log(ceil) - age * (log(ceil) - log(floor)) / depth);
+}
+
+float CContactCache::GetTimeWeight(unsigned long age)
+{
+ const float ceil = 1000.f;
+ const float floor = 0.0001f;
+ const int depth = 60 * 60 * 24 * 30;
+ if (age > depth) return 0;
+ return exp(age * (log(ceil) - log(floor)) / depth);
+}
+
+CContactCache::CContactCache(): m_cache(50, TContactInfo::cmp)
+{
+ InitializeCriticalSection(&m_cs);
+
+ int (__cdecl CContactCache::*pfn)(WPARAM, LPARAM);
+ pfn = &CContactCache::OnDbEventAdded;
+ m_hOnDbEventAdded = HookEventObj(ME_DB_EVENT_ADDED, *(MIRANDAHOOKOBJ *)&pfn, this);
+
+ Rebuild();
+}
+
+CContactCache::~CContactCache()
+{
+ UnhookEvent(m_hOnDbEventAdded);
+ DeleteCriticalSection(&m_cs);
+}
+
+void CContactCache::Rebuild()
+{
+ unsigned long timestamp = time(NULL);
+ m_lastUpdate = time(NULL);
+
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact)
+ {
+ TContactInfo *info = new TContactInfo;
+ info->hContact = hContact;
+ info->rate = 0;
+
+ HANDLE hEvent = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0);
+ while (hEvent)
+ {
+ DBEVENTINFO dbei = {0};
+ dbei.cbSize = sizeof(dbei);
+ if (!CallService(MS_DB_EVENT_GET, (WPARAM)hEvent, (LPARAM)&dbei))
+ {
+ if (float weight = GetEventWeight(timestamp - dbei.timestamp))
+ {
+ if (dbei.eventType == EVENTTYPE_MESSAGE)
+ info->rate += weight;
+ } else
+ {
+ break;
+ }
+ }
+ hEvent = (HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hEvent, 0);
+ }
+
+ m_cache.insert(info);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+}
+
+HANDLE CContactCache::get(int rate)
+{
+ if (rate >= 0 && rate < m_cache.getCount())
+ return m_cache[rate].hContact;
+ return NULL;
+}
+
+float CContactCache::getWeight(int rate)
+{
+ if (rate >= 0 && rate < m_cache.getCount())
+ return m_cache[rate].rate;
+ return -1;
+}
+
+static bool AppendInfo(TCHAR *buf, int size, HANDLE hContact, int info)
+{
+ CONTACTINFO ci = {0};
+ ci.cbSize = sizeof(ci);
+ ci.hContact = hContact;
+ ci.dwFlag = info;
+#if defined(UNICODE) || defined(_UNICODE)
+ ci.dwFlag |= CNF_UNICODE;
+#endif
+
+ bool ret = false;
+
+ if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci) && (ci.type == CNFT_ASCIIZ) && ci.pszVal)
+ {
+ if (*ci.pszVal && (lstrlen(ci.pszVal) < size-2))
+ {
+ lstrcpy(buf, ci.pszVal);
+ ret = true;
+ }
+ mir_free(ci.pszVal);
+ }
+
+ return ret;
+}
+
+void CContactCache::TContactInfo::LoadInfo()
+{
+ if (infoLoaded) return;
+ TCHAR *p = info;
+
+ p[0] = p[1] = 0;
+
+ static const int items[] = {
+ CNF_FIRSTNAME, CNF_LASTNAME, CNF_NICK , CNF_CUSTOMNICK, CNF_EMAIL, CNF_CITY, CNF_STATE,
+ CNF_COUNTRY, CNF_PHONE, CNF_HOMEPAGE, CNF_ABOUT, CNF_UNIQUEID, CNF_MYNOTES, CNF_STREET,
+ CNF_CONAME, CNF_CODEPT, CNF_COCITY, CNF_COSTATE, CNF_COSTREET, CNF_COCOUNTRY
+ };
+
+ for (int i = 0; i < SIZEOF(items); ++i)
+ {
+ if (AppendInfo(p, SIZEOF(info) - (p - info), hContact, items[i]))
+ p += lstrlen(p) + 1;
+ }
+ *p = 0;
+
+ infoLoaded = true;
+}
+
+TCHAR *nb_stristr(TCHAR *str, TCHAR *substr)
+{
+ if (!substr || !*substr) return str;
+ if (!str || !*str) return NULL;
+
+ TCHAR *str_up = NEWTSTR_ALLOCA(str);
+ TCHAR *substr_up = NEWTSTR_ALLOCA(substr);
+
+ CharUpperBuff(str_up, lstrlen(str_up));
+ CharUpperBuff(substr_up, lstrlen(substr_up));
+
+ TCHAR* p = _tcsstr(str_up, substr_up);
+ return p ? (str + (p - str_up)) : NULL;
+}
+
+bool CContactCache::filter(int rate, TCHAR *str)
+{
+ if (!str || !*str)
+ return true;
+ m_cache[rate].LoadInfo();
+
+ HKL kbdLayoutActive = GetKeyboardLayout(GetCurrentThreadId());
+ HKL kbdLayouts[10];
+ int nKbdLayouts = GetKeyboardLayoutList(SIZEOF(kbdLayouts), kbdLayouts);
+
+ TCHAR buf[256];
+ BYTE keyState[256] = {0};
+
+ for (int iLayout = 0; iLayout < nKbdLayouts; ++iLayout)
+ {
+ if (kbdLayoutActive == kbdLayouts[iLayout])
+ {
+ lstrcpy(buf, str);
+ } else
+ {
+ int i;
+ for (i = 0; str[i]; ++i)
+ {
+ UINT vk = VkKeyScanEx(str[i], kbdLayoutActive);
+ UINT scan = MapVirtualKeyEx(vk, 0, kbdLayoutActive);
+ ToUnicodeEx(vk, scan, keyState, buf+i, SIZEOF(buf)-i, 0, kbdLayouts[iLayout]);
+ }
+ buf[i] = 0;
+ }
+
+ for (TCHAR *p = m_cache[rate].info; p && *p; p = p + lstrlen(p) + 1)
+ if (nb_stristr(p, buf))
+ return true;
+ }
+
+ return false;
+}
diff --git a/plugins/FavContacts/src/contact_cache.h b/plugins/FavContacts/src/contact_cache.h
new file mode 100644
index 0000000000..905ba4b469
--- /dev/null
+++ b/plugins/FavContacts/src/contact_cache.h
@@ -0,0 +1,61 @@
+#ifndef __contact_cache__
+#define __contact_cache__
+
+class CContactCache
+{
+public:
+ enum { INFOSIZE = 1024 };
+
+private:
+
+ struct TContactInfo
+ {
+ HANDLE hContact;
+ float rate;
+ TCHAR info[INFOSIZE];
+ bool infoLoaded;
+
+ static int cmp(const TContactInfo *p1, const TContactInfo *p2)
+ {
+ if (p1->rate > p2->rate) return -1;
+ if (p1->rate < p2->rate) return 1;
+ return 0;
+ }
+
+ static int cmp2(const void *a1, const void *a2)
+ {
+ return cmp(*(const TContactInfo **)a1, *(const TContactInfo **)a2);
+ }
+
+ TContactInfo()
+ {
+ info[0] = info[1] = 0;
+ infoLoaded = false;
+ }
+
+ void LoadInfo();
+ };
+
+ OBJLIST<TContactInfo> m_cache;
+ unsigned long m_lastUpdate;
+ CRITICAL_SECTION m_cs;
+ HANDLE m_hOnDbEventAdded;
+
+ int __cdecl OnDbEventAdded(WPARAM wParam, LPARAM lParam);
+ float GetEventWeight(unsigned long age);
+ float GetTimeWeight(unsigned long age);
+
+public:
+ CContactCache();
+ ~CContactCache();
+
+ void Lock() { EnterCriticalSection(&m_cs); }
+ void Unlock() { LeaveCriticalSection(&m_cs); }
+ void Rebuild();
+
+ HANDLE get(int rate);
+ float getWeight(int rate);
+ bool filter(int rate, TCHAR *str);
+};
+
+#endif // __contact_cache__
diff --git a/plugins/FavContacts/src/cserver.cpp b/plugins/FavContacts/src/cserver.cpp
new file mode 100644
index 0000000000..957d1a6048
--- /dev/null
+++ b/plugins/FavContacts/src/cserver.cpp
@@ -0,0 +1,82 @@
+#include <winsock2.h>
+#include <windows.h>
+#include <ws2tcpip.h>
+
+#include "csocket.h"
+#include "cserver.h"
+
+void CServer::Start(int port, IConnectionProcessorFactory *connectionProcessorFactory, bool background)
+{
+ m_socket = socket(AF_INET, SOCK_STREAM, 0);
+ if (m_socket == INVALID_SOCKET) return;
+
+ sockaddr_in addr = {0};
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr.sin_port = htons((WORD)port);
+ if (bind(m_socket, (sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
+ {
+ closesocket(m_socket);
+ m_socket = INVALID_SOCKET;
+ return;
+ }
+
+ listen(m_socket, SOMAXCONN);
+
+ m_connectionProcessorFactory = connectionProcessorFactory;
+
+ if (background)
+ {
+ CreateThread(NULL, 0,
+ GlobalConnectionAcceptThread,
+ this,
+ 0, NULL);
+ } else
+ {
+ ConnectionAcceptThread();
+ }
+}
+
+void CServer::Stop()
+{
+ shutdown(m_socket, SD_BOTH);
+ closesocket(m_socket);
+}
+
+DWORD CServer::ConnectionAcceptThread()
+{
+ while (1)
+ {
+ SOCKET s = accept(m_socket, NULL, NULL);
+ if (s == INVALID_SOCKET) break;
+
+ CreateThread(NULL, 0,
+ GlobalConnectionProcessThread,
+ new GlobalConnectionProcessThreadArgs(this, s),
+ 0, NULL);
+ }
+ return 0;
+}
+
+DWORD CServer::ConnectionProcessThread(SOCKET s)
+{
+ CSocket sock(s);
+ IConnectionProcessor *processor = m_connectionProcessorFactory->Create(&sock);
+ processor->ProcessConnection();
+ delete processor;
+ return 0;
+}
+
+DWORD WINAPI CServer::GlobalConnectionAcceptThread(void *arg)
+{
+ CServer *server = (CServer *)arg;
+ return server->ConnectionAcceptThread();
+}
+
+DWORD WINAPI CServer::GlobalConnectionProcessThread(void *arg)
+{
+ GlobalConnectionProcessThreadArgs *args = (GlobalConnectionProcessThreadArgs *)arg;
+ DWORD result = args->m_server->ConnectionProcessThread(args->m_socket);
+ delete args;
+ return result;
+}
diff --git a/plugins/FavContacts/src/cserver.h b/plugins/FavContacts/src/cserver.h
new file mode 100644
index 0000000000..007a341896
--- /dev/null
+++ b/plugins/FavContacts/src/cserver.h
@@ -0,0 +1,42 @@
+#ifndef cserver_h__
+#define cserver_h__
+
+class IConnectionProcessor
+{
+public:
+ virtual ~IConnectionProcessor() {}
+ virtual void ProcessConnection() = 0;
+};
+
+class IConnectionProcessorFactory
+{
+public:
+ virtual IConnectionProcessor *Create(CSocket *s) = 0;
+};
+
+class CServer
+{
+private:
+ SOCKET m_socket;
+ IConnectionProcessorFactory *m_connectionProcessorFactory;
+
+ DWORD ConnectionAcceptThread();
+ DWORD ConnectionProcessThread(SOCKET s);
+
+ static DWORD WINAPI GlobalConnectionAcceptThread(void *arg);
+
+ struct GlobalConnectionProcessThreadArgs
+ {
+ CServer *m_server;
+ SOCKET m_socket;
+
+ GlobalConnectionProcessThreadArgs(CServer *server, SOCKET s): m_server(server), m_socket(s) {}
+ };
+ static DWORD WINAPI GlobalConnectionProcessThread(void *arg);
+
+public:
+ void Start(int port, IConnectionProcessorFactory *connectionProcessorFactory, bool background);
+ void Stop();
+};
+
+#endif // cserver_h__
diff --git a/plugins/FavContacts/src/csocket.cpp b/plugins/FavContacts/src/csocket.cpp
new file mode 100644
index 0000000000..dfff16fbf1
--- /dev/null
+++ b/plugins/FavContacts/src/csocket.cpp
@@ -0,0 +1,22 @@
+#include <winsock2.h>
+#include <windows.h>
+#include <ws2tcpip.h>
+
+#include "csocket.h"
+
+int CSocket::Recv(char *buf, int count)
+{
+ return recv(m_socket, buf, count, 0);
+}
+
+int CSocket::Send(char *buf, int count)
+{
+ if (count < 0) count = strlen(buf);
+ return send(m_socket, buf, count, 0);
+}
+
+void CSocket::Close()
+{
+ shutdown(m_socket, SD_BOTH);
+ closesocket(m_socket);
+}
diff --git a/plugins/FavContacts/src/csocket.h b/plugins/FavContacts/src/csocket.h
new file mode 100644
index 0000000000..3fa1c87852
--- /dev/null
+++ b/plugins/FavContacts/src/csocket.h
@@ -0,0 +1,16 @@
+#ifndef csocket_h__
+#define csocket_h__
+
+class CSocket
+{
+protected:
+ SOCKET m_socket;
+
+public:
+ CSocket(SOCKET socket = INVALID_SOCKET): m_socket(socket) {}
+ int Recv(char *buf, int count);
+ int Send(char *buf, int count = -1);
+ void Close();
+};
+
+#endif // csocket_h__
diff --git a/plugins/FavContacts/src/favlist.cpp b/plugins/FavContacts/src/favlist.cpp
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/plugins/FavContacts/src/favlist.cpp
diff --git a/plugins/FavContacts/src/favlist.h b/plugins/FavContacts/src/favlist.h
new file mode 100644
index 0000000000..6201126b44
--- /dev/null
+++ b/plugins/FavContacts/src/favlist.h
@@ -0,0 +1,134 @@
+#ifndef favlist_h__
+#define favlist_h__
+
+struct TContactInfo
+{
+private:
+ HANDLE hContact;
+ DWORD status;
+ TCHAR *name;
+ TCHAR *group;
+ bool bManual;
+ float fRate;
+
+public:
+ TContactInfo(HANDLE hContact, bool bManual, float fRate = 0)
+ {
+ DBVARIANT dbv = {0};
+
+ this->hContact = hContact;
+ this->bManual = bManual;
+ this->fRate = fRate;
+ name = mir_tstrdup((TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR));
+ if (g_Options.bUseGroups && !DBGetContactSettingTString(hContact, "CList", "Group", &dbv))
+ {
+ group = mir_tstrdup(dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else
+ if (g_Options.bUseGroups)
+ {
+ group = mir_tstrdup(TranslateT("<no group>"));
+ } else
+ {
+ group = mir_tstrdup(TranslateT("Favourite Contacts"));
+ }
+ status = DBGetContactSettingWord(hContact, (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0), "Status", ID_STATUS_OFFLINE);
+ }
+
+ ~TContactInfo()
+ {
+ mir_free(name);
+ mir_free(group);
+ }
+
+ HANDLE getHandle() const
+ {
+ return hContact;
+ }
+
+ TCHAR *getGroup() const
+ {
+ return group;
+ }
+
+ static int cmp(const TContactInfo *p1, const TContactInfo *p2)
+ {
+ if (p1->bManual && !p2->bManual) return -1;
+ if (!p1->bManual && p2->bManual) return 1;
+
+ if (!p1->bManual)
+ {
+ if (p1->fRate > p2->fRate) return -1;
+ if (p1->fRate < p2->fRate) return 1;
+ }
+
+ int res = 0;
+ if (res = lstrcmp(p1->group, p2->group)) return res;
+ //if (p1->status < p2->status) return -1;
+ //if (p1->status < p2->status) return +1;
+ if (res = lstrcmp(p1->name, p2->name)) return res;
+ return 0;
+ }
+};
+
+class TFavContacts: public LIST<TContactInfo>
+{
+private:
+ int nGroups;
+
+public:
+ TFavContacts(): LIST<TContactInfo>(5, TContactInfo::cmp) {}
+ ~TFavContacts()
+ {
+ for (int i = 0; i < this->getCount(); ++i)
+ delete (*this)[i];
+ }
+
+ int groupCount()
+ {
+ return nGroups;
+ }
+
+ TContactInfo *addContact(HANDLE hContact, bool bManual)
+ {
+ TContactInfo *info = new TContactInfo(hContact, bManual);
+ this->insert(info);
+ return info;
+ }
+
+ void build()
+ {
+ TCHAR *prevGroup = NULL;
+ int i;
+
+ nGroups = 1;
+
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ for ( ; hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0))
+ if (DBGetContactSettingByte(hContact, "FavContacts", "IsFavourite", 0))
+ {
+ TCHAR *group = addContact(hContact, true)->getGroup();
+ if (prevGroup && lstrcmp(prevGroup, group))
+ ++nGroups;
+ prevGroup = group;
+ }
+
+ int nRecent = 0;
+ for (i = 0; nRecent < g_Options.wMaxRecent; ++i)
+ {
+ hContact = g_contactCache->get(i);
+ if (!hContact) break;
+ if (!DBGetContactSettingByte(hContact, "FavContacts", "IsFavourite", 0))
+ {
+ TCHAR *group = addContact(hContact, false)->getGroup();
+ if (prevGroup && lstrcmp(prevGroup, group))
+ ++nGroups;
+ prevGroup = group;
+
+ ++nRecent;
+ }
+ }
+ }
+};
+
+#endif // favlist_h__
diff --git a/plugins/FavContacts/src/headers.h b/plugins/FavContacts/src/headers.h
new file mode 100644
index 0000000000..8863317199
--- /dev/null
+++ b/plugins/FavContacts/src/headers.h
@@ -0,0 +1,94 @@
+/*
+Favourite Contacts for Miranda IM
+
+Copyright 2007 Victor Pavlychko
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#define _CRT_SECURE_NO_DEPRECATE
+
+#if defined(UNICODE) && !defined(_UNICODE)
+ #define _UNICODE
+#endif
+
+#include <tchar.h>
+#define _WIN32_WINNT 0x0501
+#include <windows.h>
+#include <commctrl.h>
+#include <stdio.h>
+#include <malloc.h>
+
+#define MIRANDA_VER 0x800
+#include <win2k.h>
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_system_cpp.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_button.h>
+#include <m_clist.h>
+#include <m_clc.h>
+#include <m_clui.h>
+#include <m_options.h>
+#include <m_protosvc.h>
+#include <m_utils.h>
+#include <m_skin.h>
+#include <m_contacts.h>
+#include <m_userinfo.h>
+#include <m_history.h>
+#include <m_addcontact.h>
+#include <m_message.h>
+#include <m_file.h>
+#include <m_icolib.h>
+#include <m_idle.h>
+#include <m_awaymsg.h>
+#include <m_avatars.h>
+#include <m_toolbar.h>
+#include <m_fontservice.h>
+#include <m_hotkeys.h>
+
+#include "../resource.h"
+
+#define NEWTSTR_ALLOCA(A) (A==NULL)?NULL:_tcscpy((TCHAR*)alloca(sizeof(TCHAR)*(_tcslen(A)+1)),A)
+
+struct Options
+{
+ BYTE bSecondLine;
+ BYTE bAvatars;
+ BYTE bAvatarBorder;
+ WORD wAvatarRadius;
+ BYTE bNoTransparentBorder;
+ BYTE bSysColors;
+ BYTE bCenterHotkey;
+ BYTE bUseGroups;
+ BYTE bUseColumns;
+ BYTE bRightAvatars;
+ BYTE bDimIdle;
+ WORD wMaxRecent;
+
+ COLORREF clLine1, clLine2, clBack;
+ COLORREF clLine1Sel, clLine2Sel, clBackSel;
+ HFONT hfntName, hfntSecond;
+};
+
+
+#include "contact_cache.h"
+
+extern Options g_Options;
+extern CContactCache *g_contactCache;
+
+#include "favlist.h"
+#include "http_api.h"
diff --git a/plugins/FavContacts/src/http_api.cpp b/plugins/FavContacts/src/http_api.cpp
new file mode 100644
index 0000000000..147cabdd7d
--- /dev/null
+++ b/plugins/FavContacts/src/http_api.cpp
@@ -0,0 +1,165 @@
+#include "headers.h"
+
+#pragma comment(lib,"ws2_32.lib")
+
+#include "csocket.h"
+#include "cserver.h"
+
+#define MS_FAVCONTACTS_OPEN_CONTACT "FavContacts/OpenContact"
+
+class CHttpProcessor: public IConnectionProcessor
+{
+private:
+ CSocket *m_socket;
+
+ char *FetchURL(char *s)
+ {
+ char *p;
+ if (p = strstr(s, "\r\n")) *p = 0;
+ if (p = strrchr(s, ' ')) *p = 0;
+ if (p = strchr(s, ' ')) while (*p && *p == ' ') p++;
+ return mir_strdup(p);
+ }
+
+public:
+ CHttpProcessor(CSocket *s): m_socket(s) {}
+
+ void ProcessConnection()
+ {
+ char buf[1024];
+ int n = m_socket->Recv(buf, sizeof(buf));
+ buf[n] = 0;
+
+ char *s = FetchURL(buf);
+
+ if (!strncmp(s, "/fav/list/", 10))
+ {
+ SendList();
+ } else
+ if (!strncmp(s, "/fav/open/", 10))
+ {
+ OpenContact(s);
+ }
+
+ mir_free(s);
+ m_socket->Close();
+ }
+
+ void OpenContact(char *s)
+ {
+ m_socket->Send("HTTP 200 OK\r\n\r\n");
+
+ int hContact;
+ sscanf(s, "/fav/open/%d", &hContact);
+ if (CallService(MS_DB_CONTACT_IS, hContact, 0))
+ CallServiceSync(MS_FAVCONTACTS_OPEN_CONTACT, (WPARAM)hContact, 0);
+ }
+
+ void SendList()
+ {
+ TFavContacts favList;
+ favList.build();
+
+ m_socket->Send(
+ "HTTP 200 OK\r\n"
+ "Content-Type: text/javascript\r\n"
+ "\r\n");
+
+ Send("try {\r\n");
+ Send("SetContactCount(");
+ Send(favList.getCount());
+ Send(");\r\n");
+
+ for (int i = 0; i < favList.getCount(); ++i)
+ {
+ HANDLE hContact = favList[i]->getHandle();
+ TCHAR *name = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR);
+ AVATARCACHEENTRY *avatar = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)hContact, 0);
+ int status = DBGetContactSettingWord(hContact, (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0), "Status", ID_STATUS_OFFLINE);
+
+ Send("SetContact(");
+ Send(i);
+ Send(", ");
+ Send((int)hContact);
+ Send(", '");
+ SendQuoted(name);
+ Send("', ");
+ Send(status);
+ Send(", '");
+ SendQuoted(avatar ? avatar->szFilename : "");
+ Send("');\r\n");
+ }
+ Send("} catch(e) {}\r\n");
+ }
+
+ void Send(char *s)
+ {
+ m_socket->Send(s);
+ }
+
+#ifdef UNICODE
+ void Send(WCHAR *ws)
+ {
+ char *s = mir_utf8encodeW(ws);
+ m_socket->Send(s);
+ mir_free(s);
+ }
+#endif
+
+ void Send(int i)
+ {
+ char buf[32];
+ wsprintfA(buf, "%d", i);
+ Send(buf);
+ }
+
+ template<class XCHAR>
+ void SendQuoted(const XCHAR *s)
+ {
+ int length = 0;
+ const XCHAR *p;
+ for (p = s; *p; p++)
+ {
+ if (*p == '\'' || *p == '\\' || *p == '\"')
+ length++;
+ length++;
+ }
+ XCHAR *buf = (XCHAR *)mir_alloc(sizeof(XCHAR) * (length + 1));
+ XCHAR *q = buf;
+ for (p = s; *p; p++)
+ {
+ if (*p == '\'' || *p == '\\' || *p == '\"')
+ {
+ *q = '\\';
+ q++;
+ }
+ *q = *p;
+ q++;
+ }
+ *q = 0;
+ Send(buf);
+ mir_free(buf);
+ }
+};
+
+class CHttpProcessorFactory: public IConnectionProcessorFactory
+{
+public:
+ IConnectionProcessor *Create(CSocket *s)
+ {
+ return new CHttpProcessor(s);
+ }
+};
+
+static CHttpProcessorFactory g_httpProcessorFactory;
+static CServer g_httpServer;
+
+void LoadHttpApi()
+{
+ g_httpServer.Start(60888, &g_httpProcessorFactory, true);
+}
+
+void UnloadHttpApi()
+{
+ g_httpServer.Stop();
+}
diff --git a/plugins/FavContacts/src/http_api.h b/plugins/FavContacts/src/http_api.h
new file mode 100644
index 0000000000..cccb7ea13b
--- /dev/null
+++ b/plugins/FavContacts/src/http_api.h
@@ -0,0 +1,7 @@
+#ifndef http_api_h__
+#define http_api_h__
+
+void LoadHttpApi();
+void UnloadHttpApi();
+
+#endif // http_api_h__
diff --git a/plugins/FavContacts/src/main.cpp b/plugins/FavContacts/src/main.cpp
new file mode 100644
index 0000000000..5e5a1f1f9a
--- /dev/null
+++ b/plugins/FavContacts/src/main.cpp
@@ -0,0 +1,1453 @@
+/*
+Favourite Contacts for Miranda IM
+
+Copyright 2007 Victor Pavlychko
+
+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 "headers.h"
+
+DWORD g_mirandaVersion;
+PLUGINLINK* pluginLink = NULL;
+HINSTANCE g_hInst;
+
+struct LIST_INTERFACE li;
+struct MM_INTERFACE mmi;
+struct UTF8_INTERFACE utfi;
+
+// {AC8B66B3-AFE1-4475-BABA-49783BA39A66}
+#define MIID_FAVCONTACTS { 0xac8b66b3, 0xafe1, 0x4475, { 0xba, 0xba, 0x49, 0x78, 0x3b, 0xa3, 0x9a, 0x66 } }
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ "Favourite Contacts",
+ PLUGIN_MAKE_VERSION(0, 0, 0, 6),
+ "Favourite contacts menu",
+ "code by Victor Pavlychko, icons by Angeli-Ka",
+ "nullbie@gmail.com",
+ "Copyright 2007-2009 Victor Pavlychko",
+ "http://nullbie.miranda.im/",
+ UNICODE_AWARE,
+ 0, // replace internal version (if any)
+#ifdef _UNICODE
+ // {CE2C0401-F9E0-40d7-8E95-1A4197D7AB04}
+ { 0xce2c0401, 0xf9e0, 0x40d7, { 0x8e, 0x95, 0x1a, 0x41, 0x97, 0xd7, 0xab, 0x4 } }
+#else
+ // {DE1D765C-9DC2-4679-8633-EDAD492C8479}
+ { 0xde1d765c, 0x9dc2, 0x4679, { 0x86, 0x33, 0xed, 0xad, 0x49, 0x2c, 0x84, 0x79 } }
+#endif
+};
+
+#define MS_FAVCONTACTS_SHOWMENU "FavContacts/ShowMenu"
+#define MS_FAVCONTACTS_SHOWMENU_CENTERED "FavContacts/ShowMenuCentered"
+#define MS_FAVCONTACTS_OPEN_CONTACT "FavContacts/OpenContact"
+
+HWND g_hwndMenuHost = NULL;
+static LRESULT CALLBACK MenuHostWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+static BOOL CALLBACK OptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+static void sttLoadOptions();
+static void sttSaveOptions();
+
+int sttShowMenu(bool centered);
+
+INT_PTR svcOpenContact(WPARAM wParam, LPARAM lParam);
+
+INT_PTR svcShowMenu(WPARAM wParam, LPARAM lParam);
+INT_PTR svcShowMenuCentered(WPARAM wParam, LPARAM lParam);
+int ProcessSrmmEvent(WPARAM wParam, LPARAM lParam);
+int ProcessSrmmIconClick(WPARAM wParam, LPARAM lParam);
+
+int g_icoFavourite=0, g_icoRegular=0;
+float g_widthMultiplier = 0;
+int g_maxItemWidth = 0;
+
+CContactCache *g_contactCache = NULL;
+TCHAR g_filter[1024] = {0};
+
+Options g_Options = {0};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ g_hInst = hinstDLL;
+ return TRUE;
+}
+
+bool CoreCheck()
+{
+ char version[1024], exepath[1024];
+ GetModuleFileNameA(GetModuleHandle(NULL), exepath, sizeof(exepath));
+ CallService(MS_SYSTEM_GETVERSIONTEXT, sizeof(version), (LPARAM)version);
+ _strlwr(exepath); _strlwr(version);
+ if (!strstr(strrchr(exepath, '\\'), "miranda") ||
+ strstr(version, "coffee") ||
+ (*version && (!strncmp(version, "1.", 2) || strstr(version, " 1."))) ||
+ (g_mirandaVersion >= PLUGIN_MAKE_VERSION(1,0,0,0)))
+ {
+ MessageBoxA(0,
+ Translate(
+ "Favourite Contacts plugin was designed to be used with Miranda IM only.\n"
+ "For use with any other application, please contact author.\n"
+ ),
+ "Favourite Contacts Error",
+ MB_ICONSTOP|MB_OK);
+ return false;
+ }
+ return true;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ g_mirandaVersion = mirandaVersion;
+ return &pluginInfo;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfo(DWORD mirandaVersion)
+{
+ g_mirandaVersion = mirandaVersion;
+ return &pluginInfo;
+}
+
+extern "C" __declspec(dllexport) const MUUID *MirandaPluginInterfaces(void)
+{
+ static const MUUID interfaces[] = { MIID_FAVCONTACTS, MIID_LAST };
+ return interfaces;
+}
+
+static __forceinline COLORREF sttShadeColor(COLORREF clLine1, COLORREF clBack)
+{
+ return RGB(
+ (GetRValue(clLine1) * 66UL + GetRValue(clBack) * 34UL) / 100,
+ (GetGValue(clLine1) * 66UL + GetGValue(clBack) * 34UL) / 100,
+ (GetBValue(clLine1) * 66UL + GetBValue(clBack) * 34UL) / 100
+ );
+}
+
+HANDLE hhkProcessTBLoaded = NULL;
+int ProcessTBLoaded(WPARAM wParam, LPARAM lParam)
+{
+ TBButton button = {0};
+ button.cbSize = sizeof(button);
+ button.pszButtonID = "FavContacts/ShowMenu";
+ button.pszTooltipUp = button.pszTooltipUp =
+ button.pszButtonName = "Favourite Contacts";
+ button.pszServiceName = MS_FAVCONTACTS_SHOWMENU;
+ button.defPos = 200;
+ button.tbbFlags = TBBF_SHOWTOOLTIP|TBBF_VISIBLE;
+ button.hSecondaryIconHandle = button.hPrimaryIconHandle = (HANDLE)g_icoFavourite;
+ CallService(MS_TB_ADDBUTTON, 0, (LPARAM)&button);
+
+ return 0;
+}
+
+int ProcessReloadFonts(WPARAM wParam, LPARAM lParam)
+{
+ if (g_Options.hfntName) DeleteObject(g_Options.hfntName);
+ if (g_Options.hfntSecond) DeleteObject(g_Options.hfntSecond);
+
+ LOGFONT lf = {0};
+ FontIDT fontid = {0};
+ fontid.cbSize = sizeof(fontid);
+ lstrcpy(fontid.group, _T("Favourite Contacts"));
+
+ lstrcpy(fontid.name, _T("Contact name"));
+ g_Options.clLine1 = CallService(MS_FONT_GETT, (WPARAM)&fontid, (LPARAM)&lf);
+ g_Options.hfntName = CreateFontIndirect(&lf);
+
+ lstrcpy(fontid.name, _T("Second line"));
+ g_Options.clLine2 = CallService(MS_FONT_GETT, (WPARAM)&fontid, (LPARAM)&lf);
+ g_Options.hfntSecond = CreateFontIndirect(&lf);
+
+ lstrcpy(fontid.name, _T("Selected contact name (color)"));
+ g_Options.clLine1Sel = CallService(MS_FONT_GETT, (WPARAM)&fontid, (LPARAM)&lf);
+
+ lstrcpy(fontid.name, _T("Selected second line (color)"));
+ g_Options.clLine2Sel = CallService(MS_FONT_GETT, (WPARAM)&fontid, (LPARAM)&lf);
+
+ ColourIDT colourid = {0};
+ colourid.cbSize = sizeof(colourid);
+ lstrcpy(colourid.group, _T("Favourite Contacts"));
+
+ lstrcpy(colourid.name, _T("Background"));
+ g_Options.clBack = CallService(MS_COLOUR_GETT, (WPARAM)&colourid, (LPARAM)&lf);
+
+ lstrcpy(colourid.name, _T("Selected background"));
+ g_Options.clBackSel = CallService(MS_COLOUR_GETT, (WPARAM)&colourid, (LPARAM)&lf);
+
+ return 0;
+}
+
+int ProcessModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ if (ServiceExists(MS_MSG_ADDICON))
+ {
+ StatusIconData sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.szModule = "FavContacts";
+ sid.szTooltip = Translate("Favourite Contacts");
+ sid.hIcon = (HICON)CallService(MS_SKIN2_GETICONBYHANDLE, 0, g_icoFavourite);
+ sid.hIconDisabled = (HICON)CallService(MS_SKIN2_GETICONBYHANDLE, 0, g_icoRegular);
+ CallService(MS_MSG_ADDICON, 0, (LPARAM)&sid);
+
+ HookEvent(ME_MSG_ICONPRESSED, ProcessSrmmIconClick);
+ HookEvent(ME_MSG_WINDOWEVENT, ProcessSrmmEvent);
+ }
+
+ if (true /* ServiceExists(MS_FONT_REGISTERT) */)
+ {
+ //LOGFONT lf;
+ //GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf);
+
+ FontIDT fontid = {0};
+ fontid.cbSize = sizeof(fontid);
+ lstrcpy(fontid.group, _T("Favourite Contacts"));
+ lstrcpyA(fontid.dbSettingsGroup, "FavContacts");
+ lstrcpy(fontid.backgroundGroup, _T("Favourite Contacts"));
+ fontid.flags = FIDF_DEFAULTVALID;
+ fontid.deffontsettings.charset = DEFAULT_CHARSET;
+ fontid.deffontsettings.size = -11;
+ lstrcpy(fontid.deffontsettings.szFace, _T("MS Shell Dlg"));
+ fontid.deffontsettings.style = 0;
+
+ lstrcpy(fontid.backgroundName, _T("Background"));
+
+ lstrcpy(fontid.name, _T("Contact name"));
+ lstrcpyA(fontid.prefix, "fntName");
+ fontid.deffontsettings.colour = GetSysColor(COLOR_MENUTEXT);
+ fontid.deffontsettings.style = DBFONTF_BOLD;
+ CallService(MS_FONT_REGISTERT, (WPARAM)&fontid, 0);
+
+ lstrcpy(fontid.name, _T("Second line"));
+ lstrcpyA(fontid.prefix, "fntSecond");
+ fontid.deffontsettings.colour = sttShadeColor(GetSysColor(COLOR_MENUTEXT), GetSysColor(COLOR_MENU));
+ fontid.deffontsettings.style = 0;
+ CallService(MS_FONT_REGISTERT, (WPARAM)&fontid, 0);
+
+ lstrcpy(fontid.backgroundName, _T("Selected background"));
+
+ lstrcpy(fontid.name, _T("Selected contact name (color)"));
+ lstrcpyA(fontid.prefix, "fntNameSel");
+ fontid.deffontsettings.colour = GetSysColor(COLOR_HIGHLIGHTTEXT);
+ fontid.deffontsettings.style = DBFONTF_BOLD;
+ CallService(MS_FONT_REGISTERT, (WPARAM)&fontid, 0);
+
+ lstrcpy(fontid.name, _T("Selected second line (color)"));
+ lstrcpyA(fontid.prefix, "fntSecondSel");
+ fontid.deffontsettings.colour = sttShadeColor(GetSysColor(COLOR_HIGHLIGHTTEXT), GetSysColor(COLOR_HIGHLIGHT));
+ fontid.deffontsettings.style = 0;
+ CallService(MS_FONT_REGISTERT, (WPARAM)&fontid, 0);
+
+ ColourIDT colourid = {0};
+ colourid.cbSize = sizeof(colourid);
+ lstrcpy(colourid.group, _T("Favourite Contacts"));
+ lstrcpyA(colourid.dbSettingsGroup, "FavContacts");
+
+ lstrcpy(colourid.name, _T("Background"));
+ lstrcpyA(colourid.setting, "BackColour");
+ colourid.defcolour = GetSysColor(COLOR_MENU);
+ CallService(MS_COLOUR_REGISTERT, (WPARAM)&colourid, 0);
+
+ lstrcpy(colourid.name, _T("Selected background"));
+ lstrcpyA(colourid.setting, "SelectedColour");
+ colourid.defcolour = GetSysColor(COLOR_HIGHLIGHT);
+ CallService(MS_COLOUR_REGISTERT, (WPARAM)&colourid, 0);
+
+ HookEvent(ME_FONT_RELOAD, ProcessReloadFonts);
+ HookEvent(ME_COLOUR_RELOAD, ProcessReloadFonts);
+ ProcessReloadFonts(0, 0);
+ }
+
+ if (ServiceExists(MS_HOTKEY_REGISTER))
+ {
+ HOTKEYDESC hotkey = {0};
+ hotkey.cbSize = sizeof(hotkey);
+ hotkey.pszName = "FavContacts/ShowMenu";
+ hotkey.pszDescription = "Show favourite contacts";
+ hotkey.pszSection = "Contacts";
+ hotkey.pszService = MS_FAVCONTACTS_SHOWMENU_CENTERED;
+ hotkey.DefHotKey = MAKEWORD('Q', HOTKEYF_EXT);
+ CallService(MS_HOTKEY_REGISTER, 0, (LPARAM)&hotkey);
+ }
+
+ if (ServiceExists(MS_AV_GETAVATARBITMAP))
+ {
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ for ( ; hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0))
+ if (DBGetContactSettingByte(hContact, "FavContacts", "IsFavourite", 0))
+ CallService(MS_AV_GETAVATARBITMAP, (WPARAM)hContact, 0);
+ }
+
+ if (!hhkProcessTBLoaded) hhkProcessTBLoaded = HookEvent(ME_TB_MODULELOADED, ProcessTBLoaded);
+
+ return 0;
+}
+
+int ProcessOptInitialise(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+ odp.cbSize = sizeof(odp);
+ odp.position = 100000000;
+ odp.hInstance = g_hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS);
+ odp.ptszGroup = TranslateT("Contact List");
+ odp.ptszTitle = TranslateT("Favourites");
+ odp.groupPosition = 910000000;
+ odp.flags = ODPF_BOLDGROUPS|ODPF_TCHAR;
+ odp.pfnDlgProc = OptionsDlgProc;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp);
+ return 0;
+}
+
+extern "C" __declspec(dllexport) int Load(PLUGINLINK * link)
+{
+ pluginLink = link;
+
+ if (!CoreCheck()) return 1;
+
+ mir_getLI(&li);
+ mir_getMMI(&mmi);
+ mir_getUTFI(&utfi);
+
+ g_contactCache = new CContactCache;
+
+ WNDCLASSEX wcl = {0};
+ wcl.cbSize = sizeof(wcl);
+ wcl.lpfnWndProc = MenuHostWndProc;
+ wcl.style = 0;
+ wcl.cbClsExtra = 0;
+ wcl.cbWndExtra = 0;
+ wcl.hInstance = g_hInst;
+ wcl.hIcon = NULL;
+ wcl.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wcl.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
+ wcl.lpszMenuName = NULL;
+ wcl.lpszClassName = _T("FavContactsMenuHostWnd");
+ wcl.hIconSm = NULL;
+ RegisterClassEx(&wcl);
+
+ g_hwndMenuHost = CreateWindow(_T("FavContactsMenuHostWnd"), NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, g_hInst, NULL);
+ SetWindowPos(g_hwndMenuHost, 0, 0, 0, 0, 0, SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_HIDEWINDOW);
+
+ sttLoadOptions();
+
+ CreateServiceFunction(MS_FAVCONTACTS_SHOWMENU, svcShowMenu);
+ CreateServiceFunction(MS_FAVCONTACTS_SHOWMENU_CENTERED, svcShowMenuCentered);
+ CreateServiceFunction(MS_FAVCONTACTS_OPEN_CONTACT, svcOpenContact);
+
+ HookEvent(ME_OPT_INITIALISE, ProcessOptInitialise);
+ HookEvent(ME_SYSTEM_MODULESLOADED, ProcessModulesLoaded);
+ hhkProcessTBLoaded = HookEvent(ME_TB_MODULELOADED, ProcessTBLoaded);
+
+ if (true /*ServiceExists(MS_SKIN2_ADDICON)*/)
+ {
+ TCHAR buf[MAX_PATH];
+ GetModuleFileName(g_hInst, buf, SIZEOF(buf));
+
+ SKINICONDESC sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.ptszSection = _T("Favourites");
+ sid.ptszDefaultFile = buf;
+ sid.cx = sid.cy = 16;
+ sid.flags = SIDF_ALL_TCHAR;
+
+ sid.pszName = "favcontacts_favourite";
+ sid.ptszDescription = _T("Favourite Contact");
+ sid.iDefaultIndex = -IDI_FAVOURITE;
+ g_icoFavourite = CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszName = "favcontacts_regular";
+ sid.ptszDescription = _T("Regular Contact");
+ sid.iDefaultIndex = -IDI_REGULAR;
+ g_icoRegular = CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+ }
+
+ LoadHttpApi();
+
+#ifdef _DEBUG
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_OPTIONS);
+ mi.position = 1900000000;
+ mi.pszName = LPGEN("&Favourite Contacts...");
+ mi.pszService = MS_FAVCONTACTS_SHOWMENU;
+ CallService( MS_CLIST_ADDMAINMENUITEM, 0, ( LPARAM )&mi );
+#endif
+
+ return 0;
+}
+
+extern "C" __declspec(dllexport) int Unload(void)
+{
+ UnloadHttpApi();
+ if (g_hwndMenuHost) DestroyWindow(g_hwndMenuHost);
+ if (g_Options.hfntName) DeleteObject(g_Options.hfntName);
+ if (g_Options.hfntSecond) DeleteObject(g_Options.hfntSecond);
+ delete g_contactCache;
+ return 0;
+}
+
+static void sttLoadOptions()
+{
+ g_Options.bSecondLine = DBGetContactSettingByte(NULL, "FavContacts", "SecondLine", 1);
+ g_Options.bAvatars = DBGetContactSettingByte(NULL, "FavContacts", "Avatars", 1);
+ g_Options.bAvatarBorder = DBGetContactSettingByte(NULL, "FavContacts", "AvatarBorder", 0);
+ g_Options.wAvatarRadius = DBGetContactSettingWord(NULL, "FavContacts", "AvatarRadius", 3);
+ g_Options.bNoTransparentBorder = DBGetContactSettingByte(NULL, "FavContacts", "NoTransparentBorder",
+ !DBGetContactSettingByte(NULL, "FavContacts", "AvatarBorderTransparent", 1));
+ g_Options.bSysColors = DBGetContactSettingByte(NULL, "FavContacts", "SysColors", 0);
+ g_Options.bCenterHotkey = DBGetContactSettingByte(NULL, "FavContacts", "CenterHotkey", 1);
+ g_Options.bUseGroups = DBGetContactSettingByte(NULL, "FavContacts", "UseGroups", 0);
+ g_Options.bUseColumns = DBGetContactSettingByte(NULL, "FavContacts", "UseColumns", 1);
+ g_Options.bRightAvatars = DBGetContactSettingByte(NULL, "FavContacts", "RightAvatars", 0);
+ g_Options.bDimIdle = DBGetContactSettingByte(NULL, "FavContacts", "DimIdle", 1);
+
+ g_Options.wMaxRecent = DBGetContactSettingByte(NULL, "FavContacts", "MaxRecent", 10);
+}
+
+static void sttSaveOptions()
+{
+ DBWriteContactSettingByte(NULL, "FavContacts", "SecondLine", g_Options.bSecondLine);
+ DBWriteContactSettingByte(NULL, "FavContacts", "Avatars", g_Options.bAvatars);
+ DBWriteContactSettingByte(NULL, "FavContacts", "AvatarBorder", g_Options.bAvatarBorder);
+ DBWriteContactSettingWord(NULL, "FavContacts", "AvatarRadius", g_Options.wAvatarRadius);
+ DBWriteContactSettingByte(NULL, "FavContacts", "NoTransparentBorder", g_Options.bNoTransparentBorder);
+ DBWriteContactSettingByte(NULL, "FavContacts", "SysColors", g_Options.bSysColors);
+ DBWriteContactSettingByte(NULL, "FavContacts", "CenterHotkey", g_Options.bCenterHotkey);
+ DBWriteContactSettingByte(NULL, "FavContacts", "UseGroups", g_Options.bUseGroups);
+ DBWriteContactSettingByte(NULL, "FavContacts", "UseColumns", g_Options.bUseColumns);
+ DBWriteContactSettingByte(NULL, "FavContacts", "RightAvatars", g_Options.bRightAvatars);
+ DBWriteContactSettingByte(NULL, "FavContacts", "DimIdle", g_Options.bDimIdle);
+ DBWriteContactSettingWord(NULL, "FavContacts", "MaxRecent", g_Options.wMaxRecent);
+}
+
+static bool sttIsGroup(int id)
+{
+ if (id == 1) return true;
+
+ DBVARIANT dbv = {0};
+ char buf[32];
+ wsprintfA(buf, "%d", (int)(id-2));
+ if (!DBGetContactSettingTString(NULL, "CListGroups", buf, &dbv))
+ {
+ DBFreeVariant(&dbv);
+ return true;
+ }
+ return false;
+}
+
+static TCHAR *sttGetGroupName(int id)
+{
+ if (id == 1)
+ {
+ if (g_Options.bUseGroups)
+ return mir_tstrdup(TranslateT("<No group>"));
+ return mir_tstrdup(TranslateT("Favourite Contacts"));
+ }
+
+ DBVARIANT dbv = {0};
+ char buf[32];
+ wsprintfA(buf, "%d", (int)(id-2));
+ if (!DBGetContactSettingTString(NULL, "CListGroups", buf, &dbv))
+ {
+ TCHAR *res = mir_tstrdup(dbv.ptszVal+1);
+ DBFreeVariant(&dbv);
+ return res;
+ }
+ return NULL;
+}
+
+static int sttGetGroupId(TCHAR *name)
+{
+ for (int i = 0; ; ++i)
+ {
+ DBVARIANT dbv = {0};
+ char buf[32];
+ wsprintfA(buf, "%d", (int)i);
+ if (!DBGetContactSettingTString(NULL, "CListGroups", buf, &dbv))
+ {
+ if (!lstrcmp(dbv.ptszVal+1, name))
+ {
+ DBFreeVariant(&dbv);
+ return i+2;
+ }
+
+ DBFreeVariant(&dbv);
+ } else
+ {
+ // default is root
+ return 1;
+ }
+ }
+}
+
+static BOOL sttMeasureItem_Group(LPMEASUREITEMSTRUCT lpmis, Options *options)
+{
+ if (true)
+ {
+ HDC hdc = GetDC(g_hwndMenuHost);
+ HFONT hfntSave = (HFONT)SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
+ TCHAR *name = sttGetGroupName(lpmis->itemData);
+ SIZE sz;
+ if (!options->bSysColors) SelectObject(hdc, g_Options.hfntName);
+ GetTextExtentPoint32(hdc, name, lstrlen(name), &sz);
+ lpmis->itemHeight = sz.cy + 8;
+ lpmis->itemWidth = sz.cx + 10;
+ mir_free(name);
+ SelectObject(hdc, hfntSave);
+ ReleaseDC(g_hwndMenuHost, hdc);
+ }
+
+ return TRUE;
+}
+
+static BOOL sttMeasureItem_Contact(LPMEASUREITEMSTRUCT lpmis, Options *options)
+{
+ HANDLE hContact = (HANDLE)lpmis->itemData;
+
+ lpmis->itemHeight = 4;
+ lpmis->itemWidth = 8+10;
+
+ if (true)
+ {
+ lpmis->itemWidth += 20;
+ }
+
+ if (true)
+ {
+ SIZE sz;
+ int textWidth = 0;
+
+ HDC hdc = GetDC(g_hwndMenuHost);
+ HFONT hfntSave = (HFONT)SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
+
+ if (options->bSecondLine)
+ {
+ DBVARIANT dbv;
+ TCHAR *title;
+ bool bFree = false;
+ if (DBGetContactSettingTString(hContact, "CList", "StatusMsg", &dbv) || !*dbv.ptszVal)
+ {
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ int status = DBGetContactSettingWord(hContact, proto, "Status", ID_STATUS_OFFLINE);
+ title = (TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, status, GSMDF_TCHAR);
+ } else
+ {
+ title = dbv.ptszVal;
+ bFree = true;
+ }
+
+ if (!options->bSysColors) SelectObject(hdc, g_Options.hfntSecond);
+ GetTextExtentPoint32(hdc, title, lstrlen(title), &sz);
+ if (bFree) DBFreeVariant(&dbv);
+ textWidth = sz.cx;
+ lpmis->itemHeight += sz.cy + 3;
+ }
+
+ TCHAR *name = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR);
+
+ if (!options->bSysColors) SelectObject(hdc, g_Options.hfntName);
+ GetTextExtentPoint32(hdc, name, lstrlen(name), &sz);
+ textWidth = max(textWidth, sz.cx);
+
+ SelectObject(hdc, hfntSave);
+ ReleaseDC(g_hwndMenuHost, hdc);
+
+ lpmis->itemWidth += textWidth;
+ lpmis->itemHeight += sz.cy;
+ }
+
+ if (options->bAvatars)
+ {
+ AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)hContact, 0);
+ if (ace && (ace != (AVATARCACHEENTRY *)CALLSERVICE_NOTFOUND))
+ {
+ int avatarWidth = lpmis->itemHeight;
+ if (ace->bmWidth < ace->bmHeight)
+ avatarWidth = lpmis->itemHeight * ace->bmWidth / ace->bmHeight;
+
+ lpmis->itemWidth += avatarWidth + 5;
+ }
+ }
+
+ if (lpmis->itemHeight < 18) lpmis->itemHeight = 18;
+
+ return TRUE;
+}
+
+static BOOL sttMeasureItem(LPMEASUREITEMSTRUCT lpmis, Options *options=NULL)
+{
+ if (!options) options = &g_Options;
+
+ if (!lpmis->itemData)
+ return FALSE;
+
+ BOOL res = FALSE;
+ if (sttIsGroup(lpmis->itemData))
+ res = sttMeasureItem_Group(lpmis, options);
+ else if (CallService(MS_DB_CONTACT_IS, lpmis->itemData, 0))
+ res = sttMeasureItem_Contact(lpmis, options);
+
+ if (res && (lpmis->itemWidth > g_maxItemWidth)) lpmis->itemWidth = g_maxItemWidth;
+ if (res && g_widthMultiplier) lpmis->itemWidth *= g_widthMultiplier;
+
+ return FALSE;
+}
+
+static BOOL sttDrawItem_Group(LPDRAWITEMSTRUCT lpdis, Options *options = NULL)
+{
+ lpdis->rcItem.top++;
+ lpdis->rcItem.bottom--;
+
+ HFONT hfntSave = (HFONT)SelectObject(lpdis->hDC, GetStockObject(DEFAULT_GUI_FONT));
+ SetBkMode(lpdis->hDC, TRANSPARENT);
+ if (options->bSysColors)
+ {
+ FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT));
+ //FrameRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT));
+ SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ } else
+ {
+ HBRUSH hbr;
+ hbr = CreateSolidBrush(g_Options.clBackSel);
+ FillRect(lpdis->hDC, &lpdis->rcItem, hbr);
+ DeleteObject(hbr);
+ //hbr = CreateSolidBrush(g_Options.clBackSel);
+ //FrameRect(lpdis->hDC, &lpdis->rcItem, hbr);
+ //DeleteObject(hbr);
+ SetTextColor(lpdis->hDC, g_Options.clLine1Sel);
+ }
+
+ if (true)
+ {
+ TCHAR *name = sttGetGroupName(lpdis->itemData);
+ if (!options->bSysColors) SelectObject(lpdis->hDC, g_Options.hfntName);
+ DrawText(lpdis->hDC, name, lstrlen(name), &lpdis->rcItem, DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER|DT_CENTER);
+ mir_free(name);
+ }
+
+ SelectObject(lpdis->hDC, hfntSave);
+
+ return TRUE;
+}
+
+void ImageList_DrawDimmed(HIMAGELIST himl, int i, HDC hdc, int left, int top, UINT fStyle)
+{
+ typedef BOOL (WINAPI *TFnAlphaBlend)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION);
+ static TFnAlphaBlend pfnAlphaBlend = NULL;
+ bool load_funcs = true;
+
+ if (load_funcs)
+ {
+ pfnAlphaBlend = (TFnAlphaBlend)GetProcAddress(GetModuleHandleA("msimg32"), "AlphaBlend");
+ load_funcs = false;
+ }
+
+ int dx, dy;
+ ImageList_GetIconSize(himl, &dx, &dy);
+
+ HDC dcMem = CreateCompatibleDC(hdc);
+ HBITMAP hbm = CreateCompatibleBitmap(hdc, dx, dy);
+ HBITMAP hbmOld = (HBITMAP)SelectObject(dcMem, hbm);
+ BitBlt(dcMem, 0, 0, dx, dx, hdc, left, top, SRCCOPY);
+ ImageList_Draw(himl, i, dcMem, 0, 0, fStyle);
+ if (pfnAlphaBlend)
+ {
+ BLENDFUNCTION bf = {0};
+ bf.SourceConstantAlpha = 180;
+ pfnAlphaBlend(hdc, left, top, dx, dy, dcMem, 0, 0, dx, dy, bf);
+ } else
+ {
+ SetStretchBltMode(hdc, HALFTONE);
+ StretchBlt(hdc, left, top, dx, dy, dcMem, 0, 0, dx, dy, SRCCOPY);
+ }
+ SelectObject(dcMem, hbmOld);
+ DeleteObject(hbm);
+ DeleteDC(dcMem);
+}
+
+static BOOL sttDrawItem_Contact(LPDRAWITEMSTRUCT lpdis, Options *options = NULL)
+{
+ HANDLE hContact = (HANDLE)lpdis->itemData;
+
+ HDC hdcTemp = CreateCompatibleDC(lpdis->hDC);
+ HBITMAP hbmTemp = CreateCompatibleBitmap(lpdis->hDC, lpdis->rcItem.right-lpdis->rcItem.left, lpdis->rcItem.bottom-lpdis->rcItem.top);
+ HBITMAP hbmSave = (HBITMAP)SelectObject(hdcTemp, hbmTemp);
+ RECT rcSave = lpdis->rcItem;
+
+ OffsetRect(&lpdis->rcItem, -lpdis->rcItem.left, -lpdis->rcItem.top);
+
+ HFONT hfntSave = (HFONT)SelectObject(hdcTemp, GetStockObject(DEFAULT_GUI_FONT));
+ SetBkMode(hdcTemp, TRANSPARENT);
+ COLORREF clBack, clLine1, clLine2;
+ if (lpdis->itemState & ODS_SELECTED)
+ {
+ if (options->bSysColors)
+ {
+ FillRect(hdcTemp, &lpdis->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT));
+ clBack = GetSysColor(COLOR_HIGHLIGHT);
+ clLine1 = GetSysColor(COLOR_HIGHLIGHTTEXT);
+ } else
+ {
+ clBack = g_Options.clBackSel;
+ clLine1 = g_Options.clLine1Sel;
+ clLine2 = g_Options.clLine2Sel;
+ }
+ } else
+ {
+ if (options->bSysColors)
+ {
+ FillRect(hdcTemp, &lpdis->rcItem, GetSysColorBrush(COLOR_MENU));
+ clBack = GetSysColor(COLOR_MENU);
+ clLine1 = GetSysColor(COLOR_MENUTEXT);
+ } else
+ {
+ clBack = g_Options.clBack;
+ clLine1 = g_Options.clLine1;
+ clLine2 = g_Options.clLine2;
+ }
+ }
+ if (options->bSysColors)
+ {
+ clLine2 = RGB(
+ (GetRValue(clLine1) * 66UL + GetRValue(clBack) * 34UL) / 100,
+ (GetGValue(clLine1) * 66UL + GetGValue(clBack) * 34UL) / 100,
+ (GetBValue(clLine1) * 66UL + GetBValue(clBack) * 34UL) / 100
+ );
+ } else
+ {
+ HBRUSH hbr = CreateSolidBrush(clBack);
+ FillRect(hdcTemp, &lpdis->rcItem, hbr);
+ DeleteObject(hbr);
+ }
+
+ lpdis->rcItem.left += 4;
+ lpdis->rcItem.right -= 4;
+
+ lpdis->rcItem.top += 2;
+ lpdis->rcItem.bottom -= 2;
+
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ if (true)
+ {
+ HIMAGELIST hIml = (HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0);
+ int iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM)hContact, 0);
+
+ if (DBGetContactSettingDword(hContact, proto, "IdleTS", 0))
+ {
+ ImageList_DrawDimmed(hIml, iIcon, hdcTemp,
+ lpdis->rcItem.left, (lpdis->rcItem.top + lpdis->rcItem.bottom - 16) / 2,
+ ILD_TRANSPARENT);
+ } else
+ {
+ ImageList_Draw(hIml, iIcon, hdcTemp,
+ lpdis->rcItem.left, (lpdis->rcItem.top + lpdis->rcItem.bottom - 16) / 2,
+ ILD_TRANSPARENT);
+ }
+
+ lpdis->rcItem.left += 20;
+ }
+
+ if (options->wMaxRecent && DBGetContactSettingByte(hContact, "FavContacts", "IsFavourite", 0))
+ {
+ DrawIconEx(hdcTemp, lpdis->rcItem.right - 18, (lpdis->rcItem.top + lpdis->rcItem.bottom - 16) / 2,
+ (HICON)CallService(MS_SKIN2_GETICONBYHANDLE, 0, g_icoFavourite), 16, 16, 0, NULL, DI_NORMAL);
+ lpdis->rcItem.right -= 20;
+ }
+
+ if (options->bAvatars)
+ {
+ AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)hContact, 0);
+ if (ace && (ace != (AVATARCACHEENTRY *)CALLSERVICE_NOTFOUND))
+ {
+ int avatarWidth = lpdis->rcItem.bottom - lpdis->rcItem.top;
+ if (ace->bmWidth < ace->bmHeight)
+ avatarWidth = (lpdis->rcItem.bottom - lpdis->rcItem.top) * ace->bmWidth / ace->bmHeight;
+
+ AVATARDRAWREQUEST avdr = {0};
+ avdr.cbSize = sizeof(avdr);
+ avdr.hContact = hContact;
+ avdr.hTargetDC = hdcTemp;
+ avdr.rcDraw = lpdis->rcItem;
+ if (options->bRightAvatars)
+ avdr.rcDraw.left = avdr.rcDraw.right - avatarWidth;
+ else
+ avdr.rcDraw.right = avdr.rcDraw.left + avatarWidth;
+ avdr.dwFlags = AVDRQ_FALLBACKPROTO;
+ if (options->bAvatarBorder)
+ {
+ avdr.dwFlags |= AVDRQ_DRAWBORDER;
+ avdr.clrBorder = clLine1;
+ if (options->bNoTransparentBorder)
+ avdr.dwFlags |= AVDRQ_HIDEBORDERONTRANSPARENCY;
+ if (options->wAvatarRadius)
+ {
+ avdr.dwFlags |= AVDRQ_ROUNDEDCORNER;
+ avdr.radius = (unsigned char)options->wAvatarRadius;
+ }
+ }
+ avdr.alpha = 255;
+ CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&avdr);
+
+ if (options->bRightAvatars)
+ lpdis->rcItem.right += avatarWidth + 5;
+ else
+ lpdis->rcItem.left += avatarWidth + 5;
+ }
+ }
+
+ if (true)
+ {
+ TCHAR *name = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR);
+
+ if (!options->bSysColors) SelectObject(hdcTemp, g_Options.hfntName);
+ SetTextColor(hdcTemp, clLine1);
+ DrawText(hdcTemp, name, lstrlen(name), &lpdis->rcItem, DT_NOPREFIX|DT_SINGLELINE|DT_TOP|DT_LEFT);
+
+ SIZE sz; GetTextExtentPoint32(hdcTemp, name, lstrlen(name), &sz);
+ lpdis->rcItem.top += sz.cy + 3;
+ }
+
+ if (options->bSecondLine)
+ {
+ DBVARIANT dbv;
+ TCHAR *title;
+ bool bFree = false;
+ if (DBGetContactSettingTString(hContact, "CList", "StatusMsg", &dbv) || !*dbv.ptszVal)
+ {
+ int status = DBGetContactSettingWord(hContact, proto, "Status", ID_STATUS_OFFLINE);
+ title = (TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, status, GSMDF_TCHAR);
+ } else
+ {
+ title = dbv.ptszVal;
+ bFree = true;
+ }
+
+ if (!options->bSysColors) SelectObject(hdcTemp, g_Options.hfntSecond);
+ SetTextColor(hdcTemp, clLine2);
+ DrawText(hdcTemp, title, lstrlen(title), &lpdis->rcItem, DT_NOPREFIX|DT_SINGLELINE|DT_TOP|DT_LEFT);
+
+ if (bFree) DBFreeVariant(&dbv);
+ }
+
+ SelectObject(hdcTemp, hfntSave);
+
+ BitBlt(lpdis->hDC,
+ rcSave.left, rcSave.top,
+ rcSave.right-rcSave.left, rcSave.bottom-rcSave.top,
+ hdcTemp, 0, 0, SRCCOPY);
+
+ SelectObject(hdcTemp, hbmSave);
+ DeleteObject(hbmTemp);
+ DeleteDC(hdcTemp);
+
+ return TRUE;
+}
+
+static BOOL sttDrawItem(LPDRAWITEMSTRUCT lpdis, Options *options=NULL)
+{
+ if (!options) options = &g_Options;
+
+ if (!lpdis->itemData)
+ return FALSE;
+
+ if (sttIsGroup(lpdis->itemData))
+ return sttDrawItem_Group(lpdis, options);
+
+ if (CallService(MS_DB_CONTACT_IS, lpdis->itemData, 0))
+ return sttDrawItem_Contact(lpdis, options);
+
+ return FALSE;
+}
+
+static LRESULT CALLBACK MenuHostWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static HANDLE hContact = NULL;
+
+ switch (message)
+ {
+ case WM_MEASUREITEM:
+ {
+ LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT)lParam;
+
+ if (lpmis->CtlType != ODT_MENU) return FALSE;
+
+ if ((lpmis->itemID >= CLISTMENUIDMIN) && (lpmis->itemID <= CLISTMENUIDMAX))
+ return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam);
+
+ return sttMeasureItem(lpmis);
+ }
+
+ case WM_DRAWITEM:
+ {
+ LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
+
+ if (lpdis->CtlType != ODT_MENU) return FALSE;
+
+ if ((lpdis->itemID >= CLISTMENUIDMIN) && (lpdis->itemID <= CLISTMENUIDMAX))
+ return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam);
+
+ return sttDrawItem(lpdis);
+ }
+
+ case WM_MENUCHAR:
+ {
+ while (GetMenuItemCount((HMENU)lParam) > 1)
+ RemoveMenu((HMENU)lParam, 1, MF_BYPOSITION);
+
+ if (LOWORD(wParam) == VK_BACK)
+ {
+ if (int l = lstrlen(g_filter))
+ g_filter[l-1] = 0;
+ } else
+ if (_istalnum(LOWORD(wParam)))
+ {
+ if (lstrlen(g_filter) < SIZEOF(g_filter)-1)
+ {
+ TCHAR s[] = { LOWORD(wParam), 0 };
+ lstrcat(g_filter, s);
+ }
+ }
+
+ int nRecent = 0;
+ int maxRecent = g_Options.wMaxRecent ? g_Options.wMaxRecent : 10;
+ for (int i = 0; nRecent < maxRecent; ++i)
+ {
+ HANDLE hContact = g_contactCache->get(i);
+ if (!hContact) break;
+ if (!g_contactCache->filter(i, g_filter)) continue;
+
+ AppendMenu((HMENU)lParam, MF_OWNERDRAW, nRecent+1, (LPCTSTR)hContact);
+ ++nRecent;
+ }
+ return MAKELRESULT(1, MNC_SELECT);
+ }
+
+ case WM_MENURBUTTONUP:
+ {
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA;
+ GetMenuItemInfo((HMENU)lParam, wParam, TRUE, &mii);
+ HANDLE hContact = (HANDLE)mii.dwItemData;
+ if (!CallService(MS_DB_CONTACT_IS, mii.dwItemData, 0)) return FALSE;
+
+ HMENU hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)hContact, 0);
+
+ POINT pt;
+ GetCursorPos(&pt);
+ HWND hwndSave = GetForegroundWindow();
+ SetForegroundWindow(g_hwndMenuHost);
+ int res = TrackPopupMenu(hMenu, TPM_RECURSE|TPM_RIGHTBUTTON|TPM_RETURNCMD, pt.x, pt.y, 0, g_hwndMenuHost, NULL);
+ SetForegroundWindow(hwndSave);
+ DestroyMenu(hMenu);
+
+ CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(res, MPCF_CONTACTMENU), (LPARAM)hContact);
+ return TRUE;
+ }
+ }
+
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+int sttShowMenu(bool centered)
+{
+ TFavContacts favList;
+ HMENU hMenu = CreatePopupMenu();
+ SIZE szMenu = {0};
+ SIZE szColumn = {0};
+ TCHAR *prevGroup = NULL;
+ int i, idItem;
+ HANDLE hContact;
+
+ favList.build();
+
+ g_widthMultiplier = 0;
+
+ g_maxItemWidth = GetSystemMetrics(SM_CXSCREEN);
+ if (g_Options.bUseColumns) g_maxItemWidth /= favList.groupCount();
+
+ prevGroup = NULL;
+ for (i = 0; i < favList.getCount(); ++i)
+ {
+ hContact = favList[i]->getHandle();
+
+ MEASUREITEMSTRUCT mis = {0};
+ mis.CtlID = 0;
+ mis.CtlType = ODT_MENU;
+
+ if (!prevGroup || lstrcmp(prevGroup, favList[i]->getGroup()))
+ {
+ if (prevGroup && g_Options.bUseColumns)
+ {
+ szMenu.cx += szColumn.cx;
+ szMenu.cy = max(szMenu.cy, szColumn.cy);
+ szColumn.cx = szColumn.cy = 0;
+ }
+
+ DWORD groupID = sttGetGroupId(favList[i]->getGroup());
+
+ AppendMenu(hMenu,
+ MF_OWNERDRAW|MF_SEPARATOR| ((prevGroup && g_Options.bUseColumns) ? MF_MENUBREAK : 0),
+ ++idItem, (LPCTSTR)groupID);
+
+ mis.itemData = groupID;
+ mis.itemID = idItem;
+ sttMeasureItem(&mis);
+ szColumn.cx = max(szColumn.cx, mis.itemWidth);
+ szColumn.cy += mis.itemHeight;
+ }
+
+ AppendMenu(hMenu, MF_OWNERDRAW, ++idItem, (LPCTSTR)hContact);
+
+ mis.itemData = (DWORD)hContact;
+ mis.itemID = idItem;
+ sttMeasureItem(&mis);
+ szColumn.cx = max(szColumn.cx, mis.itemWidth);
+ szColumn.cy += mis.itemHeight;
+
+ prevGroup = favList[i]->getGroup();
+ }
+ szMenu.cx += szColumn.cx;
+ szMenu.cy = max(szMenu.cy, szColumn.cy);
+ szColumn.cx = szColumn.cy = 0;
+
+ unsigned maxWidth = GetSystemMetrics(SM_CXSCREEN) * DBGetContactSettingByte(NULL, "FavContacts", "MenuWidth", 66) / 100;
+ if (szMenu.cx > maxWidth)
+ {
+ g_widthMultiplier = (float)maxWidth / szMenu.cx;
+ szMenu.cx *= g_widthMultiplier;
+ }
+
+ POINT pt;
+
+// RECT rc;
+// GetMenuItemRect(g_hwndMenuHost, hMenu, 1, &rc);
+
+ if (centered)
+ {
+ if ((pt.x = (GetSystemMetrics(SM_CXSCREEN) - szMenu.cx) / 2) < 0) pt.x = 0;
+ if ((pt.y = (GetSystemMetrics(SM_CYSCREEN) - szMenu.cy) / 2) < 0) pt.y = 0;
+ } else
+ {
+ GetCursorPos(&pt);
+ }
+
+ HWND hwndSave = GetForegroundWindow();
+ SetForegroundWindow(g_hwndMenuHost);
+ hContact = NULL;
+ g_filter[0] = 0;
+ if (int res = TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, g_hwndMenuHost, NULL))
+ {
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA;
+ GetMenuItemInfo(hMenu, res, FALSE, &mii);
+ hContact = (HANDLE)mii.dwItemData;
+ }
+ SetForegroundWindow(hwndSave);
+ DestroyMenu(hMenu);
+
+ if (hContact)
+ CallService(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)hContact, 0);
+
+ return 0;
+}
+
+INT_PTR svcShowMenu(WPARAM wParam, LPARAM lParam)
+{
+ sttShowMenu(false);
+ return 0;
+}
+
+INT_PTR svcShowMenuCentered(WPARAM wParam, LPARAM lParam)
+{
+ sttShowMenu(g_Options.bCenterHotkey ? true : false);
+ return 0;
+}
+
+static HANDLE hDialogsList = NULL;
+static HANDLE hContactToActivate = NULL;
+
+INT_PTR svcOpenContact(WPARAM wParam, LPARAM lParam)
+{
+ hContactToActivate = (HANDLE)wParam;
+ CallService(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)hContactToActivate, 0);
+ return 0;
+}
+
+int ProcessSrmmEvent( WPARAM wParam, LPARAM lParam )
+{
+ MessageWindowEventData *event = (MessageWindowEventData *)lParam;
+
+ if ( event->uType == MSG_WINDOW_EVT_OPEN )
+ {
+ if ( !hDialogsList )
+ hDialogsList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0);
+ WindowList_Add(hDialogsList, event->hwndWindow, event->hContact);
+
+ BYTE fav = DBGetContactSettingByte(event->hContact, "FavContacts", "IsFavourite", 0);
+ StatusIconData sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.szModule = "FavContacts";
+ sid.flags = fav ? 0 : MBF_DISABLED;
+ CallService(MS_MSG_MODIFYICON, (WPARAM)event->hContact, (LPARAM)&sid);
+
+ if (event->hContact == hContactToActivate)
+ {
+ HWND hwndRoot = event->hwndWindow;
+ while (HWND hwndParent = GetParent(hwndRoot))
+ hwndRoot = hwndParent;
+
+ AttachThreadInput(GetWindowThreadProcessId(GetForegroundWindow(), NULL), GetCurrentThreadId(), TRUE);
+ SetForegroundWindow(hwndRoot);
+ SetActiveWindow(hwndRoot);
+ SetFocus(hwndRoot);
+ AttachThreadInput(GetWindowThreadProcessId(GetForegroundWindow(), NULL), GetCurrentThreadId(), FALSE);
+ }
+
+ hContactToActivate = NULL;
+ }
+ else if ( event->uType == MSG_WINDOW_EVT_CLOSING )
+ {
+ if (hDialogsList)
+ WindowList_Remove(hDialogsList, event->hwndWindow);
+ }
+
+ return 0;
+}
+
+int ProcessSrmmIconClick( WPARAM wParam, LPARAM lParam )
+{
+ StatusIconClickData *sicd = (StatusIconClickData *)lParam;
+ if (lstrcmpA(sicd->szModule, "FavContacts")) return 0;
+
+ HANDLE hContact = (HANDLE)wParam;
+ if (!hContact) return 0;
+
+ if (sicd->flags & MBCF_RIGHTBUTTON)
+ {
+ BYTE fav = !DBGetContactSettingByte(hContact, "FavContacts", "IsFavourite", 0);
+ DBWriteContactSettingByte(hContact, "FavContacts", "IsFavourite", fav);
+ if (fav) CallService(MS_AV_GETAVATARBITMAP, (WPARAM)hContact, 0);
+
+ StatusIconData sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.szModule = "FavContacts";
+ sid.flags = fav ? 0 : MBF_DISABLED;
+ CallService(MS_MSG_MODIFYICON, (WPARAM)hContact, (LPARAM)&sid);
+ } else
+ {
+ sttShowMenu(false);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////
+// Options
+static void sttResetListOptions(HWND hwndList)
+{
+ int i;
+ SendMessage(hwndList,CLM_SETBKBITMAP,0,(LPARAM)(HBITMAP)NULL);
+ SendMessage(hwndList,CLM_SETBKCOLOR,GetSysColor(COLOR_WINDOW),0);
+ SendMessage(hwndList,CLM_SETGREYOUTFLAGS,0,0);
+ SendMessage(hwndList,CLM_SETLEFTMARGIN,4,0);
+ SendMessage(hwndList,CLM_SETINDENT,10,0);
+ SendMessage(hwndList,CLM_SETHIDEEMPTYGROUPS,1,0);
+ SendMessage(hwndList,CLM_SETHIDEOFFLINEROOT,1,0);
+ for (i = 0; i <= FONTID_MAX; ++i)
+ SendMessage(hwndList, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT));
+}
+
+static void sttActivateOptionsPage(HWND hwnd, TCHAR *aSection, TCHAR *aPage)
+{
+ TCHAR buf[256];
+ TCHAR *section = TranslateTS(aSection);
+
+ HWND hwndTree = FindWindowEx(GetParent(hwnd), NULL, WC_TREEVIEW, NULL);
+ for (HTREEITEM htiSection = TreeView_GetRoot(hwndTree); htiSection; htiSection = TreeView_GetNextSibling(hwndTree, htiSection))
+ {
+ TVITEM tvi = {0};
+ tvi.mask = TVIF_TEXT;
+ tvi.hItem = htiSection;
+ tvi.pszText = buf;
+ tvi.cchTextMax = SIZEOF(buf);
+ TreeView_GetItem(hwndTree, &tvi);
+
+ if (!lstrcmp(buf, section))
+ {
+ if (!aPage)
+ {
+ TreeView_Select(hwndTree, htiSection, TVGN_CARET);
+ return;
+ } else
+ {
+ TreeView_Expand(hwndTree, htiSection, TVE_EXPAND);
+ }
+
+ TCHAR *page = TranslateTS(aPage);
+ for (HTREEITEM htiPage = TreeView_GetChild(hwndTree, htiSection); htiPage; htiPage = TreeView_GetNextSibling(hwndTree, htiPage))
+ {
+ TVITEM tvi = {0};
+ tvi.mask = TVIF_TEXT;
+ tvi.hItem = htiPage;
+ tvi.pszText = buf;
+ tvi.cchTextMax = SIZEOF(buf);
+ TreeView_GetItem(hwndTree, &tvi);
+
+ if (!lstrcmp(buf, page))
+ {
+ TreeView_Select(hwndTree, htiPage, TVGN_CARET);
+ return;
+ }
+ }
+
+ break;
+ }
+ }
+}
+
+static BOOL CALLBACK OptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static bool bInitialized = false;
+ static HANDLE hSelectedContact = 0;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ bInitialized = false;
+
+ TranslateDialogDefault(hwnd);
+
+ CheckDlgButton(hwnd, IDC_CHK_GROUPS, g_Options.bUseGroups ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwnd, IDC_CHK_GROUPCOLUMS, g_Options.bUseColumns ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwnd, IDC_CHK_SECONDLINE, g_Options.bSecondLine ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwnd, IDC_CHK_AVATARS, g_Options.bAvatars ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwnd, IDC_CHK_AVATARBORDER, g_Options.bAvatarBorder ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwnd, IDC_CHK_NOTRANSPARENTBORDER, g_Options.bNoTransparentBorder ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwnd, IDC_CHK_SYSCOLORS, g_Options.bSysColors ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwnd, IDC_CHK_CENTERHOTKEY, g_Options.bCenterHotkey ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwnd, IDC_CHK_RIGHTAVATARS, g_Options.bRightAvatars ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwnd, IDC_CHK_DIMIDLE, g_Options.bDimIdle ? BST_CHECKED : BST_UNCHECKED);
+ SetDlgItemInt(hwnd, IDC_TXT_RADIUS, g_Options.wAvatarRadius, FALSE);
+ SetDlgItemInt(hwnd, IDC_TXT_MAXRECENT, g_Options.wMaxRecent, FALSE);
+
+ SetWindowLong(GetDlgItem(hwnd, IDC_CLIST), GWL_STYLE,
+ GetWindowLong(GetDlgItem(hwnd, IDC_CLIST), GWL_STYLE)|CLS_CHECKBOXES|CLS_HIDEEMPTYGROUPS|CLS_USEGROUPS|CLS_GREYALTERNATE|CLS_GROUPCHECKBOXES);
+ SendMessage(GetDlgItem(hwnd, IDC_CLIST), CLM_SETEXSTYLE, CLS_EX_DISABLEDRAGDROP|CLS_EX_TRACKSELECT, 0);
+ sttResetListOptions(GetDlgItem(hwnd, IDC_CLIST));
+
+ hSelectedContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ for ( ; hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0))
+ {
+ SendDlgItemMessage(hwnd, IDC_CLIST, CLM_SETCHECKMARK,
+ SendDlgItemMessage(hwnd, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0),
+ DBGetContactSettingByte(hContact, "FavContacts", "IsFavourite", 0));
+ }
+
+ if (!ServiceExists(MS_HOTKEY_REGISTER))
+ EnableWindow(GetDlgItem(hwnd, IDC_BTN_HOTKEYS), FALSE);
+
+ bInitialized = true;
+
+ PostMessage(hwnd, WM_APP, 0, 0);
+
+ return TRUE;
+ }
+
+ case WM_APP:
+ {
+ BOOL bGroups = IsDlgButtonChecked(hwnd, IDC_CHK_GROUPS);
+ EnableWindow(GetDlgItem(hwnd, IDC_CHK_GROUPCOLUMS), bGroups);
+
+ BOOL bAvatars = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARS);
+ BOOL bBorders = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARBORDER);
+ EnableWindow(GetDlgItem(hwnd, IDC_CHK_AVATARBORDER), bAvatars);
+ EnableWindow(GetDlgItem(hwnd, IDC_CHK_RIGHTAVATARS), bAvatars);
+ EnableWindow(GetDlgItem(hwnd, IDC_CHK_NOTRANSPARENTBORDER), bAvatars && bBorders);
+ EnableWindow(GetDlgItem(hwnd, IDC_TXT_RADIUS), bAvatars && bBorders);
+ return TRUE;
+ }
+
+ case WM_DRAWITEM:
+ {
+ LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
+ if (lpdis->CtlID == IDC_CANVAS)
+ {
+ MEASUREITEMSTRUCT mis = {0};
+ DRAWITEMSTRUCT dis = *lpdis;
+
+ FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrush(COLOR_BTNFACE));
+ if (hSelectedContact)
+ {
+ Options options;
+ options.bSecondLine = IsDlgButtonChecked(hwnd, IDC_CHK_SECONDLINE);
+ options.bAvatars = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARS);
+ options.bAvatarBorder = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARBORDER);
+ options.bNoTransparentBorder = IsDlgButtonChecked(hwnd, IDC_CHK_NOTRANSPARENTBORDER);
+ options.bSysColors = IsDlgButtonChecked(hwnd, IDC_CHK_SYSCOLORS);
+ options.bCenterHotkey = IsDlgButtonChecked(hwnd, IDC_CHK_CENTERHOTKEY);
+ options.bRightAvatars = IsDlgButtonChecked(hwnd, IDC_CHK_RIGHTAVATARS);
+ options.bDimIdle = IsDlgButtonChecked(hwnd, IDC_CHK_DIMIDLE);
+ options.wAvatarRadius = GetDlgItemInt(hwnd, IDC_TXT_RADIUS, NULL, FALSE);
+ options.wMaxRecent = GetDlgItemInt(hwnd, IDC_TXT_MAXRECENT, NULL, FALSE);
+
+ mis.CtlID = 0;
+ mis.CtlType = ODT_MENU;
+ mis.itemData = (DWORD)hSelectedContact;
+ sttMeasureItem(&mis, &options);
+ dis.rcItem.bottom = dis.rcItem.top + mis.itemHeight;
+
+ dis.CtlID = 0;
+ dis.CtlType = ODT_MENU;
+ dis.itemData = (DWORD)hSelectedContact;
+ sttDrawItem(&dis, &options);
+
+ RECT rc = lpdis->rcItem;
+ rc.bottom = rc.top + mis.itemHeight;
+ FrameRect(lpdis->hDC, &rc, GetSysColorBrush(COLOR_HIGHLIGHT));
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_CHK_SECONDLINE:
+ case IDC_CHK_AVATARS:
+ case IDC_CHK_AVATARBORDER:
+ case IDC_CHK_NOTRANSPARENTBORDER:
+ case IDC_CHK_SYSCOLORS:
+ case IDC_CHK_CENTERHOTKEY:
+ case IDC_CHK_GROUPS:
+ case IDC_CHK_GROUPCOLUMS:
+ case IDC_CHK_RIGHTAVATARS:
+ SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
+ RedrawWindow(GetDlgItem(hwnd, IDC_CANVAS), NULL, NULL, RDW_INVALIDATE);
+ PostMessage(hwnd, WM_APP, 0, 0);
+ break;
+
+ case IDC_BTN_HOTKEYS:
+ if (ServiceExists(MS_HOTKEY_REGISTER))
+ {
+ sttActivateOptionsPage(hwnd, _T("Customize"), _T("Hotkeys"));
+ }
+ break;
+
+ case IDC_BTN_FONTS:
+ sttActivateOptionsPage(hwnd, _T("Customize"), _T("Fonts"));
+ break;
+
+ case IDC_TXT_RADIUS:
+ if ((HIWORD(wParam) == EN_CHANGE) && bInitialized)
+ {
+ RedrawWindow(GetDlgItem(hwnd, IDC_CANVAS), NULL, NULL, RDW_INVALIDATE);
+ SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
+ }
+ break;
+
+ case IDC_TXT_MAXRECENT:
+ if ((HIWORD(wParam) == EN_CHANGE) && bInitialized)
+ SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
+ break;
+ }
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ if ((((LPNMHDR)lParam)->idFrom == 0) && (((LPNMHDR)lParam)->code == PSN_APPLY))
+ {
+ g_Options.bSecondLine = IsDlgButtonChecked(hwnd, IDC_CHK_SECONDLINE);
+ g_Options.bAvatars = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARS);
+ g_Options.bAvatarBorder = IsDlgButtonChecked(hwnd, IDC_CHK_AVATARBORDER);
+ g_Options.bNoTransparentBorder = IsDlgButtonChecked(hwnd, IDC_CHK_NOTRANSPARENTBORDER);
+ g_Options.bSysColors = IsDlgButtonChecked(hwnd, IDC_CHK_SYSCOLORS);
+ g_Options.bCenterHotkey = IsDlgButtonChecked(hwnd, IDC_CHK_CENTERHOTKEY);
+ g_Options.bUseGroups = IsDlgButtonChecked(hwnd, IDC_CHK_GROUPS);
+ g_Options.bUseColumns = IsDlgButtonChecked(hwnd, IDC_CHK_GROUPCOLUMS);
+ g_Options.bRightAvatars = IsDlgButtonChecked(hwnd, IDC_CHK_RIGHTAVATARS);
+ g_Options.bDimIdle = IsDlgButtonChecked(hwnd, IDC_CHK_DIMIDLE);
+ g_Options.wAvatarRadius = GetDlgItemInt(hwnd, IDC_TXT_RADIUS, NULL, FALSE);
+ g_Options.wMaxRecent = GetDlgItemInt(hwnd, IDC_TXT_MAXRECENT, NULL, FALSE);
+
+ sttSaveOptions();
+
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ for ( ; hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0))
+ {
+ BYTE fav = SendDlgItemMessage(hwnd, IDC_CLIST, CLM_GETCHECKMARK,
+ SendDlgItemMessage(hwnd, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0), 0);
+ if (fav != DBGetContactSettingByte(hContact, "FavContacts", "IsFavourite", 0))
+ DBWriteContactSettingByte(hContact, "FavContacts", "IsFavourite", fav);
+ if (fav) CallService(MS_AV_GETAVATARBITMAP, (WPARAM)hContact, 0);
+ }
+ } else
+ if (((LPNMHDR)lParam)->idFrom == IDC_CLIST)
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case CLN_OPTIONSCHANGED:
+ {
+ sttResetListOptions(GetDlgItem(hwnd,IDC_CLIST));
+ break;
+ }
+
+ case CLN_NEWCONTACT:
+ {
+ int iSelection = (int)((NMCLISTCONTROL *)lParam)->hItem;
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ for ( ; hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0))
+ if (SendDlgItemMessage(hwnd, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0) == iSelection)
+ {
+ SendDlgItemMessage(hwnd, IDC_CLIST, CLM_SETCHECKMARK, iSelection,
+ DBGetContactSettingByte(hContact, "FavContacts", "IsFavourite", 0));
+ break;
+ }
+ break;
+ }
+
+ case CLN_CHECKCHANGED:
+ {
+ int iSelection = (int)((NMCLISTCONTROL *)lParam)->hItem;
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ for ( ; hContact; hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0))
+ if (SendDlgItemMessage(hwnd, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0) == iSelection)
+ break;
+ if (hContact)
+ {
+ hSelectedContact = hContact;
+ RedrawWindow(GetDlgItem(hwnd, IDC_CANVAS), NULL, NULL, RDW_INVALIDATE);
+ }
+ SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0);
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ return FALSE;
+}
diff --git a/plugins/FloatingContacts/FltCont_10.sln b/plugins/FloatingContacts/FltCont_10.sln
new file mode 100644
index 0000000000..823e987bbd
--- /dev/null
+++ b/plugins/FloatingContacts/FltCont_10.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FltCont", "FltCont_10.vcxproj", "{9290A9CC-3FDA-4FD6-A8A2-04AD4BA1C856}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug Unicode|Win32 = Debug Unicode|Win32
+ Debug|Win32 = Debug|Win32
+ Release Unicode|Win32 = Release Unicode|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9290A9CC-3FDA-4FD6-A8A2-04AD4BA1C856}.Debug Unicode|Win32.ActiveCfg = Debug Unicode|Win32
+ {9290A9CC-3FDA-4FD6-A8A2-04AD4BA1C856}.Debug Unicode|Win32.Build.0 = Debug Unicode|Win32
+ {9290A9CC-3FDA-4FD6-A8A2-04AD4BA1C856}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9290A9CC-3FDA-4FD6-A8A2-04AD4BA1C856}.Debug|Win32.Build.0 = Debug|Win32
+ {9290A9CC-3FDA-4FD6-A8A2-04AD4BA1C856}.Release Unicode|Win32.ActiveCfg = Release Unicode|Win32
+ {9290A9CC-3FDA-4FD6-A8A2-04AD4BA1C856}.Release Unicode|Win32.Build.0 = Release Unicode|Win32
+ {9290A9CC-3FDA-4FD6-A8A2-04AD4BA1C856}.Release|Win32.ActiveCfg = Release|Win32
+ {9290A9CC-3FDA-4FD6-A8A2-04AD4BA1C856}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/plugins/FloatingContacts/FltCont_10.vcxproj b/plugins/FloatingContacts/FltCont_10.vcxproj
new file mode 100644
index 0000000000..a76fd934d2
--- /dev/null
+++ b/plugins/FloatingContacts/FltCont_10.vcxproj
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug Unicode|Win32">
+ <Configuration>Debug Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release Unicode|Win32">
+ <Configuration>Release Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>FltCont</ProjectName>
+ <ProjectGuid>{9290A9CC-3FDA-4FD6-A8A2-04AD4BA1C856}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">fltcontacts</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>stdhdr.h</PrecompiledHeaderFile>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>stdhdr.h</PrecompiledHeaderFile>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>stdhdr.h</PrecompiledHeaderFile>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>stdhdr.h</PrecompiledHeaderFile>
+ <WarningLevel>Level4</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>Msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="bitmap_funcs.cpp" />
+ <ClCompile Include="filedrop.cpp" />
+ <ClCompile Include="main.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="options.cpp" />
+ <ClCompile Include="thumbs.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="bitmap_funcs.h" />
+ <ClInclude Include="filedrop.h" />
+ <ClInclude Include="fltcont.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="stdhdr.h" />
+ <ClInclude Include="thumbs.h" />
+ <ClInclude Include="version.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="fltcnt.rc">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ </ResourceCompile>
+ <ResourceCompile Include="Script.rc" />
+ <ResourceCompile Include="version.rc">
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">true</ExcludedFromBuild>
+ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="hide.ico" />
+ <None Include="show.ico" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/FloatingContacts/FltCont_10.vcxproj.filters b/plugins/FloatingContacts/FltCont_10.vcxproj.filters
new file mode 100644
index 0000000000..4b33b8e646
--- /dev/null
+++ b/plugins/FloatingContacts/FltCont_10.vcxproj.filters
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{84999e29-bc79-471f-9875-ab09dde3a08a}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{715cbea0-9043-4420-8266-8083bb9d03e1}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{fd5f5482-d8cc-42d5-b4e9-5055d6618caa}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="bitmap_funcs.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="filedrop.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="main.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="options.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="thumbs.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="bitmap_funcs.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="filedrop.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="fltcont.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="stdhdr.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="thumbs.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="version.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="fltcnt.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ <ResourceCompile Include="Script.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ <ResourceCompile Include="version.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="hide.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="show.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/FloatingContacts/Script.rc b/plugins/FloatingContacts/Script.rc
new file mode 100644
index 0000000000..b1bbc9db7b
--- /dev/null
+++ b/plugins/FloatingContacts/Script.rc
@@ -0,0 +1,2 @@
+#include "version.rc"
+#include "fltcnt.rc"
diff --git a/plugins/FloatingContacts/bitmap_funcs.cpp b/plugins/FloatingContacts/bitmap_funcs.cpp
new file mode 100644
index 0000000000..3d92e7a9d8
--- /dev/null
+++ b/plugins/FloatingContacts/bitmap_funcs.cpp
@@ -0,0 +1,1239 @@
+/*
+Popup Plus plugin for Miranda IM
+
+Copyright 2002 Luca Santarelli,
+ 2004-2007 Victor Pavlychko
+
+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 "stdhdr.h"
+#include "bitmap_funcs.h"
+
+#include <m_png.h>
+#include <math.h>
+
+#define PU_FONT_THRESHOLD 96
+#define PU_BMP_ACCURATE_ARITHMETICS
+
+#ifdef PU_BMP_ACCURATE_ARITHMETICS
+ #define PU_DIV255(x) ((x)/255)
+ #define PU_DIV128(x) ((x)/128)
+ typedef float pu_koef;
+#else
+ #define PU_DIV255(x) ((x)>>8)
+ #define PU_DIV128(x) ((x)>>7)
+ typedef long pu_koef;
+#endif
+
+MyBitmap::MyBitmap()
+{
+ dcBmp = 0;
+ hBmp = 0;
+ bits = 0;
+ width = height = 0;
+ bitsSave = 0;
+}
+
+MyBitmap::MyBitmap(int w, int h)
+{
+ dcBmp = 0;
+ hBmp = 0;
+ bits = 0;
+ width = height = 0;
+ bitsSave = 0;
+ allocate(w,h);
+}
+
+MyBitmap::MyBitmap(const char *fn, const char *fnAlpha)
+{
+ dcBmp = 0;
+ hBmp = 0;
+ bits = 0;
+ width = height = 0;
+ bitsSave = 0;
+ loadFromFile(fn, fnAlpha);
+}
+
+MyBitmap::~MyBitmap()
+{
+ if (bitsSave)
+ delete [] bitsSave;
+ free();
+}
+
+void MyBitmap::setAlpha(BYTE level)
+{
+ if (!bits) return;
+
+ GdiFlush();
+ for (int i = 0; i < width*height; i++)
+ {
+ if (bits[i] & 0xff000000)
+ {
+ bits[i] = rgba(getr(bits[i])*level/255, getg(bits[i])*level/255, getb(bits[i])*level/255, geta(bits[i])*level/255);
+ } else
+ {
+ bits[i] = rgba(getr(bits[i])*level/255, getg(bits[i])*level/255, getb(bits[i])*level/255, level);
+ }
+ }
+}
+
+void MyBitmap::setAlphaRect(int x1, int y1, int x2, int y2, BYTE level)
+{
+ if (!bits) return;
+
+ GdiFlush();
+ for (int i = y1; i < y2; i++)
+ for (int j = x1; j < x2; j++)
+ {
+ int idx = i * width + j;
+ if (bits[idx] & 0xff000000)
+ {
+ bits[idx] = rgba(getr(bits[idx])*level/255, getg(bits[idx])*level/255, getb(bits[idx])*level/255, geta(bits[idx])*level/255);
+ } else
+ {
+ bits[idx] = rgba(getr(bits[idx])*level/255, getg(bits[idx])*level/255, getb(bits[idx])*level/255, level);
+ }
+ }
+}
+
+void MyBitmap::makeOpaque()
+{
+ if (!bits) return;
+
+ GdiFlush();
+ for (int i = 0; i < width*height; i++)
+ bits[i] |= 0xff000000;
+}
+
+void MyBitmap::makeOpaqueRect(int x1, int y1, int x2, int y2)
+{
+ if (!bits) return;
+
+ GdiFlush();
+ for (int i = y1; i < y2; i++)
+ for (int j = x1; j < x2; j++)
+ {
+ int idx = i * width + j;
+ bits[idx] |= 0xff000000;
+ }
+}
+
+void MyBitmap::saveAlpha(int x, int y, int w, int h)
+{
+ if (bitsSave)
+ delete [] bitsSave;
+
+ GdiFlush();
+
+ if (!w) w = width;
+ if (!h) h = height;
+
+ bitsSave = new COLOR32[w*h];
+ COLOR32 *p1 = bitsSave;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ COLOR32 *p2 = bits + (y+i)*width + x;
+ p1 = bitsSave + i*w;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ *p1++ = *p2++;
+ }
+ }
+}
+
+void MyBitmap::restoreAlpha(int x, int y, int w, int h)
+{
+ if (!bitsSave)
+ return;
+
+ GdiFlush();
+
+ if (!w) w = width;
+ if (!h) h = height;
+
+ COLOR32 *p1 = bitsSave;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ COLOR32 *p2 = bits + (y+i)*width + x;
+ p1 = bitsSave + i*w;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ if ((*p1&0x00ffffff) != (*p2&0x00ffffff))
+ {
+ *p2 |= 0xff000000;
+ } else
+ {
+ *p2 = (*p2&0x00ffffff) | (*p1&0xff000000);
+ }
+ ++p1;
+ ++p2;
+ }
+ }
+
+ delete [] bitsSave;
+ bitsSave = 0;
+}
+
+void MyBitmap::DrawBits(COLOR32 *inbits, int inw, int inh, int x, int y, int w, int h)
+{
+ if (!(bits && inbits)) return;
+
+ GdiFlush();
+
+ float kx = (float)inw / w;
+ float ky = (float)inh / h;
+
+ if (x+w >= this->getWidth())
+ w = this->getWidth() - x;
+ if (y+h >= this->getHeight())
+ h = this->getHeight() - y;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ bits[(i+y)*width + (j+x)] = inbits[int(i*ky)*inw + int(j*kx)];
+ }
+ }
+}
+
+void MyBitmap::BlendBits(COLOR32 *inbits, int inw, int inh, int x, int y, int w, int h)
+{
+ if (!(bits && inbits)) return;
+
+ GdiFlush();
+
+ float kx = (float)inw / w;
+ float ky = (float)inh / h;
+
+ if (x+w >= this->getWidth())
+ w = this->getWidth() - x;
+ if (y+h >= this->getHeight())
+ h = this->getHeight() - y;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ COLOR32 src = inbits[int(i*ky)*inw + int(j*kx)];
+ COLOR32 dst = bits[(i+y)*width + (j+x)];
+ long alpha = geta(src);
+ bits[(i+y)*width + (j+x)] = rgba(
+ getr(src)+PU_DIV255((255-alpha)*getr(dst)),
+ getg(src)+PU_DIV255((255-alpha)*getg(dst)),
+ getb(src)+PU_DIV255((255-alpha)*getb(dst)),
+ geta(src)+PU_DIV255((255-alpha)*geta(dst))
+ );
+ }
+ }
+}
+
+void MyBitmap::Blend(MyBitmap *bmp, int x, int y, int w, int h)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+
+ GdiFlush();
+
+ if (!w) w = bmp->width;
+ if (!h) h = bmp->height;
+ float kx = (float)bmp->width / w;
+ float ky = (float)bmp->height / h;
+
+ if (x+w >= this->getWidth())
+ w = this->getWidth() - x;
+ if (y+h >= this->getHeight())
+ h = this->getHeight() - y;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ COLOR32 src = bmp->bits[int(i*ky)*bmp->width + int(j*kx)];
+ COLOR32 dst = bits[(i+y)*width + (j+x)];
+ long alpha = geta(src);
+ bits[(i+y)*width + (j+x)] = rgba(
+ getr(src)+PU_DIV255((255-alpha)*getr(dst)),
+ getg(src)+PU_DIV255((255-alpha)*getg(dst)),
+ getb(src)+PU_DIV255((255-alpha)*getb(dst)),
+ geta(src)+PU_DIV255((255-alpha)*geta(dst))
+ );
+ }
+ }
+}
+
+void MyBitmap::Draw(MyBitmap *bmp, int x, int y, int w, int h)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+
+ GdiFlush();
+
+ if (!w) w = bmp->width;
+ if (!h) h = bmp->height;
+
+ if (!x && !y && (w == width) && (h == height) && (w == bmp->width) && (h == bmp->height))
+ {
+ // fast bitmap copy is possible good for animated avatars
+ CopyMemory(bits, bmp->bits, width*height*sizeof(COLOR32));
+ return;
+ }
+
+ float kx = (float)bmp->width / w;
+ float ky = (float)bmp->height / h;
+
+ if (x+w >= this->getWidth())
+ w = this->getWidth() - x;
+ if (y+h >= this->getHeight())
+ h = this->getHeight() - y;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ bits[(i+y)*width + (j+x)] = bmp->bits[int(i*ky)*bmp->width + int(j*kx)];
+ }
+ }
+}
+
+void MyBitmap::BlendColorized(MyBitmap *bmp, int x, int y, int w, int h, COLOR32 color)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+
+ GdiFlush();
+
+ if (!w) w = bmp->width;
+ if (!h) h = bmp->height;
+ float kx = (float)bmp->width / w;
+ float ky = (float)bmp->height / h;
+
+ // we should swap B and R channels when working with win32 COLORREF
+ float koef1r = (255 - getb(color)) / 128.0f;
+ float koef1g = (255 - getg(color)) / 128.0f;
+ float koef1b = (255 - getr(color)) / 128.0f;
+
+ int br = - 255 + 2 * getb(color);
+ int bg = - 255 + 2 * getg(color);
+ int bb = - 255 + 2 * getr(color);
+
+ float koef2r = (getb(color)) / 128.0f;
+ float koef2g = (getg(color)) / 128.0f;
+ float koef2b = (getr(color)) / 128.0f;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+
+// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+// bits[(i+y)*width + (j+x)] = (cl > 128) ?
+// rgba(koef1r * cl + br, koef1g * cl + bg, koef1b * cl + bb, geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)])):
+// rgba(koef2r * cl, koef2g * cl, koef2b * cl, geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]));
+
+ long alpha = geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+ COLOR32 cl = alpha ? getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)])*255/alpha : 0;
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ COLOR32 src = (cl > 128) ?
+ rgba(
+ PU_DIV255((koef1r * cl + br)*alpha),
+ PU_DIV255((koef1g * cl + bg)*alpha),
+ PU_DIV255((koef1b * cl + bb)*alpha),
+ alpha):
+ rgba(
+ PU_DIV255(koef2r * cl * alpha),
+ PU_DIV255(koef2g * cl * alpha),
+ PU_DIV255(koef2b * cl * alpha),
+ alpha);
+#pragma warning(pop)
+// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+// COLOR32 src = (cl > 128) ?
+// rgba(koef1r * cl + br, koef1g * cl + bg, koef1b * cl + bb, alpha):
+// rgba(koef2r * cl, koef2g * cl, koef2b * cl, alpha);
+ COLOR32 dst = bits[(i+y)*width + (j+x)];
+// long alpha = geta(src);
+ bits[(i+y)*width + (j+x)] = rgba(
+ getr(src)+PU_DIV255((255-alpha)*getr(dst)),
+ getg(src)+PU_DIV255((255-alpha)*getg(dst)),
+ getb(src)+PU_DIV255((255-alpha)*getb(dst)),
+ geta(src)+PU_DIV255((255-alpha)*geta(dst))
+ );
+
+ }
+ }
+}
+
+void MyBitmap::DrawColorized(MyBitmap *bmp, int x, int y, int w, int h, COLOR32 color)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+
+ GdiFlush();
+
+ if (!w) w = bmp->width;
+ if (!h) h = bmp->height;
+ float kx = (float)bmp->width / w;
+ float ky = (float)bmp->height / h;
+
+ // we should swap B and R channels when working with win32 COLORREF
+ float koef1r = (255 - getb(color)) / 128.0f;
+ float koef1g = (255 - getg(color)) / 128.0f;
+ float koef1b = (255 - getr(color)) / 128.0f;
+
+ int br = - 255 + 2 * getb(color);
+ int bg = - 255 + 2 * getg(color);
+ int bb = - 255 + 2 * getr(color);
+
+ float koef2r = (getb(color)) / 128.0f;
+ float koef2g = (getg(color)) / 128.0f;
+ float koef2b = (getr(color)) / 128.0f;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+
+ long alpha = geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+ COLOR32 cl = alpha ? getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)])*255/alpha : 0;
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ bits[(i+y)*width + (j+x)] = (cl > 128) ?
+ rgba(
+ PU_DIV255((koef1r * cl + br)*alpha),
+ PU_DIV255((koef1g * cl + bg)*alpha),
+ PU_DIV255((koef1b * cl + bb)*alpha),
+ alpha):
+ rgba(
+ PU_DIV255(koef2r * cl * alpha),
+ PU_DIV255(koef2g * cl * alpha),
+ PU_DIV255(koef2b * cl * alpha),
+ alpha);
+#pragma warning(pop)
+// bits[(i+y)*width + (j+x)] = (cl > 128) ?
+// rgba(koef1r * cl + br, koef1g * cl + bg, koef1b * cl + bb, geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)])):
+// rgba(koef2r * cl, koef2g * cl, koef2b * cl, geta(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]));
+ }
+ }
+}
+
+void MyBitmap::BlendPart(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+ if (!win || !hin) return;
+
+ GdiFlush();
+
+ if (!w) w = win;
+ if (!h) h = hin;
+ float kx = (float)win / w;
+ float ky = (float)hin / h;
+
+ if (x+w >= this->getWidth())
+ w = this->getWidth() - x;
+ if (y+h >= this->getHeight())
+ h = this->getHeight() - y;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ COLOR32 src = bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)];
+ COLOR32 dst = bits[(i+y)*width + (j+x)];
+ long alpha = geta(src);
+ bits[(i+y)*width + (j+x)] = rgba(
+ getr(src)+PU_DIV255((255-alpha)*getr(dst)),
+ getg(src)+PU_DIV255((255-alpha)*getg(dst)),
+ getb(src)+PU_DIV255((255-alpha)*getb(dst)),
+ geta(src)+PU_DIV255((255-alpha)*geta(dst))
+ );
+// bits[(i+y)*width + (j+x)] = bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)];
+ }
+ }
+}
+
+void MyBitmap::BlendPartColorized(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h, COLOR32 color)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+ if (!win || !hin) return;
+
+ GdiFlush();
+
+ if (!w) w = win;
+ if (!h) h = hin;
+ float kx = (float)win / w;
+ float ky = (float)hin / h;
+
+ if (x+w >= this->getWidth())
+ w = this->getWidth() - x;
+ if (y+h >= this->getHeight())
+ h = this->getHeight() - y;
+
+ // we should swap B and R channels when working with win32 COLORREF
+ float koef1r = (255 - getb(color)) / 128.0f;
+ float koef1g = (255 - getg(color)) / 128.0f;
+ float koef1b = (255 - getr(color)) / 128.0f;
+
+ int br = - 255 + 2 * getb(color);
+ int bg = - 255 + 2 * getg(color);
+ int bb = - 255 + 2 * getr(color);
+
+ float koef2r = (getb(color)) / 128.0f;
+ float koef2g = (getg(color)) / 128.0f;
+ float koef2b = (getr(color)) / 128.0f;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+
+ long alpha = geta(bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)]);
+// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+ COLOR32 cl = alpha ? getr(bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)])*255/alpha : 0;
+#pragma warning(push)
+#pragma warning(disable: 4244)
+ COLOR32 src = (cl > 128) ?
+ rgba(
+ PU_DIV255((koef1r * cl + br)*alpha),
+ PU_DIV255((koef1g * cl + bg)*alpha),
+ PU_DIV255((koef1b * cl + bb)*alpha),
+ alpha):
+ rgba(
+ PU_DIV255(koef2r * cl * alpha),
+ PU_DIV255(koef2g * cl * alpha),
+ PU_DIV255(koef2b * cl * alpha),
+ alpha);
+#pragma warning(pop)
+// COLOR32 cl = getr(bmp->bits[int(i*ky)*bmp->width + int(j*kx)]);
+// COLOR32 src = (cl > 128) ?
+// rgba(koef1r * cl + br, koef1g * cl + bg, koef1b * cl + bb, alpha):
+// rgba(koef2r * cl, koef2g * cl, koef2b * cl, alpha);
+ COLOR32 dst = bits[(i+y)*width + (j+x)];
+// long alpha = geta(src);
+ bits[(i+y)*width + (j+x)] = rgba(
+ getr(src)+PU_DIV255((255-alpha)*getr(dst)),
+ getg(src)+PU_DIV255((255-alpha)*getg(dst)),
+ getb(src)+PU_DIV255((255-alpha)*getb(dst)),
+ geta(src)+PU_DIV255((255-alpha)*geta(dst))
+ );
+
+/* COLOR32 src = bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)];
+ COLOR32 dst = bits[(i+y)*width + (j+x)];
+ long alpha = geta(src);
+ bits[(i+y)*width + (j+x)] = rgba(
+ getr(src)+(255-alpha)*getr(dst)/255,
+ getg(src)+(255-alpha)*getg(dst)/255,
+ getb(src)+(255-alpha)*getb(dst)/255,
+ geta(src)+(255-alpha)*geta(dst)/255
+ );*/
+// bits[(i+y)*width + (j+x)] = bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)];
+ }
+ }
+}
+
+void MyBitmap::DrawPart(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+ if (!win || !hin) return;
+
+ GdiFlush();
+
+ if (!w) w = win;
+ if (!h) h = hin;
+ float kx = (float)win / w;
+ float ky = (float)hin / h;
+
+ if (x+w >= this->getWidth())
+ w = this->getWidth() - x;
+ if (y+h >= this->getHeight())
+ h = this->getHeight() - y;
+
+ for (int i = 0; i < h; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < w; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ bits[(i+y)*width + (j+x)] = bmp->bits[int(yin+i*ky)*bmp->width + int(xin+j*kx)];
+ }
+ }
+}
+
+void MyBitmap::DrawNoAlpha(MyBitmap *bmp, int x, int y, int w, int h)
+{
+ if (!(bits && bmp && bmp->bits)) return;
+
+ GdiFlush();
+
+ for (int i = 0; i < bmp->height; i++)
+ {
+ if (i+y < 0) continue;
+ if (i+y >= height) break;
+ for (int j = 0; j < bmp->width; j++)
+ {
+ if (j+x < 0) continue;
+ if (j+x >= width) break;
+ bits[(i+y)*width + (j+x)] = bmp->bits[i*bmp->width + j];
+ }
+ }
+}
+
+static __forceinline int ReadP(long *p, int w, int h, int x, int y, int k)
+{
+ if (x<0) x=0; else if (x>=w) x=w-1;
+ if (y<0) y=0; else if (y>=h) y=h-1;
+ return p[(x+y*w)*4+k];
+}
+
+void MyBitmap::Blur(int w, int h)
+{
+ if ((w <= 0) || (h <= 0)) return;
+
+ BYTE *buf_src = new BYTE[width*height*4];
+ long *buf_tmp = new long[width*height*4];
+ BYTE *buf_dst = (BYTE *)bits;
+ memcpy(buf_src, buf_dst, width*height*4);
+
+ BYTE *src, *dst;
+ long *tmp;
+
+ src = buf_src;
+ tmp = buf_tmp;
+ dst = buf_dst;
+
+ int y;
+
+ for (y = 0; y < height; ++y)
+ {
+ for (int x = 0; x < width; ++x)
+ {
+ for (int k = 0; k < 4; ++k)
+ {
+ int tot = src[0];
+ if (x > 0) tot += tmp[-4];
+ if (y > 0) tot += tmp[-width*4];
+ if (x > 0 && y > 0) tot -= tmp[-(width+1)*4];
+ *tmp = tot;
+
+ ++src;
+ ++tmp;
+ }
+ }
+ }
+
+ src = buf_src;
+ tmp = buf_tmp;
+ dst = buf_dst;
+
+ float mul = 1.f/((w*2+1)*(h*2+1));
+ for (y=0;y<height;y++)
+ {
+ for (int x=0;x<width;x++)
+ {
+ for (int k = 0; k < 4; ++k)
+ {
+ int tot = ReadP(tmp,width,height,x+w,y+h,k) +
+ ReadP(tmp,width,height,x-w,y-h,k) -
+ ReadP(tmp,width,height,x-w,y+h,k) -
+ ReadP(tmp,width,height,x+w,y-h,k);
+
+ *dst = BYTE(tot*mul);
+
+ ++dst;
+ ++src;
+ }
+ }
+ }
+
+ delete [] buf_src;
+ delete [] buf_tmp;
+}
+
+void MyBitmap::IncreaseAlpha(float q)
+{
+ BYTE *p = (BYTE *)bits;
+
+ for (int i = 0; i < height; ++i)
+ {
+ for (int j = 0; j < width; ++j)
+ {
+ if (!p[3])
+ {
+ p += 4;
+ continue;
+ }
+
+ float q1 = min(q, 255.f/p[3]);
+
+ for (int k = 0; k < 4; ++k)
+ {
+ *p = (BYTE)min(255, *p * q1);
+ ++p;
+ }
+ }
+ }
+}
+
+void MyBitmap::DrawIcon(HICON hic, int x, int y, int w, int h)
+{
+ GdiFlush();
+
+ ICONINFO info;
+ GetIconInfo(hic, &info);
+
+ BITMAP bmpColor, bmpMask;
+ GetObject(info.hbmMask, sizeof(bmpMask), &bmpMask);
+ GetObject(info.hbmColor, sizeof(bmpColor), &bmpColor);
+
+ if (!w) w = abs(bmpMask.bmWidth);
+ if (!h) h = abs(bmpMask.bmHeight);
+
+ if (bmpColor.bmBitsPixel == 32)
+ {
+ if ((w != abs(bmpMask.bmWidth)) || (h != abs(bmpMask.bmHeight)))
+ {
+ DeleteObject(info.hbmColor);
+ DeleteObject(info.hbmMask);
+ HICON hicTmp = (HICON)CopyImage(hic,IMAGE_ICON,w,h,LR_COPYFROMRESOURCE);
+ GetIconInfo(hicTmp, &info);
+ GetObject(info.hbmMask, sizeof(bmpMask), &bmpMask);
+ GetObject(info.hbmColor, sizeof(bmpColor), &bmpColor);
+ DestroyIcon(hicTmp);
+ }
+
+ BYTE *cbit = new BYTE[bmpColor.bmWidthBytes*bmpColor.bmHeight];
+ BYTE *mbit = new BYTE[bmpMask.bmWidthBytes*bmpMask.bmHeight];
+ GetBitmapBits(info.hbmColor, bmpColor.bmWidthBytes*bmpColor.bmHeight, cbit);
+ GetBitmapBits(info.hbmMask, bmpMask.bmWidthBytes*bmpMask.bmHeight, mbit);
+
+ for (int i = 0; i < bmpColor.bmHeight; i++)
+ {
+ for (int j = 0; j < bmpColor.bmWidth; j++)
+ {
+ BYTE *pixel = cbit + i*bmpColor.bmWidthBytes + j*4;
+ if (!pixel[3])
+ {
+ pixel[3] = (*(mbit + i*bmpMask.bmWidthBytes + j*bmpMask.bmBitsPixel/8) & (1<<(7-j%8))) ? 0 : 255;
+ }
+
+ if (pixel[3] != 255)
+ {
+ pixel[0] = PU_DIV255(pixel[0] * pixel[3]);
+ pixel[1] = PU_DIV255(pixel[1] * pixel[3]);
+ pixel[2] = PU_DIV255(pixel[2] * pixel[3]);
+ }
+ }
+ }
+
+ this->BlendBits((COLOR32 *)cbit, bmpColor.bmWidth, bmpColor.bmHeight, x, y, w, h);
+
+ delete [] mbit;
+ delete [] cbit;
+ } else
+ {
+ this->saveAlpha(x,y,w,h);
+ DrawIconEx(this->getDC(), x, y, hic, w, h, 0, NULL, DI_NORMAL);
+ this->restoreAlpha(x,y,w,h);
+ }
+
+ DeleteObject(info.hbmColor);
+ DeleteObject(info.hbmMask);
+}
+
+//Base on code by Artem Shpynov
+//from clist_modern plugin
+//slightly modified and integrated to MyBitmap class
+void MyBitmap::DrawText(TCHAR *str, int x, int y, int blur, int strength)
+{
+ SIZE sz; GetTextExtentPoint32(this->getDC(), str, lstrlen(str), &sz);
+ sz.cx += (blur+2)*2; sz.cy += (blur+2)*2;
+ x -= blur+2; y -= blur+2;
+
+ static BYTE pbGammaWeight[256]={0};
+ static BOOL bGammaWeightFilled=FALSE;
+
+ if (!bGammaWeightFilled)
+ {
+ int i;
+ for(i=0;i<256;i++)
+ {
+ double f;
+ double gamma=(double)700/1000;
+
+ f=(double)i/255;
+ f=pow(f,(1/gamma));
+
+ pbGammaWeight[i]=(BYTE)(255*f);
+ }
+ bGammaWeightFilled=1;
+ }
+
+ MyBitmap tmp(sz.cx, sz.cy);
+ HFONT hfnTmp = (HFONT)SelectObject(tmp.getDC(), GetCurrentObject(this->getDC(), OBJ_FONT));
+
+ RECT rc; SetRect(&rc, 0, 0, sz.cx, sz.cy);
+ SetTextColor(tmp.getDC(), RGB(255,255,255));
+ SetBkColor(tmp.getDC(), RGB(0,0,0));
+ ExtTextOutA(tmp.getDC(), 0, 0, ETO_OPAQUE, &rc, "", 0, NULL);
+ ::DrawText(tmp.getDC(), str, lstrlen(str), &rc, DT_CENTER|DT_NOPREFIX|DT_SINGLELINE|DT_VCENTER);
+ SelectObject(tmp.getDC(), hfnTmp);
+
+ GdiFlush();
+
+ if (blur)
+ {
+ for (int i = 0; i < sz.cy; i++)
+ {
+ COLOR32 *row_src = tmp.bits + i * tmp.width;
+
+ for (int j = 0; j < sz.cx; j++)
+ {
+ COLOR32 cl = row_src[j];
+ if (!cl) continue;
+
+ int a1 = (getr(cl) + getg(cl) + getb(cl)) / 3;
+ row_src[j] = rgba(a1, a1, a1, a1);
+ }
+ }
+ tmp.Blur(blur, blur);
+ tmp.IncreaseAlpha((float)(strength ? strength : blur));
+ }
+
+ // use Get*Value for COLORREF and get* for COLOR32
+ COLOR32 textColor = GetTextColor(this->getDC());
+ COLOR32 r = GetRValue(textColor);
+ COLOR32 g = GetGValue(textColor);
+ COLOR32 b = GetBValue(textColor);
+
+ int minx = max(0,-x);
+ int miny = max(0,-y);
+ int maxx = min(sz.cx, width-x);
+ int maxy = min(sz.cy, height-y);
+
+ for (int i = miny; i < maxy; i++)
+ {
+ COLOR32 *row_dst = bits + (i+y) * width + x;
+ COLOR32 *row_src = tmp.bits + i * tmp.width;
+
+ for (int j = minx; j < maxx; j++)
+ {
+ COLOR32 bx,rx,gx,mx;
+ {
+ bx=pbGammaWeight[getb(row_src[j])];
+ gx=pbGammaWeight[getg(row_src[j])];
+ rx=pbGammaWeight[getr(row_src[j])];
+ }
+
+ bx=(pbGammaWeight[bx]*(255-b)+bx*(b))/255;
+ gx=(pbGammaWeight[gx]*(255-g)+gx*(g))/255;
+ rx=(pbGammaWeight[rx]*(255-r)+rx*(r))/255;
+
+ mx=(BYTE)(max(max(bx,rx),gx));
+
+ if (1)
+ {
+ bx=(bx<mx)?(BYTE)(((WORD)bx*7+(WORD)mx)>>3):bx;
+ rx=(rx<mx)?(BYTE)(((WORD)rx*7+(WORD)mx)>>3):rx;
+ gx=(gx<mx)?(BYTE)(((WORD)gx*7+(WORD)mx)>>3):gx;
+ // reduce boldeness at white fonts
+ }
+ COLOR32 cl = row_dst[j];
+ if (mx)
+ {
+ COLOR32 rrx,grx,brx;
+ COLOR32 rlx,glx,blx;
+ COLOR32 axx=geta(cl);
+ COLOR32 mmx=(bx+gx+rx)/3;
+ COLOR32 nx=mmx;;//pbGammaWeight[mx];//
+ {
+ //Normalize components to alpha level
+ bx=(nx*(255-axx)+bx*axx)/255;
+ gx=(nx*(255-axx)+gx*axx)/255;
+ rx=(nx*(255-axx)+rx*axx)/255;
+ mx=(nx*(255-axx)+mmx*axx)/255;
+ }
+ {
+ blx = getb(cl);
+ glx = getg(cl);
+ rlx = getr(cl);
+
+ brx=(b-blx)*bx/255;
+ grx=(g-glx)*gx/255;
+ rrx=(r-rlx)*rx/255;
+ row_dst[j] = rgba(rlx+rrx, glx+grx, blx+brx, mx+(255-mx)*axx/255);
+ }
+ }
+ }
+ }
+}
+
+// based on code by Yuriy Zaporozhets from:
+// http://www.codeproject.com/gdi/coolrgn.asp?df=100&forumid=739&exp=0&select=6341
+// slightly modified to integrate with MyBitmap class.
+HRGN MyBitmap::buildOpaqueRgn(int level, bool opaque)
+{
+ GdiFlush();
+
+ const int addRectsCount = 64;
+ int rectsCount = addRectsCount;
+ PRGNDATA pRgnData = (PRGNDATA)(new BYTE[sizeof(RGNDATAHEADER) + (rectsCount)*sizeof(RECT)]);
+ LPRECT pRects = (LPRECT)(&pRgnData->Buffer);
+
+ memset(pRgnData, 0, sizeof(RGNDATAHEADER) + (rectsCount)*sizeof(RECT));
+ pRgnData->rdh.dwSize = sizeof(RGNDATAHEADER);
+ pRgnData->rdh.iType = RDH_RECTANGLES;
+
+ int first = 0;
+ bool wasfirst = false;
+ bool ismask = false;
+ for (int i = 0; i < height; i++)
+ {
+ int j; // we will need j after the loop!
+ for (j = 0; j < width; j++)
+ {
+ ismask = opaque ? (int)geta(this->getRow(i)[j]) > level : (int)geta(this->getRow(i)[j]) < level;
+ if (wasfirst)
+ {
+ if (!ismask)
+ {
+ SetRect(&pRects[pRgnData->rdh.nCount++], first, i, j, i+1);
+ if ((int)(pRgnData->rdh.nCount) >= rectsCount)
+ {
+ rectsCount += addRectsCount;
+ LPRGNDATA pRgnDataNew = (LPRGNDATA)(new BYTE[sizeof(RGNDATAHEADER) + (rectsCount)*sizeof(RECT)]);
+ memcpy(pRgnDataNew, pRgnData, sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount * sizeof(RECT));
+ delete pRgnData;
+ pRgnData = pRgnDataNew;
+ pRects = (LPRECT)(&pRgnData->Buffer);
+ }
+ wasfirst = false;
+ }
+ } else
+ if (ismask) // set wasfirst when mask is found
+ {
+ first = j;
+ wasfirst = true;
+ }
+ }
+
+ if (wasfirst && ismask)
+ {
+ SetRect(&pRects[pRgnData->rdh.nCount++], first, i, j, i+1);
+ if ((int)(pRgnData->rdh.nCount) >= rectsCount)
+ {
+ rectsCount += addRectsCount;
+ LPRGNDATA pRgnDataNew = (LPRGNDATA)(new BYTE[sizeof(RGNDATAHEADER) + (rectsCount)*sizeof(RECT)]);
+ memcpy(pRgnDataNew, pRgnData, sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount * sizeof(RECT));
+ delete pRgnData;
+ pRgnData = pRgnDataNew;
+ pRects = (LPRECT)(&pRgnData->Buffer);
+ }
+ wasfirst = false;
+ }
+
+ }
+
+ HRGN hRgn = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount*sizeof(RECT), (LPRGNDATA)pRgnData);
+ delete pRgnData;
+ return hRgn;
+}
+
+static int hex2dec(char hex)
+{
+ if ((hex >= '0') && (hex <= '9'))
+ return hex - '0';
+ if ((hex >= 'a') && (hex <= 'f'))
+ return hex - 'a' + 0xa;
+ if ((hex >= 'A') && (hex <= 'F'))
+ return hex - 'A' + 0xa;
+ return 0;
+}
+
+bool MyBitmap::loadFromFile_pixel(const char *fn, const char *fnAlpha)
+{
+ allocate(1,1);
+ int r, g, b, a=255;
+ const char *p = fn + lstrlenA("pixel:");
+ r = (hex2dec(p[0]) << 4) + hex2dec(p[1]);
+ g = (hex2dec(p[2]) << 4) + hex2dec(p[3]);
+ b = (hex2dec(p[4]) << 4) + hex2dec(p[5]);
+ *bits = rgba(r,g,b,a);
+ return true;
+}
+
+bool MyBitmap::loadFromFile_gradient(const char *fn, const char *fnAlpha)
+{
+ const char *p = fn + lstrlenA("gradient:");
+
+ if (*p == 'h') allocate(256,1);
+ else allocate(1,256);
+
+ int r, g, b, a=255;
+
+ p += 2;
+ r = (hex2dec(p[0]) << 4) + hex2dec(p[1]);
+ g = (hex2dec(p[2]) << 4) + hex2dec(p[3]);
+ b = (hex2dec(p[4]) << 4) + hex2dec(p[5]);
+ COLOR32 from = rgba(r,g,b,a);
+
+ p += 7;
+ r = (hex2dec(p[0]) << 4) + hex2dec(p[1]);
+ g = (hex2dec(p[2]) << 4) + hex2dec(p[3]);
+ b = (hex2dec(p[4]) << 4) + hex2dec(p[5]);
+ COLOR32 to = rgba(r,g,b,a);
+
+ for (int i = 0; i < 256; ++i)
+ {
+ bits[i] = rgba(
+ ((255-i) * getr(from) + i * getr(to)) / 255,
+ ((255-i) * getg(from) + i * getg(to)) / 255,
+ ((255-i) * getb(from) + i * getb(to)) / 255,
+ 255
+ );
+ }
+
+ return true;
+}
+
+bool MyBitmap::loadFromFile_png(const char *fn, const char *fnAlpha)
+{
+ if (ServiceExists(MS_PNG2DIB))
+ {
+ HANDLE hFile, hMap = 0;
+ BYTE *ppMap = 0;
+ long cbFileSize = 0;
+ BITMAPINFOHEADER *pDib;
+ BYTE *pDibBits;
+ if ((hFile = CreateFileA(fn, 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)
+ {
+ 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) UnmapViewOfFile(ppMap);
+ if (hMap) CloseHandle(hMap);
+ if (hFile) CloseHandle(hFile);
+
+ if (!cbFileSize) return false;
+
+ BITMAPINFO *bi=(BITMAPINFO*)pDib;
+ BYTE *pt=(BYTE*)bi;
+ pt+=bi->bmiHeader.biSize;
+
+ if (bi->bmiHeader.biBitCount != 32)
+ {
+ allocate(abs(bi->bmiHeader.biWidth), abs(bi->bmiHeader.biHeight));
+ HDC hdcTmp = CreateCompatibleDC(getDC());
+ HBITMAP hBitmap = CreateDIBitmap(getDC(), pDib, CBM_INIT, pDibBits, bi, DIB_PAL_COLORS);
+ SelectObject(hdcTmp, hBitmap);
+ BitBlt(this->getDC(), 0, 0, abs(bi->bmiHeader.biWidth), abs(bi->bmiHeader.biHeight), hdcTmp, 0, 0, SRCCOPY);
+ this->makeOpaque();
+ DeleteDC(hdcTmp);
+ DeleteObject(hBitmap);
+ } else
+ {
+ allocate(abs(bi->bmiHeader.biWidth), abs(bi->bmiHeader.biHeight));
+ BYTE *p2=(BYTE *)pt;
+ for (int y=0; y<bi->bmiHeader.biHeight; ++y)
+ {
+ BYTE *p1=(BYTE *)bits + (bi->bmiHeader.biHeight-y-1)*bi->bmiHeader.biWidth*4;
+ for (int x=0; x<bi->bmiHeader.biWidth; ++x)
+ {
+ p1[0]= p2[0];
+ p1[1]= p2[1];
+ p1[2]= p2[2];
+ p1[3]= p2[3];
+ p1 += 4;
+ p2 += 4;
+ }
+ }
+// memcpy(bits, pt, bi->bmiHeader.biSizeImage);
+ premultipleChannels();
+ }
+
+ GlobalFree(pDib);
+ return true;
+ } else
+ {
+// MessageBox(NULL, Translate("You need the png2dib plugin v. 0.1.3.x or later to process PNG images"), Translate("Error"), MB_OK);
+ return false;
+ }
+}
+
+bool MyBitmap::loadFromFile_default(const char *fn, const char *fnAlpha)
+{
+ SIZE sz;
+ HBITMAP hBmpLoaded = (HBITMAP)LoadImageA(NULL, fn, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
+ if (!hBmpLoaded)
+ return false;
+
+ BITMAP bm; GetObject(hBmpLoaded, sizeof(bm), &bm);
+ SetBitmapDimensionEx(hBmpLoaded, bm.bmWidth, bm.bmHeight, NULL);
+
+ HDC dcTmp = CreateCompatibleDC(0);
+ GetBitmapDimensionEx(hBmpLoaded, &sz);
+ HBITMAP hBmpDcSave = (HBITMAP)SelectObject(dcTmp, hBmpLoaded);
+
+ allocate(sz.cx, sz.cy);
+ BitBlt(dcBmp, 0, 0, width, height, dcTmp, 0, 0, SRCCOPY);
+
+ DeleteObject(SelectObject(dcTmp, hBmpDcSave));
+ DeleteDC(dcTmp);
+
+ MyBitmap alpha;
+ if (fnAlpha && alpha.loadFromFile(fnAlpha) &&
+ (alpha.getWidth() == width) &&
+ (alpha.getHeight() == height) )
+ {
+ for (int i = 0; i < width*height; i++)
+ bits[i] = (bits[i] & 0x00ffffff) | ( (alpha.bits[i] & 0x000000ff) << 24 );
+ premultipleChannels();
+ } else
+ {
+ makeOpaque();
+ }
+ return true;
+}
+
+bool MyBitmap::loadFromFile(const char *fn, const char *fnAlpha)
+{
+ if (bits) free();
+
+ if (!strncmp(fn, "pixel:", lstrlenA("pixel:")))
+ {
+ return loadFromFile_pixel(fn, fnAlpha);
+ } else
+ if (!strncmp(fn, "gradient:", lstrlenA("gradient:")))
+ {
+ return loadFromFile_gradient(fn, fnAlpha);
+ } else
+ {
+ char ext[5];
+ memcpy(ext,fn+(strlen(fn)-4),5);
+ if (!lstrcmpiA(ext,".png"))
+ {
+ return loadFromFile_png(fn, fnAlpha);
+ } else
+ {
+ return loadFromFile_default(fn, fnAlpha);
+ }
+ }
+ // unreachable place
+ return false;
+}
+
+void MyBitmap::allocate(int w, int h)
+{
+ if (dcBmp && (width == w) && (height == h)) return;
+
+ width = w;
+ height = h;
+
+ BITMAPINFO bi;
+
+ bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
+ bi.bmiHeader.biWidth = w;
+ bi.bmiHeader.biHeight = -h;
+ bi.bmiHeader.biPlanes = 1;
+ bi.bmiHeader.biBitCount = 32;
+ bi.bmiHeader.biCompression = BI_RGB;
+
+ if (dcBmp)
+ {
+ DeleteObject(SelectObject(dcBmp, hBmpSave));
+ DeleteDC(dcBmp);
+ }
+
+ hBmp = (HBITMAP)CreateDIBSection(0, &bi, DIB_RGB_COLORS, (void **)&bits, 0, 0);
+ dcBmp = CreateCompatibleDC(0);
+ hBmpSave = (HBITMAP)SelectObject(dcBmp, hBmp);
+
+ GdiFlush();
+}
+
+void MyBitmap::free()
+{
+ GdiFlush();
+
+ DeleteObject(SelectObject(dcBmp, hBmpSave));
+ DeleteDC(dcBmp);
+
+ dcBmp = 0;
+ hBmp = 0;
+ bits = 0;
+ width = height = 0;
+}
+
+void MyBitmap::premultipleChannels()
+{
+ GdiFlush();
+
+ for (int i = 0; i < width*height; i++)
+ bits[i] = rgba(getr(bits[i])*geta(bits[i])/255, getg(bits[i])*geta(bits[i])/255, getb(bits[i])*geta(bits[i])/255, geta(bits[i]));
+}
diff --git a/plugins/FloatingContacts/bitmap_funcs.h b/plugins/FloatingContacts/bitmap_funcs.h
new file mode 100644
index 0000000000..b7f55a43d7
--- /dev/null
+++ b/plugins/FloatingContacts/bitmap_funcs.h
@@ -0,0 +1,127 @@
+/*
+Popup Plus plugin for Miranda IM
+
+Copyright 2002 Luca Santarelli,
+ 2004-2007 Victor Pavlychko
+
+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 __bitmap_funcs_h__
+#define __bitmap_funcs_h__
+
+// This should make bitmap manipulations much easier...
+class MyBitmap
+{
+public:
+ typedef unsigned long COLOR32;
+ static inline COLOR32 RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a = 0xff)
+ {
+ return (a << 24) | (r << 16) | (g << 8) | b;
+ };
+
+private:
+ HBITMAP hBmpSave, hBmp;
+ HDC dcBmp;
+ COLOR32 *bits;
+ COLOR32 *bitsSave;
+ int width, height;
+
+ void free();
+
+ bool loadFromFile_pixel(const char *fn, const char *fnAlpha = 0);
+ bool loadFromFile_gradient(const char *fn, const char *fnAlpha = 0);
+ bool loadFromFile_png(const char *fn, const char *fnAlpha = 0);
+ bool loadFromFile_default(const char *fn, const char *fnAlpha = 0);
+ void premultipleChannels();
+
+public:
+ MyBitmap();
+ MyBitmap(int w, int h);
+ MyBitmap(const char *fn, const char *fnAlpha = 0);
+ ~MyBitmap();
+ void allocate(int w, int h);
+
+ bool loadFromFile(const char *fn, const char *fnAlpha = 0);
+
+ int getWidth() { return width; }
+ int getHeight() { return height; }
+
+ HDC getDC() { return dcBmp; }
+ HBITMAP getBitmap() { return hBmp; }
+
+ void setAlpha(BYTE level);
+ void setAlphaRect(int x1, int y1, int x2, int y2, BYTE level);
+ void setAlphaRect(RECT rc, BYTE level) { setAlphaRect(rc.left, rc.top, rc.right, rc.bottom, level); }
+
+ void makeOpaque();
+ void makeOpaqueRect(int x1, int y1, int x2, int y2);
+ void makeOpaqueRect(RECT rc) { makeOpaqueRect(rc.left, rc.top, rc.right, rc.bottom); }
+
+ void saveAlpha(int x = 0, int y = 0, int w = 0, int h = 0);
+ void restoreAlpha(int x = 0, int y = 0, int w = 0, int h = 0);
+
+ void DrawBits(COLOR32 *inbits, int inw, int inh, int x, int y, int w, int h);
+ void BlendBits(COLOR32 *inbits, int inw, int inh, int x, int y, int w, int h);
+
+ void DrawNoAlpha(MyBitmap *bmp, int x, int y, int w, int h);
+
+ void Blend(MyBitmap *bmp, int x, int y, int w, int h);
+ void Draw(MyBitmap *bmp, int x, int y, int w, int h);
+
+ void BlendColorized(MyBitmap *bmp, int x, int y, int w, int h, COLOR32 color);
+ void DrawColorized(MyBitmap *bmp, int x, int y, int w, int h, COLOR32 color);
+
+ void BlendPart(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h);
+ void BlendPartColorized(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h, COLOR32 color);
+ void DrawPart(MyBitmap *bmp, int xin, int yin, int win, int hin, int x, int y, int w, int h);
+// void DrawPartNoAlpha(MyBitmap *bmp, int x, int y, int w, int h);
+// void DrawPartColorized(MyBitmap *bmp, int x, int y, int w, int h, COLOR32 color);
+
+ void Blur(int w, int h);
+ void IncreaseAlpha(float q);
+
+ void DrawIcon(HICON hic, int x, int y, int w = 0, int h = 0);
+ void DrawText(TCHAR *str, int x, int y, int blur=0, int strength = 0);
+
+ __forceinline COLOR32 *getBits() { return bits; }
+ __forceinline COLOR32 *getRow(int row) { return bits + row * width; }
+ __forceinline COLOR32 *operator[] (int row) { return bits + row * width; }
+
+ static __forceinline COLOR32 rgba(COLOR32 r, COLOR32 g, COLOR32 b, COLOR32 a)
+ {
+ return ((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
+ }
+ static __forceinline COLOR32 getr(COLOR32 c)
+ {
+ return (c >> 16) & 0xff;
+ }
+ static __forceinline COLOR32 getg(COLOR32 c)
+ {
+ return (c >> 8) & 0xff;
+ }
+ static __forceinline COLOR32 getb(COLOR32 c)
+ {
+ return c & 0xff;
+ }
+ static __forceinline COLOR32 geta(COLOR32 c)
+ {
+ return (c >> 24) & 0xff;
+ }
+
+ HRGN buildOpaqueRgn(int level = 64, bool opaque = true);
+};
+
+#endif // __bitmap_funcs_h__
diff --git a/plugins/FloatingContacts/docs/fltcontacts_langpack.txt b/plugins/FloatingContacts/docs/fltcontacts_langpack.txt
new file mode 100644
index 0000000000..4aba1cd0db
--- /dev/null
+++ b/plugins/FloatingContacts/docs/fltcontacts_langpack.txt
@@ -0,0 +1,68 @@
+;============================================================
+; Module: fltcontacts.dll
+; Plugin: Floating ontacts
+; Versions: 0.1.1.9
+; URL: http://www.miranda-im.org/
+;============================================================
+
+[Floating Contacts]
+
+
+;Menu
+[Remove thumb]
+
+[Hide all thumbs]
+
+[Show all thumbs]
+
+
+;Hotkeys
+[Show/Hide all thumbs]
+
+
+;Properties
+;Main Features
+[Main Features]
+
+[Hiding contacts]
+
+[Hide offline contacts]
+
+[Hide all contacts]
+
+[Hide when a fulscreen app is active]
+
+[Hide when contact list is shown]
+
+[Stick together]
+
+[Use fixed width]
+
+[Show tooltips]
+
+[Miscellaneous]
+
+[0 = Default]
+
+[requires mToolTip or Tipper plugin]
+
+[Bring to front]
+
+[Bring to front every]
+
+
+;Appearance
+[<Contact List Text>]
+
+[Opacity:]
+
+[Floating Contacts Background]
+
+[Draw border]
+
+[Left-top edges color:]
+
+[Right-bottom eges color:]
+
+
+;End (Floating ontacts) \ No newline at end of file
diff --git a/plugins/FloatingContacts/docs/fltcontacts_readme.txt b/plugins/FloatingContacts/docs/fltcontacts_readme.txt
new file mode 100644
index 0000000000..b62a9c7ff6
--- /dev/null
+++ b/plugins/FloatingContacts/docs/fltcontacts_readme.txt
@@ -0,0 +1,91 @@
+******************
+Floating Contacts
+******************
+
+Description
+===========
+This plugin is further development of Floating contacts plugin v1.0.0.7 from Iavor Vajarov (thx).
+
+New features
+************
+- Showing a tooltip when mouse's hovering over a floating contact's window.
+- Support MUID inteface of Miranda v0.8.0.0 and higher.
+- Unicode aware.
+- True alpha channel support on windows 2000+.
+- "Bring to front" feature allows bring to front floating windows every x seconds.
+ With a lot of window may get backside effect, in this case set greater interval.
+- And various other features.
+
+Requirements
+************
+- Miranda v0.6.0.0 or higher.
+- Tipper or mToolTip plugin for tooltip show.
+
+Changelog
+=========
+
++ Relative coordinates.
+
+---1.0.2.2---
+! Fixed gdi leak.
+! Fixed possible crash.
+! Fixed drawing 8-bit status icons.
+! Show floating contacts on startup when "Hide when contact list is shown" option is checked.
+
+---1.0.2.1---
+! Wrong detection of hiding CList behind display border.
+* Changed "Mouse In" highlight (must resolve some problem).
+! Fixed "Single click" feature.
+! Fixed memory leak.
+
+----1.0.2.0---
++ True alpha channel support on windows 2000+.
+! Minor fixed.
+* Converted to C++.
+
+----1.0.1.1---
++ Added "Dim idle contacts" feature.
+! Fixed menu.
+* Updated icons (added 256 colors icons).
+* Changed painting.
+* Changed moving.
+
+----1.0.1.0---
++ Unicode aware.
++ Added russian langpack.
+* Updated langpack.
+! Fixed showing of nicks, containing "&".
++ Added feature "Single click interface".
++ Added hotkeys for "Show/Hide all thumbs" and "Hide when contact list is showing".
+! Fixed refresh icon.
++ Added "Hide when contact list is showing" feature.
+
+----1.0.0.9---
+! Fixed show of floating contact's windows if check "Hide all contacts".
++ Added "Bring to front" feature. The feature provide keeping floating contact's windows on top.
+* Unified plugin name in service, db setting and db contacts settings.
+ To keep your old settings just rename module settings branch "Floating contacts" in database to "FloatingContacts" (use DBE++).
+! Fixed font size.
+* Reformed options.
+- Deleted support Miranda version lower then 0.6.0.0.
++ Added MUID.
+* New icons.
+
+----1.0.0.8---
+! Fixed coordinate floating contact's window when it is dragged.
+! Fixed name change.
++ Added showing of tooltip when mouse's hovering over a floating contact's window (requires Tipper or mToolTip plugin).
+
+Symbols used in changelog
+--------------
++ : new feature
+* : changed
+! : bufgix
+- : feature removed or disabled because of pending bugs
+--------------
+
+Author
+======
+Created by Iavor Vajarov ( ivajarov <at> code <dot> bg ).
+Further development by Kosh&chka ( ell-6 <at> ya <dot> ru ).
+
diff --git a/plugins/FloatingContacts/docs/fltcontacts_russian_langpack.txt b/plugins/FloatingContacts/docs/fltcontacts_russian_langpack.txt
new file mode 100644
index 0000000000..2ae3442f7a
--- /dev/null
+++ b/plugins/FloatingContacts/docs/fltcontacts_russian_langpack.txt
@@ -0,0 +1,70 @@
+;============================================================
+; Module: fltcontacts.dll
+; Plugin: Floating ontacts
+; Versions: 0.1.1.9
+; Translators: SAOPP
+; URL: http://www.miranda-im.org/
+;============================================================
+[Floating Contacts]
+
+
+;Menu
+[Remove thumb]
+
+[Hide all thumbs]
+
+[Show all thumbs]
+
+
+;Hotkeys
+[Show/Hide all thumbs]
+/
+
+;Properties
+;Main Features
+[Main Features]
+
+[Hiding contacts]
+
+[Hide offline contacts]
+
+[Hide all contacts]
+
+[Hide when a fulscreen app is active]
+
+[Hide when contact list is shown]
+
+[Stick together]
+
+[Use fixed width]
+
+[Show tooltips]
+
+[Miscellaneous]
+
+[0 = Default]
+0=
+[requires mToolTip or Tipper plugin]
+ mToolTip Tipper
+[Bring to front]
+
+[Bring to front every]
+
+
+;Appearance
+[<Contact List Text>]
+
+[Opacity:]
+:
+[Floating Contacts Background]
+ :
+[Draw border]
+
+[Left-top edges color:]
+ -:
+[Right-bottom eges color:]
+ -:
+
+;End (Floating ontacts)
+
+
diff --git a/plugins/FloatingContacts/filedrop.cpp b/plugins/FloatingContacts/filedrop.cpp
new file mode 100644
index 0000000000..09fe2dace2
--- /dev/null
+++ b/plugins/FloatingContacts/filedrop.cpp
@@ -0,0 +1,368 @@
+#include "stdhdr.h"
+
+static void ProcessDroppedItems ( char **ppDroppedItems, int nCount, char **ppFiles );
+static int CountDroppedFiles ( char **ppDroppedItems, int nCount );
+static BOOL OnDropFiles ( HDROP hDrop, ThumbInfo *pThumb );
+
+HRESULT STDMETHODCALLTYPE CDropTarget::QueryInterface(REFIID riid,LPVOID *ppvObj)
+{
+ if ( IsEqualIID( riid, IID_IDropTarget ) )
+ {
+ *ppvObj = this;
+ this->AddRef();
+ return S_OK;
+ }
+
+ *ppvObj=NULL;
+
+ return ( E_NOINTERFACE );
+}
+
+ULONG STDMETHODCALLTYPE CDropTarget::AddRef( )
+{
+ return ++this->refCount;
+}
+
+ULONG STDMETHODCALLTYPE CDropTarget::Release( )
+{
+ int res = --this->refCount;
+ if (!res) delete this;
+ return res;
+}
+
+
+HRESULT STDMETHODCALLTYPE CDropTarget::DragOver( DWORD fKeyState, POINTL pt, DWORD *pdwEffect )
+{
+ *pdwEffect = 0;
+
+ if( hwndCurDrag == NULL )
+ {
+ *pdwEffect = DROPEFFECT_NONE;
+ }
+ else
+ {
+ *pdwEffect |= DROPEFFECT_COPY;
+ }
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE CDropTarget::DragEnter( IDataObject *pData, DWORD fKeyState, POINTL pt, DWORD *pdwEffect)
+{
+ HWND hwnd = NULL;
+ POINT shortPt;
+ FORMATETC feFile = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ FORMATETC feText = { CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ ThumbInfo *pThumb;
+
+ if ( S_OK == pData->QueryGetData( &feFile ) ||
+ S_OK == pData->QueryGetData( &feText ) )
+ {
+ shortPt.x = pt.x;
+ shortPt.y = pt.y;
+
+ hwnd = WindowFromPoint( shortPt );
+
+ if ( pThumb = thumbList.FindThumb( hwnd ) )
+ {
+ hwndCurDrag = hwnd;
+ pThumb->ThumbSelect( TRUE );
+ }
+ }
+
+ return DragOver( fKeyState, pt, pdwEffect);
+}
+
+
+HRESULT STDMETHODCALLTYPE CDropTarget::DragLeave( )
+{
+ ThumbInfo *pThumb = thumbList.FindThumb( hwndCurDrag );
+
+ if ( NULL != pThumb )
+ {
+ pThumb->ThumbDeselect( TRUE );
+ }
+
+ hwndCurDrag = NULL;
+
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE CDropTarget::Drop( IDataObject *pData,DWORD fKeyState,POINTL pt,DWORD *pdwEffect)
+{
+ FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ STGMEDIUM stg;
+ HDROP hDrop = NULL;
+ ThumbInfo *pThumb = NULL;
+ char *pText = NULL;
+ BOOL bFormatText = FALSE;
+
+ *pdwEffect = DROPEFFECT_NONE;
+
+
+ if( hwndCurDrag == NULL ) return( S_OK );
+
+ pThumb = (ThumbInfo*)GetWindowLong( hwndCurDrag, GWL_USERDATA );
+ if ( pThumb == NULL ) return( S_OK );
+
+ if ( S_OK != pData->GetData( &fe,&stg ) )
+ {
+ fe.cfFormat = CF_TEXT;
+
+ if ( S_OK != pData->GetData( &fe,&stg ) )
+ {
+ return( S_OK );
+ }
+ else
+ {
+ bFormatText = TRUE;
+ }
+ }
+
+
+
+ if ( !bFormatText )
+ {
+ hDrop = (HDROP)stg.hGlobal;
+
+ if ( hDrop != NULL )
+ {
+ OnDropFiles( hDrop, pThumb );
+ }
+ }
+ else
+ {
+ pText = (char*)GlobalLock( stg.hGlobal );
+
+ if ( pText != NULL )
+ {
+ SendMsgDialog( hwndCurDrag, pText );
+ GlobalUnlock( stg.hGlobal );
+ }
+ }
+
+ if( stg.pUnkForRelease != NULL )
+ {
+ stg.pUnkForRelease->Release( );
+ }
+ else
+ {
+ GlobalFree( stg.hGlobal );
+ }
+
+ DragLeave( );
+
+ return S_OK;
+}
+
+///////////////////////////////////////////////////////
+// Send files processing
+
+BOOL OnDropFiles( HDROP hDrop, ThumbInfo *pThumb )
+{
+ BOOL bSuccess = FALSE;
+ UINT nFilesCount = 0;
+ UINT iItem = 0;
+ char **ppFiles = NULL;
+ char **ppDroppedItems = NULL;
+ UINT nDroppedItemsCount = 0;
+ char szFilename[ MAX_PATH ];
+
+
+ nDroppedItemsCount = DragQueryFile( hDrop, 0xFFFFFFFF, NULL, 0 );
+
+ ppDroppedItems = ( char** )malloc( sizeof(char*)*( nDroppedItemsCount + 1 ) );
+
+ if ( ppDroppedItems == NULL )
+ {
+ return( FALSE );
+ }
+
+ ppDroppedItems[ nDroppedItemsCount ] = NULL;
+
+ for( iItem = 0; iItem < nDroppedItemsCount; ++iItem )
+ {
+ DragQueryFileA( hDrop, iItem, szFilename, sizeof( szFilename ) );
+ ppDroppedItems[ iItem ] = _strdup( szFilename );
+ }
+
+ nFilesCount = CountDroppedFiles( ppDroppedItems, nDroppedItemsCount );
+
+ ppFiles = ( char** )malloc( sizeof( char *)* ( nFilesCount+1 ) );
+
+ if ( ppFiles == NULL )
+ {
+ return( FALSE );
+ }
+
+ ppFiles[ nFilesCount] = NULL;
+
+ ProcessDroppedItems( ppDroppedItems, nDroppedItemsCount, ppFiles );
+
+ bSuccess = (BOOL)CallService( MS_CLIST_CONTACTFILESDROPPED, (WPARAM)pThumb->hContact, (LPARAM)ppFiles );
+
+ // Cleanup
+ for( iItem = 0; ppDroppedItems[ iItem ]; ++iItem )
+ {
+ free( ppDroppedItems[ iItem ] );
+ }
+
+ free( ppDroppedItems );
+
+ for( iItem = 0; iItem < nFilesCount ; ++iItem )
+ {
+ free( ppFiles[ iItem ] );
+ }
+
+ free( ppFiles );
+
+ return( bSuccess );
+}
+
+
+static int CountFiles( char *szItem )
+{
+ int nCount = 0;
+ WIN32_FIND_DATAA fd;
+
+ HANDLE hFind = FindFirstFileA( szItem, &fd );
+
+ if ( hFind != INVALID_HANDLE_VALUE )
+ {
+ do
+ {
+ if ( fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY )
+ {
+ // Skip parent directories
+ if ( ( 0 != strcmp( fd.cFileName, "." ) ) &&
+ ( 0 != strcmp( fd.cFileName, ".." ) ) )
+ {
+ char szDirName[ MAX_PATH ];
+ strncpy( szDirName, szItem, MAX_PATH - 1 );
+
+ if ( NULL != strstr( szItem, "*.*" ) )
+ {
+ sprintf( szDirName + strlen( szDirName ) - 3, "%s\0", fd.cFileName );
+ }
+
+ ++nCount;
+ strcat( szDirName, "\\*.*" );
+ nCount += CountFiles( szDirName );
+ }
+ }
+ else
+ {
+ ++nCount;
+ }
+ }
+ while( FALSE != FindNextFileA( hFind, &fd ) );
+ }
+
+ return( nCount );
+}
+
+
+
+static void SaveFiles( char *szItem, char **ppFiles, int *pnCount )
+{
+
+ WIN32_FIND_DATAA fd;
+
+ HANDLE hFind = FindFirstFileA( szItem, &fd );
+
+ if ( hFind != INVALID_HANDLE_VALUE )
+ {
+ do
+ {
+ if ( fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY )
+ {
+ // Skip parent directories
+ if ( ( 0 != strcmp( fd.cFileName, "." ) ) &&
+ ( 0 != strcmp( fd.cFileName, ".." ) ) )
+ {
+ char szDirName[ MAX_PATH ];
+ strncpy( szDirName, szItem, MAX_PATH - 1 );
+
+ if ( NULL != strstr( szItem, "*.*" ) )
+ {
+ sprintf( szDirName + strlen( szDirName ) - 3, "%s\0", fd.cFileName );
+ }
+
+ ppFiles[ *pnCount ] = _strdup( szDirName );
+ ++( *pnCount );
+
+ strcat( szDirName, "\\*.*" );
+ SaveFiles( szDirName, ppFiles, pnCount );
+
+ }
+ }
+ else
+ {
+ int nSize = sizeof(char) * ( strlen( szItem ) + strlen( fd.cFileName ) + sizeof( char ) );
+ char *szFile = (char*) malloc( nSize ) ;
+
+ strncpy( szFile, szItem, nSize - 1 );
+
+ if ( NULL != strstr( szFile, "*.*" ) )
+ {
+ szFile[ strlen( szFile ) - 3 ] = '\0';
+ strncat( szFile, fd.cFileName, MAX_PATH - 1 );
+ }
+
+ ppFiles[ *pnCount ] = szFile;
+ ++( *pnCount );
+ }
+ }
+ while( FALSE != FindNextFileA( hFind, &fd ) );
+ }
+}
+
+
+static void ProcessDroppedItems( char **ppDroppedItems, int nCount, char **ppFiles )
+{
+ int i;
+ int fileCount = 0;
+
+ for( i = 0; i < nCount; ++i )
+ {
+ SaveFiles( ppDroppedItems[ i ], ppFiles, &fileCount );
+ }
+}
+
+
+static int CountDroppedFiles( char **ppDroppedItems, int nCount )
+{
+ int fileCount = 0;
+ int i;
+
+ for( i = 0; i < nCount; ++i )
+ {
+ fileCount += CountFiles( ppDroppedItems[ i ] );
+ }
+
+ return( fileCount );
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// Init/destroy
+void InitFileDropping()
+{
+ OleInitialize( NULL );
+}
+
+void FreeFileDropping(void)
+{
+ OleUninitialize();
+}
+
+void RegisterFileDropping( HWND hwnd, CDropTarget* pdropTarget )
+{
+ RegisterDragDrop( hwnd, (IDropTarget*)pdropTarget );
+}
+
+void UnregisterFileDropping( HWND hwnd )
+{
+ RevokeDragDrop( hwnd );
+}
diff --git a/plugins/FloatingContacts/filedrop.h b/plugins/FloatingContacts/filedrop.h
new file mode 100644
index 0000000000..ed03cdbf68
--- /dev/null
+++ b/plugins/FloatingContacts/filedrop.h
@@ -0,0 +1,26 @@
+/* This file is a modification of clcfiledrop.h originally
+ written by Richard Hughes*/
+
+static HWND hwndCurDrag = NULL;
+
+class CDropTarget: public IDropTarget
+{
+private:
+ unsigned long refCount;
+
+public:
+ CDropTarget(): refCount(0) {}
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,LPVOID *ppvObj);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+ HRESULT STDMETHODCALLTYPE DragOver(DWORD fKeyState, POINTL pt, DWORD *pdwEffect);
+ HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pData, DWORD fKeyState, POINTL pt, DWORD *pdwEffect);
+ HRESULT STDMETHODCALLTYPE DragLeave();
+ HRESULT STDMETHODCALLTYPE Drop(IDataObject *pData,DWORD fKeyState,POINTL pt,DWORD *pdwEffect);
+};
+
+void InitFileDropping();
+void FreeFileDropping(void);
+void RegisterFileDropping( HWND hwnd, CDropTarget* pdropTarget );
+void UnregisterFileDropping( HWND hwnd );
diff --git a/plugins/FloatingContacts/fltcnt.rc b/plugins/FloatingContacts/fltcnt.rc
new file mode 100644
index 0000000000..c341a349cc
--- /dev/null
+++ b/plugins/FloatingContacts/fltcnt.rc
@@ -0,0 +1,232 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT
+#pragma code_page(1251)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_OPT_FLTCONT DIALOGEX 0, 0, 277, 229
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0xCC
+BEGIN
+ GROUPBOX "Hiding contacts",IDC_STATIC,4,4,269,52
+ CONTROL "Hide offline contacts",IDC_CHK_HIDE_OFFLINE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,12,16,133,10
+ CONTROL "Stick together",IDC_CHK_STICK,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,12,89,95,11
+ CONTROL "Use fixed width",IDC_CHK_WIDTH,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,12,74,62,12
+ EDITTEXT IDC_TXT_WIDTH,77,74,30,12,ES_RIGHT | ES_AUTOHSCROLL |
+ ES_NUMBER
+ CONTROL "",IDC_WIDTHSPIN,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS |
+ UDS_NOTHOUSANDS | UDS_HOTTRACK,96,73,11,14
+ LTEXT "pixels",IDC_LBL_WIDTH,111,75,27,8
+ CONTROL "Hide all contacts",IDC_CHK_HIDE_ALL,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,151,14,115,13
+ CONTROL "Hide when a fulscreen app is active",
+ IDC_CHK_HIDE_WHEN_FULSCREEN,"Button",BS_AUTOCHECKBOX |
+ BS_MULTILINE | WS_TABSTOP,12,28,137,22
+ CONTROL "Show tooltips",IDC_CHK_TIP,"Button",BS_AUTOCHECKBOX |
+ BS_MULTILINE | WS_TABSTOP,152,72,60,14
+ EDITTEXT IDC_TXT_TIMEIN,214,73,35,12,ES_RIGHT | ES_AUTOHSCROLL |
+ ES_NUMBER
+ CONTROL "",IDC_TIMEINSPIN,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS |
+ UDS_NOTHOUSANDS | UDS_HOTTRACK,242,72,11,14
+ LTEXT "ms",IDC_LBL_TIMEIN,256,75,10,8
+ GROUPBOX "Tooltips",IDC_STATIC,142,62,131,58
+ GROUPBOX "Miscellaneous",IDC_STATIC,4,62,132,58
+ LTEXT "0 = Default",IDC_LBL_TIMEIN_CMT,217,89,51,8
+ LTEXT "requires mToolTip or Tipper plugin",IDC_STATIC,153,88,
+ 56,27
+ GROUPBOX "Bring to front",IDC_STATIC,4,126,132,40
+ CONTROL "Bring to front every",IDC_CHK_TOTOP,"Button",
+ BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,12,135,56,28
+ EDITTEXT IDC_TXT_TOTOPTIME,68,142,30,12,ES_RIGHT | ES_AUTOHSCROLL |
+ ES_NUMBER
+ CONTROL "",IDC_TOTOPTIMESPIN,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS |
+ UDS_NOTHOUSANDS | UDS_HOTTRACK,85,141,11,14
+ LTEXT "seconds",IDC_LBL_TOTOP,100,144,34,8
+ CONTROL "Hide when contact list is shown",
+ IDC_CHK_HIDE_WHEN_CLISTSHOW,"Button",BS_AUTOCHECKBOX |
+ BS_MULTILINE | WS_TABSTOP,152,28,114,22
+ CONTROL "Single click interface",IDC_CHK_SINGLECLK,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,12,103,120,10
+ CONTROL "Dim idle contacts",IDC_CHK_SHOWIDLE,"Button",
+ BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,152,138,116,
+ 20
+END
+
+IDD_OPT_SKIN DIALOGEX 0, 0, 277, 229
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 400, 0, 0xCC
+BEGIN
+ GROUPBOX "Fonts",IDC_STATIC,4,2,269,113
+ COMBOBOX IDC_FONTID,12,15,253,87,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "same",IDC_STSAMETEXT,19,29,45,10,SS_CENTERIMAGE
+ CONTROL "Typeface",IDC_SAMETYPE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,64,29,52,10
+ CONTROL "Size",IDC_SAMESIZE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,117,29,45,10
+ CONTROL "Style",IDC_SAMESTYLE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,163,29,48,10
+ CONTROL "Colour",IDC_SAMECOLOUR,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,212,29,53,10
+ LTEXT "as:",IDC_STASTEXT,19,45,45,10,SS_CENTERIMAGE
+ COMBOBOX IDC_SAMEAS,64,42,201,88,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ CONTROL "",IDC_STHORZBAR,"Static",SS_ETCHEDHORZ,9,59,256,1
+ COMBOBOX IDC_TYPEFACE,12,64,136,182,CBS_DROPDOWN | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_SCRIPT,156,64,60,68,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ COMBOBOX IDC_FONTSIZE,226,64,40,69,CBS_DROPDOWN | WS_VSCROLL |
+ WS_TABSTOP
+ CONTROL "Bold",IDC_BOLD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,
+ 78,45,10
+ CONTROL "Italic",IDC_ITALIC,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,65,78,52,10
+ CONTROL "Underline",IDC_UNDERLINE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,117,78,66,10
+ CONTROL "",IDC_COLOUR,"ColourPicker",WS_TABSTOP,206,80,59,11
+ EDITTEXT IDC_SAMPLE,63,94,151,16,ES_CENTER | ES_READONLY | NOT
+ WS_TABSTOP
+ CONTROL "Slider1",IDC_SLIDER_OPACITY,"msctls_trackbar32",TBS_TOP |
+ TBS_NOTICKS | WS_TABSTOP,178,162,67,16
+ CTEXT "100 %",IDC_OPACITY,245,166,25,8
+ GROUPBOX "Border",IDC_STATIC,4,116,269,38
+ CONTROL "Draw border",IDC_DRAWBORDER,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,11,126,81,10
+ LTEXT "Left-top edges color:",IDC_STATIC,11,139,76,8,NOT
+ WS_GROUP
+ CONTROL "",IDC_LTEDGESCOLOR,"ColourPicker",WS_TABSTOP,87,138,32,
+ 10
+ LTEXT "Right-bottom eges color:",IDC_STATIC,128,139,87,8,NOT
+ WS_GROUP
+ CONTROL "",IDC_RBEDGESCOLOR,"ColourPicker",WS_TABSTOP,217,138,32,
+ 10
+ GROUPBOX "Background",IDC_STATIC,4,156,269,70
+ LTEXT "Background colour:",IDC_STATIC,13,166,72,8,NOT WS_GROUP
+ CONTROL "",IDC_BKGCOLOUR,"ColourPicker",WS_TABSTOP,87,166,32,10
+ CONTROL "Use background bitmap",IDC_BITMAP,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,13,179,115,10
+ EDITTEXT IDC_FILENAME,131,179,111,12,ES_AUTOHSCROLL
+ PUSHBUTTON "...",IDC_BROWSE,245,179,15,11
+ CONTROL "Stretch to width",IDC_STRETCHH,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,13,201,100,10
+ CONTROL "Stretch to height",IDC_STRETCHV,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,131,201,101,10
+ CONTROL "Tile horizontally",IDC_TILEH,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,13,212,102,10
+ CONTROL "Tile vertically",IDC_TILEV,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,131,212,101,10
+ CONTROL "Stretch proportionally",IDC_PROPORTIONAL,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,13,190,101,10
+ LTEXT "Opacity:",IDC_STATIC,129,166,52,8
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_OPT_FLTCONT, DIALOG
+ BEGIN
+ LEFTMARGIN, 4
+ RIGHTMARGIN, 273
+ VERTGUIDE, 12
+ VERTGUIDE, 22
+ TOPMARGIN, 4
+ BOTTOMMARGIN, 225
+ HORZGUIDE, 18
+ END
+
+ IDD_OPT_SKIN, DIALOG
+ BEGIN
+ BOTTOMMARGIN, 226
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_HIDE ICON "hide.ico"
+IDI_SHOW ICON "show.ico"
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/FloatingContacts/fltcont.h b/plugins/FloatingContacts/fltcont.h
new file mode 100644
index 0000000000..3d725d71bc
--- /dev/null
+++ b/plugins/FloatingContacts/fltcont.h
@@ -0,0 +1,191 @@
+
+#ifndef __FLTCONT_H__
+#define __FLTCONT_H__
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+#define WND_CLASS _T("MirandaThumbsWnd")
+#define WM_REFRESH_CONTACT WM_USER + 0x100
+
+#ifndef WS_EX_LAYERED
+ #define WS_EX_LAYERED 0x00080000
+#endif
+
+#ifndef LWA_ALPHA
+ #define LWA_ALPHA 0x00000002
+#endif
+
+#ifndef ULW_ALPHA
+ #define ULW_ALPHA 0x00000002
+#endif
+
+#define TIMERID_SELECT_T 1
+#define TIMERID_HOVER_T 2
+#define TIMERID_TOTOP_T 3
+#define TIMERID_LEAVE_T 4
+
+
+#if WINVER < 0x0500
+ #define SM_XVIRTUALSCREEN 76
+ #define SM_YVIRTUALSCREEN 77
+ #define SM_CXVIRTUALSCREEN 78
+ #define SM_CYVIRTUALSCREEN 79
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+enum
+{
+ FLT_FONTID_CONTACTS,
+ FLT_FONTID_INVIS,
+ FLT_FONTID_OFFLINE,
+ FLT_FONTID_OFFINVIS,
+ FLT_FONTID_NOTONLIST,
+ FLT_FONTIDS,
+};
+
+#define DBFONTF_BOLD 1
+#define DBFONTF_ITALIC 2
+#define DBFONTF_UNDERLINE 4
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+#define FLT_DEFAULT_DRAWBORDER TRUE
+#define FLT_DEFAULT_LTEDGESCOLOR GetSysColor(COLOR_3DHILIGHT)
+#define FLT_DEFAULT_RBEDGESCOLOR GetSysColor(COLOR_3DDKSHADOW)
+#define FLT_DEFAULT_BKGNDCOLOR GetSysColor(COLOR_3DFACE)
+#define FLT_DEFAULT_BKGNDUSEBITMAP FALSE
+#define FLT_DEFAULT_BKGNDBITMAPOPT CLB_STRETCH
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+#define sModule "FloatingContacts"
+
+#define TOTOPTIME_P 1000
+#define TOTOPTIME_MAX (15*(60000/TOTOPTIME_P))
+#define TOTOPTIME_DEF (3*(60000/TOTOPTIME_P))
+
+#define MAXRCOOR 32767.0
+#define DB_POS_GETX(pos) (short)(((float)(short)(LOWORD(pos))*(float)GetSystemMetrics(SM_CXSCREEN))/MAXRCOOR+0.5)
+#define DB_POS_GETY(pos) (short)(((float)(short)(HIWORD(pos))*(float)GetSystemMetrics(SM_CYSCREEN))/MAXRCOOR+0.5)
+#define DB_POS_MAKE_XY(x, y) MAKELONG((short)(((float)x*MAXRCOOR)/(float)GetSystemMetrics(SM_CXSCREEN)+0.5), (short)(((float)y*MAXRCOOR)/(float)GetSystemMetrics(SM_CYSCREEN)+0.5))
+
+extern HINSTANCE hInst;
+extern BOOL bNT;
+//extern BOOL bHideOffline;
+//extern BOOL bHideAll;
+//extern BOOL bHideWhenFullscreen;
+//extern BOOL bMoveTogether;
+//extern BOOL bFixedWidth;
+//extern int nThumbWidth;
+//extern BYTE thumbAlpha;
+//extern BOOL bShowTip;
+extern BOOL bEnableTip;
+//extern WORD TimeIn;
+//extern BOOL bToTop;
+//extern WORD ToTopTime;
+//extern BOOL bHideWhenCListShow;
+
+extern BOOL bIsCListShow;
+extern HWND hwndMiranda;
+extern HIMAGELIST himl;
+extern RECT rcScreen;
+
+extern HFONT hFont[FLT_FONTIDS];
+extern COLORREF tColor[FLT_FONTIDS];
+
+extern HPEN hLTEdgesPen;
+extern HPEN hRBEdgesPen;
+extern HBRUSH hBkBrush;
+extern DWORD bkColor;
+extern HBITMAP hBmpBackground;
+extern WORD nBackgroundBmpUse;
+
+
+
+typedef struct _FCOptions
+{
+ BYTE thumbAlpha;
+ BOOL bHideOffline;
+ BOOL bHideAll;
+ BOOL bHideWhenFullscreen;
+ BOOL bMoveTogether;
+ BOOL bFixedWidth;
+ int nThumbWidth;
+ BOOL bShowTip;
+ WORD TimeIn;
+ BOOL bToTop;
+ WORD ToTopTime;
+ BOOL bHideWhenCListShow;
+ BOOL bUseSingleClick;
+ BOOL bShowIdle;
+}
+FCOptions;
+
+extern FCOptions fcOpt;
+
+extern BOOL (WINAPI *pSetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD);
+extern BOOL (WINAPI *pUpdateLayeredWindow)
+ (HWND hwnd, HDC hdcDST, POINT *pptDst, SIZE *psize, HDC hdcSrc, POINT *pptSrc,
+ COLORREF crKey, BLENDFUNCTION *pblend, DWORD dwFlags);
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+static __forceinline BOOL ImageList_GetIconSize_my(HIMAGELIST himl, SIZE &sz)
+{
+ int cx, cy;
+ BOOL res = ImageList_GetIconSize(himl, &cx, &cy);
+ sz.cx = cx; sz.cy = cy;
+ return res;
+}
+
+void RegHotkey ( HANDLE hContact, HWND hwnd );
+BOOL IsStatusVisible ( int status );
+BOOL HideOnFullScreen ();
+void SendMsgDialog ( HWND hwnd, char *pText );
+void SaveContactsPos ( void );
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+void
+GetFontSetting
+ ( IN BOOL bFltContacts
+ , IN int nFontId
+ , IN LOGFONTA* lf
+ , IN COLORREF* colour
+ );
+
+void
+ApplyOptionsChanges();
+
+void
+OnStatusChanged();
+
+void
+SetThumbsOpacity
+ ( IN BYTE btAlpha
+ );
+
+int
+OnOptionsInitialize
+ ( IN WPARAM wParam
+ , IN LPARAM lParam
+ );
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif // #ifndef __FLTCONT_H__
+
+/////////////////////////////////////////////////////////////////////////////
+// End Of File fltcont.h
diff --git a/plugins/FloatingContacts/hide.ico b/plugins/FloatingContacts/hide.ico
new file mode 100644
index 0000000000..941da6aeb9
--- /dev/null
+++ b/plugins/FloatingContacts/hide.ico
Binary files differ
diff --git a/plugins/FloatingContacts/main.cpp b/plugins/FloatingContacts/main.cpp
new file mode 100644
index 0000000000..9246e6f2b2
--- /dev/null
+++ b/plugins/FloatingContacts/main.cpp
@@ -0,0 +1,1331 @@
+/*
+Miranda Floating Contacts plugin, created by Iavor Vajarov ( ivajarov@code.bg )
+http://miranda-icq.sourceforge.net/
+
+Miranda fonts and colors settings by Ranger.
+Extended bonts and backgrounds settings by Oleksiy Shurubura
+
+
+This file is placed in the public domain. Anybody is free to use or
+modify it as they wish with no restriction.
+
+This plugin has been tested to work under Windows ME, 2000 and XP.
+
+No warranty for any misbehaviour.
+*/
+
+#include "stdhdr.h"
+#include "shlwapi.h"
+
+#include "version.h"
+
+#pragma comment ( lib, "comctl32.lib" )
+#pragma comment ( lib, "shlwapi.lib" )
+
+#pragma warning ( default : 4201 )
+
+//#define DB_POS_GETX(pos) LOWORD(pos)
+//#define DB_POS_GETY(pos) HIWORD(pos)
+//#define DB_POS_MAKE_XY(x, y) MAKELONG(x, y)
+
+BOOL (WINAPI *pSetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD);
+BOOL (WINAPI *pUpdateLayeredWindow)
+ (HWND hwnd, HDC hdcDST, POINT *pptDst, SIZE *psize, HDC hdcSrc, POINT *pptSrc,
+ COLORREF crKey, BLENDFUNCTION *pblend, DWORD dwFlags);
+
+// Globals
+
+// TODO: move to some more approriate place, probably part of Thumbs manager
+static void LoadContacts ( void );
+static void LoadContact ( HANDLE hContact );
+
+// Internal funcs
+static void RepaintWindow ( HWND hwnd, HDC hdc );
+static void LoadMenus ();
+static void CreateThumbWnd ( TCHAR *ptszName, HANDLE hContact, int nX, int nY );
+static void RegisterWindowClass ( void );
+static void UnregisterWindowClass ( void );
+static void CleanUp ( void );
+static BOOL GetOSPlatform ( void );
+static void LoadDBSettings ( void );
+static void CreateThumbsFont ( void );
+static void CreateBackgroundBrush ( void );
+static int GetContactStatus ( HANDLE hContact );
+static void GetScreenRect ( void );
+extern void SetThumbsOpacity ( BYTE btAlpha );
+static int ClcStatusToPf2 ( int status );
+
+static LRESULT __stdcall CommWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
+static LRESULT __stdcall newMirandaWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
+
+static int OnContactDeleted ( WPARAM wParam,LPARAM lParam );
+static int OnContactIconChanged ( WPARAM wParam, LPARAM lParam );
+static int OnContactDrag ( WPARAM wParam, LPARAM lParam );
+static int OnContactDrop ( WPARAM wParam, LPARAM lParam );
+static int OnContactDragStop ( WPARAM wParam, LPARAM lParam );
+static int OnSkinIconsChanged ( WPARAM wParam, LPARAM lParam );
+static int OnContactSettingChanged ( WPARAM wParam, LPARAM lParam );
+static int OnStatusModeChange ( WPARAM wParam, LPARAM lParam );
+static int OnModulesLoded ( WPARAM wParam, LPARAM lParam );
+static int OnPrebuildContactMenu ( WPARAM wParam, LPARAM lParam );
+
+static int OnContactMenu_Remove ( WPARAM wParam,LPARAM lParam );
+//static int OnContactMenu_HideAll ( WPARAM wParam,LPARAM lParam );
+static int OnMainMenu_HideAll ( WPARAM wParam,LPARAM lParam );
+static int OnHotKey_HideWhenCListShow( WPARAM wParam,LPARAM lParam );
+static VOID CALLBACK ToTopTimerProc ( HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
+
+WNDPROC oldMirandaWndProc;
+
+
+HINSTANCE hInst = NULL;
+HMODULE hUserDll = NULL;
+PLUGINLINK *pluginLink = NULL;
+LIST_INTERFACE li = {0};
+HFONT hFont[FLT_FONTIDS] = {NULL};
+COLORREF tColor[FLT_FONTIDS] = {0};
+HIMAGELIST himl = NULL;
+HANDLE hevContactIcon = NULL;
+HANDLE hevContactDrop = NULL;
+HANDLE hevContactDragStop = NULL;
+HANDLE hevSkinIcons = NULL;
+HANDLE hevContactDrag = NULL;
+HANDLE hevContactSetting = NULL;
+HANDLE hevContactDeleted = NULL;
+HANDLE hevOptionsInit = NULL;
+HANDLE hevStatusMode = NULL;
+HANDLE hevModules = NULL;
+HANDLE hevPrebuildMenu = NULL;
+HANDLE hNewContact = NULL;
+
+HPEN hLTEdgesPen = NULL;
+HPEN hRBEdgesPen = NULL;
+HBRUSH hBkBrush = NULL;
+DWORD bkColor = 0;
+HBITMAP hBmpBackground = NULL;
+WORD nBackgroundBmpUse = CLB_STRETCH;
+
+HWND hwndMiranda = NULL;
+BOOL bVersionOK = FALSE;
+BOOL bNT = FALSE;
+BOOL bDockHorz = TRUE;
+//UINT nStatus = 0;
+HMENU hContactMenu = NULL;
+HANDLE hMenuItemRemove = NULL;
+HANDLE hMenuItemHideAll = NULL;
+HANDLE hMainMenuItemHideAll = NULL;
+RECT rcScreen;
+DWORD dwOfflineModes = 0;
+BOOL bEnableTip = FALSE;
+UINT_PTR ToTopTimerID = 0;
+BOOL bIsCListShow = TRUE;
+
+HANDLE hRemoveThumb = NULL;
+HANDLE hMainHideAllThumbs = NULL;
+HANDLE hHideWhenCListShow = NULL;
+
+//Options
+
+FCOptions fcOpt = {0};
+
+static void InitOptions(){
+ fcOpt.thumbAlpha = 255;
+ fcOpt.bHideOffline = FALSE;
+ fcOpt.bHideAll = FALSE;
+ fcOpt.bHideWhenFullscreen = FALSE;
+ fcOpt.bMoveTogether = FALSE;
+ fcOpt.bFixedWidth = FALSE;
+ fcOpt.nThumbWidth = 0;
+ fcOpt.bShowTip = TRUE;
+ fcOpt.TimeIn = 0;
+ fcOpt.bToTop = TRUE;
+ fcOpt.ToTopTime = TOTOPTIME_DEF;
+ fcOpt.bHideWhenCListShow = FALSE;
+ fcOpt.bUseSingleClick = FALSE;
+ fcOpt.bShowIdle = TRUE;
+}
+
+
+PLUGININFO pluginInfo ={
+ sizeof(PLUGININFO),
+ __PLUGIN_NAME,
+ 0,
+ __DESC,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ 0
+};
+
+// {53C715A8-EB01-4136-A73C-441868610074}
+#define MIID_FLTCONT { 0x53c715a8, 0xeb01, 0x4136, { 0xa7, 0x3c, 0x44, 0x18, 0x68, 0x61, 0x0, 0x74 } }
+
+static const MUUID interfaces[] = {MIID_FLTCONT, MIID_LAST};
+
+extern "C" __declspec(dllexport) const MUUID * MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+PLUGININFOEX pluginInfoEx ={
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ 0,
+ __DESC,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ 0,
+ MIID_FLTCONT
+};
+
+_inline unsigned int MakeVer(int a,int b,int c,int d)
+{
+ return PLUGIN_MAKE_VERSION(a,b,c,d);
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) {
+
+ if( mirandaVersion < MakeVer(MINIMAL_COREVERSION) ) return NULL;
+ pluginInfoEx.version=MakeVer(PRODUCT_VERSION);
+ return &pluginInfoEx;
+}
+
+
+///////////////////////////////////////////////////////
+// Load / unload
+BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
+{
+ hInst = hinstDLL;
+
+ switch ( fdwReason )
+ {
+ case DLL_PROCESS_ATTACH:
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+
+ return( TRUE );
+}
+
+
+
+extern "C" __declspec(dllexport) PLUGININFO* MirandaPluginInfo( DWORD mirandaVersion )
+{
+ if( mirandaVersion < MakeVer(MINIMAL_COREVERSION) ) return NULL;
+ pluginInfo.version=MakeVer(PRODUCT_VERSION);
+ return &pluginInfo;
+}
+
+
+
+extern "C" int __declspec(dllexport) Load( PLUGINLINK *link )
+{
+ SetLastError( 0 );
+ InitOptions();
+ pluginLink = link;
+
+ mir_getLI(&li);
+
+ hevModules = HookEvent( ME_SYSTEM_MODULESLOADED, OnModulesLoded );
+ bNT = GetOSPlatform();
+
+ if (hUserDll = LoadLibrary(_T("user32.dll")))
+ {
+ pSetLayeredWindowAttributes =
+ (BOOL (WINAPI *)(HWND,COLORREF,BYTE,DWORD))
+ GetProcAddress(hUserDll, "SetLayeredWindowAttributes");
+ pUpdateLayeredWindow =
+ (BOOL (WINAPI *)(HWND, HDC, POINT *, SIZE *, HDC, POINT *, COLORREF, BLENDFUNCTION *, DWORD))
+ GetProcAddress(hUserDll, "UpdateLayeredWindow");
+ } else
+ {
+ pSetLayeredWindowAttributes = NULL;
+ pUpdateLayeredWindow = NULL;
+ }
+
+ return 0;
+}
+
+
+
+extern "C" int __declspec(dllexport) Unload()
+{
+ CleanUp();
+ return 0;
+}
+
+
+
+static void CleanUp()
+{
+ int nFontId;
+
+ UnhookEvent( hevContactIcon );
+ UnhookEvent( hevContactDrag );
+ UnhookEvent( hevContactDrop );
+ UnhookEvent( hevContactDragStop );
+ UnhookEvent( hevSkinIcons );
+ UnhookEvent( hevContactDeleted );
+ UnhookEvent( hevContactSetting );
+ UnhookEvent( hevOptionsInit );
+ UnhookEvent( hevStatusMode );
+ UnhookEvent( hevModules );
+ UnhookEvent( hevPrebuildMenu );
+
+ if(hRemoveThumb)
+ DestroyServiceFunction(hRemoveThumb);
+ if(hMainHideAllThumbs)
+ DestroyServiceFunction(hMainHideAllThumbs);
+ if(hHideWhenCListShow)
+ DestroyServiceFunction(hHideWhenCListShow);
+
+// while( pThumbsList != NULL )
+// RemoveThumb( pThumbsList );
+
+ if(ServiceExists(MS_HOTKEY_UNREGISTER)){
+ CallService(MS_HOTKEY_UNREGISTER, 0, (LPARAM)(sModule "/MainHideAllThumbs"));
+ CallService(MS_HOTKEY_UNREGISTER, 0, (LPARAM)(sModule "/HideWhenCListShow"));
+ }
+
+ if (NULL != hLTEdgesPen)
+ DeleteObject(hLTEdgesPen);
+ if (NULL != hRBEdgesPen)
+ DeleteObject(hRBEdgesPen);
+ if (NULL != hBmpBackground)
+ DeleteObject(hBmpBackground);
+ if (NULL != hBkBrush)
+ {
+ SetClassLong((HWND)WND_CLASS, GCL_HBRBACKGROUND, (LONG)NULL);
+ DeleteObject(hBkBrush);
+ hBkBrush=NULL;
+ }
+
+ for (nFontId = 0; nFontId < FLT_FONTIDS; nFontId++)
+ if (NULL != hFont[nFontId])
+ DeleteObject(hFont[nFontId]);
+
+ UnregisterWindowClass();
+
+ FreeFileDropping();
+
+ if ( hUserDll != NULL )
+ {
+ FreeLibrary( hUserDll );
+ }
+}
+
+
+
+///////////////////////////////////////////////////////
+// Hooked events
+static int OnModulesLoded( WPARAM wParam, LPARAM lParam )
+{
+ hevContactIcon = HookEvent( ME_CLIST_CONTACTICONCHANGED, OnContactIconChanged );
+ hevSkinIcons = HookEvent( ME_SKIN_ICONSCHANGED, OnSkinIconsChanged );
+ hevContactDrag = HookEvent( ME_CLUI_CONTACTDRAGGING, OnContactDrag );
+ hevContactDrop = HookEvent( ME_CLUI_CONTACTDROPPED, OnContactDrop );
+ hevContactDragStop = HookEvent( ME_CLUI_CONTACTDRAGSTOP, OnContactDragStop );
+ hevContactSetting = HookEvent( ME_DB_CONTACT_SETTINGCHANGED, OnContactSettingChanged );
+ hevContactDeleted = HookEvent( ME_DB_CONTACT_DELETED, OnContactDeleted );
+ hevOptionsInit = HookEvent( ME_OPT_INITIALISE, OnOptionsInitialize );
+ hevStatusMode = HookEvent( ME_CLIST_STATUSMODECHANGE, OnStatusModeChange );
+ hevPrebuildMenu = HookEvent( ME_CLIST_PREBUILDCONTACTMENU, OnPrebuildContactMenu );
+ hwndMiranda = (HWND)CallService( MS_CLUI_GETHWND, 0, 0 );
+
+ oldMirandaWndProc = (WNDPROC)SetWindowLong( hwndMiranda, GWL_WNDPROC, (LONG)newMirandaWndProc);
+
+
+
+ // No thumbs yet
+// pThumbsList = NULL;
+ bEnableTip = ServiceExists("mToolTip/ShowTip");
+
+ RegisterWindowClass();
+ InitFileDropping();
+ GetScreenRect();
+ LoadDBSettings();
+ CreateBackgroundBrush();
+ CreateThumbsFont();
+ LoadContacts();
+ LoadMenus();
+
+ if(fcOpt.bToTop){
+ fcOpt.ToTopTime = (fcOpt.ToTopTime<1)?1:fcOpt.ToTopTime;
+ fcOpt.ToTopTime = (fcOpt.ToTopTime>TOTOPTIME_MAX)?TOTOPTIME_MAX:fcOpt.ToTopTime;
+ ToTopTimerID=SetTimer(NULL, 0, fcOpt.ToTopTime*TOTOPTIME_P, ToTopTimerProc);
+ }
+ return( 0 );
+}
+
+
+static int OnContactDeleted( WPARAM wParam, LPARAM lParam )
+{
+ HANDLE hContact = ( HANDLE )wParam;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+ if (!pThumb) return 0;
+
+ pThumb->DeleteContactPos();
+ thumbList.RemoveThumb(pThumb);
+
+ return 0;
+}
+
+
+static int OnContactIconChanged( WPARAM wParam, LPARAM lParam )
+{
+ HANDLE hContact = ( HANDLE )wParam;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+
+ if ( pThumb )
+ {
+ pThumb->RefreshContactIcon( ( int )lParam );
+ //pThumb->ThumbSelect( FALSE );
+ //SetTimer( pThumb->hwnd, TIMERID_SELECT_T, 1000, NULL );
+ }
+
+ return 0;
+}
+
+
+static int OnContactDrag( WPARAM wParam, LPARAM lParam )
+{
+ ThumbInfo *pNewThumb = NULL;
+ HANDLE hContact = ( HANDLE )wParam;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+ TCHAR *ptName = (TCHAR*)CallService( MS_CLIST_GETCONTACTDISPLAYNAME, wParam, (LPARAM)GCDNF_TCHAR );
+ int idStatus = ID_STATUS_OFFLINE;
+ POINT pt;
+ GetCursorPos(&pt);
+
+ if ( pThumb == NULL )
+ {
+ idStatus = GetContactStatus( hContact );
+
+ if ( !fcOpt.bHideAll && !HideOnFullScreen() && ( !fcOpt.bHideOffline || IsStatusVisible( idStatus ) ) && (!fcOpt.bHideWhenCListShow || !bIsCListShow) )
+ {
+// CreateThumbWnd( pName, hContact, LOWORD( lParam ), HIWORD( lParam ) );
+ CreateThumbWnd( ptName, hContact, pt.x, pt.y );
+ pNewThumb = thumbList.FindThumbByContact( hContact );
+ ShowWindow( pNewThumb->hwnd, SW_SHOWNA );
+ hNewContact = hContact;
+
+ OnStatusChanged();
+ }
+ }
+ else if ( hContact == hNewContact )
+ {
+// PositionThumb( pThumb, (short)( LOWORD( lParam ) - 5 ), (short)( HIWORD( lParam ) - 5 ) );
+ pThumb->PositionThumb( (short)( pt.x - 5 ), (short)( pt.y - 5 ) );
+ }
+
+ return( hNewContact != NULL ? 1 : 0 );
+}
+
+
+
+static int OnContactDrop( WPARAM wParam, LPARAM lParam )
+{
+ RECT rcMiranda;
+ RECT rcThumb;
+// RECT rcOverlap;
+
+ HANDLE hContact = ( HANDLE )wParam;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+
+ if ( ( hNewContact == hContact ) && ( pThumb != NULL ) )
+ {
+ hNewContact = NULL;
+
+ GetWindowRect( hwndMiranda, &rcMiranda );
+ pThumb->GetThumbRect( &rcThumb );
+
+ //if ( IntersectRect( &rcOverlap, &rcThumb, &rcMiranda ) )
+ //{
+ // pThumb->OnLButtonDown( (short)(rcThumb.left + 5), (short)(rcThumb.top + 5) );
+ //}
+ }
+
+ SaveContactsPos();
+
+ return( 1 );
+}
+
+
+static int OnContactDragStop( WPARAM wParam, LPARAM lParam )
+{
+ HANDLE hContact = ( HANDLE )wParam;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+
+ if ( ( pThumb != NULL ) && ( hNewContact == hContact ) )
+ {
+ thumbList.RemoveThumb( pThumb );
+ hNewContact = NULL;
+ }
+
+ return( 0 );
+}
+
+
+static int OnSkinIconsChanged( WPARAM wParam, LPARAM lParam )
+{
+ // Get handle to the image list
+ himl = ( HIMAGELIST )CallService( MS_CLIST_GETICONSIMAGELIST, 0, 0 );
+
+ // Update thumbs
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ thumbList[i]->UpdateContent();
+
+ return( 0 );
+}
+
+
+
+static int OnContactSettingChanged( WPARAM wParam, LPARAM lParam )
+{
+ HANDLE hContact = ( HANDLE )wParam;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+ int idStatus = ID_STATUS_OFFLINE;
+ BOOL bRefresh = TRUE;
+ DBCONTACTWRITESETTING* pdbcws = ( DBCONTACTWRITESETTING* )lParam;
+
+
+ if ( hContact == NULL )
+ {
+ if(( 0 == stricmp( pdbcws->szModule, "CLC" ) ) || ( 0 == stricmp( pdbcws->szModule, sModule ) ) ){
+ LoadDBSettings();
+ ApplyOptionsChanges();
+ }
+
+ return( 0 );
+ }
+
+ if ( pThumb == NULL ) return( 0 );
+
+ // Only on these 2 events we need to refresh
+ if( 0 == stricmp( pdbcws->szSetting, "Status" ) )
+ {
+ idStatus = pdbcws->value.wVal;
+ }
+ else if ( 0 == stricmp( pdbcws->szSetting, "Nick" ) )
+ {
+ idStatus = GetContactStatus( hContact );
+ }
+ else if ( 0 == stricmp( pdbcws->szSetting, "MyHandle" ) )
+ {
+ idStatus = GetContactStatus( hContact );
+ }
+ else if ( fcOpt.bShowIdle && 0 == stricmp( pdbcws->szSetting, "IdleTS" ))
+ {
+ idStatus = GetContactStatus( hContact );
+ }
+ else
+ {
+ bRefresh = FALSE;
+ }
+
+ if ( bRefresh )
+ {
+ // Detach call
+ PostMessage( pThumb->hwnd, WM_REFRESH_CONTACT, 0, idStatus );
+ }
+
+ return( 0 );
+}
+
+
+static int OnStatusModeChange( WPARAM wParam, LPARAM lParam )
+{
+ int idStatus;
+
+ //nStatus = (int)wParam;
+
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ {
+ idStatus = GetContactStatus( thumbList[i]->hContact );
+ thumbList[i]->RefreshContactStatus( idStatus );
+ }
+ if ( wParam == ID_STATUS_OFFLINE )
+ {
+ // Floating status window will use this
+ }
+
+ return( 0 );
+}
+
+
+
+static int OnPrebuildContactMenu( WPARAM wParam, LPARAM lParam )
+{
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( (HANDLE) wParam );
+ CLISTMENUITEM clmi;
+
+ ZeroMemory( &clmi, sizeof( clmi ) );
+ clmi.cbSize = sizeof( clmi );
+
+ clmi.flags = ( pThumb == NULL ) ? CMIM_FLAGS | CMIF_HIDDEN : CMIM_FLAGS &~CMIF_HIDDEN;
+ CallService( MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItemRemove, (LPARAM)&clmi );
+
+ clmi.flags = fcOpt.bHideAll ? CMIM_FLAGS | CMIF_HIDDEN : CMIM_FLAGS &~CMIF_HIDDEN;
+ CallService( MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItemHideAll, (LPARAM)&clmi );
+
+ return( 0 );
+}
+
+
+
+
+///////////////////////////////////////////////////////
+// General functions
+
+static void LoadDBSettings()
+{
+ fcOpt.thumbAlpha = (BYTE)((double)DBGetContactSettingByte( NULL, sModule, "Opacity", 100 ) * 2.55 );
+ fcOpt.bHideOffline = (BOOL)DBGetContactSettingByte( NULL, sModule, "HideOffline", 0 );
+ fcOpt.bHideAll = (BOOL)DBGetContactSettingByte( NULL, sModule, "HideAll", 0 );
+ fcOpt.bHideWhenFullscreen = (BOOL)DBGetContactSettingByte( NULL, sModule, "HideWhenFullscreen", 0 );
+ fcOpt.bMoveTogether = (BOOL)DBGetContactSettingByte( NULL, sModule, "MoveTogether", 0 );
+ fcOpt.bFixedWidth = (BOOL)DBGetContactSettingByte( NULL, sModule, "FixedWidth", 0 );
+ fcOpt.nThumbWidth = (DWORD)DBGetContactSettingDword( NULL, sModule, "Width", 0 );
+ dwOfflineModes = DBGetContactSettingDword( NULL, "CLC","OfflineModes", CLCDEFAULT_OFFLINEMODES );
+ fcOpt.bShowTip = (BOOL)DBGetContactSettingByte( NULL, sModule, "ShowTip", 1 );
+ fcOpt.TimeIn = (WORD)DBGetContactSettingWord( NULL, sModule, "TimeIn", 0 );
+ fcOpt.bToTop = (BOOL)DBGetContactSettingByte( NULL, sModule, "ToTop", 0 );
+ fcOpt.ToTopTime = (WORD)DBGetContactSettingWord( NULL, sModule, "ToTopTime", TOTOPTIME_DEF );
+ fcOpt.bHideWhenCListShow = (BOOL)DBGetContactSettingByte( NULL, sModule, "HideWhenCListShow", 0 );
+ fcOpt.bUseSingleClick = (BOOL)DBGetContactSettingByte( NULL, sModule, "UseSingleClick", 0 );
+ fcOpt.bShowIdle = (BOOL)DBGetContactSettingByte( NULL, sModule, "ShowIdle", 0 );
+
+ if(DBGetContactSettingByte(NULL, "ModernData", "HideBehind", 0))
+ bIsCListShow = (DBGetContactSettingByte(NULL, "ModernData", "BehindEdge", 0)==0);
+ else
+ bIsCListShow = (DBGetContactSettingByte(NULL,"CList","State",0)==2);
+}
+
+void SendMsgDialog( HWND hwnd, char *pText )
+{
+ ThumbInfo *pThumb = thumbList.FindThumb( hwnd );
+
+ if ( pThumb != NULL )
+ CallService( MS_MSG_SENDMESSAGE, (WPARAM)pThumb->hContact, (LPARAM)pText );
+}
+
+
+static void ShowContactMenu( HWND hwnd, POINT pt )
+{
+ ThumbInfo *pThumb = thumbList.FindThumb( hwnd );
+ int idCommand = 0;
+
+ if ( pThumb != NULL )
+ {
+ hContactMenu = (HMENU)CallService( MS_CLIST_MENUBUILDCONTACT, (WPARAM)pThumb->hContact, (LPARAM)0 );
+
+ if ( hContactMenu == NULL ) return;
+
+ idCommand = TrackPopupMenu( hContactMenu, TPM_RIGHTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, 0 , hwnd, NULL );
+ CallService( MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM( idCommand ,MPCF_CONTACTMENU), (LPARAM)pThumb->hContact );
+ }
+}
+
+static LRESULT __stdcall CommWndProc( HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam )
+{
+ LRESULT lResult = 0;
+ ThumbInfo *pThumb = thumbList.FindThumb( hwnd );
+
+ switch( uMsg )
+ {
+ case WM_RBUTTONUP:
+ {
+ POINT pt;
+ pt.x = LOWORD( lParam );
+ pt.y = HIWORD( lParam );
+
+ if (pThumb) pThumb->ThumbDeselect( TRUE );
+
+ ClientToScreen(hwnd,&pt);
+ ShowContactMenu( hwnd, pt );
+ }
+
+ break;
+
+//#if 0
+ case WM_NCPAINT:
+ if(pThumb){
+ HDC hdc = GetWindowDC( hwnd );
+ BitBlt(hdc, 0, 0, pThumb->bmpContent.getWidth(), pThumb->bmpContent.getHeight(), pThumb->bmpContent.getDC(), 0, 0, SRCCOPY);
+ //RepaintWindow( hwnd, hdc );
+ ReleaseDC( hwnd, hdc );
+ ValidateRect( hwnd, NULL );
+ return 0;
+ }
+
+ case WM_PAINT:
+ if(pThumb){
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(hwnd, &ps);
+ BitBlt(hdc, 0, 0, pThumb->bmpContent.getWidth(), pThumb->bmpContent.getHeight(), pThumb->bmpContent.getDC(), 0, 0, SRCCOPY);
+ //RepaintWindow( hwnd, hdc );
+ EndPaint(hwnd, &ps);
+ break;
+ }
+
+ case WM_PRINT:
+ case WM_PRINTCLIENT:
+ if(pThumb){
+ BitBlt((HDC)wParam, 0, 0, pThumb->bmpContent.getWidth(), pThumb->bmpContent.getHeight(), pThumb->bmpContent.getDC(), 0, 0, SRCCOPY);
+ //RepaintWindow(hwnd, (HDC)wParam);
+ break;
+ }
+//#endif
+
+ case WM_MEASUREITEM:
+ lResult = CallService( MS_CLIST_MENUMEASUREITEM,wParam,lParam );
+ break;
+
+ case WM_DRAWITEM:
+ lResult = CallService( MS_CLIST_MENUDRAWITEM,wParam,lParam );
+ break;
+
+ case WM_LBUTTONDOWN:
+ if (pThumb) pThumb->OnLButtonDown( (short)LOWORD( lParam ), (short)HIWORD( lParam ) );
+ break;
+
+ case WM_MOUSEMOVE:
+ if (pThumb) pThumb->OnMouseMove( (short)LOWORD( lParam ), (short)HIWORD( lParam ), wParam);
+ break;
+
+ case WM_LBUTTONUP:
+ if (pThumb) pThumb->OnLButtonUp();
+ //if (bMouseMoved || !DBGetContactSettingByte(NULL, "CList", "Tray1Click", SETTING_TRAY1CLICK_DEFAULT))
+ break;
+ // FALL THRU
+
+ case WM_LBUTTONDBLCLK:
+ // Popup message dialog
+ //if (pThumb) pThumb->ThumbDeselect( TRUE );
+ if(!fcOpt.bUseSingleClick && pThumb)
+ pThumb->PopUpMessageDialog();
+ break;
+
+ case WM_RBUTTONDOWN:
+ if(bEnableTip && fcOpt.bShowTip && pThumb) pThumb->KillTip();
+ break;
+ case WM_REFRESH_CONTACT:
+ if (pThumb)
+ {
+ _tcsncpy( pThumb->ptszName, (TCHAR*)CallService( MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)pThumb->hContact, (LPARAM)GCDNF_TCHAR ), USERNAME_LEN - 1 );
+ pThumb->RefreshContactStatus( (int)lParam );
+ pThumb->ResizeThumb();
+ }
+ break;
+
+ case WM_TIMER:
+ if(pThumb)pThumb->OnTimer(wParam);
+ break;
+
+ case WM_HOTKEY:
+ {
+ ThumbInfo *pThumb = thumbList.FindThumb( ( HWND )wParam );
+
+ if (pThumb) pThumb->PopUpMessageDialog();
+ }
+
+ default:
+ break;
+ }
+
+ lResult = DefWindowProc( hwnd, uMsg, wParam, lParam );
+
+ return( lResult );
+}
+
+
+
+extern void SetThumbsOpacity( BYTE btAlpha )
+{
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ thumbList[i]->SetThumbOpacity( btAlpha );
+}
+
+
+
+static void GetScreenRect()
+{
+ rcScreen.left = GetSystemMetrics( SM_XVIRTUALSCREEN );
+ rcScreen.top = GetSystemMetrics( SM_YVIRTUALSCREEN );
+ rcScreen.right = GetSystemMetrics( SM_CXVIRTUALSCREEN ) + rcScreen.left;
+ rcScreen.bottom = GetSystemMetrics( SM_CYVIRTUALSCREEN ) + rcScreen.top;
+}
+
+
+
+void OnStatusChanged()
+{
+ int idStatus = ID_STATUS_OFFLINE;
+
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ {
+ idStatus = GetContactStatus( thumbList[i]->hContact );
+ thumbList[i]->RefreshContactStatus( idStatus );
+ }
+}
+
+
+
+void ApplyOptionsChanges()
+{
+ CreateThumbsFont();
+ CreateBackgroundBrush();
+
+// dwOfflineModes = DBGetContactSettingDword( NULL, "CLC","OfflineModes", CLCDEFAULT_OFFLINEMODES );
+ if(!fcOpt.bToTop && ToTopTimerID){
+ KillTimer(NULL, ToTopTimerID);
+ ToTopTimerID = 0;
+ }
+ if(fcOpt.bToTop){
+ if (ToTopTimerID) KillTimer(NULL, ToTopTimerID);
+ fcOpt.ToTopTime = (fcOpt.ToTopTime<1)?1:fcOpt.ToTopTime;
+ fcOpt.ToTopTime = (fcOpt.ToTopTime>TOTOPTIME_MAX)?TOTOPTIME_MAX:fcOpt.ToTopTime;
+ ToTopTimerID = SetTimer(NULL, 0, fcOpt.ToTopTime*TOTOPTIME_P, ToTopTimerProc);
+ }
+
+ OnStatusChanged();
+
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ thumbList[i]->ResizeThumb();
+}
+
+
+
+///////////////////////////////////////////////////////
+// Window creation
+static void RegisterWindowClass()
+{
+ WNDCLASSEX wcx;
+ ZeroMemory( &wcx, sizeof( wcx ) );
+
+ wcx.cbSize = sizeof( WNDCLASSEX );
+ wcx.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
+ wcx.lpfnWndProc = CommWndProc;
+ wcx.cbClsExtra = 0;
+ wcx.cbWndExtra = 0;
+ wcx.hInstance = hInst;
+ wcx.hIcon = NULL;
+ wcx.hCursor = NULL;
+ wcx.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
+ wcx.lpszMenuName = NULL;
+ wcx.lpszClassName = WND_CLASS;
+ wcx.hIconSm = NULL;
+
+ SetLastError( 0 );
+
+ RegisterClassEx( &wcx );
+}
+
+
+
+static void UnregisterWindowClass()
+{
+ UnregisterClass( WND_CLASS, hInst );
+}
+
+
+
+static void CreateThumbWnd( TCHAR *ptszName, HANDLE hContact, int nX, int nY )
+{
+ HWND hwnd = NULL;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+
+ // Prepare for window creation
+ if ( pThumb == NULL )
+ {
+ hwnd = CreateWindowEx( WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
+ WND_CLASS,
+ ptszName,
+ WS_POPUP,
+ nX,
+ nY,
+ 50,
+ 20,
+ NULL /*hwndMiranda*/,
+ NULL,
+ hInst,
+ NULL
+ );
+
+ if ( hwnd != NULL )
+ {
+ pThumb = thumbList.AddThumb( hwnd, ptszName, hContact );
+ SetWindowLong( hwnd, GWL_USERDATA, (long)pThumb );
+ pThumb->ResizeThumb();
+
+ pThumb->SetThumbOpacity( fcOpt.thumbAlpha );
+ ShowWindow( hwnd, ( fcOpt.bHideAll || HideOnFullScreen() || fcOpt.bHideOffline || (fcOpt.bHideWhenCListShow && bIsCListShow) )? SW_HIDE : SW_SHOWNA );
+ pThumb->PositionThumb( (short)nX, (short)nY );
+
+ // force repaint
+ pThumb->UpdateContent();
+ }
+ }
+}
+
+
+
+static BOOL GetOSPlatform()
+{
+ OSVERSIONINFO VersionInfo;
+
+ // Get OS platform
+ ZeroMemory( &VersionInfo, sizeof( VersionInfo ) );
+ VersionInfo.dwOSVersionInfoSize = sizeof( VersionInfo );
+
+ GetVersionEx( &VersionInfo );
+ return( VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT );
+}
+
+
+
+static void CreateThumbsFont()
+{
+ int nFontId;
+ LOGFONTA lf;
+
+ for (nFontId = 0; nFontId < FLT_FONTIDS; nFontId++)
+ {
+ if (NULL != hFont[nFontId])
+ {
+ DeleteObject(hFont[nFontId]);
+ hFont[nFontId] = NULL;
+ }
+ GetFontSetting(TRUE, nFontId, &lf, &tColor[nFontId]);
+ {
+ LONG height;
+ HDC hdc=GetDC(NULL);
+ height=lf.lfHeight;
+ lf.lfHeight=-MulDiv(lf.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+ ReleaseDC(NULL,hdc);
+
+ hFont[nFontId] = CreateFontIndirectA(&lf);
+
+ lf.lfHeight=height;
+ }
+ }
+}
+
+
+
+static void CreateBackgroundBrush()
+{
+// LOGBRUSH lb;
+ bkColor = DBGetContactSettingDword(NULL, sModule, "BkColor", FLT_DEFAULT_BKGNDCOLOR);
+
+
+ if (NULL != hLTEdgesPen)
+ {
+ DeleteObject(hLTEdgesPen);
+ hLTEdgesPen = NULL;
+ }
+ if (NULL != hRBEdgesPen)
+ {
+ DeleteObject(hRBEdgesPen);
+ hRBEdgesPen = NULL;
+ }
+ if (NULL != hBmpBackground)
+ {
+ DeleteObject(hBmpBackground);
+ hBmpBackground = NULL;
+ }
+ if (NULL != hBkBrush)
+ {
+ SetClassLong((HWND)WND_CLASS, GCL_HBRBACKGROUND, (LONG)NULL);
+ DeleteObject( hBkBrush );
+ hBkBrush = NULL;
+ }
+
+ if (DBGetContactSettingByte(NULL, sModule, "DrawBorder", FLT_DEFAULT_DRAWBORDER))
+ {
+ COLORREF cr;
+
+ cr = (COLORREF)DBGetContactSettingDword(NULL, sModule, "LTEdgesColor", FLT_DEFAULT_LTEDGESCOLOR);
+ hLTEdgesPen = CreatePen(PS_SOLID, 1, cr);
+ cr = (COLORREF)DBGetContactSettingDword(NULL, sModule, "RBEdgesColor", FLT_DEFAULT_RBEDGESCOLOR);
+ hRBEdgesPen = CreatePen(PS_SOLID, 1, cr);
+ }
+ if (DBGetContactSettingByte(NULL, sModule, "BkUseBitmap", FLT_DEFAULT_BKGNDUSEBITMAP))
+ {
+ DBVARIANT dbv;
+
+ if (!DBGetContactSetting(NULL, sModule, "BkBitmap", &dbv))
+ {
+ hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP, 0, (LPARAM)dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+ nBackgroundBmpUse = (WORD)DBGetContactSettingWord(NULL, sModule, "BkBitmapOpt", FLT_DEFAULT_BKGNDBITMAPOPT);
+
+ // Create brush
+ hBkBrush = CreateSolidBrush(bkColor);
+
+ // Attach brush to the window
+ SetClassLong((HWND)WND_CLASS, GCL_HBRBACKGROUND, (LONG)hBkBrush);
+}
+
+
+static int GetContactStatus( HANDLE hContact )
+{
+ char *szProto = NULL;
+ int idStatus = ID_STATUS_OFFLINE;
+
+ if ( hContact == NULL )
+ {
+ assert( !"Contact is NULL" );
+ return( 0 );
+ }
+
+ szProto = ( char* )CallService( "Proto/GetContactBaseProto", (WPARAM)hContact, 0 );
+
+ if ( NULL != szProto )
+ {
+ idStatus = DBGetContactSettingWord( hContact, szProto, "Status", ID_STATUS_OFFLINE );
+ }
+
+
+ return( idStatus );
+}
+
+
+static int ClcStatusToPf2( int status )
+{
+ switch(status) {
+ case ID_STATUS_ONLINE: return PF2_ONLINE;
+ case ID_STATUS_AWAY: return PF2_SHORTAWAY;
+ case ID_STATUS_DND: return PF2_HEAVYDND;
+ case ID_STATUS_NA: return PF2_LONGAWAY;
+ case ID_STATUS_OCCUPIED: return PF2_LIGHTDND;
+ case ID_STATUS_FREECHAT: return PF2_FREECHAT;
+ case ID_STATUS_INVISIBLE: return PF2_INVISIBLE;
+ case ID_STATUS_ONTHEPHONE: return PF2_ONTHEPHONE;
+ case ID_STATUS_OUTTOLUNCH: return PF2_OUTTOLUNCH;
+ case ID_STATUS_OFFLINE: return MODEF_OFFLINE;
+ }
+ return 0;
+}
+
+BOOL IsStatusVisible( int status )
+{
+ return ( 0 == ( dwOfflineModes & ClcStatusToPf2( status ) ) );
+}
+
+
+
+void RegHotkey( HANDLE hContact, HWND hwnd )
+{
+ char szBuf[ MAX_PATH ]= {0};
+/* char szPath[ MAX_PATH ]= {0};
+
+ GetModuleFileName( NULL, szPath, MAX_PATH );
+ PathRemoveFileSpec( szPath );
+ strcat( szPath, "\\Thumbs.ini" );
+ GetPrivateProfileString( "Hotkeys", szName, "", szBuf, MAX_PATH - 1, szPath );*/
+ DBVARIANT dbv;
+ if(DBGetContactSettingString ( hContact, sModule, "Hotkey", &dbv)) return;
+ strncpy(szBuf, dbv.pszVal, MAX_PATH - 1);
+ DBFreeVariant( &dbv );
+
+ if ( 0 != strlen( szBuf ) )
+ {
+ UINT nModifiers = 0;
+ char chKey = 0;
+ char szMod[ 2 ][ 20 ] = {0};
+ char szKey[ 20 ] = {0};
+ int i = 0;
+
+ sscanf( szBuf, "%[^'+']+%[^'+']+%[^'+']", szMod[ 0 ], szMod[ 1 ], szKey );
+
+ for ( i = 0; i < 2; ++i )
+ {
+ if( 0 == strncmp( szMod[ i ], "ALT", 19 ) )
+ {
+ nModifiers = nModifiers | MOD_ALT;
+ }
+ else if( 0 == strncmp( szMod[ i ], "CTRL", 19 ) )
+ {
+ nModifiers = nModifiers | MOD_CONTROL;
+ }
+ else if( 0 == strncmp( szMod[ i ], "SHIFT", 19 ) )
+ {
+ nModifiers = nModifiers | MOD_SHIFT;
+ }
+ }
+
+ chKey = szKey[ 0 ];
+
+ RegisterHotKey( hwnd, (int)hwnd, nModifiers, VkKeyScan( chKey ) );
+ }
+}
+
+
+
+///////////////////////////////////////////////////////
+// Contact sttings
+
+void SaveContactsPos()
+{
+ RECT rc;
+
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ {
+ SetLastError( 0 );
+
+ thumbList[i]->GetThumbRect( &rc );
+
+ if( 0 == GetLastError() )
+ DBWriteContactSettingDword( thumbList[i]->hContact, sModule, "ThumbsPos", DB_POS_MAKE_XY(rc.left,rc.top) );
+ }
+}
+
+
+static void LoadContacts()
+{
+ HANDLE hContact = (HANDLE)CallService( MS_DB_CONTACT_FINDFIRST, 0, 0) ;
+
+ while( hContact != NULL )
+ {
+ LoadContact( hContact );
+
+ hContact = (HANDLE)CallService( MS_DB_CONTACT_FINDNEXT, ( WPARAM ) hContact, 0 );
+ }
+}
+
+
+
+
+static void LoadMenus()
+{
+ CLISTMENUITEM mi;
+
+ // Remove thumb menu item
+ hRemoveThumb = CreateServiceFunction( sModule "/RemoveThumb",OnContactMenu_Remove );
+ ZeroMemory( &mi,sizeof( mi ) );
+
+ mi.cbSize = sizeof( mi );
+ mi.position = 0xFFFFF;
+ mi.flags = CMIF_TCHAR;
+ mi.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_HIDE ) );
+ mi.ptszName = _T("Remove thumb");
+ mi.pszService = sModule "/RemoveThumb";
+ hMenuItemRemove = (HANDLE)CallService( MS_CLIST_ADDCONTACTMENUITEM,0, ( LPARAM )&mi );
+
+ // Hide all thumbs main menu item
+ hMainHideAllThumbs = CreateServiceFunction( sModule "/MainHideAllThumbs",OnMainMenu_HideAll );
+ ZeroMemory( &mi,sizeof( mi ) );
+
+ mi.cbSize = sizeof( mi );
+ mi.position = 0xFFFFF;
+ mi.flags = CMIF_TCHAR;
+ mi.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( fcOpt.bHideAll ? IDI_SHOW : IDI_HIDE ) );
+ mi.ptszName = fcOpt.bHideAll ? _T("Show all thumbs") : _T("Hide all thumbs");
+ mi.pszService = sModule "/MainHideAllThumbs";
+ hMainMenuItemHideAll = (HANDLE)CallService( MS_CLIST_ADDMAINMENUITEM,0, ( LPARAM )&mi );
+
+ if(ServiceExists(MS_HOTKEY_REGISTER)){
+ HOTKEYDESC hkd={0};
+
+ hkd.cbSize = sizeof(hkd);
+ hkd.pszSection = "Floating Contacts";
+
+ hkd.pszName = sModule "/MainHideAllThumbs";
+ hkd.pszDescription = "Show/Hide all thumbs";
+ hkd.pszService = sModule "/MainHideAllThumbs";
+ CallService(MS_HOTKEY_REGISTER, 0, (LPARAM)&hkd);
+
+ hHideWhenCListShow = CreateServiceFunction( sModule "/HideWhenCListShow",OnHotKey_HideWhenCListShow );
+ hkd.pszName = sModule "/HideWhenCListShow";
+ hkd.pszDescription = "Hide when contact list is shown";
+ hkd.pszService = sModule "/HideWhenCListShow";
+ CallService(MS_HOTKEY_REGISTER, 0, (LPARAM)&hkd);
+ }
+}
+
+
+static void LoadContact( HANDLE hContact )
+{
+ DWORD dwPos = (DWORD)-1;
+ TCHAR *ptName = NULL;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+ int nX, nY;
+
+
+ if ( hContact == NULL ) return;
+
+ dwPos = DBGetContactSettingDword( hContact, sModule, "ThumbsPos", (DWORD)-1 );
+
+ if ( dwPos != -1 )
+ {
+ ptName = (TCHAR*)CallService( MS_CLIST_GETCONTACTDISPLAYNAME, ( WPARAM )hContact, (LPARAM)GCDNF_TCHAR );
+
+ if ( ptName != NULL )
+ {
+ nX = DB_POS_GETX( dwPos );
+ nY = DB_POS_GETY( dwPos );
+
+ CreateThumbWnd( ptName, hContact, nX, nY );
+ pThumb->PositionThumb( (short)nX, (short)nY );
+ }
+ }
+}
+
+
+BOOL HideOnFullScreen()
+{
+ BOOL bFullscreen = FALSE;
+ HWND hWnd = 0;
+
+ if ( fcOpt.bHideWhenFullscreen )
+ {
+ int w = GetSystemMetrics(SM_CXSCREEN);
+ int h = GetSystemMetrics(SM_CYSCREEN);
+
+ hWnd = GetForegroundWindow();
+
+ while (GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_TOPMOST)
+ {
+ RECT WindowRect;
+ GetWindowRect(hWnd, &WindowRect);
+
+ if ( (w == (WindowRect.right - WindowRect.left) ) &&
+ (h == (WindowRect.bottom - WindowRect.top)))
+ {
+ bFullscreen = TRUE;
+ break;
+ }
+
+ hWnd = GetNextWindow( hWnd, GW_HWNDNEXT );
+ }
+ }
+
+ return bFullscreen && fcOpt.bHideWhenFullscreen;
+}
+
+
+static int OnContactMenu_Remove( WPARAM wParam,LPARAM lParam )
+{
+ HANDLE hContact = ( HANDLE )wParam;
+ ThumbInfo *pThumb = thumbList.FindThumbByContact( hContact );
+
+ if (pThumb)
+ {
+ pThumb->DeleteContactPos();
+ thumbList.RemoveThumb(pThumb);
+ }
+
+ DestroyMenu( hContactMenu );
+
+ return 0;
+}
+
+static int OnHotKey_HideWhenCListShow( WPARAM wParam,LPARAM lParam )
+{
+ fcOpt.bHideWhenCListShow=!fcOpt.bHideWhenCListShow;
+ DBWriteContactSettingByte(NULL, sModule, "HideWhenCListShow", (BYTE)fcOpt.bHideWhenCListShow);
+ OnStatusChanged();
+ return 0;
+}
+
+
+static int OnMainMenu_HideAll( WPARAM wParam,LPARAM lParam )
+{
+ CLISTMENUITEM clmi = {0};
+ int b;
+
+ fcOpt.bHideAll = !fcOpt.bHideAll;
+ DBWriteContactSettingByte(NULL, sModule, "HideAll", (BYTE)fcOpt.bHideAll);
+ OnStatusChanged();
+
+ clmi.cbSize = sizeof( clmi );
+ clmi.flags = CMIM_NAME | CMIM_ICON|CMIF_TCHAR;
+ clmi.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( fcOpt.bHideAll ? IDI_SHOW : IDI_HIDE ) );
+ clmi.ptszName = fcOpt.bHideAll ? _T("Show all thumbs") : _T("Hide all thumbs");
+ b = CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMainMenuItemHideAll, ( LPARAM )&clmi );
+ return 0;
+}
+
+static VOID CALLBACK ToTopTimerProc ( HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ {
+ SetWindowPos(thumbList[i]->hwnd,
+ HWND_TOPMOST,
+ 0,
+ 0,
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOMOVE | /*SWP_NOZORDER |*/ SWP_NOACTIVATE);
+ }
+}
+
+void ShowThumbsOnHideCList()
+{
+ if(!fcOpt.bHideWhenCListShow || fcOpt.bHideAll || HideOnFullScreen())return;
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ {
+ if ( !fcOpt.bHideOffline || IsStatusVisible( GetContactStatus(thumbList[i]->hContact) ) )
+ {
+ ShowWindow( thumbList[i]->hwnd, SW_SHOWNA );
+ }
+ }
+}
+
+
+void HideThumbsOnShowCList()
+{
+ if(!fcOpt.bHideWhenCListShow || fcOpt.bHideAll || HideOnFullScreen())return;
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ ShowWindow( thumbList[i]->hwnd, SW_HIDE );
+}
+
+static LRESULT __stdcall newMirandaWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ if( uMsg == WM_WINDOWPOSCHANGED)
+ {
+ WINDOWPOS *wp = (WINDOWPOS *)lParam;
+ if(wp->flags&SWP_HIDEWINDOW) {
+ bIsCListShow = FALSE;
+ ShowThumbsOnHideCList();
+ }
+ else if(wp->flags&SWP_SHOWWINDOW){
+ bIsCListShow = TRUE;
+ HideThumbsOnShowCList();
+ }
+ else if(!(wp->flags&SWP_NOMOVE)){
+ BYTE method=DBGetContactSettingByte(NULL, "ModernData", "HideBehind", 0);
+ if(method) {
+ WORD wBehindEdgeBorderSize=DBGetContactSettingWord(NULL, "ModernData", "HideBehindBorderSize", 0);
+ RECT rc = {wp->x, wp->y, wp->x+wp->cx, wp->y+wp->cy};
+ RECT rcScreen = {wBehindEdgeBorderSize*(2-method), 0, GetSystemMetrics(SM_CXSCREEN)-wBehindEdgeBorderSize*(method-1), GetSystemMetrics(SM_CYSCREEN)};
+ RECT rcOverlap;
+ BOOL isIntersect;
+
+ isIntersect = IntersectRect( &rcOverlap, &rc, &rcScreen );
+ if ( !isIntersect && bIsCListShow ){
+ bIsCListShow = FALSE;
+ ShowThumbsOnHideCList();
+ }
+ else if ( isIntersect && !bIsCListShow ){
+ bIsCListShow = TRUE;
+ HideThumbsOnShowCList();
+ }
+ }
+ }
+ }
+ return( CallWindowProc(oldMirandaWndProc, hwnd, uMsg, wParam, lParam) );
+}
diff --git a/plugins/FloatingContacts/options.cpp b/plugins/FloatingContacts/options.cpp
new file mode 100644
index 0000000000..be257e7456
--- /dev/null
+++ b/plugins/FloatingContacts/options.cpp
@@ -0,0 +1,1179 @@
+
+#include "stdhdr.h"
+
+#include "resource.h"
+#include "fltcont.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+#define SAMEASF_FACE 1
+#define SAMEASF_SIZE 2
+#define SAMEASF_STYLE 4
+#define SAMEASF_COLOUR 8
+
+typedef struct _SFontSettings
+{
+ BYTE sameAsFlags,sameAs;
+ COLORREF colour;
+ char size;
+ BYTE style;
+ BYTE charset;
+ char szFace[LF_FACESIZE];
+} SFontSettings;
+
+static SFontSettings s_rgFontSettings[FLT_FONTIDS];
+static SFontSettings s_rgFontSettingsMiranda[FLT_FONTIDS];
+
+#define FLT_SAME_AS_NONE ((BYTE)0xFF)
+#define FLT_SAME_AS_MIRANDA ((BYTE)0xFE)
+
+static char* s_rgszFontSizes[]={"8","10","14","16","18","20","24","28"};
+
+static const TCHAR* s_rgszFontIdDescr[FLT_FONTIDS] =
+{
+ _T("Standard contacts"),
+ _T("Online contacts to whom you have a different visibility"),
+ _T("Offline contacts"),
+ _T("Offline contacts to whom you have a different visibility"),
+ _T("Contacts which are 'not on list'"),
+};
+
+static WORD s_rgwFontSameAsDefault[FLT_FONTIDS] =
+{
+ MAKEWORD(FLT_SAME_AS_MIRANDA, 0x0F),
+ MAKEWORD(FLT_SAME_AS_MIRANDA, 0x0F),
+ MAKEWORD(FLT_SAME_AS_MIRANDA, 0x0F),
+ MAKEWORD(FLT_SAME_AS_MIRANDA, 0x0F),
+ MAKEWORD(FLT_SAME_AS_MIRANDA, 0x0F),
+};
+
+static int s_rgnMirandaFontId[FLT_FONTIDS] =
+{
+ FONTID_CONTACTS,
+ FONTID_INVIS,
+ FONTID_OFFLINE,
+ FONTID_OFFINVIS,
+ FONTID_NOTONLIST
+};
+
+#define M_REBUILDFONTGROUP (WM_USER + 10)
+#define M_REMAKESAMPLE (WM_USER + 11)
+#define M_RECALCONEFONT (WM_USER + 12)
+#define M_RECALCOTHERFONTS (WM_USER + 13)
+#define M_SAVEFONT (WM_USER + 14)
+#define M_REFRESHSAMEASBOXES (WM_USER + 15)
+#define M_FILLSCRIPTCOMBO (WM_USER + 16)
+#define M_LOADFONT (WM_USER + 17)
+#define M_GUESSSAMEASBOXES (WM_USER + 18)
+#define M_SETSAMEASBOXES (WM_USER + 19)
+
+#define M_REFRESHBKGBOXES (WM_USER + 20)
+#define M_REFRESHBORDERPICKERS (WM_USER + 21)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+static
+LRESULT
+APIENTRY
+OptWndProc
+ ( IN HWND hwndDlg
+ , IN UINT uMsg
+ , IN WPARAM wParam
+ , IN LPARAM lParam
+ );
+
+static
+LRESULT
+APIENTRY
+OptSknWndProc
+ ( IN HWND hwndDlg
+ , IN UINT uMsg
+ , IN WPARAM wParam
+ , IN LPARAM lParam
+ );
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+int
+OnOptionsInitialize
+ ( IN WPARAM wParam
+ , IN LPARAM lParam
+ )
+{
+ OPTIONSDIALOGPAGE odp;
+
+ ZeroMemory(&odp, sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_FLTCONT);
+ odp.ptszTitle = _T("Floating Contacts");
+ odp.ptszGroup = _T("Plugins");
+ odp.ptszTab = _T("Main Features");
+ odp.flags = ODPF_BOLDGROUPS|ODPF_TCHAR;
+ odp.pfnDlgProc = (DLGPROC)OptWndProc;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp);
+
+ ZeroMemory(&odp, sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SKIN);
+ odp.ptszTitle = _T("Floating Contacts");
+ odp.ptszGroup = _T("Plugins");
+ odp.ptszTab = _T("Appearance");
+ odp.flags = ODPF_BOLDGROUPS|ODPF_TCHAR;
+ odp.pfnDlgProc = (DLGPROC)OptSknWndProc;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp);
+
+ return 0;
+}
+
+static
+int
+CALLBACK
+EnumFontsProc
+ ( IN ENUMLOGFONTEXA* lpelfe
+ , IN NEWTEXTMETRICEXA* lpntme
+ , IN int FontType
+ , IN LPARAM lParam
+ )
+{
+ if (IsWindow((HWND)lParam))
+ {
+ if (CB_ERR == SendMessageA((HWND)lParam, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)lpelfe->elfLogFont.lfFaceName))
+ SendMessageA((HWND)lParam, CB_ADDSTRING, 0, (LPARAM)lpelfe->elfLogFont.lfFaceName);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void
+FillFontListThread
+ ( IN HWND hwndDlg
+ )
+{
+ LOGFONTA lf = {0};
+ HDC hdc = GetDC(hwndDlg);
+
+ lf.lfCharSet = DEFAULT_CHARSET;
+ lf.lfFaceName[0] = 0;
+ lf.lfPitchAndFamily = 0;
+ EnumFontFamiliesExA(hdc, &lf, (FONTENUMPROCA)EnumFontsProc, (LPARAM)GetDlgItem(hwndDlg,IDC_TYPEFACE), 0);
+ ReleaseDC(hwndDlg, hdc);
+ return;
+}
+
+static
+int
+CALLBACK
+EnumFontScriptsProc
+ ( IN ENUMLOGFONTEX* lpelfe
+ , IN NEWTEXTMETRICEX* lpntme
+ , IN int FontType
+ , IN LPARAM lParam
+ )
+{
+ if (CB_ERR == SendMessage((HWND)lParam, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)lpelfe->elfScript))
+ {
+ int i = SendMessage((HWND)lParam, CB_ADDSTRING, 0, (LPARAM)lpelfe->elfScript);
+ SendMessage((HWND)lParam, CB_SETITEMDATA, i, lpelfe->elfLogFont.lfCharSet);
+ }
+ return TRUE;
+}
+
+static
+void
+GetDefaultFontSetting
+ ( IN BOOL bFltContacts
+ , IN int nFontId
+ , IN LOGFONTA* lf
+ , IN COLORREF* colour
+ )
+{
+ SystemParametersInfoA(SPI_GETICONTITLELOGFONT, sizeof(LOGFONTA), lf, FALSE);
+ *colour = GetSysColor(COLOR_WINDOWTEXT);
+ if (bFltContacts)
+ {
+ switch (nFontId)
+ {
+ case FLT_FONTID_OFFINVIS:
+ case FLT_FONTID_INVIS:
+ lf->lfItalic = !lf->lfItalic;
+ break;
+
+ case FLT_FONTID_NOTONLIST:
+ *colour = GetSysColor(COLOR_3DSHADOW);
+ break;
+ }
+ }
+ else
+ {
+ switch (s_rgnMirandaFontId[nFontId])
+ {
+ case FONTID_OFFINVIS:
+ case FONTID_INVIS:
+ lf->lfItalic = !lf->lfItalic;
+ break;
+
+ case FONTID_NOTONLIST:
+ *colour = GetSysColor(COLOR_3DSHADOW);
+ break;
+ }
+ }
+}
+
+void
+GetFontSetting
+ ( IN BOOL bFltContacts
+ , IN int nFontId
+ , IN LOGFONTA* lf
+ , IN COLORREF* colour
+ )
+{
+ DBVARIANT dbv;
+ char idstr[10];
+ BYTE style;
+ const char* pModule = (bFltContacts ? sModule : "CLC");
+
+ GetDefaultFontSetting(bFltContacts, nFontId, lf, colour);
+ if (!bFltContacts)
+ nFontId = s_rgnMirandaFontId[nFontId];
+ wsprintfA(idstr, "Font%dName", nFontId);
+ if (!DBGetContactSetting(NULL, pModule, idstr, &dbv))
+ {
+ lstrcpyA(lf->lfFaceName, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+
+ wsprintfA(idstr, "Font%dCol", nFontId);
+ *colour = DBGetContactSettingDword(NULL, pModule, idstr, *colour);
+
+ wsprintfA(idstr, "Font%dSize", nFontId);
+ lf->lfHeight = (char)DBGetContactSettingByte(NULL, pModule, idstr, lf->lfHeight);
+
+ wsprintfA(idstr, "Font%dSty", nFontId);
+ style = (BYTE)DBGetContactSettingByte(NULL, pModule, idstr
+ , (lf->lfWeight == FW_NORMAL ? 0 : DBFONTF_BOLD)
+ | (lf->lfItalic ? DBFONTF_ITALIC : 0)
+ | (lf->lfUnderline ? DBFONTF_UNDERLINE : 0)
+ );
+ lf->lfWidth = lf->lfEscapement = lf->lfOrientation = 0;
+ lf->lfWeight = ((style & DBFONTF_BOLD) ? FW_BOLD : FW_NORMAL);
+ lf->lfItalic = (0 != (style & DBFONTF_ITALIC));
+ lf->lfUnderline = (0 != (style & DBFONTF_UNDERLINE));
+ lf->lfStrikeOut = 0;
+
+ wsprintfA(idstr, "Font%dSet", nFontId);
+ lf->lfCharSet = (BYTE)DBGetContactSettingByte(NULL, pModule, idstr, lf->lfCharSet);
+ lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
+ lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf->lfQuality = DEFAULT_QUALITY;
+ lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+
+ if (bFltContacts)
+ {
+ WORD wSameAs;
+ BYTE bySameAs;
+ BYTE bySameAsFlags;
+
+ wsprintfA(idstr, "Font%dAs", nFontId);
+ wSameAs = (WORD)DBGetContactSettingWord(NULL, sModule, idstr, s_rgwFontSameAsDefault[nFontId]);
+ bySameAs=LOBYTE(wSameAs);
+ bySameAsFlags=HIBYTE(wSameAs);
+
+ if (FLT_SAME_AS_MIRANDA == bySameAs)
+ {
+ LOGFONTA lfMiranda;
+ COLORREF colourMiranda;
+
+ GetFontSetting(FALSE, nFontId, &lfMiranda, &colourMiranda);
+ if (bySameAsFlags & SAMEASF_FACE)
+ {
+ lstrcpyA(lf->lfFaceName, lfMiranda.lfFaceName);
+ lf->lfCharSet = lfMiranda.lfCharSet;
+ }
+ if (bySameAsFlags & SAMEASF_SIZE)
+ lf->lfHeight = lfMiranda.lfHeight;
+ if (bySameAsFlags & SAMEASF_STYLE)
+ {
+ lf->lfWeight = lfMiranda.lfWeight;
+ lf->lfItalic = lfMiranda.lfItalic;
+ lf->lfUnderline = lfMiranda.lfUnderline;
+ }
+ if (bySameAsFlags & SAMEASF_COLOUR)
+ *colour = colourMiranda;
+ }
+ }
+}
+
+static
+LRESULT
+APIENTRY
+OptWndProc
+ ( IN HWND hwndDlg
+ , IN UINT uMsg
+ , IN WPARAM wParam
+ , IN LPARAM lParam
+ )
+{
+ switch ( uMsg )
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ // Properties
+ CheckDlgButton(hwndDlg, IDC_CHK_HIDE_OFFLINE, (fcOpt.bHideOffline ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHK_HIDE_ALL, (fcOpt.bHideAll ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHK_HIDE_WHEN_FULSCREEN, (fcOpt.bHideWhenFullscreen ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHK_STICK, (fcOpt.bMoveTogether ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHK_WIDTH, (fcOpt.bFixedWidth ? BST_CHECKED : BST_UNCHECKED));
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_WIDTH), fcOpt.bFixedWidth);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_WIDTH), fcOpt.bFixedWidth);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_WIDTHSPIN), fcOpt.bFixedWidth);
+
+ SendDlgItemMessage(hwndDlg, IDC_WIDTHSPIN, UDM_SETRANGE, 0, MAKELONG(255,0));
+ SendDlgItemMessage(hwndDlg, IDC_WIDTHSPIN, UDM_SETPOS, 0, fcOpt.nThumbWidth);
+
+ CheckDlgButton(hwndDlg, IDC_CHK_TIP, (fcOpt.bShowTip ? BST_CHECKED : BST_UNCHECKED));
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_TIP), bEnableTip);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_TIMEIN), bEnableTip && fcOpt.bShowTip);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_TIMEIN_CMT), bEnableTip && fcOpt.bShowTip);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_TIMEIN), bEnableTip && fcOpt.bShowTip);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TIMEINSPIN), bEnableTip && fcOpt.bShowTip);
+
+ SendDlgItemMessage(hwndDlg, IDC_TIMEINSPIN, UDM_SETRANGE, 0, MAKELONG(5000,0));
+ SendDlgItemMessage(hwndDlg, IDC_TIMEINSPIN, UDM_SETPOS, 0, fcOpt.TimeIn);
+
+ CheckDlgButton(hwndDlg, IDC_CHK_TOTOP, (fcOpt.bToTop ? BST_CHECKED : BST_UNCHECKED));
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_TOTOP), fcOpt.bToTop);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_TOTOPTIME), fcOpt.bToTop);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TOTOPTIMESPIN), fcOpt.bToTop);
+
+ SendDlgItemMessage(hwndDlg, IDC_TOTOPTIMESPIN, UDM_SETRANGE, 0, MAKELONG(TOTOPTIME_MAX,1));
+ SendDlgItemMessage(hwndDlg, IDC_TOTOPTIMESPIN, UDM_SETPOS, 0, fcOpt.ToTopTime);
+
+ CheckDlgButton(hwndDlg, IDC_CHK_HIDE_WHEN_CLISTSHOW, (fcOpt.bHideWhenCListShow ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHK_SINGLECLK, (fcOpt.bUseSingleClick ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_CHK_SHOWIDLE, (fcOpt.bShowIdle ? BST_CHECKED : BST_UNCHECKED));
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_CHK_WIDTH:
+ {
+ if (BN_CLICKED == HIWORD(wParam))
+ {
+ BOOL bChecked = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_WIDTH);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_WIDTH ), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_WIDTH ), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_WIDTHSPIN), bChecked);
+ }
+ break;
+ }
+ case IDC_TXT_WIDTH:
+ {
+ if (EN_CHANGE != HIWORD(wParam) || (HWND)lParam != GetFocus())
+ return 0;
+ break;
+ }
+ case IDC_CHK_TIP:
+ {
+ if (BN_CLICKED == HIWORD(wParam))
+ {
+ BOOL bChecked = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_TIP);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_TIMEIN ), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_TIMEIN_CMT ), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_TIMEIN ), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TIMEINSPIN), bChecked);
+ }
+ break;
+ }
+ case IDC_TXT_TIMEIN:
+ {
+ if (EN_CHANGE != HIWORD(wParam) || (HWND)lParam != GetFocus())
+ return 0;
+ break;
+ }
+ case IDC_CHK_TOTOP:
+ {
+ if (BN_CLICKED == HIWORD(wParam))
+ {
+ BOOL bChecked = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_TOTOP);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_TOTOP ), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_TOTOPTIME ), bChecked);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TOTOPTIMESPIN), bChecked);
+ }
+ break;
+ }
+ case IDC_TXT_TOTOPTIME:
+ {
+ if (EN_CHANGE != HIWORD(wParam) || (HWND)lParam != GetFocus())
+ return 0;
+ break;
+ }
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ LPNMHDR phdr = (LPNMHDR)(lParam);
+
+ if (0 == phdr->idFrom)
+ {
+ switch (phdr->code)
+ {
+ case PSN_APPLY:
+ {
+ BOOL bSuccess = FALSE;
+
+ fcOpt.bHideOffline = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_HIDE_OFFLINE);
+ DBWriteContactSettingByte(NULL, sModule, "HideOffline", (BYTE)fcOpt.bHideOffline);
+
+ fcOpt.bHideAll = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_HIDE_ALL);
+ DBWriteContactSettingByte(NULL, sModule, "HideAll", (BYTE)fcOpt.bHideAll);
+
+ fcOpt.bHideWhenFullscreen = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_HIDE_WHEN_FULSCREEN);
+ DBWriteContactSettingByte(NULL, sModule, "HideWhenFullscreen", (BYTE)fcOpt.bHideWhenFullscreen);
+
+ fcOpt.bMoveTogether = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_STICK);
+ DBWriteContactSettingByte(NULL, sModule, "MoveTogether", (BYTE)fcOpt.bMoveTogether);
+
+ fcOpt.bFixedWidth = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_WIDTH);
+ DBWriteContactSettingByte(NULL, sModule, "FixedWidth", (BYTE)fcOpt.bFixedWidth);
+ fcOpt.nThumbWidth = GetDlgItemInt(hwndDlg, IDC_TXT_WIDTH, &bSuccess, FALSE);
+ DBWriteContactSettingDword(NULL, sModule, "Width", fcOpt.nThumbWidth );
+
+ if(bEnableTip)
+ {
+ fcOpt.bShowTip = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_TIP);
+ DBWriteContactSettingByte(NULL, sModule, "ShowTip", (BYTE)fcOpt.bShowTip);
+ fcOpt.TimeIn = GetDlgItemInt(hwndDlg, IDC_TXT_TIMEIN, &bSuccess, FALSE);
+ DBWriteContactSettingWord(NULL, sModule, "TimeIn", fcOpt.TimeIn );
+ }
+
+ fcOpt.bToTop = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_TOTOP);
+ DBWriteContactSettingByte(NULL, sModule, "ToTop", (BYTE)fcOpt.bToTop);
+ fcOpt.ToTopTime = GetDlgItemInt(hwndDlg, IDC_TXT_TOTOPTIME, &bSuccess, FALSE);
+ DBWriteContactSettingWord(NULL, sModule, "ToTopTime", fcOpt.ToTopTime );
+
+ fcOpt.bHideWhenCListShow = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_HIDE_WHEN_CLISTSHOW);
+ DBWriteContactSettingByte(NULL, sModule, "HideWhenCListShow", (BYTE)fcOpt.bHideWhenCListShow);
+
+ fcOpt.bUseSingleClick = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_SINGLECLK);
+ DBWriteContactSettingByte(NULL, sModule, "UseSingleClick", (BYTE)fcOpt.bUseSingleClick);
+
+ fcOpt.bShowIdle = (BOOL)IsDlgButtonChecked(hwndDlg, IDC_CHK_SHOWIDLE);
+ DBWriteContactSettingByte(NULL, sModule, "ShowIdle", (BYTE)fcOpt.bShowIdle);
+
+ ApplyOptionsChanges();
+ OnStatusChanged();
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+ }
+ return FALSE;
+}
+
+static
+LRESULT
+APIENTRY
+OptSknWndProc
+ ( IN HWND hwndDlg
+ , IN UINT uMsg
+ , IN WPARAM wParam
+ , IN LPARAM lParam
+ )
+{
+ static HFONT hFontSample;
+
+ switch ( uMsg )
+ {
+ case WM_INITDIALOG:
+ {
+ BYTE btOpacity;
+ char szPercent[20];
+
+ TranslateDialogDefault(hwndDlg);
+
+ // Border
+ CheckDlgButton(hwndDlg, IDC_DRAWBORDER
+ , DBGetContactSettingByte(NULL, sModule, "DrawBorder", FLT_DEFAULT_DRAWBORDER)
+ ? BST_CHECKED : BST_UNCHECKED
+ );
+ SendMessage(hwndDlg, M_REFRESHBORDERPICKERS, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_LTEDGESCOLOR, CPM_SETDEFAULTCOLOUR, 0, FLT_DEFAULT_LTEDGESCOLOR);
+ SendDlgItemMessage(hwndDlg, IDC_LTEDGESCOLOR, CPM_SETCOLOUR, 0
+ , DBGetContactSettingDword(NULL, sModule, "LTEdgesColor", FLT_DEFAULT_LTEDGESCOLOR)
+ );
+ SendDlgItemMessage(hwndDlg, IDC_RBEDGESCOLOR, CPM_SETDEFAULTCOLOUR, 0, FLT_DEFAULT_RBEDGESCOLOR);
+ SendDlgItemMessage(hwndDlg, IDC_RBEDGESCOLOR, CPM_SETCOLOUR, 0
+ , DBGetContactSettingDword(NULL, sModule, "RBEdgesColor", FLT_DEFAULT_RBEDGESCOLOR)
+ );
+
+ // Background
+ CheckDlgButton(hwndDlg, IDC_CHK_WIDTH, (fcOpt.bFixedWidth ? BST_CHECKED : BST_UNCHECKED));
+
+ SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETDEFAULTCOLOUR, 0, FLT_DEFAULT_BKGNDCOLOR);
+ SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETCOLOUR, 0
+ , DBGetContactSettingDword(NULL, sModule, "BkColor", FLT_DEFAULT_BKGNDCOLOR)
+ );
+ CheckDlgButton(hwndDlg, IDC_BITMAP
+ , DBGetContactSettingByte(NULL, sModule, "BkUseBitmap", FLT_DEFAULT_BKGNDUSEBITMAP)
+ ? BST_CHECKED : BST_UNCHECKED
+ );
+ SendMessage(hwndDlg, M_REFRESHBKGBOXES, 0, 0);
+ {
+ DBVARIANT dbv;
+
+ if (!DBGetContactSetting(NULL, sModule, "BkBitmap", &dbv))
+ {
+ SetDlgItemTextA(hwndDlg, IDC_FILENAME, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+ {
+ WORD bmpUse = (WORD)DBGetContactSettingWord(NULL, sModule, "BkBitmapOpt", FLT_DEFAULT_BKGNDBITMAPOPT);
+
+ 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_PROPORTIONAL, ((bmpUse & CLBF_PROPORTIONAL) ? 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);
+ }
+
+ // Windows 2K/XP
+ btOpacity = (BYTE)DBGetContactSettingByte(NULL, sModule, "Opacity", 100);
+ SendDlgItemMessage(hwndDlg, IDC_SLIDER_OPACITY, TBM_SETRANGE, TRUE, MAKELONG(0, 100));
+ SendDlgItemMessage(hwndDlg, IDC_SLIDER_OPACITY, TBM_SETPOS, TRUE, btOpacity);
+
+ wsprintfA(szPercent, "%d%%", btOpacity);
+ SetDlgItemTextA(hwndDlg, IDC_OPACITY, szPercent);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SLIDER_OPACITY), (NULL != pSetLayeredWindowAttributes));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_OPACITY), (NULL != pSetLayeredWindowAttributes));
+
+ // Fonts
+ hFontSample = NULL;
+ SetDlgItemText(hwndDlg, IDC_SAMPLE, TranslateT("Sample"));
+ FillFontListThread(hwndDlg);
+ {
+ int i;
+ int itemId;
+ LOGFONTA lf;
+ COLORREF colour;
+ WORD sameAs;
+ char str[32];
+
+ for (i = 0; i < FLT_FONTIDS; i++)
+ {
+ // Floating contacts fonts
+ GetFontSetting(TRUE, i, &lf, &colour);
+ wsprintfA(str, "Font%dAs", i);
+ sameAs = (WORD)DBGetContactSettingWord(NULL, sModule, str, s_rgwFontSameAsDefault[i]);
+ s_rgFontSettings[i].sameAs = LOBYTE(sameAs);
+ s_rgFontSettings[i].sameAsFlags = HIBYTE(sameAs);
+ s_rgFontSettings[i].style = (FW_NORMAL == lf.lfWeight? 0 : DBFONTF_BOLD)
+ | (lf.lfItalic ? DBFONTF_ITALIC : 0)
+ | (lf.lfUnderline ? DBFONTF_UNDERLINE : 0);
+ if (lf.lfHeight < 0)
+ {
+ HDC hdc;
+ SIZE size;
+ HFONT hFont = CreateFontIndirectA(&lf);
+
+ hdc=GetDC(hwndDlg);
+ SelectObject(hdc, hFont);
+ GetTextExtentPoint32A(hdc, "x", 1, &size);
+ ReleaseDC(hwndDlg, hdc);
+ DeleteObject(hFont);
+ s_rgFontSettings[i].size = (char)size.cy;
+ }
+ else
+ s_rgFontSettings[i].size = (char)lf.lfHeight;
+ s_rgFontSettings[i].charset = lf.lfCharSet;
+ s_rgFontSettings[i].colour = colour;
+ lstrcpyA(s_rgFontSettings[i].szFace, lf.lfFaceName);
+ itemId = SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_ADDSTRING, 0, (LPARAM)TranslateTS(s_rgszFontIdDescr[i]));
+ SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_SETITEMDATA, itemId, i);
+
+ // Miranda contact list fonts
+ GetFontSetting(FALSE, i, &lf, &colour);
+ s_rgFontSettingsMiranda[i].sameAs = 0;
+ s_rgFontSettingsMiranda[i].sameAsFlags = 0;
+ lstrcpyA(s_rgFontSettingsMiranda[i].szFace, lf.lfFaceName);
+ s_rgFontSettingsMiranda[i].charset = lf.lfCharSet;
+ s_rgFontSettingsMiranda[i].style = (FW_NORMAL == lf.lfWeight? 0 : DBFONTF_BOLD)
+ | (lf.lfItalic ? DBFONTF_ITALIC : 0)
+ | (lf.lfUnderline ? DBFONTF_UNDERLINE : 0);
+ if (lf.lfHeight < 0)
+ {
+ HDC hdc;
+ SIZE size;
+ HFONT hFont = CreateFontIndirectA(&lf);
+
+ hdc = GetDC(hwndDlg);
+ SelectObject(hdc, hFont);
+ GetTextExtentPoint32A(hdc, "x", 1, &size);
+ ReleaseDC(hwndDlg, hdc);
+ DeleteObject(hFont);
+ s_rgFontSettingsMiranda[i].size = (char)size.cy;
+ }
+ else
+ s_rgFontSettingsMiranda[i].size = (char)lf.lfHeight;
+ s_rgFontSettingsMiranda[i].colour = colour;
+ }
+ SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_SETCURSEL, 0, 0);
+ for (i = 0; i < sizeof(s_rgszFontSizes)/sizeof(s_rgszFontSizes[0]); i++)
+ SendDlgItemMessageA(hwndDlg, IDC_FONTSIZE, CB_ADDSTRING, 0, (LPARAM)s_rgszFontSizes[i]);
+ }
+ SendMessage(hwndDlg, M_REBUILDFONTGROUP, 0, 0);
+ SendMessage(hwndDlg, M_SAVEFONT, 0, 0);
+ return TRUE;
+ }
+ case M_REFRESHBKGBOXES:
+ {
+ BOOL bEnable = IsDlgButtonChecked(hwndDlg, IDC_BITMAP);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FILENAME), bEnable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BROWSE), bEnable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_STRETCHH), bEnable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_STRETCHV), bEnable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TILEH), bEnable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TILEV), bEnable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PROPORTIONAL), bEnable);
+ break;
+ }
+ case M_REFRESHBORDERPICKERS:
+ {
+ BOOL bEnable = IsDlgButtonChecked(hwndDlg, IDC_DRAWBORDER);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LTEDGESCOLOR), bEnable);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RBEDGESCOLOR), bEnable);
+ break;
+ }
+ // remake all the needed controls when the user changes the font selector at the top
+ case M_REBUILDFONTGROUP:
+ {
+ int i = SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETCURSEL, 0, 0);
+ int j;
+ int itemId;
+ int nSameAs = FLT_SAME_AS_NONE;
+ char szText[256];
+
+ SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_RESETCONTENT, 0, 0);
+ itemId = SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_ADDSTRING, 0, (LPARAM)TranslateT("<none>"));
+ SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETITEMDATA, itemId, FLT_SAME_AS_NONE);
+ SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETCURSEL, itemId, 0);
+ itemId = SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_ADDSTRING, 0, (LPARAM)TranslateT("<Contact List Text>"));
+ SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETITEMDATA, itemId, FLT_SAME_AS_MIRANDA);
+ if (FLT_SAME_AS_MIRANDA == s_rgFontSettings[i].sameAs)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETCURSEL, itemId, 0);
+ nSameAs = FLT_SAME_AS_MIRANDA;
+ }
+ for (j = 0; j < FLT_FONTIDS; j++)
+ {
+ int nDependsOn = j;
+
+ while (nDependsOn != i)
+ {
+ if (FLT_SAME_AS_NONE == nDependsOn || FLT_SAME_AS_MIRANDA == nDependsOn)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETLBTEXT, j, (LPARAM)szText);
+ itemId = SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_ADDSTRING, 0, (LPARAM)szText);
+ SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETITEMDATA, itemId, j);
+ if (j == s_rgFontSettings[i].sameAs)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_SETCURSEL, itemId, 0);
+ nSameAs = j;
+ }
+ break;
+ }
+ else
+ nDependsOn = s_rgFontSettings[nDependsOn].sameAs;
+ }
+ }
+ if (FLT_SAME_AS_NONE == nSameAs)
+ s_rgFontSettings[i].sameAsFlags = 0;
+
+ SendMessage(hwndDlg, M_LOADFONT, i, 0);
+ SendMessage(hwndDlg, M_SETSAMEASBOXES, i, 0);
+ SendMessage(hwndDlg, M_REFRESHSAMEASBOXES, i, 0);
+ SendMessage(hwndDlg, M_REMAKESAMPLE, 0, 0);
+ break;
+ }
+ //fill the script combo box and set the selection to the value for fontid wParam
+ case M_FILLSCRIPTCOMBO:
+ {
+ int i;
+ HDC hdc = GetDC(hwndDlg);
+ LOGFONT lf = {0};
+
+ lf.lfCharSet = DEFAULT_CHARSET;
+ lf.lfPitchAndFamily = 0;
+ GetDlgItemText(hwndDlg, IDC_TYPEFACE, lf.lfFaceName, sizeof(lf.lfFaceName));
+ SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_RESETCONTENT, 0, 0);
+ EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)EnumFontScriptsProc, (LPARAM)GetDlgItem(hwndDlg, IDC_SCRIPT), 0);
+ ReleaseDC(hwndDlg, hdc);
+ for (i = SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETCOUNT, 0, 0) - 1; i >= 0; i--)
+ {
+ if (SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETITEMDATA, i, 0) == s_rgFontSettings[wParam].charset)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_SETCURSEL, i, 0);
+ break;
+ }
+ }
+ if (i < 0)
+ SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_SETCURSEL, 0, 0);
+ break;
+ }
+ // set the check mark in the 'same as' boxes to the right value for fontid wParam
+ case M_SETSAMEASBOXES:
+ {
+ CheckDlgButton(hwndDlg, IDC_SAMETYPE, (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_FACE ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_SAMESIZE, (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_SIZE ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_SAMESTYLE, (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_STYLE ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_SAMECOLOUR, (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_COLOUR ? BST_CHECKED : BST_UNCHECKED));
+ break;
+ }
+ // set the disabled flag on the 'same as' checkboxes to the values for fontid wParam
+ case M_REFRESHSAMEASBOXES:
+ {
+ BOOL bSameAsNone = (FLT_SAME_AS_NONE == s_rgFontSettings[wParam].sameAs);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SAMETYPE), !bSameAsNone);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SAMESIZE), !bSameAsNone);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SAMESTYLE), !bSameAsNone);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SAMECOLOUR), !bSameAsNone);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TYPEFACE), bSameAsNone || !(s_rgFontSettings[wParam].sameAsFlags & SAMEASF_FACE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SCRIPT), bSameAsNone || !(s_rgFontSettings[wParam].sameAsFlags & SAMEASF_FACE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_FONTSIZE), bSameAsNone || !(s_rgFontSettings[wParam].sameAsFlags & SAMEASF_SIZE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_BOLD), bSameAsNone || !(s_rgFontSettings[wParam].sameAsFlags & SAMEASF_STYLE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ITALIC), bSameAsNone || !(s_rgFontSettings[wParam].sameAsFlags & SAMEASF_STYLE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_UNDERLINE), bSameAsNone || !(s_rgFontSettings[wParam].sameAsFlags & SAMEASF_STYLE));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_COLOUR), bSameAsNone || !(s_rgFontSettings[wParam].sameAsFlags & SAMEASF_COLOUR));
+ break;
+ }
+ // remake the sample edit box font based on the settings in the controls
+ case M_REMAKESAMPLE:
+ {
+ LOGFONTA lf;
+
+ if (hFontSample)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_SAMPLE, WM_SETFONT, SendDlgItemMessage(hwndDlg, IDC_FONTID, WM_GETFONT, 0, 0), 0);
+ DeleteObject(hFontSample);
+ }
+ lf.lfHeight = GetDlgItemInt(hwndDlg, IDC_FONTSIZE, NULL, FALSE);
+ {
+ HDC hdc=GetDC(NULL);
+ lf.lfHeight=-MulDiv(lf.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+ ReleaseDC(NULL,hdc);
+ }
+ lf.lfWidth = 0;
+ lf.lfEscapement = 0;
+ lf.lfOrientation = 0;
+ lf.lfWeight = (IsDlgButtonChecked(hwndDlg, IDC_BOLD) ? FW_BOLD : FW_NORMAL);
+ lf.lfItalic = (BYTE)IsDlgButtonChecked(hwndDlg, IDC_ITALIC);
+ lf.lfUnderline = (BYTE)IsDlgButtonChecked(hwndDlg, IDC_UNDERLINE);
+ lf.lfStrikeOut = 0;
+ lf.lfCharSet = (BYTE)SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETCURSEL, 0, 0), 0);
+ lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
+ lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf.lfQuality = DEFAULT_QUALITY;
+ lf.lfPitchAndFamily = (DEFAULT_PITCH | FF_DONTCARE);
+ GetDlgItemTextA(hwndDlg, IDC_TYPEFACE, lf.lfFaceName, sizeof(lf.lfFaceName));
+ if (NULL != (hFontSample = CreateFontIndirectA(&lf)))
+ SendDlgItemMessage(hwndDlg, IDC_SAMPLE, WM_SETFONT, (WPARAM)hFontSample, TRUE);
+ break;
+ }
+ // copy the 'same as' settings for fontid wParam from their sources
+ case M_RECALCONEFONT:
+ {
+ if (FLT_SAME_AS_NONE != s_rgFontSettings[wParam].sameAs)
+ {
+ SFontSettings* pSameAs = ((FLT_SAME_AS_MIRANDA == s_rgFontSettings[wParam].sameAs)
+ ? &s_rgFontSettingsMiranda[wParam]
+ : &s_rgFontSettings[s_rgFontSettings[wParam].sameAs]
+ );
+
+ if (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_FACE)
+ {
+ lstrcpyA(s_rgFontSettings[wParam].szFace, pSameAs->szFace);
+ s_rgFontSettings[wParam].charset = pSameAs->charset;
+ }
+ if (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_SIZE)
+ s_rgFontSettings[wParam].size = pSameAs->size;
+ if (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_STYLE)
+ s_rgFontSettings[wParam].style = pSameAs->style;
+ if (s_rgFontSettings[wParam].sameAsFlags & SAMEASF_COLOUR)
+ s_rgFontSettings[wParam].colour = pSameAs->colour;
+ }
+ break;
+ }
+ // recalculate the 'same as' settings for all fonts but wParam
+ case M_RECALCOTHERFONTS:
+ {
+ int nFont;
+ int nDepth;
+ int nRecalcedFonts = 1;
+ int nRecalcDepth;
+ int nFontId = (int)wParam;
+ int nSameAs;
+
+ for (nRecalcDepth = 0; nRecalcedFonts < FLT_FONTIDS && nRecalcDepth < FLT_FONTIDS; nRecalcDepth++)
+ {
+ for (nFont = 0; nFont < FLT_FONTIDS; nFont++)
+ {
+ if (nFontId == nFont)
+ continue;
+
+ nSameAs = s_rgFontSettings[nFont].sameAs;
+ for (nDepth = 0; nDepth < nRecalcDepth; nDepth++)
+ {
+ if (FLT_SAME_AS_NONE == nSameAs || FLT_SAME_AS_MIRANDA == nSameAs || nFontId == nSameAs)
+ break;
+
+ nSameAs = s_rgFontSettings[nSameAs].sameAs;
+ }
+ if (nDepth == nRecalcDepth)
+ {
+ if (nFontId == nSameAs)
+ {
+ SendMessage(hwndDlg, M_RECALCONEFONT, nFont, 0);
+ nRecalcedFonts++;
+ }
+ else if (FLT_SAME_AS_NONE == nSameAs || FLT_SAME_AS_MIRANDA == nSameAs)
+ nRecalcedFonts++;
+ }
+ }
+ }
+ break;
+ }
+ //save the font settings from the controls to font wParam
+ case M_SAVEFONT:
+ {
+ s_rgFontSettings[wParam].sameAsFlags = (IsDlgButtonChecked(hwndDlg, IDC_SAMETYPE) ? SAMEASF_FACE : 0)
+ | (IsDlgButtonChecked(hwndDlg, IDC_SAMESIZE) ? SAMEASF_SIZE : 0)
+ | (IsDlgButtonChecked(hwndDlg, IDC_SAMESTYLE) ? SAMEASF_STYLE : 0)
+ | (IsDlgButtonChecked(hwndDlg, IDC_SAMECOLOUR) ? SAMEASF_COLOUR : 0);
+ s_rgFontSettings[wParam].sameAs = (BYTE)SendDlgItemMessage(hwndDlg
+ , IDC_SAMEAS
+ , CB_GETITEMDATA
+ , SendDlgItemMessage(hwndDlg, IDC_SAMEAS, CB_GETCURSEL, 0, 0)
+ , 0
+ );
+ GetDlgItemTextA(hwndDlg, IDC_TYPEFACE, s_rgFontSettings[wParam].szFace, sizeof(s_rgFontSettings[wParam].szFace));
+ s_rgFontSettings[wParam].charset = (BYTE)SendDlgItemMessage(hwndDlg
+ , IDC_SCRIPT
+ , CB_GETITEMDATA
+ , SendDlgItemMessage(hwndDlg, IDC_SCRIPT, CB_GETCURSEL, 0, 0)
+ , 0
+ );
+ s_rgFontSettings[wParam].size = (char)GetDlgItemInt(hwndDlg, IDC_FONTSIZE, NULL, FALSE);
+ s_rgFontSettings[wParam].style= (IsDlgButtonChecked(hwndDlg, IDC_BOLD) ? DBFONTF_BOLD : 0)
+ | (IsDlgButtonChecked(hwndDlg, IDC_ITALIC) ? DBFONTF_ITALIC : 0)
+ | (IsDlgButtonChecked(hwndDlg, IDC_UNDERLINE) ? DBFONTF_UNDERLINE : 0);
+ s_rgFontSettings[wParam].colour = SendDlgItemMessage(hwndDlg, IDC_COLOUR, CPM_GETCOLOUR, 0, 0);
+ break;
+ }
+ // load font wParam into the controls
+ case M_LOADFONT:
+ {
+ LOGFONTA lf;
+ COLORREF colour;
+
+ SetDlgItemTextA(hwndDlg, IDC_TYPEFACE, s_rgFontSettings[wParam].szFace);
+ SendMessage(hwndDlg, M_FILLSCRIPTCOMBO, wParam, 0);
+ SetDlgItemInt(hwndDlg, IDC_FONTSIZE, s_rgFontSettings[wParam].size, FALSE);
+ CheckDlgButton(hwndDlg, IDC_BOLD, ((s_rgFontSettings[wParam].style & DBFONTF_BOLD) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_ITALIC, ((s_rgFontSettings[wParam].style & DBFONTF_ITALIC) ? BST_CHECKED : BST_UNCHECKED));
+ CheckDlgButton(hwndDlg, IDC_UNDERLINE, ((s_rgFontSettings[wParam].style & DBFONTF_UNDERLINE) ? BST_CHECKED : BST_UNCHECKED));
+ GetDefaultFontSetting(TRUE, wParam, &lf, &colour);
+ SendDlgItemMessage(hwndDlg, IDC_COLOUR, CPM_SETDEFAULTCOLOUR, 0, colour);
+ SendDlgItemMessage(hwndDlg, IDC_COLOUR, CPM_SETCOLOUR, 0, s_rgFontSettings[wParam].colour);
+ break;
+ }
+ // guess suitable values for the 'same as' checkboxes for fontId wParam
+ case M_GUESSSAMEASBOXES:
+ {
+ s_rgFontSettings[wParam].sameAsFlags = 0;
+ if (FLT_SAME_AS_NONE != s_rgFontSettings[wParam].sameAs)
+ {
+ SFontSettings* pSameAs = ((FLT_SAME_AS_MIRANDA == s_rgFontSettings[wParam].sameAs)
+ ? &s_rgFontSettingsMiranda[wParam]
+ : &s_rgFontSettings[s_rgFontSettings[wParam].sameAs]
+ );
+
+ if (!lstrcmpA(s_rgFontSettings[wParam].szFace, pSameAs->szFace) && s_rgFontSettings[wParam].charset == pSameAs->charset)
+ s_rgFontSettings[wParam].sameAsFlags |= SAMEASF_FACE;
+ if (s_rgFontSettings[wParam].size == pSameAs->size)
+ s_rgFontSettings[wParam].sameAsFlags |= SAMEASF_SIZE;
+ if (s_rgFontSettings[wParam].style == pSameAs->style)
+ s_rgFontSettings[wParam].sameAsFlags |= SAMEASF_STYLE;
+ if (s_rgFontSettings[wParam].colour == pSameAs->colour)
+ s_rgFontSettings[wParam].sameAsFlags |= SAMEASF_COLOUR;
+ SendMessage(hwndDlg,M_SETSAMEASBOXES,wParam,0);
+ }
+ break;
+ }
+ case WM_CTLCOLORSTATIC:
+ {
+ if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SAMPLE))
+ {
+ SetTextColor((HDC)wParam, SendDlgItemMessage(hwndDlg, IDC_COLOUR, CPM_GETCOLOUR, 0, 0));
+ SetBkColor((HDC)wParam, GetSysColor(COLOR_3DFACE));
+ return (BOOL)GetSysColorBrush(COLOR_3DFACE);
+ }
+ break;
+ }
+ case WM_HSCROLL:
+ {
+ if (wParam != TB_ENDTRACK)
+ {
+ int nPos;
+ char szPercent[20];
+
+ nPos = (BYTE)SendDlgItemMessage(hwndDlg, IDC_SLIDER_OPACITY, TBM_GETPOS, 0, 0);
+ fcOpt.thumbAlpha = (BYTE)(( nPos * 255 ) / 100 );
+ SetThumbsOpacity(fcOpt.thumbAlpha);
+
+ wsprintfA(szPercent, "%d%%", nPos);
+ SetDlgItemTextA(hwndDlg, IDC_OPACITY, szPercent);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ break;
+ }
+ case WM_COMMAND:
+ {
+ int nFontId = SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETITEMDATA
+ , SendDlgItemMessage(hwndDlg, IDC_FONTID, CB_GETCURSEL, 0, 0)
+ , 0
+ );
+
+ switch (LOWORD(wParam))
+ {
+ case IDC_DRAWBORDER:
+ {
+ SendMessage(hwndDlg, M_REFRESHBORDERPICKERS, 0, 0);
+ break;
+ }
+ case IDC_BROWSE:
+ {
+ char str[MAX_PATH];
+ OPENFILENAMEA ofn={0};
+ char filter[512];
+
+ GetDlgItemTextA(hwndDlg, IDC_FILENAME, str, sizeof(str));
+ ofn.lStructSize = sizeof(OPENFILENAMEA);
+ 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))
+ return FALSE;
+ SetDlgItemTextA(hwndDlg, IDC_FILENAME, str);
+ break;
+ }
+ case IDC_FILENAME:
+ {
+ if (EN_CHANGE != HIWORD(wParam) || (HWND)lParam != GetFocus())
+ return FALSE;
+ break;
+ }
+ case IDC_BITMAP:
+ {
+ SendMessage(hwndDlg, M_REFRESHBKGBOXES, 0, 0);
+ break;
+ }
+ case IDC_FONTID:
+ {
+ if (CBN_SELCHANGE == HIWORD(wParam))
+ SendMessage(hwndDlg, M_REBUILDFONTGROUP, 0, 0);
+ return FALSE;
+ }
+ case IDC_SAMETYPE:
+ case IDC_SAMESIZE:
+ case IDC_SAMESTYLE:
+ case IDC_SAMECOLOUR:
+ {
+ SendMessage(hwndDlg, M_SAVEFONT, nFontId, 0);
+ SendMessage(hwndDlg, M_RECALCONEFONT, nFontId, 0);
+ SendMessage(hwndDlg, M_RECALCOTHERFONTS, nFontId, 0);
+ SendMessage(hwndDlg, M_LOADFONT, nFontId, 0);
+ SendMessage(hwndDlg, M_REFRESHSAMEASBOXES, nFontId, 0);
+ SendMessage(hwndDlg, M_REMAKESAMPLE, 0, 0);
+ break;
+ }
+ case IDC_SAMEAS:
+ {
+ if (CBN_SELCHANGE != HIWORD(wParam))
+ return FALSE;
+ SendMessage(hwndDlg, M_SAVEFONT, nFontId, 0);
+ SendMessage(hwndDlg, M_GUESSSAMEASBOXES, nFontId, 0);
+ SendMessage(hwndDlg, M_REFRESHSAMEASBOXES, nFontId, 0);
+ break;
+ }
+ case IDC_TYPEFACE:
+ case IDC_SCRIPT:
+ case IDC_FONTSIZE:
+ {
+ if (CBN_EDITCHANGE != HIWORD(wParam) && CBN_SELCHANGE != HIWORD(wParam))
+ return FALSE;
+ if (CBN_SELCHANGE == HIWORD(wParam))
+ SendDlgItemMessage(hwndDlg, LOWORD(wParam), CB_SETCURSEL, SendDlgItemMessage(hwndDlg, LOWORD(wParam), CB_GETCURSEL, 0, 0), 0);
+ if (IDC_TYPEFACE == LOWORD(wParam))
+ SendMessage(hwndDlg, M_FILLSCRIPTCOMBO, nFontId, 0);
+ // FALL THRU
+ }
+ case IDC_BOLD:
+ case IDC_ITALIC:
+ case IDC_UNDERLINE:
+ case IDC_COLOUR:
+ {
+ SendMessage(hwndDlg, M_SAVEFONT, nFontId, 0);
+ //SendMessage(hwndDlg, M_GUESSSAMEASBOXES, nFontId, 0);
+ //SendMessage(hwndDlg, M_REFRESHSAMEASBOXES, nFontId, 0);
+ SendMessage(hwndDlg, M_RECALCOTHERFONTS, nFontId, 0);
+ SendMessage(hwndDlg, M_REMAKESAMPLE, 0, 0);
+ break;
+ }
+ case IDC_SAMPLE:
+ return 0;
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ LPNMHDR phdr = (LPNMHDR)(lParam);
+
+ if (0 == phdr->idFrom)
+ {
+ switch (phdr->code)
+ {
+ case PSN_APPLY:
+ {
+ int i;
+ char str[20];
+ //BOOL bSuccess = FALSE;
+
+ // Border
+ DBWriteContactSettingByte(NULL, sModule, "DrawBorder", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_DRAWBORDER));
+ {
+ COLORREF col;
+
+ col = SendDlgItemMessage(hwndDlg, IDC_LTEDGESCOLOR, CPM_GETCOLOUR, 0, 0);
+ DBWriteContactSettingDword(NULL, sModule, "LTEdgesColor", col);
+ col = SendDlgItemMessage(hwndDlg, IDC_RBEDGESCOLOR, CPM_GETCOLOUR, 0, 0);
+ DBWriteContactSettingDword(NULL, sModule, "RBEdgesColor", col);
+ }
+
+ // Backgroud
+ {
+ COLORREF col;
+
+ col = SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR, 0, 0);
+ DBWriteContactSettingDword(NULL, sModule, "BkColor", col);
+ }
+ DBWriteContactSettingByte(NULL, sModule, "BkUseBitmap", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_BITMAP));
+ {
+ char str[MAX_PATH];
+
+ GetDlgItemTextA(hwndDlg, IDC_FILENAME, str, sizeof(str));
+ DBWriteContactSettingString(NULL, sModule, "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_PROPORTIONAL))
+ flags |= CLBF_PROPORTIONAL;
+ DBWriteContactSettingWord(NULL, sModule, "BkBitmapOpt", flags);
+ }
+
+ DBWriteContactSettingByte(NULL, sModule, "Opacity"
+ , (BYTE)SendDlgItemMessage(hwndDlg, IDC_SLIDER_OPACITY, TBM_GETPOS, 0, 0)
+ );
+
+ for (i = 0; i < FLT_FONTIDS; i++)
+ {
+ wsprintfA(str, "Font%dName", i);
+ DBWriteContactSettingString(NULL, sModule, str, s_rgFontSettings[i].szFace);
+ wsprintfA(str, "Font%dSet", i);
+ DBWriteContactSettingByte(NULL, sModule, str, s_rgFontSettings[i].charset);
+ wsprintfA(str, "Font%dSize", i);
+ DBWriteContactSettingByte(NULL, sModule, str, s_rgFontSettings[i].size);
+ wsprintfA(str, "Font%dSty", i);
+ DBWriteContactSettingByte(NULL, sModule, str, s_rgFontSettings[i].style);
+ wsprintfA(str, "Font%dCol", i);
+ DBWriteContactSettingDword(NULL, sModule, str, s_rgFontSettings[i].colour);
+ wsprintfA(str, "Font%dAs", i);
+ DBWriteContactSettingWord(NULL, sModule, str, MAKEWORD(s_rgFontSettings[i].sameAs, s_rgFontSettings[i].sameAsFlags));
+ }
+
+ ApplyOptionsChanges();
+ OnStatusChanged();
+ return TRUE;
+ }
+ case PSN_RESET:
+ //case PSN_KILLACTIVE:
+ {
+ fcOpt.thumbAlpha = (BYTE)((double)DBGetContactSettingByte(NULL, sModule, "Opacity", 100) * 2.55);
+ SetThumbsOpacity(fcOpt.thumbAlpha);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case WM_DESTROY:
+ {
+ if (hFontSample)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_SAMPLE, WM_SETFONT, SendDlgItemMessage(hwndDlg, IDC_FONTID, WM_GETFONT, 0, 0), 0);
+ DeleteObject(hFontSample);
+ }
+ break;
+ }
+
+ }
+ return FALSE;
+}
+
diff --git a/plugins/FloatingContacts/resource.h b/plugins/FloatingContacts/resource.h
new file mode 100644
index 0000000000..fec93538d8
--- /dev/null
+++ b/plugins/FloatingContacts/resource.h
@@ -0,0 +1,75 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Script.rc
+//
+#define IDD_OPT_FLTCONT 101
+#define IDI_ICON1 103
+#define IDI_HIDE 103
+#define IDI_SHOW 105
+#define IDD_OPT_FNT 106
+#define IDD_OPT_SKIN 106
+#define IDC_SLIDER_OPACITY 1001
+#define IDC_OPACITY 1002
+#define IDC_CHK_HIDE_OFFLINE 1003
+#define IDC_CHK_STICK 1004
+#define IDC_CHK_WIDTH 1005
+#define IDC_LBL_WIDTH 1006
+#define IDC_TXT_WIDTH 1007
+#define IDC_WIDTHSPIN 1008
+#define IDC_TXT_TIMEIN 1009
+#define IDC_TIMEINSPIN 1010
+#define IDC_TXT_TOTOPTIME 1011
+#define IDC_CHK_HIDE_ALL 1012
+#define IDC_CHK_DEF_BACKGROUND 1013
+#define IDC_TOTOPTIMESPIN 1013
+#define IDC_CHK_HIDE_WHEN_FULSCREEN 1014
+#define IDC_CHK_TIP 1015
+#define IDC_LBL_TIMEIN 1016
+#define IDC_CHK_TOTOP 1017
+#define IDC_LBL_TOTOP 1018
+#define IDC_CHK_HIDE_WHEN_CLISTSHOW 1019
+#define IDC_CHECK1 1020
+#define IDC_CHK_SINGLECLK 1020
+#define IDC_CHECK2 1021
+#define IDC_CHK_SHOWIDLE 1021
+#define IDC_FONTID 1100
+#define IDC_SAMEAS 1101
+#define IDC_LBL_TIMEIN_CMT 1101
+#define IDC_SAMETYPE 1102
+#define IDC_SAMESIZE 1103
+#define IDC_SAMESTYLE 1104
+#define IDC_SAMECOLOUR 1105
+#define IDC_TYPEFACE 1106
+#define IDC_SCRIPT 1107
+#define IDC_FONTSIZE 1108
+#define IDC_BOLD 1109
+#define IDC_ITALIC 1110
+#define IDC_UNDERLINE 1111
+#define IDC_COLOUR 1112
+#define IDC_SAMPLE 1113
+#define IDC_STSAMETEXT 1114
+#define IDC_STASTEXT 1115
+#define IDC_STHORZBAR 1116
+#define IDC_BKGCOLOUR 1200
+#define IDC_BITMAP 1201
+#define IDC_FILENAME 1202
+#define IDC_BROWSE 1203
+#define IDC_STRETCHH 1204
+#define IDC_STRETCHV 1205
+#define IDC_TILEH 1206
+#define IDC_TILEV 1207
+#define IDC_PROPORTIONAL 1208
+#define IDC_DRAWBORDER 1209
+#define IDC_LTEDGESCOLOR 1210
+#define IDC_RBEDGESCOLOR 1211
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 107
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1022
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/FloatingContacts/show.ico b/plugins/FloatingContacts/show.ico
new file mode 100644
index 0000000000..f924c12891
--- /dev/null
+++ b/plugins/FloatingContacts/show.ico
Binary files differ
diff --git a/plugins/FloatingContacts/stdhdr.h b/plugins/FloatingContacts/stdhdr.h
new file mode 100644
index 0000000000..95e5c6cca7
--- /dev/null
+++ b/plugins/FloatingContacts/stdhdr.h
@@ -0,0 +1,64 @@
+
+#ifndef __STDHDR_H__
+#define __STDHDR_H__
+
+// disable security warnings about "*_s" functions
+#define _CRT_SECURE_NO_DEPRECATE
+
+// disable warnings about underscore in stdc functions
+#pragma warning(disable: 4996)
+
+// Unreferenced formal parameter
+#pragma warning(disable: 4100)
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+/////////////////////////////////////////////////////////////////////////////
+//
+
+#define STRICT
+
+#include <windows.h>
+#include <stdio.h>
+#include <assert.h>
+
+#pragma warning ( disable : 4201 ) //nonstandard extension used : nameless struct/union
+#include <commctrl.h>
+
+#define MIRANDA_VER 0x600
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_system_cpp.h>
+#include <m_skin.h>
+#include <m_utils.h>
+#include <m_langpack.h>
+#include <m_protocols.h>
+#include <m_protosvc.h>
+#include <m_database.h>
+#include <m_message.h>
+//#include "../../include/msgs.h"
+#include <m_file.h>
+#include <m_clist.h>
+#include <m_clui.h>
+#include <m_options.h>
+#include <m_clc.h>
+//#include "../../include/clc.h"
+#include <m_clistint.h>
+#include <m_hotkeys.h>
+
+#include "bitmap_funcs.h"
+
+#include "fltcont.h"
+#include "thumbs.h"
+#include "filedrop.h"
+#include "resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif // #ifndef __STDHDR_H__
+
+/////////////////////////////////////////////////////////////////////////////
+// End Of File stdhdr.h
diff --git a/plugins/FloatingContacts/thumbs.cpp b/plugins/FloatingContacts/thumbs.cpp
new file mode 100644
index 0000000000..ad08865f01
--- /dev/null
+++ b/plugins/FloatingContacts/thumbs.cpp
@@ -0,0 +1,1013 @@
+#include "stdhdr.h"
+#include "Wingdi.h"
+
+ThumbList thumbList;
+
+/////////////////////////////////////////////////////////////////////////////
+// ThumbInfo
+static POINT ptOld;
+static BOOL bMouseDown = FALSE;
+static BOOL bMouseIn = FALSE;
+static BOOL bMouseMoved = FALSE;
+static short nLeft = 0;
+static short nTop = 0;
+static int nOffs = 5;
+static ThumbInfo *pThumbMouseIn = NULL;
+
+static void SnapToScreen( RECT rcThumb, int nX, int nY, int *pX, int *pY )
+{
+ int nWidth;
+ int nHeight;
+
+ assert( NULL != pX );
+ assert( NULL != pY );
+
+ nWidth = rcThumb.right - rcThumb.left;
+ nHeight = rcThumb.bottom - rcThumb.top;
+
+ *pX = nX < ( nOffs + rcScreen.left ) ? rcScreen.left : nX;
+ *pY = nY < ( nOffs + rcScreen.top ) ? rcScreen.top : nY;
+ *pX = *pX > ( rcScreen.right - nWidth - nOffs ) ? ( rcScreen.right - nWidth ) : *pX;
+ *pY = *pY > ( rcScreen.bottom - nHeight - nOffs ) ? ( rcScreen.bottom - nHeight ) : *pY;
+}
+
+ThumbInfo::ThumbInfo()
+{
+ dropTarget = new CDropTarget;
+ dropTarget->AddRef();
+ btAlpha = 255;
+}
+
+ThumbInfo::~ThumbInfo()
+{
+ if(pThumbMouseIn==this){
+ pThumbMouseIn=NULL;
+ KillTimer(hwnd, TIMERID_LEAVE_T);
+ }
+ dropTarget->Release();
+}
+
+void ThumbInfo::GetThumbRect(RECT *rc)
+{
+ rc->left = ptPos.x;
+ rc->top = ptPos.y;
+ rc->right = ptPos.x + szSize.cx;
+ rc->bottom = ptPos.y + szSize.cy;
+}
+
+void ThumbInfo::PositionThumb(short nX, short nY)
+{
+ POINT pos = { nX, nY };
+ HDWP hdwp;
+
+ hdwp = BeginDeferWindowPos(1);
+
+ ThumbInfo *pThumb = this;
+ while (pThumb)
+ {
+ pThumb->PositionThumbWorker( (short)pos.x, (short)pos.y, &pos );
+
+ DeferWindowPos( hdwp,
+ pThumb->hwnd,
+ HWND_TOPMOST,
+ pos.x,
+ pos.y,
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
+
+ pThumb->ptPos = pos;
+ pos.x += pThumb->szSize.cx;
+
+ pThumb = fcOpt.bMoveTogether ? thumbList.FindThumb( pThumb->dockOpt.hwndRight ) : NULL;
+ }
+
+ EndDeferWindowPos(hdwp);
+}
+
+void ThumbInfo::PositionThumbWorker(short nX, short nY, POINT *newPos)
+{
+ RECT rc;
+ RECT rcThumb;
+ int nNewX;
+ int nNewY;
+ int nWidth;
+ int nHeight;
+ POINT pt;
+ RECT rcLeft;
+ RECT rcTop;
+ RECT rcRight;
+ RECT rcBottom;
+ BOOL bDocked;
+ BOOL bDockedLeft;
+ BOOL bDockedRight;
+ BOOL bLeading;
+
+ // Get thumb dimnsions
+ GetThumbRect( &rcThumb );
+ nWidth = rcThumb.right - rcThumb.left;
+ nHeight = rcThumb.bottom - rcThumb.top;
+
+ // Docking and screen boundaries check
+ SnapToScreen( rcThumb, nX, nY, &nNewX, &nNewY );
+
+ bLeading = dockOpt.hwndRight != NULL;
+
+ if ( fcOpt.bMoveTogether )
+ {
+ UndockThumbs( this, thumbList.FindThumb( dockOpt.hwndLeft ) );
+ }
+
+
+ for (int i = 0; i < thumbList.getCount(); ++i)
+ {
+ ThumbInfo *pCurThumb = thumbList[i];
+
+ if ( pCurThumb != this )
+ {
+ GetThumbRect( &rcThumb );
+ OffsetRect( &rcThumb, nX - rcThumb.left, nY - rcThumb.top );
+
+ pCurThumb->GetThumbRect( &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 ( fcOpt.bMoveTogether )
+ {
+ if ( bDockedRight )
+ {
+ DockThumbs( this, pCurThumb, TRUE );
+ }
+
+ if ( bDockedLeft )
+ {
+ DockThumbs( pCurThumb, this, 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;
+ }
+ }
+ }
+ }
+
+ // Adjust coords once again
+ SnapToScreen( rcThumb, nNewX, nNewY, &nNewX, &nNewY );
+
+ newPos->x = nNewX;
+ newPos->y = nNewY;
+}
+
+void ThumbInfo::ResizeThumb()
+{
+ HDC hdc = NULL;
+ HFONT hOldFont = NULL;
+ POINT ptText;
+ SIZEL sizeIcon;
+ SIZEL sizeText;
+ RECT rcThumb;
+ int index = FLT_FONTID_NOTONLIST;
+
+ ThumbInfo *pNextThumb = NULL;
+
+ himl = ( HIMAGELIST )CallService( MS_CLIST_GETICONSIMAGELIST, 0, 0 );
+
+ if ( himl == NULL ) return;
+
+ ImageList_GetIconSize_my(himl, sizeIcon);
+
+ hdc = GetWindowDC(hwnd);
+
+ if (!DBGetContactSettingByte(hContact, "CList", "NotOnList", 0))
+ {
+ int nStatus;
+ int nContactStatus;
+ int nApparentMode;
+ char* szProto;
+
+ szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ if ( NULL != szProto )
+ {
+ nStatus = CallProtoService(szProto, PS_GETSTATUS, 0, 0);
+ nContactStatus = DBGetContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ nApparentMode = DBGetContactSettingWord(hContact, szProto, "ApparentMode", 0);
+
+ if ( (nStatus == ID_STATUS_INVISIBLE && nApparentMode == ID_STATUS_ONLINE)
+ || (nStatus != ID_STATUS_INVISIBLE && nApparentMode == ID_STATUS_OFFLINE)
+ )
+ {
+ if (ID_STATUS_OFFLINE == nContactStatus)
+ {
+ index = FLT_FONTID_OFFINVIS;
+ }
+ else
+ {
+ index = FLT_FONTID_INVIS;
+ }
+ }
+ else if (ID_STATUS_OFFLINE == nContactStatus)
+ {
+ index = FLT_FONTID_OFFLINE;
+ }
+ else
+ {
+ index = FLT_FONTID_CONTACTS;
+ }
+ }
+ }
+ else
+ {
+ index = FLT_FONTID_NOTONLIST;
+ }
+
+ hOldFont = (HFONT)SelectObject( hdc, hFont[ index ] );
+
+ // Get text and icon sizes
+ GetTextExtentPoint32( hdc, ptszName, _tcslen( ptszName ), &sizeText );
+
+
+ SelectObject( hdc, hOldFont );
+
+ // Transform text size
+ ptText.x = sizeText.cx;
+ ptText.y = sizeText.cy;
+ LPtoDP( hdc, &ptText, 1 );
+
+
+ szSize.cx = fcOpt.bFixedWidth ? fcOpt.nThumbWidth : sizeIcon.cx + ptText.x + 10;
+ szSize.cy = ( ( sizeIcon.cy > ptText.y ) ? sizeIcon.cy : ptText.y ) + 4;
+
+ SetWindowPos( hwnd,
+ HWND_TOPMOST,
+ 0,
+ 0,
+ szSize.cx,
+ szSize.cy,
+ SWP_NOMOVE | /*SWP_NOZORDER |*/ SWP_NOACTIVATE );
+
+ RefreshContactIcon(0xFFFFFFFF);
+
+ ReleaseDC( hwnd, hdc );
+
+ // Move the docked widnow if needed
+ if (pNextThumb = thumbList.FindThumb(dockOpt.hwndRight))
+ {
+ GetThumbRect( &rcThumb );
+ pNextThumb->PositionThumb( (short)rcThumb.right, (short)rcThumb.top );
+ }
+}
+
+void ThumbInfo::RefreshContactIcon(int iIcon)
+{
+ if ( iIcon == 0xFFFFFFFF || ImageList_GetImageCount(himl)<=iIcon )
+ {
+ this->iIcon = CallService( MS_CLIST_GETCONTACTICON, (WPARAM)hContact, 0 );
+ }
+ else
+ {
+ this->iIcon = iIcon;
+ }
+
+ UpdateContent();
+}
+
+void ThumbInfo::RefreshContactStatus(int idStatus)
+{
+ if ( IsStatusVisible( idStatus ) )
+ {
+ RegisterFileDropping( hwnd, dropTarget );
+ }
+ else
+ {
+ UnregisterFileDropping( hwnd );
+ }
+
+ ShowWindow( hwnd, fcOpt.bHideAll || HideOnFullScreen() || ( fcOpt.bHideOffline && ( !IsStatusVisible( idStatus ) ) ) || (fcOpt.bHideWhenCListShow && bIsCListShow) ? SW_HIDE : SW_SHOWNA );
+}
+
+void ThumbInfo::DeleteContactPos()
+{
+ DBDeleteContactSetting( hContact, sModule, "ThumbsPos" );
+}
+
+void ThumbInfo::OnLButtonDown(short nX, short nY)
+{
+ RECT rc;
+
+ if(bEnableTip && fcOpt.bShowTip) KillTip();
+
+// ptOld.x = nX;
+// ptOld.y = nY;
+
+// ClientToScreen( hwnd, &ptOld );
+
+ GetCursorPos(&ptOld);
+ GetThumbRect(&rc);
+
+ nLeft = (short)rc.left;
+ nTop = (short)rc.top;
+
+ //bMouseIn = FALSE;
+ bMouseDown = TRUE;
+ bMouseMoved = FALSE;
+
+// SetCapture(hwnd);
+}
+
+void ThumbInfo::OnLButtonUp()
+{
+ RECT rcMiranda;
+ RECT rcThumb;
+ RECT rcOverlap;
+
+ if (!bMouseMoved && fcOpt.bUseSingleClick && bMouseIn){
+ PopUpMessageDialog();
+ }
+
+ //ThumbDeselect( TRUE );
+
+ if ( bMouseDown )
+ {
+ bMouseDown = FALSE;
+ SetCursor( LoadCursor( NULL, IDC_ARROW ) );
+
+ // Check whether we shoud remove the window
+ GetWindowRect( hwndMiranda, &rcMiranda );
+ GetThumbRect( &rcThumb );
+
+ if ( IntersectRect( &rcOverlap, &rcMiranda, &rcThumb ) )
+ {
+ if( IsWindowVisible( hwndMiranda ) )
+ {
+ DeleteContactPos( );
+ thumbList.RemoveThumb( this );
+ }
+ }
+ }
+
+ SaveContactsPos();
+}
+
+void ThumbInfo::OnMouseMove(short nX, short nY, WPARAM wParam)
+{
+// if (bMouseDown && !wParam&MK_LBUTTON) OnLButtonUp();
+
+ int dX;
+ int dY;
+ POINT ptNew;
+
+ // Position thumb
+
+ if( bMouseDown )
+ {
+
+ ptNew.x = nX;
+ ptNew.y = nY;
+
+ ClientToScreen( hwnd, &ptNew );
+
+ dX = ptNew.x - ptOld.x;
+ dY = ptNew.y - ptOld.y;
+
+ if(dX || dY){
+ bMouseMoved = TRUE;
+
+ nLeft += (short)dX;
+ nTop += (short)dY;
+
+ PositionThumb( nLeft, nTop );
+ }
+
+ ptOld = ptNew;
+ }
+ else
+ {
+ SetCursor( LoadCursor( NULL, IDC_ARROW ) );
+ }
+
+ // Update selection status
+ if ( !pThumbMouseIn )//
+ {
+ SetTimer( hwnd, TIMERID_LEAVE_T, 10, NULL );
+ pThumbMouseIn=this;
+
+ ThumbSelect( TRUE );
+ }
+ if(bEnableTip && fcOpt.bShowTip && !bMouseDown){
+ WORD tmpTimeIn;
+ POINT pt;
+ RECT rc;
+
+ GetCursorPos(&pt);
+ GetThumbRect(&rc);
+ if(!PtInRect(&rc,pt)){
+ KillTip();
+ return;
+ }
+ if(fTipTimerActive && abs(pt.x-ptTipSt.x)<5 && abs(pt.y-ptTipSt.x)<5){
+ return;
+ }
+ ptTipSt=pt;
+
+ if (fTipTimerActive) {
+ KillTimer(hwnd, TIMERID_HOVER_T);
+ }
+ if (fTipActive) {
+ return;
+ }
+
+ tmpTimeIn = (fcOpt.TimeIn>0)?fcOpt.TimeIn:CallService(MS_CLC_GETINFOTIPHOVERTIME, 0, 0);
+ SetTimer(hwnd, TIMERID_HOVER_T, tmpTimeIn, 0);
+ fTipTimerActive = TRUE;
+ }
+}
+
+void ThumbInfo::ThumbSelect(BOOL bMouse)
+{
+ if ( bMouse )
+ {
+ bMouseIn = TRUE;
+ SetCapture( hwnd );
+ }
+
+ SetThumbOpacity( 255 );
+}
+
+void ThumbInfo::ThumbDeselect(BOOL bMouse)
+{
+ if ( bMouse )
+ {
+ bMouseIn = FALSE;
+ ReleaseCapture();
+ }
+
+ SetThumbOpacity( fcOpt.thumbAlpha );
+}
+
+void ThumbInfo::SetThumbOpacity(BYTE bAlpha)
+{
+ if ( pUpdateLayeredWindow && (bAlpha != btAlpha) )
+ {
+ btAlpha = bAlpha;
+ UpdateContent();
+ }
+}
+
+void ThumbInfo::KillTip()
+{
+ if (fTipTimerActive)
+ {
+ KillTimer(hwnd, TIMERID_HOVER_T);
+ fTipTimerActive = FALSE;
+ }
+
+ if (fTipActive)
+ {
+ CallService("mToolTip/HideTip", 0, 0);
+ fTipActive = FALSE;
+ }
+}
+
+void ThumbInfo::UpdateContent()
+{
+ bmpContent.allocate(szSize.cx, szSize.cy);
+
+ HFONT hOldFont;
+ SIZE size;
+ RECT rc;
+ RECT rcText;
+ DWORD oldColor;
+ int oldBkMode, index = 0;// nStatus;
+ UINT fStyle = ILD_NORMAL;
+
+ HDC hdcDraw = bmpContent.getDC();
+ SetRect(&rc, 0, 0, szSize.cx, szSize.cy);
+
+ if ( NULL != hBmpBackground )
+ {
+ RECT rcBkgnd;
+ BITMAP bmp;
+ HDC hdcBmp;
+ HBITMAP hbmTmp;
+ int x,y;
+ int maxx,maxy;
+ int destw,desth;
+ int width;
+ int height;
+
+ SetRect(&rcBkgnd, 0, 0, szSize.cx, szSize.cy);
+ if (NULL != hLTEdgesPen)
+ InflateRect(&rcBkgnd, -1, -1);
+ width = rcBkgnd.right - rcBkgnd.left;
+ height = rcBkgnd.bottom - rcBkgnd.top;
+
+ GetObject(hBmpBackground, sizeof(bmp), &bmp);
+ hdcBmp = CreateCompatibleDC( hdcDraw );
+ hbmTmp = (HBITMAP)SelectObject( hdcBmp, hBmpBackground );
+
+ maxx = (0 != (nBackgroundBmpUse & CLBF_TILEH) ? rcBkgnd.right : rcBkgnd.left + 1);
+ maxy = (0 != (nBackgroundBmpUse & CLBF_TILEV) ? rcBkgnd.bottom : rcBkgnd.top + 1);
+ switch (nBackgroundBmpUse & CLBM_TYPE)
+ {
+ case CLB_STRETCH:
+ if (0 != (nBackgroundBmpUse & CLBF_PROPORTIONAL))
+ {
+ if (width * bmp.bmHeight < height * bmp.bmWidth)
+ {
+ desth = height;
+ destw = desth * bmp.bmWidth / bmp.bmHeight;
+ }
+ else
+ {
+ destw = width;
+ desth = destw * bmp.bmHeight / bmp.bmWidth;
+ }
+ }
+ else
+ {
+ destw = width;
+ desth = height;
+ }
+ break;
+
+ case CLB_STRETCHH:
+ destw = width;
+ if (0 != (nBackgroundBmpUse & CLBF_PROPORTIONAL))
+ desth = destw * bmp.bmHeight / bmp.bmWidth;
+ else
+ desth = bmp.bmHeight;
+ break;
+
+ case CLB_STRETCHV:
+ desth = height;
+ if (0 != (nBackgroundBmpUse & CLBF_PROPORTIONAL))
+ destw = desth * bmp.bmWidth / bmp.bmHeight;
+ else
+ destw = bmp.bmWidth;
+ break;
+
+ default: //clb_topleft
+ destw = bmp.bmWidth;
+ desth = bmp.bmHeight;
+ break;
+ }
+ SetStretchBltMode(hdcBmp, STRETCH_HALFTONE);
+
+ for (x = rcBkgnd.left; x < maxx; x += destw)
+ {
+ for (y = rcBkgnd.top; y < maxy; y += desth)
+ {
+ StretchBlt( hdcDraw, x, y, destw, desth, hdcBmp, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY );
+ }
+ }
+
+ SelectObject( hdcBmp, hbmTmp );
+ DeleteDC( hdcBmp );
+ }
+ else
+ {
+ FillRect( hdcDraw, &rc, hBkBrush );
+ }
+
+ if (NULL != hLTEdgesPen)
+ {
+ HPEN hOldPen = (HPEN)SelectObject( hdcDraw, hLTEdgesPen );
+
+ MoveToEx(hdcDraw, 0, 0, NULL);
+ LineTo(hdcDraw, szSize.cx, 0);
+ MoveToEx(hdcDraw, 0, 0, NULL);
+ LineTo(hdcDraw, 0, szSize.cy);
+
+ SelectObject(hdcDraw, hRBEdgesPen);
+
+ MoveToEx(hdcDraw, 0, szSize.cy - 1, NULL);
+ LineTo(hdcDraw, szSize.cx - 1, szSize.cy - 1);
+ MoveToEx(hdcDraw, szSize.cx - 1, szSize.cy - 1, NULL);
+ LineTo(hdcDraw, szSize.cx - 1, 0);
+
+ SelectObject(hdcDraw, hOldPen);
+ //InflateRect(&rc, -1, -1);
+ }
+
+ bmpContent.setAlpha(btAlpha);
+
+ ImageList_GetIconSize_my( himl, size );
+
+ oldBkMode = SetBkMode( hdcDraw, TRANSPARENT );
+
+ if (!DBGetContactSettingByte(hContact, "CList", "NotOnList", 0))
+ {
+ int nStatus;
+ int nContactStatus;
+ int nApparentMode;
+ char* szProto;
+
+
+ szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+
+ if ( NULL != szProto )
+ {
+ nStatus = CallProtoService(szProto, PS_GETSTATUS, 0, 0);
+ nContactStatus = DBGetContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ nApparentMode = DBGetContactSettingWord(hContact, szProto, "ApparentMode", 0);
+
+ if ( (nStatus == ID_STATUS_INVISIBLE && nApparentMode == ID_STATUS_ONLINE) ||
+ (nStatus != ID_STATUS_INVISIBLE && nApparentMode == ID_STATUS_OFFLINE) )
+ {
+ if (ID_STATUS_OFFLINE == nContactStatus)
+ {
+ index = FLT_FONTID_OFFINVIS;
+ }
+ else
+ {
+ index = FLT_FONTID_INVIS;
+ if(fcOpt.bShowIdle && DBGetContactSettingDword(hContact, szProto, "IdleTS", 0)){
+ fStyle|=ILD_BLEND50;
+ }
+ }
+ }
+ else if (ID_STATUS_OFFLINE == nContactStatus)
+ {
+ index = FLT_FONTID_OFFLINE;
+ }
+ else
+ {
+ index = FLT_FONTID_CONTACTS;
+ if(fcOpt.bShowIdle && DBGetContactSettingDword(hContact, szProto, "IdleTS", 0)){
+ fStyle|=ILD_BLEND50;
+ }
+ }
+
+ }
+ }
+ else
+ {
+ index = FLT_FONTID_NOTONLIST;
+ fStyle|=ILD_BLEND50;
+ }
+
+ oldColor = SetTextColor( hdcDraw, tColor[ index ] );
+
+/* ImageList_DrawEx( himl,
+ iIcon,
+ hdcDraw,
+ 2,
+ ( szSize.cy - size.cx ) / 2,
+ 0,
+ 0,
+ CLR_NONE,
+ CLR_NONE,
+ fStyle);
+*/
+ {
+ HICON icon = ImageList_GetIcon(himl, iIcon, ILD_NORMAL);
+ MyBitmap bmptmp(size.cx, size.cy);
+ bmptmp.DrawIcon(icon,0,0);//bmpContent
+ BLENDFUNCTION blend;
+ blend.BlendOp = AC_SRC_OVER;
+ blend.BlendFlags = 0;
+ blend.SourceConstantAlpha = (fStyle&ILD_BLEND50)?128:255;
+ blend.AlphaFormat = AC_SRC_ALPHA;
+ AlphaBlend(hdcDraw, 2,( szSize.cy - size.cx ) / 2, bmptmp.getWidth(), bmptmp.getHeight(), bmptmp.getDC(), 0, 0, bmptmp.getWidth(), bmptmp.getHeight(), blend);
+ DestroyIcon(icon);
+ }
+ SetRect(&rcText, 0, 0, szSize.cx, szSize.cy);
+ rcText.left += size.cx + 4;
+
+ hOldFont = (HFONT)SelectObject( hdcDraw, hFont[ index ] );
+
+ SIZE szText;
+ GetTextExtentPoint32(hdcDraw, ptszName, _tcslen(ptszName), &szText);
+ SetTextColor(hdcDraw, bkColor);
+
+ // simple border
+ bmpContent.DrawText(ptszName, rcText.left-1, (rcText.top + rcText.bottom - szText.cy)/2);
+ bmpContent.DrawText(ptszName, rcText.left+1, (rcText.top + rcText.bottom - szText.cy)/2);
+ bmpContent.DrawText(ptszName, rcText.left, (rcText.top + rcText.bottom - szText.cy)/2-1);
+ bmpContent.DrawText(ptszName, rcText.left, (rcText.top + rcText.bottom - szText.cy)/2+1);
+
+ // blurred border
+ // bmpContent.DrawText(ptszName, rcText.left, (rcText.top + rcText.bottom - szText.cy)/2, 3);
+
+ // text itself
+ SetTextColor(hdcDraw, tColor[index]);
+ bmpContent.DrawText(ptszName, rcText.left, (rcText.top + rcText.bottom - szText.cy)/2);
+
+ SelectObject( hdcDraw, hOldFont );
+
+ SetTextColor( hdcDraw, oldColor );
+ SetBkMode( hdcDraw, oldBkMode );
+
+ if (pUpdateLayeredWindow)
+ {
+ SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED );
+
+ RECT rc; GetWindowRect(hwnd, &rc);
+ POINT ptDst = {rc.left, rc.top};
+ POINT ptSrc = {0, 0};
+
+ BLENDFUNCTION blend;
+ blend.BlendOp = AC_SRC_OVER;
+ blend.BlendFlags = 0;
+ blend.SourceConstantAlpha = 255;
+ blend.AlphaFormat = AC_SRC_ALPHA;
+
+ pUpdateLayeredWindow(hwnd, NULL, &ptDst, &szSize, bmpContent.getDC(), &ptSrc, 0xffffffff, &blend, ULW_ALPHA);
+ } else
+ {
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE);
+ UpdateWindow(hwnd);
+ }
+}
+
+void ThumbInfo::PopUpMessageDialog( )
+{
+ CallService( MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)hContact, (LPARAM)0 );
+}
+
+void ThumbInfo::OnTimer(BYTE idTimer)
+{
+ if(idTimer == TIMERID_SELECT_T){
+ KillTimer( hwnd, TIMERID_SELECT_T );
+ ThumbDeselect( FALSE );
+ }
+ if(idTimer == TIMERID_LEAVE_T && !bMouseDown){
+ POINT pt;
+ RECT rc;
+
+ GetCursorPos(&pt);
+ GetThumbRect(&rc);
+ if(!PtInRect(&rc, pt)){
+ KillTimer( hwnd, TIMERID_LEAVE_T );
+ pThumbMouseIn = NULL;
+ ThumbDeselect( TRUE );
+ }
+ }
+ if(bEnableTip && fcOpt.bShowTip && idTimer == TIMERID_HOVER_T){
+ POINT pt;
+ CLCINFOTIP ti = {0};
+ ti.cbSize = sizeof(ti);
+
+ KillTimer(hwnd, TIMERID_HOVER_T);
+ fTipTimerActive = FALSE;
+ GetCursorPos(&pt);
+ if(abs(pt.x-ptTipSt.x)<5 && abs(pt.y-ptTipSt.y)<5){
+ ti.ptCursor = pt;
+
+ fTipActive = TRUE;
+ ti.isGroup = 0;
+ ti.hItem = hContact;
+ ti.isTreeFocused = 0;
+ CallService("mToolTip/ShowTip", 0, (LPARAM)&ti);
+ }
+ }
+}
+
+void DockThumbs( ThumbInfo *pThumbLeft, ThumbInfo *pThumbRight, BOOL bMoveLeft )
+{
+ if ( ( pThumbRight->dockOpt.hwndLeft == NULL ) && ( pThumbLeft->dockOpt.hwndRight == NULL ) )
+ {
+ pThumbRight->dockOpt.hwndLeft = pThumbLeft->hwnd;
+ pThumbLeft->dockOpt.hwndRight = pThumbRight->hwnd;
+ }
+}
+
+
+void UndockThumbs( ThumbInfo *pThumb1, ThumbInfo *pThumb2 )
+{
+ if ( ( pThumb1 == NULL ) || ( pThumb2 == NULL ) )
+ {
+ return;
+ }
+
+ if ( pThumb1->dockOpt.hwndRight == pThumb2->hwnd )
+ {
+ pThumb1->dockOpt.hwndRight = NULL;
+ }
+
+ if ( pThumb1->dockOpt.hwndLeft == pThumb2->hwnd )
+ {
+ pThumb1->dockOpt.hwndLeft = NULL;
+ }
+
+ if ( pThumb2->dockOpt.hwndRight == pThumb1->hwnd )
+ {
+ pThumb2->dockOpt.hwndRight = NULL;
+ }
+
+ if ( pThumb2->dockOpt.hwndLeft == pThumb1->hwnd )
+ {
+ pThumb2->dockOpt.hwndLeft = NULL;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// ThumbList
+ThumbList::ThumbList(): LIST<ThumbInfo>(1, cmp)
+{
+}
+
+ThumbList::~ThumbList()
+{
+ for (int i = 0; i < getCount(); ++i)
+ delete (*this)[i];
+ destroy();
+}
+
+ThumbInfo *ThumbList::AddThumb(HWND hwnd, TCHAR *ptszName, HANDLE hContact)
+{
+ ThumbInfo *pThumb = NULL;
+
+ if ( ptszName == NULL ) return( NULL );
+ if ( hContact == NULL ) return( NULL );
+ if ( hwnd == NULL ) return( NULL );
+
+ pThumb = new ThumbInfo;
+
+ if ( pThumb != NULL )
+ {
+ _tcsncpy( pThumb->ptszName, ptszName, USERNAME_LEN - 1 );
+ pThumb->hContact = hContact;
+ pThumb->hwnd = hwnd;
+
+ pThumb->dockOpt.hwndLeft = NULL;
+ pThumb->dockOpt.hwndRight = NULL;
+
+ pThumb->fTipActive = FALSE;
+
+// RegHotkey(szName, hwnd);
+ RegHotkey(hContact, hwnd);
+ }
+
+ insert(pThumb);
+
+ return( pThumb );
+}
+
+void ThumbList::RemoveThumb(ThumbInfo *pThumb)
+{
+ if (!pThumb) return;
+
+ if (fcOpt.bMoveTogether)
+ {
+ UndockThumbs(pThumb, FindThumb(pThumb->dockOpt.hwndLeft));
+ UndockThumbs(pThumb, FindThumb(pThumb->dockOpt.hwndRight));
+ }
+
+ remove(pThumb);
+
+ UnregisterFileDropping( pThumb->hwnd );
+ DestroyWindow( pThumb->hwnd );
+ delete pThumb;
+}
+
+ThumbInfo *ThumbList::FindThumb(HWND hwnd)
+{
+ if (!hwnd) return NULL;
+
+ for (int i = 0; i < getCount(); ++i)
+ if ((*this)[i]->hwnd == hwnd)
+ return (*this)[i];
+
+ return NULL;
+}
+
+ThumbInfo *ThumbList::FindThumbByContact(HANDLE hContact)
+{
+ if (!hContact) return NULL;
+
+ for (int i = 0; i < getCount(); ++i)
+ if ((*this)[i]->hContact == hContact)
+ return (*this)[i];
+
+ return NULL;
+}
+
+int ThumbList::cmp(const ThumbInfo *p1, const ThumbInfo *p2)
+{
+ if ((DWORD)p1->hContact < (DWORD)p2->hContact) return -1;
+ if ((DWORD)p1->hContact > (DWORD)p2->hContact) return +1;
+ return 0;
+}
diff --git a/plugins/FloatingContacts/thumbs.h b/plugins/FloatingContacts/thumbs.h
new file mode 100644
index 0000000000..ee6db80097
--- /dev/null
+++ b/plugins/FloatingContacts/thumbs.h
@@ -0,0 +1,74 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+#define USERNAME_LEN 50
+class CDropTarget;
+
+typedef struct _DockOpt
+{
+ HWND hwndLeft;
+ HWND hwndRight;
+}
+DockOpt;
+
+struct ThumbInfo
+{
+public: // TODO: make private
+ HWND hwnd;
+ TCHAR ptszName[ USERNAME_LEN ];
+ HANDLE hContact;
+ int iIcon;
+ CDropTarget * dropTarget;
+ DockOpt dockOpt;
+ BOOL fTipActive;
+ BOOL fTipTimerActive;
+ POINT ptTipSt;
+
+ BYTE btAlpha;
+ MyBitmap bmpContent;
+
+ POINT ptPos;
+ SIZE szSize;
+
+public:
+ ThumbInfo();
+ ~ThumbInfo();
+
+ void GetThumbRect (RECT *rc);
+ void PositionThumb (short nX, short nY);
+ void PositionThumbWorker (short nX, short nY, POINT *rcNewPos);
+ void ResizeThumb ();
+ void RefreshContactIcon (int iIcon);
+ void RefreshContactStatus (int idStatus);
+ void DeleteContactPos ();
+ void OnLButtonDown (short nX, short nY);
+ void OnLButtonUp ();
+ void OnMouseMove (short nX, short nY, WPARAM wParam);
+ void ThumbSelect (BOOL bMouse);
+ void ThumbDeselect (BOOL bMouse);
+ void SetThumbOpacity (BYTE btAlpha);
+ void KillTip ();
+ void UpdateContent ();
+ void PopUpMessageDialog ();
+ void OnTimer (BYTE idTimer);
+};
+
+void UndockThumbs ( ThumbInfo *pThumb1, ThumbInfo *pThumb2 );
+void DockThumbs ( ThumbInfo *pThumbLeft, ThumbInfo *pThumbRight, BOOL bMoveLeft );
+
+class ThumbList: public LIST<ThumbInfo>
+{
+public:
+ ThumbList();
+ ~ThumbList();
+
+ ThumbInfo* AddThumb (HWND hwnd, TCHAR *ptszName, HANDLE hContact);
+ void RemoveThumb (ThumbInfo *pThumb);
+
+ ThumbInfo* FindThumb (HWND hwnd);
+ ThumbInfo* FindThumbByContact (HANDLE hContact);
+
+private:
+ static int cmp(const ThumbInfo *p1, const ThumbInfo *p2);
+};
+
+extern ThumbList thumbList;
diff --git a/plugins/FloatingContacts/version.h b/plugins/FloatingContacts/version.h
new file mode 100644
index 0000000000..2bc7b1cc21
--- /dev/null
+++ b/plugins/FloatingContacts/version.h
@@ -0,0 +1,29 @@
+#define BUILD_NUM 2
+#define BUILD_NUM_STR "2"
+#define REVISION "$Revision: 1136 $"
+
+#define COREVERSION_NUM 1, 0, 2,
+#define COREVERSION_NUM_STR "1, 0, 2"
+
+#define MINIMAL_COREVERSION 0, 6, 0, 0
+#define MINIMAL_COREVERSION_STR "0, 6, 0, 0"
+
+#ifdef UNICODE
+#define UNICODE_AWARE_STR " (Unicode)"
+#else
+#define UNICODE_AWARE_STR " (Ansi)"
+#endif
+
+#define FILE_VERSION COREVERSION_NUM BUILD_NUM
+#define FILE_VERSION_STR COREVERSION_NUM_STR UNICODE_AWARE_STR " build " BUILD_NUM_STR " " REVISION
+
+#define PRODUCT_VERSION FILE_VERSION
+#define PRODUCT_VERSION_STR FILE_VERSION_STR
+
+#define __PLUGIN_NAME "Floating Contacts" UNICODE_AWARE_STR
+#define __FILENAME "FltContacts.dll"
+#define __DESC "Floating Contacts plugin for Miranda"
+#define __AUTHOR "Iavor Vajarov, Kosh&chka, Victor Pavlychko"
+#define __AUTHOREMAIL "ell-6@ya.ru"
+#define __AUTHORWEB "http://www.miranda-im.org/"
+#define __COPYRIGHT " 2002-2004 I. Vajarov (ivajarov@code.bg), 2008 Kosh&chka, V. Pavlychko"
diff --git a/plugins/FloatingContacts/version.rc b/plugins/FloatingContacts/version.rc
new file mode 100644
index 0000000000..8214739c31
--- /dev/null
+++ b/plugins/FloatingContacts/version.rc
@@ -0,0 +1,36 @@
+
+#include <windows.h>
+#include "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 "Author", __AUTHOR
+ VALUE "FileDescription", __DESC
+ VALUE "FileVersion", FILE_VERSION_STR
+ VALUE "InternalName", __PLUGIN_NAME
+ VALUE "LegalCopyright", __COPYRIGHT
+ VALUE "OriginalFilename", __FILENAME
+ VALUE "ProductName", __PLUGIN_NAME
+ VALUE "ProductVersion", PRODUCT_VERSION_STR
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
diff --git a/plugins/Gender/commonheaders.h b/plugins/Gender/commonheaders.h
new file mode 100644
index 0000000000..ef43423b66
--- /dev/null
+++ b/plugins/Gender/commonheaders.h
@@ -0,0 +1,63 @@
+/*
+ Show Contact Gender plugin for Miranda-IM (www.miranda-im.org)
+ (c) 2006-2011 by Thief
+
+ 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 name : $URL: http://svn.miranda.im/mainrepo/gender/trunk/commonheaders.h $
+ Revision : $Rev: 1687 $
+ Last change on : $Date: 2011-01-22 18:44:21 +0200 (Сб, 22 янв 2011) $
+ Last change by : $Author: Thief $
+
+*/
+
+#ifndef COMMHEADERS_H
+#define COMMHEADERS_H
+
+#include <stdio.h> //needed by m_utils.h
+#include <stddef.h> // needed by m_icolib.h > r9256
+
+#include <windows.h>
+#include <commctrl.h>
+
+//Miranda API headers
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_system.h>
+#include <m_protocols.h>
+#include <m_protosvc.h>
+#include <m_utils.h>
+#include <m_clist.h>
+#include <m_options.h>
+#include <m_langpack.h>
+#include <m_genmenu.h>
+#include <m_icolib.h>
+#include <m_cluiframes.h>
+
+//Gender SDK
+#include "m_gender.h"
+
+//Resources
+#include "resource.h"
+
+//external SDK headers
+#include "m_updater.h"
+#include "m_metacontacts.h"
+#include "m_extraicons.h"
+
+static const int DefaultSlot = EXTRA_ICON_ADV2;
+#define MODULENAME "Gender"
+
+#endif //COMMHEADERS_H
diff --git a/plugins/Gender/docs/gender-readme.txt b/plugins/Gender/docs/gender-readme.txt
new file mode 100644
index 0000000000..9b61305da1
--- /dev/null
+++ b/plugins/Gender/docs/gender-readme.txt
@@ -0,0 +1,62 @@
+Gender plugin for Miranda IM (http://miranda-im.org)
+Homepage: http://thief.miranda.im
+Version: 0.0.2.1 (c) 2006-2011 Thief
+Idea by nile, icons by a0x
+
+This plugin shows gender icon in contact list. Nothing more ;)
+
+Changes:
+
+v0.0.2.1
++ 64bit build
++ internal unicode support
+- removed old PLUGININFO support
+
+v0.0.2.0
++ added support for extraicons service plugin
+
+v0.0.1.9
+* gender key is now written to "UserInfo" module instead of protocol (the key doesn't get deleted on info update) (ticket #32)
++ option to draw an icon when no gender info found (ticket #33)
+* look up for gender key in "UserInfo" module and then in protocol
+* other small fixes
+
+v0.0.1.8
+- some changes to icons handling, now Miranda 0.7 is required
++ added possibility to disable contact list icon
+* fixed service function
+
+v0.0.1.7
+- version bump (to allow update from 0.0.1.6 previously released as beta)
+
+v0.0.1.6
++ metacontacts support (thanks sje for clearing things out)
++ added a service for retrieving gender icon for a contact
+
+v0.0.1.5
+* changed icons - now using cute icons by a0x (thanks!)
+
+v0.0.1.4
++ added uuid (FB1C17E0-77FC-45A7-9C8B-E2BEF4F56B28) and MIID_GENDER interface for Miranda 0.8.x compatibility
+* make menu subitem checked when gender key is found
+
+v0.0.1.3
+! addons release
+* hide menu items for chatrooms and non-IM protocols (like weather, etc)
+* icons changes in icolib reflect menuitems icons
++ option to disable menu items
+
+v0.0.1.2
++ plugin now checks "UserInfo" module if gender key was not found in protocol module (FR by BraVo123)
+- MinGW build
+
+v0.0.1.1
++ menuitems to set gender (FR by Shaggoth)
++ langpack and readme
+Happy New Year! :)
+
+v0.0.1.0
+- initial release
+
+Plugin is released under GPL licence.
+http://www.gnu.org/copyleft/gpl.html \ No newline at end of file
diff --git a/plugins/Gender/docs/gender-translate.txt b/plugins/Gender/docs/gender-translate.txt
new file mode 100644
index 0000000000..b2f31b9876
--- /dev/null
+++ b/plugins/Gender/docs/gender-translate.txt
@@ -0,0 +1,24 @@
+[Gender]
+[Male]
+[Female]
+[Undefined]
+[Set Gender]
+[Set Male]
+[Set Female]
+[Set Undefined]
+[Plugin settings]
+[Use]
+[slot to draw the icon]
+[Email]
+[Protocol]
+[SMS]
+[Advanced 1]
+[Advanced 2]
+[Web]
+[Client]
+[Advanced 3]
+[Advanced 4]
+[Advanced 5]
+[Enable menu items]
+[No info]
+[Draw an icon when gender info not found] \ No newline at end of file
diff --git a/plugins/Gender/gender.rc b/plugins/Gender/gender.rc
new file mode 100644
index 0000000000..651f86bd36
--- /dev/null
+++ b/plugins/Gender/gender.rc
@@ -0,0 +1,129 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Ukrainian resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_UKR)
+#ifdef _WIN32
+LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_MALE ICON "icons\\male.ico"
+IDI_FEMALE ICON "icons\\female.ico"
+IDI_UNDEF ICON "icons\\gender.ico"
+#endif // Ukrainian resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_GENDER_OPT DIALOGEX 0, 0, 314, 240
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ COMBOBOX IDC_ADVICON,95,102,78,81,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP,WS_EX_CLIENTEDGE
+ GROUPBOX "Plugin settings",IDC_STATIC,46,78,222,100
+ RTEXT "Use",IDC_USE_L,56,104,33,12
+ LTEXT "slot to draw the icon",IDC_SLOT_L,179,104,76,17
+ CONTROL "Enable menu items",IDC_MENUITEMS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,76,122,167,12
+ LTEXT "Note: if you still don't see the icons try changing icon slot. Perhaps its used by some other plugin.",
+ IDC_NOTE_L,53,152,200,18
+ CONTROL "Draw an icon when gender info not found",
+ IDC_DRAWUNDEFICON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 76,138,167,12
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_GENDER_OPT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 307
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 233
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/Gender/gender_10.sln b/plugins/Gender/gender_10.sln
new file mode 100644
index 0000000000..238e9b5269
--- /dev/null
+++ b/plugins/Gender/gender_10.sln
@@ -0,0 +1,31 @@
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual C++ Express 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gender_10", "gender_10.vcxproj", "{9DF8913A-99A3-40D2-86FE-585EBDDCABB2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release Unicode|Win32 = Release Unicode|Win32
+ Release Unicode|x64 = Release Unicode|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9DF8913A-99A3-40D2-86FE-585EBDDCABB2}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9DF8913A-99A3-40D2-86FE-585EBDDCABB2}.Debug|Win32.Build.0 = Debug|Win32
+ {9DF8913A-99A3-40D2-86FE-585EBDDCABB2}.Debug|x64.ActiveCfg = Debug|x64
+ {9DF8913A-99A3-40D2-86FE-585EBDDCABB2}.Debug|x64.Build.0 = Debug|x64
+ {9DF8913A-99A3-40D2-86FE-585EBDDCABB2}.Release Unicode|Win32.ActiveCfg = Release Unicode|Win32
+ {9DF8913A-99A3-40D2-86FE-585EBDDCABB2}.Release Unicode|Win32.Build.0 = Release Unicode|Win32
+ {9DF8913A-99A3-40D2-86FE-585EBDDCABB2}.Release Unicode|x64.ActiveCfg = Release Unicode|x64
+ {9DF8913A-99A3-40D2-86FE-585EBDDCABB2}.Release Unicode|x64.Build.0 = Release Unicode|x64
+ {9DF8913A-99A3-40D2-86FE-585EBDDCABB2}.Release|Win32.ActiveCfg = Release|Win32
+ {9DF8913A-99A3-40D2-86FE-585EBDDCABB2}.Release|Win32.Build.0 = Release|Win32
+ {9DF8913A-99A3-40D2-86FE-585EBDDCABB2}.Release|x64.ActiveCfg = Release|x64
+ {9DF8913A-99A3-40D2-86FE-585EBDDCABB2}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/plugins/Gender/gender_10.vcxproj b/plugins/Gender/gender_10.vcxproj
new file mode 100644
index 0000000000..cc02d4a65a
--- /dev/null
+++ b/plugins/Gender/gender_10.vcxproj
@@ -0,0 +1,263 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release Unicode|Win32">
+ <Configuration>Release Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release Unicode|x64">
+ <Configuration>Release Unicode</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9DF8913A-99A3-40D2-86FE-585EBDDCABB2}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <ProjectName>gender</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;GENDER2_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(OutDir)gender2.pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;GENDER2_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(OutDir)gender2.pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;GENDER2_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;GENDER2_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;GENDER2_EXPORTS; _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </ClCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;GENDER2_EXPORTS; _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </ClCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="main.cpp" />
+ <ClCompile Include="options.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="commonheaders.h" />
+ <ClInclude Include="m_gender.h" />
+ <ClInclude Include="sdk\m_metacontacts.h" />
+ <ClInclude Include="sdk\m_updater.h" />
+ <ClInclude Include="resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="icons\choose.ico" />
+ <None Include="icons\female.ico" />
+ <None Include="icons\male.ico" />
+ <None Include="docs\gender-readme.txt" />
+ <None Include="docs\gender-translate.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="gender.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Gender/icons/female.ico b/plugins/Gender/icons/female.ico
new file mode 100644
index 0000000000..fe1cbd2bce
--- /dev/null
+++ b/plugins/Gender/icons/female.ico
Binary files differ
diff --git a/plugins/Gender/icons/gender.ico b/plugins/Gender/icons/gender.ico
new file mode 100644
index 0000000000..930c34279c
--- /dev/null
+++ b/plugins/Gender/icons/gender.ico
Binary files differ
diff --git a/plugins/Gender/icons/male.ico b/plugins/Gender/icons/male.ico
new file mode 100644
index 0000000000..ebd0420554
--- /dev/null
+++ b/plugins/Gender/icons/male.ico
Binary files differ
diff --git a/plugins/Gender/main.cpp b/plugins/Gender/main.cpp
new file mode 100644
index 0000000000..e66d3ef41b
--- /dev/null
+++ b/plugins/Gender/main.cpp
@@ -0,0 +1,474 @@
+/*
+ Show Contact Gender plugin for Miranda-IM (www.miranda-im.org)
+ (c) 2006-2011 by Thief
+
+ 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 name : $URL: http://svn.miranda.im/mainrepo/gender/trunk/main.cpp $
+ Revision : $Rev: 1688 $
+ Last change on : $Date: 2011-01-22 19:44:43 +0200 (Сб, 22 янв 2011) $
+ Last change by : $Author: Thief $
+
+*/
+
+#include "commonheaders.h"
+
+HINSTANCE g_hInst;
+PLUGINLINK *pluginLink;
+static HANDLE hHookModulesLoaded = NULL, hSystemOKToExit = NULL, hOptInitialise = NULL, hIcoLibIconsChanged = NULL;
+static HANDLE hHookExtraIconsRebuild = NULL, hHookExtraIconsApply = NULL, hContactMenu = NULL;
+static HANDLE hContactMenuMale = NULL, hContactMenuFemale = NULL, hContactMenuNotDef = NULL, hHookPrebuildContactMenu = NULL;
+static HANDLE hSetMale = NULL, hSetFemale = NULL, hSetUndef = NULL, hGenderGetIcon = NULL;
+
+HANDLE g_hExtraIcon = NULL;
+HANDLE g_hIconMale, g_hIconFemale, g_hIconMenu;
+IconExtraColumn g_IECMale = {0};
+IconExtraColumn g_IECFemale = {0};
+IconExtraColumn g_IECUndef = {0};
+IconExtraColumn g_IECClear = {0};
+
+int clistIcon = 0; // Icon slot to use
+byte bEnableClistIcon = 1; // do we need clist icon?
+byte bDrawNoGenderIcon = 0; // enable icon when no info?
+byte bContactMenuItems = 1; // do we need a contact menu items?
+byte bMetaAvail = 0; // metacontacts installed?
+
+extern int onOptInitialise(WPARAM wParam, LPARAM lParam);
+
+PLUGININFOEX pluginInfo={
+sizeof(PLUGININFOEX),
+#ifdef WIN64
+ "Show Contact Gender (x64)",
+#else
+ "Show Contact Gender",
+#endif
+ PLUGIN_MAKE_VERSION(0,0,2,1),
+ "Shows contacts gender as an icon in contact list",
+ "Thief, idea by nile, icons by a0x",
+ "thief@miranda.im",
+ "2006-2011 Alexander Turyak",
+ "http://thief.miranda.im/",
+ UNICODE_AWARE,
+ 0, //doesn't replace anything built-in
+#ifdef WIN64
+ { 0x3a99592e, 0x20d5, 0x4b72, { 0xa5, 0x96, 0xe6, 0x7d, 0xd7, 0x13, 0xde, 0xfb } } // {3A99592E-20D5-4B72-A596-E67DD713DEFB}
+#else
+ {0xfb1c17e0, 0x77fc, 0x45a7, {0x9c, 0x8b, 0xe2, 0xbe, 0xf4, 0xf5, 0x6b, 0x28}} /* FB1C17E0-77FC-45A7-9C8B-E2BEF4F56B28 */
+#endif
+};
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ g_hInst = hinstDLL;
+ return TRUE;
+}
+
+/* 0FF3991A-5505-479D-A2E0-53DD31C6DFA7 */
+#define MIID_GENDER {0x0ff3991a, 0x5505, 0x479d, {0xa2, 0xe0, 0x53, 0xdd, 0x31, 0xc6, 0xdf, 0xa7}}
+
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ static const MUUID interfaces[] = {MIID_GENDER, MIID_LAST};
+ return interfaces;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+void setIcon(HANDLE hContact, unsigned int gender)
+{
+ if (g_hExtraIcon != NULL)
+ {
+ char *ico;
+ switch (gender)
+ {
+ case 77: ico = "male_icon"; break;
+ case 70: ico = "female_icon"; break;
+ default: ico = (bDrawNoGenderIcon ? "menu_icon" : NULL); break;
+ }
+ ExtraIcon_SetIcon(g_hExtraIcon, hContact, ico);
+ }
+ else
+ {
+ IconExtraColumn *col;
+ switch (gender)
+ {
+ case 77: col = &g_IECMale; break;
+ case 70: col = &g_IECFemale; break;
+ default: col = (bDrawNoGenderIcon ? &g_IECUndef : &g_IECClear); break;
+ }
+ CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM)hContact, (LPARAM)col);
+ }
+}
+
+int onExtraImageApplying(WPARAM wParam, LPARAM lParam)
+{
+ if (g_hExtraIcon == NULL && !bEnableClistIcon) return 0;
+
+ HANDLE hContact = (HANDLE)wParam;
+ if (bMetaAvail)
+ {
+ HANDLE hMetacontact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, wParam, 0);
+ if (hMetacontact != NULL) hContact = hMetacontact;
+ }
+
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);
+ if (!proto) return 0;
+
+ if (DBGetContactSettingByte((HANDLE)wParam, proto, "ChatRoom", 0)) return 0;
+
+ unsigned int gender = DBGetContactSettingByte(hContact, "UserInfo", "Gender", DBGetContactSettingByte(hContact, proto, "Gender", 0));
+
+ setIcon(hContact, gender);
+ if ((HANDLE)wParam != hContact)
+ setIcon((HANDLE)wParam, gender);
+
+ return 0;
+}
+
+int onExtraImageListRebuild(WPARAM wParam, LPARAM lParam)
+{
+ g_IECMale.cbSize = sizeof(IconExtraColumn);
+ g_IECMale.ColumnType = clistIcon;
+ g_IECFemale.cbSize = sizeof(IconExtraColumn);
+ g_IECFemale.ColumnType = clistIcon;
+ g_IECUndef.cbSize = sizeof(IconExtraColumn);
+ g_IECUndef.ColumnType = clistIcon;
+
+ if (ServiceExists(MS_CLIST_EXTRA_ADD_ICON))
+ {
+ if(hIcoLibIconsChanged)
+ {
+ g_IECMale.hImage = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)g_hIconMale), (LPARAM)0);
+ g_IECFemale.hImage = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)g_hIconFemale), (LPARAM)0);
+ g_IECUndef.hImage = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)g_hIconMenu), (LPARAM)0);
+ }
+ }
+
+ return 0;
+}
+
+// Returns gender icon for specific contact
+INT_PTR GetIcon(WPARAM wParam, LPARAM lParam)
+{
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);
+ unsigned short gender = DBGetContactSettingByte((HANDLE)wParam, "UserInfo", "Gender", DBGetContactSettingByte((HANDLE)wParam, proto, "Gender", 0));
+
+ if (gender > 0)
+ {
+ if (gender == 77) return CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)g_hIconMale);
+ else if (gender == 70) return CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)g_hIconFemale);
+ }
+
+ return 0;
+}
+
+int onPrebuildContactMenu(WPARAM wParam, LPARAM lParam)
+{
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);
+
+ if (!proto) return 0;
+
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(CLISTMENUITEM);
+
+
+ if (DBGetContactSettingByte((HANDLE)wParam, proto, "ChatRoom", 0) || !(CallProtoService(proto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMSEND))
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ else
+ mi.flags = CMIM_FLAGS;
+
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenu, (LPARAM)&mi);
+
+ unsigned short gender = DBGetContactSettingByte((HANDLE)wParam, proto, "Gender", DBGetContactSettingByte((HANDLE)wParam, "UserInfo", "Gender", 0));
+
+ CLISTMENUITEM mitem = {0};
+ mitem.cbSize = sizeof(CLISTMENUITEM);
+ mitem.flags = CMIM_FLAGS;
+
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuMale, (LPARAM)&mitem);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuFemale, (LPARAM)&mitem);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuNotDef, (LPARAM)&mitem);
+
+ mitem.flags = CMIM_FLAGS | CMIF_CHECKED;
+
+ switch (gender)
+ {
+ case 77:
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuMale, (LPARAM)&mitem);
+ break;
+ case 70:
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuFemale, (LPARAM)&mitem);
+ break;
+ case 0:
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hContactMenuNotDef, (LPARAM)&mitem);
+ break;
+ }
+
+ return 0;
+}
+
+void setGender(HANDLE hContact, unsigned int gender)
+{
+ DBWriteContactSettingByte(hContact, "UserInfo", "Gender", gender);
+ setIcon(hContact, gender);
+
+ int metasnum = (bMetaAvail ? CallService(MS_MC_GETNUMCONTACTS,(WPARAM)hContact,0) : 0);
+ for(int i=0; i<metasnum; i++)
+ {
+ HANDLE hSubContact = (HANDLE)CallService(MS_MC_GETSUBCONTACT, (WPARAM)hContact, i);
+ DBWriteContactSettingByte(hSubContact, "UserInfo", "Gender", gender);
+ setIcon(hSubContact, gender);
+ }
+}
+
+INT_PTR onSetMale(WPARAM wParam,LPARAM lParam)
+{
+ setGender((HANDLE)wParam, 77);
+ return 0;
+}
+
+INT_PTR onSetFemale(WPARAM wParam,LPARAM lParam)
+{
+ setGender((HANDLE)wParam, 70);
+ return 0;
+}
+
+INT_PTR onSetUndef(WPARAM wParam,LPARAM lParam)
+{
+ DBDeleteContactSetting((HANDLE)wParam, "UserInfo", "Gender");
+ onExtraImageApplying(wParam, 0);
+
+ int metasnum = (bMetaAvail ? CallService(MS_MC_GETNUMCONTACTS,wParam,0) : 0);
+ for(int i=0; i<metasnum; i++)
+ {
+ HANDLE hContact = (HANDLE)CallService(MS_MC_GETSUBCONTACT, wParam, i);
+ DBDeleteContactSetting(hContact, "UserInfo", "Gender");
+ onExtraImageApplying((WPARAM)hContact, 0);
+ }
+
+ return 0;
+}
+
+int onModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ hOptInitialise = HookEvent(ME_OPT_INITIALISE, onOptInitialise);
+ if (bContactMenuItems) hHookPrebuildContactMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, onPrebuildContactMenu);
+ bMetaAvail = (ServiceExists(MS_MC_GETMETACONTACT) != 0);
+
+ //IcoLib support
+ if(ServiceExists(MS_SKIN2_ADDICON))
+ {
+ SKINICONDESC sid = {0};
+ sid.cbSize = SKINICONDESC_SIZE;
+ sid.flags = SIDF_ALL_TCHAR;
+ sid.ptszSection = LPGENT("Gender");
+ TCHAR szFile[MAX_PATH];
+ GetModuleFileName(g_hInst, szFile, MAX_PATH);
+ sid.ptszDefaultFile = szFile;
+
+ sid.ptszDescription = LPGENT("Male");
+ sid.pszName = "male_icon";
+ sid.iDefaultIndex = -IDI_MALE;
+ g_hIconMale = (HANDLE)CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.ptszDescription = LPGENT("Female");
+ sid.pszName = "female_icon";
+ sid.iDefaultIndex = -IDI_FEMALE;
+ g_hIconFemale = (HANDLE)CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.ptszDescription = LPGENT("No info");
+ sid.pszName = "menu_icon";
+ sid.iDefaultIndex = -IDI_UNDEF;
+ g_hIconMenu = (HANDLE)CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ hIcoLibIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, onExtraImageListRebuild);
+ }
+
+ g_hExtraIcon = ExtraIcon_Register("gender", "Gender", "menu_icon");
+ if (g_hExtraIcon != NULL)
+ {
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact != NULL)
+ {
+ onExtraImageApplying((WPARAM) hContact, 0);
+
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+ }
+ else
+ {
+ hHookExtraIconsRebuild = HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, onExtraImageListRebuild);
+ hHookExtraIconsApply = HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, onExtraImageApplying);
+
+ onExtraImageListRebuild(0,0);
+ }
+
+ // Adding menu items, submenu even if clist supports that
+ if (bContactMenuItems)
+ {
+ if(ServiceExists(MS_CLIST_ADDSUBGROUPMENUITEM))
+ {
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(CLISTMENUITEM);
+ mi.flags = CMIF_ROOTPOPUP | CMIF_ICONFROMICOLIB | CMIF_TCHAR;
+ mi.icolibItem = g_hIconMenu;
+ mi.pszPopupName = (char*)-1;
+ mi.position = 203;
+ mi.ptszName = LPGENT("Set Gender");
+ mi.pszService = NULL;
+ hContactMenu = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) &mi);
+
+ mi.flags = CMIF_CHILDPOPUP | CMIF_ICONFROMICOLIB | CMIF_TCHAR;
+ mi.position = 1001;
+ mi.pszPopupName = (char*)hContactMenu;
+
+ mi.ptszName = LPGENT("Male");
+ mi.icolibItem = g_hIconMale;
+ mi.pszService = "Gender/MenuItemSetMale";
+ hContactMenuMale = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) &mi);
+
+ mi.ptszName = LPGENT("Female");
+ mi.icolibItem = g_hIconFemale;
+ mi.pszService = "Gender/MenuItemSetFemale";
+ hContactMenuFemale = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) &mi);
+
+ mi.ptszName = LPGENT("Undefined");
+ mi.hIcon = NULL;
+ mi.pszService = "Gender/MenuItemSetUndef";
+ hContactMenuNotDef = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) &mi);
+ }
+ else
+ {
+ CLISTMENUITEM mimale = {0};
+ mimale.cbSize = sizeof(CLISTMENUITEM);
+ mimale.flags = CMIF_ICONFROMICOLIB | CMIF_TCHAR;
+ mimale.position = 1001;
+ mimale.ptszName = LPGENT("Set Male");
+ mimale.icolibItem = g_hIconMale;
+ mimale.pszService = "Gender/MenuItemSetMale";
+ hContactMenuMale = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) &mimale);
+
+ CLISTMENUITEM mifemale = {0};
+ mifemale.cbSize = sizeof(CLISTMENUITEM);
+ mifemale.flags = CMIF_ICONFROMICOLIB | CMIF_TCHAR;
+ mifemale.position = 1002;
+ mifemale.ptszName = LPGENT("Set Female");
+ mifemale.icolibItem = g_hIconFemale;
+ mifemale.pszService = "Gender/MenuItemSetFemale";
+ hContactMenuFemale = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) &mifemale);
+
+ CLISTMENUITEM miundef = {0};
+ miundef.cbSize = sizeof(CLISTMENUITEM);
+ miundef.flags = CMIF_TCHAR;
+ miundef.position = 1003;
+ miundef.ptszName = LPGENT("Set Undefined");
+ miundef.pszService = "Gender/MenuItemSetUndef";
+ miundef.hIcon = NULL;
+ hContactMenuNotDef = (HANDLE) CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) &miundef);
+ }
+ }
+
+ // Updater support
+ if (ServiceExists(MS_UPDATE_REGISTER))
+ {
+ Update update = {0};
+ char szVersion[16];
+
+ update.cbSize = sizeof(Update);
+
+ update.szComponentName = pluginInfo.shortName;
+ update.pbVersion = (BYTE *)CreateVersionStringPluginEx(&pluginInfo, szVersion);
+ update.cpbVersion = (int)strlen((char *)update.pbVersion);
+
+ update.szUpdateURL = UPDATER_AUTOREGISTER;
+
+#ifndef WIN64
+ // these are the three lines that matter - the archive, the page containing the version string, and the text (or data)
+ // before the version that we use to locate it on the page
+ // (note that if the update URL and the version URL point to standard file listing entries, the backend xml
+ // data will be used to check for updates rather than the actual web page - this is not true for beta urls)
+ update.szBetaUpdateURL = "http://thief.miranda.im/gender.zip";
+ update.szBetaVersionURL = "http://thief.miranda.im/updater/gender_version.txt";
+ update.szBetaChangelogURL = "http://thief.miranda.im";
+ update.pbBetaVersionPrefix = (BYTE *)"Gender ";
+
+ update.cpbBetaVersionPrefix = strlen((char *)update.pbBetaVersionPrefix);
+#endif
+
+ CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update);
+ }
+
+ return 0;
+}
+
+int onSystemOKToExit(WPARAM wParam,LPARAM lParam)
+{
+ UnhookEvent(hHookModulesLoaded);
+ UnhookEvent(hHookExtraIconsRebuild);
+ UnhookEvent(hHookExtraIconsApply);
+ UnhookEvent(hHookPrebuildContactMenu);
+ UnhookEvent(hOptInitialise);
+ UnhookEvent(hSystemOKToExit);
+ if (hIcoLibIconsChanged) UnhookEvent(hIcoLibIconsChanged);
+
+
+ DestroyServiceFunction(hSetMale);
+ DestroyServiceFunction(hSetFemale);
+ DestroyServiceFunction(hSetUndef);
+ DestroyServiceFunction(hGenderGetIcon);
+
+ if (hIcoLibIconsChanged)
+ {
+ CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)"menu_icon");
+ CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)"male_icon");
+ CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)"female_icon");
+ }
+
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ pluginLink = link;
+
+ hHookModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, onModulesLoaded);
+ hSystemOKToExit = HookEvent(ME_SYSTEM_OKTOEXIT,onSystemOKToExit);
+
+ bEnableClistIcon = DBGetContactSettingByte(NULL, MODULENAME, "ClistIcon", 1);
+ bContactMenuItems = DBGetContactSettingByte(NULL, MODULENAME, "MenuItems", 1);
+ bDrawNoGenderIcon = DBGetContactSettingByte(NULL, MODULENAME, "NoGenderIcon", 0);
+
+
+ hSetMale = CreateServiceFunction("Gender/MenuItemSetMale", onSetMale);
+ hSetFemale = CreateServiceFunction("Gender/MenuItemSetFemale", onSetFemale);
+ hSetUndef = CreateServiceFunction("Gender/MenuItemSetUndef", onSetUndef);
+
+ clistIcon = DBGetContactSettingByte(NULL, MODULENAME, "AdvancedIcon", DefaultSlot);
+ g_IECClear.cbSize = sizeof(IconExtraColumn);
+ g_IECClear.ColumnType = clistIcon;
+ g_IECClear.hImage = (HANDLE) -1;
+
+ hGenderGetIcon = CreateServiceFunction(MS_GENDER_GETICON, GetIcon);
+
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ return 0;
+}
diff --git a/plugins/Gender/options.cpp b/plugins/Gender/options.cpp
new file mode 100644
index 0000000000..32d919c020
--- /dev/null
+++ b/plugins/Gender/options.cpp
@@ -0,0 +1,167 @@
+/*
+ Show Contact Gender plugin for Miranda-IM (www.miranda-im.org)
+ (c) 2006-2011 by Thief
+
+ 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 name : $URL: http://svn.miranda.im/mainrepo/gender/trunk/options.cpp $
+ Revision : $Rev: 1687 $
+ Last change on : $Date: 2011-01-22 18:44:21 +0200 (Сб, 22 янв 2011) $
+ Last change by : $Author: Thief $
+
+*/
+
+#include "commonheaders.h"
+
+extern HINSTANCE g_hInst;
+extern int onExtraImageApplying(WPARAM wParam, LPARAM lParam);
+extern int onExtraImageListRebuild(WPARAM wParam, LPARAM lParam);
+extern IconExtraColumn g_IECClear;
+extern int clistIcon;
+extern HANDLE g_hExtraIcon;
+extern byte bContactMenuItems, bEnableClistIcon, bDrawNoGenderIcon;
+const TCHAR *szAdvancedIcons[] = {LPGENT("Email"), LPGENT("Protocol"), LPGENT("SMS"), LPGENT("Advanced 1"), LPGENT("Advanced 2"), LPGENT("Web"), LPGENT("Client"), LPGENT("Advanced 3"), LPGENT("Advanced 4"), LPGENT("Advanced 5")};
+const int cAdvancedIcons = sizeof(szAdvancedIcons) / sizeof(szAdvancedIcons[0]);
+
+INT_PTR CALLBACK DlgProcOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static int bInitializing = 0;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ bInitializing = 1;
+ if (g_hExtraIcon == NULL)
+ {
+ SendMessage(GetDlgItem(hwndDlg, IDC_ADVICON), CB_ADDSTRING, 0, (LPARAM) TranslateT("Disabled"));
+ for (int i = 0; i < cAdvancedIcons; i++)
+ {
+ SendMessage(GetDlgItem(hwndDlg, IDC_ADVICON), CB_ADDSTRING, 0, (LPARAM) TranslateTS(szAdvancedIcons[i]));
+ }
+
+ if (bEnableClistIcon)
+ SendMessage(GetDlgItem(hwndDlg, IDC_ADVICON), CB_SETCURSEL, clistIcon, 0);
+ else
+ SendMessage(GetDlgItem(hwndDlg, IDC_ADVICON), CB_SETCURSEL, 0, 0);
+ }
+ else
+ {
+ ShowWindow(GetDlgItem(hwndDlg, IDC_USE_L), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ADVICON), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_SLOT_L), SW_HIDE);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_NOTE_L), SW_HIDE);
+ }
+ CheckDlgButton(hwndDlg, IDC_MENUITEMS, DBGetContactSettingByte(NULL, MODULENAME, "MenuItems", 1) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DRAWUNDEFICON, bDrawNoGenderIcon ? BST_CHECKED : BST_UNCHECKED);
+
+ bInitializing = 0;
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam)) {
+ case IDC_ADVICON:
+ {
+ if ((HIWORD(wParam) == EN_CHANGE) && (!bInitializing) || (HIWORD(wParam) == CBN_SELENDOK))
+ {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+ break;
+ case IDC_MENUITEMS:
+ case IDC_DRAWUNDEFICON:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ if (((LPNMHDR)lParam)->idFrom == 0)
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ HANDLE hContact;
+
+ bDrawNoGenderIcon = IsDlgButtonChecked(hwndDlg, IDC_DRAWUNDEFICON);
+
+ if (g_hExtraIcon == NULL)
+ {
+ clistIcon = SendMessage(GetDlgItem(hwndDlg, IDC_ADVICON), CB_GETCURSEL, 0, 0);
+ DBWriteContactSettingByte(NULL, MODULENAME, "AdvancedIcon", clistIcon);
+
+ if (bEnableClistIcon)
+ {
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact)
+ {
+ CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM)hContact, (LPARAM)&g_IECClear);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ }
+
+ bEnableClistIcon = (clistIcon != 0);
+
+ if (bEnableClistIcon)
+ {
+ g_IECClear.ColumnType = clistIcon;
+ onExtraImageListRebuild(0,0);
+ }
+ }
+
+ if (g_hExtraIcon != NULL || bEnableClistIcon)
+ {
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact)
+ {
+ onExtraImageApplying((WPARAM)hContact,0);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ }
+
+ DBWriteContactSettingByte(NULL, MODULENAME, "ClistIcon", bEnableClistIcon);
+ DBWriteContactSettingByte(NULL, MODULENAME, "NoGenderIcon", bDrawNoGenderIcon);
+ DBWriteContactSettingByte(NULL, MODULENAME, "MenuItems", IsDlgButtonChecked(hwndDlg, IDC_MENUITEMS));
+ }
+ return TRUE;
+ }
+ }
+
+ case WM_DESTROY:
+ break;
+ }
+ return FALSE;
+}
+
+int onOptInitialise(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp;
+ ZeroMemory(&odp, sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.position = 0;
+ odp.hInstance = g_hInst;
+ odp.ptszGroup = LPGENT("Plugins");
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_GENDER_OPT);
+ odp.ptszTitle = LPGENT("Gender");
+ odp.pfnDlgProc = DlgProcOptions;
+ odp.flags = ODPF_BOLDGROUPS|ODPF_TCHAR;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) &odp);
+
+ return 0;
+}
diff --git a/plugins/Gender/resource.h b/plugins/Gender/resource.h
new file mode 100644
index 0000000000..8ea2786991
--- /dev/null
+++ b/plugins/Gender/resource.h
@@ -0,0 +1,25 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by gender.rc
+//
+#define IDD_GENDER_OPT 9
+#define IDI_MALE 101
+#define IDI_FEMALE 102
+#define IDI_UNDEF 103
+#define IDC_ADVICON 1001
+#define IDC_MENUITEMS 1002
+#define IDC_DRAWUNDEFICON 1003
+#define IDC_USE_L 1004
+#define IDC_SLOT_L 1005
+#define IDC_NOTE_L 1006
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 104
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1007
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/ProfileManager/pmanagerEx.c b/plugins/ProfileManager/pmanagerEx.c
new file mode 100644
index 0000000000..63f57f5bea
--- /dev/null
+++ b/plugins/ProfileManager/pmanagerEx.c
@@ -0,0 +1,109 @@
+/*
+Miranda plugin template, originally by Richard Hughes
+http://miranda-icq.sourceforge.net/
+
+This file is placed in the public domain. Anybody is free to use or
+modify it as they wish with no restriction.
+There is no warranty.
+*/
+#include <windows.h>
+#include <newpluginapi.h>
+#include <m_clist.h>
+#include <m_skin.h>
+#include <m_langpack.h>
+#include <tchar.h>
+#include "resource.h"
+
+
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+TCHAR fn[MAX_PATH];
+TCHAR lmn[MAX_PATH];
+TCHAR* pathn;
+
+#define SIZEOF(x) (sizeof(x)/sizeof(*x))
+
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ "Miranda IM Profile Changer",
+ PLUGIN_MAKE_VERSION(0,0,0,3),
+ "Adds a menu item to change or load a different profile of Miranda IM.",
+ "Roman Gemini",
+ "woobind@ukr.net",
+ " 2008 - 2010 Roman Gemini",
+ "http://code.google.com/p/alfamar/",
+ 0, //not transient
+ 0, //doesn't replace anything built-in
+ // Generate your own unique id for your plugin.
+ // Do not use this UUID!
+ // Use uuidgen.exe to generate the uuuid
+ {0x7eeeb55e, 0x9d83, 0x4e1a, { 0xa1, 0x2f, 0x8f, 0x13, 0xf1, 0xa1, 0x24, 0xfb } }
+
+};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInst=hinstDLL;
+ return TRUE;
+}
+
+static int ChangePM(WPARAM wParam,LPARAM lParam)
+{
+ GetModuleFileName(GetModuleHandle(NULL), fn, SIZEOF(fn));
+ ShellExecute(0, "open", fn, "/FORCESHOW", "", 1);
+ CallService("CloseAction", 0, 0);
+ return 0;
+}
+
+static int LoadPM(WPARAM wParam,LPARAM lParam)
+{
+ GetModuleFileName(GetModuleHandle(NULL), fn, SIZEOF(fn));
+ ShellExecute(0, "open", fn, "/FORCESHOW", "", 1);
+ return 0;
+}
+
+
+__declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+static const MUUID interfaces[] = {MIID_TESTPLUGIN, MIID_LAST};
+__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ CLISTMENUITEM mi;
+ pluginLink=link;
+
+ CreateServiceFunction("Database/LoadPM",LoadPM);
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize=sizeof(mi);
+ mi.position=-500200000;
+ mi.flags=0;
+ mi.hIcon=LoadIcon(hInst, MAKEINTRESOURCE(IDI_LoadPM));
+ mi.pszPopupName = "Database";
+ mi.pszName=LPGEN("Load profile");
+ mi.pszService="Database/LoadPM";
+ CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi);
+
+ CreateServiceFunction("Database/ChangePM",ChangePM);
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize=sizeof(mi);
+ mi.position=-500200000;
+ mi.flags=0;
+ mi.hIcon=LoadIcon(hInst, MAKEINTRESOURCE(IDI_ChangePM));
+ mi.pszPopupName = "Database";
+ mi.pszName=LPGEN("Change profile");
+ mi.pszService="Database/ChangePM";
+ CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi);
+ return 0;
+}
+
+int __declspec(dllexport) Unload(void)
+{
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/ProfileManager/pmanagerEx.vcproj b/plugins/ProfileManager/pmanagerEx.vcproj
new file mode 100644
index 0000000000..4c5613bdec
--- /dev/null
+++ b/plugins/ProfileManager/pmanagerEx.vcproj
@@ -0,0 +1,247 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="pmanagerEx"
+ ProjectGUID="{728CF16E-F3FF-4DEB-88C5-E9118F61ACD5}"
+ RootNamespace="pmanager"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/pmanager.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="4"
+ AdditionalIncludeDirectories="../../include;../ExternalAPI"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;pmanager_EXPORTS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="0"
+ PrecompiledHeaderFile=".\Debug/pmanager.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="2057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="./plugins/pmanager.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ ProgramDatabaseFile=".\Debug/pmanager.pdb"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary=".\Debug/pmanager.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile=".\Debug/pmanager.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release Unicode|Win32"
+ OutputDirectory="$(SolutionDir)/Debug/"
+ IntermediateDirectory="$(SolutionDir)/Debug/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/pmanager.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="2"
+ OmitFramePointers="false"
+ EnableFiberSafeOptimizations="false"
+ AdditionalIncludeDirectories="../../include;../ExternalAPI"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;pmanager_EXPORTS"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ EnableEnhancedInstructionSet="2"
+ PrecompiledHeaderFile="$(IntDir)/pmanager.pch"
+ AssemblerListingLocation="$(IntDir)/"
+ ObjectFile="$(IntDir)/"
+ ProgramDataBaseFileName="$(IntDir)/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="2057"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="D:\Miranda\plugins/pmanager.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ ManifestFile="$(IntDir)\$(TargetFileName).intermediate.manifest"
+ ProgramDatabaseFile="$(IntDir)/pmanager.pdb"
+ ProfileGuidedDatabase=""
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(IntDir)/pmanager.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ OutputDocumentFile="$(IntDir)$(TargetName).xml"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile="$(IntDir)/pmanager.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine=""
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath=".\pmanagerEx.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ <File
+ RelativePath=".\resource.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/plugins/ProfileManager/res/ChangePM.ico b/plugins/ProfileManager/res/ChangePM.ico
new file mode 100644
index 0000000000..89b5d08f0f
--- /dev/null
+++ b/plugins/ProfileManager/res/ChangePM.ico
Binary files differ
diff --git a/plugins/ProfileManager/res/LoadPM.ico b/plugins/ProfileManager/res/LoadPM.ico
new file mode 100644
index 0000000000..ec298dea37
--- /dev/null
+++ b/plugins/ProfileManager/res/LoadPM.ico
Binary files differ
diff --git a/plugins/ProfileManager/resource.h b/plugins/ProfileManager/resource.h
new file mode 100644
index 0000000000..638fcfb4f6
--- /dev/null
+++ b/plugins/ProfileManager/resource.h
@@ -0,0 +1,17 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by resource.rc
+//
+#define IDI_ChangePM 101
+#define IDI_LoadPM 102
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 105
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1007
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/ProfileManager/resource.rc b/plugins/ProfileManager/resource.rc
new file mode 100644
index 0000000000..92a42063c4
--- /dev/null
+++ b/plugins/ProfileManager/resource.rc
@@ -0,0 +1,46 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.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(1250)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ChangePM ICON "res/ChangePM.ico"
+IDI_LoadPM ICON "res/LoadPM.ico"
+#endif // Neutral resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/Rate/commonheaders.h b/plugins/Rate/commonheaders.h
new file mode 100644
index 0000000000..34aeb65dff
--- /dev/null
+++ b/plugins/Rate/commonheaders.h
@@ -0,0 +1,78 @@
+/*
+ Authorization State plugin for Miranda-IM (www.miranda-im.org)
+ (c) 2006 by Thief
+ Icons by Faith Healer
+
+ 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 name : $URL: http://svn.mirandaim.ru/mainrepo/authstate/trunk/commonheaders.h $
+ Revision : $Rev: 222 $
+ Last change on : $Date: 2006-09-26 05:54:03 +0700 (Вт, 26 сен 2006) $
+ Last change by : $Author: Thief $
+
+*/
+
+#ifndef COMMHEADERS_H
+#define COMMHEADERS_H
+
+//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+
+//needed by m_utils.h
+#include <stdio.h>
+
+// needed by m_icolib.h > r9256
+#include <stddef.h>
+
+//Miranda API headers
+#include <windows.h>
+#include <win2k.h>
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_system.h>
+//#include <m_protocols.h>
+#include <m_utils.h>
+#include <m_clist.h>
+#include <m_options.h>
+#include <m_langpack.h>
+#include <m_icolib.h>
+#include "resource.h"
+
+//external SDK headers
+#include <m_cluiframes.h>
+#include <m_updater.h>
+#include <m_extraicons.h>
+
+static const int DefaultSlot = EXTRA_ICON_PROTO;
+#define MODULENAME "Rate"
+
+/* 0e2866a8-6f4c-4132-98ae-6afdb8766c48 */
+#define MIID_CONTACTSRATE {0x0e2866a8, 0x6f4c, 0x4132, {0x98, 0xae, 0x6a, 0xfd, 0xb8, 0x76, 0x6c, 0x48}}
+
+static struct
+{
+ char* szDescr;
+ char* szName;
+ int defIconID;
+ HANDLE hIconLibItem;
+} iconList[] =
+{
+ { LPGEN( "Rate high" ), "rate_high", IDI_RATEHI },
+ { LPGEN( "Rate medium" ), "rate_medium", IDI_RATEME },
+ { LPGEN( "Rate low" ), "rate_low", IDI_RATELO },
+};
+
+
+
+#endif //COMMHEADERS_H
diff --git a/plugins/Rate/docs/Rate-readme.txt b/plugins/Rate/docs/Rate-readme.txt
new file mode 100644
index 0000000000..aafc63f812
--- /dev/null
+++ b/plugins/Rate/docs/Rate-readme.txt
@@ -0,0 +1,49 @@
+Contacts Rate plugin for Miranda IM (http://miranda-im.org)
+Version: 0.0.2.1 (c) 2007-2009 Kildor
+Icons by Faith Healer
+
+This small plugin intended to show an icon in front of contacts which have
+non-empty rating at Modern Contact List.
+
+http://svn.miranda.im/mainrepo/contacts_rate/trunk/ - plugin`s SVN
+
+I would like to say thanks to:
+Faith Healer for icons
+Thief for his Authstate plugin that was base for this plugin.
+FYR for his clist_modern
+
+
+Changes:
+
+v0.0.2.1
+- Translation fixes.
+
+v0.0.2.0
+- ExtraIcons plugin support (big thanks to Pescuma for patch)
+
+v0.0.1.5
+- fixes typos and bugs
+- add support for clist_nicer and clist_mw, and handling of clist_classic
+
+v0.0.1.4
+- Fix for new m_cluiframes.h (need to be checked with clist_nicer)
+
+v0.0.1.3
+- More clean-up.
+
+v0.0.1.2
+- clean-up.
+
+v0.0.1.1
+- fix for new pluginapi
+- copyrights update
+- small clean-up
+
+v0.0.1.0
+- public release
+
+v0.0.0.x
+- test versions, unreleased
+
+Plugin is released under GPL licence.
+http://www.gnu.org/copyleft/gpl.html
diff --git a/plugins/Rate/docs/rate.txt b/plugins/Rate/docs/rate.txt
new file mode 100644
index 0000000000..e743807a44
--- /dev/null
+++ b/plugins/Rate/docs/rate.txt
@@ -0,0 +1 @@
+Rate 0.0.2.1 \ No newline at end of file
diff --git a/plugins/Rate/icons/rate_high.ico b/plugins/Rate/icons/rate_high.ico
new file mode 100644
index 0000000000..ad5fa6acf1
--- /dev/null
+++ b/plugins/Rate/icons/rate_high.ico
Binary files differ
diff --git a/plugins/Rate/icons/rate_low.ico b/plugins/Rate/icons/rate_low.ico
new file mode 100644
index 0000000000..66a340da9c
--- /dev/null
+++ b/plugins/Rate/icons/rate_low.ico
Binary files differ
diff --git a/plugins/Rate/icons/rate_med.ico b/plugins/Rate/icons/rate_med.ico
new file mode 100644
index 0000000000..2b3220de1b
--- /dev/null
+++ b/plugins/Rate/icons/rate_med.ico
Binary files differ
diff --git a/plugins/Rate/main.cpp b/plugins/Rate/main.cpp
new file mode 100644
index 0000000000..9810378eca
--- /dev/null
+++ b/plugins/Rate/main.cpp
@@ -0,0 +1,289 @@
+/*==========================================================================*/
+/*
+ FILE DESCRIPTION: Rate main
+
+ AUTHOR: Kildor
+ GROUP: The NULL workgroup
+ PROJECT: Contact`s rate
+ PART: Main
+ VERSION: 1.0
+ CREATED: 20.12.2006 23:11:41
+
+ EMAIL: kostia@ngs.ru
+ WWW: http://kildor.miranda.im
+
+ COPYRIGHT: (C) 2006 The NULL workgroup. All Rights Reserved.
+*/
+/*--------------------------------------------------------------------------*/
+/*
+ Copyright (C) 2006 The NULL workgroup
+
+ 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 ID: $Id$
+
+ CHANGE LOG:
+
+ $Log$
+*/
+#include "commonheaders.h"
+
+HINSTANCE g_hInst;
+PLUGINLINK *pluginLink;
+static HANDLE hHookModulesLoaded = NULL, hSystemOKToExit = NULL, hOptInitialise = NULL, hIcoLibIconsChanged = NULL;
+static HANDLE hHookExtraIconsRebuild = NULL, hHookExtraIconsApply = NULL, hContactSettingChanged = NULL;
+static HANDLE hPrebuildContactMenu = NULL;
+static HANDLE hExtraIcon = NULL;
+IconExtraColumn g_IECRateHigh = {0};
+IconExtraColumn g_IECRateMedium = {0};
+IconExtraColumn g_IECRateLow = {0};
+IconExtraColumn g_IECClear = {0};
+int clistIcon = 0; //Icon slot to use
+byte bRate = 0;
+
+extern int onOptInitialise(WPARAM wParam, LPARAM lParam);
+
+
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ "Contact`s Rate",
+ PLUGIN_MAKE_VERSION(0,0,2,1),
+ "Show rating of contact in contact list (if presents).",
+ "Kildor, Thief",
+ "kostia@ngs.ru",
+ " 2006-2009 Kostia Romanov, based on AuthState by Alexander Turyak",
+ "http://kildor.miranda.im/",
+ 0, // is not unicode
+ 0, //doesn't replace anything built-in
+ {0x45230488, 0x977b, 0x405b, {0x85, 0x6d, 0xea, 0x27, 0x6d, 0x70, 0x83, 0xb7}}
+/* 45230488-977b-405b-856d-ea276d7083b7 */
+
+};
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ g_hInst = hinstDLL;
+ return TRUE;
+}
+
+//
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ if (mirandaVersion < PLUGIN_MAKE_VERSION(0, 8, 0, 29))
+ {
+ MessageBox( NULL, TranslateT("The plugin requires Miranda IM 0.8.0.29 or later for correct applying its preferences."), TranslateT("Contact` Rate"),
+ MB_OK|MB_ICONWARNING|MB_SETFOREGROUND|MB_TOPMOST );
+ }
+
+ return &pluginInfo;
+}
+
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ static const MUUID interfaces[] = {MIID_CONTACTSRATE, MIID_LAST};
+ return interfaces;
+}
+
+int onSystemOKToExit(WPARAM wParam,LPARAM lParam)
+{
+ UnhookEvent(hHookModulesLoaded);
+ UnhookEvent(hHookExtraIconsRebuild);
+ UnhookEvent(hHookExtraIconsApply);
+ UnhookEvent(hOptInitialise);
+ UnhookEvent(hSystemOKToExit);
+ if (hIcoLibIconsChanged) UnhookEvent(hIcoLibIconsChanged);
+ if (hContactSettingChanged)
+ UnhookEvent(hContactSettingChanged);
+
+ return 0;
+}
+
+void setExtaIcon(HANDLE hContact, int bRate = -1, BOOL clear = TRUE)
+{
+ if (hContact == NULL)
+ return;
+
+ if (bRate < 0)
+ bRate = DBGetContactSettingByte(hContact, "CList", "Rate", 0);
+
+ if (hExtraIcon != NULL)
+ {
+ const char *icon;
+ switch(bRate)
+ {
+ case 3: icon = "rate_high"; break;
+ case 2: icon = "rate_medium"; break;
+ case 1: icon = "rate_low"; break;
+ default: icon = NULL; break;
+ }
+
+ if (icon == NULL && !clear)
+ return;
+
+ ExtraIcon_SetIcon(hExtraIcon, hContact, icon);
+ }
+ else
+ {
+ switch(bRate)
+ {
+ case 3: CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM) hContact, (LPARAM) &g_IECRateHigh); break;
+ case 2: CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM) hContact, (LPARAM) &g_IECRateMedium); break;
+ case 1: CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM) hContact, (LPARAM) &g_IECRateLow); break;
+ default: CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM) hContact, (LPARAM) &g_IECClear); break;
+ }
+ }
+}
+
+
+int onExtraImageApplying(WPARAM wParam, LPARAM lParam)
+{
+ setExtaIcon((HANDLE) wParam);
+ return 0;
+}
+
+
+int onExtraImageListRebuild(WPARAM wParam, LPARAM lParam)
+{
+ g_IECRateHigh.cbSize = sizeof(IconExtraColumn);
+ g_IECRateHigh.ColumnType = clistIcon;
+ g_IECRateMedium.cbSize = sizeof(IconExtraColumn);
+ g_IECRateMedium.ColumnType = clistIcon;
+ g_IECRateLow.cbSize = sizeof(IconExtraColumn);
+ g_IECRateLow.ColumnType = clistIcon;
+
+ if (ServiceExists(MS_CLIST_EXTRA_ADD_ICON))
+ {
+ g_IECRateHigh.hImage = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)(HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM)"rate_high"), (LPARAM)0);
+ g_IECRateMedium.hImage = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)(HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM)"rate_medium"), (LPARAM)0);
+ g_IECRateLow.hImage = (HANDLE)CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM)(HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM)"rate_low"), (LPARAM)0);
+ }
+ return 0;
+}
+
+
+static void init_icolib (void)
+{
+ SKINICONDESC sid = {0};
+ char szFile[MAX_PATH];
+ sid.cbSize = SKINICONDESC_SIZE_V1;
+ int i = 0;
+
+ sid.pszSection = Translate("Contact Rate");
+ GetModuleFileNameA(g_hInst, szFile, MAX_PATH);
+ sid.pszDefaultFile = szFile;
+
+ for ( i = 0; i < SIZEOF(iconList); i++ ) {
+ sid.pszName = iconList[i].szName;
+ sid.ptszDescription = iconList[i].szDescr;
+ sid.iDefaultIndex = -iconList[i].defIconID;
+ iconList[i].hIconLibItem = (HANDLE) CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+ }
+}
+
+
+int onModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ //IcoLib support
+ init_icolib();
+
+
+ // Updater support
+ // switch off
+ if ( ServiceExists(MS_UPDATE_REGISTER))
+ {
+ Update update = {0};
+ char szVersion[16];
+
+ update.cbSize = sizeof(Update);
+
+ update.szComponentName = pluginInfo.shortName;
+ update.pbVersion = (BYTE *)CreateVersionString(pluginInfo.version, szVersion);
+ update.cpbVersion = (int)strlen((char *)update.pbVersion);
+
+ update.szUpdateURL = UPDATER_AUTOREGISTER;
+
+ // these are the three lines that matter - the archive, the page containing the version string, and the text (or data)
+ // before the version that we use to locate it on the page
+ // (note that if the update URL and the version URL point to standard file listing entries, the backend xml
+ // data will be used to check for updates rather than the actual web page - this is not true for beta urls)
+ update.szBetaUpdateURL = "http://kildor.miranda.im/miranda/rate.zip";
+ update.szBetaVersionURL = "http://kildor.miranda.im/miranda/rate.txt";
+ update.szBetaChangelogURL = "http://kildor.miranda.im/miranda/rate_changes.txt";
+ update.pbBetaVersionPrefix = (BYTE *)"Rate ";
+ update.cpbBetaVersionPrefix = (int)strlen((char *)update.pbBetaVersionPrefix);
+
+ CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update);
+ }
+
+ // Extra icon support
+ hExtraIcon = ExtraIcon_Register("contact_rate", "Contact rate", "rate_high");
+
+ if (hExtraIcon != NULL)
+ {
+ // Set initial value for all contacts
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact != NULL)
+ {
+ setExtaIcon(hContact, -1, FALSE);
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+ }
+ else
+ {
+ hOptInitialise = HookEvent(ME_OPT_INITIALISE, onOptInitialise);
+ hIcoLibIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, onExtraImageListRebuild);
+ hHookExtraIconsRebuild = HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, onExtraImageListRebuild);
+ hHookExtraIconsApply = HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, onExtraImageApplying);
+ onExtraImageListRebuild(0,0);
+ }
+
+ return 0;
+}
+
+
+int onContactSettingChanged(WPARAM wParam,LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *cws=(DBCONTACTWRITESETTING*)lParam;
+
+ if (wParam != NULL && !lstrcmp(cws->szModule,"CList") && !lstrcmp(cws->szSetting,"Rate"))
+ setExtaIcon((HANDLE)wParam, cws->value.type == DBVT_DELETED ? 0 : cws->value.bVal);
+
+ return 0;
+}
+
+
+extern "C" int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ pluginLink=link;
+
+ hHookModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, onModulesLoaded);
+ hSystemOKToExit = HookEvent(ME_SYSTEM_OKTOEXIT,onSystemOKToExit);
+ hContactSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, onContactSettingChanged);
+
+ clistIcon = DBGetContactSettingByte(NULL, MODULENAME, "AdvancedIcon", DefaultSlot);
+
+ g_IECClear.cbSize = sizeof(IconExtraColumn);
+ g_IECClear.ColumnType = clistIcon;
+ g_IECClear.hImage = (HANDLE) -1;
+
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ return 0;
+}
diff --git a/plugins/Rate/options.cpp b/plugins/Rate/options.cpp
new file mode 100644
index 0000000000..47714d6828
--- /dev/null
+++ b/plugins/Rate/options.cpp
@@ -0,0 +1,224 @@
+/*
+ Authorization State plugin for Miranda-IM (www.miranda-im.org)
+ (c) 2006 by Thief
+ Icons by Faith Healer
+
+ 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 name : $URL: svn://svnsrv.mirandaim.ru/mainrepo/authstate/trunk/options.cpp $
+ Revision : $Rev: 233 $
+ Last change on : $Date: 2006-10-05 15:48:05 +0300 (Thu, 05 Oct 2006) $
+ Last change by : $Author: Thief $
+
+*/
+
+#include "commonheaders.h"
+
+extern HINSTANCE g_hInst;
+extern int onExtraImageApplying(WPARAM wParam, LPARAM lParam);
+extern int onExtraImageListRebuild(WPARAM wParam, LPARAM lParam);
+extern IconExtraColumn g_IECAuth, g_IECGrant, g_IECAuthGrant, g_IECClear;
+extern int clistIcon;
+//extern byte bUseAuthIcon, bUseGrantIcon, bContactMenuItem, bIconsForRecentContacts;
+
+//#define EXTRA_ICON_RES0 0 // only used by nicer
+//#define EXTRA_ICON_EMAIL 1
+//#define EXTRA_ICON_WEB 2
+//#define EXTRA_ICON_SMS 3
+//#define EXTRA_ICON_ADV1 4
+//#define EXTRA_ICON_ADV2 5
+//#define EXTRA_ICON_ADV3 6
+//#define EXTRA_ICON_CLIENT 7
+//#define EXTRA_ICON_ADV4 8
+//#define EXTRA_ICON_RES1 9 // only used by nicer
+//#define EXTRA_ICON_PROTO 9 // used by mwclist and modern
+//#define EXTRA_ICON_RES2 10 // only used by nicer
+//#define EXTRA_ICON_VISMODE 10 // only used by modern
+
+#define MS_SKINENG_DRAWICONEXFIX "SkinEngine/DrawIconEx_Fix"
+
+enum {
+ clist_none,
+ clist_modern,
+ clist_nicer
+};
+
+const char *szAdvancedIconsModern[] = {
+ "E-mail",
+ "Web page",
+ "Phone/SMS",
+ "Advanced #1",
+ "Advanced #2",
+ "Advanced #3",
+ "Client",
+ "Advanced #4",
+ "Protocol",
+ "Visibility/Chat activity"
+};
+//const int cAdvancedIconsModern = sizeof(szAdvancedIconsModern) / sizeof(szAdvancedIconsModern[0]);
+
+const char *szAdvancedIconsNicer[] = {
+ "Reserved",
+ "E-mail",
+ "Homepage",
+ "Telephone",
+ "Advanced #1",
+ "Advanced #2",
+ "Client",
+ "Advanced #3",
+ "Advanced #4",
+ "Reserved #1",
+ "Reserved #2"
+ };
+//const int cAdvancedIconsNicer = sizeof(szAdvancedIconsNicer) / sizeof(szAdvancedIconsNicer[0]);
+
+INT_PTR CALLBACK DlgProcOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static int bInitializing = 0;
+ static int usedClist = clist_none;
+ int cAdvancedIcons;
+// const char **szAdvancedIcons;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ bInitializing = 1;
+ if (ServiceExists(MS_CLIST_EXTRA_ADD_ICON))
+ {
+ if (ServiceExists(MS_SKINENG_DRAWICONEXFIX))
+ { // modern?
+// SendDlgItemMessage(hwndDlg,IDC_USED_CLIST, WM_SETTEXT,0,(LPARAM)_T("Your clist: modern"));
+ cAdvancedIcons = SIZEOF(szAdvancedIconsModern);
+ usedClist = clist_modern;
+ }
+ else
+ {
+ if (ServiceExists("CLN/About"))
+ {
+ usedClist = clist_nicer;
+// szAdvancedIcons = szAdvancedIconsNicer;
+ cAdvancedIcons = SIZEOF(szAdvancedIconsNicer);
+ SendDlgItemMessage(hwndDlg,IDC_USED_CLIST, WM_SETTEXT,0,(LPARAM)TranslateT("Your clist: nicer"));
+ }
+ else
+ {
+ usedClist = clist_modern;
+ cAdvancedIcons = SIZEOF(szAdvancedIconsModern) - 1; // mw doesn`t have last modern extraicon
+// SendDlgItemMessage(hwndDlg,IDC_USED_CLIST, WM_SETTEXT,0,(LPARAM)_T("Your clist: mw"));
+ }
+ SendDlgItemMessage(hwndDlg,IDC_NOTMODERN_WARNING, WM_SETTEXT,0,(LPARAM)TranslateT("Warning: your contact list plugin doesn`t have ability to sort contacts by rate."));
+ ShowWindow(GetDlgItem(hwndDlg, IDC_NOTMODERN_WARNING), SW_SHOW);
+ }
+ }
+ else
+ {
+ cAdvancedIcons = 0;
+// SendDlgItemMessage(hwndDlg,IDC_USED_CLIST, WM_SETTEXT,0,(LPARAM)_T("Your clist: classic"));
+ SendDlgItemMessage(hwndDlg,IDC_NOTMODERN_WARNING, WM_SETTEXT,0,(LPARAM)TranslateT("Warning: classic contact list plugin doesn`t have ability to use extraicons"));
+ ShowWindow(GetDlgItem(hwndDlg, IDC_NOTMODERN_WARNING), SW_SHOW);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADVICON), 0);
+ }
+// cAdvancedIcons = sizeof(szAdvancedIcons) / sizeof(szAdvancedIcons[0]);
+// cAdvancedIcons = SIZEOF(szAdvancedIcons);
+
+ if (usedClist != clist_none) {
+ for (int i = 0; i < cAdvancedIcons; i++)
+ {
+ SendMessage(GetDlgItem(hwndDlg, IDC_ADVICON), CB_ADDSTRING, 0, (LPARAM) Translate( usedClist==clist_modern ? szAdvancedIconsModern[i] : szAdvancedIconsNicer[i]));
+ }
+
+ if (usedClist == clist_modern )
+ SendMessage(GetDlgItem(hwndDlg, IDC_ADVICON), CB_SETCURSEL, clistIcon-1, 0);
+ else
+ SendMessage(GetDlgItem(hwndDlg, IDC_ADVICON), CB_SETCURSEL, clistIcon, 0);
+ }
+ bInitializing = 0;
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam)) {
+ case IDC_ADVICON:
+ {
+ if ((HIWORD(wParam) == EN_CHANGE) && (!bInitializing) || (HIWORD(wParam) == CBN_SELENDOK))
+ {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ if (((LPNMHDR)lParam)->idFrom == 0)
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ if (usedClist==clist_none)
+ return TRUE;
+
+ clistIcon = SendMessage(GetDlgItem(hwndDlg, IDC_ADVICON), CB_GETCURSEL, 0, 0);
+ if (usedClist == clist_modern )
+ clistIcon++;
+
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact)
+ {
+ CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM)hContact, (LPARAM)&g_IECClear);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ g_IECClear.ColumnType = clistIcon;
+ onExtraImageListRebuild(0,0);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact)
+ {
+ onExtraImageApplying((WPARAM)hContact,0);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ //Store options values to DB
+ DBWriteContactSettingByte(NULL, MODULENAME, "AdvancedIcon", clistIcon);
+ }
+ return TRUE;
+ }
+ }
+ }
+ case WM_DESTROY:
+ break;
+ }
+ return FALSE;
+}
+
+int onOptInitialise(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp;
+
+ ZeroMemory(&odp, sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.position = 0;
+ odp.hInstance = g_hInst;
+ odp.pszGroup = Translate("Contact List");
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_RATE_OPT);
+ odp.pszTitle = Translate("Rate");
+ odp.pfnDlgProc = DlgProcOptions;
+ odp.flags = ODPF_BOLDGROUPS;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM) &odp);
+
+ return 0;
+}
diff --git a/plugins/Rate/rate.rc b/plugins/Rate/rate.rc
new file mode 100644
index 0000000000..e1a75b6808
--- /dev/null
+++ b/plugins/Rate/rate.rc
@@ -0,0 +1,124 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Ukrainian resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_UKR)
+#ifdef _WIN32
+LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_RATEHI ICON "icons\\rate_high.ico"
+IDI_RATELO ICON "icons\\rate_low.ico"
+IDI_RATEME ICON "icons\\rate_med.ico"
+#endif // Ukrainian resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_RATE_OPT DIALOGEX 0, 0, 314, 240
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ COMBOBOX IDC_ADVICON,95,102,78,81,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP,WS_EX_CLIENTEDGE
+ GROUPBOX "Plugin settings",IDC_STATIC,46,46,222,118
+ RTEXT "Use",IDC_STATIC,56,104,33,12
+ LTEXT "slot to draw the icon",IDC_STATIC,179,104,76,17
+ LTEXT "Warning: classic contact list plugin doesn`t have ability to use extraicons",
+ IDC_NOTMODERN_WARNING,77,126,171,18,NOT WS_VISIBLE
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_RATE_OPT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 307
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 233
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/Rate/rate_10.sln b/plugins/Rate/rate_10.sln
new file mode 100644
index 0000000000..765fedbeef
--- /dev/null
+++ b/plugins/Rate/rate_10.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rate", "rate_10.vcxproj", "{DB315D7D-00BB-43B2-93A6-0430CA2B9F28}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DB315D7D-00BB-43B2-93A6-0430CA2B9F28}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DB315D7D-00BB-43B2-93A6-0430CA2B9F28}.Debug|Win32.Build.0 = Debug|Win32
+ {DB315D7D-00BB-43B2-93A6-0430CA2B9F28}.Debug|x64.ActiveCfg = Debug|x64
+ {DB315D7D-00BB-43B2-93A6-0430CA2B9F28}.Debug|x64.Build.0 = Debug|x64
+ {DB315D7D-00BB-43B2-93A6-0430CA2B9F28}.Release|Win32.ActiveCfg = Release|Win32
+ {DB315D7D-00BB-43B2-93A6-0430CA2B9F28}.Release|Win32.Build.0 = Release|Win32
+ {DB315D7D-00BB-43B2-93A6-0430CA2B9F28}.Release|x64.ActiveCfg = Release|x64
+ {DB315D7D-00BB-43B2-93A6-0430CA2B9F28}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/plugins/Rate/rate_10.vcxproj b/plugins/Rate/rate_10.vcxproj
new file mode 100644
index 0000000000..aa8e74a341
--- /dev/null
+++ b/plugins/Rate/rate_10.vcxproj
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{DB315D7D-00BB-43B2-93A6-0430CA2B9F28}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <ProjectName>rate</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalApi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;AUTHSTATE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <BaseAddress>0x22620000</BaseAddress>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalApi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;AUTHSTATE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <BaseAddress>0x22620000</BaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalApi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;AUTHSTATE_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ </ClCompile>
+ <Link>
+ <ShowProgress>NotSet</ShowProgress>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <BaseAddress>0x22620000</BaseAddress>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalApi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;AUTHSTATE_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ </ClCompile>
+ <Link>
+ <ShowProgress>NotSet</ShowProgress>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <BaseAddress>0x22620000</BaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="main.cpp" />
+ <ClCompile Include="options.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="commonheaders.h" />
+ <ClInclude Include="resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="rate.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="icons\rate_high.ico" />
+ <None Include="icons\rate_low.ico" />
+ <None Include="icons\rate_med.ico" />
+ <None Include="docs\Rate-readme.txt" />
+ <None Include="docs\rate.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Rate/rate_10.vcxproj.filters b/plugins/Rate/rate_10.vcxproj.filters
new file mode 100644
index 0000000000..53188635f5
--- /dev/null
+++ b/plugins/Rate/rate_10.vcxproj.filters
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx</Extensions>
+ </Filter>
+ <Filter Include="Docs">
+ <UniqueIdentifier>{629d9113-01ed-4da4-8f68-76e949ebdb7b}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="main.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="options.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="commonheaders.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="rate.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="icons\rate_high.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="icons\rate_low.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="icons\rate_med.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="docs\Rate-readme.txt">
+ <Filter>Docs</Filter>
+ </None>
+ <None Include="docs\rate.txt">
+ <Filter>Docs</Filter>
+ </None>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Rate/resource.h b/plugins/Rate/resource.h
new file mode 100644
index 0000000000..3b27728839
--- /dev/null
+++ b/plugins/Rate/resource.h
@@ -0,0 +1,22 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by rate.rc
+//
+#define IDD_RATE_OPT 9
+#define IDI_RATEHI 101
+#define IDI_RATEME 102
+#define IDI_RATELO 103
+#define IDC_ADVICON 1001
+#define IDC_NOTMODERN_WARNING 1010
+#define IDC_USED_CLIST 1011
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 104
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1013
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/TooltipNotify/doc/todo.txt b/plugins/TooltipNotify/doc/todo.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/plugins/TooltipNotify/doc/todo.txt
diff --git a/plugins/TooltipNotify/doc/tt_wnd_def_style.txt b/plugins/TooltipNotify/doc/tt_wnd_def_style.txt
new file mode 100644
index 0000000000..c47a6a363f
--- /dev/null
+++ b/plugins/TooltipNotify/doc/tt_wnd_def_style.txt
@@ -0,0 +1,9 @@
+ws_popup
+ws_visible
+ws_clipsiblings
+ws_border
+
+ws_ex_left
+ws_ex_ltrreading
+ws_ex_rightscrollbar
+ws_ex_topmost \ No newline at end of file
diff --git a/plugins/TooltipNotify/doc/ttnotify-readme.txt b/plugins/TooltipNotify/doc/ttnotify-readme.txt
new file mode 100644
index 0000000000..1d2e816390
--- /dev/null
+++ b/plugins/TooltipNotify/doc/ttnotify-readme.txt
@@ -0,0 +1,128 @@
+
+
+ Tooltip notify plugin for Miranda IM
+ ____________________________________
+
+ Version 0.6.0.45
+
+
+About
+_____
+
+This Miranda IM plugin popups a small tooltip above system tray area
+when a contact changes his status. It's intended for and tested with ICQ
+protocol mainly, so it can miswork with other protocols.
+
+
+
+Changelog
+_________
+
+Version 0.6.0.45
+ - Individual font settings for events
+
+Version 0.5.0.42
+ - Added idle notifications
+ - Using font services
+
+Version 0.4.0.36
+ - Fixed crash with too long contact names
+
+Version 0.4.0.32
+ - Next generation plugin interface support
+ - Correct unicode/ansi flag in plugin description
+
+Version 0.4.0.29
+ - per-contact notifications ability
+ - ansi/unicode module check on corresponding os
+ - more unicode support
+ - internal module name changed from 'ttntfmod' to 'Tooltip Notify'
+ (all settings migrate automatically)
+ - fixed potential crash while reading font settings
+ - fixed memory leak
+
+Version 0.3.0.15
+ - fixed one major unexpected crash
+
+Version 0.3.0.14
+ - unicode support
+ - fixed minor bug related to settings reading
+ - fixed potential crash with the tooltip moving
+ - other minor fixes
+
+Version 0.2.0.2
+ - obey 'suppress online notification' setting
+ - sound plays only if the event notification is checked
+ - minor stability fixes
+ - translation file update
+
+Version 0.2.0.1
+ - stability fixes
+
+Version 0.2.0.0
+ - some controls' text fields are enlarged (translators requests)
+ - win9x misworking fixed (not tested)
+ - new abilities:
+ - proto name prefixing
+ - enabled back
+ - work in conjunction with 'suppress online notification'
+
+Version 0.1.0.0
+ - the whole code rewritten in cpp
+ - new abilities:
+ - suppress notifications upon connect
+ - typing notification
+ - disabled
+ - work in conjunction with 'suppress online notification'
+
+Version 0.0.6.0
+ - rewritten code of the tooltip window
+ - tooltip dragging behavior changed (now with usual left-click)
+ - new options:
+ - double click on tooltip action
+ - font and color customization
+ - some minor fixes/changes
+
+Version 0.0.5.0
+ - sound support for the contact events
+ - added a button to run the tooltip within the options dialog to test it
+ - some minor changes
+
+Version 0.0.4.3
+ - protocols selection bug fixed
+
+Version 0.0.4.2
+ - translucency options
+ - translation support
+
+Version 0.0.4.0
+ - ability to select protocols to react to
+ - ability of custom tooltip placement
+
+Version 0.0.3.1
+ - a little translations added
+
+Version 0.0.3.0
+ - options moved to events->tooltip notify
+ - options added:
+ - allow tooltip duration adjusting
+ - conjunctive work with 'Suppress online notification'
+ - fixed showing a tooltip when protocol goes offline
+ - plugin size reduced
+
+Version 0.0.2.4
+ - some internal fixes
+
+
+Copyright
+_________
+
+Copyright (C) 2004-2008 Gneedah software (perf@mail333.com)
+
+
+
+DISCLAIMER OF WARRANTY
+--------------------------------------------------------------------
+
+This software is distributed "AS IS" without any warranties.
+USE IT AT YOU OWN RISK.
diff --git a/plugins/TooltipNotify/doc/ttnotify_translation.txt b/plugins/TooltipNotify/doc/ttnotify_translation.txt
new file mode 100644
index 0000000000..2c7d965d67
--- /dev/null
+++ b/plugins/TooltipNotify/doc/ttnotify_translation.txt
@@ -0,0 +1,47 @@
+; This is a template for Tooltip Notify translation.
+
+
+; ******** Plugin info ********
+;[Tooltip Notify]
+;[Shows a small tooltip above system tray area when a contact status is changed]
+
+
+; ******** Options and tooltip text ********
+
+;[Notify upon the following contact status changes]
+;[Online]
+;[Offline]
+;[Away]
+;[N/A]
+;[Occupied]
+;[DND]
+;[Free for chat]
+;[Invisible]
+;[All other]
+;[Unknown]
+;[Typing]
+;[Idle]
+;[Suppress notifications upon connection for]
+;[sec]
+;[Prefix proto name]
+;[Protocols]
+;[is]
+
+;[Duration]
+;[Show tooltip for]
+;[ms]
+;[Duration x2 upon online event]
+
+;[Double click on tooltip]
+;[Shows/Hides CList]
+;[Opens message dialog]
+
+;[Misc]
+;[Obey 'Suppress online notification' settings]
+;[Auto positioning]
+;[Transparent input]
+
+;[Preview]
+
+;[Translucency options (Windows 2000/XP only)]
+;[Transparent tooltip]
diff --git a/plugins/TooltipNotify/src/DbHelpers.cpp b/plugins/TooltipNotify/src/DbHelpers.cpp
new file mode 100644
index 0000000000..930206486d
--- /dev/null
+++ b/plugins/TooltipNotify/src/DbHelpers.cpp
@@ -0,0 +1,120 @@
+// DbHelpers.cpp
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "DbHelpers.h"
+
+typedef std::vector<const char*> SettingsList;
+
+static int EnumSettingsProc1(const char *pszSetting, LPARAM lParam)
+{
+ return 0;
+}
+
+bool ModuleSettingsExists(HANDLE hContact, const char* pszModuleName)
+{
+ DBCONTACTENUMSETTINGS dbces = {0};
+ dbces.szModule = pszModuleName;
+ dbces.pfnEnumProc = EnumSettingsProc1;
+
+ int nResult = ::CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)hContact, (LPARAM)&dbces);
+ return (nResult != -1);
+}
+
+static int EnumSettingsProc2(const char *pszSetting, LPARAM lParam)
+{
+ SettingsList& settingsList = *((SettingsList*)lParam);
+ settingsList.push_back(_strdup(pszSetting));
+ return 0;
+}
+
+void DeleteModuleSettings(HANDLE hContact, const char* pszModuleName)
+{
+ SettingsList settingsList;
+ DBCONTACTENUMSETTINGS dbces = {0};
+ dbces.szModule = pszModuleName;
+ dbces.lParam = (LPARAM)&settingsList;
+ dbces.pfnEnumProc = EnumSettingsProc2;
+
+ int nResult = ::CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)hContact, (LPARAM)&dbces);
+ if (nResult != -1)
+ {
+ for(unsigned i=0; i<settingsList.size(); i++)
+ {
+ DBDeleteContactSetting(hContact, pszModuleName, settingsList[i]);
+ free((char*)settingsList[i]);
+ }
+ }
+}
+
+
+static int GetSetting(HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv)
+{
+ DBCONTACTGETSETTING cgs;
+
+ cgs.szModule=szModule;
+ cgs.szSetting=szSetting;
+ cgs.pValue=dbv;
+ dbv->type = 0;
+
+ int rr = CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs);
+
+ if (dbv->type != DBVT_UTF8)
+ return rr;
+ else
+ return 1;
+}
+
+void RenameModule(HANDLE hContact, const char* pszOldName, const char* pszNewName)
+{
+ SettingsList settingsList;
+ DBCONTACTENUMSETTINGS dbces = {0};
+ dbces.szModule = pszOldName;
+ dbces.lParam = (LPARAM)&settingsList;
+ dbces.pfnEnumProc = EnumSettingsProc2;
+
+ int nResult = ::CallService(MS_DB_CONTACT_ENUMSETTINGS, (WPARAM)hContact, (LPARAM)&dbces);
+ if (nResult != -1)
+ {
+ DBVARIANT dbv;
+
+ for(unsigned i=0; i<settingsList.size(); i++)
+ {
+ const char* pszSetting = settingsList[i];
+
+ if (!GetSetting(hContact, pszOldName, pszSetting, &dbv))
+ {
+ switch (dbv.type)
+ {
+ case DBVT_BYTE:
+ DBWriteContactSettingByte(hContact, pszNewName, pszSetting, dbv.bVal);
+ break;
+
+ case DBVT_WORD:
+ DBWriteContactSettingWord(hContact, pszNewName, pszSetting, dbv.wVal);
+ break;
+
+ case DBVT_DWORD:
+ DBWriteContactSettingDword(hContact, pszNewName, pszSetting, dbv.dVal);
+ break;
+
+ case DBVT_ASCIIZ:
+ DBWriteContactSettingString(hContact, pszNewName, pszSetting, dbv.pszVal);
+ break;
+
+ case DBVT_UTF8:
+ DBWriteContactSettingStringUtf(hContact, pszNewName, pszSetting, dbv.pszVal);
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+ DBDeleteContactSetting(hContact, pszOldName, pszSetting);
+ DBFreeVariant(&dbv);
+ }
+ free((char*)settingsList[i]);
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/TooltipNotify/src/DbHelpers.h b/plugins/TooltipNotify/src/DbHelpers.h
new file mode 100644
index 0000000000..aea3c9a9b2
--- /dev/null
+++ b/plugins/TooltipNotify/src/DbHelpers.h
@@ -0,0 +1,9 @@
+// DbHelpers.h
+//
+//////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+bool ModuleSettingsExists(HANDLE hContact, const char* pszModuleName);
+void DeleteModuleSettings(HANDLE hContact, const char* pszModuleName);
+void RenameModule(HANDLE hContact, const char* pszOldName, const char* pszNewName);
diff --git a/plugins/TooltipNotify/src/Settings.h b/plugins/TooltipNotify/src/Settings.h
new file mode 100644
index 0000000000..ce705ef514
--- /dev/null
+++ b/plugins/TooltipNotify/src/Settings.h
@@ -0,0 +1,42 @@
+//
+// Settings.h
+//
+
+#pragma once
+
+// Settings related
+#define DEF_LOGPIXELSY 96
+#define PROTO_TT_ON_INT_BIT 0x01
+#define PROTO_TT_ON_USER_BIT 0x02
+#define SHOW_HIDE_CLIST 1
+#define OPEN_MSGDLG 2
+
+// Default settings
+#define DEF_SETTING_FIRSTRUN 1 //
+#define DEF_SETTING_DURATION 550*6 // tooltip showing duration
+#define DEF_SETTING_ONLINE 1 // 1: On, 0: Off
+#define DEF_SETTING_OFFLINE 1 // 1: On, 0: Off
+#define DEF_SETTING_OTHER 0 // 1: On, 0: Off
+#define DEF_SETTING_TYPING 0 // 1: On, 0: Off
+#define DEF_SETTING_X2 1 // 1: On, 0: Off
+#define DEF_SETTING_CONJSOLN 0 // 1: On, 0: Off
+#define DEF_SETTING_BALLONTIP 0 // 1: On, 0: Off
+#define DEF_SETTING_DEF_POS 1 // 1: On, 0: Off
+#define DEF_SETTING_DEF_XPOS 600 //
+#define DEF_SETTING_DEF_YPOS 500 //
+#define DEF_SETTING_TRANSP 0
+#define DEF_SETTING_ALPHA 255
+#define DEF_SETTING_TRANSP_INPUT 0
+#define DEF_SETTING_PREFIX_PROTO 0
+#define DEF_SETTING_LDBLCLICK SHOW_HIDE_CLIST
+#define DEF_SETTING_BGCOLOR GetSysColor(COLOR_INFOBK)
+#define DEF_SETTING_TXTCOLOR GetSysColor(COLOR_INFOTEXT)
+#define DEF_SETTING_FONT_FACE _T("Tahoma")
+#define DEF_SETTING_FONT_SIZE 8
+#define DEF_SETTING_FONT_STYLE 0
+#define DEF_SETTING_FONT_CHARSET DEFAULT_CHARSET
+#define DEF_SETTING_STARTUP_DELAY 10
+#define DEF_SETTING_IGNORE_UNKNOWN FALSE
+#define DEF_SETTING_IGNORE_NEW FALSE
+
+
diff --git a/plugins/TooltipNotify/src/Tooltip.cpp b/plugins/TooltipNotify/src/Tooltip.cpp
new file mode 100644
index 0000000000..5373e68f4c
--- /dev/null
+++ b/plugins/TooltipNotify/src/Tooltip.cpp
@@ -0,0 +1,219 @@
+// Tooltip.cpp: implementation of the CTooltip class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "Tooltip.h"
+#include "Settings.h"
+#include "TooltipNotify.h"
+
+/*static*/ const TCHAR *CTooltip::s_szTooltipClass = _T("MimTooltipNotify");
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CTooltip::CTooltip(CTooltipNotify *pTooltipNotify)
+{
+ m_pTooltipNotify = pTooltipNotify;
+ m_bLDblClick = DEF_SETTING_LDBLCLICK;
+ m_hFont = 0;
+ m_hWnd = 0;
+ m_szText = 0;
+
+ m_hWnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST, s_szTooltipClass, 0,
+ WS_POPUP|WS_BORDER, 100, 100, 50, 50, 0, 0,
+ m_pTooltipNotify->GetDllInstance(), NULL);
+
+ SetWindowLong(m_hWnd, GWL_USERDATA, reinterpret_cast<LONG>(this));
+}
+
+
+CTooltip::~CTooltip()
+{
+ if (m_hWnd) DestroyWindow(m_hWnd);
+ if (m_hFont) DeleteObject(m_hFont);
+
+ if (m_szText) free(m_szText);
+}
+
+/*static*/ void CTooltip::Initialize(HMODULE hInstance)
+{
+ WNDCLASSEX wcexWndClass;
+ wcexWndClass.cbSize = sizeof(WNDCLASSEX);
+ wcexWndClass.style = CS_SAVEBITS;
+ wcexWndClass.lpfnWndProc = (WNDPROC)CTooltip::WindowProcWrapper;
+ wcexWndClass.cbClsExtra = 0;
+ wcexWndClass.cbWndExtra = 0;
+ wcexWndClass.hInstance = hInstance;
+ wcexWndClass.hIcon = 0;
+ wcexWndClass.hCursor = 0;
+ wcexWndClass.hbrBackground = 0;
+ wcexWndClass.lpszMenuName = 0;
+ wcexWndClass.lpszClassName = s_szTooltipClass;
+ wcexWndClass.hIconSm = 0;
+ RegisterClassEx(&wcexWndClass);
+}
+
+/*static*/ void CTooltip::Deinitialize(HMODULE hInstance)
+{
+ UnregisterClass(s_szTooltipClass, hInstance);
+}
+
+LRESULT CALLBACK CTooltip::WindowProcWrapper(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ CTooltip* pThis = reinterpret_cast<CTooltip *>(GetWindowLong(hWnd, GWL_USERDATA));
+ return pThis->WindowProc(hWnd, message, wParam, lParam);
+}
+
+
+
+LRESULT CALLBACK CTooltip::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_CREATE:
+ break;
+
+ case WM_COMMAND:
+ break;
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ HDC hDC = BeginPaint(hWnd, &ps);
+
+ RECT rect;
+ GetClientRect(hWnd, &rect);
+
+ rect.top += 1;
+ rect.left += 1;
+ rect.right -= 1;
+ rect.bottom -= 1;
+
+ SetBkMode(hDC, TRANSPARENT);
+ SetTextColor(hDC, m_dwTextColor);
+ SelectObject(hDC, m_hFont);
+ DrawText(hDC, m_szText, lstrlen(m_szText), &rect, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
+
+ EndPaint(hWnd, &ps);
+
+ break;
+ }
+
+ case WM_ERASEBKGND:
+ {
+ RECT rect;
+ GetClientRect(hWnd, &rect);
+ HBRUSH hBgBrush = CreateSolidBrush(m_dwBgColor);
+ FillRect((HDC)wParam, &rect, hBgBrush);
+ DeleteObject(hBgBrush);
+
+ return TRUE;
+ }
+
+ case WM_NCHITTEST:
+ {
+ UINT uHitTest = DefWindowProc(hWnd, message, wParam, lParam);
+ if(uHitTest == HTCLIENT)
+ return HTCAPTION;
+ else
+ return uHitTest;
+ }
+
+ case WM_NCLBUTTONDBLCLK:
+ {
+ m_pTooltipNotify->OnTooltipDblClicked(this);
+ break;
+ }
+
+ case WM_SYSCOMMAND:
+ {
+ if (!m_pTooltipNotify->OnTooltipBeginMove(this))
+ break;
+
+ // doesn't return until the moving is complete
+ DefWindowProc(hWnd, message, wParam, lParam);
+ // DefWindowProc returned
+ m_pTooltipNotify->OnTooltipEndMove(this);
+
+ break;
+ }
+
+ case WM_DESTROY:
+ break;
+
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+ return 0;
+
+}
+
+
+VOID CTooltip::Validate()
+{
+ m_hFont = CreateFontIndirect(&m_lfFont);
+ SIZE Size;
+ HDC hDC = GetDC(m_hWnd);
+ SelectObject(hDC, m_hFont);
+ GetTextExtentPoint32(hDC, m_szText, lstrlen(m_szText), &Size);
+ SetWindowPos(m_hWnd, 0, 0, 0, Size.cx+6, Size.cy+4,
+ SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOREDRAW);
+ ReleaseDC(m_hWnd, hDC);
+}
+
+
+VOID CTooltip::Show()
+{
+ ShowWindow(m_hWnd, SW_SHOWNOACTIVATE);
+}
+
+
+VOID CTooltip::Hide()
+{
+ ShowWindow(m_hWnd, SW_HIDE);
+}
+
+
+
+VOID CTooltip::set_Translucency(BYTE bAlpha)
+{
+ typedef BOOL (WINAPI *pfnSetLayeredWindowAttributes_t)(HWND, COLORREF, BYTE, DWORD);
+ pfnSetLayeredWindowAttributes_t pfnSetLayeredWindowAttributes;
+
+ pfnSetLayeredWindowAttributes = reinterpret_cast<pfnSetLayeredWindowAttributes_t>
+ (GetProcAddress(GetModuleHandle(_T("user32.dll")), "SetLayeredWindowAttributes"));
+
+ if (pfnSetLayeredWindowAttributes &&
+ SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED) != 0)
+ {
+ pfnSetLayeredWindowAttributes(m_hWnd, RGB(0,0,0), bAlpha, LWA_ALPHA);
+ }
+}
+
+VOID CTooltip::set_TransparentInput(BOOL bOnOff)
+{
+ if (bOnOff)
+ SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) | WS_EX_TRANSPARENT);
+ else
+ SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) & ~WS_EX_TRANSPARENT);
+}
+
+
+VOID CTooltip::get_Rect(RECT *Rect) const
+{
+ GetWindowRect(m_hWnd, Rect);
+}
+
+VOID CTooltip::set_Position(INT x, INT y)
+{
+ SetWindowPos(m_hWnd, 0, x, y, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
+}
+
+VOID CTooltip::set_Text(const TCHAR* szText)
+{
+ if (m_szText) free(m_szText);
+ m_szText = _tcsdup(szText);
+}
+
diff --git a/plugins/TooltipNotify/src/Tooltip.h b/plugins/TooltipNotify/src/Tooltip.h
new file mode 100644
index 0000000000..fc97348370
--- /dev/null
+++ b/plugins/TooltipNotify/src/Tooltip.h
@@ -0,0 +1,55 @@
+// Tooltip.h: interface for the CTooltip class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class CTooltipNotify;
+
+class CTooltip
+{
+public:
+
+ CTooltip(CTooltipNotify *pTooltipNotify);
+ virtual ~CTooltip();
+
+ HWND GetHandle() const { return m_hWnd; }
+ VOID Hide();
+ VOID Show();
+ VOID Validate();
+ VOID set_Position(INT x, INT y);
+ VOID get_Rect(RECT *Rect) const;
+ VOID set_TransparentInput(BOOL bOnOff);
+ VOID set_Translucency(BYTE bAlpha);
+ VOID set_Text(const TCHAR* szText);
+ VOID set_Font(const LOGFONT& Font) { m_lfFont = Font; }
+ VOID set_TextColor(DWORD TextColor) { m_dwTextColor = TextColor; }
+ VOID set_BgColor(DWORD BgColor) { m_dwBgColor = BgColor; }
+
+ static void Initialize(HMODULE hInstance);
+ static void Deinitialize(HMODULE hInstance);
+
+private:
+ // prohibit copying
+ CTooltip(const CTooltip& rhs);
+ CTooltip& operator= (const CTooltip& rhs);
+
+private:
+ static LRESULT CALLBACK WindowProcWrapper(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+ LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+ HWND m_hWnd;
+ HFONT m_hFont;
+
+ // tooltip parameters
+ DWORD m_dwTextColor;
+ DWORD m_dwBgColor;
+ LOGFONT m_lfFont;
+ TCHAR *m_szText;
+ BYTE m_bAlpha;
+ BOOL m_bTranspInput;
+ BYTE m_bLDblClick;
+
+ CTooltipNotify *m_pTooltipNotify;
+ static const TCHAR *s_szTooltipClass;
+};
diff --git a/plugins/TooltipNotify/src/TooltipNotify.cpp b/plugins/TooltipNotify/src/TooltipNotify.cpp
new file mode 100644
index 0000000000..ac480dc1e6
--- /dev/null
+++ b/plugins/TooltipNotify/src/TooltipNotify.cpp
@@ -0,0 +1,1114 @@
+// TooltipNotify.cpp: implementation of the CTooltipNotify class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "resource.h"
+#include "TooltipNotify.h"
+#include "Tooltip.h"
+#include "Settings.h"
+#include "DbHelpers.h"
+#include "Utils.h"
+
+#define ReadSettingByte(c, d) DBGetContactSettingByte(NULL, s_szModuleName, c, d)
+#define ReadSettingWord(c, d) DBGetContactSettingWord(NULL, s_szModuleName, c, d)
+#define ReadSettingDword(c, d) DBGetContactSettingDword(NULL, s_szModuleName, c, d)
+#define ReadSettingString(c, d) DBGetContactSettingTString(NULL, s_szModuleName, c, d)
+
+#define WriteSettingByte(c, d) DBWriteContactSettingByte(NULL, s_szModuleName, c, d)
+#define WriteSettingWord(c, d) DBWriteContactSettingWord(NULL, s_szModuleName, c, d)
+#define WriteSettingDword(c, d) DBWriteContactSettingDword(NULL, s_szModuleName, c, d)
+#define WriteSettingString(c, d) DBWriteContactSettingTString(NULL, s_szModuleName, c, d)
+
+enum
+{
+ ProtoIntBit = 0x01,
+ ProtoUserBit = 0x02
+};
+
+static const char* SND_ONLINE = "ttntfOnline";
+static const char* SND_OFFLINE = "ttntfOffline";
+static const char* SND_OTHER = "ttntfOther";
+static const char* SND_TYPING = "ttntfTyping";
+static const char* CONTACT_IGNORE_TTNOTIFY = "Ignore";
+
+static const int ID_TTNTF_STATUS_TYPING = ID_STATUS_INVISIBLE+10;
+static const int ID_TTNTF_STATUS_IDLE = ID_STATUS_INVISIBLE+11;
+static const int ID_TTNTF_STATUS_NOT_IDLE = ID_STATUS_INVISIBLE+12;
+
+#define FONTSERV_GROUP _T("Tooltip Notify")
+#define FONTSERV_ONLINE _T("Online")
+#define FONTSERV_OFFLINE _T("Offline")
+#define FONTSERV_OTHER _T("Other Status")
+#define FONTSERV_TYPING _T("Typing")
+#define FONTSERV_IDLE _T("Idle")
+
+struct FontEntry
+{
+ int status;
+ TCHAR* name;
+ char* fontPrefix;
+ char* clrPrefix;
+};
+
+static FontEntry s_fontTable[] =
+{
+ ID_STATUS_ONLINE, FONTSERV_ONLINE, "OnlineFont", "OnlineBgColor",
+ ID_STATUS_OFFLINE, FONTSERV_OFFLINE, "OfflineFont", "OfflineBgColor",
+ ID_TTNTF_STATUS_TYPING, FONTSERV_TYPING, "TypingFont", "TypingBgColor",
+ ID_TTNTF_STATUS_IDLE, FONTSERV_IDLE, "IdleFont", "IdleBgColor",
+ ID_TTNTF_STATUS_NOT_IDLE, FONTSERV_IDLE, "IdleFont", "IdleBgColor",
+ 0, FONTSERV_OTHER, "OtherFont", "OtherBgColor",
+};
+
+/*static*/ CTooltipNotify *CTooltipNotify::s_pInstance = 0;
+/*static*/ const char *CTooltipNotify::s_szModuleNameOld = "ttntfmod";
+/*static*/ const char *CTooltipNotify::s_szModuleName = "TooltipNotify";
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CTooltipNotify::CTooltipNotify(HINSTANCE hinstDLL) :
+ m_hDllInstance(hinstDLL), m_bNt50(IsNt50())
+{
+ if (s_pInstance!=0)
+ throw EAlreadyExists();
+
+ s_pInstance = this;
+
+ CTooltip::Initialize(m_hDllInstance);
+}
+
+CTooltipNotify::~CTooltipNotify()
+{
+ EndNotifyAll();
+ CTooltip::Deinitialize(m_hDllInstance);
+ s_pInstance=0;
+}
+
+void CTooltipNotify::RegisterFonts()
+{
+ FontIDT fontId = {0};
+ fontId.cbSize = sizeof(fontId);
+ _tcscpy(fontId.group, FONTSERV_GROUP);
+ strcpy(fontId.dbSettingsGroup, s_szModuleName);
+ fontId.flags = FIDF_DEFAULTVALID;
+ fontId.deffontsettings.colour = DEF_SETTING_TXTCOLOR;
+ fontId.deffontsettings.size = -MulDiv(DEF_SETTING_FONT_SIZE, DEF_LOGPIXELSY, 72);
+ fontId.deffontsettings.style = DEF_SETTING_FONT_STYLE;
+ fontId.deffontsettings.charset = DEF_SETTING_FONT_CHARSET;
+ _tcscpy(fontId.deffontsettings.szFace, DEF_SETTING_FONT_FACE);
+ fontId.order = 0;
+ _tcscpy(fontId.backgroundGroup, FONTSERV_GROUP);
+
+ ColourIDT colorId = {0};
+ colorId.cbSize = sizeof(colorId);
+ _tcscpy(colorId.group, FONTSERV_GROUP);
+ strcpy(colorId.dbSettingsGroup, s_szModuleName);
+ colorId.flags = 0;
+ colorId.defcolour = DEF_SETTING_BGCOLOR;
+ colorId.order = 0;
+
+ for (int i=0; i<ARRAY_SIZE(s_fontTable); i++)
+ {
+ _tcscpy(fontId.name, s_fontTable[i].name);
+ strcpy(fontId.prefix, s_fontTable[i].fontPrefix);
+ _tcscpy(fontId.backgroundName, s_fontTable[i].name);
+ ::CallService(MS_FONT_REGISTERT, (WPARAM)&fontId, 0);
+
+ _tcscpy(colorId.name, s_fontTable[i].name);
+ strcpy(colorId.setting, s_fontTable[i].clrPrefix);
+ ::CallService(MS_COLOUR_REGISTERT, (WPARAM)&colorId, 0);
+ }
+}
+
+void CTooltipNotify::GetFont(int iStatus, LOGFONT* lf, COLORREF* text, COLORREF* bg)
+{
+ TCHAR* fontName = 0;
+ for(int i=0; i<ARRAY_SIZE(s_fontTable); i++)
+ {
+ if (s_fontTable[i].status == iStatus)
+ {
+ fontName = s_fontTable[i].name;
+ }
+ }
+ if (fontName == 0)
+ {
+ fontName = s_fontTable[ARRAY_SIZE(s_fontTable)-1].name;
+ }
+
+ // name and group only
+ FontIDT fontId = { sizeof(fontId), FONTSERV_GROUP, 0 };
+ _tcscpy(fontId.name, fontName);
+ *text = (COLORREF)::CallService(MS_FONT_GETT, (WPARAM)&fontId, (LPARAM)lf);
+ ColourIDT colorId = { sizeof(colorId), FONTSERV_GROUP, 0 };
+ _tcscpy(colorId.name, fontName);
+ *bg = (COLORREF)::CallService(MS_COLOUR_GETT, (WPARAM)&colorId, 0);
+}
+
+int CTooltipNotify::ModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ MigrateSettings();
+ LoadSettings();
+ ValidateSettings();
+
+ if (m_sOptions.bFirstRun)
+ {
+ DBWriteContactSettingByte(NULL, "SkinSoundsOff", SND_ONLINE, 1);
+ DBWriteContactSettingByte(NULL, "SkinSoundsOff", SND_OFFLINE, 1);
+ DBWriteContactSettingByte(NULL, "SkinSoundsOff", SND_OTHER, 1);
+ DBWriteContactSettingByte(NULL, "SkinSoundsOff", SND_TYPING, 1);
+ WriteSettingByte("firstrun", 0);
+ }
+
+ SkinAddNewSound(SND_ONLINE, "Tooltip Notify: Online", "online.wav");
+ SkinAddNewSound(SND_OFFLINE, "Tooltip Notify: Offline", "offline.wav");
+ SkinAddNewSound(SND_OTHER, "Tooltip Notify: Other", "other.wav");
+ SkinAddNewSound(SND_TYPING, "Tooltip Notify: Typing", "typing.wav");
+
+ RegisterFonts();
+
+ return 0;
+}
+
+
+int CTooltipNotify::ProtoContactIsTyping(WPARAM wParam, LPARAM lParam)
+{
+ if (!m_sOptions.bTyping) return 0;
+
+ if (lParam>0)
+ {
+ STooltipData *pTooltipData = new STooltipData;
+ pTooltipData->uiTimeout = lParam*1000;
+ pTooltipData->hContact = (HANDLE)wParam;
+ pTooltipData->iStatus = ID_TTNTF_STATUS_TYPING;
+
+ EndNotifyAll();
+ SkinPlaySound(SND_TYPING);
+ BeginNotify(pTooltipData);
+ }
+ else
+ {
+ EndNotifyAll();
+ }
+
+ return 0;
+}
+
+
+int CTooltipNotify::ProtoAck(WPARAM wParam, LPARAM lParam)
+{
+ ACKDATA *ack=(ACKDATA*)lParam;
+ if(ack->type != ACKTYPE_STATUS) return 0;
+
+ WORD wNewStatus = (WORD)ack->lParam;
+ WORD wOldStatus = (WORD)ack->hProcess;
+ if (wOldStatus == wNewStatus) return 0; //Useless message.
+
+ char *szProtocol = (char *)ack->szModule;
+
+ if (wNewStatus == ID_STATUS_OFFLINE)
+ {
+ BYTE bProtoActive = ReadSettingByte(szProtocol, ProtoUserBit|ProtoIntBit);
+ bProtoActive &= ~ProtoIntBit;
+ WriteSettingByte(szProtocol, bProtoActive);
+ }
+ else
+ {
+ if (wOldStatus < ID_STATUS_ONLINE && wNewStatus > ID_STATUS_OFFLINE)
+ {
+ UINT_PTR idTimer = SetTimer(0, 0, m_sOptions.wStartupDelay*1000, ConnectionTimerProcWrapper);
+ ProtoData protoData = { _strdup(szProtocol), idTimer };
+ m_mapTimerIdProto.push_back(protoData);
+ }
+ }
+
+ return 0;
+}
+
+int CTooltipNotify::ContactSettingChanged(WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam;
+ HANDLE hContact = (HANDLE)wParam;
+ if(hContact==NULL) return 0;
+
+ bool idle = false;
+ if (lstrcmpA(cws->szSetting,"Status")==0)
+ idle = false;
+ else if (lstrcmpA(cws->szSetting,"IdleTS")==0)
+ idle = true;
+ else return 0;
+
+ if(DBGetContactSettingByte(hContact, "CList", "Hidden", 0)) return 0;
+
+ const char *pszProto = cws->szModule;
+ if (ReadSettingByte(pszProto, ProtoUserBit|ProtoIntBit) != (ProtoUserBit|ProtoIntBit))
+ {
+ return 0;
+ }
+
+ if (DBGetContactSettingByte(hContact, "CList", "NotOnList", 0) && m_sOptions.bIgnoreUnknown)
+ {
+ return 0;
+ }
+
+ if (DBGetContactSettingByte(hContact, s_szModuleName, CONTACT_IGNORE_TTNOTIFY, m_sOptions.bIgnoreNew))
+ {
+ return 0;
+ }
+
+ if (idle && !m_sOptions.bIdle) return 0;
+
+ WORD wNewStatus = cws->value.wVal;
+ switch(wNewStatus)
+ {
+ case ID_STATUS_OFFLINE:
+ if (!m_sOptions.bOffline) return 0;
+ SkinPlaySound(SND_OFFLINE);
+ break;
+
+ case ID_STATUS_ONLINE:
+ if(CallService(MS_IGNORE_ISIGNORED,(WPARAM)hContact,IGNOREEVENT_USERONLINE) && m_sOptions.bConjSOLN) return 0;
+ if (!m_sOptions.bOnline) return 0;
+ SkinPlaySound(SND_ONLINE);
+ break;
+
+ default:
+ if (!m_sOptions.bOther) return 0;
+ SkinPlaySound(SND_OTHER);
+ break;
+ }
+
+ STooltipData *pTooltipData = new STooltipData;
+ pTooltipData->uiTimeout = m_sOptions.wDuration * (wNewStatus==ID_STATUS_ONLINE ? (m_sOptions.bX2+1):1);
+ pTooltipData->hContact = hContact;
+
+ if (idle) wNewStatus = (wNewStatus!=0 ? ID_TTNTF_STATUS_IDLE : ID_TTNTF_STATUS_NOT_IDLE);
+ pTooltipData->iStatus = wNewStatus;
+
+ EndNotifyAll();
+ BeginNotify(pTooltipData);
+
+ return 0;
+
+}
+
+int CTooltipNotify::InitializeOptions(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp;
+
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.position = 100000000;
+ odp.hInstance = m_hDllInstance;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS);
+ odp.ptszTitle = TranslateT("Tooltip Notify");
+ odp.ptszGroup = TranslateT("Appearance");
+ odp.groupPosition = 910000000;
+ odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
+ odp.pfnDlgProc = CTooltipNotify::OptionsDlgProcWrapper;
+ ::CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp);
+
+ return 0;
+}
+
+CTooltip *CTooltipNotify::BeginNotify(STooltipData *pTooltipData)
+{
+ TCHAR szTooltipText[64] = {0};
+ MakeTooltipString(pTooltipData->hContact, pTooltipData->iStatus, szTooltipText, 64);
+
+ LOGFONT lf = {0};
+ COLORREF textColor = 0;
+ COLORREF bgColor = 0;
+ GetFont(pTooltipData->iStatus, &lf, &textColor, &bgColor);
+
+ CTooltip *pTooltip = new CTooltip(this);
+ pTooltip->set_Text(szTooltipText);
+ pTooltip->set_Font(lf);
+ pTooltip->set_BgColor(bgColor);
+ pTooltip->set_TextColor(textColor);
+ if (m_bNt50 && m_sOptions.bTransp)
+ pTooltip->set_Translucency(m_sOptions.bAlpha);
+ pTooltip->set_TransparentInput(m_bNt50 && m_sOptions.bTransp && m_sOptions.bTranspInput);
+ pTooltip->Validate();
+
+ RECT TooltipRect, WorkAreaRect;
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &WorkAreaRect, 0);
+ pTooltip->get_Rect(&TooltipRect);
+
+ int tt_width = TooltipRect.right-TooltipRect.left;
+ int tt_height = TooltipRect.bottom-TooltipRect.top;
+
+ if (m_sOptions.bAutoPos ||
+ m_sOptions.wXPos > WorkAreaRect.right-tt_width ||
+ m_sOptions.wYPos > WorkAreaRect.bottom-tt_height)
+ {
+ pTooltip->set_Position(
+ WorkAreaRect.right - 10 - tt_width,
+ WorkAreaRect.bottom - 2 - tt_height);
+ }
+ else
+ {
+ pTooltip->set_Position(m_sOptions.wXPos, m_sOptions.wYPos);
+ }
+
+
+ UINT_PTR idTimer = SetTimer(0, 0, pTooltipData->uiTimeout, TooltipTimerProcWrapper);
+ pTooltipData->idTimer = idTimer;
+ pTooltipData->pTooltip = pTooltip;
+
+ m_TooltipsList.push_back(pTooltipData);
+
+ pTooltip->Show();
+
+ return pTooltip;
+}
+
+BOOL CTooltipNotify::EndNotify(STooltipData* pTooltipData)
+{
+ CTooltip* pTooltip = pTooltipData->pTooltip;
+
+ // return if the tooltip timer suspended
+ if (pTooltipData->idTimer == 0) return FALSE;
+ SuspendTimer(pTooltip);
+
+ pTooltip->Hide();
+ delete pTooltip;
+ delete pTooltipData;
+
+ m_TooltipsList.erase(
+ std::remove(m_TooltipsList.begin(), m_TooltipsList.end(), pTooltipData),
+ m_TooltipsList.end());
+
+ return TRUE;
+}
+
+VOID CTooltipNotify::EndNotifyAll()
+{
+ // iterate through active tooltips and
+ // remove one which do not have its timer suspended
+ TooltipsList::reverse_iterator mapRevIter = m_TooltipsList.rbegin();
+ while (mapRevIter != m_TooltipsList.rend())
+ {
+ STooltipData* pTooltipData = *mapRevIter;
+ if (EndNotify(pTooltipData))
+ {
+ mapRevIter = m_TooltipsList.rbegin();
+ }
+ else
+ {
+ ++mapRevIter;
+ }
+ }
+}
+
+CTooltipNotify::MapTimerIdProtoIter CTooltipNotify::FindProtoByTimer(UINT idTimer)
+{
+ for (
+ MapTimerIdProtoIter iter = m_mapTimerIdProto.begin();
+ iter != m_mapTimerIdProto.end();
+ ++iter)
+ {
+ if (iter->timerId == idTimer)
+ {
+ return iter;
+ }
+ }
+
+ return m_mapTimerIdProto.end();
+}
+
+VOID CTooltipNotify::OnConnectionTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ BOOL bSuccess = KillTimer(0, idEvent);
+ assert(bSuccess);
+
+ MapTimerIdProtoIter iter = FindProtoByTimer(idEvent);
+ assert(iter!=m_mapTimerIdProto.end());
+
+ BYTE bProtoActive = ReadSettingByte(iter->proto, ProtoUserBit|ProtoIntBit);
+ bProtoActive |= ProtoIntBit;
+ WriteSettingByte(iter->proto, bProtoActive);
+
+ free((char*)iter->proto);
+ m_mapTimerIdProto.erase(iter);
+}
+
+
+VOID CTooltipNotify::OnTooltipTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ TooltipsList::iterator iter = FindBy(&STooltipData::idTimer, idEvent);
+ assert(iter!=m_TooltipsList.end());
+
+ STooltipData* pTooltipData = *iter;
+ EndNotify(pTooltipData);
+}
+
+VOID CTooltipNotify::MigrateSettings()
+{
+ if (ModuleSettingsExists(NULL, s_szModuleNameOld) && !ModuleSettingsExists(NULL, s_szModuleName))
+ {
+ RenameModule(NULL, s_szModuleNameOld, s_szModuleName);
+ }
+}
+
+VOID CTooltipNotify::LoadSettings()
+{
+ m_sOptions.bFirstRun = ReadSettingByte("firstrun", DEF_SETTING_FIRSTRUN);
+ m_sOptions.bOffline = ReadSettingByte("offline", DEF_SETTING_OFFLINE);
+ m_sOptions.bOnline = ReadSettingByte("online", DEF_SETTING_ONLINE);
+ m_sOptions.bOther = ReadSettingByte("other", DEF_SETTING_OTHER);
+ m_sOptions.bTyping = ReadSettingByte("typing", DEF_SETTING_TYPING);
+ m_sOptions.bIdle = ReadSettingByte("idle", DEF_SETTING_TYPING);
+ m_sOptions.bX2 = ReadSettingByte("x2", DEF_SETTING_X2);
+ m_sOptions.bConjSOLN = ReadSettingByte("conjsoln", DEF_SETTING_CONJSOLN);
+ m_sOptions.bAutoPos = ReadSettingByte("autopos", DEF_SETTING_DEF_POS);
+ m_sOptions.bBallonTip = ReadSettingByte("balloontip", DEF_SETTING_BALLONTIP);
+ m_sOptions.bTransp = ReadSettingByte("transp", DEF_SETTING_TRANSP);
+ m_sOptions.bAlpha = ReadSettingByte("alpha", DEF_SETTING_ALPHA);
+ m_sOptions.bTranspInput = ReadSettingByte("transpinput", DEF_SETTING_TRANSP_INPUT);
+ m_sOptions.bPrefixProto = ReadSettingByte("prfxproto", DEF_SETTING_PREFIX_PROTO);
+ m_sOptions.bLDblClick = ReadSettingByte("ldblclick", DEF_SETTING_LDBLCLICK);
+ m_sOptions.wDuration = ReadSettingWord("duration", DEF_SETTING_DURATION);
+ m_sOptions.wXPos = ReadSettingWord("xpos", DEF_SETTING_DEF_XPOS);
+ m_sOptions.wYPos = ReadSettingWord("ypos", DEF_SETTING_DEF_YPOS);
+ m_sOptions.wStartupDelay = ReadSettingWord("suprconndelay", DEF_SETTING_STARTUP_DELAY);
+ m_sOptions.bIgnoreUnknown = ReadSettingByte("ignoreunknown", DEF_SETTING_IGNORE_UNKNOWN);
+ m_sOptions.bIgnoreNew = ReadSettingByte("ignorenew", DEF_SETTING_IGNORE_NEW);
+}
+
+VOID CTooltipNotify::SaveSettings()
+{
+ WriteSettingWord("duration", m_sOptions.wDuration);
+ WriteSettingWord("suprconndelay", m_sOptions.wStartupDelay);
+ WriteSettingByte("offline", m_sOptions.bOffline);
+ WriteSettingByte("online", m_sOptions.bOnline);
+ WriteSettingByte("other", m_sOptions.bOther);
+ WriteSettingByte("typing", m_sOptions.bTyping);
+ WriteSettingByte("idle", m_sOptions.bIdle);
+ WriteSettingByte("prfxproto", m_sOptions.bPrefixProto);
+ WriteSettingByte("x2", m_sOptions.bX2);
+ WriteSettingByte("conjsoln", m_sOptions.bConjSOLN);
+ WriteSettingByte("autopos", m_sOptions.bAutoPos);
+ WriteSettingByte("balloontip", m_sOptions.bBallonTip);
+ WriteSettingByte("transp", m_sOptions.bTransp);
+ WriteSettingByte("alpha", m_sOptions.bAlpha);
+ WriteSettingByte("transpinput", m_sOptions.bTranspInput);
+ WriteSettingByte("ldblclick", m_sOptions.bLDblClick);
+ WriteSettingByte("ignoreunknown", m_sOptions.bIgnoreUnknown);
+ WriteSettingByte("ignorenew", m_sOptions.bIgnoreNew);
+}
+
+
+VOID CTooltipNotify::ReadSettingsFromDlg(HWND hDlg)
+{
+ m_sOptions.bOffline = (BYTE)(IsDlgButtonChecked(hDlg, IDC_OFFLINE) == BST_CHECKED ? 1:0);
+ m_sOptions.bOnline = (BYTE)(IsDlgButtonChecked(hDlg, IDC_ONLINE) == BST_CHECKED ? 1:0);
+ m_sOptions.bOther = (BYTE)(IsDlgButtonChecked(hDlg, IDC_OTHER) == BST_CHECKED ? 1:0);
+ m_sOptions.bTyping = (BYTE)(IsDlgButtonChecked(hDlg, IDC_TYPING) == BST_CHECKED ? 1:0);
+ m_sOptions.bIdle = (BYTE)(IsDlgButtonChecked(hDlg, IDC_IDLE) == BST_CHECKED ? 1:0);
+ m_sOptions.bX2 = (BYTE)(IsDlgButtonChecked(hDlg, IDC_X2) == BST_CHECKED ? 1:0);
+ m_sOptions.bConjSOLN = (BYTE)(IsDlgButtonChecked(hDlg, IDC_CONJSOLN) == BST_CHECKED ? 1:0);
+ m_sOptions.bAutoPos = (BYTE)(IsDlgButtonChecked(hDlg, IDC_AUTOPOS) == BST_CHECKED ? 1:0);
+ m_sOptions.bBallonTip = (BYTE)(IsDlgButtonChecked(hDlg, IDC_BALLONTIP) == BST_CHECKED ? 1:0);
+ m_sOptions.bTransp = (BYTE)(IsDlgButtonChecked(hDlg, IDC_TRANSPARENCY) == BST_CHECKED ? 1:0);
+ m_sOptions.bAlpha = (BYTE)SendDlgItemMessage(hDlg,IDC_TRANSPARENCY_SLIDER,TBM_GETPOS,0,0);
+ m_sOptions.bTranspInput = (BYTE)(IsDlgButtonChecked(hDlg, IDC_TRANSP_INPUT) == BST_CHECKED ? 1:0);
+ m_sOptions.bPrefixProto = (BYTE)(IsDlgButtonChecked(hDlg, IDC_PREFIX_PROTO) == BST_CHECKED ? 1:0);
+ m_sOptions.bLDblClick = (BYTE)(IsDlgButtonChecked(hDlg, IDC_RB_CLIST) == BST_CHECKED) ? SHOW_HIDE_CLIST:OPEN_MSGDLG;
+ m_sOptions.wDuration = LOWORD(SendDlgItemMessage(hDlg, IDC_DURATIONSPIN, UDM_GETPOS, 0, 0));
+ m_sOptions.wStartupDelay = LOWORD(SendDlgItemMessage(hDlg, IDC_DELAYONCONNSPIN, UDM_GETPOS, 0, 0));
+}
+
+VOID CTooltipNotify::WriteSettingsToDlg(HWND hDlg)
+{
+ SendDlgItemMessage(hDlg, IDC_DURATIONSPIN, UDM_SETRANGE, 0, MAKELONG(550*36, 550));
+ SendDlgItemMessage(hDlg, IDC_DURATIONSPIN, UDM_SETPOS, 0, MAKELONG(m_sOptions.wDuration, 0));
+ SendDlgItemMessage(hDlg, IDC_DELAYONCONNSPIN, UDM_SETRANGE, 0, MAKELONG(30, 0));
+ SendDlgItemMessage(hDlg, IDC_DELAYONCONNSPIN, UDM_SETPOS, 0, MAKELONG(m_sOptions.wStartupDelay, 0));
+
+ CheckDlgButton(hDlg, IDC_OFFLINE, m_sOptions.bOffline ? BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_ONLINE, m_sOptions.bOnline ? BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_OTHER, m_sOptions.bOther ? BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_TYPING, m_sOptions.bTyping ? BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_IDLE, m_sOptions.bIdle ? BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_PREFIX_PROTO, m_sOptions.bPrefixProto ? BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_X2, m_sOptions.bX2 ? BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_CONJSOLN, m_sOptions.bConjSOLN ? BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_AUTOPOS, m_sOptions.bAutoPos ? BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_BALLONTIP, m_sOptions.bBallonTip ? BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_TRANSPARENCY, m_sOptions.bTransp ? BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hDlg, IDC_TRANSP_INPUT, m_sOptions.bTranspInput ? BST_CHECKED:BST_UNCHECKED);
+
+ switch(m_sOptions.bLDblClick)
+ {
+ case SHOW_HIDE_CLIST: CheckDlgButton(hDlg, IDC_RB_CLIST, TRUE); break;
+ case OPEN_MSGDLG: CheckDlgButton(hDlg, IDC_RB_MSGDLG, TRUE); break;
+ default: CheckDlgButton(hDlg, IDC_RB_CLIST, TRUE); break;
+ }
+
+ EnableWindow(GetDlgItem(hDlg, IDC_GB_TRANSP), m_bNt50);
+ EnableWindow(GetDlgItem(hDlg, IDC_TRANSPARENCY), m_bNt50);
+ EnableWindow(GetDlgItem(hDlg, IDC_TRANSPARENCY_SLIDER), m_sOptions.bTransp && m_bNt50);
+ EnableWindow(GetDlgItem(hDlg, IDC_TRANSPERC), m_sOptions.bTransp && m_bNt50);
+ EnableWindow(GetDlgItem(hDlg, IDC_TRANSP_INPUT), m_sOptions.bTransp && m_bNt50);
+ //EnableWindow(GetDlgItem(hDlg, IDC_GB_DBLCLICK), m_sOptions.bTranspInput);
+ EnableWindow(GetDlgItem(hDlg, IDC_RB_CLIST), !m_sOptions.bTranspInput);
+ EnableWindow(GetDlgItem(hDlg, IDC_RB_MSGDLG), !m_sOptions.bTranspInput);
+
+ SendDlgItemMessage(hDlg, IDC_TRANSPARENCY_SLIDER, TBM_SETRANGE, FALSE, MAKELONG(1,255));
+ SendDlgItemMessage(hDlg, IDC_TRANSPARENCY_SLIDER, TBM_SETPOS, TRUE, m_sOptions.bAlpha);
+}
+
+
+VOID CTooltipNotify::ValidateSettings()
+{
+ if (m_sOptions.wStartupDelay>30) m_sOptions.wStartupDelay=30;
+ if (m_sOptions.wDuration>550*36) m_sOptions.wDuration=550*36;
+ if (m_sOptions.wDuration<550*1) m_sOptions.wDuration=550*1;
+ if (!m_sOptions.bTransp) m_sOptions.bTranspInput=0;
+}
+
+
+// main options dialog
+BOOL CTooltipNotify::OptionsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hDlg);
+ WriteSettingsToDlg(hDlg);
+ SendMessage(hDlg, WM_HSCROLL, 0x12345678, 0);
+
+ return TRUE;
+ }
+
+ case WM_VSCROLL:
+ case WM_HSCROLL:
+ {
+ TCHAR str[10];
+ wsprintf(str, _T("%d%%"), 100*SendDlgItemMessage(hDlg, IDC_TRANSPARENCY_SLIDER, TBM_GETPOS, 0, 0)/255);
+ SetDlgItemText(hDlg, IDC_TRANSPERC, str);
+ if(wParam!=0x12345678) SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_TRANSPARENCY:
+ EnableWindow(GetDlgItem(hDlg, IDC_TRANSPERC), IsDlgButtonChecked(hDlg, IDC_TRANSPARENCY) == BST_CHECKED);
+ EnableWindow(GetDlgItem(hDlg, IDC_TRANSPARENCY_SLIDER), IsDlgButtonChecked(hDlg, IDC_TRANSPARENCY) == BST_CHECKED);
+ EnableWindow(GetDlgItem(hDlg, IDC_TRANSP_INPUT), IsDlgButtonChecked(hDlg, IDC_TRANSPARENCY) == BST_CHECKED);
+ CheckDlgButton(hDlg, IDC_TRANSP_INPUT, IsDlgButtonChecked(hDlg, IDC_TRANSPARENCY) == BST_CHECKED ? m_sOptions.bTranspInput : BST_UNCHECKED);
+ SendMessage(hDlg, WM_COMMAND, MAKEWPARAM(IDC_TRANSP_INPUT, 0), 0);
+ SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case IDC_TRANSP_INPUT:
+ //EnableWindow(GetDlgItem(hDlg,IDC_GB_DBLCLICK), IsDlgButtonChecked(hDlg, IDC_TRANSP_INPUT));
+ EnableWindow(GetDlgItem(hDlg,IDC_RB_CLIST), !(IsDlgButtonChecked(hDlg, IDC_TRANSP_INPUT) == BST_CHECKED));
+ EnableWindow(GetDlgItem(hDlg,IDC_RB_MSGDLG), !(IsDlgButtonChecked(hDlg, IDC_TRANSP_INPUT) == BST_CHECKED));
+ SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case IDC_BALLONTIP:
+ EnableWindow(GetDlgItem(hDlg,IDC_DURATION),!(IsDlgButtonChecked(hDlg,IDC_BALLONTIP)==BST_CHECKED));
+ EnableWindow(GetDlgItem(hDlg,IDC_X2),!(IsDlgButtonChecked(hDlg,IDC_BALLONTIP)==BST_CHECKED));
+ EnableWindow(GetDlgItem(hDlg,IDC_RB_CLIST),!(IsDlgButtonChecked(hDlg,IDC_BALLONTIP)==BST_CHECKED));
+ EnableWindow(GetDlgItem(hDlg,IDC_RB_MSGDLG),!(IsDlgButtonChecked(hDlg,IDC_BALLONTIP)==BST_CHECKED));
+ EnableWindow(GetDlgItem(hDlg,IDC_TRANSP_INPUT),!(IsDlgButtonChecked(hDlg,IDC_BALLONTIP)==BST_CHECKED));
+ EnableWindow(GetDlgItem(hDlg,IDC_AUTOPOS),!(IsDlgButtonChecked(hDlg,IDC_BALLONTIP)==BST_CHECKED));
+ SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case IDC_DURATION:
+ if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()) return FALSE;
+ SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case IDC_DELAYONCONN:
+ if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()) return FALSE;
+ SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case IDC_PREVIEW:
+ {
+ STooltipData *pTooltipData = new STooltipData;
+ pTooltipData->uiTimeout = m_sOptions.wDuration * (m_sOptions.bX2 ? (m_sOptions.bX2+1):1);
+ pTooltipData->hContact = 0;
+ pTooltipData->iStatus = ID_STATUS_ONLINE;
+
+ EndNotifyAll();
+ BeginNotify(pTooltipData);
+ break;
+ }
+
+ case IDC_SEL_PROTO:
+ DialogBox(m_hDllInstance, MAKEINTRESOURCE(IDD_PROTOS), hDlg, (DLGPROC)CTooltipNotify::ProtosDlgProcWrapper);
+ break;
+
+ case IDC_IGNORE:
+ DialogBox(m_hDllInstance, MAKEINTRESOURCE(IDD_CONTACTS), hDlg, (DLGPROC)CTooltipNotify::ContactsDlgProcWrapper);
+ break;
+
+ default:
+ // activate 'apply' button
+ SendMessage(GetParent(hDlg), PSM_CHANGED, 0, 0);
+ return TRUE;
+ }
+
+ return TRUE;
+ }
+
+ case WM_NOTIFY:
+ {
+ //Here we have pressed either the OK or the APPLY button.
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ ReadSettingsFromDlg(hDlg);
+ SaveSettings();
+ return TRUE;
+
+ } // switch code
+ break;
+
+ } //switch idFrom
+
+ return TRUE;
+ }
+
+ default:
+ break;
+
+ }
+
+ return FALSE;
+
+}
+
+
+// dialog for protocols selecting
+BOOL CTooltipNotify::ProtosDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hDlg);
+
+ ListView_SetExtendedListViewStyle(GetDlgItem(hDlg, IDC_PROTOS), LVS_EX_CHECKBOXES);
+
+ // enum protocols currently running
+ int iProtoCount = 0;
+ PROTOCOLDESCRIPTOR **ppProtos = 0;
+ ::CallService(MS_PROTO_ENUMPROTOCOLS, (WPARAM)&iProtoCount, (LPARAM)&ppProtos);
+
+ // and fill in the list
+ int iNonProtoCount = 0;
+ for (int i=0; i < iProtoCount; i++)
+ {
+ if (ppProtos[i]->type == PROTOTYPE_PROTOCOL)
+ {
+ LV_ITEM lvi;
+
+ lvi.mask = LVIF_TEXT;
+ lvi.iSubItem = 0;
+ lvi.iItem = i;
+ lvi.lParam = i;
+#ifdef _UNICODE
+ WCHAR wszProto[128];
+ long lLen = MultiByteToWideChar(CP_ACP, 0, ppProtos[i]->szName,
+ strlen(ppProtos[i]->szName), wszProto, ARRAY_SIZE(wszProto));
+ wszProto[lLen] = L'\0';
+
+ lvi.pszText = wszProto;
+#else
+ lvi.pszText = ppProtos[lvi.iItem]->szName;
+#endif
+ int new_item = ListView_InsertItem(GetDlgItem(hDlg,IDC_PROTOS),&lvi);
+
+ BYTE bProtoState = ReadSettingByte(ppProtos[i]->szName, ProtoUserBit|ProtoIntBit);
+ BOOL bProtoEnabled = (bProtoState & ProtoUserBit) != 0;
+ ListView_SetCheckState(GetDlgItem(hDlg,IDC_PROTOS), i-iNonProtoCount, bProtoEnabled);
+ }
+ else
+ {
+ iNonProtoCount++;
+ }
+ }
+
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ if (LOWORD(wParam) == IDOK)
+ {
+ int proto_count = ListView_GetItemCount(GetDlgItem(hDlg,IDC_PROTOS));
+
+ for (int i=0; i < proto_count; i++)
+ {
+ TCHAR szProto[64];
+
+ ListView_GetItemText(GetDlgItem(hDlg,IDC_PROTOS), i, 0, szProto, ARRAY_SIZE(szProto));
+#ifdef _UNICODE
+ char szMultiByteProto[128];
+ long lLen = WideCharToMultiByte(CP_ACP, 0, szProto, lstrlen(szProto),
+ szMultiByteProto, sizeof(szMultiByteProto), NULL, NULL);
+ szMultiByteProto[lLen] = '\0';
+
+ BYTE bProtoState = ReadSettingByte(szMultiByteProto, ProtoUserBit|ProtoIntBit);
+#else
+ BYTE bProtoState = ReadSettingByte(szProto, ProtoUserBit|ProtoIntBit);
+#endif
+
+ BOOL bProtoEnabled = ListView_GetCheckState(GetDlgItem(hDlg,IDC_PROTOS), i);
+ bProtoState = bProtoEnabled ? bProtoState|ProtoUserBit : bProtoState&~ProtoUserBit;
+#ifdef _UNICODE
+ WriteSettingByte(szMultiByteProto, bProtoState);
+#else
+ WriteSettingByte(szProto, bProtoState);
+#endif
+ }
+
+ EndDialog(hDlg, LOWORD(wParam));
+ return TRUE;
+ }
+
+ if (LOWORD(wParam) == IDCANCEL)
+ {
+ EndDialog(hDlg, LOWORD(wParam));
+ return TRUE;
+ }
+
+ return TRUE;
+ }
+
+ case WM_CLOSE:
+ EndDialog(hDlg, LOWORD(wParam));
+ return TRUE;
+
+ default:
+ break;
+
+ } // switch (msg)
+
+ return FALSE;
+
+}
+
+void CTooltipNotify::ResetCList(HWND hwndDlg)
+{
+ BOOL b = (CallService(MS_CLUI_GETCAPS, 0, 0) & CLUIF_DISABLEGROUPS &&
+ DBGetContactSettingByte(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT));
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETUSEGROUPS, (WPARAM) b, 0);
+
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETHIDEEMPTYGROUPS, 1, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETGREYOUTFLAGS, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETLEFTMARGIN, 2, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETBKBITMAP, 0, (LPARAM) (HBITMAP) NULL);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETINDENT, 10, 0);
+
+ for (int i = 0; i <= FONTID_MAX; i++)
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT));
+}
+
+void CTooltipNotify::LoadList(HWND hwndDlg, HANDLE hItemNew, HANDLE hItemUnknown)
+{
+ if (hItemNew && !m_sOptions.bIgnoreNew)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM) hItemNew, 1);
+ }
+ if (hItemUnknown && !m_sOptions.bIgnoreUnknown)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM) hItemUnknown, 1);
+ }
+
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ do
+ {
+ HANDLE hItem = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM) hContact, 0);
+ if (hItem && !DBGetContactSettingByte(hContact, s_szModuleName, CONTACT_IGNORE_TTNOTIFY, m_sOptions.bIgnoreNew))
+ {
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM) hItem, 1);
+ }
+ }
+ while (hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0));
+}
+
+void CTooltipNotify::SaveList(HWND hwndDlg, HANDLE hItemNew, HANDLE hItemUnknown)
+{
+ if (hItemNew)
+ {
+ m_sOptions.bIgnoreNew = (BYTE) (SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItemNew, 0) ? 0 : 1);
+ }
+ if (hItemUnknown)
+ {
+ m_sOptions.bIgnoreUnknown = (BYTE) (SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItemUnknown, 0) ? 0 : 1);
+ }
+
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ do
+ {
+ HANDLE hItem = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM) hContact, 0);
+ if (hItem)
+ {
+ BYTE bChecked = (BYTE) (SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItem, 0));
+ DBWriteContactSettingByte(hContact, s_szModuleName, CONTACT_IGNORE_TTNOTIFY, bChecked ? 0 : 1);
+ }
+ }
+ while (hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0));
+}
+
+
+// dialog for ignore tooltip notifications
+BOOL CTooltipNotify::ContactsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static HANDLE hItemNew, hItemUnknown;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hDlg);
+
+ CLCINFOITEM cii = { 0 };
+ cii.cbSize = sizeof(cii);
+ cii.flags = CLCIIF_GROUPFONT | CLCIIF_CHECKBOX;
+ cii.pszText = TranslateT("** New contacts **");
+ hItemNew = (HANDLE) SendDlgItemMessage(hDlg, IDC_CLIST, CLM_ADDINFOITEM, 0, (LPARAM) & cii);
+ cii.pszText = TranslateT("** Unknown contacts **");
+ hItemUnknown = (HANDLE) SendDlgItemMessage(hDlg, IDC_CLIST, CLM_ADDINFOITEM, 0, (LPARAM) & cii);
+
+ ResetCList(hDlg);
+ LoadList(hDlg, hItemNew, hItemUnknown);
+ return TRUE;
+ }
+
+
+ case WM_COMMAND:
+ {
+ if (LOWORD(wParam) == IDOK)
+ {
+ SaveList(hDlg, hItemNew, hItemUnknown);
+ EndDialog(hDlg, LOWORD(wParam));
+ return TRUE;
+ }
+
+ if (LOWORD(wParam) == IDCANCEL)
+ {
+ EndDialog(hDlg, LOWORD(wParam));
+ return TRUE;
+ }
+
+ return TRUE;
+ }
+
+ case WM_CLOSE:
+ EndDialog(hDlg, LOWORD(wParam));
+ return TRUE;
+
+ default:
+ break;
+
+ } // switch (msg)
+
+ return FALSE;
+
+}
+
+
+
+TCHAR *CTooltipNotify::StatusToString(int iStatus, TCHAR *szStatus, int iBufSize)
+{
+
+ //iBufSize--;
+
+ switch(iStatus)
+ {
+ case ID_STATUS_OFFLINE:
+ lstrcpyn(szStatus, TranslateT("Offline"), iBufSize);
+ break;
+
+ case ID_STATUS_ONLINE:
+ lstrcpyn(szStatus, TranslateT("Online"), iBufSize);
+ break;
+
+ case ID_STATUS_AWAY:
+ lstrcpyn(szStatus, TranslateT("Away"), iBufSize);
+ break;
+
+ case ID_STATUS_NA :
+ lstrcpyn(szStatus, TranslateT("N/A"), iBufSize);
+ break;
+
+ case ID_STATUS_OCCUPIED:
+ lstrcpyn(szStatus, TranslateT("Occupied"), iBufSize);
+ break;
+
+ case ID_STATUS_DND:
+ lstrcpyn(szStatus, TranslateT("DND"), iBufSize);
+ break;
+
+ case ID_STATUS_FREECHAT:
+ lstrcpyn(szStatus, TranslateT("Free for chat"), iBufSize);
+ break;
+
+ case ID_STATUS_INVISIBLE:
+ lstrcpyn(szStatus, TranslateT("Invisible"), iBufSize);
+ break;
+
+ case ID_TTNTF_STATUS_TYPING:
+ lstrcpyn(szStatus, TranslateT("Typing"), iBufSize);
+ break;
+
+ case ID_TTNTF_STATUS_IDLE:
+ lstrcpyn(szStatus, TranslateT("Idle"), iBufSize);
+ break;
+
+ case ID_TTNTF_STATUS_NOT_IDLE:
+ lstrcpyn(szStatus, TranslateT("Not Idle"), iBufSize);
+ break;
+
+ default:
+ lstrcpyn(szStatus, TranslateT("Unknown"), iBufSize);
+ break;
+ }
+
+ return szStatus;
+
+}
+
+TCHAR *CTooltipNotify::MakeTooltipString(HANDLE hContact, int iStatus, TCHAR *szString, int iBufSize)
+{
+ TCHAR szStatus[32];
+ StatusToString(iStatus, szStatus, ARRAY_SIZE(szStatus));
+
+ // "proro: user is online"
+ const TCHAR *szFormatString = m_sOptions.bPrefixProto ? _T("%s%s%s") : _T("%.0s%.0s%s");
+ const TCHAR* szIs = TranslateT("is");
+
+ const char* szProto =
+ hContact==0 ? "Proto" : (char*)::CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ const TCHAR* szContactName =
+ (TCHAR *)::CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR);
+
+ memset(szString, 0, iBufSize*sizeof(TCHAR));
+
+#ifdef _UNICODE
+ WCHAR wszProto[32];
+ long lLen = MultiByteToWideChar(CP_ACP, 0, szProto, strlen(szProto), wszProto, ARRAY_SIZE(wszProto));
+ wszProto[lLen] = _T('\0');
+
+ _sntprintf(szString, iBufSize-1, szFormatString, wszProto, _T(": "), szContactName);
+#else
+ _sntprintf(szString, iBufSize-1, szFormatString, szProto, _T(": "), szContactName);
+#endif
+
+ TruncateWithDots(szString, iBufSize-1-_tcslen(szStatus)-_tcslen(szIs)-2); // 2 spaces around szIs
+ _sntprintf(szString+_tcslen(szString), iBufSize-1-_tcslen(szString), _T(" %s %s"), szIs, szStatus);
+
+ return szString;
+}
+
+
+VOID CTooltipNotify::OnTooltipDblClicked(CTooltip *pTooltip)
+{
+ switch(m_sOptions.bLDblClick)
+ {
+ case SHOW_HIDE_CLIST:
+ ::CallService(MS_CLIST_SHOWHIDE,0,0);
+ break;
+
+ case OPEN_MSGDLG:
+ {
+ TooltipsList::iterator iter = FindBy(&STooltipData::pTooltip, pTooltip);
+ STooltipData* pTooltipData = *iter;
+ WPARAM wParam = (WPARAM)pTooltipData->hContact;
+ if (wParam) ::CallService(MS_CLIST_CONTACTDOUBLECLICKED, wParam, 0);
+ break;
+ }
+
+ default:
+ ::CallService(MS_CLIST_SHOWHIDE,0,0);
+ break;
+ }
+}
+
+
+BOOL CTooltipNotify::OnTooltipBeginMove(CTooltip *pTooltip)
+{
+ if (m_sOptions.bAutoPos) return FALSE;
+
+ SuspendTimer(pTooltip);
+ return TRUE;
+}
+
+
+VOID CTooltipNotify::OnTooltipEndMove(CTooltip *pTooltip)
+{
+ RECT TooltipRect;
+
+ pTooltip->get_Rect(&TooltipRect);
+ m_sOptions.wXPos = (WORD)TooltipRect.left;
+ m_sOptions.wYPos = (WORD)TooltipRect.top;
+ WriteSettingWord("xpos", m_sOptions.wXPos);
+ WriteSettingWord("ypos", m_sOptions.wYPos);
+
+ ResumeTimer(pTooltip);
+}
+
+
+VOID CTooltipNotify::SuspendTimer(CTooltip *pTooltip)
+{
+ TooltipsList::iterator iter = FindBy(&STooltipData::pTooltip, pTooltip);
+ assert(iter!=m_TooltipsList.end());
+
+ STooltipData* pTooltipData = *iter;
+
+ BOOL bSuccess = KillTimer(0, pTooltipData->idTimer);
+ assert(bSuccess);
+ pTooltipData->idTimer = 0; // denote that the timer is inactive
+}
+
+
+VOID CTooltipNotify::ResumeTimer(CTooltip *pTooltip)
+{
+ TooltipsList::iterator iter = FindBy(&STooltipData::pTooltip, pTooltip);
+ assert(iter!=m_TooltipsList.end());
+
+ STooltipData* pTooltipData = *iter;
+
+ UINT_PTR idTimer = SetTimer(0, 0, pTooltipData->uiTimeout, TooltipTimerProcWrapper);
+ pTooltipData->idTimer = idTimer;
+}
+
+template<typename T>
+CTooltipNotify::TooltipsList::iterator CTooltipNotify::FindBy(T STooltipData::* field, const T& value)
+{
+ for (
+ TooltipsList::iterator iter = m_TooltipsList.begin();
+ iter != m_TooltipsList.end();
+ ++iter)
+ {
+ STooltipData *pTooltipData = *iter;
+ if (pTooltipData->*field == value)
+ {
+ return iter;
+ }
+ }
+
+ return m_TooltipsList.end();
+}
diff --git a/plugins/TooltipNotify/src/TooltipNotify.h b/plugins/TooltipNotify/src/TooltipNotify.h
new file mode 100644
index 0000000000..5e17597dd6
--- /dev/null
+++ b/plugins/TooltipNotify/src/TooltipNotify.h
@@ -0,0 +1,143 @@
+// TooltipNotify.h: interface for the CTooltipNotify class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class CTooltip;
+
+class CTooltipNotify
+{
+private:
+ struct STooltipData;
+
+public:
+ CTooltipNotify(HINSTANCE hinstDLL);
+ virtual ~CTooltipNotify();
+
+ // exceptions
+ class EAlreadyExists {};
+
+ BOOL EndNotify(STooltipData* pTooltipData);
+ VOID EndNotifyAll();
+ CTooltip *BeginNotify(STooltipData *pTooltipData);
+ VOID OnTooltipDblClicked(CTooltip *pTooltip);
+ BOOL OnTooltipBeginMove(CTooltip *pTooltip);
+ VOID OnTooltipEndMove(CTooltip *pTooltip);
+ int InitializeOptions(WPARAM wParam, LPARAM lParam);
+ int ContactSettingChanged(WPARAM wParam, LPARAM lParam);
+ int ProtoAck(WPARAM wParam, LPARAM lParam);
+ int ModulesLoaded(WPARAM wParam,LPARAM lParam);
+ int ProtoContactIsTyping(WPARAM wParam, LPARAM lParam);
+
+ static CTooltipNotify *GetObjInstance() { return s_pInstance; }
+ HINSTANCE GetDllInstance() const { return m_hDllInstance; }
+
+private:
+ // prohibit copying
+ CTooltipNotify(const CTooltipNotify& rhs);
+ CTooltipNotify& operator= (const CTooltipNotify& rhs);
+
+private:
+ static CTooltipNotify *s_pInstance;
+ static const char *s_szModuleNameOld;
+ static const char *s_szModuleName;
+
+ const HINSTANCE m_hDllInstance;
+ const BOOL m_bNt50;
+
+ struct SOptions {
+ BYTE bFirstRun;
+ BYTE bOffline;
+ BYTE bOnline;
+ BYTE bOther;
+ BYTE bTyping;
+ BYTE bIdle;
+ BYTE bConjSOLN;
+ BYTE bX2;
+ BYTE bAutoPos;
+ BYTE bBallonTip;
+ BYTE bTransp;
+ BYTE bTranspInput;
+ BYTE bAlpha;
+ BYTE bLDblClick;
+ BYTE bPrefixProto;
+ WORD wDuration;
+ WORD wXPos;
+ WORD wYPos;
+ WORD wStartupDelay;
+ BYTE bIgnoreNew;
+ BYTE bIgnoreUnknown;
+ } m_sOptions;
+
+ struct STooltipData {
+ CTooltip *pTooltip;
+ UINT_PTR idTimer;
+ UINT uiTimeout;
+ HANDLE hContact;
+ int iStatus;
+ };
+
+ struct ProtoData {
+ const char* proto;
+ UINT_PTR timerId;
+ };
+
+ typedef std::vector<STooltipData*> TooltipsList;
+ typedef TooltipsList::iterator TooltipsListIter;
+ typedef TooltipsList::reverse_iterator TooltipsListRevIter;
+ TooltipsList m_TooltipsList;
+
+ typedef std::vector<ProtoData> MapTimerIdProto;
+ typedef MapTimerIdProto::iterator MapTimerIdProtoIter;
+ MapTimerIdProto m_mapTimerIdProto;
+
+ MapTimerIdProtoIter FindProtoByTimer(UINT idTimer);
+ template<typename T> TooltipsListIter FindBy(T STooltipData::* m, const T& value);
+ TCHAR *StatusToString(int iStatus, TCHAR *szStatus, int iBufSize);
+ TCHAR *MakeTooltipString(HANDLE hContact, int iStatus, TCHAR *szString, int iBufSize);
+ VOID MigrateSettings();
+ void RegisterFonts();
+ void GetFont(int iStatus, LOGFONT* lf, COLORREF* text, COLORREF* bg);
+ void ResetCList(HWND hwndDlg);
+ void LoadList(HWND hwndDlg, HANDLE hItemNew, HANDLE hItemUnknown);
+ void SaveList(HWND hwndDlg, HANDLE hItemNew, HANDLE hItemUnknown);
+ VOID LoadSettings();
+ VOID SaveSettings();
+ VOID ValidateSettings();
+ VOID ReadSettingsFromDlg(HWND hDlg);
+ VOID WriteSettingsToDlg(HWND hDlg);
+
+ VOID SuspendTimer(CTooltip *pTooltip);
+ VOID ResumeTimer(CTooltip *pTooltip);
+ VOID OnConnectionTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
+ VOID OnTooltipTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
+
+ // Dialog procedures
+ BOOL OptionsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+ BOOL ProtosDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+ BOOL ContactsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+ static VOID CALLBACK ConnectionTimerProcWrapper(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+ {
+ CTooltipNotify::GetObjInstance()->OnConnectionTimer(hwnd, uMsg, idEvent, dwTime);
+ }
+ static VOID CALLBACK TooltipTimerProcWrapper(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+ {
+ CTooltipNotify::GetObjInstance()->OnTooltipTimer(hwnd, uMsg, idEvent, dwTime);
+ }
+ static BOOL CALLBACK OptionsDlgProcWrapper(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+ {
+ return CTooltipNotify::GetObjInstance()->OptionsDlgProc(hDlg, msg, wParam, lParam);
+ }
+ static BOOL CALLBACK ProtosDlgProcWrapper(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+ {
+ return CTooltipNotify::GetObjInstance()->ProtosDlgProc(hDlg, msg, wParam, lParam);
+ }
+
+ static BOOL CALLBACK ContactsDlgProcWrapper(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+ {
+ return CTooltipNotify::GetObjInstance()->ContactsDlgProc(hDlg, msg, wParam, lParam);
+ }
+
+};
diff --git a/plugins/TooltipNotify/src/Utils.cpp b/plugins/TooltipNotify/src/Utils.cpp
new file mode 100644
index 0000000000..ce73dbc59b
--- /dev/null
+++ b/plugins/TooltipNotify/src/Utils.cpp
@@ -0,0 +1,32 @@
+//
+// Utils.cpp
+//
+
+#include "stdafx.h"
+#include "Utils.h"
+
+BOOL IsNt50()
+{
+ WORD wOsVersion = LOWORD(GetVersion());
+ BYTE bMajorVer = LOBYTE(wOsVersion);
+ BYTE bMinorVer = HIBYTE(wOsVersion);
+
+ return (bMajorVer>=5 && bMinorVer>=0);
+}
+
+void TruncateWithDots(TCHAR* szString, int iNewLen)
+{
+ assert(iNewLen >= 0);
+
+ int iOrigLen = _tcslen(szString);
+ if (iNewLen < iOrigLen)
+ {
+ TCHAR* p = szString+iNewLen;
+ *p = _T('\0');
+ for(int i=0; --p>=szString && i<3; i++)
+ {
+ *p = _T('.');
+ }
+ }
+}
+
diff --git a/plugins/TooltipNotify/src/Utils.h b/plugins/TooltipNotify/src/Utils.h
new file mode 100644
index 0000000000..d1ad4d0fe7
--- /dev/null
+++ b/plugins/TooltipNotify/src/Utils.h
@@ -0,0 +1,8 @@
+//
+// Utils.h
+//
+
+#pragma once
+
+BOOL IsNt50();
+void TruncateWithDots(TCHAR* szString, int iNewLen); \ No newline at end of file
diff --git a/plugins/TooltipNotify/src/main.cpp b/plugins/TooltipNotify/src/main.cpp
new file mode 100644
index 0000000000..5695120354
--- /dev/null
+++ b/plugins/TooltipNotify/src/main.cpp
@@ -0,0 +1,218 @@
+/*/////////////////////////////////////////////
+ Tooltip Notify plugin for Miranda IM
+*//////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "version.h"
+#include "TooltipNotify.h"
+
+// {5906A545-F31A-4726-B48F-03A09F060318}
+static const MUUID MIID_TOOLTIPNOTIFY_UNICODE =
+{ 0x5906a545, 0xf31a, 0x4726, { 0xb4, 0x8f, 0x3, 0xa0, 0x9f, 0x6, 0x3, 0x18 } };
+
+// {C4475C65-630F-4e70-980F-C0CA98767110}
+static const MUUID MIID_TOOLTIPNOTIFY_ANSI =
+{ 0xc4475c65, 0x630f, 0x4e70, { 0x98, 0xf, 0xc0, 0xca, 0x98, 0x76, 0x71, 0x10 } };
+
+// {03CD82B6-0BB5-4f26-8EB4-06CD8ECD36FF}
+static const MUUID MIID_TOOLTIPNOTIFY =
+{ 0x3cd82b6, 0xbb5, 0x4f26, { 0x8e, 0xb4, 0x6, 0xcd, 0x8e, 0xcd, 0x36, 0xff } };
+
+static int InitializeOptions(WPARAM wParam,LPARAM lParam);
+static int ModulesLoaded(WPARAM wParam,LPARAM lParam);
+static int ContactSettingChanged(WPARAM wParam,LPARAM lParam);
+static int ProtoAck(WPARAM,LPARAM);
+static int ProtoContactIsTyping(WPARAM wParam,LPARAM lParam);
+
+
+// Globals
+PLUGINLINK *pluginLink; // cannot be static since it is used for mim service calls
+
+static HANDLE g_hContactSettingChanged = 0;
+static HANDLE g_hOptionsInitialize = 0;
+static HANDLE g_hModulesLoaded = 0;
+static HANDLE g_hProtoAck = 0;
+static HANDLE g_hProtoContactIsTyping = 0;
+static HINSTANCE g_hInstDLL = 0;
+static bool g_bRightModule = false; // i.e. ansi for win9x, and unicode for winnt
+
+// Main global object
+static CTooltipNotify *g_pTooltipNotify = 0;
+
+
+//================================================================================
+// plugin init/deinit routines
+//================================================================================
+
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch(fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ DisableThreadLibraryCalls(hInstDLL);
+ g_hInstDLL = hInstDLL;
+
+ OSVERSIONINFO OsVersionInfo;
+ OsVersionInfo.dwOSVersionInfoSize = sizeof(OsVersionInfo);
+ GetVersionEx(&OsVersionInfo);
+
+#ifdef _UNICODE
+ g_bRightModule = (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
+#else
+ g_bRightModule = (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
+#endif
+
+ break;
+ }
+
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+
+ return TRUE;
+}
+
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ static const MUUID interfaces[] = {MIID_TOOLTIPNOTIFY, MIID_LAST};
+ return interfaces;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ static char szWrongUsage9x[] =
+ "Warning! You are trying to use unicode version of the plugin on win9x system! "
+ "It can not be working here. You must use ansi version of the plugin.";
+
+ static char szWrongUsageNt[] =
+ "Warning! You are using ansi version of the plugin on a unicode-aware system. "
+ "It is recommended to use unicode version of the plugin.";
+
+ static char szFunctionalDescription[] =
+ "Shows a small tooltip above system tray area when a contact status is changed.";
+
+
+ static PLUGININFOEX sPluginInfo =
+ {
+ sizeof(PLUGININFOEX),
+ "Tooltip Notify",
+ PLUGIN_MAKE_VERSION(MAJOR,MINOR,BUILD,REVISION), // major, minor, revision, build
+#ifdef _UNICODE
+ g_bRightModule ? szFunctionalDescription : szWrongUsage9x,
+#else
+ g_bRightModule ? szFunctionalDescription : szWrongUsageNt,
+#endif
+ "perf",
+ "perf@mail333.com",
+ " 2004-2008 Gneedah software",
+ "http://addons.miranda-im.org/details.php?action=viewfile&id=1290",
+ UNICODE_AWARE,
+ 0, //doesn't replace anything built-in
+#ifdef _UNICODE
+ MIID_TOOLTIPNOTIFY_UNICODE
+#else
+ MIID_TOOLTIPNOTIFY_ANSI
+#endif
+ };
+
+ return &sPluginInfo;
+}
+
+extern "C" __declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
+{
+ PLUGININFOEX* pPluginInfoEx = MirandaPluginInfoEx(mirandaVersion);
+
+ static PLUGININFO sPluginInfo =
+ {
+ sizeof(PLUGININFO),
+ pPluginInfoEx->shortName,
+ pPluginInfoEx->version,
+ pPluginInfoEx->description,
+ pPluginInfoEx->author,
+ pPluginInfoEx->authorEmail,
+ pPluginInfoEx->copyright,
+ pPluginInfoEx->homepage,
+ pPluginInfoEx->flags,
+ pPluginInfoEx->replacesDefaultModule
+ };
+
+ return &sPluginInfo;
+}
+
+
+extern "C" int __declspec(dllexport) Load(PLUGINLINK *pLink)
+{
+#ifdef _UNICODE
+ if (!g_bRightModule) return 0;
+#else
+ // ansi version can work ok on winnt platform
+#endif
+
+ pluginLink = pLink;
+
+ g_pTooltipNotify = new CTooltipNotify(g_hInstDLL);
+ assert(g_pTooltipNotify!=0);
+
+ g_hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded);
+
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ if (g_hContactSettingChanged) UnhookEvent(g_hContactSettingChanged);
+ if (g_hProtoContactIsTyping) UnhookEvent(g_hProtoContactIsTyping);
+ if (g_hProtoAck) UnhookEvent(g_hProtoAck);
+ if (g_hOptionsInitialize) UnhookEvent(g_hOptionsInitialize);
+ if (g_hModulesLoaded) UnhookEvent(g_hModulesLoaded);
+ delete g_pTooltipNotify;
+
+ return 0;
+}
+
+
+
+//================================================================================
+//================================================================================
+//================================================================================
+
+
+int ModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ g_hContactSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, ContactSettingChanged);
+ g_hProtoAck = HookEvent(ME_PROTO_ACK, ProtoAck);
+ g_hProtoContactIsTyping = HookEvent(ME_PROTO_CONTACTISTYPING, ProtoContactIsTyping);
+ g_hOptionsInitialize = HookEvent(ME_OPT_INITIALISE, InitializeOptions);
+
+ return CTooltipNotify::GetObjInstance()->ModulesLoaded(wParam, lParam);
+}
+
+
+int ProtoContactIsTyping(WPARAM wParam, LPARAM lParam)
+{
+ return CTooltipNotify::GetObjInstance()->ProtoContactIsTyping(wParam, lParam);
+}
+
+
+int ProtoAck(WPARAM wParam, LPARAM lParam)
+{
+ return CTooltipNotify::GetObjInstance()->ProtoAck(wParam, lParam);
+}
+
+
+int ContactSettingChanged(WPARAM wParam, LPARAM lParam)
+{
+ return CTooltipNotify::GetObjInstance()->ContactSettingChanged(wParam, lParam);
+}
+
+
+int InitializeOptions(WPARAM wParam, LPARAM lParam)
+{
+ return CTooltipNotify::GetObjInstance()->InitializeOptions(wParam, lParam);
+}
+
+
+
+
+
diff --git a/plugins/TooltipNotify/src/main.rc b/plugins/TooltipNotify/src/main.rc
new file mode 100644
index 0000000000..fe1fbad85f
--- /dev/null
+++ b/plugins/TooltipNotify/src/main.rc
@@ -0,0 +1,204 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Russian resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
+#ifdef _WIN32
+LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
+#pragma code_page(1251)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""windows.h""\r\n"
+ "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "#include ""version.rc2""\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Russian resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_PROTOS DIALOGEX 0, 0, 106, 138
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
+ WS_CAPTION | WS_SYSMENU
+CAPTION "Select protocols"
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,28,117,50,14
+ CONTROL "List1",IDC_PROTOS,"SysListView32",LVS_LIST |
+ LVS_SINGLESEL | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER |
+ WS_BORDER | WS_TABSTOP,7,7,91,103
+END
+
+IDD_CONTACTS DIALOGEX 0, 0, 284, 234
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP |
+ WS_CAPTION | WS_SYSMENU
+CAPTION "Choose contacts..."
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "Allow tooltip notifications for the following users:",
+ IDC_STATIC,8,9,268,9
+ CONTROL "",IDC_CLIST,"CListControl",WS_TABSTOP | 0x3da,7,23,270,
+ 180,WS_EX_CLIENTEDGE
+ DEFPUSHBUTTON "OK",IDOK,171,213,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,227,213,50,14
+END
+
+IDD_OPTIONS DIALOGEX 0, 0, 316, 250
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ GROUPBOX "Notify upon the following events",IDC_STATIC,5,7,304,32,
+ WS_GROUP
+ CONTROL "Online",IDC_ONLINE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,15,17,46,14
+ CONTROL "Offline",IDC_OFFLINE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,66,17,46,14
+ CONTROL "All other",IDC_OTHER,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,117,17,52,14
+ CONTROL "Typing",IDC_TYPING,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,174,17,51,14
+ PUSHBUTTON "Protocols",IDC_SEL_PROTO,254,162,46,14
+ LTEXT "Suppress notifications upon connection for",IDC_STATIC,
+ 120,93,137,9
+ EDITTEXT IDC_DELAYONCONN,259,91,27,12,ES_RIGHT | ES_NUMBER
+ CONTROL "Spin1",IDC_DELAYONCONNSPIN,"msctls_updown32",
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS | UDS_NOTHOUSANDS,280,86,11,14
+ LTEXT "sec",IDC_STATIC,290,93,12,10
+ CONTROL "Prefix proto name",IDC_PREFIX_PROTO,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,15,163,70,11
+ GROUPBOX "Duration",IDC_GB_DURATION,5,43,304,30
+ LTEXT "Show tooltip for",IDC_STATIC,15,55,51,10
+ EDITTEXT IDC_DURATION,69,53,36,12,ES_RIGHT | ES_NUMBER
+ CONTROL "Spin1",IDC_DURATIONSPIN,"msctls_updown32",
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS | UDS_NOTHOUSANDS,100,47,10,14
+ LTEXT "ms",IDC_STATIC,109,55,14,10
+ CONTROL "Duration x2 upon online event",IDC_X2,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,159,55,137,10
+ GROUPBOX "Double click on tooltip",IDC_GB_DBLCLICK,5,78,103,54
+ CONTROL "Shows/Hides CList",IDC_RB_CLIST,"Button",
+ BS_AUTORADIOBUTTON | WS_TABSTOP,15,93,83,11
+ CONTROL "Opens message dialog",IDC_RB_MSGDLG,"Button",
+ BS_AUTORADIOBUTTON | WS_TABSTOP,15,112,88,11
+ GROUPBOX "Behavior",IDC_STATIC,113,78,196,54
+ GROUPBOX "Misc",IDC_STATIC,5,136,304,44
+ CONTROL "Obey 'Suppress online notification' settings",
+ IDC_CONJSOLN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,119,
+ 112,164,11
+ CONTROL "Auto positioning",IDC_AUTOPOS,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,15,147,75,11
+ CONTROL "Transparent input",IDC_TRANSP_INPUT,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,96,147,81,11
+ PUSHBUTTON "Preview",IDC_PREVIEW,201,162,46,14
+ GROUPBOX "Translucency options (Windows 2000/XP only)",
+ IDC_GB_TRANSP,5,185,304,34
+ CONTROL "Transparent tooltip",IDC_TRANSPARENCY,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,15,200,73,9
+ CONTROL "Slider1",IDC_TRANSPARENCY_SLIDER,"msctls_trackbar32",
+ TBS_TOP | TBS_NOTICKS | WS_TABSTOP,94,199,170,11
+ LTEXT "000%",IDC_TRANSPERC,273,201,22,9
+ PUSHBUTTON "Contacts",IDC_IGNORE,254,144,46,14
+ CONTROL "Idle",IDC_IDLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 227,17,51,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_PROTOS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 99
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 131
+ END
+
+ IDD_CONTACTS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 277
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 227
+ END
+
+ IDD_OPTIONS, DIALOG
+ BEGIN
+ VERTGUIDE, 5
+ VERTGUIDE, 309
+ HORZGUIDE, 246
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#include "version.rc"
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/TooltipNotify/src/resource.h b/plugins/TooltipNotify/src/resource.h
new file mode 100644
index 0000000000..d67e8c5746
--- /dev/null
+++ b/plugins/TooltipNotify/src/resource.h
@@ -0,0 +1,47 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by main.rc
+//
+#define IDD_OPTIONS 101
+#define IDD_PROTOS 103
+#define IDD_CONTACTS 104
+#define IDC_ONLINE 1002
+#define IDC_OTHER 1003
+#define IDC_OFFLINE 1004
+#define IDC_TYPING 1006
+#define IDC_IDLE 1007
+#define IDC_X2 1011
+#define IDC_CONJSOLN 1012
+#define IDC_PROTOS 1014
+#define IDC_SEL_PROTO 1015
+#define IDC_AUTOPOS 1016
+#define IDC_TRANSPARENCY_SLIDER 1017
+#define IDC_TRANSPERC 1018
+#define IDC_TRANSPARENCY 1019
+#define IDC_GB_TRANSP 1020
+#define IDC_TRANSP_INPUT 1021
+#define IDC_PREVIEW 1025
+#define IDC_RB_CLIST 1026
+#define IDC_RB_MSGDLG 1027
+#define IDC_IGNORE 1028
+#define IDC_GB_DBLCLICK 1033
+#define IDC_BALLONTIP 1034
+#define IDC_GB_DURATION 1035
+#define IDC_PREFIX_PROTO 1039
+#define IDC_CLIST 1040
+#define IDC_DURATION 1283
+#define IDC_DURATIONSPIN 1284
+#define IDC_DELAYONCONN 1285
+#define IDC_DELAYONCONNSPIN 1286
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 105
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1042
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/TooltipNotify/src/stdafx.cpp b/plugins/TooltipNotify/src/stdafx.cpp
new file mode 100644
index 0000000000..cb27709b24
--- /dev/null
+++ b/plugins/TooltipNotify/src/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// ttnotify.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/plugins/TooltipNotify/src/stdafx.h b/plugins/TooltipNotify/src/stdafx.h
new file mode 100644
index 0000000000..d77c5a3037
--- /dev/null
+++ b/plugins/TooltipNotify/src/stdafx.h
@@ -0,0 +1,37 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#define _WIN32_WINNT 0x0500
+
+// Windows header files
+#include <windows.h>
+#include <commctrl.h>
+#include <commdlg.h>
+
+// C/C++ header files
+#include <cassert>
+#include <algorithm>
+#include <vector>
+
+// Miranda IM header files
+#include <newpluginapi.h>
+#include <m_clist.h>
+#include <m_skin.h>
+#include <m_system.h>
+#include <m_database.h>
+#include <m_clui.h>
+#include <m_ignore.h>
+#include <m_options.h>
+#include <m_protosvc.h>
+#include <m_langpack.h>
+#include <m_utils.h>
+#include <m_clc.h>
+#include <m_fontservice.h>
+
+#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) \ No newline at end of file
diff --git a/plugins/TooltipNotify/src/version.h b/plugins/TooltipNotify/src/version.h
new file mode 100644
index 0000000000..9de12d2cee
--- /dev/null
+++ b/plugins/TooltipNotify/src/version.h
@@ -0,0 +1,11 @@
+/*********************************************************************/
+//
+// Tooltip Notify version file
+//
+/*********************************************************************/
+
+
+#define MAJOR 0
+#define MINOR 6
+#define BUILD 0
+#define REVISION 47
diff --git a/plugins/TooltipNotify/src/version.rc b/plugins/TooltipNotify/src/version.rc
new file mode 100644
index 0000000000..da191b4d06
--- /dev/null
+++ b/plugins/TooltipNotify/src/version.rc
@@ -0,0 +1,52 @@
+//
+// version.rc2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+#error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+#include "version.h"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION MAJOR,MINOR,BUILD,REVISION
+ PRODUCTVERSION MAJOR,MINOR,BUILD,REVISION
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", "Shows a small tooltip above system tray area when a contact status is changed."
+ VALUE "CompanyName", "Gneedah software"
+ VALUE "FileDescription", "Tooltip Notify plugin for Miranda IM."
+ VALUE "FileVersion", "*,*,*,*"
+ VALUE "InternalName", "ttnotify.dll"
+ VALUE "LegalCopyright", " 2004-2008 Gneedah software"
+ VALUE "OriginalFilename", "ttnotify.dll"
+ VALUE "ProductName", "Tooltip Notify"
+ VALUE "ProductVersion", "*,*,*,*"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/plugins/TooltipNotify/ttnotify_10.sln b/plugins/TooltipNotify/ttnotify_10.sln
new file mode 100644
index 0000000000..16bad206d7
--- /dev/null
+++ b/plugins/TooltipNotify/ttnotify_10.sln
@@ -0,0 +1,25 @@
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ttnotify", "ttnotify_10.vcxproj", "{1948EAEA-4C25-4F6B-AD9E-5891F656EADA}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug-Unicode|Win32 = Debug-Unicode|Win32
+ Release|Win32 = Release|Win32
+ Release-Unicode|Win32 = Release-Unicode|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1948EAEA-4C25-4F6B-AD9E-5891F656EADA}.Debug|Win32.ActiveCfg = Debug|Win32
+ {1948EAEA-4C25-4F6B-AD9E-5891F656EADA}.Debug|Win32.Build.0 = Debug|Win32
+ {1948EAEA-4C25-4F6B-AD9E-5891F656EADA}.Debug-Unicode|Win32.ActiveCfg = Debug-Unicode|Win32
+ {1948EAEA-4C25-4F6B-AD9E-5891F656EADA}.Debug-Unicode|Win32.Build.0 = Debug-Unicode|Win32
+ {1948EAEA-4C25-4F6B-AD9E-5891F656EADA}.Release|Win32.ActiveCfg = Release|Win32
+ {1948EAEA-4C25-4F6B-AD9E-5891F656EADA}.Release|Win32.Build.0 = Release|Win32
+ {1948EAEA-4C25-4F6B-AD9E-5891F656EADA}.Release-Unicode|Win32.ActiveCfg = Release-Unicode|Win32
+ {1948EAEA-4C25-4F6B-AD9E-5891F656EADA}.Release-Unicode|Win32.Build.0 = Release-Unicode|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/plugins/TooltipNotify/ttnotify_10.vcxproj b/plugins/TooltipNotify/ttnotify_10.vcxproj
new file mode 100644
index 0000000000..dc421eac67
--- /dev/null
+++ b/plugins/TooltipNotify/ttnotify_10.vcxproj
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug-Unicode|Win32">
+ <Configuration>Debug-Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release-Unicode|Win32">
+ <Configuration>Release-Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>ttnotify</ProjectName>
+ <ProjectGuid>{1948EAEA-4C25-4F6B-AD9E-5891F656EADA}</ProjectGuid>
+ <RootNamespace>ttnotify</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release-Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug-Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release-Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug-Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug-Unicode|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug-Unicode|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug-Unicode|Win32'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release-Unicode|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release-Unicode|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release-Unicode|Win32'">false</LinkIncremental>
+ <IncludePath Condition="'$(Configuration)|$(Platform)'=='Release-Unicode|Win32'">D:\SVN\Miranda\Trunk\miranda\include;$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <PreBuildEvent>
+ <Message>Updating revision...</Message>
+ <Command>SubWCRev . src\version.wcr src\version.h</Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TTNOTIFY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(OutDir)ttnotify.pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <PreBuildEvent>
+ <Message>Updating revision...</Message>
+ <Command>SubWCRev . src\version.wcr src\version.h</Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;TTNOTIFY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ </ClCompile>
+ <Link>
+ <ShowProgress>NotSet</ShowProgress>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug-Unicode|Win32'">
+ <PreBuildEvent>
+ <Message>Updating revision...</Message>
+ <Command>SubWCRev . src\version.wcr src\version.h</Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;TTNOTIFY_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(OutDir)ttnotify.pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release-Unicode|Win32'">
+ <PreBuildEvent>
+ <Command>
+ </Command>
+ </PreBuildEvent>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;TTNOTIFY_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <StringPooling>true</StringPooling>
+ </ClCompile>
+ <Link>
+ <ShowProgress>NotSet</ShowProgress>
+ <IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="src\DbHelpers.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug-Unicode|Win32'">Use</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release-Unicode|Win32'">Use</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\main.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug-Unicode|Win32'">Use</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release-Unicode|Win32'">Use</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\stdafx.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug-Unicode|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release-Unicode|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\Tooltip.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug-Unicode|Win32'">Use</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release-Unicode|Win32'">Use</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\TooltipNotify.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug-Unicode|Win32'">Use</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Use</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release-Unicode|Win32'">Use</PrecompiledHeader>
+ <AssemblerOutput Condition="'$(Configuration)|$(Platform)'=='Release-Unicode|Win32'">AssemblyAndSourceCode</AssemblerOutput>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Use</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="src\Utils.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\DbHelpers.h" />
+ <ClInclude Include="src\resource.h" />
+ <ClInclude Include="src\Settings.h" />
+ <ClInclude Include="src\stdafx.h" />
+ <ClInclude Include="src\Tooltip.h" />
+ <ClInclude Include="src\TooltipNotify.h" />
+ <ClInclude Include="src\Utils.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="src\main.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="src\version.rc2" />
+ <None Include="src\version.wcr" />
+ <None Include="doc\todo.txt" />
+ <None Include="doc\tt_wnd_def_style.txt" />
+ <None Include="doc\ttnotify-readme.txt" />
+ <None Include="doc\ttnotify_translation.txt" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/TooltipNotify/ttnotify_10.vcxproj.filters b/plugins/TooltipNotify/ttnotify_10.vcxproj.filters
new file mode 100644
index 0000000000..f756faf1c4
--- /dev/null
+++ b/plugins/TooltipNotify/ttnotify_10.vcxproj.filters
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="src">
+ <UniqueIdentifier>{c12316ee-1d9e-470b-a9d4-2f96e30ea10d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="doc">
+ <UniqueIdentifier>{9fe30d32-97fa-41fc-8586-9f52a8580112}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="src\DbHelpers.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="src\main.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="src\stdafx.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="src\Tooltip.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="src\TooltipNotify.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ <ClCompile Include="src\Utils.cpp">
+ <Filter>src</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="src\DbHelpers.h">
+ <Filter>src</Filter>
+ </ClInclude>
+ <ClInclude Include="src\resource.h">
+ <Filter>src</Filter>
+ </ClInclude>
+ <ClInclude Include="src\Settings.h">
+ <Filter>src</Filter>
+ </ClInclude>
+ <ClInclude Include="src\stdafx.h">
+ <Filter>src</Filter>
+ </ClInclude>
+ <ClInclude Include="src\Tooltip.h">
+ <Filter>src</Filter>
+ </ClInclude>
+ <ClInclude Include="src\TooltipNotify.h">
+ <Filter>src</Filter>
+ </ClInclude>
+ <ClInclude Include="src\Utils.h">
+ <Filter>src</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="src\main.rc">
+ <Filter>src</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="src\version.rc2">
+ <Filter>src</Filter>
+ </None>
+ <None Include="src\version.wcr">
+ <Filter>src</Filter>
+ </None>
+ <None Include="doc\todo.txt">
+ <Filter>doc</Filter>
+ </None>
+ <None Include="doc\tt_wnd_def_style.txt">
+ <Filter>doc</Filter>
+ </None>
+ <None Include="doc\ttnotify-readme.txt">
+ <Filter>doc</Filter>
+ </None>
+ <None Include="doc\ttnotify_translation.txt">
+ <Filter>doc</Filter>
+ </None>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/UserGuide/UserGuide_10.sln b/plugins/UserGuide/UserGuide_10.sln
new file mode 100644
index 0000000000..6e11d96610
--- /dev/null
+++ b/plugins/UserGuide/UserGuide_10.sln
@@ -0,0 +1,25 @@
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UserGuide", "UserGuide_10.vcxproj", "{92E3BDEE-DD17-4619-AD61-70C0ADE04217}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {92E3BDEE-DD17-4619-AD61-70C0ADE04217}.Debug|Win32.ActiveCfg = Debug|Win32
+ {92E3BDEE-DD17-4619-AD61-70C0ADE04217}.Debug|Win32.Build.0 = Debug|Win32
+ {92E3BDEE-DD17-4619-AD61-70C0ADE04217}.Debug|x64.ActiveCfg = Debug|x64
+ {92E3BDEE-DD17-4619-AD61-70C0ADE04217}.Debug|x64.Build.0 = Debug|x64
+ {92E3BDEE-DD17-4619-AD61-70C0ADE04217}.Release|Win32.ActiveCfg = Release|Win32
+ {92E3BDEE-DD17-4619-AD61-70C0ADE04217}.Release|Win32.Build.0 = Release|Win32
+ {92E3BDEE-DD17-4619-AD61-70C0ADE04217}.Release|x64.ActiveCfg = Release|x64
+ {92E3BDEE-DD17-4619-AD61-70C0ADE04217}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/plugins/UserGuide/UserGuide_10.vcxproj b/plugins/UserGuide/UserGuide_10.vcxproj
new file mode 100644
index 0000000000..ac05a53d99
--- /dev/null
+++ b/plugins/UserGuide/UserGuide_10.vcxproj
@@ -0,0 +1,285 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>UserGuide</ProjectName>
+ <ProjectGuid>{92E3BDEE-DD17-4619-AD61-70C0ADE04217}</ProjectGuid>
+ <RootNamespace>UserGuide</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release/UserGuide.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>false</OmitFramePointers>
+ <EnableFiberSafeOptimizations>false</EnableFiberSafeOptimizations>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;UserGuide_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <BrowseInformation>
+ </BrowseInformation>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0419</Culture>
+ </ResourceCompile>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)UserGuide.pdb</ProgramDatabaseFile>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ </Link>
+ <Xdcmake>
+ <OutputFile>$(IntDir)$(TargetName).xml</OutputFile>
+ </Xdcmake>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Release/UserGuide.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>false</OmitFramePointers>
+ <EnableFiberSafeOptimizations>false</EnableFiberSafeOptimizations>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;UserGuide_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <BrowseInformation>
+ </BrowseInformation>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0419</Culture>
+ </ResourceCompile>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)UserGuide.pdb</ProgramDatabaseFile>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ </Link>
+ <Xdcmake>
+ <OutputFile>$(IntDir)$(TargetName).xml</OutputFile>
+ </Xdcmake>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Debug/UserGuide.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;UserGuide_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <BrowseInformation>true</BrowseInformation>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0419</Culture>
+ </ResourceCompile>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)UserGuide.pdb</ProgramDatabaseFile>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <Xdcmake>
+ <OutputFile>$(IntDir)$(TargetName).xml</OutputFile>
+ </Xdcmake>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TypeLibraryName>.\Debug/UserGuide.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;UserGuide_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <BrowseInformation>true</BrowseInformation>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0419</Culture>
+ </ResourceCompile>
+ <Link>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)UserGuide.pdb</ProgramDatabaseFile>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ <Xdcmake>
+ <OutputFile>$(IntDir)$(TargetName).xml</OutputFile>
+ </Xdcmake>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="main.c">
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="commonheaders.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/UserGuide/UserGuide_10.vcxproj.filters b/plugins/UserGuide/UserGuide_10.vcxproj.filters
new file mode 100644
index 0000000000..a9fe7c62a4
--- /dev/null
+++ b/plugins/UserGuide/UserGuide_10.vcxproj.filters
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{dcd1a3fe-3ade-453c-9845-9cb074da6b5b}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{72da96a4-67f9-49cc-94d3-6730544c949f}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{34beb523-18cd-4f3d-85db-ec309fbf1d1a}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="main.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="commonheaders.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/UserGuide/commonheaders.h b/plugins/UserGuide/commonheaders.h
new file mode 100644
index 0000000000..4f7479c2ef
--- /dev/null
+++ b/plugins/UserGuide/commonheaders.h
@@ -0,0 +1,10 @@
+#include <windows.h>
+#include <newpluginapi.h>
+#include <m_langpack.h>
+#include <m_system.h>
+#include <m_database.h>
+#include <m_clist.h>
+#include <m_skin.h>
+#include <m_utils.h>
+
+#define MIID_USERGUIDE {0x297ec1e7, 0x41b7, 0x41f9, { 0xbb, 0x91, 0xef, 0xa9, 0x50, 0x28, 0xf1, 0x6c }} //297ec1e7-41b7-41f9-bb91-efa95028f16c
diff --git a/plugins/UserGuide/main.c b/plugins/UserGuide/main.c
new file mode 100644
index 0000000000..853658300c
--- /dev/null
+++ b/plugins/UserGuide/main.c
@@ -0,0 +1,130 @@
+#include "commonheaders.h"
+
+struct MM_INTERFACE mmi;
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+HANDLE hModulesLoaded;
+
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ "User Guide Plugin",
+ PLUGIN_MAKE_VERSION(0,0,0,1),
+ "This plug-in adds the main menu item used to view miranda-im pack user guide.",
+ "Yasnovidyashii",
+ "yasnovidyashii@gmail.com",
+ " 2009 Mikhail Yuriev",
+ "http://miranda-im.org/",
+ 0, //not transient
+ 0, //doesn't replace anything built-in
+ // Generate your own unique id for your plugin.
+ // Do not use this UUID!
+ // Use uuidgen.exe to generate the uuuid
+ MIID_USERGUIDE
+};
+
+static INT_PTR ShowGuideFile(WPARAM wParam,LPARAM lParam)
+{
+ DBVARIANT dbv = {0};
+ int iRes;
+
+ LPCSTR pszEmptySting="";
+ LPSTR pszDirName, pszDirNameEx, pszFileName,pszDivider;
+
+ REPLACEVARSDATA dat = {0};
+ dat.cbSize = sizeof( dat );
+ dat.dwFlags = 0;
+
+ pszDirName=(LPSTR)mir_alloc(250*sizeof(CHAR));
+ pszFileName=(LPSTR)mir_alloc(250*sizeof(CHAR));
+
+ iRes = DBGetContactSettingString(NULL,"UserGuide","PathToHelpFile",&dbv);
+
+ if (iRes!=0)
+ {
+ strcpy(pszDirName, "%miranda_path%\\Plugins");
+ strcpy(pszFileName, "UserGuide.chm");
+ }
+ else
+ if(strcmp((dbv.pszVal),pszEmptySting)==0)
+ {
+ strcpy(pszDirName, "%miranda_path%\\Plugins");
+ strcpy(pszFileName, "UserGuide.chm");
+ mir_free(dbv.pszVal);
+ }
+ else
+ {
+ pszDivider = strrchr(dbv.pszVal, '\\');
+ if (pszDivider == NULL)
+ {
+ pszDirName = "";
+ strncpy(pszFileName, dbv.pszVal, strlen(dbv.pszVal) );
+ }
+ else
+ {
+ strncpy(pszFileName, pszDivider+1, strlen(dbv.pszVal)-strlen(pszDivider)-1);
+ pszFileName[strlen(dbv.pszVal)-strlen(pszDivider)-1] = 0;
+ strncpy(pszDirName, dbv.pszVal, pszDivider-dbv.pszVal);
+ pszDirName[pszDivider-dbv.pszVal] = 0;
+ }
+ mir_free(dbv.pszVal);
+ }
+ if (ServiceExists(MS_UTILS_REPLACEVARS))
+ pszDirNameEx = (char *) CallService(MS_UTILS_REPLACEVARS,(WPARAM)pszDirName,(LPARAM)&dat);
+ else
+ pszDirNameEx = mir_strdup(pszDirName);
+
+ ShellExecuteA(NULL,"open",pszFileName,NULL,pszDirNameEx,SW_SHOW);
+ mir_free(pszDirName);
+ mir_free(pszFileName);
+ mir_free(pszDirNameEx);
+ return 0;
+}
+
+int ModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ CLISTMENUITEM mi;
+
+ CreateServiceFunction("UserGuide/ShowGuide",ShowGuideFile);
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize=sizeof(mi);
+ mi.position=500000;
+ mi.flags=0;
+ mi.hIcon=LoadSkinnedIcon(SKINICON_OTHER_HELP);
+ mi.pszName=LPGEN("User Guide");
+ mi.pszService="UserGuide/ShowGuide";
+ CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi);
+
+ return 0;
+}
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInst=hinstDLL;
+ return TRUE;
+}
+
+
+__declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+static const MUUID interfaces[] = {MIID_USERGUIDE, MIID_LAST};
+__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ pluginLink=link;
+ mir_getMMI(&mmi);
+ hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED,ModulesLoaded);
+ return 0;
+}
+
+int __declspec(dllexport) Unload(void)
+{
+ UnhookEvent(hModulesLoaded);
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/w7ui/clistproxywindow.cpp b/plugins/w7ui/clistproxywindow.cpp
new file mode 100644
index 0000000000..12e5b476ed
--- /dev/null
+++ b/plugins/w7ui/clistproxywindow.cpp
@@ -0,0 +1,292 @@
+#include "headers.h"
+
+CClistProxyWindow *g_clistProxyWnd = 0;
+extern ITaskbarList3 *g_pTaskbarList;
+
+CClistProxyWindow::CClistProxyWindow() : m_overlayEvents(5)
+{
+ g_clistProxyWnd = this;
+
+ m_activeOverlay = 0;
+ m_overlayIcon = 0;
+ m_overlayText = 0;
+
+ SetWindowText(hwnd(), _T("Miranda IM"));
+ SendMessage(hwnd(), WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedIcon(SKINICON_OTHER_MIRANDA));
+ SendMessage(hwnd(), WM_SETICON, ICON_SMALL, (LPARAM)LoadSkinnedIcon(SKINICON_OTHER_MIRANDA));
+
+ SetEventHook(ME_CLIST_STATUSMODECHANGE, &CClistProxyWindow::OnStatusModeChanged);
+ SetEventHook(ME_AV_MYAVATARCHANGED, &CClistProxyWindow::OnAvatarChanged);
+ SetEventHook(ME_SYSTEM_MODULESLOADED, &CClistProxyWindow::OnModulesLoaded);
+ SetEventHook(ME_PROTO_ACCLISTCHANGED, &CClistProxyWindow::OnAccListChanged);
+
+ SetTimer(1, 500);
+}
+
+CClistProxyWindow::~CClistProxyWindow()
+{
+ KillObjectEventHooks(this);
+}
+
+int __cdecl CClistProxyWindow::OnStatusModeChanged(WPARAM wParam, LPARAM lParam)
+{
+ Update();
+ return 0;
+}
+int __cdecl CClistProxyWindow::OnAvatarChanged(WPARAM wParam, LPARAM lParam)
+{
+ Update();
+ return 0;
+}
+int __cdecl CClistProxyWindow::OnModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ Update();
+ return 0;
+}
+int __cdecl CClistProxyWindow::OnAccListChanged(WPARAM wParam, LPARAM lParam)
+{
+ Update();
+ return 0;
+}
+
+HANDLE CClistProxyWindow::SetEventHook(char *evt, int (__cdecl CClistProxyWindow::*fn)(WPARAM, LPARAM))
+{
+ return HookEventObj(evt, *(MIRANDAHOOKOBJ *)&fn, this);
+}
+
+void CClistProxyWindow::Flash()
+{
+ FlashWindow(hwnd(), TRUE);
+}
+
+void CClistProxyWindow::SetOverlayIcon(HICON hIcon)
+{
+ m_overlayIcon = hIcon;
+ m_overlayIconHandle = 0;
+}
+
+void CClistProxyWindow::SetOverlayIconHandle(HANDLE hIcolibIcon)
+{
+ m_overlayIcon = 0;
+ m_overlayIconHandle = hIcolibIcon;
+}
+
+void CClistProxyWindow::AddOverlayEvent(int idx)
+{
+ m_overlayEvents[idx].Push();
+}
+
+void CClistProxyWindow::RemoveOverlayEvent(int idx)
+{
+ m_overlayEvents[idx].Pop();
+}
+
+int CClistProxyWindow::AllocateOverlayEvent(HANDLE hIcolibIcon)
+{
+ m_overlayEvents.insert(new COverlayEventSlot(hIcolibIcon, _T("")), m_overlayEvents.getCount());
+ return m_overlayEvents.getCount() - 1;
+}
+
+void CClistProxyWindow::Update()
+{
+ AddButton(LoadSkinnedIcon(SKINICON_OTHER_MIRANDA), TranslateT("Menu"), -1);
+
+ int nAccounts = 0;
+ PROTOACCOUNT **accounts;
+ ProtoEnumAccounts(&nAccounts, &accounts);
+ for (int i = 0; i < nAccounts; ++i)
+ {
+ if (!accounts[i]->bIsEnabled || !accounts[i]->bIsVisible || !accounts[i]->ppro || !(accounts[i]->ppro->GetCaps(PFLAGNUM_1) & PF1_IM))
+ continue;
+
+ HICON hIcon = LoadSkinnedProtoIcon(accounts[i]->szModuleName, CallProtoService(accounts[i]->szModuleName, PS_GETSTATUS, 0, 0));
+ AddButton(hIcon, accounts[i]->tszAccountName, (INT_PTR)accounts[i]->tszAccountName);
+ }
+ UpdateButtons(g_pTaskbarList);
+
+ InvalidateThumbnail();
+}
+
+void CClistProxyWindow::OnActivate(HWND hwndFrom)
+{
+ CallService(MS_CLIST_SHOWHIDE, 0, 0);
+
+ HWND hwndClui = (HWND)CallService(MS_CLUI_GETHWND, 0, 0);
+ if (hwndFrom != hwndClui && !IsIconic(hwndClui) && IsWindowVisible(hwndClui))
+ SetForegroundWindow(hwndClui);
+ else
+ SetForegroundWindow(NULL);
+}
+
+void CClistProxyWindow::OnToolbar(int id, INT_PTR data)
+{
+ POINT pt; GetCursorPos(&pt);
+ HMENU hMenu = NULL;
+ HWND hwndClui = (HWND)CallService(MS_CLUI_GETHWND, 0, 0);
+
+ switch (data)
+ {
+ case -1:
+ {
+ hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDMAIN, 0, 0);
+ break;
+ }
+
+ default:
+ {
+ hMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS, 0, 0);
+ int nItems = GetMenuItemCount(hMenu);
+ for (int i = 0; i < nItems; ++i)
+ {
+ TCHAR buf[128];
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_STRING|MIIM_SUBMENU;
+ mii.dwTypeData = buf;
+ mii.cch = SIZEOF(buf);
+ GetMenuItemInfo(hMenu, i, TRUE, &mii);
+
+ if (mii.hSubMenu && !lstrcmp(mii.dwTypeData, (TCHAR*)data))
+ {
+ hMenu = mii.hSubMenu;
+ break;
+ }
+ }
+ }
+ }
+
+ SetForegroundWindow(hwndClui);
+ TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hwndClui, NULL);
+}
+
+void CClistProxyWindow::OnRenderThumbnail(int width, int height)
+{
+ HBITMAP hbmp = CreateDwmBitmap(width, height);
+ HDC hdc = CreateCompatibleDC(0);
+ SelectObject(hdc, hbmp);
+
+ RGBQUAD rgb0, rgb1;
+ rgb0.rgbRed = 0; rgb0.rgbGreen = 0; rgb0.rgbBlue = 0;
+ rgb1.rgbRed = 19; rgb1.rgbGreen = 58; rgb1.rgbBlue = 89;
+ DrawGradient(hdc, 0, 0, width, height, &rgb0, &rgb1);
+
+ HFONT hfntSave = (HFONT)SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
+ SetTextColor(hdc, RGB(255, 255, 255));
+ SetBkMode(hdc, TRANSPARENT);
+
+ RECT rc;
+ SIZE sz;
+ SetRect(&rc, 5, 5, width-10, height-10);
+
+ int avatarWidth = 0;
+ int avatarHeight = 0;
+ if (true)
+ {
+ AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETMYAVATAR, 0, (LPARAM)"");
+ if (ace && (ace != (AVATARCACHEENTRY *)CALLSERVICE_NOTFOUND))
+ {
+ if (ace->bmWidth < width / 4)
+ {
+ avatarWidth = ace->bmWidth;
+ avatarHeight = ace->bmHeight;
+ } else
+ {
+ avatarWidth = width / 4;
+ avatarHeight = avatarWidth * ace->bmHeight / ace->bmWidth;
+ }
+
+ AVATARDRAWREQUEST avdr = {0};
+ avdr.cbSize = sizeof(avdr);
+ avdr.hContact = NULL;
+ avdr.hTargetDC = hdc;
+ avdr.rcDraw = rc;
+ avdr.rcDraw.bottom = avdr.rcDraw.top + avatarHeight;
+ avdr.rcDraw.right = avdr.rcDraw.left + avatarWidth;
+ avdr.dwFlags = AVDRQ_FALLBACKPROTO | AVDRQ_FORCEALPHA | AVDRQ_OWNPIC;
+ avdr.szProto = "";
+
+ avdr.alpha = 255;
+ CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&avdr);
+
+ rc.left += avatarWidth + 5;
+ }
+ }
+
+ int nAccounts = 0;
+ PROTOACCOUNT **accounts;
+ ProtoEnumAccounts(&nAccounts, &accounts);
+ for (int i = 0; i < nAccounts; ++i)
+ {
+ if (!accounts[i]->bIsEnabled /*|| !accounts[i]->ppro || !(accounts[i]->ppro->GetCaps(PFLAGNUM_1) & PF1_IM)*/)
+ continue;
+
+ char *proto = accounts[i]->szModuleName;
+
+ if (true)
+ {
+ TCHAR name[128]; name[0] = 0;
+
+ CONTACTINFO ci = {0};
+ ci.cbSize = sizeof(ci);
+ ci.hContact = NULL;
+ ci.szProto = proto;
+ ci.dwFlag = CNF_UNIQUEID | CNF_TCHAR;
+ if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci))
+ {
+ switch (ci.type)
+ {
+ case CNFT_ASCIIZ:
+ mir_sntprintf(name, SIZEOF(name), _T("%s - %s"), accounts[i]->tszAccountName, ci.pszVal);
+ mir_free((void *)ci.pszVal);
+ break;
+ case CNFT_DWORD:
+ mir_sntprintf(name, SIZEOF(name), _T("%s - %u"), accounts[i]->tszAccountName, ci.dVal);
+ break;
+ }
+
+ } else
+ {
+ lstrcpyn(name, accounts[i]->tszAccountName, SIZEOF(name));
+ }
+
+ RECT rcText = rc;
+ rcText.left += 20;
+ DrawText(hdc, name, -1, &rcText, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK|DT_TOP|DT_SINGLELINE);
+ GetTextExtentPoint32(hdc, name, lstrlen(name), &sz);
+ }
+
+ if (true)
+ {
+ HICON hIcon = LoadSkinnedProtoIcon(proto, CallProtoService(proto, PS_GETSTATUS, 0, 0));
+ DrawIconEx(hdc, rc.left, rc.top + (sz.cy - 16) / 2, hIcon, 16, 16, 0, NULL, DI_NORMAL);
+ }
+
+ rc.top += sz.cy + 5;
+ }
+
+ SelectObject(hdc, hfntSave);
+
+ DeleteDC(hdc);
+ MakeBitmapOpaque(hbmp);
+ SetThumbnail(hbmp);
+ DeleteObject(hbmp);
+}
+
+void CClistProxyWindow::OnClose()
+{
+ CallService("CloseAction", NULL, NULL);
+}
+
+void CClistProxyWindow::OnTimer(int id)
+{
+ HANDLE hIcolibItem = m_overlayIconHandle;
+ for (m_activeOverlay = (m_activeOverlay + 1) % (m_overlayEvents.getCount() + 1); m_activeOverlay < m_overlayEvents.getCount(); ++m_activeOverlay)
+ if (m_overlayEvents[m_activeOverlay])
+ {
+ hIcolibItem = m_overlayEvents[m_activeOverlay].GetIcon();
+ break;
+ }
+
+ HICON hIcon = hIcolibItem ? (HICON)CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)hIcolibItem) : m_overlayIcon;
+ if (hIcon) g_pTaskbarList->SetOverlayIcon(hwnd(), hIcon, L"");
+}
diff --git a/plugins/w7ui/clistproxywindow.h b/plugins/w7ui/clistproxywindow.h
new file mode 100644
index 0000000000..153c59089b
--- /dev/null
+++ b/plugins/w7ui/clistproxywindow.h
@@ -0,0 +1,64 @@
+#ifndef clistproxywindow_h__
+#define clistproxywindow_h__
+
+class CClistProxyWindow: public CDwmWindow
+{
+public:
+ CClistProxyWindow();
+ ~CClistProxyWindow();
+
+ void Flash();
+ void SetOverlayIcon(HICON hIcon);
+ void SetOverlayIconHandle(HANDLE hIcolibIcon);
+ void AddOverlayEvent(int idx);
+ void RemoveOverlayEvent(int idx);
+ int AllocateOverlayEvent(HANDLE hIcolibIcon);
+
+private:
+ class COverlayEventSlot
+ {
+ private:
+ HANDLE m_hIcolibItem;
+ TCHAR *m_overlayText;
+ int m_level;
+
+ public:
+ COverlayEventSlot(HANDLE hIcolibItem, TCHAR *overlayText)
+ {
+ m_hIcolibItem = hIcolibItem;
+ m_overlayText = mir_tstrdup(overlayText);
+ m_level = 0;
+ }
+ ~COverlayEventSlot() { mir_free(m_overlayText); }
+ void Push() { m_level++; }
+ void Pop() { if (m_level > 0) m_level--; }
+ operator bool() { return m_level > 0; }
+ HANDLE GetIcon() { return m_hIcolibItem; }
+ };
+
+ int m_activeOverlay;
+ HICON m_overlayIcon;
+ HANDLE m_overlayIconHandle;
+ TCHAR *m_overlayText;
+ OBJLIST<COverlayEventSlot> m_overlayEvents;
+
+ int __cdecl OnStatusModeChanged(WPARAM wParam, LPARAM lParam);
+ int __cdecl OnAvatarChanged(WPARAM wParam, LPARAM lParam);
+ int __cdecl OnModulesLoaded(WPARAM wParam, LPARAM lParam);
+ int __cdecl OnAccListChanged(WPARAM wParam, LPARAM lParam);
+
+ HANDLE SetEventHook(char *evt, int (__cdecl CClistProxyWindow::*fn)(WPARAM, LPARAM));
+
+ void Update();
+
+protected:
+ void OnActivate(HWND hwndFrom);
+ void OnToolbar(int id, INT_PTR data);
+ void OnRenderThumbnail(int width, int height);
+ void OnClose();
+ void OnTimer(int id);
+};
+
+extern CClistProxyWindow *g_clistProxyWnd;
+
+#endif // clistproxywindow_h__
diff --git a/plugins/w7ui/dwmwindow.cpp b/plugins/w7ui/dwmwindow.cpp
new file mode 100644
index 0000000000..2d8dd6e9e4
--- /dev/null
+++ b/plugins/w7ui/dwmwindow.cpp
@@ -0,0 +1,209 @@
+#include "headers.h"
+
+#define WNDCLASSNAME _T("W7DwmWndClass")
+
+CDwmWindow::CDwmWindow()
+{
+ GlobalInitWndClass();
+
+ m_btnInitialized = false;
+ m_btnCount = 0;
+ for (int i = 0; i < SIZEOF(m_btnInfo); ++i)
+ {
+ m_btnInfo[i].iId = i;
+ m_btnInfo[i].dwMask = THUMBBUTTONMASK(THB_FLAGS);
+ m_btnInfo[i].dwFlags = THUMBBUTTONFLAGS(THBF_HIDDEN);
+ m_btnData[i] = 0;
+ }
+
+ m_hwnd = CreateWindowEx(WS_EX_APPWINDOW|WS_EX_NOACTIVATE, WNDCLASSNAME, NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, g_hInst, NULL);
+ SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)this);
+ SetWindowPos(m_hwnd, 0, -100000, -100000, 0, 0, SWP_NOZORDER|SWP_NOACTIVATE|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_SHOWWINDOW);
+
+ BOOL val = 1;
+ DwmSetWindowAttribute(m_hwnd, DWMWA_HAS_ICONIC_BITMAP, &val, 4);
+ DwmSetWindowAttribute(m_hwnd, DWMWA_FORCE_ICONIC_REPRESENTATION, &val, 4);
+ dwmInvalidateIconicBitmaps(m_hwnd);
+}
+
+HBITMAP CDwmWindow::CreateDwmBitmap(int width, int height)
+{
+ BITMAPINFO bi;
+ bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
+ bi.bmiHeader.biWidth = width;
+ bi.bmiHeader.biHeight = -height;
+ bi.bmiHeader.biPlanes = 1;
+ bi.bmiHeader.biBitCount = 32;
+ bi.bmiHeader.biCompression = BI_RGB;
+ return CreateDIBSection(0, &bi, DIB_RGB_COLORS, NULL, 0, 0);
+}
+
+void CDwmWindow::MakeBitmapOpaque(HBITMAP hBmp)
+{
+ BITMAP bmp;
+ GetObject(hBmp, sizeof(bmp), &bmp);
+ if (bmp.bmBitsPixel != 32) return;
+ if (bmp.bmHeight < 0) bmp.bmHeight *= -1;
+
+ int size = bmp.bmWidth * bmp.bmHeight * 4;
+ BYTE *data = new BYTE[size];
+ GetBitmapBits(hBmp, size, data);
+ for (int i = 3; i < size; i += 4)
+ data[i] = 255;
+ SetBitmapBits(hBmp, size, data);
+ delete [] data;
+
+}
+
+void CDwmWindow::DrawGradient(HDC hdc, int x, int y, int width, int height, RGBQUAD *rgb0, RGBQUAD *rgb1)
+{
+ int oldMode = SetBkMode(hdc, OPAQUE);
+ COLORREF oldColor = SetBkColor(hdc, 0);
+
+ RECT rc; SetRect(&rc, x, 0, x+width, 0);
+ for (int i=y+height; --i >= y; ) {
+ COLORREF color = RGB(
+ ((height-i-1)*rgb0->rgbRed + i*rgb1->rgbRed) / height,
+ ((height-i-1)*rgb0->rgbGreen + i*rgb1->rgbGreen) / height,
+ ((height-i-1)*rgb0->rgbBlue + i*rgb1->rgbBlue) / height);
+ rc.top = rc.bottom = i;
+ ++rc.bottom;
+ SetBkColor(hdc, color);
+ ExtTextOutA(hdc, 0, 0, ETO_OPAQUE, &rc, "", 0, 0);
+ }
+
+ SetBkMode(hdc, oldMode);
+ SetBkColor(hdc, oldColor);
+}
+
+bool CDwmWindow::AddButton(HICON hIcon, TCHAR *text, INT_PTR data, DWORD flags)
+{
+ if (m_btnCount == SIZEOF(m_btnInfo)) return false;
+ m_btnInfo[m_btnCount].dwMask = THUMBBUTTONMASK(THB_ICON|THB_TOOLTIP|THB_FLAGS);
+ m_btnInfo[m_btnCount].hIcon = hIcon;
+ lstrcpyn(m_btnInfo[m_btnCount].szTip, text, SIZEOF(m_btnInfo[m_btnCount].szTip));
+ m_btnInfo[m_btnCount].dwFlags = THUMBBUTTONFLAGS(flags);
+ m_btnData[m_btnCount] = data;
+ m_btnCount++;
+ return true;
+}
+
+void CDwmWindow::UpdateButtons(ITaskbarList3 *p)
+{
+ if (m_btnInitialized)
+ p->ThumbBarUpdateButtons(hwnd(), SIZEOF(m_btnInfo), m_btnInfo);
+ else
+ p->ThumbBarAddButtons(hwnd(), SIZEOF(m_btnInfo), m_btnInfo);
+
+ m_btnCount = 0; // reset this for next iteration
+ m_btnInitialized = true;
+}
+
+void CDwmWindow::SetTimer(int id, int timeout)
+{
+ ::SetTimer(m_hwnd, id, timeout, NULL);
+}
+
+void CDwmWindow::KillTimer(int id)
+{
+ ::KillTimer(m_hwnd, id);
+}
+
+void CDwmWindow::InvalidateThumbnail()
+{
+ dwmInvalidateIconicBitmaps(m_hwnd);
+}
+
+void CDwmWindow::SetPreview(HBITMAP hbmp, int x, int y)
+{
+ POINT pt = { x, y };
+ dwmSetIconicLivePreviewBitmap(m_hwnd, hbmp, &pt, 0);
+}
+
+void CDwmWindow::SetThumbnail(HBITMAP hbmp)
+{
+ dwmSetIconicThumbnail(m_hwnd, hbmp, 0);
+}
+
+LRESULT CDwmWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_ACTIVATE:
+ {
+ if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE)
+ {
+ OnActivate((HWND)wParam);
+ }
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ OnClose();
+ return FALSE;
+ }
+
+ case WM_DWMSENDICONICLIVEPREVIEWBITMAP:
+ {
+ OnRenderPreview();
+ break;
+ }
+
+ case WM_DWMSENDICONICTHUMBNAIL:
+ {
+ int width = HIWORD(lParam);
+ int height = LOWORD(lParam);
+ OnRenderThumbnail(width, height);
+ break;
+ }
+
+ case WM_TIMER:
+ {
+ OnTimer(wParam);
+ break;
+ }
+
+ case WM_COMMAND:
+ {
+ if (HIWORD(wParam) == THBN_CLICKED)
+ OnToolbar(LOWORD(wParam), m_btnData[LOWORD(wParam)]);
+ break;
+ }
+ }
+
+ return DefWindowProc(m_hwnd, msg, wParam, lParam);
+}
+
+void CDwmWindow::GlobalInitWndClass()
+{
+ static bool bInitialized = false;
+ if (bInitialized) return;
+
+ WNDCLASSEX wcl = {0};
+ wcl.cbSize = sizeof(wcl);
+ wcl.lpfnWndProc = GlobalWndProc;
+ wcl.style = 0;
+ wcl.cbClsExtra = 0;
+ wcl.cbWndExtra = 0;
+ wcl.hInstance = g_hInst;
+ wcl.hIcon = NULL;
+ wcl.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wcl.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
+ wcl.lpszMenuName = NULL;
+ wcl.lpszClassName = WNDCLASSNAME;
+ wcl.hIconSm = NULL;
+ RegisterClassEx(&wcl);
+}
+
+LRESULT CALLBACK CDwmWindow::GlobalWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CDwmWindow *wnd = (CDwmWindow *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ if (!wnd) return DefWindowProc(hwnd, msg, wParam, lParam);
+ if (msg == WM_DESTROY)
+ {
+ delete wnd;
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return wnd->WndProc(msg, wParam, lParam);
+} \ No newline at end of file
diff --git a/plugins/w7ui/dwmwindow.h b/plugins/w7ui/dwmwindow.h
new file mode 100644
index 0000000000..e795823247
--- /dev/null
+++ b/plugins/w7ui/dwmwindow.h
@@ -0,0 +1,59 @@
+#ifndef dwmwindow_h__
+#define dwmwindow_h__
+
+class CDwmWindow
+{
+public:
+ CDwmWindow();
+ virtual ~CDwmWindow() {}
+
+ HWND hwnd() { return m_hwnd; }
+
+ template<class TWindow>
+ static TWindow *GetWindow(HWND hwnd)
+ {
+ return (TWindow *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ }
+
+protected:
+ // events
+ virtual void OnActivate(HWND hwndFrom) {}
+ virtual void OnClose() {}
+ virtual void OnRenderThumbnail(int mzxWidth, int maxHeight) {}
+ virtual void OnRenderPreview() {}
+ virtual void OnTimer(int id) {}
+ virtual void OnToolbar(int id, INT_PTR data) {}
+
+ // timer stuff
+ void SetTimer(int id, int timeout);
+ void KillTimer(int id);
+
+ // manage thumbnail and aero peek
+ void InvalidateThumbnail();
+ void SetPreview(HBITMAP hbmp, int x, int y);
+ void SetThumbnail(HBITMAP hbmp);
+
+ // manage toolbar
+ bool AddButton(HICON hIcon, TCHAR *text, INT_PTR data, DWORD flags = THBF_ENABLED);
+ void UpdateButtons(ITaskbarList3 *p);
+
+ //utilities
+ static HBITMAP CreateDwmBitmap(int width, int height);
+ static void MakeBitmapOpaque(HBITMAP hBmp);
+ static void DrawGradient(HDC hdc, int x, int y, int width, int height, RGBQUAD *rgb0, RGBQUAD *rgb1);
+
+private:
+ HWND m_hwnd;
+
+ bool m_btnInitialized;
+ int m_btnCount;
+ THUMBBUTTON m_btnInfo[7];
+ INT_PTR m_btnData[7];
+
+ LRESULT CALLBACK WndProc(UINT msg, WPARAM wParam, LPARAM lParam);
+
+ static void GlobalInitWndClass();
+ static LRESULT CALLBACK GlobalWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+};
+
+#endif // dwmwindow_h__ \ No newline at end of file
diff --git a/plugins/w7ui/headers.h b/plugins/w7ui/headers.h
new file mode 100644
index 0000000000..55a3480dbd
--- /dev/null
+++ b/plugins/w7ui/headers.h
@@ -0,0 +1,81 @@
+/*
+
+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.
+*/
+
+#define _CRT_SECURE_NO_DEPRECATE
+
+#if defined(UNICODE) && !defined(_UNICODE)
+ #define _UNICODE
+#endif
+
+#include <tchar.h>
+#define _WIN32_WINNT 0x0501
+#include <windows.h>
+#include <shlobj.h>
+#include <commctrl.h>
+#include <stdio.h>
+
+#include <dwmapi.h>
+#include <propkey.h>
+#include <propvarutil.h>
+
+#define MIRANDA_VER 0x800
+#include <win2k.h>
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_button.h>
+#include <m_clist.h>
+#include <m_clc.h>
+#include <m_clui.h>
+#include <m_options.h>
+#include <m_protosvc.h>
+#include <m_utils.h>
+#include <m_skin.h>
+#include <m_contacts.h>
+#include <m_userinfo.h>
+#include <m_history.h>
+#include <m_addcontact.h>
+#include <m_message.h>
+#include <m_file.h>
+#include <m_icolib.h>
+#include <m_idle.h>
+#include <m_awaymsg.h>
+#include <m_system_cpp.h>
+#include <m_avatars.h>
+#include <m_clistint.h>
+#include <m_protoint.h>
+#include "m_w7ui.h"
+
+#include "win7api.h"
+
+#include "jumplistarray.h"
+#include "jumplistbuilder.h"
+#include "jumplist.h"
+
+#include "subclassmgr.h"
+#include "dwmwindow.h"
+#include "clistproxywindow.h"
+#include "srmmproxywindow.h"
+
+extern HINSTANCE g_hInst;
diff --git a/plugins/w7ui/jumplist.cpp b/plugins/w7ui/jumplist.cpp
new file mode 100644
index 0000000000..4fd1a68e9d
--- /dev/null
+++ b/plugins/w7ui/jumplist.cpp
@@ -0,0 +1,123 @@
+#include "headers.h"
+
+static HANDLE hProcessJumpList = 0;
+
+static void ProcessJumpListImpl(char *arg)
+{
+ char *prefix = mir_strdup(arg);
+ char *argument = strchr(prefix, ':');
+ if (argument) *argument++ = 0;
+ NotifyEventHooks(hProcessJumpList, (WPARAM)prefix, (LPARAM)argument);
+ mir_free(prefix);
+}
+
+static LRESULT CALLBACK MirandaJumpListProcessorWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_COPYDATA:
+ {
+ COPYDATASTRUCT *data = (COPYDATASTRUCT *)lParam;
+ ProcessJumpListImpl((char *)data->lpData);
+ break;
+ }
+ }
+
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+extern "C" __declspec(dllexport) void ProcessJumpList(HWND, HINSTANCE, LPSTR arg, UINT)
+{
+ char miranda_path[MAX_PATH];
+ GetModuleFileNameA(g_hInst, miranda_path, SIZEOF(miranda_path));
+ lstrcpyA(strstr(_strlwr(miranda_path), "plugins\\w7ui.dll"), "miranda32.exe");
+
+ if (HWND hwnd = FindWindowA("MirandaJumpListProcessor", miranda_path))
+ {
+ COPYDATASTRUCT data = {0};
+ data.dwData = 0;
+ data.cbData = lstrlenA(arg) + 1;
+ data.lpData = arg;
+ SendMessage(hwnd, WM_COPYDATA, 0, (LPARAM)&data);
+ } else
+ {
+ char command[MAX_PATH * 2];
+ wsprintfA(command, "\"%s\" -jump %s", miranda_path, arg);
+ WinExec(command, SW_SHOWNORMAL);
+ }
+}
+
+static int OnJumpListItems(WPARAM, LPARAM lParam)
+{
+ WCHAR *category = (WCHAR *)lParam;
+
+ if (!category)
+ {
+ MJumpList_AddItem(SKINICON_STATUS_ONLINE, TranslateT("Online"), L"status", L"online");
+ MJumpList_AddItem(SKINICON_STATUS_DND, TranslateT("Do not disturb"), L"status", L"dnd");
+ MJumpList_AddItem(SKINICON_STATUS_INVISIBLE, TranslateT("Invisible"), L"status", L"invisible");
+ MJumpList_AddItem(SKINICON_STATUS_OFFLINE, TranslateT("Offline"), L"status", L"offline");
+ return 0;
+ }
+
+ return 0;
+}
+
+static int OnJumpListProcess(WPARAM wParam, LPARAM lParam)
+{
+ char *prefix = (char *)wParam;
+ char *argument = (char *)lParam;
+
+ if (!lstrcmpA(prefix, "status"))
+ {
+ if (!lstrcmpA(argument, "online"))
+ {
+ CallService(MS_CLIST_SETSTATUSMODE, ID_STATUS_ONLINE, 0);
+ } else
+ if (!lstrcmpA(argument, "dnd"))
+ {
+ CallService(MS_CLIST_SETSTATUSMODE, ID_STATUS_DND, 0);
+ } else
+ if (!lstrcmpA(argument, "invisible"))
+ {
+ CallService(MS_CLIST_SETSTATUSMODE, ID_STATUS_INVISIBLE, 0);
+ } else
+ if (!lstrcmpA(argument, "offline"))
+ {
+ CallService(MS_CLIST_SETSTATUSMODE, ID_STATUS_OFFLINE, 0);
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+void LoadJumpList()
+{
+ hProcessJumpList = CreateHookableEvent(ME_JUMPLIST_PROCESS);
+}
+
+void InitJumpList()
+{
+ HookEvent(ME_JUMPLIST_BUILDITEMS, OnJumpListItems);
+ HookEvent(ME_JUMPLIST_PROCESS, OnJumpListProcess);
+
+ if (char *cmd = strstr(GetCommandLineA(), " -jump "))
+ ProcessJumpListImpl(cmd + 7);
+
+ WNDCLASSEX wcx = {0};
+ wcx.cbSize = sizeof(wcx);
+ wcx.lpfnWndProc = MirandaJumpListProcessorWndProc;
+ wcx.hInstance = g_hInst;
+ wcx.lpszClassName = _T("MirandaJumpListProcessor");
+ RegisterClassEx(&wcx);
+
+ char miranda_path[MAX_PATH];
+ GetModuleFileNameA(g_hInst, miranda_path, SIZEOF(miranda_path));
+ lstrcpyA(strstr(_strlwr(miranda_path), "plugins\\w7ui.dll"), "miranda32.exe");
+
+ HWND hwnd = CreateWindowA("MirandaJumpListProcessor", miranda_path, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL, g_hInst, NULL);
+ ShowWindow(hwnd, SW_HIDE);
+
+ CJumpListBuilder::Rebuild();
+}
diff --git a/plugins/w7ui/jumplist.h b/plugins/w7ui/jumplist.h
new file mode 100644
index 0000000000..de5a6f0548
--- /dev/null
+++ b/plugins/w7ui/jumplist.h
@@ -0,0 +1,7 @@
+#ifndef jumplist_h__
+#define jumplist_h__
+
+void LoadJumpList();
+void InitJumpList();
+
+#endif // jumplist_h__
diff --git a/plugins/w7ui/jumplistarray.cpp b/plugins/w7ui/jumplistarray.cpp
new file mode 100644
index 0000000000..669a7784ef
--- /dev/null
+++ b/plugins/w7ui/jumplistarray.cpp
@@ -0,0 +1,214 @@
+#include "headers.h"
+
+#pragma pack(push, 1)
+typedef struct
+{
+ BYTE bWidth; // Width, in pixels, of the image
+ BYTE bHeight; // Height, in pixels, of the image
+ BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
+ BYTE bReserved; // Reserved ( must be 0)
+ WORD wPlanes; // Color Planes
+ WORD wBitCount; // Bits per pixel
+ DWORD dwBytesInRes; // How many bytes in this resource?
+ DWORD dwImageOffset; // Where in the file is this image?
+} ICONDIRENTRY, *LPICONDIRENTRY;
+
+typedef struct
+{
+ WORD idReserved; // Reserved (must be 0)
+ WORD idType; // Resource Type (1 for icons)
+ WORD idCount; // How many images?
+ ICONDIRENTRY idEntries[1]; // An entry for each image (idCount of 'em)
+} ICONDIR, *LPICONDIR;
+#pragma pack(pop)
+
+static void SaveIconToFile(HICON hIcon, TCHAR *szFile)
+{
+ ICONINFO iconInfo = {0};
+ BITMAP bmpColor, bmpMask;
+ HANDLE hFile = 0;
+ HANDLE hMap = 0;
+ BYTE *pFile = 0;
+
+ GetIconInfo(hIcon, &iconInfo);
+ GetObject(iconInfo.hbmColor, sizeof(bmpColor), &bmpColor);
+ GetObject(iconInfo.hbmMask, sizeof(bmpMask), &bmpMask);
+
+ do
+ {
+ if (bmpColor.bmBitsPixel <= 8) break;
+
+ DWORD dwColorSize = bmpColor.bmWidthBytes * bmpColor.bmHeight;
+ DWORD dwMaskSize = bmpMask.bmWidthBytes * bmpMask.bmHeight;
+ DWORD dwFileSize = sizeof(ICONDIR) + sizeof(BITMAPINFOHEADER) + dwColorSize + dwMaskSize;
+
+ hFile = CreateFile(szFile, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) break;
+ hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwFileSize, NULL);
+ if (!hMap) break;
+ pFile = (BYTE *)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0 ,0);
+ if (!pFile) break;
+
+ ICONDIR iconDir = {0};
+ iconDir.idCount = 1;
+ iconDir.idType = 1;
+ iconDir.idEntries[0].bWidth = bmpColor.bmWidth;
+ iconDir.idEntries[0].bHeight = bmpColor.bmHeight;
+ iconDir.idEntries[0].bColorCount = 0;
+ iconDir.idEntries[0].wPlanes = bmpColor.bmPlanes;
+ iconDir.idEntries[0].wBitCount = bmpColor.bmBitsPixel;
+ iconDir.idEntries[0].dwBytesInRes = sizeof(BITMAPINFOHEADER) + dwColorSize + dwMaskSize;
+ iconDir.idEntries[0].dwImageOffset = sizeof(ICONDIR);
+ MoveMemory(pFile, &iconDir, sizeof(ICONDIR));
+
+ BITMAPINFOHEADER iconBmp = {0};
+ iconBmp.biSize = sizeof(iconBmp);
+ iconBmp.biWidth = bmpColor.bmWidth;
+ iconBmp.biHeight = bmpColor.bmHeight + bmpMask.bmHeight;
+ iconBmp.biPlanes = bmpColor.bmPlanes;
+ iconBmp.biBitCount = bmpColor.bmBitsPixel;
+ iconBmp.biSizeImage = dwColorSize + dwMaskSize;
+ MoveMemory(pFile + sizeof(ICONDIR), &iconBmp, sizeof(BITMAPINFOHEADER));
+
+ BYTE *buf = (BYTE *)mir_alloc(dwColorSize);
+ GetBitmapBits(iconInfo.hbmColor, dwColorSize, buf);
+ for (int row = 0; row < bmpColor.bmHeight; ++row)
+ {
+ MoveMemory(
+ pFile + sizeof(ICONDIR) + sizeof(BITMAPINFOHEADER) + row * bmpColor.bmWidthBytes,
+ buf + (bmpColor.bmHeight - row - 1) * bmpColor.bmWidthBytes,
+ bmpColor.bmWidthBytes);
+ }
+ mir_free(buf);
+
+ GetBitmapBits(iconInfo.hbmMask, dwMaskSize, pFile + sizeof(ICONDIR) + sizeof(BITMAPINFOHEADER) + dwColorSize);
+ } while(0);
+
+ DeleteObject(iconInfo.hbmColor);
+ DeleteObject(iconInfo.hbmMask);
+
+ if (pFile) UnmapViewOfFile(pFile);
+ if (hMap) CloseHandle(hMap);
+ if (hFile && hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
+}
+
+CJumpListArray::CJumpListArray()
+{
+ CoCreateInstance(CLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC_SERVER, IID_IObjectCollection, (void **)&m_pObjects);
+}
+
+CJumpListArray::~CJumpListArray()
+{
+ if (m_pObjects) m_pObjects->Release();
+}
+
+void CJumpListArray::AddItemImpl(TCHAR *icon, int iIcon, TCHAR *title, TCHAR *path, TCHAR *args)
+{
+ IShellLink *link = NewShellLink(icon, iIcon, title, path, args);
+ m_pObjects->AddObject(link);
+ link->Release();
+}
+
+void CJumpListArray::AddItem(char *mir_icon, TCHAR *title, TCHAR *path, TCHAR *args)
+{
+ TCHAR icon[MAX_PATH]; int iIcon;
+ LoadMirandaIcon(mir_icon, icon, &iIcon);
+ AddItemImpl(icon, iIcon, title, path, args);
+}
+
+void CJumpListArray::AddItem(int skinicon, TCHAR *title, TCHAR *path, TCHAR *args)
+{
+ TCHAR icon[MAX_PATH]; int iIcon;
+ LoadMirandaIcon(skinicon, icon, &iIcon);
+ AddItemImpl(icon, iIcon, title, path, args);
+}
+
+void CJumpListArray::AddItem(char *proto, int status, TCHAR *title, TCHAR *path, TCHAR *args)
+{
+ TCHAR icon[MAX_PATH]; int iIcon;
+ LoadMirandaIcon(proto, status, icon, &iIcon);
+ AddItemImpl(icon, iIcon, title, path, args);
+}
+
+IObjectArray *CJumpListArray::GetArray()
+{
+ IObjectArray *result = NULL;
+ m_pObjects->QueryInterface(IID_IObjectArray, (void **)&result);
+ return result;
+}
+
+bool CJumpListArray::LoadMirandaIcon(char *mir_icon, TCHAR *icon, int *id)
+{
+ *id = 0;
+
+ TCHAR *path = Utils_ReplaceVarsT(_T("%miranda_userdata%\\w7ui.IconCache"));
+ CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)path);
+
+ TCHAR *name = mir_a2t(mir_icon);
+ for (TCHAR *ch = name; *ch; ++ch) if (_tcschr(_T("\\/:*?<>|"), *ch)) *ch = _T('_');
+ mir_sntprintf(icon, MAX_PATH, _T("%s\\%s.ico"), path, name);
+
+ mir_free(name);
+ mir_free(path);
+
+ HICON hIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)mir_icon);
+ SaveIconToFile(hIcon, icon);
+
+ return true;
+}
+
+bool CJumpListArray::LoadMirandaIcon(int skinicon, TCHAR *icon, int *id)
+{
+ *id = 0;
+
+ TCHAR *path = Utils_ReplaceVarsT(_T("%miranda_userdata%\\w7ui.IconCache"));
+ CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)path);
+ mir_sntprintf(icon, MAX_PATH, _T("%s\\skinicon$%d.ico"), path, skinicon);
+ mir_free(path);
+
+ HICON hIcon = LoadSkinnedIcon(skinicon);
+ SaveIconToFile(hIcon, icon);
+
+ return true;
+}
+
+bool CJumpListArray::LoadMirandaIcon(char *proto, int status, TCHAR *icon, int *id)
+{
+ *id = 0;
+
+ TCHAR *path = Utils_ReplaceVarsT(_T("%miranda_userdata%\\w7ui.IconCache"));
+ CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)path);
+ mir_sntprintf(icon, MAX_PATH, _T("%s\\skinprotoicon$") _T(TCHAR_STR_PARAM) _T("$%d.ico"), path, proto, status);
+ mir_free(path);
+
+ HICON hIcon = LoadSkinnedProtoIcon(proto, status);
+ SaveIconToFile(hIcon, icon);
+
+ return true;
+}
+
+IShellLink *CJumpListArray::NewShellLink(TCHAR *icon, int iIcon, TCHAR *title, TCHAR *path, TCHAR *args)
+{
+ IShellLink *pShellLink = NULL;
+ CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&pShellLink);
+
+ pShellLink->SetPath(path);
+ pShellLink->SetIconLocation(icon, iIcon);
+ pShellLink->SetArguments(args);
+ pShellLink->SetShowCmd(SW_SHOWDEFAULT);
+
+ IPropertyStore *pPropStore = NULL;
+ if (SUCCEEDED(pShellLink->QueryInterface(IID_IPropertyStore, (void **)&pPropStore)))
+ {
+ PROPVARIANT pv;
+
+ InitPropVariantFromString(title, &pv);
+ pPropStore->SetValue(PKEY_Title, pv);
+ PropVariantClear(&pv);
+
+ pPropStore->Commit();
+ pPropStore->Release();
+ }
+
+ return pShellLink;
+} \ No newline at end of file
diff --git a/plugins/w7ui/jumplistarray.h b/plugins/w7ui/jumplistarray.h
new file mode 100644
index 0000000000..c9f2a8b979
--- /dev/null
+++ b/plugins/w7ui/jumplistarray.h
@@ -0,0 +1,29 @@
+#ifndef jumplistarray_h__
+#define jumplistarray_h__
+
+class CJumpListArray
+{
+private:
+ IObjectCollection *m_pObjects;
+
+public:
+ CJumpListArray();
+ ~CJumpListArray();
+
+ void AddItem(char *mir_icon, TCHAR *title, TCHAR *path, TCHAR *args);
+ void AddItem(int skinicon, TCHAR *title, TCHAR *path, TCHAR *args);
+ void AddItem(char *proto, int skinicon, TCHAR *title, TCHAR *path, TCHAR *args);
+
+ IObjectArray *GetArray();
+
+private:
+ void AddItemImpl(TCHAR *icon, int iIcon, TCHAR *title, TCHAR *path, TCHAR *args);
+
+ bool LoadMirandaIcon(char *mir_icon, TCHAR *icon, int *id);
+ bool LoadMirandaIcon(int skinicon, TCHAR *icon, int *id);
+ bool LoadMirandaIcon(char *proto, int status, TCHAR *icon, int *id);
+
+ static IShellLink *NewShellLink(TCHAR *icon, int iIcon, TCHAR *title, TCHAR *path, TCHAR *args);
+};
+
+#endif // jumplistarray_h__
diff --git a/plugins/w7ui/jumplistbuilder.cpp b/plugins/w7ui/jumplistbuilder.cpp
new file mode 100644
index 0000000000..5e5f1d9f65
--- /dev/null
+++ b/plugins/w7ui/jumplistbuilder.cpp
@@ -0,0 +1,127 @@
+#include "headers.h"
+
+CJumpListBuilder *CJumpListBuilder::m_instance = 0;
+
+CJumpListBuilder::CJumpListBuilder()
+{
+ m_hBuildCategories = CreateHookableEvent(ME_JUMPLIST_BUILDCATEGORIES);
+ m_hBuildItems = CreateHookableEvent(ME_JUMPLIST_BUILDITEMS);
+ CreateSvc(MS_JUMPLIST_REBUILD, &CJumpListBuilder::Rebuild);
+ CreateSvc(MS_JUMPLIST_ADDCATEGORY, &CJumpListBuilder::AddCategory);
+ CreateSvc(MS_JUMPLIST_ADDITEM, &CJumpListBuilder::AddItem);
+}
+
+CJumpListBuilder::~CJumpListBuilder()
+{
+ KillObjectServices(this);
+ DestroyHookableEvent(m_hBuildCategories);
+ DestroyHookableEvent(m_hBuildItems);
+}
+
+void CJumpListBuilder::BuildJumpList()
+{
+ m_lists = new LIST<TCHAR>(5, _tcscmp);
+ NotifyEventHooks(m_hBuildCategories, 0, 0);
+
+ UINT maxSlots;
+ IObjectArray *pRemoved;
+ CoCreateInstance(CLSID_CustomDestinationList, NULL, CLSCTX_INPROC_SERVER, IID_ICustomDestinationList, (void **)&m_pList);
+ m_pList->BeginList(&maxSlots, IID_IObjectArray, (void **)&pRemoved);
+ BuildCategory(NULL);
+ for (int i = 0; i < m_lists->getCount(); ++i)
+ BuildCategory((*m_lists)[i]);
+ m_pList->CommitList();
+ m_pList->Release();
+ pRemoved->Release();
+
+ m_lists->destroy();
+ delete m_lists;
+}
+
+int __cdecl CJumpListBuilder::Rebuild(WPARAM wParam, LPARAM lParam)
+{
+ BuildJumpList();
+ return 0;
+}
+
+int __cdecl CJumpListBuilder::AddCategory(WPARAM wParam, LPARAM lParam)
+{
+ TCHAR *category = (TCHAR *)lParam;
+ if (!m_lists->find(category)) m_lists->insert(mir_wstrdup(category));
+ return 0;
+}
+
+int __cdecl CJumpListBuilder::AddItem(WPARAM wParam, LPARAM lParam)
+{
+ MIRANDAJUMPLISTITEM *item = (MIRANDAJUMPLISTITEM *)lParam;
+ switch (item->iconSource)
+ {
+ case MIS_ICOLIB:
+ m_pCurrentList->AddItem(item->iconName, item->szTitle, _T("rundll32.exe"), BuildJumpListCommand(item->szPrefix, item->szArgument));
+ break;
+ case MIS_GENERAL:
+ m_pCurrentList->AddItem(item->iconIdx, item->szTitle, _T("rundll32.exe"), BuildJumpListCommand(item->szPrefix, item->szArgument));
+ break;
+ case MIS_PROTOCOL:
+ m_pCurrentList->AddItem(item->iconName, item->iconIdx, item->szTitle, _T("rundll32.exe"), BuildJumpListCommand(item->szPrefix, item->szArgument));
+ break;
+ }
+ return 0;
+}
+
+void CJumpListBuilder::BuildCategory(TCHAR *category)
+{
+ m_pCurrentList = new CJumpListArray;
+ NotifyEventHooks(m_hBuildItems, 0, (LPARAM)category);
+
+ if (category)
+ m_pList->AppendCategory(category, m_pCurrentList->GetArray());
+ else
+ m_pList->AddUserTasks(m_pCurrentList->GetArray());
+ delete m_pCurrentList;
+
+}
+
+TCHAR *CJumpListBuilder::BuildJumpListCommand(TCHAR *prefix, TCHAR *argument)
+{
+ TCHAR path[MAX_PATH];
+ GetModuleFileName(g_hInst, path, SIZEOF(path));
+ mir_sntprintf(m_cmdBuf, SIZEOF(m_cmdBuf), _T("\"%s\",ProcessJumpList %s:%s"), path, prefix, argument);
+ return m_cmdBuf;
+}
+
+HANDLE CJumpListBuilder::CreateSvc(char *svc, int (__cdecl CJumpListBuilder::*fn)(WPARAM, LPARAM))
+{
+ return CreateServiceFunctionObj(svc, *(MIRANDASERVICEOBJ *)&fn, this);
+}
+
+/*
+static TCHAR *BuildJumpListCommand(TCHAR *buf, int size, TCHAR *arg);
+
+static void SetupTasks()
+{
+ TCHAR buf[MAX_PATH * 2];
+
+ CJumpListArray tasks;
+ tasks.AddItem(SKINICON_STATUS_ONLINE, TranslateT("Online"), _T("rundll32.exe"), BuildJumpListCommand(buf, SIZEOF(buf), _T("status:online")));
+ tasks.AddItem(SKINICON_STATUS_DND, TranslateT("Do not disturb"), _T("rundll32.exe"), BuildJumpListCommand(buf, SIZEOF(buf), _T("status:dnd")));
+ tasks.AddItem(SKINICON_STATUS_INVISIBLE, TranslateT("Invisible"), _T("rundll32.exe"), BuildJumpListCommand(buf, SIZEOF(buf), _T("status:invisible")));
+ tasks.AddItem(SKINICON_STATUS_OFFLINE, TranslateT("Offline"), _T("rundll32.exe"), BuildJumpListCommand(buf, SIZEOF(buf), _T("status:offline")));
+
+// CJumpListArray contacts;
+// contacts.AddItem("core_status_*0", TranslateT("Nickname"), L"taskhost.exe", L"profile.dat -contact:hcontact");
+
+ UINT maxSlots;
+ IObjectArray *pRemoved;
+
+ ICustomDestinationList *pList;
+ CoCreateInstance(CLSID_CustomDestinationList, NULL, CLSCTX_INPROC_SERVER, IID_ICustomDestinationList, (void **)&pList);
+ pList->BeginList(&maxSlots, IID_IObjectArray, (void **)&pRemoved);
+ pList->AddUserTasks(tasks.GetArray());
+// pList->AppendCategory(L"Contacts", contacts.GetArray());
+ pList->CommitList();
+ pList->Release();
+
+ pRemoved->Release();
+}
+*/ \ No newline at end of file
diff --git a/plugins/w7ui/jumplistbuilder.h b/plugins/w7ui/jumplistbuilder.h
new file mode 100644
index 0000000000..f0e1cbd438
--- /dev/null
+++ b/plugins/w7ui/jumplistbuilder.h
@@ -0,0 +1,47 @@
+#ifndef jumplistbuilder_h__
+#define jumplistbuilder_h__
+
+class CJumpListBuilder
+{
+public:
+ static void Load()
+ {
+ m_instance = new CJumpListBuilder;
+ }
+
+ static void Unload()
+ {
+ delete m_instance;
+ }
+
+ static void Rebuild()
+ {
+ m_instance->BuildJumpList();
+ }
+
+private:
+ static CJumpListBuilder *m_instance;
+
+ LIST<TCHAR> *m_lists;
+ ICustomDestinationList *m_pList;
+ CJumpListArray *m_pCurrentList;
+ TCHAR m_cmdBuf[MAX_PATH * 2];
+
+ HANDLE m_hBuildCategories;
+ HANDLE m_hBuildItems;
+
+ CJumpListBuilder();
+ ~CJumpListBuilder();
+ void BuildJumpList();
+
+ int __cdecl Rebuild(WPARAM wParam, LPARAM lParam);
+ int __cdecl AddCategory(WPARAM wParam, LPARAM lParam);
+ int __cdecl AddItem(WPARAM wParam, LPARAM lParam);
+
+ void BuildCategory(TCHAR *category);
+
+ TCHAR *BuildJumpListCommand(TCHAR *prefix, TCHAR *argument);
+ HANDLE CreateSvc(char *svc, int (__cdecl CJumpListBuilder::*fn)(WPARAM, LPARAM));
+};
+
+#endif // jumplistbuilder_h__
diff --git a/plugins/w7ui/main.cpp b/plugins/w7ui/main.cpp
new file mode 100644
index 0000000000..a8763a60a6
--- /dev/null
+++ b/plugins/w7ui/main.cpp
@@ -0,0 +1,93 @@
+/*
+Miranda core extensions
+
+Copyright 2000-2007 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 "headers.h"
+#include <win2k.h>
+
+int LoadW7UI();
+int UnloadW7UI();
+
+PLUGINLINK* pluginLink;
+HINSTANCE g_hInst;
+
+struct LIST_INTERFACE li;
+struct MM_INTERFACE mmi;
+
+// {3625ACB8-794C-4727-88EA-76DBBAC6D200}
+#define MIID_W7UI { 0x3625acb8, 0x794c, 0x4727, { 0x88, 0xea, 0x76, 0xdb, 0xba, 0xc6, 0xd2, 0x0 } }
+
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ "Windows 7 UI",
+ PLUGIN_MAKE_VERSION(0, 0, 0, 1),
+ "Provides support for Windows 7 Taskbar feautures such as Aero Peek, Overlay icons, Jump Lists, Progress Bar",
+ "nullbie, persei",
+ "nullbie@miranda.im",
+ "2009 Victor Pavlychko, Vitaliy Igonin",
+ "http://nullbie.miranda.im",
+ UNICODE_AWARE,
+ 0, // replace internal version (if any)
+#ifdef _UNICODE
+ // {D38EEB0B-B8EE-4177-B9E5-91EBE101E054}
+ { 0xd38eeb0b, 0xb8ee, 0x4177, { 0xb9, 0xe5, 0x91, 0xeb, 0xe1, 0x1, 0xe0, 0x54 } }
+#else
+ // {DEB3FAFA-6B24-4db3-AA34-9EC27B868B50}
+ { 0xdeb3fafa, 0x6b24, 0x4db3, { 0xaa, 0x34, 0x9e, 0xc2, 0x7b, 0x86, 0x8b, 0x50 } }
+#endif
+};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ g_hInst = hinstDLL;
+ return TRUE;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+extern "C" __declspec(dllexport) const MUUID *MirandaPluginInterfaces(void)
+{
+ static const MUUID interfaces[] = { MIID_W7UI, MIID_LAST };
+ return interfaces;
+}
+
+extern "C" __declspec(dllexport) int Load(PLUGINLINK * link)
+{
+ if (!IsWinVer7Plus()) return 1;
+
+ pluginLink = link;
+ mir_getLI(&li);
+ mir_getMMI(&mmi);
+
+ LoadW7UI();
+
+ return 0;
+}
+
+extern "C" __declspec(dllexport) int Unload(void)
+{
+ UnloadW7UI();
+ return 0;
+}
diff --git a/plugins/w7ui/srmmproxywindow.cpp b/plugins/w7ui/srmmproxywindow.cpp
new file mode 100644
index 0000000000..a70ca1b672
--- /dev/null
+++ b/plugins/w7ui/srmmproxywindow.cpp
@@ -0,0 +1,374 @@
+#include "headers.h"
+
+extern int g_eventSlotMessage;
+extern ITaskbarList3 *g_pTaskbarList;
+
+///////////////////////////////////////////////////////////////////////////////
+// srmm processing
+
+CSrmmProxyWindow::CSrmmProxyWindow(HANDLE hContact, HWND hwndWindow, HWND hwndParent)
+{
+ m_hContact = hContact;
+ m_hwndWindow = hwndWindow;
+ m_hwndParent = hwndParent;
+
+ m_hbmpPreview = NULL;
+ m_refreshPreview = true;
+
+ m_bActive = false;
+ m_bUnread = false;
+ m_bTyping = false;
+
+ UpdateIcon();
+ SetWindowText(hwnd(), (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)m_hContact, GCDNF_TCHAR));
+ SetTimer(1, 1000);
+
+ SetEventHook(ME_DB_EVENT_ADDED, &CSrmmProxyWindow::OnDbEventAdded);
+ SetEventHook(ME_DB_CONTACT_SETTINGCHANGED, &CSrmmProxyWindow::OnDbSettingChanged);
+ SetEventHook(ME_AV_AVATARCHANGED, &CSrmmProxyWindow::OnAvatarChanged);
+ SetEventHook(ME_PROTO_CONTACTISTYPING, &CSrmmProxyWindow::OnContactTyping);
+
+ AddButton(LoadSkinnedIcon(SKINICON_OTHER_USERDETAILS), TranslateT("User Details"), 1, THBF_DISMISSONCLICK);
+ AddButton(LoadSkinnedIcon(SKINICON_OTHER_HISTORY), TranslateT("History"), 2, THBF_DISMISSONCLICK);
+ AddButton(LoadSkinnedIcon(SKINICON_EVENT_FILE), TranslateT("File"), 3, THBF_DISMISSONCLICK);
+ UpdateButtons(g_pTaskbarList);
+}
+
+CSrmmProxyWindow::~CSrmmProxyWindow()
+{
+ DeleteObject(m_hbmpPreview);
+ KillObjectEventHooks(this);
+}
+
+
+void CSrmmProxyWindow::Refresh()
+{
+ InvalidateThumbnail();
+ m_refreshPreview = true;
+}
+
+int __cdecl CSrmmProxyWindow::OnDbEventAdded(WPARAM wParam, LPARAM lParam)
+{
+ if ((HANDLE)wParam == m_hContact)
+ {
+ Refresh();
+
+ if (!m_bUnread && !IsActive())
+ {
+ DBEVENTINFO dbei = {0};
+ dbei.cbSize = sizeof(dbei);
+ if (!CallService(MS_DB_EVENT_GET, (WPARAM)lParam, (LPARAM)&dbei))
+ if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & (DBEF_READ|DBEF_SENT)))
+ {
+ g_clistProxyWnd->Flash();
+ g_clistProxyWnd->AddOverlayEvent(g_eventSlotMessage);
+ m_bUnread = true;
+ UpdateIcon();
+ }
+ }
+ }
+ return 0;
+}
+
+int __cdecl CSrmmProxyWindow::OnDbSettingChanged(WPARAM wParam, LPARAM lParam)
+{
+ if ((HANDLE)wParam == m_hContact)
+ {
+ UpdateIcon();
+ Refresh();
+ }
+ return 0;
+}
+
+int __cdecl CSrmmProxyWindow::OnAvatarChanged(WPARAM wParam, LPARAM lParam)
+{
+ if ((HANDLE)wParam == m_hContact)
+ Refresh();
+ return 0;
+}
+
+int __cdecl CSrmmProxyWindow::OnContactTyping(WPARAM wParam, LPARAM lParam)
+{
+ if ((HANDLE)wParam == m_hContact)
+ {
+ m_bTyping = lParam ? true : false;
+ UpdateIcon();
+ }
+ return 0;
+}
+
+HANDLE CSrmmProxyWindow::SetEventHook(char *evt, int (__cdecl CSrmmProxyWindow::*fn)(WPARAM, LPARAM))
+{
+ return HookEventObj(evt, *(MIRANDAHOOKOBJ *)&fn, this);
+}
+
+void CSrmmProxyWindow::OnTabActive()
+{
+ m_bActive = true;
+ if (m_bUnread)
+ {
+ g_clistProxyWnd->RemoveOverlayEvent(g_eventSlotMessage);
+ m_bUnread = false;
+ UpdateIcon();
+ }
+}
+
+void CSrmmProxyWindow::OnTabInactive()
+{
+ m_bActive = false;
+}
+
+bool CSrmmProxyWindow::IsActive()
+{
+ for (HWND hwnd = GetFocus(); hwnd; hwnd = GetParent(hwnd))
+ if (hwnd == m_hwndWindow)
+ return m_bActive = true;
+ return m_bActive = false;
+}
+
+void CSrmmProxyWindow::UpdateIcon()
+{
+ HICON hIcon;
+ if (m_bTyping)
+ {
+ hIcon = LoadSkinnedIcon(SKINICON_OTHER_TYPING);
+ } else
+ if (m_bUnread)
+ {
+ hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE);
+ } else
+ {
+ char *szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)m_hContact, 0);
+ if (!szProto) return;
+ int iStatus = DBGetContactSettingWord(m_hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ hIcon = (HICON)LoadSkinnedProtoIcon(szProto, iStatus);
+ }
+
+ SendMessage(hwnd(), WM_SETICON, ICON_BIG, (LPARAM)hIcon);
+ SendMessage(hwnd(), WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
+}
+
+void CSrmmProxyWindow::OnActivate(HWND hwndFrom)
+{
+ CallService(MS_CLIST_CONTACTDOUBLECLICKED, (WPARAM)m_hContact, 0);
+}
+
+void CSrmmProxyWindow::OnToolbar(int id, INT_PTR data)
+{
+ POINT pt; GetCursorPos(&pt);
+ HMENU hMenu = NULL;
+ HWND hwndClui = (HWND)CallService(MS_CLUI_GETHWND, 0, 0);
+
+ switch (data)
+ {
+ case 1:
+ CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)m_hContact, 0);
+ break;
+
+ case 2:
+ CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM)m_hContact, 0);
+ break;
+
+ case 3:
+ CallService(MS_FILE_SENDFILE, (WPARAM)m_hContact, 0);
+ break;
+ }
+}
+
+void CSrmmProxyWindow::OnRenderThumbnail(int width, int height)
+{
+ HBITMAP hbmp = CreateDwmBitmap(width, height);
+ HDC hdc = CreateCompatibleDC(0);
+ SelectObject(hdc, hbmp);
+
+ RGBQUAD rgb0, rgb1;
+ rgb0.rgbRed = 0; rgb0.rgbGreen = 0; rgb0.rgbBlue = 0;
+ rgb1.rgbRed = 19; rgb1.rgbGreen = 58; rgb1.rgbBlue = 89;
+ DrawGradient(hdc, 0, 0, width, height, &rgb0, &rgb1);
+
+ HFONT hfntSave = (HFONT)SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
+ SetTextColor(hdc, RGB(255, 255, 255));
+ SetBkMode(hdc, TRANSPARENT);
+
+ RECT rc;
+ SIZE sz;
+ SetRect(&rc, 5, 5, width-10, height-10);
+
+ int avatarWidth = 0;
+ int avatarHeight = 0;
+ if (true)
+ {
+ AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)m_hContact, 0);
+ if (ace && (ace != (AVATARCACHEENTRY *)CALLSERVICE_NOTFOUND))
+ {
+ if (ace->bmWidth < width / 4)
+ {
+ avatarWidth = ace->bmWidth;
+ avatarHeight = ace->bmHeight;
+ } else
+ {
+ avatarWidth = width / 4;
+ avatarHeight = avatarWidth * ace->bmHeight / ace->bmWidth;
+ }
+
+ AVATARDRAWREQUEST avdr = {0};
+ avdr.cbSize = sizeof(avdr);
+ avdr.hContact = m_hContact;
+ avdr.hTargetDC = hdc;
+ avdr.rcDraw = rc;
+ avdr.rcDraw.bottom = avdr.rcDraw.top + avatarHeight;
+ avdr.rcDraw.right = avdr.rcDraw.left + avatarWidth;
+ avdr.dwFlags = AVDRQ_FALLBACKPROTO | AVDRQ_FORCEALPHA;
+
+ avdr.alpha = 255;
+ CallService(MS_AV_DRAWAVATAR, 0, (LPARAM)&avdr);
+
+ rc.left += avatarWidth + 5;
+ }
+ }
+
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)m_hContact, 0);
+
+ if (true)
+ {
+ CONTACTINFO ci = {0};
+ ci.cbSize = sizeof(ci);
+ ci.hContact = m_hContact;
+ ci.szProto = proto;
+ ci.dwFlag = CNF_UNIQUEID | CNF_TCHAR;
+ if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci))
+ {
+ TCHAR name[128]; name[0] = 0;
+ switch (ci.type)
+ {
+ case CNFT_ASCIIZ:
+ mir_sntprintf(name, SIZEOF(name), _T("%s"), ci.pszVal);
+ mir_free((void *)ci.pszVal);
+ break;
+ case CNFT_DWORD:
+ mir_sntprintf(name, SIZEOF(name), _T("%u"), ci.dVal);
+ break;
+ }
+
+ TextOut(hdc, rc.left + 20, rc.top, name, lstrlen(name));
+ GetTextExtentPoint32(hdc, name, lstrlen(name), &sz);
+ }
+ }
+
+ if (true)
+ {
+ HIMAGELIST hIml = (HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0);
+ int iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM)m_hContact, 0);
+ ImageList_Draw(hIml, iIcon, hdc, rc.left, rc.top + (sz.cy - 16) / 2, ILD_TRANSPARENT);
+ }
+
+ rc.top += sz.cy + 5;
+
+ rc.left += 10;
+
+ struct
+ {
+ TCHAR *text;
+ bool out;
+ } msgs[10] = {0};
+
+ if (true)
+ {
+ int hMsgs = 0;
+ int n = 0;
+ HANDLE hEvent = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)m_hContact, 0);
+ while (hEvent)
+ {
+ BYTE buf[1024];
+ DBEVENTINFO dbei = {0};
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = sizeof(buf);
+ dbei.pBlob = buf;
+ if (!CallService(MS_DB_EVENT_GET, (WPARAM)hEvent, (LPARAM)&dbei))
+ {
+ if (dbei.eventType == EVENTTYPE_MESSAGE)
+ {
+ msgs[n].text = DbGetEventTextT(&dbei, CP_ACP);
+ msgs[n].out = dbei.flags & DBEF_SENT ? true : false;
+
+ RECT rcCopy = rc;
+ hMsgs += DrawText(hdc, msgs[n].text, -1, &rcCopy, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK|DT_TOP|DT_CALCRECT);
+ if (n && hMsgs > rc.bottom - rc.top)
+ {
+ mir_free(msgs[n].text);
+ msgs[n].text = 0;
+ break;
+ }
+
+ hMsgs += 3;
+
+ if (++n >= SIZEOF(msgs)) break;
+ }
+ }
+ hEvent = (HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hEvent, 0);
+ }
+ }
+
+ if (true)
+ {
+ for (int i = SIZEOF(msgs); i--; )
+ {
+ if (!msgs[i].text) continue;
+
+ TCHAR szDir[] = { (msgs[i].out ? (WCHAR)0xbb : (WCHAR)0xab), 0 };
+ rc.left -= 10;
+ DrawText(hdc, szDir, -1, &rc, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK|DT_TOP);
+ rc.left += 10;
+
+ rc.top += 3 + DrawText(hdc, msgs[i].text, -1, &rc, DT_LEFT|DT_NOPREFIX|DT_WORDBREAK|DT_TOP);
+ mir_free(msgs[i].text);
+ }
+ }
+
+ SelectObject(hdc, hfntSave);
+
+ DeleteDC(hdc);
+ MakeBitmapOpaque(hbmp);
+ SetThumbnail(hbmp);
+ DeleteObject(hbmp);
+}
+
+void CSrmmProxyWindow::OnRenderPreview()
+{
+ if (!m_hbmpPreview) return;
+
+ RECT rc;
+ GetWindowRect(m_hwndWindow, &rc);
+ MapWindowPoints(NULL, m_hwndParent, (POINT *)&rc, 2);
+ SetPreview(m_hbmpPreview, rc.left, rc.top);
+}
+
+void CSrmmProxyWindow::OnTimer(int)
+{
+ g_pTaskbarList->UnregisterTab(m_hwndParent);
+
+ if (!m_refreshPreview) return;
+ if (!IsWindowVisible(m_hwndWindow) || !IsWindowVisible(m_hwndParent) || IsIconic(m_hwndParent)) return;
+ if (m_hbmpPreview) DeleteObject(m_hbmpPreview);
+
+ m_refreshPreview = false;
+
+ RECT rc;
+ GetWindowRect(m_hwndWindow, &rc);
+
+ m_hbmpPreview = CreateDwmBitmap(rc.right - rc.left, rc.bottom - rc.top);
+ HDC hdc = CreateCompatibleDC(0);
+ HBITMAP hbmpSave = (HBITMAP)SelectObject(hdc, m_hbmpPreview);
+ PrintWindow(m_hwndWindow, hdc, PW_CLIENTONLY);
+ SelectObject(hdc, hbmpSave);
+ DeleteDC(hdc);
+
+ MakeBitmapOpaque(m_hbmpPreview);
+
+ InvalidateThumbnail();
+}
+
+void CSrmmProxyWindow::OnClose()
+{
+ SendMessage(m_hwndWindow, WM_CLOSE, 1, 0);
+} \ No newline at end of file
diff --git a/plugins/w7ui/srmmproxywindow.h b/plugins/w7ui/srmmproxywindow.h
new file mode 100644
index 0000000000..f1c447d4e8
--- /dev/null
+++ b/plugins/w7ui/srmmproxywindow.h
@@ -0,0 +1,42 @@
+#ifndef srmmproxywindow_h__
+#define srmmproxywindow_h__
+
+class CSrmmProxyWindow: public CDwmWindow
+{
+public:
+ CSrmmProxyWindow(HANDLE hContact, HWND hwndWindow, HWND hwndParent);
+ ~CSrmmProxyWindow();
+
+ void OnTabActive();
+ void OnTabInactive();
+
+private:
+ HANDLE m_hContact;
+ HWND m_hwndWindow, m_hwndParent;
+ HBITMAP m_hbmpPreview;
+ bool m_refreshPreview;
+ bool m_bActive, m_bUnread, m_bTyping;
+
+ void Refresh();
+
+ int __cdecl OnDbEventAdded(WPARAM wParam, LPARAM lParam);
+ int __cdecl OnDbSettingChanged(WPARAM wParam, LPARAM lParam);
+ int __cdecl OnAvatarChanged(WPARAM wParam, LPARAM lParam);
+ int __cdecl OnContactTyping(WPARAM wParam, LPARAM lParam);
+
+ HANDLE SetEventHook(char *evt, int (__cdecl CSrmmProxyWindow::*fn)(WPARAM, LPARAM));
+
+ void UpdateIcon();
+
+ bool IsActive();
+
+protected:
+ void OnActivate(HWND hwndFrom);
+ void OnToolbar(int id, INT_PTR data);
+ void OnRenderThumbnail(int width, int height);
+ void OnRenderPreview();
+ void OnTimer(int);
+ void OnClose();
+};
+
+#endif // srmmproxywindow_h__
diff --git a/plugins/w7ui/subclassmgr.cpp b/plugins/w7ui/subclassmgr.cpp
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/plugins/w7ui/subclassmgr.cpp
diff --git a/plugins/w7ui/subclassmgr.h b/plugins/w7ui/subclassmgr.h
new file mode 100644
index 0000000000..1cf2433254
--- /dev/null
+++ b/plugins/w7ui/subclassmgr.h
@@ -0,0 +1,71 @@
+#ifndef subclassmgr_h__
+#define subclassmgr_h__
+
+struct TSubclassData
+{
+ WNDPROC oldWndProc;
+ LPARAM lParam;
+};
+
+typedef LRESULT (*TSubclassProc)(MSG *msg, TSubclassData *data);
+
+class CSubclassMgr
+{
+public:
+ static void Subclass(HWND hwnd, TSubclassProc newWndProc, LPARAM lParam)
+ {
+ TWindowInfo *wi = new TWindowInfo;
+ wi->hwnd = hwnd;
+ wi->newWndProc = newWndProc;
+ wi->lParam = lParam;
+ Instance().m_windows.insert(wi);
+ wi->oldWndProc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)GlobalSubclassProc);
+ }
+
+private:
+ CSubclassMgr(): m_windows(5, TWindowInfo::Compare) {}
+ CSubclassMgr(const CSubclassMgr &);
+ CSubclassMgr &operator=(const CSubclassMgr &);
+
+ static CSubclassMgr &Instance()
+ {
+ static CSubclassMgr theInstance;
+ return theInstance;
+ }
+
+ struct TWindowInfo
+ {
+ HWND hwnd;
+ WNDPROC oldWndProc;
+ TSubclassProc newWndProc;
+ LPARAM lParam;
+
+ static int Compare(const TWindowInfo *p1, const TWindowInfo *p2)
+ {
+ return (int)p1->hwnd - (int)p2->hwnd;
+ }
+ };
+
+ OBJLIST<TWindowInfo> m_windows;
+
+ static LRESULT CALLBACK GlobalSubclassProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+ {
+ TWindowInfo search = { hwnd };
+ TWindowInfo *wnd = Instance().m_windows.find(&search);
+ if (!wnd) return DefWindowProc(hwnd, message, wParam, lParam);
+
+ MSG msg = { hwnd, message, wParam, lParam };
+ TSubclassData data = { wnd->oldWndProc, wnd->lParam };
+ LRESULT result = wnd->newWndProc(&msg, &data);
+
+ if (message == WM_DESTROY)
+ {
+ SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)wnd->oldWndProc);
+ Instance().m_windows.remove(wnd);
+ }
+
+ return result;
+ }
+};
+
+#endif // subclassmgr_h__
diff --git a/plugins/w7ui/w7ui.cpp b/plugins/w7ui/w7ui.cpp
new file mode 100644
index 0000000000..afce9b65eb
--- /dev/null
+++ b/plugins/w7ui/w7ui.cpp
@@ -0,0 +1,180 @@
+#include "headers.h"
+
+ITaskbarList3 *g_pTaskbarList = NULL;
+UINT g_wm_TaskbarButtonCreated = 0;
+HANDLE hSrmmWindows = NULL;
+
+int g_eventSlotTyping = 0;
+int g_eventSlotMessage = 0;
+
+void InitJumpList();
+
+static LRESULT CALLBACK W7UIHostWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+static LRESULT CALLBACK W7SrmmProxyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+static int OnModulesLoaded(WPARAM, LPARAM);
+static int OnProcessSrmmEvent(WPARAM, LPARAM lParam);
+static int OnStatusModeChanged(WPARAM wParam, LPARAM);
+
+int LoadW7UI()
+{
+ CoInitialize(NULL);
+
+ CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void **)&g_pTaskbarList);
+ g_pTaskbarList->HrInit();
+
+ g_wm_TaskbarButtonCreated = RegisterWindowMessage(_T("TaskbarButtonCreated"));
+
+ CJumpListBuilder::Load();
+ LoadJumpList();
+
+ HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
+ HookEvent(ME_CLIST_STATUSMODECHANGE, OnStatusModeChanged);
+
+ hSrmmWindows = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0);
+ new CClistProxyWindow();
+
+ return 0;
+}
+
+int UnloadW7UI()
+{
+ CJumpListBuilder::Unload();
+ return 0;
+}
+
+static int OnContactIsTyping(WPARAM wParam, LPARAM lParam)
+{
+ if (!wParam) return 0;
+
+ if (lParam) g_clistProxyWnd->AddOverlayEvent(g_eventSlotTyping);
+ else g_clistProxyWnd->RemoveOverlayEvent(g_eventSlotTyping);
+
+ return 0;
+}
+
+static int OnModulesLoaded(WPARAM, LPARAM)
+{
+ InitJumpList();
+ g_eventSlotMessage = g_clistProxyWnd->AllocateOverlayEvent(LoadSkinnedIconHandle(SKINICON_EVENT_MESSAGE));
+ g_eventSlotTyping = g_clistProxyWnd->AllocateOverlayEvent(LoadSkinnedIconHandle(SKINICON_OTHER_TYPING));
+ OnStatusModeChanged(CallService(MS_CLIST_GETSTATUSMODE, 0, 0), 0);
+ HookEvent(ME_MSG_WINDOWEVENT, OnProcessSrmmEvent);
+ HookEvent(ME_PROTO_CONTACTISTYPING, OnContactIsTyping);
+ return 0;
+}
+
+static LRESULT SrmmSubclassProc(MSG *msg, TSubclassData *data)
+{
+ HWND hwndProxy = WindowList_Find(hSrmmWindows, (HANDLE)data->lParam);
+ CSrmmProxyWindow *wnd = CDwmWindow::GetWindow<CSrmmProxyWindow>(hwndProxy);
+
+ if (wnd)
+ {
+ switch (msg->message)
+ {
+ case WM_SETFOCUS:
+ wnd->OnTabActive();
+ break;
+ case WM_ACTIVATE:
+ switch (msg->wParam)
+ {
+ case WA_ACTIVE:
+ case WA_CLICKACTIVE:
+ wnd->OnTabActive();
+ break;
+ case WA_INACTIVE:
+ wnd->OnTabInactive();
+ }
+ break;
+ case WM_NCACTIVATE:
+ if (msg->wParam)
+ wnd->OnTabActive();
+ else
+ wnd->OnTabInactive();
+ break;
+ }
+ }
+
+ return CallWindowProc(data->oldWndProc, msg->hwnd, msg->message, msg->wParam, msg->lParam);
+}
+
+static HWND FindParent(HWND hwnd)
+{
+ while (1)
+ {
+ HWND hwndParent = GetParent(hwnd);
+ if (hwndParent == NULL)
+ return hwnd;
+ hwnd = hwndParent;
+ }
+}
+
+int OnProcessSrmmEvent(WPARAM, LPARAM lParam)
+{
+ MessageWindowEventData *evt = (MessageWindowEventData *)lParam;
+
+ switch (evt->uType)
+ {
+ case MSG_WINDOW_EVT_OPENING:
+ {
+ CSubclassMgr::Subclass(evt->hwndWindow, SrmmSubclassProc, (LPARAM)evt->hContact);
+ break;
+ }
+
+ case MSG_WINDOW_EVT_OPEN:
+ {
+ HWND hwndParent = FindParent(evt->hwndWindow);
+ if (hwndParent != evt->hwndWindow)
+ {
+ SetWindowLong(hwndParent, GWL_EXSTYLE, GetWindowLong(hwndParent, GWL_EXSTYLE) & ~WS_EX_APPWINDOW);
+ CSrmmProxyWindow *wnd = new CSrmmProxyWindow(evt->hContact, evt->hwndWindow, hwndParent);
+ HWND hwndProxy = wnd->hwnd();
+ g_pTaskbarList->UnregisterTab(hwndParent);
+ g_pTaskbarList->RegisterTab(hwndProxy, hwndParent);
+ g_pTaskbarList->SetTabOrder(hwndProxy, 0);
+ g_pTaskbarList->SetTabActive(hwndProxy, hwndParent, TBATF_USEMDITHUMBNAIL);
+ WindowList_Add(hSrmmWindows, hwndProxy, evt->hContact);
+ }
+ break;
+ }
+
+ case MSG_WINDOW_EVT_CLOSING:
+ {
+ HWND hwndProxy = WindowList_Find(hSrmmWindows, evt->hContact);
+ if (hwndProxy)
+ {
+ WindowList_Remove(hSrmmWindows, hwndProxy);
+ g_pTaskbarList->UnregisterTab(hwndProxy);
+ DestroyWindow(hwndProxy);
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// status processing
+
+int OnStatusModeChanged(WPARAM wParam, LPARAM)
+{
+ static int icons[] =
+ {
+ SKINICON_STATUS_OFFLINE,
+ SKINICON_STATUS_ONLINE,
+ SKINICON_STATUS_AWAY,
+ SKINICON_STATUS_DND,
+ SKINICON_STATUS_NA,
+ SKINICON_STATUS_OCCUPIED,
+ SKINICON_STATUS_FREE4CHAT,
+ SKINICON_STATUS_INVISIBLE,
+ SKINICON_STATUS_ONTHEPHONE,
+ SKINICON_STATUS_OUTTOLUNCH,
+ };
+
+ g_clistProxyWnd->SetOverlayIcon(LoadSkinnedIcon(icons[wParam - ID_STATUS_OFFLINE]));
+
+ return 0;
+}
diff --git a/plugins/w7ui/w7ui_10.sln b/plugins/w7ui/w7ui_10.sln
new file mode 100644
index 0000000000..025cd91ade
--- /dev/null
+++ b/plugins/w7ui/w7ui_10.sln
@@ -0,0 +1,37 @@
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "w7ui", "w7ui_10.vcxproj", "{86704897-EABF-439D-BE0E-52CEA67C2C43}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug Unicode|Win32 = Debug Unicode|Win32
+ Debug Unicode|x64 = Debug Unicode|x64
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release Unicode|Win32 = Release Unicode|Win32
+ Release Unicode|x64 = Release Unicode|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Debug Unicode|Win32.ActiveCfg = Debug Unicode|Win32
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Debug Unicode|Win32.Build.0 = Debug Unicode|Win32
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Debug Unicode|x64.ActiveCfg = Debug Unicode|x64
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Debug Unicode|x64.Build.0 = Debug Unicode|x64
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Debug|Win32.ActiveCfg = Debug|Win32
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Debug|Win32.Build.0 = Debug|Win32
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Debug|x64.ActiveCfg = Debug|x64
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Debug|x64.Build.0 = Debug|x64
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Release Unicode|Win32.ActiveCfg = Release Unicode|Win32
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Release Unicode|Win32.Build.0 = Release Unicode|Win32
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Release Unicode|x64.ActiveCfg = Release Unicode|x64
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Release Unicode|x64.Build.0 = Release Unicode|x64
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Release|Win32.ActiveCfg = Release|Win32
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Release|Win32.Build.0 = Release|Win32
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Release|x64.ActiveCfg = Release|x64
+ {86704897-EABF-439D-BE0E-52CEA67C2C43}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/plugins/w7ui/w7ui_10.vcxproj b/plugins/w7ui/w7ui_10.vcxproj
new file mode 100644
index 0000000000..9f35dff44e
--- /dev/null
+++ b/plugins/w7ui/w7ui_10.vcxproj
@@ -0,0 +1,364 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug Unicode|Win32">
+ <Configuration>Debug Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug Unicode|x64">
+ <Configuration>Debug Unicode</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release Unicode|Win32">
+ <Configuration>Release Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release Unicode|x64">
+ <Configuration>Release Unicode</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>w7ui</ProjectName>
+ <ProjectGuid>{86704897-EABF-439D-BE0E-52CEA67C2C43}</ProjectGuid>
+ <RootNamespace>w7ui</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">$(SolutionDir)$(Configuration)/Plugins\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">$(SolutionDir)$(Configuration)64/Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">$(SolutionDir)$(Configuration)/Obj/$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">$(SolutionDir)$(Configuration)64/Obj/$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">false</LinkIncremental>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;W7UI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>msimg32.lib;dwmapi.lib;comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;W7UI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>msimg32.lib;dwmapi.lib;comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;W7UI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>msimg32.lib;dwmapi.lib;comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;W7UI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>msimg32.lib;dwmapi.lib;comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;W7UI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>msimg32.lib;dwmapi.lib;comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Unicode|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;W7UI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>msimg32.lib;dwmapi.lib;comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|Win32'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;W7UI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>msimg32.lib;dwmapi.lib;comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Unicode|x64'">
+ <ClCompile>
+ <Optimization>Full</Optimization>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;W7UI_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>msimg32.lib;dwmapi.lib;comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="clistproxywindow.cpp" />
+ <ClCompile Include="dwmwindow.cpp" />
+ <ClCompile Include="jumplist.cpp" />
+ <ClCompile Include="jumplistarray.cpp" />
+ <ClCompile Include="jumplistbuilder.cpp" />
+ <ClCompile Include="main.cpp" />
+ <ClCompile Include="srmmproxywindow.cpp" />
+ <ClCompile Include="subclassmgr.cpp" />
+ <ClCompile Include="w7ui.cpp" />
+ <ClCompile Include="win7api.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="clistproxywindow.h" />
+ <ClInclude Include="dwmwindow.h" />
+ <ClInclude Include="headers.h" />
+ <ClInclude Include="jumplist.h" />
+ <ClInclude Include="jumplistarray.h" />
+ <ClInclude Include="jumplistbuilder.h" />
+ <ClInclude Include="m_w7ui.h" />
+ <ClInclude Include="srmmproxywindow.h" />
+ <ClInclude Include="subclassmgr.h" />
+ <ClInclude Include="win7api.h" />
+ <ClInclude Include="win7api_ICustomDestinationList.h" />
+ <ClInclude Include="win7api_IObjectArray.h" />
+ <ClInclude Include="win7api_IObjectCollection.h" />
+ <ClInclude Include="win7api_ITaskbarList3.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/w7ui/win7api.cpp b/plugins/w7ui/win7api.cpp
new file mode 100644
index 0000000000..dcfb6058ec
--- /dev/null
+++ b/plugins/w7ui/win7api.cpp
@@ -0,0 +1,25 @@
+#include <windows.h>
+
+//extern "C" const CLSID CLSID_TaskbarList = {0x56fdf344,0xfd6d,0x11d0,{0x95,0x8a,0x00,0x60,0x97,0xc9,0xa0,0x90}}; // 56fdf344-fd6d-11d0-958a-006097c9a090;
+//extern "C" const IID IID_ITaskbarList = {0x56FDF342,0xFD6D,0x11d0,{0x95,0x8A,0x00,0x60,0x97,0xC9,0xA0,0x90}}; // 56FDF342-FD6D-11d0-958A-006097C9A090;
+//extern "C" const IID IID_ITaskbarList2 = {0x602D4995,0xB13A,0x429b,{0xA6,0x6E,0x19,0x35,0xE4,0x4F,0x43,0x17}}; // 602D4995-B13A-429b-A66E-1935E44F4317;
+//extern "C" const IID IID_ICustomDestinationList = {0x6332debf,0x87b5,0x4670,{0x90,0xc0,0x5e,0x57,0xb4,0x08,0xa4,0x9e}}; // 6332debf-87b5-4670-90c0-5e57b408a49e
+//extern "C" const IID IID_IObjectArray = {0x92CA9DCD,0x5622,0x4bba,{0xA8,0x05,0x5E,0x9F,0x54,0x1B,0xD8,0xC9}}; // 92CA9DCD-5622-4bba-A805-5E9F541BD8C9
+//extern "C" const IID IID_IObjectCollection = {0x5632b1a4,0xe38a,0x400a,{0x92,0x8a,0xd4,0xcd,0x63,0x23,0x02,0x95}}; // 5632b1a4-e38a-400a-928a-d4cd63230295
+//extern "C" const IID IID_ITaskbarList3 = {0xea1afb91,0x9e28,0x4b86,{0x90,0xe9,0x9e,0x9f,0x8a,0x5e,0xef,0xaf}}; // ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf
+extern "C" const CLSID CLSID_CustomDestinationList = {0x77f10cf0,0x3db5,0x4966,{0xb5,0x20,0xb7,0xc5,0x4f,0xd3,0x5e,0xd6}};
+//extern "C" const CLSID CLSID_EnumerableObjectCollection = {0x2d3468c1,0x36a7,0x43b6,{0xac,0x24,0xd3,0xf0,0x2f,0xd9,0x60,0x7a}};
+
+HRESULT (WINAPI *dwmInvalidateIconicBitmaps)(HWND) =
+ (HRESULT (WINAPI *)(HWND))GetProcAddress(LoadLibraryA("dwmapi.dll"), "DwmInvalidateIconicBitmaps");
+HRESULT (WINAPI *dwmSetIconicThumbnail)(HWND, HBITMAP, DWORD) =
+ (HRESULT (WINAPI *)(HWND, HBITMAP, DWORD))GetProcAddress(LoadLibraryA("dwmapi.dll"), "DwmSetIconicThumbnail");
+HRESULT (WINAPI *dwmSetIconicLivePreviewBitmap)(HWND, HBITMAP, LPPOINT, DWORD) =
+ (HRESULT (WINAPI *)(HWND, HBITMAP, LPPOINT, DWORD))GetProcAddress(LoadLibraryA("dwmapi.dll"), "DwmSetIconicLivePreviewBitmap");
+
+HANDLE (STDAPICALLTYPE *openThemeData)(HWND, LPCWSTR) =
+ (HANDLE (STDAPICALLTYPE *)(HWND, LPCWSTR))GetProcAddress(LoadLibraryA("uxtheme.dll"), "OpenThemeData");
+HRESULT (STDAPICALLTYPE *drawThemeTextEx)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, LPRECT, const struct _DTTOPTS *) =
+ (HRESULT (STDAPICALLTYPE *)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, LPRECT, const struct _DTTOPTS *))GetProcAddress(LoadLibraryA("uxtheme.dll"), "DrawThemeTextEx");
+HRESULT (STDAPICALLTYPE *closeThemeData)(HANDLE) =
+ (HRESULT (STDAPICALLTYPE *)(HANDLE))GetProcAddress(LoadLibraryA("uxtheme.dll"), "CloseThemeData");
diff --git a/plugins/w7ui/win7api.h b/plugins/w7ui/win7api.h
new file mode 100644
index 0000000000..f9fa806335
--- /dev/null
+++ b/plugins/w7ui/win7api.h
@@ -0,0 +1,38 @@
+#ifndef win7api_h__
+#define win7api_h__
+
+#define WM_DWMSENDICONICTHUMBNAIL 0x0323
+#define WM_DWMSENDICONICLIVEPREVIEWBITMAP 0x0326
+
+#define DWMWA_HAS_ICONIC_BITMAP 10
+
+#define DWM_SIT_DISPLAYFRAME 0x00000001
+
+enum TBATFLAG
+{ TBATF_USEMDITHUMBNAIL = 0x1,
+ TBATF_USEMDILIVEPREVIEW = 0x2
+};
+
+#define THBN_CLICKED 0x1800
+
+extern HRESULT (WINAPI *dwmInvalidateIconicBitmaps)(HWND);
+extern HRESULT (WINAPI *dwmSetIconicThumbnail)(HWND, HBITMAP, DWORD);
+extern HRESULT (WINAPI *dwmSetIconicLivePreviewBitmap)(HWND, HBITMAP, LPPOINT, DWORD);
+
+extern HANDLE (STDAPICALLTYPE *openThemeData)(HWND, LPCWSTR);
+extern HRESULT (STDAPICALLTYPE *drawThemeTextEx)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, LPRECT, const struct _DTTOPTS *);
+extern HRESULT (STDAPICALLTYPE *closeThemeData)(HANDLE);
+
+extern "C" const IID IID_ICustomDestinationList;
+extern "C" const IID IID_IObjectArray;
+extern "C" const IID IID_IObjectCollection;
+extern "C" const IID IID_ITaskbarList3;
+extern "C" const CLSID CLSID_CustomDestinationList;
+extern "C" const CLSID CLSID_EnumerableObjectCollection;
+
+#include "win7api_IObjectArray.h"
+#include "win7api_IObjectCollection.h"
+#include "win7api_ICustomDestinationList.h"
+//#include "win7api_ITaskbarList3.h"
+
+#endif // win7api_h__
diff --git a/plugins/w7ui/win7api_ICustomDestinationList.h b/plugins/w7ui/win7api_ICustomDestinationList.h
new file mode 100644
index 0000000000..6d3f770d29
--- /dev/null
+++ b/plugins/w7ui/win7api_ICustomDestinationList.h
@@ -0,0 +1,34 @@
+#ifndef __ICustomDestinationList_INTERFACE_DEFINED__
+#define __ICustomDestinationList_INTERFACE_DEFINED__
+
+typedef /* [v1_enum] */ enum tagKNOWNDESTCATEGORY {
+ KDC_FREQUENT = 1,
+ KDC_RECENT = (KDC_FREQUENT + 1)
+} KNOWNDESTCATEGORY;
+
+MIDL_INTERFACE("6332debf-87b5-4670-90c0-5e57b408a49e")
+ICustomDestinationList : public IUnknown {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE SetAppID(
+ /* [string][in] */__RPC__in_string LPCWSTR pszAppID) = 0;
+ virtual HRESULT STDMETHODCALLTYPE BeginList(
+ /* [out] */ __RPC__out UINT *pcMaxSlots,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = 0;
+ virtual HRESULT STDMETHODCALLTYPE AppendCategory(
+ /* [string][in] */ __RPC__in_string LPCWSTR pszCategory,
+ /* [in] */ __RPC__in_opt IObjectArray *poa) = 0;
+ virtual HRESULT STDMETHODCALLTYPE AppendKnownCategory(
+ /* [in] */ KNOWNDESTCATEGORY category) = 0;
+ virtual HRESULT STDMETHODCALLTYPE AddUserTasks(
+ /* [in] */ __RPC__in_opt IObjectArray *poa) = 0;
+ virtual HRESULT STDMETHODCALLTYPE CommitList(void) = 0;
+ virtual HRESULT STDMETHODCALLTYPE GetRemovedDestinations(
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = 0;
+ virtual HRESULT STDMETHODCALLTYPE DeleteList(
+ /* [string][in] */ __RPC__in_string LPCWSTR pszAppID) = 0;
+ virtual HRESULT STDMETHODCALLTYPE AbortList(void) = 0;
+};
+
+#endif // __ICustomDestinationList_INTERFACE_DEFINED__
diff --git a/plugins/w7ui/win7api_IObjectArray.h b/plugins/w7ui/win7api_IObjectArray.h
new file mode 100644
index 0000000000..2102276989
--- /dev/null
+++ b/plugins/w7ui/win7api_IObjectArray.h
@@ -0,0 +1,15 @@
+#ifndef __IObjectArray_INTERFACE_DEFINED__
+#define __IObjectArray_INTERFACE_DEFINED__
+
+MIDL_INTERFACE("92CA9DCD-5622-4bba-A805-5E9F541BD8C9")
+IObjectArray : public IUnknown {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetCount(
+ /* [out] */ __RPC__out UINT *pcObjects) = 0;
+ virtual HRESULT STDMETHODCALLTYPE GetAt(
+ /* [in] */ UINT uiIndex,
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */ __RPC__deref_out_opt void **ppv) = 0;
+};
+
+#endif // __IObjectArray_INTERFACE_DEFINED__
diff --git a/plugins/w7ui/win7api_IObjectCollection.h b/plugins/w7ui/win7api_IObjectCollection.h
new file mode 100644
index 0000000000..71b37d0e99
--- /dev/null
+++ b/plugins/w7ui/win7api_IObjectCollection.h
@@ -0,0 +1,16 @@
+#ifndef __IObjectCollection_INTERFACE_DEFINED__
+#define __IObjectCollection_INTERFACE_DEFINED__
+
+MIDL_INTERFACE("5632b1a4-e38a-400a-928a-d4cd63230295")
+IObjectCollection : public IObjectArray {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE AddObject(
+ /* [in] */ __RPC__in_opt IUnknown *punk) = 0;
+ virtual HRESULT STDMETHODCALLTYPE AddFromArray(
+ /* [in] */ __RPC__in_opt IObjectArray *poaSource) = 0;
+ virtual HRESULT STDMETHODCALLTYPE RemoveObjectAt(
+ /* [in] */ UINT uiIndex) = 0;
+ virtual HRESULT STDMETHODCALLTYPE Clear(void) = 0;
+};
+
+#endif // __IObjectCollection_INTERFACE_DEFINED__
diff --git a/plugins/w7ui/win7api_ITaskbarList3.h b/plugins/w7ui/win7api_ITaskbarList3.h
new file mode 100644
index 0000000000..8c39fb5c41
--- /dev/null
+++ b/plugins/w7ui/win7api_ITaskbarList3.h
@@ -0,0 +1,65 @@
+#ifndef __ITaskbarList3_FWD_DEFINED__
+#define __ITaskbarList3_FWD_DEFINED__
+typedef interface ITaskbarList3 ITaskbarList3;
+#endif /* __ITaskbarList3_FWD_DEFINED__ */
+
+/* interface ITaskbarList3 */
+/* [object][uuid] */
+
+MIDL_INTERFACE("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")
+ITaskbarList3 : public ITaskbarList2
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE SetProgressValue(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [in] */ ULONGLONG ullCompleted,
+ /* [in] */ ULONGLONG ullTotal) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetProgressState(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [in] */ TBPFLAG tbpFlags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RegisterTab(
+ /* [in] */ __RPC__in HWND hwndTab,
+ /* [in] */ __RPC__in HWND hwndMDI) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE UnregisterTab(
+ /* [in] */ __RPC__in HWND hwndTab) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetTabOrder(
+ /* [in] */ __RPC__in HWND hwndTab,
+ /* [in] */ __RPC__in HWND hwndInsertBefore) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetTabActive(
+ /* [in] */ __RPC__in HWND hwndTab,
+ /* [in] */ __RPC__in HWND hwndMDI,
+ /* [in] */ TBATFLAG tbatFlags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ThumbBarAddButtons(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [in] */ UINT cButtons,
+ /* [size_is][in] */ __RPC__in_ecount_full(cButtons) LPTHUMBBUTTON pButton) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ThumbBarUpdateButtons(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [in] */ UINT cButtons,
+ /* [size_is][in] */ __RPC__in_ecount_full(cButtons) LPTHUMBBUTTON pButton) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ThumbBarSetImageList(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [in] */ __RPC__in_opt HIMAGELIST himl) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetOverlayIcon(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [in] */ __RPC__in HICON hIcon,
+ /* [string][in] */ __RPC__in_string LPCWSTR pszDescription) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetThumbnailTooltip(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [string][in] */ __RPC__in_string LPCWSTR pszTip) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetThumbnailClip(
+ /* [in] */ __RPC__in HWND hwnd,
+ /* [in] */ __RPC__in RECT *prcClip) = 0;
+
+};