summaryrefslogtreecommitdiff
path: root/plugins/Clist_modern/src
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Clist_modern/src')
-rw-r--r--plugins/Clist_modern/src/MString.cpp205
-rw-r--r--plugins/Clist_modern/src/hdr/MString.h2304
-rw-r--r--plugins/Clist_modern/src/hdr/modern_awaymsg.h37
-rw-r--r--plugins/Clist_modern/src/hdr/modern_cache_funcs.h46
-rw-r--r--plugins/Clist_modern/src/hdr/modern_callproc.h128
-rw-r--r--plugins/Clist_modern/src/hdr/modern_clc.h515
-rw-r--r--plugins/Clist_modern/src/hdr/modern_clcpaint.h191
-rw-r--r--plugins/Clist_modern/src/hdr/modern_clist.h165
-rw-r--r--plugins/Clist_modern/src/hdr/modern_clui.h193
-rw-r--r--plugins/Clist_modern/src/hdr/modern_cluiframes.h150
-rw-r--r--plugins/Clist_modern/src/hdr/modern_commonheaders.h460
-rw-r--r--plugins/Clist_modern/src/hdr/modern_commonprototypes.h356
-rw-r--r--plugins/Clist_modern/src/hdr/modern_defsettings.h284
-rw-r--r--plugins/Clist_modern/src/hdr/modern_effectenum.h93
-rw-r--r--plugins/Clist_modern/src/hdr/modern_gettextasync.h5
-rw-r--r--plugins/Clist_modern/src/hdr/modern_global_structure.h92
-rw-r--r--plugins/Clist_modern/src/hdr/modern_image_array.h104
-rw-r--r--plugins/Clist_modern/src/hdr/modern_layered_window_engine.h51
-rw-r--r--plugins/Clist_modern/src/hdr/modern_log.h27
-rw-r--r--plugins/Clist_modern/src/hdr/modern_popup.h48
-rw-r--r--plugins/Clist_modern/src/hdr/modern_row.h86
-rw-r--r--plugins/Clist_modern/src/hdr/modern_rowheight_funcs.h70
-rw-r--r--plugins/Clist_modern/src/hdr/modern_skinengine.h148
-rw-r--r--plugins/Clist_modern/src/hdr/modern_skinned_profile.h245
-rw-r--r--plugins/Clist_modern/src/hdr/modern_skinselector.h88
-rw-r--r--plugins/Clist_modern/src/hdr/modern_static_clui.h246
-rw-r--r--plugins/Clist_modern/src/hdr/modern_static_cluiframes_service.h192
-rw-r--r--plugins/Clist_modern/src/hdr/modern_statusbar.h44
-rw-r--r--plugins/Clist_modern/src/hdr/modern_statusmodes.h43
-rw-r--r--plugins/Clist_modern/src/hdr/modern_sync.h98
-rw-r--r--plugins/Clist_modern/src/hdr/modern_tstring.h58
-rw-r--r--plugins/Clist_modern/src/init.cpp244
-rw-r--r--plugins/Clist_modern/src/m_api/m_skin_eng.h434
-rw-r--r--plugins/Clist_modern/src/m_api/m_skinbutton.h31
-rw-r--r--plugins/Clist_modern/src/m_api/m_skinned_profile.h44
-rw-r--r--plugins/Clist_modern/src/m_api/m_xpTheme.h35
-rw-r--r--plugins/Clist_modern/src/modern_aniavatars.cpp1300
-rw-r--r--plugins/Clist_modern/src/modern_awaymsg.cpp232
-rw-r--r--plugins/Clist_modern/src/modern_cachefuncs.cpp968
-rw-r--r--plugins/Clist_modern/src/modern_callproc.cpp20
-rw-r--r--plugins/Clist_modern/src/modern_clc.cpp2107
-rw-r--r--plugins/Clist_modern/src/modern_clcidents.cpp299
-rw-r--r--plugins/Clist_modern/src/modern_clcitems.cpp819
-rw-r--r--plugins/Clist_modern/src/modern_clcmsgs.cpp262
-rw-r--r--plugins/Clist_modern/src/modern_clcopts.cpp2068
-rw-r--r--plugins/Clist_modern/src/modern_clcpaint.cpp3385
-rw-r--r--plugins/Clist_modern/src/modern_clcutils.cpp870
-rw-r--r--plugins/Clist_modern/src/modern_clistevents.cpp624
-rw-r--r--plugins/Clist_modern/src/modern_clistmenus.cpp217
-rw-r--r--plugins/Clist_modern/src/modern_clistmod.cpp567
-rw-r--r--plugins/Clist_modern/src/modern_clistopts.cpp1282
-rw-r--r--plugins/Clist_modern/src/modern_clistsettings.cpp531
-rw-r--r--plugins/Clist_modern/src/modern_clisttray.cpp736
-rw-r--r--plugins/Clist_modern/src/modern_clui.cpp3111
-rw-r--r--plugins/Clist_modern/src/modern_cluiframes.cpp4222
-rw-r--r--plugins/Clist_modern/src/modern_cluiservices.cpp178
-rw-r--r--plugins/Clist_modern/src/modern_commonheaders.cpp247
-rw-r--r--plugins/Clist_modern/src/modern_contact.cpp219
-rw-r--r--plugins/Clist_modern/src/modern_docking.cpp372
-rw-r--r--plugins/Clist_modern/src/modern_extraimage.cpp509
-rw-r--r--plugins/Clist_modern/src/modern_framesmenu.cpp214
-rw-r--r--plugins/Clist_modern/src/modern_gdiplus.cpp308
-rw-r--r--plugins/Clist_modern/src/modern_gettextasync.cpp205
-rw-r--r--plugins/Clist_modern/src/modern_global.cpp35
-rw-r--r--plugins/Clist_modern/src/modern_groupmenu.cpp754
-rw-r--r--plugins/Clist_modern/src/modern_image_array.cpp705
-rw-r--r--plugins/Clist_modern/src/modern_keyboard.cpp67
-rw-r--r--plugins/Clist_modern/src/modern_log.cpp46
-rw-r--r--plugins/Clist_modern/src/modern_newrowopts.cpp198
-rw-r--r--plugins/Clist_modern/src/modern_popup.cpp131
-rw-r--r--plugins/Clist_modern/src/modern_row.cpp789
-rw-r--r--plugins/Clist_modern/src/modern_rowheight_funcs.cpp796
-rw-r--r--plugins/Clist_modern/src/modern_rowtemplateopt.cpp704
-rw-r--r--plugins/Clist_modern/src/modern_skinbutton.cpp815
-rw-r--r--plugins/Clist_modern/src/modern_skineditor.cpp841
-rw-r--r--plugins/Clist_modern/src/modern_skinengine.cpp4650
-rw-r--r--plugins/Clist_modern/src/modern_skinned_profile.cpp115
-rw-r--r--plugins/Clist_modern/src/modern_skinopt.cpp771
-rw-r--r--plugins/Clist_modern/src/modern_skinselector.cpp792
-rw-r--r--plugins/Clist_modern/src/modern_statusbar.cpp1136
-rw-r--r--plugins/Clist_modern/src/modern_statusbar_options.cpp541
-rw-r--r--plugins/Clist_modern/src/modern_sync.cpp147
-rw-r--r--plugins/Clist_modern/src/modern_tbbutton.cpp503
-rw-r--r--plugins/Clist_modern/src/modern_toolbar.cpp357
-rw-r--r--plugins/Clist_modern/src/modern_viewmodebar.cpp1574
-rw-r--r--plugins/Clist_modern/src/modern_xptheme.cpp265
-rw-r--r--plugins/Clist_modern/src/resource.h1053
-rw-r--r--plugins/Clist_modern/src/version.h15
88 files changed, 51232 insertions, 0 deletions
diff --git a/plugins/Clist_modern/src/MString.cpp b/plugins/Clist_modern/src/MString.cpp
new file mode 100644
index 0000000000..caba4e022c
--- /dev/null
+++ b/plugins/Clist_modern/src/MString.cpp
@@ -0,0 +1,205 @@
+
+#include <windows.h>
+#include <stdio.h>
+#include <win2k.h>
+#include "hdr/MString.h"
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CMBaseString
+
+CNilMStringData CMBaseString::m_nil;
+
+CMStringData* CMBaseString::Allocate( int nChars, int nCharSize )
+{
+ CMStringData* pData;
+ nChars++; // nil char
+ size_t nDataBytes = nCharSize * nChars;
+ size_t nTotalSize = nDataBytes + sizeof(CMStringData);
+
+ pData = static_cast<CMStringData*>(malloc(nTotalSize));
+ if (pData == NULL)
+ return NULL;
+
+ pData->nRefs = 1;
+ pData->nAllocLength = nChars - 1;
+ pData->nDataLength = 0;
+ return pData;
+}
+
+void CMBaseString::Free(CMStringData* pData)
+{
+ free(pData);
+}
+
+CMStringData* CMBaseString::Realloc(CMStringData* pData, int nChars, int nCharSize)
+{
+ CMStringData* pNewData;
+ nChars++; // nil char
+ ULONG nDataBytes = nCharSize * nChars;
+ ULONG nTotalSize = nDataBytes + sizeof(CMStringData);
+
+ pNewData = static_cast<CMStringData*>(realloc(pData, nTotalSize));
+ if (pNewData == NULL)
+ return NULL;
+
+ pNewData->nAllocLength = nChars - 1;
+ return pNewData;
+}
+
+CMStringData* CMBaseString::GetNilString()
+{
+ m_nil.AddRef();
+ return &m_nil;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// CMStringData
+
+void* CMStringData::data()
+{
+ return (this + 1);
+}
+
+void CMStringData::AddRef()
+{
+ InterlockedIncrement(&nRefs);
+}
+
+bool CMStringData::IsLocked() const
+{
+ return nRefs < 0;
+}
+
+bool CMStringData::IsShared() const
+{
+ return (nRefs > 1);
+}
+
+void CMStringData::Lock()
+{
+ nRefs--; // Locked buffers can't be shared, so no interlocked operation necessary
+ if ( nRefs == 0 )
+ nRefs = -1;
+}
+
+void CMStringData::Release()
+{
+ if (InterlockedDecrement(&nRefs) <= 0)
+ CMBaseString::Free(this);
+}
+
+void CMStringData::Unlock()
+{
+ if (IsLocked())
+ {
+ nRefs++; // Locked buffers can't be shared, so no interlocked operation necessary
+ if (nRefs == 0)
+ nRefs = 1;
+ }
+}
+
+CNilMStringData::CNilMStringData()
+{
+ nRefs = 2; // Never gets freed
+ nDataLength = 0;
+ nAllocLength = 0;
+ achNil[0] = 0;
+ achNil[1] = 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// ChTraitsCRT<wchar_t>
+
+#if _MSC_VER < 1400
+static HINSTANCE hCrt = NULL;
+
+typedef int ( __cdecl *_vscprintf_func )( LPCSTR pszFormat, va_list args );
+static _vscprintf_func _vscprintf_ptr = NULL;
+
+typedef int ( __cdecl *_vscwprintf_func )( LPCWSTR pszFormat, va_list args );
+static _vscwprintf_func _vscwprintf_ptr = NULL;
+
+typedef int ( __cdecl *_vsnprintf_func )( char*, size_t, const char*, va_list );
+static _vsnprintf_func _vsnprintf_ptr = NULL;
+
+typedef int ( __cdecl *_vsnwprintf_func )( wchar_t *, size_t, const wchar_t *, va_list );
+static _vsnwprintf_func _vsnwprintf_ptr = NULL;
+
+typedef int ( __cdecl *vswprintf_func )( wchar_t *, size_t, const wchar_t *, va_list );
+static vswprintf_func vswprintf_ptr = NULL;
+
+typedef int ( __cdecl *vsprintf_func )( char*, size_t, const char*, va_list );
+static vsprintf_func vsprintf_ptr = NULL;
+
+static void checkCrt( void )
+{
+ if ( hCrt == NULL ) {
+ hCrt = GetModuleHandleA( "msvcrt.dll" );
+ _vscprintf_ptr = (_vscprintf_func)GetProcAddress( hCrt, "_vscprintf" );
+ _vscwprintf_ptr = (_vscwprintf_func)GetProcAddress( hCrt, "_vscwprintf" );
+ _vsnprintf_ptr = (_vsnprintf_func)GetProcAddress( hCrt, "_vsnprintf" );
+ _vsnwprintf_ptr = (_vsnwprintf_func)GetProcAddress( hCrt, "_vsnwprintf" );
+ vswprintf_ptr = (vswprintf_func)GetProcAddress( hCrt, "vswprintf" );
+ vsprintf_ptr = (vsprintf_func)GetProcAddress( hCrt, "vsprintf" );
+} }
+#endif
+
+int __stdcall ChTraitsCRT<wchar_t>::GetFormattedLength( LPCWSTR pszFormat, va_list args )
+{
+ #if _MSC_VER < 1400
+ checkCrt();
+
+ if ( _vscwprintf_ptr != NULL )
+ return _vscwprintf_ptr( pszFormat, args );
+
+ WCHAR buf[ 4000 ];
+ return vswprintf_ptr( buf, SIZEOF(buf), pszFormat, args );
+ #else
+ return _vscwprintf( pszFormat, args );
+ #endif
+}
+
+int __stdcall ChTraitsCRT<wchar_t>::Format( LPWSTR pszBuffer, size_t nLength, LPCWSTR pszFormat, va_list args)
+{
+ #if _MSC_VER < 1400
+ checkCrt();
+
+ if ( _vsnwprintf_ptr != NULL )
+ return _vsnwprintf_ptr( pszBuffer, nLength, pszFormat, args );
+
+ return vswprintf_ptr( pszBuffer, nLength, pszFormat, args );
+ #else
+ return _vsnwprintf( pszBuffer, nLength, pszFormat, args );
+ #endif
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// ChTraitsCRT<char>
+
+int __stdcall ChTraitsCRT<char>::GetFormattedLength( LPCSTR pszFormat, va_list args )
+{
+ #if _MSC_VER < 1400
+ checkCrt();
+
+ if ( _vscprintf_ptr != NULL )
+ return _vscprintf_ptr( pszFormat, args );
+
+ char buf[4000];
+ return vsprintf_ptr( buf, sizeof(buf), pszFormat, args );
+ #else
+ return _vscprintf( pszFormat, args );
+ #endif
+}
+
+int __stdcall ChTraitsCRT<char>::Format( LPSTR pszBuffer, size_t nlength, LPCSTR pszFormat, va_list args )
+{
+ #if _MSC_VER < 1400
+ checkCrt();
+
+ return _vsnprintf( pszBuffer, nlength, pszFormat, args );
+ #else
+ return vsprintf_s( pszBuffer, nlength, pszFormat, args );
+ #endif
+}
+
diff --git a/plugins/Clist_modern/src/hdr/MString.h b/plugins/Clist_modern/src/hdr/MString.h
new file mode 100644
index 0000000000..497f074e5d
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/MString.h
@@ -0,0 +1,2304 @@
+#pragma once
+
+#include <string.h>
+#include <mbstring.h>
+#include <wchar.h>
+
+#ifdef __MINGW32__
+#include <limits.h>
+
+__inline size_t strnlen(const char *string, size_t maxlen)
+{
+ const char *end = (const char *)memchr ((const void *)string, '\0', maxlen);
+ return end ? (size_t) (end - string) : maxlen;
+}
+__inline size_t wcsnlen(const wchar_t *string, size_t maxlen)
+{
+ const wchar_t *end = wmemchr (string, L'\0', maxlen);
+ return end ? (size_t) (end - string) : maxlen;
+}
+
+/* FIXME: This may be wrong assumption about _AtlGetConversionACP */
+#define _AtlGetConversionACP() CP_THREAD_ACP
+/* FIXME: This is unsafe */
+#define memcpy_s(dest,size,src,count) memcpy(dest,src,count)
+/* FIXME: This is quite silly implementation of _mbsstr */
+#define _mbsstr(str,search) strstr((const char *)str,(const char *)search)
+#define __max(x,y) (((x)<(y))?(y):(x))
+#endif /* __MINGW32__ */
+
+struct CMStringData
+{
+ int nDataLength; // Length of currently used data in XCHARs (not including terminating null)
+ int nAllocLength; // Length of allocated data in XCHARs (not including terminating null)
+ long nRefs; // Reference count: negative == locked
+ // XCHAR data[nAllocLength+1] // A CStringData is always followed in memory by the actual array of character data
+ void* data();
+ void AddRef();
+ bool IsLocked() const;
+ bool IsShared() const;
+ void Lock();
+ void Release();
+ void Unlock();
+};
+
+class CNilMStringData : public CMStringData
+{
+public:
+ CNilMStringData();
+
+public:
+ wchar_t achNil[2];
+};
+
+template< typename BaseType = char >
+class ChTraitsBase
+{
+public:
+ typedef char XCHAR;
+ typedef LPSTR PXSTR;
+ typedef LPCSTR PCXSTR;
+ typedef wchar_t YCHAR;
+ typedef LPWSTR PYSTR;
+ typedef LPCWSTR PCYSTR;
+};
+
+template<>
+class ChTraitsBase< wchar_t >
+{
+public:
+ typedef wchar_t XCHAR;
+ typedef LPWSTR PXSTR;
+ typedef LPCWSTR PCXSTR;
+ typedef char YCHAR;
+ typedef LPSTR PYSTR;
+ typedef LPCSTR PCYSTR;
+};
+
+class CMBaseString
+{
+public:
+ static CMStringData* Allocate(int nChars, int nCharSize);
+ static void Free(CMStringData* pData);
+ static CMStringData* Realloc(CMStringData* pData, int nChars, int nCharSize);
+
+protected:
+ static CMStringData* GetNilString();
+ static CNilMStringData m_nil;
+};
+
+template< typename BaseType >
+class CMSimpleStringT : public CMBaseString
+{
+public:
+ typedef typename ChTraitsBase< BaseType >::XCHAR XCHAR;
+ typedef typename ChTraitsBase< BaseType >::PXSTR PXSTR;
+ typedef typename ChTraitsBase< BaseType >::PCXSTR PCXSTR;
+ typedef typename ChTraitsBase< BaseType >::YCHAR YCHAR;
+ typedef typename ChTraitsBase< BaseType >::PYSTR PYSTR;
+ typedef typename ChTraitsBase< BaseType >::PCYSTR PCYSTR;
+
+public:
+ explicit CMSimpleStringT()
+ {
+ CMStringData* pData = GetNilString();
+ Attach(pData);
+ }
+
+ CMSimpleStringT(const CMSimpleStringT& strSrc)
+ {
+ CMStringData* pSrcData = strSrc.GetData();
+ CMStringData* pNewData = CloneData( pSrcData );
+ Attach( pNewData );
+ }
+
+ CMSimpleStringT(PCXSTR pszSrc)
+ {
+ int nLength = StringLength( pszSrc );
+ CMStringData* pData = Allocate( nLength, sizeof( XCHAR ));
+ if (pData != NULL)
+ {
+ Attach( pData );
+ SetLength( nLength );
+ CopyChars( m_pszData, nLength, pszSrc, nLength );
+ }
+ }
+ CMSimpleStringT(const XCHAR* pchSrc, int nLength)
+ {
+ CMStringData* pData = Allocate( nLength, sizeof( XCHAR ));
+ if ( pData != NULL )
+ {
+ Attach( pData );
+ SetLength( nLength );
+ CopyChars( m_pszData, nLength, pchSrc, nLength );
+ }
+ }
+ ~CMSimpleStringT()
+ {
+ CMStringData* pData = GetData();
+ pData->Release();
+ }
+
+ operator CMSimpleStringT<BaseType>&()
+ {
+ return *(CMSimpleStringT<BaseType>*)this;
+ }
+
+ CMSimpleStringT& operator=(const CMSimpleStringT& strSrc )
+ {
+ CMStringData* pSrcData = strSrc.GetData();
+ CMStringData* pOldData = GetData();
+ if ( pSrcData != pOldData)
+ {
+ if ( pOldData->IsLocked())
+ SetString( strSrc.GetString(), strSrc.GetLength());
+ else
+ {
+ CMStringData* pNewData = CloneData( pSrcData );
+ pOldData->Release();
+ Attach( pNewData );
+ }
+ }
+
+ return *this;
+ }
+
+ CMSimpleStringT& operator=(PCXSTR pszSrc)
+ {
+ SetString( pszSrc );
+ return *this;
+ }
+
+ CMSimpleStringT& operator+=( const CMSimpleStringT& strSrc )
+ {
+ Append( strSrc );
+
+ return *this;
+ }
+
+ CMSimpleStringT& operator+=( PCXSTR pszSrc )
+ {
+ Append( pszSrc );
+
+ return *this;
+ }
+ CMSimpleStringT& operator+=( char ch )
+ {
+ AppendChar(XCHAR(ch));
+
+ return *this;
+ }
+ CMSimpleStringT& operator+=( unsigned char ch )
+ {
+ AppendChar(XCHAR(ch));
+
+ return *this;
+ }
+ CMSimpleStringT& operator+=( wchar_t ch )
+ {
+ AppendChar(XCHAR(ch));
+
+ return *this;
+ }
+
+ XCHAR operator[]( int iChar ) const
+ {
+ return m_pszData[iChar];
+ }
+
+ operator PCXSTR() const
+ {
+ return m_pszData;
+ }
+
+ PCXSTR c_str() const
+ {
+ return m_pszData;
+ }
+
+ void Append( PCXSTR pszSrc )
+ {
+ Append( pszSrc, StringLength( pszSrc ));
+ }
+ void Append( PCXSTR pszSrc, int nLength )
+ {
+ // See comment in SetString() about why we do this
+ UINT_PTR nOffset = pszSrc - GetString();
+
+ UINT nOldLength = GetLength();
+ if (nOldLength < 0)
+ {
+ // protects from underflow
+ nOldLength = 0;
+ }
+
+ //Make sure we don't read pass end of the terminating NULL
+ int nSrcLength = StringLength(pszSrc);
+ nLength = nLength > nSrcLength ? nSrcLength: nLength;
+
+ int nNewLength = nOldLength+nLength;
+ PXSTR pszBuffer = GetBuffer( nNewLength );
+ if ( nOffset <= nOldLength )
+ {
+ pszSrc = pszBuffer+nOffset;
+ // No need to call CopyCharsOverlapped, since the destination is
+ // beyond the end of the original buffer
+ }
+ CopyChars( pszBuffer+nOldLength, nLength, pszSrc, nLength );
+ ReleaseBufferSetLength( nNewLength );
+ }
+ void AppendChar( XCHAR ch )
+ {
+ UINT nOldLength = GetLength();
+ int nNewLength = nOldLength+1;
+ PXSTR pszBuffer = GetBuffer( nNewLength );
+ pszBuffer[nOldLength] = ch;
+ ReleaseBufferSetLength( nNewLength );
+ }
+ void Append( const CMSimpleStringT& strSrc )
+ {
+ Append( strSrc.GetString(), strSrc.GetLength());
+ }
+ void Empty()
+ {
+ CMStringData* pOldData = GetData();
+ if ( pOldData->nDataLength == 0 )
+ return;
+
+ if ( pOldData->IsLocked())
+ {
+ // Don't reallocate a locked buffer that's shrinking
+ SetLength( 0 );
+ }
+ else
+ {
+ pOldData->Release();
+ CMStringData* pNewData = GetNilString();
+ Attach( pNewData );
+ }
+ }
+ void FreeExtra()
+ {
+ CMStringData* pOldData = GetData();
+ int nLength = pOldData->nDataLength;
+ if ( pOldData->nAllocLength == nLength )
+ return;
+
+ if ( !pOldData->IsLocked()) // Don't reallocate a locked buffer that's shrinking
+ {
+ CMStringData* pNewData = Allocate( nLength, sizeof( XCHAR ));
+ if ( pNewData == NULL ) {
+ SetLength( nLength );
+ return;
+ }
+
+ CopyChars( PXSTR( pNewData->data()), nLength, PCXSTR( pOldData->data()), nLength );
+
+ pOldData->Release();
+ Attach( pNewData );
+ SetLength( nLength );
+ }
+ }
+
+ int GetAllocLength() const
+ {
+ return GetData()->nAllocLength;
+ }
+ XCHAR GetAt( int iChar ) const
+ {
+ return m_pszData[iChar];
+ }
+ PXSTR GetBuffer()
+ {
+ CMStringData* pData = GetData();
+ if ( pData->IsShared())
+ Fork( pData->nDataLength );
+
+ return m_pszData;
+ }
+ PXSTR GetBuffer( int nMinBufferLength )
+ {
+ return PrepareWrite( nMinBufferLength );
+ }
+ PXSTR GetBufferSetLength( int nLength )
+ {
+ PXSTR pszBuffer = GetBuffer( nLength );
+ SetLength( nLength );
+
+ return pszBuffer;
+ }
+ int GetLength() const
+ {
+ return GetData()->nDataLength;
+ }
+
+ PCXSTR GetString() const
+ {
+ return m_pszData;
+ }
+ bool IsEmpty() const
+ {
+ return GetLength() == 0;
+ }
+ PXSTR LockBuffer()
+ {
+ CMStringData* pData = GetData();
+ if ( pData->IsShared())
+ {
+ Fork( pData->nDataLength );
+ pData = GetData(); // Do it again, because the fork might have changed it
+ }
+ pData->Lock();
+
+ return m_pszData;
+ }
+ void UnlockBuffer()
+ {
+ CMStringData* pData = GetData();
+ pData->Unlock();
+ }
+ void Preallocate( int nLength )
+ {
+ PrepareWrite( nLength );
+ }
+ void ReleaseBuffer( int nNewLength = -1 )
+ {
+ if ( nNewLength == -1 )
+ {
+ int nAlloc = GetData()->nAllocLength;
+ nNewLength = StringLengthN( m_pszData, nAlloc);
+ }
+ SetLength( nNewLength );
+ }
+ void ReleaseBufferSetLength( int nNewLength )
+ {
+ SetLength( nNewLength );
+ }
+ void Truncate( int nNewLength )
+ {
+ GetBuffer( nNewLength );
+ ReleaseBufferSetLength( nNewLength );
+ }
+ void SetAt( int iChar, XCHAR ch )
+ {
+ int nLength = GetLength();
+ PXSTR pszBuffer = GetBuffer();
+ pszBuffer[iChar] = ch;
+ ReleaseBufferSetLength( nLength );
+
+ }
+ void SetString( PCXSTR pszSrc )
+ {
+ SetString( pszSrc, StringLength( pszSrc ));
+ }
+ void assign( PCXSTR pszSrc )
+ {
+ SetString( pszSrc, StringLength( pszSrc ));
+ }
+ void SetString( PCXSTR pszSrc, int nLength )
+ {
+ if ( nLength == 0 )
+ {
+ Empty();
+ }
+ else
+ {
+
+ UINT nOldLength = GetLength();
+ UINT_PTR nOffset = pszSrc - GetString();
+
+ PXSTR pszBuffer = GetBuffer( nLength );
+ if ( nOffset <= nOldLength )
+ {
+ CopyCharsOverlapped( pszBuffer, GetAllocLength(),
+ pszBuffer+nOffset, nLength );
+ }
+ else
+ {
+ CopyChars( pszBuffer, GetAllocLength(), pszSrc, nLength );
+ }
+ ReleaseBufferSetLength( nLength );
+ }
+ }
+public:
+ friend CMSimpleStringT __stdcall operator+(const CMSimpleStringT& str1, const CMSimpleStringT& str2)
+ {
+ CMSimpleStringT s;
+
+ Concatenate( s, str1, str1.GetLength(), str2, str2.GetLength());
+
+ return s;
+ }
+
+ friend CMSimpleStringT __stdcall operator+(const CMSimpleStringT& str1, PCXSTR psz2)
+ {
+ CMSimpleStringT s;
+
+ Concatenate( s, str1, str1.GetLength(), psz2, StringLength( psz2 ));
+
+ return s;
+ }
+
+ friend CMSimpleStringT __stdcall operator+(PCXSTR psz1, const CMSimpleStringT& str2)
+ {
+ CMSimpleStringT s;
+
+ Concatenate( s, psz1, StringLength( psz1 ), str2, str2.GetLength());
+
+ return s;
+ }
+
+ static void __stdcall CopyChars(XCHAR* pchDest, const XCHAR* pchSrc, int nChars )
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ memcpy(pchDest, pchSrc, nChars * sizeof(XCHAR));
+#pragma warning (pop)
+ }
+ static void __stdcall CopyChars(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars )
+ {
+ #if _MSC_VER >= 1400
+ memcpy_s(pchDest, nDestLen * sizeof(XCHAR), pchSrc, nChars * sizeof(XCHAR));
+ #else
+ memcpy(pchDest, pchSrc, nDestLen * sizeof(XCHAR));
+ #endif
+ }
+
+ static void __stdcall CopyCharsOverlapped(XCHAR* pchDest, const XCHAR* pchSrc, int nChars )
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ memmove(pchDest, pchSrc, nChars * sizeof(XCHAR));
+#pragma warning (pop)
+ }
+ static void __stdcall CopyCharsOverlapped(XCHAR* pchDest, size_t nDestLen, const XCHAR* pchSrc, int nChars)
+ {
+ #if _MSC_VER >= 1400
+ memmove_s(pchDest, nDestLen * sizeof(XCHAR), pchSrc, nChars * sizeof(XCHAR));
+ #else
+ memmove(pchDest, pchSrc, nDestLen * sizeof(XCHAR));
+ #endif
+ }
+ static int __stdcall StringLength(const char* psz)
+ {
+ if (psz == NULL)
+ {
+ return(0);
+ }
+ return (int(strlen(psz)));
+ }
+ static int __stdcall StringLength(const wchar_t* psz)
+ {
+ if (psz == NULL)
+ return 0;
+
+ return int(wcslen(psz));
+ }
+ static int __stdcall StringLengthN(const char* psz, size_t sizeInXChar )
+ {
+ if ( psz == NULL )
+ return 0;
+
+ return int( strnlen( psz, sizeInXChar ));
+ }
+ static int __stdcall StringLengthN(const wchar_t* psz, size_t sizeInXChar )
+ {
+ if ( psz == NULL )
+ return 0;
+
+ return int( wcsnlen( psz, sizeInXChar ));
+ }
+protected:
+ static void __stdcall Concatenate(CMSimpleStringT& strResult, PCXSTR psz1, int nLength1, PCXSTR psz2, int nLength2)
+ {
+ int nNewLength = nLength1+nLength2;
+ PXSTR pszBuffer = strResult.GetBuffer(nNewLength);
+ CopyChars(pszBuffer, nLength1, psz1, nLength1 );
+ CopyChars(pszBuffer + nLength1, nLength2, psz2, nLength2);
+ strResult.ReleaseBufferSetLength(nNewLength);
+ }
+ // Implementation
+private:
+ void Attach(CMStringData* pData)
+ {
+ m_pszData = static_cast<PXSTR>(pData->data());
+ }
+ void Fork(int nLength)
+ {
+ CMStringData* pOldData = GetData();
+ int nOldLength = pOldData->nDataLength;
+ CMStringData* pNewData = Allocate(nLength, sizeof(XCHAR));
+ if (pNewData != NULL)
+ {
+ int nCharsToCopy = ((nOldLength < nLength) ? nOldLength : nLength)+1; // Copy '\0'
+ CopyChars( PXSTR( pNewData->data()), nCharsToCopy, PCXSTR( pOldData->data()), nCharsToCopy );
+ pNewData->nDataLength = nOldLength;
+ pOldData->Release();
+ Attach(pNewData);
+ }
+ }
+ CMStringData* GetData() const
+ {
+ return (reinterpret_cast<CMStringData *>(m_pszData) - 1);
+ }
+ PXSTR PrepareWrite( int nLength )
+ {
+ CMStringData* pOldData = GetData();
+ int nShared = 1 - pOldData->nRefs; // nShared < 0 means true, >= 0 means false
+ int nTooShort = pOldData->nAllocLength-nLength; // nTooShort < 0 means true, >= 0 means false
+ if ((nShared | nTooShort) < 0 ) // If either sign bit is set (i.e. either is less than zero), we need to copy data
+ PrepareWrite2(nLength);
+
+ return m_pszData;
+ }
+ void PrepareWrite2(int nLength)
+ {
+ CMStringData* pOldData = GetData();
+ if (pOldData->nDataLength > nLength)
+ nLength = pOldData->nDataLength;
+
+ if (pOldData->IsShared())
+ {
+ Fork(nLength);
+ }
+ else if (pOldData->nAllocLength < nLength)
+ {
+ // Grow exponentially, until we hit 1K.
+ int nNewLength = pOldData->nAllocLength;
+ if ( nNewLength > 1024 )
+ nNewLength += 1024;
+ else
+ nNewLength *= 2;
+
+ if ( nNewLength < nLength )
+ nNewLength = nLength;
+
+ Reallocate( nNewLength );
+ }
+ }
+ void Reallocate( int nLength )
+ {
+ CMStringData* pOldData = GetData();
+ if ( pOldData->nAllocLength >= nLength || nLength <= 0)
+ return;
+
+ CMStringData* pNewData = Realloc( pOldData, nLength, sizeof( XCHAR ));
+ if ( pNewData != NULL )
+ Attach( pNewData );
+ }
+
+ void SetLength( int nLength )
+ {
+ GetData()->nDataLength = nLength;
+ m_pszData[nLength] = 0;
+ }
+
+ static CMStringData* __stdcall CloneData(CMStringData* pData)
+ {
+ CMStringData* pNewData = NULL;
+
+ if (!pData->IsLocked()) {
+ pNewData = pData;
+ pNewData->AddRef();
+ }
+
+ return pNewData;
+ }
+
+public :
+ // typedef CStrBufT<BaseType> CStrBuf;
+private:
+ PXSTR m_pszData;
+};
+
+
+template< typename _CharType = char >
+class ChTraitsCRT : public ChTraitsBase< _CharType >
+{
+public:
+ static char* __stdcall CharNext( const char* p )
+ {
+ return reinterpret_cast< char* >( _mbsinc( reinterpret_cast< const unsigned char* >( p )));
+ }
+
+ static int __stdcall IsDigit( char ch )
+ {
+ return _ismbcdigit( ch );
+ }
+
+ static int __stdcall IsSpace( char ch )
+ {
+ return _ismbcspace( ch );
+ }
+
+ static int __stdcall StringCompare( LPCSTR pszA, LPCSTR pszB )
+ {
+ return _mbscmp( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ));
+ }
+
+ static int __stdcall StringCompareIgnore( LPCSTR pszA, LPCSTR pszB )
+ {
+ return _mbsicmp( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ));
+ }
+
+ static int __stdcall StringCollate( LPCSTR pszA, LPCSTR pszB )
+ {
+ return _mbscoll( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ));
+ }
+
+ static int __stdcall StringCollateIgnore( LPCSTR pszA, LPCSTR pszB )
+ {
+ return _mbsicoll( reinterpret_cast< const unsigned char* >( pszA ), reinterpret_cast< const unsigned char* >( pszB ));
+ }
+
+ static LPCSTR __stdcall StringFindString( LPCSTR pszBlock, LPCSTR pszMatch )
+ {
+ return reinterpret_cast< LPCSTR >( _mbsstr( reinterpret_cast< const unsigned char* >( pszBlock ),
+ reinterpret_cast< const unsigned char* >( pszMatch )));
+ }
+
+ static LPSTR __stdcall StringFindString( LPSTR pszBlock, LPCSTR pszMatch )
+ {
+ return const_cast< LPSTR >( StringFindString( const_cast< LPCSTR >( pszBlock ), pszMatch ));
+ }
+
+ static LPCSTR __stdcall StringFindChar( LPCSTR pszBlock, char chMatch )
+ {
+ return reinterpret_cast< LPCSTR >( _mbschr( reinterpret_cast< const unsigned char* >( pszBlock ), (unsigned char)chMatch ));
+ }
+
+ static LPCSTR __stdcall StringFindCharRev( LPCSTR psz, char ch )
+ {
+ return reinterpret_cast< LPCSTR >( _mbsrchr( reinterpret_cast< const unsigned char* >( psz ), (unsigned char)ch ));
+ }
+
+ static LPCSTR __stdcall StringScanSet( LPCSTR pszBlock, LPCSTR pszMatch )
+ {
+ return reinterpret_cast< LPCSTR >( _mbspbrk( reinterpret_cast< const unsigned char* >( pszBlock ),
+ reinterpret_cast< const unsigned char* >( pszMatch )));
+ }
+
+ static int __stdcall StringSpanIncluding( LPCSTR pszBlock, LPCSTR pszSet )
+ {
+ return (int)_mbsspn( reinterpret_cast< const unsigned char* >( pszBlock ), reinterpret_cast< const unsigned char* >( pszSet ));
+ }
+
+ static int __stdcall StringSpanExcluding( LPCSTR pszBlock, LPCSTR pszSet )
+ {
+ return (int)_mbscspn( reinterpret_cast< const unsigned char* >( pszBlock ), reinterpret_cast< const unsigned char* >( pszSet ));
+ }
+
+ static LPSTR __stdcall StringUppercase( LPSTR psz )
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ return reinterpret_cast< LPSTR >( _mbsupr( reinterpret_cast< unsigned char* >( psz )) );
+#pragma warning (pop)
+ }
+
+ static LPSTR __stdcall StringLowercase( LPSTR psz )
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ return reinterpret_cast< LPSTR >( _mbslwr( reinterpret_cast< unsigned char* >( psz )) );
+#pragma warning (pop)
+ }
+
+ static LPSTR __stdcall StringUppercase( LPSTR psz, size_t size )
+ {
+ #if _MSC_VER >= 1400
+ _mbsupr_s(reinterpret_cast< unsigned char* >( psz ), size);
+ #else
+ _mbsupr(reinterpret_cast< unsigned char* >( psz ));
+ #endif
+ return psz;
+ }
+
+ static LPSTR __stdcall StringLowercase( LPSTR psz, size_t size )
+ {
+ #if _MSC_VER >= 1400
+ _mbslwr_s( reinterpret_cast< unsigned char* >( psz ), size );
+ #else
+ _mbsupr(reinterpret_cast< unsigned char* >( psz ));
+ #endif
+ return psz;
+ }
+
+ static LPSTR __stdcall StringReverse( LPSTR psz )
+ {
+ return reinterpret_cast< LPSTR >( _mbsrev( reinterpret_cast< unsigned char* >( psz )) );
+ }
+
+ static int __stdcall GetFormattedLength( LPCSTR pszFormat, va_list args );
+
+ static int __stdcall Format( LPSTR pszBuffer, LPCSTR pszFormat, va_list args )
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ return vsprintf( pszBuffer, pszFormat, args );
+#pragma warning (pop)
+
+ }
+
+ static int __stdcall Format( LPSTR pszBuffer, size_t nlength, LPCSTR pszFormat, va_list args );
+
+ static int __stdcall GetBaseTypeLength( LPCSTR pszSrc )
+ {
+ // Returns required buffer length in XCHARs
+ return int( strlen( pszSrc ));
+ }
+
+ static int __stdcall GetBaseTypeLength( LPCSTR pszSrc, int nLength )
+ {
+ (void)pszSrc;
+ // Returns required buffer length in XCHARs
+ return nLength;
+ }
+
+ static int __stdcall GetBaseTypeLength( LPCWSTR pszSource )
+ {
+ // Returns required buffer length in XCHARs
+ return ::WideCharToMultiByte( _AtlGetConversionACP(), 0, pszSource, -1, NULL, 0, NULL, NULL )-1;
+ }
+
+ static int __stdcall GetBaseTypeLength( LPCWSTR pszSource, int nLength )
+ {
+ // Returns required buffer length in XCHARs
+ return ::WideCharToMultiByte( _AtlGetConversionACP(), 0, pszSource, nLength, NULL, 0, NULL, NULL );
+ }
+
+ static void __stdcall ConvertToBaseType( LPSTR pszDest, int nDestLength, LPCSTR pszSrc, int nSrcLength = -1 )
+ {
+ if (nSrcLength == -1) { nSrcLength=1 + GetBaseTypeLength(pszSrc); }
+ // nLen is in XCHARs
+ memcpy_s( pszDest, nDestLength*sizeof( char ),
+ pszSrc, nSrcLength*sizeof( char ));
+ }
+
+ static void __stdcall ConvertToBaseType( LPSTR pszDest, int nDestLength, LPCWSTR pszSrc, int nSrcLength = -1)
+ {
+ // nLen is in XCHARs
+ ::WideCharToMultiByte( _AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL );
+ }
+
+ static void ConvertToOem( _CharType* pstrString)
+ {
+ BOOL fSuccess=::CharToOemA(pstrString, pstrString);
+ }
+
+ static void ConvertToAnsi( _CharType* pstrString)
+ {
+ BOOL fSuccess=::OemToCharA(pstrString, pstrString);
+ }
+
+ static void ConvertToOem( _CharType* pstrString, size_t size)
+ {
+ if(size>UINT_MAX)
+ {
+ return;
+ }
+ DWORD dwSize=static_cast<DWORD>(size);
+ BOOL fSuccess=::CharToOemBuffA(pstrString, pstrString, dwSize);
+ }
+
+ static void ConvertToAnsi( _CharType* pstrString, size_t size)
+ {
+ if(size>UINT_MAX)
+ return;
+
+ DWORD dwSize=static_cast<DWORD>(size);
+ BOOL fSuccess=::OemToCharBuffA(pstrString, pstrString, dwSize);
+ }
+
+ static void __stdcall FloodCharacters( char ch, int nLength, char* pch )
+ {
+ // nLength is in XCHARs
+ memset( pch, ch, nLength );
+ }
+
+ static BSTR __stdcall AllocSysString( const char* pchData, int nDataLength )
+ {
+ int nLen = ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pchData, nDataLength, NULL, NULL );
+ BSTR bstr = ::SysAllocStringLen( NULL, nLen );
+ if ( bstr != NULL )
+ ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pchData, nDataLength, bstr, nLen );
+
+ return bstr;
+ }
+
+ static BOOL __stdcall ReAllocSysString( const char* pchData, BSTR* pbstr, int nDataLength )
+ {
+ int nLen = ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pchData, nDataLength, NULL, NULL );
+ BOOL bSuccess = ::SysReAllocStringLen( pbstr, NULL, nLen );
+ if ( bSuccess )
+ ::MultiByteToWideChar( _AtlGetConversionACP(), 0, pchData, nDataLength, *pbstr, nLen );
+
+ return bSuccess;
+ }
+
+ static int __stdcall SafeStringLen( LPCSTR psz )
+ {
+ // returns length in bytes
+ return (psz != NULL) ? int( strlen( psz )) : 0;
+ }
+
+ static int __stdcall SafeStringLen( LPCWSTR psz )
+ {
+ // returns length in wchar_ts
+ return (psz != NULL) ? int( wcslen( psz )) : 0;
+ }
+
+ static int __stdcall GetCharLen( const wchar_t* pch )
+ {
+ // returns char length
+ return 1;
+ }
+
+ static int __stdcall GetCharLen( const char* pch )
+ {
+ // returns char length
+ return int( _mbclen( reinterpret_cast< const unsigned char* >( pch )) );
+ }
+
+ static DWORD __stdcall GetEnvironmentVariable( LPCSTR pszVar, LPSTR pszBuffer, DWORD dwSize )
+ {
+ return ::GetEnvironmentVariableA( pszVar, pszBuffer, dwSize );
+ }
+};
+
+// specialization for wchar_t
+template<>
+class ChTraitsCRT< wchar_t > : public ChTraitsBase< wchar_t >
+{
+ static DWORD __stdcall _GetEnvironmentVariableW( LPCWSTR pszName, LPWSTR pszBuffer, DWORD nSize )
+ {
+ return ::GetEnvironmentVariableW( pszName, pszBuffer, nSize );
+ }
+
+public:
+ static LPWSTR __stdcall CharNext( LPCWSTR psz )
+ {
+ return const_cast< LPWSTR >( psz+1 );
+ }
+
+ static int __stdcall IsDigit( wchar_t ch )
+ {
+ return iswdigit( static_cast<unsigned short>(ch));
+ }
+
+ static int __stdcall IsSpace( wchar_t ch )
+ {
+ return iswspace( static_cast<unsigned short>(ch));
+ }
+
+ static int __stdcall StringCompare( LPCWSTR pszA, LPCWSTR pszB )
+ {
+ return wcscmp( pszA, pszB );
+ }
+
+ static int __stdcall StringCompareIgnore( LPCWSTR pszA, LPCWSTR pszB )
+ {
+ return _wcsicmp( pszA, pszB );
+ }
+
+ static int __stdcall StringCollate( LPCWSTR pszA, LPCWSTR pszB )
+ {
+ return wcscoll( pszA, pszB );
+ }
+
+ static int __stdcall StringCollateIgnore( LPCWSTR pszA, LPCWSTR pszB )
+ {
+ return _wcsicoll( pszA, pszB );
+ }
+
+ static LPCWSTR __stdcall StringFindString( LPCWSTR pszBlock, LPCWSTR pszMatch )
+ {
+ return wcsstr( pszBlock, pszMatch );
+ }
+
+ static LPWSTR __stdcall StringFindString( LPWSTR pszBlock, LPCWSTR pszMatch )
+ {
+ return const_cast< LPWSTR >( StringFindString( const_cast< LPCWSTR >( pszBlock ), pszMatch ));
+ }
+
+ static LPCWSTR __stdcall StringFindChar( LPCWSTR pszBlock, wchar_t chMatch )
+ {
+ return wcschr( pszBlock, chMatch );
+ }
+
+ static LPCWSTR __stdcall StringFindCharRev( LPCWSTR psz, wchar_t ch )
+ {
+ return wcsrchr( psz, ch );
+ }
+
+ static LPCWSTR __stdcall StringScanSet( LPCWSTR pszBlock, LPCWSTR pszMatch )
+ {
+ return wcspbrk( pszBlock, pszMatch );
+ }
+
+ static int __stdcall StringSpanIncluding( LPCWSTR pszBlock, LPCWSTR pszSet )
+ {
+ return (int)wcsspn( pszBlock, pszSet );
+ }
+
+ static int __stdcall StringSpanExcluding( LPCWSTR pszBlock, LPCWSTR pszSet )
+ {
+ return (int)wcscspn( pszBlock, pszSet );
+ }
+
+ static LPWSTR __stdcall StringUppercase( LPWSTR psz )
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ return _wcsupr( psz );
+#pragma warning (pop)
+ }
+
+ static LPWSTR __stdcall StringLowercase( LPWSTR psz )
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ return _wcslwr( psz );
+#pragma warning (pop)
+ }
+
+ static LPWSTR __stdcall StringUppercase( LPWSTR psz, size_t size )
+ {
+ return _wcsupr( psz );
+ }
+
+ static LPWSTR __stdcall StringLowercase( LPWSTR psz, size_t size )
+ {
+ return _wcslwr( psz );
+ }
+
+ static LPWSTR __stdcall StringReverse( LPWSTR psz )
+ {
+ return _wcsrev( psz );
+ }
+
+ static int __stdcall GetFormattedLength( LPCWSTR pszFormat, va_list args);
+
+ static int __stdcall Format( LPWSTR pszBuffer, LPCWSTR pszFormat, va_list args)
+ {
+#pragma warning (push)
+#pragma warning(disable : 4996)
+ return vswprintf( pszBuffer, pszFormat, args );
+#pragma warning (pop)
+ }
+
+ static int __stdcall Format( LPWSTR pszBuffer, size_t nLength, LPCWSTR pszFormat, va_list args);
+
+ static int __stdcall GetBaseTypeLength( LPCSTR pszSrc )
+ {
+ // Returns required buffer size in wchar_ts
+ return ::MultiByteToWideChar( CP_ACP, 0, pszSrc, -1, NULL, 0 )-1;
+ }
+
+ static int __stdcall GetBaseTypeLength( LPCSTR pszSrc, int nLength )
+ {
+ // Returns required buffer size in wchar_ts
+ return ::MultiByteToWideChar( CP_ACP, 0, pszSrc, nLength, NULL, 0 );
+ }
+
+ static int __stdcall GetBaseTypeLength( LPCWSTR pszSrc )
+ {
+ // Returns required buffer size in wchar_ts
+ return (int)wcslen( pszSrc );
+ }
+
+ static int __stdcall GetBaseTypeLength( LPCWSTR pszSrc, int nLength )
+ {
+ (void)pszSrc;
+ // Returns required buffer size in wchar_ts
+ return nLength;
+ }
+
+ static void __stdcall ConvertToBaseType( LPWSTR pszDest, int nDestLength, LPCSTR pszSrc, int nSrcLength = -1)
+ {
+ // nLen is in wchar_ts
+ ::MultiByteToWideChar( CP_ACP, 0, pszSrc, nSrcLength, pszDest, nDestLength );
+ }
+
+ static void __stdcall ConvertToBaseType( LPWSTR pszDest, int nDestLength, LPCWSTR pszSrc, int nSrcLength = -1 )
+ {
+ if (nSrcLength == -1) { nSrcLength=1 + GetBaseTypeLength(pszSrc); }
+ // nLen is in wchar_ts
+ #if _MSC_VER >= 1400
+ wmemcpy_s(pszDest, nDestLength, pszSrc, nSrcLength);
+ #else
+ wmemcpy(pszDest, pszSrc, nDestLength);
+ #endif
+ }
+
+ static void __stdcall FloodCharacters( wchar_t ch, int nLength, LPWSTR psz )
+ {
+ // nLength is in XCHARs
+ for ( int i = 0; i < nLength; i++ )
+ {
+ psz[i] = ch;
+ }
+ }
+
+ static BSTR __stdcall AllocSysString( const wchar_t* pchData, int nDataLength )
+ {
+ return ::SysAllocStringLen( pchData, nDataLength );
+ }
+
+ static BOOL __stdcall ReAllocSysString( const wchar_t* pchData, BSTR* pbstr, int nDataLength )
+ {
+ return ::SysReAllocStringLen( pbstr, pchData, nDataLength );
+ }
+
+ static int __stdcall SafeStringLen( LPCSTR psz )
+ {
+ // returns length in bytes
+ return (psz != NULL) ? (int)strlen( psz ) : 0;
+ }
+
+ static int __stdcall SafeStringLen( LPCWSTR psz )
+ {
+ // returns length in wchar_ts
+ return (psz != NULL) ? (int)wcslen( psz ) : 0;
+ }
+
+ static int __stdcall GetCharLen( const wchar_t* pch )
+ {
+ (void)pch;
+ // returns char length
+ return 1;
+ }
+
+ static int __stdcall GetCharLen( const char* pch )
+ {
+ // returns char length
+ return (int)( _mbclen( reinterpret_cast< const unsigned char* >( pch )) );
+ }
+
+ static DWORD __stdcall GetEnvironmentVariable( LPCWSTR pszVar, LPWSTR pszBuffer, DWORD dwSize )
+ {
+ return _GetEnvironmentVariableW( pszVar, pszBuffer, dwSize );
+ }
+
+ static void __stdcall ConvertToOem( LPWSTR /*psz*/ )
+ {
+ }
+
+ static void __stdcall ConvertToAnsi( LPWSTR /*psz*/ )
+ {
+ }
+
+ static void __stdcall ConvertToOem( LPWSTR /*psz*/, size_t )
+ {
+ }
+
+ static void __stdcall ConvertToAnsi( LPWSTR /*psz*/, size_t )
+ {
+ }
+};
+
+template< typename BaseType, class StringTraits >
+class CMStringT : public CMSimpleStringT< BaseType >
+{
+public:
+ typedef CMSimpleStringT< BaseType> CThisSimpleString;
+ typedef typename CThisSimpleString::XCHAR XCHAR;
+ typedef typename CThisSimpleString::PXSTR PXSTR;
+ typedef typename CThisSimpleString::PCXSTR PCXSTR;
+ typedef typename CThisSimpleString::YCHAR YCHAR;
+ typedef typename CThisSimpleString::PYSTR PYSTR;
+ typedef typename CThisSimpleString::PCYSTR PCYSTR;
+
+public:
+ CMStringT() : CThisSimpleString()
+ {
+ }
+
+ static void __stdcall Construct( CMStringT* pString )
+ {
+ new( pString ) CMStringT;
+ }
+
+ // Copy constructor
+ CMStringT( const CMStringT& strSrc ) :
+ CThisSimpleString( strSrc )
+ {
+ }
+
+ CMStringT( const XCHAR* pszSrc ) :
+ CThisSimpleString()
+ {
+ // nDestLength is in XCHARs
+ *this = pszSrc;
+ }
+
+ CMStringT( const YCHAR* pszSrc ) :
+ CThisSimpleString()
+ {
+ *this = pszSrc;
+ }
+
+
+ CMStringT( const unsigned char* pszSrc ) :
+ CThisSimpleString()
+ {
+ *this = reinterpret_cast< const char* >( pszSrc );
+ }
+
+ CMStringT( char ch, int nLength = 1 ) :
+ CThisSimpleString()
+ {
+ if ( nLength > 0 )
+ {
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::FloodCharacters( XCHAR( ch ), nLength, pszBuffer );
+ this->ReleaseBufferSetLength( nLength );
+ }
+ }
+
+ CMStringT( wchar_t ch, int nLength = 1 ) :
+ CThisSimpleString()
+ {
+ if ( nLength > 0 )
+ {
+ //Convert ch to the BaseType
+ wchar_t pszCh[2] = { ch , 0 };
+ int nBaseTypeCharLen = 1;
+
+ if(ch != L'\0')
+ {
+ nBaseTypeCharLen = StringTraits::GetBaseTypeLength(pszCh);
+ }
+
+ XCHAR *buffBaseTypeChar = new XCHAR[nBaseTypeCharLen+1];
+ StringTraits::ConvertToBaseType( buffBaseTypeChar, nBaseTypeCharLen+1, pszCh, 1 );
+ //Allocate enough characters in String and flood (replicate) with the (converted character)*nLength
+ PXSTR pszBuffer = this->GetBuffer( nLength*nBaseTypeCharLen );
+ if (nBaseTypeCharLen == 1)
+ { //Optimization for a common case - wide char translates to 1 ansi/wide char.
+ StringTraits::FloodCharacters( buffBaseTypeChar[0], nLength, pszBuffer );
+ } else
+ {
+ XCHAR* p=pszBuffer;
+ for (int i=0 ; i < nLength ;++i)
+ {
+ for (int j=0 ; j < nBaseTypeCharLen ;++j)
+ {
+ *p=buffBaseTypeChar[j];
+ ++p;
+ }
+ }
+ }
+ this->ReleaseBufferSetLength( nLength*nBaseTypeCharLen );
+ delete [] buffBaseTypeChar;
+ }
+ }
+
+ CMStringT( const XCHAR* pch, int nLength ) :
+ CThisSimpleString( pch, nLength )
+ {
+ }
+
+ CMStringT( const YCHAR* pch, int nLength ) :
+ CThisSimpleString()
+ {
+ if ( nLength > 0 )
+ {
+ int nDestLength = StringTraits::GetBaseTypeLength( pch, nLength );
+ PXSTR pszBuffer = this->GetBuffer( nDestLength );
+ StringTraits::ConvertToBaseType( pszBuffer, nDestLength, pch, nLength );
+ this->ReleaseBufferSetLength( nDestLength );
+ }
+ }
+
+ // Destructor
+ ~CMStringT()
+ {
+ }
+
+ // Assignment operators
+ CMStringT& operator=( const CMStringT& strSrc )
+ {
+ CThisSimpleString::operator=( strSrc );
+
+ return *this;
+ }
+
+ CMStringT& operator=( PCXSTR pszSrc )
+ {
+ CThisSimpleString::operator=( pszSrc );
+
+ return *this;
+ }
+
+ CMStringT& operator=( PCYSTR pszSrc )
+ {
+ // nDestLength is in XCHARs
+ int nDestLength = (pszSrc != NULL) ? StringTraits::GetBaseTypeLength( pszSrc ) : 0;
+ if ( nDestLength > 0 )
+ {
+ PXSTR pszBuffer = this->GetBuffer( nDestLength );
+ StringTraits::ConvertToBaseType( pszBuffer, nDestLength, pszSrc);
+ this->ReleaseBufferSetLength( nDestLength );
+ }
+ else
+ {
+ this->Empty();
+ }
+
+ return *this;
+ }
+
+ CMStringT& operator=( const unsigned char* pszSrc )
+ {
+ return operator=( reinterpret_cast< const char* >( pszSrc ));
+ }
+
+ CMStringT& operator=( char ch )
+ {
+ char ach[2] = { ch, 0 };
+
+ return operator=( ach );
+ }
+
+ CMStringT& operator=( wchar_t ch )
+ {
+ wchar_t ach[2] = { ch, 0 };
+
+ return operator=( ach );
+ }
+
+// CMStringT& operator=( const VARIANT& var );
+
+ CMStringT& operator+=( const CMStringT& str )
+ {
+ CThisSimpleString::operator+=( str );
+ return *this;
+ }
+
+ CMStringT& operator+=( const CThisSimpleString& str )
+ {
+ CThisSimpleString::operator+=( str );
+ return *this;
+ }
+
+ CMStringT& operator+=( PCXSTR pszSrc )
+ {
+ CThisSimpleString::operator+=( pszSrc );
+ return *this;
+ }
+// template< int t_nSize >
+// CMStringT& operator+=( const CStaticString< XCHAR, t_nSize >& strSrc )
+// {
+// CThisSimpleString::operator+=( strSrc );
+//
+// return *this;
+// }
+ CMStringT& operator+=( PCYSTR pszSrc )
+ {
+ CMStringT str( pszSrc );
+
+ return operator+=( str );
+ }
+
+ CMStringT& operator+=( char ch )
+ {
+ CThisSimpleString::operator+=( ch );
+
+ return *this;
+ }
+
+ CMStringT& operator+=( unsigned char ch )
+ {
+ CThisSimpleString::operator+=( ch );
+
+ return *this;
+ }
+
+ CMStringT& operator+=( wchar_t ch )
+ {
+ CThisSimpleString::operator+=( ch );
+
+ return *this;
+ }
+
+ // Comparison
+
+ int Compare( PCXSTR psz ) const
+ {
+ return StringTraits::StringCompare( this->GetString(), psz );
+ }
+
+ int CompareNoCase( PCXSTR psz ) const
+ {
+ return StringTraits::StringCompareIgnore( this->GetString(), psz );
+ }
+
+ int Collate( PCXSTR psz ) const
+ {
+ return StringTraits::StringCollate( this->GetString(), psz );
+ }
+
+ int CollateNoCase( PCXSTR psz ) const
+ {
+ return StringTraits::StringCollateIgnore( this->GetString(), psz );
+ }
+
+ // Advanced manipulation
+
+ // Delete 'nCount' characters, starting at index 'iIndex'
+ int Delete( int iIndex, int nCount = 1 )
+ {
+ if ( iIndex < 0 )
+ iIndex = 0;
+
+ if ( nCount < 0 )
+ nCount = 0;
+
+ int nLength = this->GetLength();
+ if ( nCount + iIndex > nLength )
+ {
+ nCount = nLength-iIndex;
+ }
+ if ( nCount > 0 )
+ {
+ int nNewLength = nLength-nCount;
+ int nXCHARsToCopy = nLength-(iIndex+nCount)+1;
+ PXSTR pszBuffer = this->GetBuffer();
+ #if _MSC_VER >= 1400
+ memmove_s( pszBuffer+iIndex, nXCHARsToCopy*sizeof( XCHAR ), pszBuffer+iIndex+nCount, nXCHARsToCopy*sizeof( XCHAR ));
+ #else
+ memmove( pszBuffer+iIndex, pszBuffer+iIndex+nCount, nXCHARsToCopy*sizeof( XCHAR ));
+ #endif
+ this->ReleaseBufferSetLength( nNewLength );
+ }
+
+ return this->GetLength();
+ }
+
+ // Insert character 'ch' before index 'iIndex'
+ int Insert( int iIndex, XCHAR ch )
+ {
+ if ( iIndex < 0 )
+ iIndex = 0;
+
+ if ( iIndex > this->GetLength())
+ iIndex = this->GetLength();
+
+ int nNewLength = this->GetLength()+1;
+
+ PXSTR pszBuffer = this->GetBuffer( nNewLength );
+
+ // move existing bytes down
+ #if _MSC_VER >= 1400
+ memmove_s( pszBuffer+iIndex+1, (nNewLength-iIndex)*sizeof( XCHAR ), pszBuffer+iIndex, (nNewLength-iIndex)*sizeof( XCHAR ));
+ #else
+ memmove( pszBuffer+iIndex+1, pszBuffer+iIndex, (nNewLength-iIndex)*sizeof( XCHAR ));
+ #endif
+ pszBuffer[iIndex] = ch;
+
+ this->ReleaseBufferSetLength( nNewLength );
+ return nNewLength;
+ }
+
+ // Insert string 'psz' before index 'iIndex'
+ int Insert( int iIndex, PCXSTR psz )
+ {
+ if ( iIndex < 0 )
+ iIndex = 0;
+
+ if ( iIndex > this->GetLength())
+ {
+ iIndex = this->GetLength();
+ }
+
+ // nInsertLength and nNewLength are in XCHARs
+ int nInsertLength = StringTraits::SafeStringLen( psz );
+ int nNewLength = this->GetLength();
+ if ( nInsertLength > 0 )
+ {
+ nNewLength += nInsertLength;
+
+ PXSTR pszBuffer = this->GetBuffer( nNewLength );
+ // move existing bytes down
+ #if _MSC_VER >= 1400
+ memmove_s( pszBuffer+iIndex+nInsertLength, (nNewLength-iIndex-nInsertLength+1)*sizeof( XCHAR ), pszBuffer+iIndex, (nNewLength-iIndex-nInsertLength+1)*sizeof( XCHAR ));
+ memcpy_s( pszBuffer+iIndex, nInsertLength*sizeof( XCHAR ), psz, nInsertLength*sizeof( XCHAR ));
+ #else
+ memmove( pszBuffer+iIndex+nInsertLength, pszBuffer+iIndex, (nNewLength-iIndex-nInsertLength+1)*sizeof( XCHAR ));
+ memcpy( pszBuffer+iIndex, psz, nInsertLength*sizeof( XCHAR ));
+ #endif
+ this->ReleaseBufferSetLength( nNewLength );
+ }
+
+ return nNewLength;
+ }
+
+ // Replace all occurrences of character 'chOld' with character 'chNew'
+ int Replace( XCHAR chOld, XCHAR chNew )
+ {
+ int nCount = 0;
+
+ // short-circuit the nop case
+ if ( chOld != chNew )
+ {
+ // otherwise modify each character that matches in the string
+ bool bCopied = false;
+ PXSTR pszBuffer = const_cast< PXSTR >( this->GetString()); // We don't actually write to pszBuffer until we've called GetBuffer().
+
+ int nLength = this->GetLength();
+ int iChar = 0;
+ while( iChar < nLength )
+ {
+ // replace instances of the specified character only
+ if ( pszBuffer[iChar] == chOld )
+ {
+ if ( !bCopied )
+ {
+ bCopied = true;
+ pszBuffer = this->GetBuffer( nLength );
+ }
+ pszBuffer[iChar] = chNew;
+ nCount++;
+ }
+ iChar = int( StringTraits::CharNext( pszBuffer+iChar )-pszBuffer );
+ }
+ if ( bCopied )
+ {
+ this->ReleaseBufferSetLength( nLength );
+ }
+ }
+
+ return nCount;
+ }
+
+ // Replace all occurrences of string 'pszOld' with string 'pszNew'
+ int Replace( PCXSTR pszOld, PCXSTR pszNew )
+ {
+ // can't have empty or NULL lpszOld
+
+ // nSourceLen is in XCHARs
+ int nSourceLen = StringTraits::SafeStringLen( pszOld );
+ if ( nSourceLen == 0 )
+ return 0;
+ // nReplacementLen is in XCHARs
+ int nReplacementLen = StringTraits::SafeStringLen( pszNew );
+
+ // loop once to figure out the size of the result string
+ int nCount = 0;
+ {
+ PCXSTR pszStart = this->GetString();
+ PCXSTR pszEnd = pszStart+this->GetLength();
+ while( pszStart < pszEnd )
+ {
+ PCXSTR pszTarget;
+ while((pszTarget = StringTraits::StringFindString( pszStart, pszOld )) != NULL)
+ {
+ nCount++;
+ pszStart = pszTarget+nSourceLen;
+ }
+ pszStart += StringTraits::SafeStringLen( pszStart )+1;
+ }
+ }
+
+ // if any changes were made, make them
+ if ( nCount > 0 )
+ {
+ // if the buffer is too small, just
+ // allocate a new buffer (slow but sure)
+ int nOldLength = this->GetLength();
+ int nNewLength = nOldLength+(nReplacementLen-nSourceLen)*nCount;
+
+ PXSTR pszBuffer = this->GetBuffer( __max( nNewLength, nOldLength ));
+
+ PXSTR pszStart = pszBuffer;
+ PXSTR pszEnd = pszStart+nOldLength;
+
+ // loop again to actually do the work
+ while( pszStart < pszEnd )
+ {
+ PXSTR pszTarget;
+ while((pszTarget = StringTraits::StringFindString( pszStart, pszOld )) != NULL )
+ {
+ int nBalance = nOldLength-int(pszTarget-pszBuffer+nSourceLen);
+ memmove_s( pszTarget+nReplacementLen, nBalance*sizeof( XCHAR ),
+ pszTarget+nSourceLen, nBalance*sizeof( XCHAR ));
+ memcpy_s( pszTarget, nReplacementLen*sizeof( XCHAR ),
+ pszNew, nReplacementLen*sizeof( XCHAR ));
+ pszStart = pszTarget+nReplacementLen;
+ pszTarget[nReplacementLen+nBalance] = 0;
+ nOldLength += (nReplacementLen-nSourceLen);
+ }
+ pszStart += StringTraits::SafeStringLen( pszStart )+1;
+ }
+ this->ReleaseBufferSetLength( nNewLength );
+ }
+
+ return nCount;
+ }
+
+ // Remove all occurrences of character 'chRemove'
+ int Remove( XCHAR chRemove )
+ {
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+
+ PXSTR pszSource = pszBuffer;
+ PXSTR pszDest = pszBuffer;
+ PXSTR pszEnd = pszBuffer+nLength;
+
+ while( pszSource < pszEnd )
+ {
+ PXSTR pszNewSource = StringTraits::CharNext( pszSource );
+ if ( *pszSource != chRemove )
+ {
+ // Copy the source to the destination. Remember to copy all bytes of an MBCS character
+ // Copy the source to the destination. Remember to copy all bytes of an MBCS character
+ size_t NewSourceGap = (pszNewSource-pszSource);
+ PXSTR pszNewDest = pszDest + NewSourceGap;
+ size_t i = 0;
+ for (i = 0; pszDest != pszNewDest && i < NewSourceGap; i++)
+ {
+ *pszDest = *pszSource;
+ pszSource++;
+ pszDest++;
+ }
+ }
+ pszSource = pszNewSource;
+ }
+ *pszDest = 0;
+ int nCount = int( pszSource-pszDest );
+ this->ReleaseBufferSetLength( nLength-nCount );
+
+ return nCount;
+ }
+
+ CMStringT Tokenize( PCXSTR pszTokens, int& iStart ) const
+ {
+ if ((pszTokens == NULL) || (*pszTokens == (XCHAR)0))
+ {
+ if (iStart < this->GetLength())
+ return CMStringT( this->GetString()+iStart );
+ }
+ else
+ {
+ PCXSTR pszPlace = this->GetString()+iStart;
+ PCXSTR pszEnd = this->GetString()+this->GetLength();
+ if ( pszPlace < pszEnd )
+ {
+ int nIncluding = StringTraits::StringSpanIncluding( pszPlace, pszTokens );
+
+ if ((pszPlace+nIncluding) < pszEnd )
+ {
+ pszPlace += nIncluding;
+ int nExcluding = StringTraits::StringSpanExcluding( pszPlace, pszTokens );
+
+ int iFrom = iStart+nIncluding;
+ int nUntil = nExcluding;
+ iStart = iFrom+nUntil+1;
+
+ return Mid( iFrom, nUntil );
+ }
+ }
+ }
+
+ // return empty string, done tokenizing
+ iStart = -1;
+
+ return CMStringT();
+ }
+
+ // find routines
+
+ // Find the first occurrence of character 'ch', starting at index 'iStart'
+ int Find( XCHAR ch, int iStart = 0 ) const
+ {
+ // nLength is in XCHARs
+ int nLength = this->GetLength();
+ if ( iStart < 0 || iStart >= nLength)
+ return -1;
+
+ // find first single character
+ PCXSTR psz = StringTraits::StringFindChar( this->GetString()+iStart, ch );
+
+ // return -1 if not found and index otherwise
+ return (psz == NULL) ? -1 : int( psz-this->GetString());
+ }
+
+ // look for a specific sub-string
+
+ // Find the first occurrence of string 'pszSub', starting at index 'iStart'
+ int Find( PCXSTR pszSub, int iStart = 0 ) const
+ {
+ // iStart is in XCHARs
+ if(pszSub == NULL)
+ return -1;
+
+ // nLength is in XCHARs
+ int nLength = this->GetLength();
+ if ( iStart < 0 || iStart > nLength )
+ return -1;
+
+ // find first matching substring
+ PCXSTR psz = StringTraits::StringFindString( this->GetString()+iStart, pszSub );
+
+ // return -1 for not found, distance from beginning otherwise
+ return (psz == NULL) ? -1 : int( psz-this->GetString());
+ }
+
+ // Find the first occurrence of any of the characters in string 'pszCharSet'
+ int FindOneOf( PCXSTR pszCharSet ) const
+ {
+ PCXSTR psz = StringTraits::StringScanSet( this->GetString(), pszCharSet );
+ return (psz == NULL) ? -1 : int( psz-this->GetString());
+ }
+
+ // Find the last occurrence of character 'ch'
+ int ReverseFind( XCHAR ch ) const
+ {
+ // find last single character
+ PCXSTR psz = StringTraits::StringFindCharRev( this->GetString(), ch );
+
+ // return -1 if not found, distance from beginning otherwise
+ return (psz == NULL) ? -1 : int( psz-this->GetString());
+ }
+
+ // manipulation
+
+ // Convert the string to uppercase
+ CMStringT& MakeUpper()
+ {
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::StringUppercase( pszBuffer, nLength+1 );
+ this->ReleaseBufferSetLength( nLength );
+
+ return *this;
+ }
+
+ // Convert the string to lowercase
+ CMStringT& MakeLower()
+ {
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::StringLowercase( pszBuffer, nLength+1 );
+ this->ReleaseBufferSetLength( nLength );
+
+ return *this;
+ }
+
+ // Reverse the string
+ CMStringT& MakeReverse()
+ {
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::StringReverse( pszBuffer );
+ this->ReleaseBufferSetLength( nLength );
+
+ return *this;
+ }
+
+ // trimming
+
+ // Remove all trailing whitespace
+ CMStringT& TrimRight()
+ {
+ // find beginning of trailing spaces by starting
+ // at beginning (DBCS aware)
+
+ PCXSTR psz = this->GetString();
+ PCXSTR pszLast = NULL;
+
+ while( *psz != 0 )
+ {
+ if ( StringTraits::IsSpace( *psz ))
+ {
+ if ( pszLast == NULL )
+ pszLast = psz;
+ }
+ else
+ {
+ pszLast = NULL;
+ }
+ psz = StringTraits::CharNext( psz );
+ }
+
+ if ( pszLast != NULL )
+ {
+ // truncate at trailing space start
+ int iLast = int( pszLast-this->GetString());
+
+ this->Truncate( iLast );
+ }
+
+ return *this;
+ }
+
+ // Remove all leading whitespace
+ CMStringT& TrimLeft()
+ {
+ // find first non-space character
+
+ PCXSTR psz = this->GetString();
+
+ while( StringTraits::IsSpace( *psz ))
+ {
+ psz = StringTraits::CharNext( psz );
+ }
+
+ if ( psz != this->GetString())
+ {
+ // fix up data and length
+ int iFirst = int( psz-this->GetString());
+ PXSTR pszBuffer = this->GetBuffer( this->GetLength());
+ psz = pszBuffer+iFirst;
+ int nDataLength = this->GetLength()-iFirst;
+ memmove_s( pszBuffer, (this->GetLength()+1)*sizeof( XCHAR ),
+ psz, (nDataLength+1)*sizeof( XCHAR ));
+ this->ReleaseBufferSetLength( nDataLength );
+ }
+
+ return *this;
+ }
+
+ // Remove all leading and trailing whitespace
+ CMStringT& Trim()
+ {
+ return TrimRight().TrimLeft();
+ }
+
+ // Remove all leading and trailing occurrences of character 'chTarget'
+ CMStringT& Trim( XCHAR chTarget )
+ {
+ return TrimRight( chTarget ).TrimLeft( chTarget );
+ }
+
+ // Remove all leading and trailing occurrences of any of the characters in the string 'pszTargets'
+ CMStringT& Trim( PCXSTR pszTargets )
+ {
+ return TrimRight( pszTargets ).TrimLeft( pszTargets );
+ }
+
+ // trimming anything (either side)
+
+ // Remove all trailing occurrences of character 'chTarget'
+ CMStringT& TrimRight( XCHAR chTarget )
+ {
+ // find beginning of trailing matches
+ // by starting at beginning (DBCS aware)
+
+ PCXSTR psz = this->GetString();
+ PCXSTR pszLast = NULL;
+
+ while( *psz != 0 )
+ {
+ if ( *psz == chTarget )
+ {
+ if ( pszLast == NULL )
+ {
+ pszLast = psz;
+ }
+ }
+ else
+ {
+ pszLast = NULL;
+ }
+ psz = StringTraits::CharNext( psz );
+ }
+
+ if ( pszLast != NULL )
+ {
+ // truncate at left-most matching character
+ int iLast = int( pszLast-this->GetString());
+ this->Truncate( iLast );
+ }
+
+ return *this;
+ }
+
+ // Remove all trailing occurrences of any of the characters in string 'pszTargets'
+ CMStringT& TrimRight( PCXSTR pszTargets )
+ {
+ // if we're not trimming anything, we're not doing any work
+ if ((pszTargets == NULL) || (*pszTargets == 0))
+ {
+ return *this;
+ }
+
+ // find beginning of trailing matches
+ // by starting at beginning (DBCS aware)
+
+ PCXSTR psz = this->GetString();
+ PCXSTR pszLast = NULL;
+
+ while( *psz != 0 )
+ {
+ if ( StringTraits::StringFindChar( pszTargets, *psz ) != NULL )
+ {
+ if ( pszLast == NULL )
+ {
+ pszLast = psz;
+ }
+ }
+ else
+ {
+ pszLast = NULL;
+ }
+ psz = StringTraits::CharNext( psz );
+ }
+
+ if ( pszLast != NULL )
+ {
+ // truncate at left-most matching character
+ int iLast = int( pszLast-this->GetString());
+ this->Truncate( iLast );
+ }
+
+ return *this;
+ }
+
+ // Remove all leading occurrences of character 'chTarget'
+ CMStringT& TrimLeft( XCHAR chTarget )
+ {
+ // find first non-matching character
+ PCXSTR psz = this->GetString();
+
+ while( chTarget == *psz )
+ {
+ psz = StringTraits::CharNext( psz );
+ }
+
+ if ( psz != this->GetString())
+ {
+ // fix up data and length
+ int iFirst = int( psz-this->GetString());
+ PXSTR pszBuffer = this->GetBuffer( this->GetLength());
+ psz = pszBuffer+iFirst;
+ int nDataLength = this->GetLength()-iFirst;
+ memmove_s( pszBuffer, (this->GetLength()+1)*sizeof( XCHAR ),
+ psz, (nDataLength+1)*sizeof( XCHAR ));
+ this->ReleaseBufferSetLength( nDataLength );
+ }
+
+ return *this;
+ }
+
+ // Remove all leading occurrences of any of the characters in string 'pszTargets'
+ CMStringT& TrimLeft( PCXSTR pszTargets )
+ {
+ // if we're not trimming anything, we're not doing any work
+ if ((pszTargets == NULL) || (*pszTargets == 0))
+ {
+ return *this;
+ }
+
+ PCXSTR psz = this->GetString();
+ while((*psz != 0) && (StringTraits::StringFindChar( pszTargets, *psz ) != NULL))
+ {
+ psz = StringTraits::CharNext( psz );
+ }
+
+ if ( psz != this->GetString())
+ {
+ // fix up data and length
+ int iFirst = int( psz-this->GetString());
+ PXSTR pszBuffer = this->GetBuffer( this->GetLength());
+ psz = pszBuffer+iFirst;
+ int nDataLength = this->GetLength()-iFirst;
+ memmove_s( pszBuffer, (this->GetLength()+1)*sizeof( XCHAR ),
+ psz, (nDataLength+1)*sizeof( XCHAR ));
+ this->ReleaseBufferSetLength( nDataLength );
+ }
+
+ return *this;
+ }
+
+ // Convert the string to the OEM character set
+ void AnsiToOem()
+ {
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::ConvertToOem( pszBuffer, nLength+1 );
+ this->ReleaseBufferSetLength( nLength );
+ }
+
+ // Convert the string to the ANSI character set
+ void OemToAnsi()
+ {
+ int nLength = this->GetLength();
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::ConvertToAnsi( pszBuffer, nLength+1 );
+ this->ReleaseBufferSetLength( nLength );
+ }
+
+ // Very simple sub-string extraction
+
+ // Return the substring starting at index 'iFirst'
+ CMStringT Mid( int iFirst ) const
+ {
+ return Mid( iFirst, this->GetLength()-iFirst );
+ }
+
+ // Return the substring starting at index 'iFirst', with length 'nCount'
+ CMStringT Mid( int iFirst, int nCount ) const
+ {
+ // nCount is in XCHARs
+
+ // out-of-bounds requests return sensible things
+ if (iFirst < 0)
+ iFirst = 0;
+ if (nCount < 0)
+ nCount = 0;
+
+ if ((iFirst + nCount) > this->GetLength())
+ nCount = this->GetLength()-iFirst;
+
+ if ( iFirst > this->GetLength())
+ nCount = 0;
+
+ // optimize case of returning entire string
+ if ((iFirst == 0) && ((iFirst+nCount) == this->GetLength()))
+ return *this;
+
+ return CMStringT( this->GetString()+iFirst, nCount );
+ }
+
+ // Return the substring consisting of the rightmost 'nCount' characters
+ CMStringT Right( int nCount ) const
+ {
+ // nCount is in XCHARs
+ if (nCount < 0)
+ nCount = 0;
+
+ int nLength = this->GetLength();
+ if ( nCount >= nLength )
+ {
+ return *this;
+ }
+
+ return CMStringT( this->GetString()+nLength-nCount, nCount );
+ }
+
+ // Return the substring consisting of the leftmost 'nCount' characters
+ CMStringT Left( int nCount ) const
+ {
+ // nCount is in XCHARs
+ if (nCount < 0)
+ nCount = 0;
+
+ int nLength = this->GetLength();
+ if ( nCount >= nLength )
+ return *this;
+
+ return CMStringT( this->GetString(), nCount );
+ }
+
+ // Return the substring consisting of the leftmost characters in the set 'pszCharSet'
+ CMStringT SpanIncluding( PCXSTR pszCharSet ) const
+ {
+ return Left( StringTraits::StringSpanIncluding( this->GetString(), pszCharSet ));
+ }
+
+ // Return the substring consisting of the leftmost characters not in the set 'pszCharSet'
+ CMStringT SpanExcluding( PCXSTR pszCharSet ) const
+ {
+ return Left( StringTraits::StringSpanExcluding( this->GetString(), pszCharSet ));
+ }
+
+ // Format data using format string 'pszFormat'
+ void Format( PCXSTR pszFormat, ... );
+
+ // Append formatted data using format string 'pszFormat'
+ void AppendFormat( PCXSTR pszFormat, ... );
+
+ void AppendFormatV( PCXSTR pszFormat, va_list args )
+ {
+ int nCurrentLength = this->GetLength();
+ int nAppendLength = StringTraits::GetFormattedLength( pszFormat, args );
+ PXSTR pszBuffer = this->GetBuffer( nCurrentLength+nAppendLength );
+ StringTraits::Format( pszBuffer+nCurrentLength,
+ nAppendLength+1, pszFormat, args );
+ this->ReleaseBufferSetLength( nCurrentLength+nAppendLength );
+ }
+
+ void FormatV( PCXSTR pszFormat, va_list args )
+ {
+ int nLength = StringTraits::GetFormattedLength( pszFormat, args );
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::Format( pszBuffer, nLength+1, pszFormat, args );
+ this->ReleaseBufferSetLength( nLength );
+ }
+
+ // OLE BSTR support
+
+ // Allocate a BSTR containing a copy of the string
+ BSTR AllocSysString() const
+ {
+ BSTR bstrResult = StringTraits::AllocSysString( this->GetString(), this->GetLength());
+ return bstrResult;
+ }
+
+ BSTR SetSysString( BSTR* pbstr ) const
+ {
+ StringTraits::ReAllocSysString( this->GetString(), pbstr, this->GetLength());
+ return *pbstr;
+ }
+
+ // Set the string to the value of environment variable 'pszVar'
+ BOOL GetEnvironmentVariable( PCXSTR pszVar )
+ {
+ ULONG nLength = StringTraits::GetEnvironmentVariable( pszVar, NULL, 0 );
+ BOOL bRetVal = FALSE;
+
+ if ( nLength == 0 )
+ {
+ this->Empty();
+ }
+ else
+ {
+ PXSTR pszBuffer = this->GetBuffer( nLength );
+ StringTraits::GetEnvironmentVariable( pszVar, pszBuffer, nLength );
+ this->ReleaseBuffer();
+ bRetVal = TRUE;
+ }
+
+ return bRetVal;
+ }
+
+ // Load the string from resource 'nID'
+ BOOL LoadString( UINT nID )
+ {
+ HINSTANCE hInst = StringTraits::FindStringResourceInstance( nID );
+ if ( hInst == NULL )
+ return FALSE;
+
+ return LoadString( hInst, nID );
+ }
+
+ friend CMStringT __stdcall operator+( const CMStringT& str1, const CMStringT& str2 )
+ {
+ CMStringT strResult;
+
+ Concatenate( strResult, str1, str1.GetLength(), str2, str2.GetLength());
+
+ return strResult;
+ }
+
+ friend CMStringT __stdcall operator+( const CMStringT& str1, PCXSTR psz2 )
+ {
+ CMStringT strResult;
+
+ Concatenate( strResult, str1, str1.GetLength(), psz2, StringLength( psz2 ));
+
+ return strResult;
+ }
+
+ friend CMStringT __stdcall operator+( PCXSTR psz1, const CMStringT& str2 )
+ {
+ CMStringT strResult;
+
+ Concatenate( strResult, psz1, StringLength( psz1 ), str2, str2.GetLength());
+
+ return strResult;
+ }
+
+ friend CMStringT __stdcall operator+( const CMStringT& str1, wchar_t ch2 )
+ {
+ CMStringT strResult;
+ XCHAR chTemp = XCHAR( ch2 );
+
+ Concatenate( strResult, str1, str1.GetLength(), &chTemp, 1 );
+
+ return strResult;
+ }
+
+ friend CMStringT __stdcall operator+( const CMStringT& str1, char ch2 )
+ {
+ CMStringT strResult;
+ XCHAR chTemp = XCHAR( ch2 );
+
+ Concatenate( strResult, str1, str1.GetLength(), &chTemp, 1 );
+
+ return strResult;
+ }
+
+ friend CMStringT __stdcall operator+( wchar_t ch1, const CMStringT& str2 )
+ {
+ CMStringT strResult;
+ XCHAR chTemp = XCHAR( ch1 );
+
+ Concatenate( strResult, &chTemp, 1, str2, str2.GetLength());
+
+ return strResult;
+ }
+
+ friend CMStringT __stdcall operator+( char ch1, const CMStringT& str2 )
+ {
+ CMStringT strResult;
+ XCHAR chTemp = XCHAR( ch1 );
+
+ Concatenate( strResult, &chTemp, 1, str2, str2.GetLength());
+
+ return strResult;
+ }
+
+ friend bool __stdcall operator==( const CMStringT& str1, const CMStringT& str2 )
+ {
+ return str1.Compare( str2 ) == 0;
+ }
+
+ friend bool __stdcall operator==( const CMStringT& str1, PCXSTR psz2 )
+ {
+ return str1.Compare( psz2 ) == 0;
+ }
+
+ friend bool __stdcall operator==( PCXSTR psz1, const CMStringT& str2 )
+ {
+ return str2.Compare( psz1 ) == 0;
+ }
+
+ friend bool __stdcall operator==( const CMStringT& str1, PCYSTR psz2 )
+ {
+ CMStringT str2( psz2 );
+
+ return str1 == str2;
+ }
+
+ friend bool __stdcall operator==( PCYSTR psz1, const CMStringT& str2 )
+ {
+ CMStringT str1( psz1 );
+
+ return str1 == str2;
+ }
+
+ friend bool __stdcall operator!=( const CMStringT& str1, const CMStringT& str2 )
+ {
+ return str1.Compare( str2 ) != 0;
+ }
+
+ friend bool __stdcall operator!=( const CMStringT& str1, PCXSTR psz2 )
+ {
+ return str1.Compare( psz2 ) != 0;
+ }
+
+ friend bool __stdcall operator!=( PCXSTR psz1, const CMStringT& str2 )
+ {
+ return str2.Compare( psz1 ) != 0;
+ }
+
+ friend bool __stdcall operator!=( const CMStringT& str1, PCYSTR psz2 )
+ {
+ CMStringT str2( psz2 );
+
+ return str1 != str2;
+ }
+
+ friend bool __stdcall operator!=( PCYSTR psz1, const CMStringT& str2 )
+ {
+ CMStringT str1( psz1 );
+
+ return str1 != str2;
+ }
+
+ friend bool __stdcall operator<( const CMStringT& str1, const CMStringT& str2 )
+ {
+ return str1.Compare( str2 ) < 0;
+ }
+
+ friend bool __stdcall operator<( const CMStringT& str1, PCXSTR psz2 )
+ {
+ return str1.Compare( psz2 ) < 0;
+ }
+
+ friend bool __stdcall operator<( PCXSTR psz1, const CMStringT& str2 )
+ {
+ return str2.Compare( psz1 ) > 0;
+ }
+
+ friend bool __stdcall operator>( const CMStringT& str1, const CMStringT& str2 )
+ {
+ return str1.Compare( str2 ) > 0;
+ }
+
+ friend bool __stdcall operator>( const CMStringT& str1, PCXSTR psz2 )
+ {
+ return str1.Compare( psz2 ) > 0;
+ }
+
+ friend bool __stdcall operator>( PCXSTR psz1, const CMStringT& str2 )
+ {
+ return str2.Compare( psz1 ) < 0;
+ }
+
+ friend bool __stdcall operator<=( const CMStringT& str1, const CMStringT& str2 )
+ {
+ return str1.Compare( str2 ) <= 0;
+ }
+
+ friend bool __stdcall operator<=( const CMStringT& str1, PCXSTR psz2 )
+ {
+ return str1.Compare( psz2 ) <= 0;
+ }
+
+ friend bool __stdcall operator<=( PCXSTR psz1, const CMStringT& str2 )
+ {
+ return str2.Compare( psz1 ) >= 0;
+ }
+
+ friend bool __stdcall operator>=( const CMStringT& str1, const CMStringT& str2 )
+ {
+ return str1.Compare( str2 ) >= 0;
+ }
+
+ friend bool __stdcall operator>=( const CMStringT& str1, PCXSTR psz2 )
+ {
+ return str1.Compare( psz2 ) >= 0;
+ }
+
+ friend bool __stdcall operator>=( PCXSTR psz1, const CMStringT& str2 )
+ {
+ return str2.Compare( psz1 ) <= 0;
+ }
+
+ friend bool __stdcall operator==( XCHAR ch1, const CMStringT& str2 )
+ {
+ return (str2.GetLength() == 1) && (str2[0] == ch1);
+ }
+
+ friend bool __stdcall operator==( const CMStringT& str1, XCHAR ch2 )
+ {
+ return (str1.GetLength() == 1) && (str1[0] == ch2);
+ }
+
+ friend bool __stdcall operator!=( XCHAR ch1, const CMStringT& str2 )
+ {
+ return (str2.GetLength() != 1) || (str2[0] != ch1);
+ }
+
+ friend bool __stdcall operator!=( const CMStringT& str1, XCHAR ch2 )
+ {
+ return (str1.GetLength() != 1) || (str1[0] != ch2);
+ }
+};
+
+template< typename BaseType, class StringTraits >
+inline void CMStringT<BaseType, StringTraits>::Format(PCXSTR pszFormat, ... )
+{
+ va_list argList;
+ va_start( argList, pszFormat );
+ FormatV( pszFormat, argList );
+ va_end( argList );
+}
+
+template< typename BaseType, class StringTraits >
+inline void CMStringT<BaseType, StringTraits>::AppendFormat(PCXSTR pszFormat, ... )
+{
+ va_list argList;
+ va_start( argList, pszFormat );
+ AppendFormatV( pszFormat, argList );
+ va_end( argList );
+}
+
+typedef CMStringT< wchar_t, ChTraitsCRT< wchar_t > > CMStringW;
+typedef CMStringT< char, ChTraitsCRT< char > > CMStringA;
+typedef CMStringT< TCHAR, ChTraitsCRT< TCHAR > > CMString;
diff --git a/plugins/Clist_modern/src/hdr/modern_awaymsg.h b/plugins/Clist_modern/src/hdr/modern_awaymsg.h
new file mode 100644
index 0000000000..ea51c6ddb2
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_awaymsg.h
@@ -0,0 +1,37 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+/*
+* Author Artem Shpynov aka FYR
+* Copyright 2000-2008 Artem Shpynov
+*/
+
+#pragma once
+//////////////////////////////////////////////////////////////////////////
+// Module to Request Away Messages
+
+void InitAwayMsgModule();
+void UninitAwayMsgModule();
+void amRequestAwayMsg(HANDLE hContact);
+
diff --git a/plugins/Clist_modern/src/hdr/modern_cache_funcs.h b/plugins/Clist_modern/src/hdr/modern_cache_funcs.h
new file mode 100644
index 0000000000..ba2b59f2c3
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_cache_funcs.h
@@ -0,0 +1,46 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Created by Pescuma
+
+*/
+#pragma once
+
+#ifndef __CACHE_FUNCS_H__
+# define __CACHE_FUNCS_H__
+
+#include "modern_clc.h"
+#include "modern_commonprototypes.h"
+
+void Cache_GetText(struct ClcData *dat, struct ClcContact *contact, BOOL forceRenew);
+void Cache_GetFirstLineText(struct ClcData *dat, struct ClcContact *contact);
+void Cache_GetSecondLineText(struct SHORTDATA *dat, PDNCE pdnce);
+void Cache_GetThirdLineText(struct SHORTDATA *dat, PDNCE pdnce);
+void Cache_GetAvatar(struct ClcData *dat, struct ClcContact *contact);
+void Cache_GetTimezone(struct ClcData *dat, HANDLE hContact);
+int Cache_GetLineText(PDNCE pdnce, int type, LPTSTR text, int text_size, TCHAR *variable_text, BOOL xstatus_has_priority,
+ BOOL show_status_if_no_away, BOOL show_listening_if_no_away, BOOL use_name_and_message_for_xstatus,
+ BOOL pdnce_time_show_only_if_different);
+
+void amRequestAwayMsg(HANDLE hContact);
+
+#endif // __CACHE_FUNCS_H__
diff --git a/plugins/Clist_modern/src/hdr/modern_callproc.h b/plugins/Clist_modern/src/hdr/modern_callproc.h
new file mode 100644
index 0000000000..19cfb883b6
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_callproc.h
@@ -0,0 +1,128 @@
+#ifndef modern_callproc_h__
+#define modern_callproc_h__
+
+namespace call {
+#include <windows.h>
+
+//////////////////////////////////////////////////////////////////////////
+// USE AS
+// ret = call::sync( proc, param1, param2 ... etc)
+//////////////////////////////////////////////////////////////////////////
+// internal realization
+enum ASYNC_T { ASYNC = 0, SYNC };
+int __ProcessCall( class __baseCall * pStorage, ASYNC_T async );
+
+class __baseCall { public: virtual int __DoCallStorageProc() =0; virtual ~__baseCall() {}; };
+template< class R > class _callParams0 : public __baseCall
+{
+public:
+ R(*_proc)();
+ _callParams0( R (*proc)()) : _proc(proc){};
+ int __DoCallStorageProc() { return (int)_proc(); }
+};
+
+template<> class _callParams0<void> : public __baseCall
+{
+public:
+ void(*_proc)();
+ _callParams0( void (*proc)()) : _proc(proc){};
+ int __DoCallStorageProc() { _proc(); return 0; }
+};
+
+template< class R, class A> class _callParams1 : public __baseCall
+{
+public:
+ R(*_proc)(A); A _a;
+ _callParams1( R(*proc)(A), A a) : _proc(proc), _a(a) {};
+ int __DoCallStorageProc() { return (int)_proc(_a); }
+};
+
+template<class A> class _callParams1<void, A> : public __baseCall
+{
+public:
+ void(*_proc)(A); A _a;
+ _callParams1( void(*proc)(A), A a) : _proc(proc), _a(a) {};
+ int __DoCallStorageProc() { _proc(_a); return 0; }
+};
+
+template< class R, class A, class B> class _callParams2 : public __baseCall
+{
+public:
+ R (*_proc)(A, B); A _a; B _b;
+ _callParams2( R (*proc)(A, B), A a, B b) : _proc(proc), _a(a), _b(b) {};
+ int __DoCallStorageProc() { return (int)_proc(_a, _b); }
+};
+
+template< class A, class B> class _callParams2<void, A, B> : public __baseCall
+{
+public:
+ void (*_proc)(A, B); A _a; B _b;
+ _callParams2( void (*proc)(A, B), A a, B b) : _proc(proc), _a(a), _b(b) {};
+ int __DoCallStorageProc() { _proc(_a, _b); return 0; }
+};
+
+template< class R, class A, class B, class C> class _callParams3 : public __baseCall
+{
+public:
+ R (*_proc)(A, B, C); A _a; B _b; C _c;
+ _callParams3( R (*proc)(A, B, C), A a, B b, C c ) : _proc(proc), _a(a), _b(b), _c(c) {};
+ int __DoCallStorageProc() { return (int)_proc(_a,_b,_c); }
+};
+
+template< class A, class B, class C> class _callParams3<void, A, B, C> : public __baseCall
+{
+public:
+ void (*_proc)(A, B, C); A _a; B _b; C _c;
+ _callParams3( void (*proc)(A, B, C), A a, B b, C c ) : _proc(proc), _a(a), _b(b), _c(c) {};
+ int __DoCallStorageProc() { _proc(_a,_b,_c); return 0;}
+};
+
+template < class R > R __DoCall( R(*__proc)(), ASYNC_T sync_mode )
+{
+ typedef _callParams0< R > callClass;
+ callClass * storage = new callClass( __proc );
+ return (R) call::__ProcessCall( storage, sync_mode );
+};
+
+template < class R, class A > R __DoCall( R(*__proc)( A ), A a, ASYNC_T sync_mode )
+{
+ typedef _callParams1< R, A > callClass;
+ callClass * storage = new callClass( __proc, a );
+ return (R)__ProcessCall( storage, sync_mode );
+};
+
+
+template < class R, class A, class B > R __DoCall( R(*__proc)( A, B ), A a, B b, ASYNC_T sync_mode )
+{
+ typedef _callParams2< R, A, B > callClass;
+ callClass * storage = new callClass( __proc, a, b);
+ return (R)__ProcessCall( storage, sync_mode );
+};
+
+
+template < class R, class A, class B, class C > R __DoCall( R(*__proc)( A, B, C ), A a, B b, C c, ASYNC_T sync_mode )
+{
+ typedef _callParams3< R, A, B, C > callClass;
+ callClass * storage = new callClass( __proc, a, b, c);
+ return (R)__ProcessCall( storage, sync_mode );
+};
+
+
+template < class R > R sync( R(*_proc)())
+{ return __DoCall(_proc, SYNC); };
+template < class R, class A > R sync( R(*_proc)( A ), A a )
+{ return __DoCall(_proc, a, SYNC); };
+template < class R, class A, class B > R sync( R(*_proc)( A,B), A a, B b )
+{ return __DoCall(_proc, a, b, SYNC); };
+template < class R, class A, class B, class C > R sync( R(*_proc)( A,B,C ), A a, B b, C c)
+{ return __DoCall(_proc, a, b, c, SYNC); };
+template < class R > int async( R(*_proc)())
+{ return __DoCall(_proc, ASYNC); };
+template < class R, class A > R async( R(*_proc)( A ), A a )
+{ return __DoCall(_proc, a, ASYNC); };
+template < class R, class A, class B > R async( R(*_proc)( A,B), A a, B b )
+{ return __DoCall(_proc, a, b, ASYNC); };
+template < class R, class A, class B, class C > R async( R(*_proc)( A,B,C ), A a, B b, C c)
+{ return __DoCall(_proc, a, b, c, ASYNC); };
+}; // namespace call
+#endif // modern_callproc_h__
diff --git a/plugins/Clist_modern/src/hdr/modern_clc.h b/plugins/Clist_modern/src/hdr/modern_clc.h
new file mode 100644
index 0000000000..56c7a8b4c0
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_clc.h
@@ -0,0 +1,515 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#pragma once
+
+#ifndef _CLC_H_
+#define _CLC_H_
+#include "modern_image_array.h"
+#include "../m_api/m_xpTheme.h"
+
+#include "modern_defsettings.h"
+#include "modern_clist.h"
+
+#define SETTING_TRAYICON_SINGLE 0
+#define SETTING_TRAYICON_CYCLE 1
+#define SETTING_TRAYICON_MULTI 2
+
+#define NIIF_INTERN_UNICODE 0x00000100
+
+#define SETTING_STATE_HIDDEN 0
+#define SETTING_STATE_MINIMIZED 1
+#define SETTING_STATE_NORMAL 2
+
+#define SETTING_BRINGTOFRONT_DEFAULT 0
+
+#define SETTING_AVATAR_OVERLAY_TYPE_NORMAL 0
+#define SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL 1
+#define SETTING_AVATAR_OVERLAY_TYPE_CONTACT 2
+
+#define HCONTACT_ISGROUP 0x80000000
+#define HCONTACT_ISINFO 0xFFFF0000
+
+#define MAXEXTRACOLUMNS 16
+#define MAXSTATUSMSGLEN 256
+
+#define INTM_NAMECHANGED (WM_USER+10)
+#define INTM_ICONCHANGED (WM_USER+11)
+#define INTM_GROUPCHANGED (WM_USER+12)
+#define INTM_GROUPSCHANGED (WM_USER+13)
+#define INTM_CONTACTADDED (WM_USER+14)
+#define INTM_CONTACTDELETED (WM_USER+15)
+#define INTM_HIDDENCHANGED (WM_USER+16)
+#define INTM_INVALIDATE (WM_USER+17)
+#define INTM_APPARENTMODECHANGED (WM_USER+18)
+#define INTM_SETINFOTIPHOVERTIME (WM_USER+19)
+#define INTM_NOTONLISTCHANGED (WM_USER+20)
+#define INTM_RELOADOPTIONS (WM_USER+21)
+#define INTM_NAMEORDERCHANGED (WM_USER+22)
+#define INTM_IDLECHANGED (WM_USER+23)
+#define INTM_SCROLLBARCHANGED (WM_USER+24)
+#define INTM_PROTOCHANGED (WM_USER+25)
+#define INTM_STATUSMSGCHANGED (WM_USER+26)
+#define INTM_STATUSCHANGED (WM_USER+27)
+#define INTM_AVATARCHANGED (WM_USER+28)
+#define INTM_TIMEZONECHANGED (WM_USER+29)
+
+
+
+#define CLM_SETEXTRACOLUMNSSPACE (CLM_FIRST+73) //wParam=extra space between icons
+
+#define CLBF_TILEVTOROWHEIGHT 0x0100
+
+#define TIMERID_RENAME 10
+#define TIMERID_DRAGAUTOSCROLL 11
+#define TIMERID_INFOTIP 13
+#define TIMERID_REBUILDAFTER 14
+#define TIMERID_DELAYEDRESORTCLC 15
+#define TIMERID_SUBEXPAND 21
+#define TIMERID_INVALIDATE 22
+#define TIMERID_INVALIDATE_FULL 25
+#define TIMERID_RECALCSCROLLBAR 26
+
+#define TIMERID_FIRST TIMERID_RENAME
+#define TIMERID_LAST TIMERID_RECALCSCROLLBAR
+
+void clcSetDelayTimer( UINT_PTR uIDEvent, HWND hwnd, int nDelay = -1);
+
+#define FONTID_CONTACTS 0
+#define FONTID_INVIS 1
+#define FONTID_OFFLINE 2
+#define FONTID_NOTONLIST 3
+#define FONTID_OPENGROUPS 4
+#define FONTID_OPENGROUPCOUNTS 5
+#define FONTID_DIVIDERS 6
+#define FONTID_OFFINVIS 7
+#define FONTID_SECONDLINE 8
+#define FONTID_THIRDLINE 9
+#define FONTID_AWAY 10
+#define FONTID_DND 11
+#define FONTID_NA 12
+#define FONTID_OCCUPIED 13
+#define FONTID_CHAT 14
+#define FONTID_INVISIBLE 15
+#define FONTID_PHONE 16
+#define FONTID_LUNCH 17
+#define FONTID_CONTACT_TIME 18
+#define FONTID_CLOSEDGROUPS 19
+#define FONTID_CLOSEDGROUPCOUNTS 20
+#define FONTID_STATUSBAR_PROTONAME 21
+#define FONTID_EVENTAREA 22
+#define FONTID_VIEMODES 23
+#define FONTID_MODERN_MAX 23
+
+#define DROPTARGET_OUTSIDE 0
+#define DROPTARGET_ONSELF 1
+#define DROPTARGET_ONNOTHING 2
+#define DROPTARGET_ONGROUP 3
+#define DROPTARGET_ONCONTACT 4
+#define DROPTARGET_INSERTION 5
+#define DROPTARGET_ONMETACONTACT 6
+#define DROPTARGET_ONSUBCONTACT 7
+
+struct ClcGroup;
+
+#define CONTACTF_ONLINE 1
+#define CONTACTF_INVISTO 2
+#define CONTACTF_VISTO 4
+#define CONTACTF_NOTONLIST 8
+#define CONTACTF_CHECKED 16
+#define CONTACTF_IDLE 32
+//#define CONTACTF_STATUSMSG 64
+
+#define AVATAR_POS_DONT_HAVE -1
+#define AVATAR_POS_ANIMATED -2
+
+#define TEXT_PIECE_TYPE_TEXT 0
+#define TEXT_PIECE_TYPE_SMILEY 1
+
+#define DRAGSTAGE_NOTMOVED 0
+#define DRAGSTAGE_ACTIVE 1
+#define DRAGSTAGEM_STAGE 0x00FF
+#define DRAGSTAGEF_MAYBERENAME 0x8000
+#define DRAGSTAGEF_OUTSIDE 0x4000
+#define DRAGSTAGEF_SKIPRENAME 0x2000
+
+#define ITEM_AVATAR 0
+#define ITEM_ICON 1
+#define ITEM_TEXT 2
+#define ITEM_EXTRA_ICONS 3
+#define ITEM_CONTACT_TIME 4
+#define NUM_ITEM_TYPE 5
+
+#define TEXT_EMPTY -1
+#define TEXT_STATUS 0
+#define TEXT_NICKNAME 1
+#define TEXT_STATUS_MESSAGE 2
+#define TEXT_TEXT 3
+#define TEXT_CONTACT_TIME 4
+#define TEXT_LISTENING_TO 5
+
+#define TEXT_TEXT_MAX_LENGTH 1024
+
+typedef struct tagClcContactTextPiece
+{
+ int type;
+ int len;
+ union
+ {
+ struct
+ {
+ int start_pos;
+ };
+ struct
+ {
+ HICON smiley;
+ int smiley_width;
+ int smiley_height;
+ };
+ };
+} ClcContactTextPiece;
+
+enum {
+ CIT_PAINT_END=0, //next items are invalids
+ CIT_AVATAR, // 1
+ CIT_ICON, // 2
+ CIT_TEXT, // 3 //the contact name or group name
+ CIT_SUBTEXT1, // 4 //the second line for contact or group counter for groups
+ CIT_SUBTEXT2, // 5
+ CIT_TIME, // 6
+ CIT_CHECKBOX, // 7
+ CIT_SELECTION, // 8
+ CIT_EXTRA=64 //use bit compare for extra icon, the mask &0x3F will return number of extra icon
+};
+
+
+typedef struct _tagContactItems
+{
+ BYTE itemType; //one of above CIT_ definitions
+ RECT itemRect;
+}tContactItems;
+
+struct ClcContact {
+ BYTE type;
+ BYTE flags;
+ union {
+ struct {
+ int iImage;
+ HANDLE hContact;
+ };
+ struct {
+ WORD groupId;
+ struct ClcGroup *group;
+ };
+ };
+ BYTE iExtraImage[MAXEXTRACOLUMNS];
+ TCHAR szText[120 - MAXEXTRACOLUMNS];
+ char * proto; // MS_PROTO_GETBASEPROTO
+
+ struct ClcContact *subcontacts;
+ BYTE SubAllocated;
+ BYTE SubExpanded;
+ BYTE isSubcontact;
+// int status;
+ BOOL image_is_special;
+ int avatar_pos;
+ struct avatarCacheEntry *avatar_data;
+ SIZE avatar_size;
+ CSmileyString ssText;
+
+
+ // For hittest
+ int pos_indent;
+ RECT pos_check;
+ RECT pos_avatar;
+ RECT pos_icon;
+ RECT pos_label;
+ RECT pos_rename_rect;
+ RECT pos_contact_time;
+ RECT pos_extra[MAXEXTRACOLUMNS];
+ DWORD lastPaintCounter;
+ BYTE bContactRate;
+
+ // For extended layout
+ BYTE ext_nItemsNum;
+ BOOL ext_fItemsValid;
+ tContactItems ext_mpItemsDesc[MAXEXTRACOLUMNS+10]; //up to 10 items
+
+ WORD iWideExtraImage[MAXEXTRACOLUMNS];
+
+
+};
+
+
+
+struct ClcModernFontInfo {
+ HFONT hFont;
+ int fontHeight,changed;
+ COLORREF colour;
+ BYTE effect;
+ COLORREF effectColour1;
+ COLORREF effectColour2;
+};
+
+struct ClcData {
+ struct ClcGroup list;
+ int max_row_height;
+
+ int yScroll;
+ int selection;
+ struct ClcFontInfo fontInfo[FONTID_MAX+1];
+ int scrollTime;
+ HIMAGELIST himlHighlight;
+ int groupIndent;
+ TCHAR szQuickSearch[128];
+ int iconXSpace;
+ HWND hwndRenameEdit;
+ COLORREF bkColour,selBkColour,selTextColour,hotTextColour,quickSearchColour;
+ int iDragItem,iInsertionMark;
+ int dragStage;
+ POINT ptDragStart;
+ int dragAutoScrolling;
+ int dragAutoScrollHeight;
+ int leftMargin;
+ int insertionMarkHitHeight;
+ HBITMAP hBmpBackground;
+ int backgroundBmpUse,bkChanged;
+ int iHotTrack;
+ int gammaCorrection;
+ DWORD greyoutFlags; //see m_clc.h
+ DWORD offlineModes;
+ DWORD exStyle;
+ POINT ptInfoTip;
+ int infoTipTimeout;
+ HANDLE hInfoTipItem;
+ HIMAGELIST himlExtraColumns;
+ int extraColumnsCount;
+ int extraColumnSpacing;
+ int checkboxSize;
+ int showSelAlways;
+ int showIdle;
+ int noVScrollbar;
+ int useWindowsColours;
+ int NeedResort;
+ SortedList lCLCContactsCache;
+ BYTE HiLightMode;
+ BYTE doubleClickExpand;
+ int MetaIgnoreEmptyExtra;
+ BYTE expandMeta;
+ BYTE IsMetaContactsEnabled;
+ time_t last_tick_time;
+ BOOL force_in_dialog;
+ int subIndent;
+ int rightMargin;
+ HBITMAP hMenuBackground;
+ DWORD MenuBkColor, MenuBkHiColor, MenuTextColor, MenuTextHiColor;
+ int MenuBmpUse;
+
+ // Row height
+ int *row_heights;
+ int row_heights_size;
+ int row_heights_allocated;
+
+ // Avatar cache
+ int use_avatar_service;
+ IMAGE_ARRAY_DATA avatar_cache;
+
+ // Row
+ int row_min_heigh;
+ int row_border;
+ int row_before_group_space;
+
+ BOOL row_variable_height;
+ BOOL row_align_left_items_to_left;
+ BOOL row_align_right_items_to_right;
+ int row_items[NUM_ITEM_TYPE];
+ BOOL row_hide_group_icon;
+ BYTE row_align_group_mode;
+
+ // Avatar
+ BOOL avatars_show;
+ BOOL avatars_draw_border;
+ COLORREF avatars_border_color;
+ BOOL avatars_round_corners;
+ BOOL avatars_use_custom_corner_size;
+ int avatars_custom_corner_size;
+ BOOL avatars_ignore_size_for_row_height;
+ BOOL avatars_draw_overlay;
+ int avatars_overlay_type;
+
+ int avatars_maxheight_size;
+ int avatars_maxwidth_size;
+
+ // Icon
+ BOOL icon_hide_on_avatar;
+ BOOL icon_draw_on_avatar_space;
+ BOOL icon_ignore_size_for_row_height;
+
+ // Contact time
+ BOOL contact_time_show;
+ BOOL contact_time_show_only_if_different;
+
+ // Text
+ BOOL text_rtl;
+ BOOL text_align_right;
+ BOOL text_replace_smileys;
+ BOOL text_resize_smileys;
+ int text_smiley_height;
+ BOOL text_use_protocol_smileys;
+ BOOL text_ignore_size_for_row_height;
+
+ // First line
+ BOOL first_line_draw_smileys;
+ BOOL first_line_append_nick;
+
+ // Second line
+ BOOL second_line_show;
+ int second_line_top_space;
+ BOOL second_line_draw_smileys;
+ int second_line_type;
+ TCHAR second_line_text[TEXT_TEXT_MAX_LENGTH];
+ BOOL second_line_xstatus_has_priority;
+ BOOL second_line_show_status_if_no_away;
+ BOOL second_line_show_listening_if_no_away;
+ BOOL second_line_use_name_and_message_for_xstatus;
+
+ // Third line
+ BOOL third_line_show;
+ int third_line_top_space;
+ BOOL third_line_draw_smileys;
+ int third_line_type;
+ TCHAR third_line_text[TEXT_TEXT_MAX_LENGTH];
+ BOOL third_line_xstatus_has_priority;
+ BOOL third_line_show_status_if_no_away;
+ BOOL third_line_show_listening_if_no_away;
+ BOOL third_line_use_name_and_message_for_xstatus;
+ struct ClcModernFontInfo fontModernInfo[FONTID_MODERN_MAX+1];
+ HWND hWnd;
+ BYTE menuOwnerType;
+ int menuOwnerID;
+ DWORD m_paintCouter; //range is enoght to 49 days if painting will occure each one millisecond
+ BYTE useMetaIcon;
+ BYTE drawOverlayedStatus;
+ int nInsertionLevel;
+
+ BYTE dbbMetaHideExtra;
+ BYTE dbbBlendInActiveState;
+ BYTE dbbBlend25;
+
+ XPTHANDLE hCheckBoxTheme;
+ BYTE bCompactMode;
+
+ HIMAGELIST himlWideExtraColumns;
+
+};
+
+struct SHORTDATA
+{
+ HWND hWnd;
+ BOOL contact_time_show_only_if_different;
+ int text_smiley_height;
+ BOOL text_replace_smileys;
+ BOOL text_use_protocol_smileys;
+
+ // Second line
+ BOOL second_line_show;
+ BOOL second_line_draw_smileys;
+ int second_line_type;
+ TCHAR second_line_text[TEXT_TEXT_MAX_LENGTH];
+ BOOL second_line_xstatus_has_priority;
+ BOOL second_line_show_status_if_no_away;
+ BOOL second_line_show_listening_if_no_away;
+ BOOL second_line_use_name_and_message_for_xstatus;
+
+ // Third line
+ BOOL third_line_show;
+ BOOL third_line_draw_smileys;
+ int third_line_type;
+ TCHAR third_line_text[TEXT_TEXT_MAX_LENGTH];
+ BOOL third_line_xstatus_has_priority;
+ BOOL third_line_show_status_if_no_away;
+ BOOL third_line_show_listening_if_no_away;
+ BOOL third_line_use_name_and_message_for_xstatus;
+};
+
+
+typedef struct tagOVERLAYICONINFO
+{
+ char *name;
+ char *description;
+ int id;
+ int listID;
+} OVERLAYICONINFO;
+
+//clc.c
+void ClcOptionsChanged(void);
+
+//clcidents.c
+int cliGetRowsPriorTo(struct ClcGroup *group,struct ClcGroup *subgroup,int contactIndex);
+int FindItem(HWND hwnd,struct ClcData *dat,HANDLE hItem,struct ClcContact **contact,struct ClcGroup **subgroup,int *isVisible, BOOL isIgnoreSubcontacts );
+int cliGetRowByIndex(struct ClcData *dat,int testindex,struct ClcContact **contact,struct ClcGroup **subgroup);
+HANDLE ContactToHItem(struct ClcContact *contact);
+HANDLE ContactToItemHandle(struct ClcContact *contact,DWORD *nmFlags);
+void ClearRowByIndexCache();
+
+//clcitems.c
+struct ClcGroup *cli_AddGroup(HWND hwnd,struct ClcData *dat,const TCHAR *szName,DWORD flags,int groupId,int calcTotalMembers);
+void cli_FreeGroup(struct ClcGroup *group);
+int cli_AddInfoItemToGroup(struct ClcGroup *group,int flags,const TCHAR *pszText);
+void cliRebuildEntireList(HWND hwnd,struct ClcData *dat);
+void cli_DeleteItemFromTree(HWND hwnd,HANDLE hItem);
+void cli_AddContactToTree(HWND hwnd,struct ClcData *dat,HANDLE hContact,int updateTotalCount,int checkHideOffline);
+void cli_SortCLC(HWND hwnd,struct ClcData *dat,int useInsertionSort);
+int GetNewSelection(struct ClcGroup *group,int selection, int direction);
+
+//clcmsgs.c
+LRESULT cli_ProcessExternalMessages(HWND hwnd,struct ClcData *dat,UINT msg,WPARAM wParam,LPARAM lParam);
+
+//clcutils.c
+void cliRecalcScrollBar(HWND hwnd,struct ClcData *dat);
+void cliBeginRenameSelection(HWND hwnd,struct ClcData *dat);
+int cliHitTest(HWND hwnd,struct ClcData *dat,int testx,int testy,struct ClcContact **contact,struct ClcGroup **group,DWORD *flags);
+void cliScrollTo(HWND hwnd,struct ClcData *dat,int desty,int noSmooth);
+int GetDropTargetInformation(HWND hwnd,struct ClcData *dat,POINT pt);
+void LoadCLCOptions(HWND hwnd,struct ClcData *dat);
+
+
+//clcpaint.c
+void CLCPaint_cliPaintClc(HWND hwnd,struct ClcData *dat,HDC hdc,RECT *rcPaint);
+
+//clcopts.c
+int ClcOptInit(WPARAM wParam,LPARAM lParam);
+DWORD GetDefaultExStyle(void);
+void GetFontSetting(int i,LOGFONT *lf,COLORREF *colour,BYTE *effect, COLORREF *eColour1,COLORREF *eColour2);
+
+//clistsettings.c
+TCHAR * GetContactDisplayNameW( HANDLE hContact, int mode );
+
+//groups.c
+TCHAR* GetGroupNameTS( int idx, DWORD* pdwFlags );
+int RenameGroupT(WPARAM groupID, LPARAM newName);
+
+int GetContactCachedStatus(HANDLE hContact);
+char *GetContactCachedProtocol(HANDLE hContact);
+
+#endif /* _CLC_H_ */
diff --git a/plugins/Clist_modern/src/hdr/modern_clcpaint.h b/plugins/Clist_modern/src/hdr/modern_clcpaint.h
new file mode 100644
index 0000000000..9c2a2d68d6
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_clcpaint.h
@@ -0,0 +1,191 @@
+#ifndef modern_clcpaint_h__
+#define modern_clcpaint_h__
+
+extern class CLCPaint g_clcPainter;
+class CLCPaint
+{
+
+public:
+ CLCPaint();
+ ~CLCPaint() {};
+
+ CLINTERFACE void cliPaintClc( HWND hwnd, struct ClcData *dat, HDC hdc, RECT *rcPaint );
+ CLINTERFACE tPaintCallbackProc PaintCallbackProc( HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData );
+
+ BOOL IsForegroundWindow( HWND hWnd );
+ HFONT ChangeToFont( HDC hdc, struct ClcData *dat, int id, int *fontHeight );
+ int GetBasicFontID( struct ClcContact * contact );
+ void GetTextSize( SIZE *text_size, HDC hdcMem, RECT free_row_rc, TCHAR *szText, SortedList *plText, UINT uTextFormat, int smiley_height );
+ void AddParam( MODERNMASK * mpModernMask, DWORD dwParamHash, const char* szValue, DWORD dwValueHash );
+ BOOL CheckMiniMode( struct ClcData *dat, BOOL selected, BOOL hot );
+
+private:
+ static const int HORIZONTAL_SPACE;
+ static const int EXTRA_CHECKBOX_SPACE;
+ static const int EXTRA_SPACE;
+ static const int SELECTION_BORDER;
+ static const int MIN_TEXT_WIDTH;
+ static const int BUF2SIZE;
+
+ static const BYTE GIM_SELECTED_AFFECT;
+ static const BYTE GIM_HOT_AFFECT;
+ static const BYTE GIM_TEMP_AFFECT;
+ static const BYTE GIM_IDLE_AFFECT;
+ static const BYTE GIM_EXTRAICON_AFFECT;
+ static const BYTE GIM_STATUSICON_AFFECT;
+ static const BYTE GIM_AVATAR_AFFECT;
+
+ enum tagenumHASHINDEX
+ {
+ hi_Module=0,
+ hi_ID,
+ hi_Type,
+ hi_Open,
+ hi_IsEmpty,
+ hi_SubPos,
+ hi_Protocol,
+ hi_RootGroup,
+ hi_Status,
+ hi_HasAvatar,
+ hi_GroupPos,
+ hi_Selected,
+ hi_Hot,
+ hi_Odd,
+ hi_Indent,
+ hi_Index,
+ hi_Name,
+ hi_Group,
+ hi_True,
+ hi_False,
+ hi_ONLINE,
+ hi_AWAY,
+ hi_DND,
+ hi_NA,
+ hi_OCCUPIED,
+ hi_FREECHAT,
+ hi_INVISIBLE,
+ hi_OUTTOLUNCH,
+ hi_ONTHEPHONE,
+ hi_IDLE,
+ hi_OFFLINE,
+ hi_Row,
+ hi_CL,
+ hi_SubContact,
+ hi_MetaContact,
+ hi_Contact,
+ hi_Divider,
+ hi_Info,
+ hi_First_Single,
+ hi_First,
+ hi_Middle,
+ hi_Mid,
+ hi_Single,
+ hi_Last,
+ hi_Rate,
+ hi_None,
+ hi_Low,
+ hi_Medium,
+ hi_High,
+ hi_State,
+ hi_stActive,
+ hi_stInactive,
+ //ADD new item above here
+ hi_LastItem
+ } enumHASHINDEX;
+ static const char * HASHTEXT[hi_LastItem];
+ static DWORD HASH[hi_LastItem];
+
+
+
+ void _FillQuickHash();
+ void _SetHotTrackColour( HDC hdc, struct ClcData *dat );
+ int _GetStatusOnlineness( int status );
+ int _GetGeneralisedStatus();
+ int _GetRealStatus( struct ClcContact * pContact, int nStatus );
+ RECT _GetRectangle( struct ClcData *dat, RECT *row_rc, RECT *free_row_rc, int *left_pos, int *right_pos, BOOL left, int real_width, int width, int height, int horizontal_space );
+ void _DrawTextSmiley( HDC hdcMem, RECT * free_rc, SIZE * text_size, TCHAR *szText, int len, SortedList *plText, UINT uTextFormat, BOOL ResizeSizeSmiley );
+ void _AddParameter( MODERNMASK * mpModernMask, MASKPARAM * lpParam );
+ void _AddParamShort( MODERNMASK * mpModernMask, DWORD dwParamIndex, DWORD dwValueIndex );
+ void _FillParam( MASKPARAM * lpParam, DWORD dwParamHash, const char* szValue, DWORD dwValueHash );
+ MODERNMASK * _GetCLCContactRowBackModernMask( struct ClcGroup * group, struct ClcContact * Drawing, int indent, int index, BOOL selected, BOOL hottrack, struct ClcData * dat );
+ void _RTLRect( RECT *rect, int width, int offset );
+ void _PaintRowItemsEx( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT row_rc, RECT free_row_rc, int left_pos, int right_pos, int selected, int hottrack, RECT *rcPaint );
+ void _DrawStatusIcon( struct ClcContact * Drawing, struct ClcData *dat, int iImage, HDC hdcMem, int x, int y, int cx, int cy, DWORD colorbg, DWORD colorfg, int mode );
+ BOOL _DrawNonEnginedBackground( HWND hwnd, HDC hdcMem, RECT * rcPaint, RECT clRect, struct ClcData * dat );
+ void _PaintClc( HWND hwnd, struct ClcData *dat, HDC hdc, RECT *rcPaint );
+ void _StoreItemPos( struct ClcContact *contact, int ItemType, RECT * rc );
+ void _CalcItemsPos( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *in_row_rc, RECT *in_free_row_rc, int left_pos, int right_pos, int selected, int hottrack );
+ BOOL __IsVisible( RECT * firtRect, RECT * secondRect );
+ void _GetBlendMode( IN struct ClcData *dat, IN struct ClcContact * Drawing, IN BOOL selected, IN BOOL hottrack, IN BOOL bFlag, OUT COLORREF * OutColourFg, OUT int * OutMode );
+ void _DrawContactItems( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *row_rc, RECT *free_row_rc, int left_pos, int right_pos, int selected, int hottrack, RECT *rcPaint );
+ void _PaintRowItems ( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT row_rc, RECT free_row_rc, int left_pos, int right_pos, int selected, int hottrack, RECT *rcPaint );
+
+ void _DrawContactAvatar ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *row_rc, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem );
+ void _DrawContactIcon ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem );
+ void _DrawContactText ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem, UINT uTextFormat );
+ void _DrawContactSubText ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem, UINT uTextFormat, BYTE itemType );
+ void _DrawContactTime ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem );
+ void _DrawContactExtraIcon ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * rc, int iImage );
+ void _DrawContactSelection ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT *rcPaint, RECT * prcItem );
+ void _DrawContactLine ( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *free_row_rc, RECT *rcPaint, RECT& text_rc );
+
+ int _rcWidth( RECT *rc ) { return rc->right-rc->left; }
+ int _rcHeight( RECT *rc ) { return rc->bottom-rc->top; }
+
+private:
+ enum enDrawMode
+ {
+ DM_LAYERED = 1, // Draw normal skin on 32 bit with alpha layer
+ DM_NON_LAYERED = 2, // Draw skinnable, but does not take care about alpha
+ DM_CLASSIC = 4, // Old style draw for classic
+ DM_CONTROL = 8, // Draw as control according to windows color scheme
+ DM_FLOAT = 16, // Float mode
+ DM_GRAY = 32, // Grayed mode
+ DM_GREYALTERNATE = 64, // Gray odd lines
+ DM_DRAW_OFFSCREEN = DM_FLOAT | DM_CONTROL | DM_NON_LAYERED | DM_CLASSIC,
+
+ };
+
+ inline int _DetermineDrawMode( HWND hWnd, struct ClcData *dat );
+
+ struct _PaintContext
+ {
+ enum
+ { release_none = 0,
+ release_hdcmem2 = 1,
+ release_hdcmem = 2
+ };
+ HDC hdcMem;
+ HDC hdcMem2;
+
+ HBITMAP hBmpOsb2;
+ HBITMAP oldbmp2;
+
+ HBITMAP hBmpOsb;
+ HBITMAP oldbmp;
+
+ HBRUSH hBrushAlternateGrey;
+ COLORREF tmpbkcolour;
+ COLORREF tmpforecolour;
+
+ DWORD fRelease;
+ _PaintContext( HDC _hdcMem = NULL) :
+ hdcMem ( _hdcMem ), hdcMem2( NULL ),
+ hBmpOsb2( NULL ), oldbmp2( NULL ),
+ hBmpOsb( NULL ), oldbmp( NULL ),
+ hBrushAlternateGrey ( NULL ),
+ tmpbkcolour( 0 ), tmpforecolour( 0 ),
+ fRelease ( release_none ) {};
+ };
+ inline void _PreparePaintContext( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT& clRect, _PaintContext& pc );
+ inline void _DrawBackground( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT* rcPaint, RECT& clRect, _PaintContext& pc );
+ inline void _DrawLines( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT* rcPaint, RECT& clRect, _PaintContext& pc );
+ inline void _DrawInsertionMark( struct ClcData * dat, RECT& clRect, _PaintContext& pc );
+ inline void _CopyPaintToDest( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT* rcPaint, RECT& clRect, _PaintContext& pc );
+ inline void _FreePaintContext( _PaintContext& pc );
+
+ // void _PaintClcOld( HWND hwnd, struct ClcData *dat, HDC hdc, RECT *rcPaint );
+};
+
+
+#endif // modern_clcpaint_h__
diff --git a/plugins/Clist_modern/src/hdr/modern_clist.h b/plugins/Clist_modern/src/hdr/modern_clist.h
new file mode 100644
index 0000000000..527bf18b64
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_clist.h
@@ -0,0 +1,165 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#pragma once
+
+#ifndef _CLIST_H_
+#define _CLIST_H_
+
+void LoadContactTree(void);
+int ExtIconFromStatusMode(HANDLE hContact, const char *szProto,int status);
+HTREEITEM GetTreeItemByHContact(HANDLE hContact);
+void cli_ChangeContactIcon(HANDLE hContact,int iIcon,int add);
+int GetContactInfosForSort(HANDLE hContact,char **Proto,TCHAR **Name,int *Status);
+
+typedef HMONITOR ( WINAPI *pfnMyMonitorFromPoint )(POINT,DWORD);
+extern pfnMyMonitorFromPoint MyMonitorFromPoint;
+
+typedef HMONITOR( WINAPI *pfnMyMonitorFromWindow) (HWND, DWORD);
+extern pfnMyMonitorFromWindow MyMonitorFromWindow;
+
+typedef BOOL(WINAPI *pfnMyGetMonitorInfo) (HMONITOR, LPMONITORINFO);
+extern pfnMyGetMonitorInfo MyGetMonitorInfo;
+
+///////////////////////////////////////////////////////////////////////////////
+
+class CSmileyString
+{
+public:
+ SortedList* plText;
+ int iMaxSmileyHeight;
+
+ CSmileyString() : plText( NULL ), iMaxSmileyHeight( 0 ) {};
+ CSmileyString( const CSmileyString& ssIn )
+ {
+ _CopySmileyList( ssIn.plText );
+ iMaxSmileyHeight = ssIn.iMaxSmileyHeight;
+ }
+
+ CSmileyString& operator= ( const CSmileyString& ssIn )
+ {
+ DestroySmileyList();
+ _CopySmileyList( ssIn.plText );
+ iMaxSmileyHeight = ssIn.iMaxSmileyHeight;
+ return *this;
+ }
+
+ ~CSmileyString()
+ {
+ DestroySmileyList();
+ }
+
+ void ReplaceSmileys(struct SHORTDATA *dat, struct displayNameCacheEntry *pdnce, TCHAR *szText, BOOL replace_smileys);
+
+ /** Destroy smiley list */
+ void DestroySmileyList();
+ /** Copy Smiley List */
+ void _CopySmileyList( SortedList *plInput );
+ void AddListeningToIcon(struct SHORTDATA *dat, struct displayNameCacheEntry *pdnce, TCHAR *szText, BOOL replace_smileys);
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+struct displayNameCacheEntry : public ClcCacheEntryBase
+{
+ int m_cache_nNoHiddenOffline;
+
+ char* m_cache_cszProto;
+ bool m_cache_bProtoNotExists;
+ int m_cache_nStatus;
+ int m_cache_nHiddenSubcontact;
+
+ int i;
+ int ApparentMode;
+ int NotOnList;
+ int IdleTS;
+ void* ClcContact;
+ BYTE IsExpanded;
+ bool isUnknown;
+
+ TCHAR* szSecondLineText;
+ CSmileyString ssSecondLine;
+
+ TCHAR* szThirdLineText;
+ CSmileyString ssThirdLine;
+
+ HANDLE hTimeZone;
+ DWORD dwLastMsgTime;
+
+ void getName(void);
+ void freeName(void);
+};
+
+typedef displayNameCacheEntry *pdisplayNameCacheEntry, *PDNCE;
+
+///////////////////////////////////////////////////////////////////////////////
+
+typedef struct tagEXTRASLOTINFO
+{
+ union
+ {
+ TCHAR * ptszSlotName; // one of this string should be given
+ char * pszSlotName;
+ };
+ char * pszSlotID;
+ BOOL fUnicode;
+ BYTE iSlot; // the slot 10-16 are available, do not use
+} EXTRASLOTINFO;
+
+#define CLVM_FILTER_PROTOS 1
+#define CLVM_FILTER_GROUPS 2
+#define CLVM_FILTER_STATUS 4
+#define CLVM_FILTER_VARIABLES 8
+#define CLVM_STICKY_CONTACTS 16
+#define CLVM_FILTER_STICKYSTATUS 32
+#define CLVM_FILTER_LASTMSG 64
+#define CLVM_FILTER_LASTMSG_OLDERTHAN 128
+#define CLVM_FILTER_LASTMSG_NEWERTHAN 256
+
+#define CLVM_PROTOGROUP_OP 1
+#define CLVM_GROUPSTATUS_OP 2
+#define CLVM_AUTOCLEAR 4
+#define CLVM_INCLUDED_UNGROUPED 8
+#define CLVM_USELASTMSG 16
+
+#define CLVM_USEGROUPS 32
+#define CLVM_DONOTUSEGROUPS 64
+
+//changes the 'use groups' flag and call CLUI v0.8.0.16+
+//wParam=newValue
+//lParam=0
+//returns 0 on success, nonzero on failure
+//newValue is 0 to not use gruops, 1 to use groups
+//or -1 to toggle the value
+#define MS_CLIST_SETUSEGROUPS "CList/SetUseGroups"
+
+
+#if defined(_UNICODE)
+#define CLVM_MODULE "CLVM_W"
+#else
+#define CLVM_MODULE "CLVM"
+#endif
+
+#define GROUPF_SHOWOFFLINE 0x40
+
+#endif \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_clui.h b/plugins/Clist_modern/src/hdr/modern_clui.h
new file mode 100644
index 0000000000..eb353f4609
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_clui.h
@@ -0,0 +1,193 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+
+listed in contributors.txt.
+
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#ifndef modern_clui_h__
+#define modern_clui_h__
+
+#include "windowsX.h"
+#define HANDLE_MESSAGE( _message, _fn) \
+ case (_message): return This->_fn((_message), (wParam), (lParam))
+
+class CLUI
+{
+public:
+ static HWND m_hWnd;
+ static CLUI * m_pCLUI;
+ static BOOL m_fMainMenuInited;
+
+private:
+ CLUI(); // is protected use InitClui to initialize instead
+
+public:
+ ~CLUI();
+
+ static HRESULT InitClui() { m_pCLUI = new CLUI(); return S_OK; };
+ static HWND& ClcWnd() { return pcli->hwndContactTree; }
+ static HWND& CluiWnd() { return pcli->hwndContactList; }
+ static CLUI * GetClui() { return m_pCLUI; }
+ static BOOL IsMainMenuInited() { return CLUI::m_fMainMenuInited; }
+
+ CLINTERFACE void cliOnCreateClc();
+
+ EVENTHOOK( OnEvent_ModulesLoaded );
+ EVENTHOOK( OnEvent_ContactMenuPreBuild );
+ EVENTHOOK( OnEvent_DBSettingChanging );
+ EVENTHOOK( OnEvent_FontReload );
+
+ SERVICE( Service_ShowMainMenu );
+ SERVICE( Service_ShowStatusMenu );
+ SERVICE( Service_Menu_ShowContactAvatar );
+ SERVICE( Service_Menu_HideContactAvatar );
+
+ static LRESULT CALLBACK cli_ContactListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+ {
+ CLUI * This = m_pCLUI;
+ if ( !m_hWnd ) m_hWnd = hwnd;
+
+ BOOL bHandled = FALSE;
+ LRESULT lRes= This->PreProcessWndProc( msg, wParam, lParam, bHandled );
+ if ( bHandled ) return lRes;
+
+ switch ( msg )
+ {
+ HANDLE_MESSAGE( WM_NCCREATE, OnNcCreate );
+ HANDLE_MESSAGE( WM_CREATE, OnCreate );
+ HANDLE_MESSAGE( UM_CREATECLC, OnCreateClc );
+ HANDLE_MESSAGE( UM_SETALLEXTRAICONS, OnSetAllExtraIcons );
+ HANDLE_MESSAGE( WM_INITMENU, OnInitMenu );
+ HANDLE_MESSAGE( WM_SIZE, OnSizingMoving );
+ HANDLE_MESSAGE( WM_SIZING, OnSizingMoving );
+ HANDLE_MESSAGE( WM_MOVE, OnSizingMoving );
+ HANDLE_MESSAGE( WM_EXITSIZEMOVE, OnSizingMoving );
+ HANDLE_MESSAGE( WM_WINDOWPOSCHANGING, OnSizingMoving );
+ HANDLE_MESSAGE( WM_DISPLAYCHANGE, OnSizingMoving );
+ HANDLE_MESSAGE( WM_THEMECHANGED, OnThemeChanged );
+ HANDLE_MESSAGE( WM_DWMCOMPOSITIONCHANGED, OnDwmCompositionChanged );
+ HANDLE_MESSAGE( UM_SYNCCALL, OnSyncCall );
+ HANDLE_MESSAGE( UM_UPDATE, OnUpdate );
+ HANDLE_MESSAGE( WM_NCACTIVATE, OnNcPaint );
+ HANDLE_MESSAGE( WM_PRINT, OnNcPaint );
+ HANDLE_MESSAGE( WM_NCPAINT, OnNcPaint );
+ HANDLE_MESSAGE( WM_ERASEBKGND, OnEraseBkgnd );
+ HANDLE_MESSAGE( WM_PAINT, OnPaint );
+ HANDLE_MESSAGE( WM_LBUTTONDOWN, OnLButtonDown );
+ HANDLE_MESSAGE( WM_PARENTNOTIFY, OnParentNotify );
+ HANDLE_MESSAGE( WM_SETFOCUS, OnSetFocus );
+ HANDLE_MESSAGE( WM_TIMER, OnTimer );
+ HANDLE_MESSAGE( WM_ACTIVATE, OnActivate );
+ HANDLE_MESSAGE( WM_SETCURSOR, OnSetCursor );
+ HANDLE_MESSAGE( WM_MOUSEACTIVATE, OnMouseActivate );
+ HANDLE_MESSAGE( WM_NCLBUTTONDOWN, OnNcLButtonDown );
+ HANDLE_MESSAGE( WM_NCLBUTTONDBLCLK, OnNcLButtonDblClk );
+ HANDLE_MESSAGE( WM_NCHITTEST, OnNcHitTest );
+ HANDLE_MESSAGE( WM_SHOWWINDOW, OnShowWindow );
+ HANDLE_MESSAGE( WM_SYSCOMMAND, OnSysCommand );
+ HANDLE_MESSAGE( WM_KEYDOWN, OnKeyDown );
+ HANDLE_MESSAGE( WM_GETMINMAXINFO, OnGetMinMaxInfo );
+ HANDLE_MESSAGE( WM_MOVING, OnMoving );
+ HANDLE_MESSAGE( WM_NOTIFY, OnNotify );
+ HANDLE_MESSAGE( WM_CONTEXTMENU, OnContextMenu );
+ HANDLE_MESSAGE( WM_MEASUREITEM, OnMeasureItem );
+ HANDLE_MESSAGE( WM_DRAWITEM, OnDrawItem );
+ HANDLE_MESSAGE( WM_DESTROY, OnDestroy );
+ default:
+ return This->DefCluiWndProc( msg, wParam, lParam );
+ }
+ return FALSE;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // METHODS
+ //
+private:
+ HRESULT CreateCLC();
+ HRESULT FillAlphaChannel( HDC hDC, RECT* prcParent, BYTE bAlpha);
+ HRESULT SnappingToEdge( WINDOWPOS * lpWindowPos );
+ HRESULT LoadDllsRuntime();
+ HRESULT RegisterAvatarMenu(); // TODO move to CLC class
+ HRESULT CreateCluiFrames();
+ HRESULT CreateCLCWindow(const HWND parent);
+ HRESULT CreateUIFrames();
+
+ LRESULT DefCluiWndProc( UINT msg, WPARAM wParam, LPARAM lParam )
+ {
+ return corecli.pfnContactListWndProc( m_hWnd, msg, wParam, lParam );
+ }
+
+ // MessageMap
+ LRESULT PreProcessWndProc( UINT msg, WPARAM wParam, LPARAM lParam, BOOL& bHandled );
+ LRESULT OnSizingMoving( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnThemeChanged( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnDwmCompositionChanged( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnSyncCall( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnUpdate( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnInitMenu( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnNcPaint( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnEraseBkgnd( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnNcCreate( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnPaint( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnCreate( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnSetAllExtraIcons( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnCreateClc( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnLButtonDown( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnParentNotify( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnSetFocus( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnStatusBarUpdateTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnAutoAlphaTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnSmoothAlphaTransitionTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnDelayedSizingTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnBringOutTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnBringInTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnUpdateBringTimer( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnActivate( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnSetCursor( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnMouseActivate( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnNcLButtonDown( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnNcLButtonDblClk( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnNcHitTest( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnShowWindow( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnSysCommand( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnKeyDown( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnGetMinMaxInfo( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnMoving( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnNotify( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnNewContactNotify( NMCLISTCONTROL * pnmc );
+ LRESULT OnListRebuildNotify( NMCLISTCONTROL * pnmc );
+ LRESULT OnListSizeChangeNotify( NMCLISTCONTROL * pnmc );
+ LRESULT OnClickNotify( NMCLISTCONTROL * pnmc );
+ LRESULT OnContextMenu( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnMeasureItem( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnDrawItem( UINT msg, WPARAM wParam, LPARAM lParam );
+ LRESULT OnDestroy( UINT msg, WPARAM wParam, LPARAM lParam );
+
+protected:
+ HMODULE m_hDwmapiDll;
+ HMODULE m_hUserDll;
+
+ enum { SNAPTOEDGESENSIVITY = 30 };
+};
+
+#endif // modern_clui_h__ \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_cluiframes.h b/plugins/Clist_modern/src/hdr/modern_cluiframes.h
new file mode 100644
index 0000000000..e2c1aade78
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_cluiframes.h
@@ -0,0 +1,150 @@
+/*
+Miranda ICQ: the free icq client for MS Windows
+Copyright (C) 2000-2 Richard Hughes, Roland Rabien & Tristan Van de Vreede
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#pragma once
+
+#ifndef _CLUIFRAMES_H_
+#define _CLUIFRAMES_H_
+
+#include "../m_api/m_skin_eng.h"
+
+int LoadCLUIFramesModule(void);
+int UnLoadCLUIFramesModule(void);
+int CLUIFramesGetMinHeight();
+int CLUIFramesOnClistResize(WPARAM wParam,LPARAM lParam);
+int CLUIFrames_GetTotalHeight();
+
+typedef struct tagProtocolData {
+ char *RealName;
+ int protopos;
+ boolean show;
+} ProtocolData;
+
+typedef struct
+{
+ int order;
+ int realpos;
+}SortData;
+
+
+
+
+//============
+#define CLUIFRAMESSETALIGN "CLUIFramesSetAlign"
+
+#define CLUIFRAMESSETALIGNALTOP "CLUIFramesSetAlignalTop"
+#define CLUIFRAMESSETALIGNALCLIENT "CLUIFramesSetAlignalClient"
+#define CLUIFRAMESSETALIGNALBOTTOM "CLUIFramesSetAlignalBottom"
+#define CLUIFRAMESSETFLOATING "Set_Floating"
+
+#define CLUIFRAMESMOVEUPDOWN "CLUIFramesMoveUpDown"
+#define CLUIFRAMESMOVEUP "CLUIFramesMoveUp"
+#define CLUIFRAMESMOVEDOWN "CLUIFramesMoveDown"
+
+typedef struct tagMenuHandles
+{
+ HANDLE MainMenuItem;
+ HANDLE MIVisible,MITitle,MITBVisible,MILock,MIColl,MIFloating,MIAlignRoot;
+ HANDLE MIAlignTop,MIAlignClient,MIAlignBottom;
+ HANDLE MIBorder;
+ HANDLE MIPosRoot;
+ HANDLE MIPosUp,MIPosDown;
+} FrameMenuHandles;
+
+typedef struct tagFrameTitleBar{
+ HWND hwnd;
+ HWND TitleBarbutt;
+ HWND hwndTip;
+
+ TCHAR* tbname;
+ TCHAR* tooltip;
+
+ char * sztbname;
+ char * sztooltip;
+
+ HMENU hmenu;
+ HICON hicon;
+
+ BOOLEAN ShowTitleBar;
+ BOOLEAN ShowTitleBarTip;
+ COLORREF BackColour;
+ COLORREF TextColour;
+ int oldstyles;
+ POINT oldpos;
+ RECT wndSize;
+} FrameTitleBar;
+
+typedef struct _DockOpt
+{
+ HWND hwndLeft;
+ HWND hwndRight;
+}
+DockOpt;
+typedef struct _tagFrameWnd{
+ int id;
+ HWND hWnd ;
+ RECT wndSize;
+ TCHAR * Name;
+ char * szName;
+ int align;
+ int height;
+ int dwFlags;
+ BOOLEAN Locked;
+ BOOLEAN visible;
+ BOOLEAN needhide;
+ BOOLEAN collapsed;
+ int prevvisframe;
+ int HeightWhenCollapsed;
+ FrameTitleBar TitleBar;
+ FrameMenuHandles MenuHandles;
+ int oldstyles;
+ BOOLEAN floating;
+ HWND ContainerWnd;
+ POINT FloatingPos;
+ POINT FloatingSize;
+ BOOLEAN minmaxenabled;
+ BOOLEAN UseBorder;
+ int order;
+ DockOpt dockOpt;
+ HWND OwnerWindow;
+ tPaintCallbackProc PaintCallbackProc;
+ sPaintRequest * PaintData;
+ BOOLEAN bQueued;
+ HRGN UpdateRgn;
+
+} FRAMEWND;
+
+#define OFFSET_PROTOPOS 200
+#define OFFSET_VISIBLE 400
+
+#define CLUIFrameSubContainerClassName _T("CLUIFrameSubContainer")
+#define CLUIFrameTitleBarClassName _T("CLUIFrameTitleBar")
+#define CLUIFrameModule "CLUIFrames"
+
+//integrated menu module
+#define MS_INT_MENUMEASUREITEM "CLUIFrames/IntMenuMeasureItem"
+#define MS_INT_MENUDRAWITEM "CLUIFrames/IntMenuDrawItem"
+#define MS_INT_MENUPROCESSCOMMAND "CLUIFrames/IntMenuProcessCommand"
+#define MS_INT_MODIFYMENUITEM "CLUIFrames/IntModifyMenuItem"
+
+#endif
+
+
+
+
diff --git a/plugins/Clist_modern/src/hdr/modern_commonheaders.h b/plugins/Clist_modern/src/hdr/modern_commonheaders.h
new file mode 100644
index 0000000000..922e0b0d90
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_commonheaders.h
@@ -0,0 +1,460 @@
+#ifndef commonheaders_h__
+#define commonheaders_h__
+
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#pragma once
+#define MIRANDA_VER 0x0A00
+
+#define _WIN32_WINNT 0x0501
+
+#ifndef _WIN32_IE
+#define _WIN32_IE 0x0501
+#endif
+
+#ifndef DB_USEHELPERFUNCTIONS // to supress static inline db helpers
+#define DB_NOHELPERFUNCTIONS
+#endif
+
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS // to suppress secure warnings in VC2005
+#endif
+
+#ifndef _CRT_SECURE_NO_DEPRECATE // to suppress secure deprecate warnings in VC2005
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+#if defined (_DEBUG)
+#define TRACE(str) { log0(str); }
+#else
+ #define TRACE(str)
+#endif
+
+#if defined (_DEBUG)
+ #define TRACEVAR(str,n) { log1(str,n); }
+#else
+ #define TRACEVAR(str,n)
+#endif
+
+#if defined (_DEBUG)
+#define TRACET(str) OutputDebugString(str)
+#else
+#define TRACET(str)
+#endif
+
+#define SERVICE(serviceproc) static INT_PTR serviceproc(WPARAM wParam,LPARAM lParam)
+#define EVENTHOOK(eventhookproc) static int eventhookproc(WPARAM wParam,LPARAM lParam)
+#define CLINTERFACE static
+
+#define PLUGININTERFACE extern "C" __declspec( dllexport )
+#define UPDATER_PATH "http://miranda-im.org/download/details.php?action=viewfile&id=3684"
+
+#include "m_stdhdr.h"
+
+#include <windows.h>
+#include <commctrl.h>
+#include <uxtheme.h>
+#include <vssym32.h>
+#include <stdio.h>
+#include <time.h>
+#include <stddef.h>
+//#include <process.h>
+#include <io.h>
+#include <math.h>
+#include <string.h>
+#include <direct.h>
+#include <win2k.h>
+
+#include "modern_global_structure.h"
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_system_cpp.h>
+#include <m_utils.h>
+
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_button.h>
+#include <m_options.h>
+#include <m_protosvc.h>
+#include <m_clist.h>
+#include <m_clistint.h>
+#include <m_skin.h>
+#include <m_contacts.h>
+#include <m_plugins.h>
+#include <m_avatars.h>
+#include <m_genmenu.h>
+#include <m_clui.h>
+#include <m_clc.h>
+#include <m_icolib.h>
+#include <m_userinfo.h>
+#include <m_addcontact.h>
+#include <m_fontservice.h>
+#include <m_file.h>
+#include <m_timezones.h>
+
+#include "modern_clc.h"
+#include "modern_clist.h"
+#include "modern_cluiframes.h"
+#include "m_cluiframes.h"
+#include "m_metacontacts.h"
+#include "../m_api/m_skin_eng.h"
+
+#include "modern_rowheight_funcs.h"
+#include "modern_cache_funcs.h"
+#include "modern_log.h"
+
+#include "richedit.h"
+#include "m_variables.h"
+
+#include "m_smileyadd.h"
+
+#include "../m_api/m_xpTheme.h"
+#include "../resource.h"
+
+#include "modern_layered_window_engine.h"
+
+// module name of MetaContacts plugin
+extern char *g_szMetaModuleName;
+
+//macros to free data and set it pointer to NULL
+#define mir_free_and_nil(x) {mir_free((void*)x); x=NULL;}
+// shared vars
+
+#define CLUI_FRAME_AUTOHIDENOTIFY 512
+#define CLUI_FRAME_SHOWALWAYS 1024
+
+
+//#define alloc(n) mir_alloc(n)
+
+#define MAX_REGS(_A_) (sizeof(_A_)/sizeof(_A_[0]))
+
+#ifndef CS_DROPSHADOW
+#define CS_DROPSHADOW 0x00020000
+#endif
+
+#define MENU_MIRANDAMENU 0xFFFF1234
+#define MENU_STATUSMENU 0xFFFF1235
+#define MENU_MINIMIZE 0xFFFF1236
+
+#define UM_CREATECLC (WM_USER+1)
+#define UM_SETALLEXTRAICONS (WM_USER+2)
+#define UM_UPDATE (WM_USER+50)
+#define UM_SYNCCALL (WM_USER+654)
+
+// Define constants for CLUI_SizingOnBorder SC_SIZE
+
+#define SCF_NONE 0
+#define SCF_LEFT 1
+#define SCF_RIGHT 2
+#define SCF_TOP 3
+#define SCF_BOTTOM 6
+
+char* __cdecl strstri( char *a, const char *b);
+BOOL __cdecl mir_bool_strcmpi(const char *a, const char *b);
+int __cdecl mir_strcmp (const char *a, const char *b);
+int __cdecl mir_strlen (const char *a);
+int __cdecl mir_strcmpi(const char *a, const char *b);
+int __cdecl mir_tstrcmpi(const TCHAR *a, const TCHAR *b);
+BOOL __cdecl mir_bool_tstrcmpi(const TCHAR *a, const TCHAR *b);
+DWORD exceptFunction(LPEXCEPTION_POINTERS EP);
+
+#ifndef MYCMP
+#define MYCMP 1
+#define strcmp(a,b) mir_strcmp(a,b)
+#define strlen(a) mir_strlen(a)
+#endif
+
+// Register of plugin's user
+//
+// wParam = (WPARAM)szSetting - string that describes a user
+// format: Category/ModuleName,
+// eg: "Contact list background/CLUI",
+// "Status bar background/StatusBar"
+// lParam = (LPARAM)dwFlags
+//
+#define MS_BACKGROUNDCONFIG_REGISTER "ModernBkgrCfg/Register"
+
+//
+// Notification about changed background
+// wParam = ModuleName
+// lParam = 0
+#define ME_BACKGROUNDCONFIG_CHANGED "ModernBkgrCfg/Changed"
+
+
+
+HBITMAP ske_CreateDIB32(int cx, int cy);
+
+extern void InitDisplayNameCache(void);
+extern void FreeDisplayNameCache();
+extern int CLUI_ShowWindowMod(HWND hwnd, int cmd);
+
+#ifdef UNICODE
+ #define GSMDF_TCHAR_MY GSMDF_TCHAR|CNF_UNICODE
+#else
+ #define GSMDF_TCHAR_MY 0
+#endif
+
+#ifndef LWA_COLORKEY
+#define LWA_COLORKEY 0x00000001
+#endif
+
+#ifndef AC_SRC_ALPHA
+#define AC_SRC_ALPHA 0x01
+#endif
+
+//#ifdef _DEBUG
+//#define DeleteObject(a) DebugDeleteObject(a)
+//#endif
+
+#define strsetA(a,b) {if (a) mir_free_and_nill(a); a=mir_strdup(b);}
+#define strsetT(a,b) {if (a) mir_free_and_nill(a); a=mir_tstrdup(b);}
+
+extern void TRACE_ERROR();
+extern BOOL DebugDeleteObject(HGDIOBJ a);
+extern BOOL mod_DeleteDC(HDC hdc);
+extern BOOL ske_ResetTextEffect(HDC hdc);
+extern BOOL ske_SelectTextEffect(HDC hdc, BYTE EffectID, DWORD FirstColor, DWORD SecondColor);
+extern void IvalidateDisplayNameCache(DWORD mode);
+
+typedef BOOL (WINAPI *pfnTryEnterCriticalSection)( LPCRITICAL_SECTION );
+extern pfnTryEnterCriticalSection fnTryEnterCriticalSection;
+
+typedef BOOL (WINAPI *pfnGetScrollBarInfo)( HWND, LONG, PSCROLLBARINFO );
+extern pfnGetScrollBarInfo fnGetScrollBarInfo;
+
+typedef DWORD (WINAPI *pfnMsgWaitForMultipleObjectsEx)( DWORD, CONST HANDLE*, DWORD, DWORD, DWORD );
+extern pfnMsgWaitForMultipleObjectsEx fnMsgWaitForMultipleObjectsEx;
+
+typedef HWND (WINAPI *pfnGetAncestor)( HWND, UINT );
+extern pfnGetAncestor fnGetAncestor;
+HWND WINAPI MyGetAncestor( HWND, UINT );
+
+typedef BOOL (WINAPI *pfnGetMenuBarInfo)( HWND, LONG, LONG, PMENUBARINFO );
+extern pfnGetMenuBarInfo fnGetMenuBarInfo;
+
+void FreeAndNil( void **p );
+
+extern SortedList *clistCache;
+
+HICON LoadSmallIconShared(HINSTANCE hInstance, LPCTSTR lpIconName);
+HICON LoadSmallIcon(HINSTANCE hInstance, LPCTSTR lpIconName);
+BOOL DestroyIcon_protect(HICON icon);
+
+#ifndef ETDT_ENABLETAB
+#define ETDT_DISABLE 0x00000001
+#define ETDT_ENABLE 0x00000002
+#define ETDT_USETABTEXTURE 0x00000004
+#define ETDT_ENABLETAB (ETDT_ENABLE | ETDT_USETABTEXTURE)
+#endif
+
+
+
+#define TreeView_InsertItemA(hwnd, lpis) \
+ (HTREEITEM)SendMessageA((hwnd), TVM_INSERTITEMA, 0, (LPARAM)(LPTV_INSERTSTRUCTA)(lpis))
+
+#define TreeView_GetItemA(hwnd, pitem) \
+ (BOOL)SendMessageA((hwnd), TVM_GETITEMA, 0, (LPARAM)(TV_ITEM *)(pitem))
+
+enum
+{
+ STATE_DLL_LOADING = 0,
+ STATE_CLUI_LOADING,
+ STATE_NORMAL,
+ STATE_PREPEARETOEXIT,
+ STATE_EXITING
+};
+
+#define MirandaLoading() ((g_CluiData.bSTATE<STATE_NORMAL))
+#define MirandaExiting() ((g_CluiData.bSTATE>STATE_NORMAL))
+
+char * strdupn(const char * src, int len);
+
+#define SORTBY_NAME 0
+#define SORTBY_STATUS 1
+#define SORTBY_LASTMSG 2
+#define SORTBY_PROTO 3
+#define SORTBY_RATE 4
+#define SORTBY_NAME_LOCALE 5
+#define SORTBY_NOTHING 10
+
+#define DT_FORCENATIVERENDER 0x10000000
+
+#define _BOOL(a) (a != 0)
+
+/* modern_animated_avatars.c */
+int AniAva_InitModule(); // HAVE TO BE AFTER GDI+ INITIALIZED
+int AniAva_UnloadModule();
+int AniAva_UpdateOptions(); //reload options, //hot enable/disable engine
+
+int AniAva_AddAvatar(HANDLE hContact, TCHAR * szFilename, int width, int heigth); // adds avatars to be displayed
+int AniAva_SetAvatarPos(HANDLE hContact, RECT * rc, int overlayIdx, BYTE bAlpha); // update avatars pos
+int AniAva_InvalidateAvatarPositions(HANDLE hContact); // reset positions of avatars to be drawn (still be painted at same place)
+int AniAva_RemoveInvalidatedAvatars(); // all avatars without validated position will be stop painted and probably removed
+int AniAva_RemoveAvatar(HANDLE hContact); // remove avatar
+int AniAva_RedrawAllAvatars(BOOL updateZOrder); // request to repaint all
+void AniAva_UpdateParent();
+int AniAva_RenderAvatar( HANDLE hContact, HDC hdcMem, RECT * rc );
+
+
+#define CCI_NAME 1
+#define CCI_GROUP (1<<1)
+#define CCI_PROTO (1<<2)
+#define CCI_STATUS (1<<3)
+#define CCI_LINES (1<<4)
+#define CCI_HIDDEN (1<<4)
+#define CCI_NOHIDEOFFLINE (1<<5)
+#define CCI_NOPROTO (1<<6)
+#define CCI_HIDESUBCONTACT (1<<7)
+#define CCI_I (1<<8)
+#define CCI_APPARENT (1<<9)
+#define CCI_NOTONLIST (1<<10)
+#define CCI_IDLETS (1<<11)
+#define CCI_CCONTACT (1<<12)
+#define CCI_EXPAND (1<<13)
+#define CCI_UNKNOWN (1<<14)
+#define CCI_TIME (1<<15)
+#define CCI_OTHER ~( CCI_NAME|CCI_GROUP|CCI_PROTO|CCI_STATUS|CCI_LINES|CCI_TIME )
+#define CCI_ALL (0xFFFFFFFF)
+
+void CListSettings_FreeCacheItemData(pdisplayNameCacheEntry pDst);
+int CLUI_SyncGetPDNCE(WPARAM wParam, LPARAM lParam);
+WORD pdnce___GetStatus(pdisplayNameCacheEntry pdnce);
+void pdnce___SetStatus( pdisplayNameCacheEntry pdnce, WORD wStatus );
+
+/* move to list module */
+typedef void (*ItemDestuctor)(void*);
+
+void li_ListDestruct(SortedList *pList, ItemDestuctor pItemDestructor);
+void li_RemoveDestruct(SortedList *pList, int index, ItemDestuctor pItemDestructor);
+void li_RemovePtrDestruct(SortedList *pList, void * ptr, ItemDestuctor pItemDestructor);
+void li_SortList(SortedList *pList, FSortFunc pSortFunct);
+
+#define mir_safe_free(a) if(a) mir_free(a)
+
+template <class T> class INIT : public T
+{
+public:
+ INIT()
+ {
+ memset(this, 0, sizeof(T));
+ this->cbSize=sizeof(T);
+ }
+};
+
+#ifdef __cplusplus
+const ROWCELL * rowAddCell(ROWCELL* &, int );
+void rowDeleteTree(ROWCELL *cell);
+BOOL rowParse(ROWCELL* &cell, ROWCELL* parent, char *tbuf, int &hbuf, int &sequence, ROWCELL** RowTabAccess );
+void rowSizeWithReposition(ROWCELL* &root, int width);
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+// Specific class for quick implementation of map<string, *> list
+// with some more fast searching it is
+// hash_map alternative - for faked hash search;
+// the items are stored no by char* key but both int(hash),char*.
+// have items sorted in map firstly via hash, secondly via string
+// the method is case insensitive
+// To use this simple define like
+// typedef std::map<HashStringKeyNoCase, _Type > map_Type;
+// map_Type myMap;
+// and access it as usual via simpe char* indexing:
+// myList[ "first" ]=_Type_value;
+// myList[ "second" ]=_Type_value;
+// _Type a = myList[ "second"];
+
+class HashStringKeyNoCase
+{
+public:
+
+ HashStringKeyNoCase( const char* szKey )
+ {
+ _strKey=_strdup( szKey );
+ _CreateHashKey();
+ }
+
+ HashStringKeyNoCase( const HashStringKeyNoCase& hsKey )
+ {
+ _strKey = _strdup( hsKey._strKey );
+ _dwKey = hsKey._dwKey;
+ }
+
+ HashStringKeyNoCase& operator= ( const HashStringKeyNoCase& hsKey )
+ {
+ _strKey = _strdup( hsKey._strKey );
+ _dwKey = hsKey._dwKey;
+ }
+
+#ifdef _UNICODE
+ HashStringKeyNoCase( const wchar_t* szKey )
+ {
+ int codepage=0;
+ int cbLen = WideCharToMultiByte( codepage, 0, szKey, -1, NULL, 0, NULL, NULL );
+ char* result = ( char* )malloc( cbLen+1 );
+ WideCharToMultiByte( codepage, 0, szKey, -1, result, cbLen, NULL, NULL );
+ result[ cbLen ] = 0;
+
+ _strKey=result;
+ _CreateHashKey();
+ }
+#endif
+
+ ~HashStringKeyNoCase()
+ {
+ if (_strKey) free (_strKey);
+ _strKey = NULL;
+ _dwKey=0;
+ }
+
+private:
+ char* _strKey;
+ DWORD _dwKey;
+
+ void _CreateHashKey()
+ {
+ _strKey=_strupr( _strKey );
+ _dwKey = mod_CalcHash( _strKey );
+ }
+
+public:
+ bool operator< ( const HashStringKeyNoCase& second ) const
+ {
+ if ( this->_dwKey != second._dwKey )
+ return ( this->_dwKey < second._dwKey );
+ else
+ return ( strcmp( this->_strKey, second._strKey ) < 0 ); // already maked upper so in any case - will be case insensitive
+ }
+
+ struct HashKeyLess
+ {
+ bool operator() ( const HashStringKeyNoCase& first, const HashStringKeyNoCase& second ) const
+ { return ( first < second ); }
+ };
+};
+
+#define EXTRACOLUMNCOUNT 10
+
+
+#endif // commonheaders_h__
diff --git a/plugins/Clist_modern/src/hdr/modern_commonprototypes.h b/plugins/Clist_modern/src/hdr/modern_commonprototypes.h
new file mode 100644
index 0000000000..d8cb8d33e9
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_commonprototypes.h
@@ -0,0 +1,356 @@
+#pragma once
+
+#ifndef _COMMONPROTOTYPES
+#define _COMMONPROTOTYPES
+
+#ifndef commonheaders_h__
+#error "hdr/modern_commonheaders.h have to be including first"
+#endif
+
+#include "modern_commonheaders.h" //TO DO: Move contents of this file to commonheaders.h
+#include "modern_clist.h"
+#include "modern_cluiframes.h"
+#include "modern_row.h"
+#include "modern_skinengine.h"
+#include "modern_skinselector.h"
+#include "modern_statusbar.h"
+
+#define SKIN "ModernSkin"
+
+extern PLUGININFOEX pluginInfo;
+extern CLIST_INTERFACE * pcli;
+extern CLIST_INTERFACE corecli;
+
+//Global variables
+extern int ON_SETALLEXTRAICON_CYCLE;
+extern BOOL CLM_AUTOREBUILD_WAS_POSTED;
+extern FRAMEWND *g_pfwFrames;
+extern int g_nFramesCount;
+extern RECT g_rcEdgeSizingRect;
+extern FRAMEWND *wndFrameEventArea;
+extern ROWCELL * gl_RowTabAccess[];
+extern ROWCELL * gl_RowRoot;
+extern HIMAGELIST hAvatarOverlays;
+extern int g_nTitleBarHeight;
+extern BOOL g_bTransparentFlag;
+extern HIMAGELIST g_himlCListClc;
+extern HIMAGELIST hCListImages;
+extern BOOL g_mutex_bSizing;
+extern BOOL LOCK_RECALC_SCROLLBAR;
+extern HIMAGELIST g_himlCListClc;
+extern int currentDesiredStatusMode;
+extern BYTE nameOrder[];
+extern SortedList lContactsCache;
+extern BOOL g_flag_bOnModulesLoadedCalled;
+extern HIMAGELIST hCListImages;
+extern SKINOBJECTSLIST g_SkinObjectList;
+extern CURRWNDIMAGEDATA * g_pCachedWindow;
+extern BOOL g_mutex_bLockUpdating;
+extern LISTMODERNMASK *MainModernMaskList;
+extern HIMAGELIST hCListImages;
+extern STATUSBARDATA g_StatusBarData;
+extern SKINOBJECTSLIST g_SkinObjectList;
+extern CURRWNDIMAGEDATA * g_pCachedWindow;
+extern char * g_szConnectingProto;
+extern BOOL g_mutex_bLockUpdating;
+extern BOOL g_mutex_bSetAllExtraIconsCycle;
+extern int g_mutex_nCalcRowHeightLock;
+extern int g_mutex_bOnTrayRightClick;
+extern BOOL g_flag_bPostWasCanceled;
+extern BOOL g_flag_bFullRepaint;
+extern BOOL g_bMultiConnectionMode;
+extern BYTE g_bCalledFromShowHide;
+extern HICON g_hListeningToIcon;
+extern BOOL glOtherSkinWasLoaded;
+extern BYTE glSkinWasModified;
+extern HWND g_hCLUIOptionsWnd;
+extern BOOL g_bTransparentFlag;
+extern HINSTANCE g_hInst;
+extern HIMAGELIST hCListImages;
+extern BOOL g_mutex_bChangingMode;
+extern DWORD g_dwMainThreadID;
+extern DWORD g_dwAwayMsgThreadID;
+extern DWORD g_dwGetTextAsyncThreadID;
+extern DWORD g_dwSmoothAnimationThreadID;
+extern DWORD g_dwFillFontListThreadID;
+extern HWND g_hwndViewModeFrame;
+extern HANDLE hSmileyAddOptionsChangedHook,hAvatarChanged,hIconChangedHook;
+extern BYTE gl_TrimText;
+
+/************************************************************************/
+/* TYPE DEFS */
+/************************************************************************/
+
+typedef INT_PTR (*PSYNCCALLBACKPROC)(WPARAM,LPARAM);
+
+/************************************************************************/
+/* PROTOTYPES */
+/************************************************************************/
+
+
+/* CLCItems */
+BOOL CLCItems_IsShowOfflineGroup(struct ClcGroup* group);
+
+/* CListMod */
+int CListMod_HideWindow(HWND hwndContactList, int mode);
+
+/* CLUI */
+HANDLE RegisterIcolibIconHandle(char * szIcoID, char *szSectionName, char * szDescription, TCHAR * tszDefaultFile, int iDefaultIndex, HINSTANCE hDefaultModule, int iDefaultResource );
+void CLUI_UpdateAeroGlass();
+void CLUI_ChangeWindowMode();
+BOOL CLUI_CheckOwnedByClui(HWND hwnd);
+INT_PTR CLUI_GetConnectingIconService(WPARAM wParam,LPARAM lParam);
+int CLUI_HideBehindEdge();
+int CLUI_IconsChanged(WPARAM,LPARAM);
+int CLUI_IsInMainWindow(HWND hwnd);
+HICON CLUI_LoadIconFromExternalFile (char *filename,int i,BOOL UseLibrary,bool registerit,char *IconName,char *SectName,char *Description,int internalidx, BOOL * needFree);
+int CLUI_OnSkinLoad(WPARAM wParam, LPARAM lParam);
+int CLUI_ReloadCLUIOptions();
+int CLUI_ShowFromBehindEdge();
+int CLUI_SizingGetWindowRect(HWND hwnd,RECT * rc);
+int CLUI_SizingOnBorder(POINT ,int);
+int CLUI_SmoothAlphaTransition(HWND hwnd, BYTE GoalAlpha, BOOL wParam);
+int CLUI_TestCursorOnBorders();
+int CLUI_UpdateTimer(BYTE BringIn);
+void CLUI_UpdateLayeredMode();
+UINT_PTR CLUI_SafeSetTimer(HWND hwnd, int ID, int Timeout, TIMERPROC proc);
+
+/* CLUIServices */
+INT_PTR CLUIServices_ProtocolStatusChanged(WPARAM wParam,LPARAM lParam);
+
+int CLUIUnreadEmailCountChanged(WPARAM wParam,LPARAM lParam);
+
+/* GDIPlus */
+BOOL GDIPlus_AlphaBlend(HDC hdcDest,int nXOriginDest,int nYOriginDest,int nWidthDest,int nHeightDest,HDC hdcSrc,int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc, BLENDFUNCTION * blendFunction);
+HBITMAP GDIPlus_LoadGlyphImage(char *szFileName);
+
+/* EventArea */
+void EventArea_ConfigureEventArea();
+
+/* ExtraImage */
+void ExtraImage_SetAllExtraIcons(HWND hwndList,HANDLE hContact);
+
+/* ModernSkinButton */
+int ModernSkinButton_AddButton(HWND parent,char * ID,char * CommandService,char * StateDefService,char * HandeService, int Left, int Top, int Right, int Bottom, DWORD AlignedTo,TCHAR * Hint,char * DBkey,char * TypeDef,int MinWidth, int MinHeight);
+int ModernSkinButtonLoadModule();
+int ModernSkinButton_ReposButtons(HWND parent, BYTE draw, RECT * r);
+int ModernSkinButtonUnloadModule(WPARAM,LPARAM);
+
+/* RowHeight */
+int RowHeight_CalcRowHeight(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item);
+
+/* SkinEngine */
+BOOL ske_AlphaBlend(HDC hdcDest,int nXOriginDest,int nYOriginDest,int nWidthDest,int nHeightDest,HDC hdcSrc,int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc,BLENDFUNCTION blendFunction);
+void ske_ApplyTransluency(void);
+int ske_BltBackImage (HWND destHWND, HDC destDC, RECT * BltClientRect);
+HBITMAP ske_CreateDIB32(int cx, int cy);
+HBITMAP ske_CreateDIB32Point(int cx, int cy, void ** bits);
+HRGN ske_CreateOpaqueRgn(BYTE Level, bool Opaque);
+HICON ske_CreateJoinedIcon(HICON hBottom, HICON hTop,BYTE alpha);
+int ske_DrawImageAt(HDC hdc, RECT *rc);
+BOOL ske_DrawIconEx(HDC hdc,int xLeft,int yTop,HICON hIcon,int cxWidth,int cyWidth, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags);
+int ske_DrawNonFramedObjects(BOOL Erase,RECT *r);
+BOOL ske_DrawText(HDC hdc, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format);
+BOOL ske_DrawTextA(HDC hdc, char * lpString, int nCount, RECT * lpRect, UINT format);
+LPSKINOBJECTDESCRIPTOR ske_FindObjectByName(const char * szName, BYTE objType, SKINOBJECTSLIST* Skin);
+HBITMAP ske_GetCurrentWindowImage();
+int ske_GetFullFilename(char * buf, char *file, char * skinfolder,BOOL madeAbsolute);
+int ske_GetSkinFolder(char * szFileName, char * t2);
+BOOL ske_ImageList_DrawEx( HIMAGELIST himl,int i,HDC hdcDst,int x,int y,int dx,int dy,COLORREF rgbBk,COLORREF rgbFg,UINT fStyle);
+HICON ske_ImageList_GetIcon(HIMAGELIST himl, int i, UINT fStyle);
+int ske_JustUpdateWindowImageRect(RECT * rty);
+HBITMAP ske_LoadGlyphImage(char * szFileName);
+HRESULT SkinEngineLoadModule();
+void ske_LoadSkinFromDB(void);
+int ske_LoadSkinFromIniFile(TCHAR*, BOOL);
+TCHAR* ske_ParseText(TCHAR *stzText);
+int ske_PrepeareImageButDontUpdateIt(RECT * r);
+int ske_ReCreateBackImage(BOOL Erase,RECT *w);
+int ske_RedrawCompleteWindow();
+BOOL ske_ResetTextEffect(HDC);
+BOOL ske_SelectTextEffect(HDC hdc, BYTE EffectID, DWORD FirstColor, DWORD SecondColor);
+INT_PTR ske_Service_DrawGlyph(WPARAM wParam,LPARAM lParam);
+BOOL ske_SetRectOpaque(HDC memdc,RECT *fr, BOOL force = FALSE );
+BOOL ske_SetRgnOpaque(HDC memdc,HRGN hrgn, BOOL force = FALSE );
+BOOL ske_TextOut(HDC hdc, int x, int y, LPCTSTR lpString, int nCount);
+BOOL ske_TextOutA(HDC hdc, int x, int y, char * lpString, int nCount);
+int ske_UnloadGlyphImage(HBITMAP hbmp);
+int SkinEngineUnloadModule();
+int ske_UpdateWindowImage();
+int ske_UpdateWindowImageRect(RECT * lpRect);
+int ske_ValidateFrameImageProc(RECT * r);
+
+/* CLUIFrames.c PROXIED */
+
+int CLUIFrames_ActivateSubContainers(BOOL wParam);
+int CLUIFrames_OnClistResize_mod(WPARAM wParam,LPARAM lParam);
+int CLUIFrames_OnMoving( HWND, RECT * );
+int CLUIFrames_OnShowHide( HWND hwnd, int mode );
+int CLUIFrames_SetLayeredMode( BOOL fLayeredMode, HWND hwnd );
+int CLUIFrames_SetParentForContainers( HWND parent );
+int CLUIFramesOnClistResize(WPARAM wParam,LPARAM lParam);
+
+FRAMEWND * FindFrameByItsHWND(HWND FrameHwnd); //cluiframes.c
+
+//int callProxied_DrawTitleBar(HDC hdcMem2,RECT * rect,int Frameid);
+int DrawTitleBar(HDC hdcMem2,RECT * rect,int Frameid);
+
+int FindFrameID(HWND FrameHwnd);
+int SetAlpha(BYTE Alpha);
+
+
+/* others TODO: move above */
+int Docking_ProcessWindowMessage(WPARAM wParam,LPARAM lParam);
+void DrawBackGround(HWND hwnd,HDC mhdc, HBITMAP hBmpBackground, COLORREF bkColour, DWORD backgroundBmpUse );
+HRESULT BackgroundsLoadModule();
+int BackgroundsUnloadModule();
+BOOL wildcmp(const char * name, const char * mask, BYTE option); //mod_skin_selector.c
+BOOL wildcmpi(char * name, char * mask); //mod_skin_selector.c
+BOOL wildcmpi(WCHAR* name, WCHAR* mask); //mod_skin_selector.c
+INT_PTR CALLBACK DlgSkinEditorOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); //SkinEditor.c
+INT_PTR CALLBACK DlgTmplEditorOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); //RowTemplate.c
+BOOL FindMenuHanleByGlobalID(HMENU hMenu, int globalID, struct _MenuItemHandles * dat); //GenMenu.c
+BOOL MatchMask(char * name, char * mask); //mod_skin_selector.c
+char* GetContactCachedProtocol(HANDLE hContact); //clistsettings.c
+char* GetParamN(char * string, char * buf, int buflen, BYTE paramN, char Delim, BOOL SkipSpaces); //mod_skin_selector.c
+DWORD CompareContacts2_getLMTime(HANDLE u); //contact.c
+DWORD mod_CalcHash(const char * a); //mod_skin_selector.c
+HICON cliGetIconFromStatusMode(HANDLE hContact, const char *szProto,int status); //clistmod.c
+HICON GetMainStatusOverlay(int STATUS); //clc.c
+int __fastcall CLVM_GetContactHiddenStatus(HANDLE hContact, char *szStatus, struct ClcData *dat); //clcitems.c
+int BgStatusBarChange(WPARAM wParam,LPARAM lParam); //clcopts.c
+int ClcDoProtoAck(HANDLE wParam,ACKDATA * ack); //clc.c
+int ModernSkinButtonDeleteAll(); //modernbutton.c
+int GetAverageMode( void ); //clisttray.c
+int GetContactCachedStatus(HANDLE hContact); //clistsettings.c
+INT_PTR GetContactIcon(WPARAM wParam,LPARAM lParam); //clistmod.c
+int GetContactIconC(pdisplayNameCacheEntry cacheEntry); //clistmod.c
+int GetContactIndex(struct ClcGroup *group,struct ClcContact *contact); //clcidents.c
+int GetStatusForContact(HANDLE hContact,char *szProto); //clistsettings.c
+int InitCustomMenus(void); //clistmenus.c
+int InitFramesMenus(void); //framesmenus.c
+int LoadMoveToGroup(); //movetogroup.c
+int LoadPositionsFromDB(BYTE * OrderPos); //clistopts.c
+int LoadStatusBarData(); //modern_statusbar.c
+int MenuModulesLoaded(WPARAM wParam,LPARAM lParam); //clistmenu.c
+int MenuModulesShutdown(WPARAM wParam,LPARAM lParam); //clistmenu.c
+int MenuProcessCommand(WPARAM wParam,LPARAM lParam); //clistmenu.c
+int ModifyMenuItemProxy(WPARAM wParam,LPARAM lParam); //framesmenu.c
+int OnFrameTitleBarBackgroundChange(WPARAM wParam,LPARAM lParam); //cluiframes.c
+int ProcessCommandProxy(WPARAM wParam,LPARAM lParam); //framesmenu.c
+int QueueAllFramesUpdating (BYTE); //cluiframes.c
+int RecursiveDeleteMenu(HMENU hMenu); //clistmenus.c
+int ModernSkinButtonRedrawAll(HDC hdc); //modern_button.c
+int RegisterButtonByParce(char * ObjectName, char * Params); //mod_skin_selector.c
+int RestoreAllContactData(struct ClcData *dat); //cache_funcs.c
+
+int SkinSelector_DeleteMask(MODERNMASK * mm); //mod_skin_selector.c
+int StoreAllContactData(struct ClcData *dat); //cache_func.c
+INT_PTR ToggleHideOffline(WPARAM wParam,LPARAM lParam); //contact.c
+INT_PTR ToggleGroups(WPARAM wParam,LPARAM lParam); //contact.c
+INT_PTR SetUseGroups(WPARAM wParam,LPARAM lParam); //contact.c
+INT_PTR ToggleSounds(WPARAM wParam,LPARAM lParam); //contact.c
+int UnitFramesMenu(); //framesmenu.c
+void ClcOptionsChanged(); //clc.c
+void Docking_GetMonitorRectFromWindow(HWND hWnd,RECT *rc); //Docking.c
+void DrawAvatarImageWithGDIp(HDC hDestDC,int x, int y, DWORD width, DWORD height, HBITMAP hbmp, int x1, int y1, DWORD width1, DWORD height1,DWORD flag,BYTE alpha); //gdiplus.cpp
+void FreeRowCell(); //RowHeight
+void InitGdiPlus(); //gdiplus.cpp
+void InitTray(); //clisttray.c
+void InvalidateDNCEbyPointer(HANDLE hContact,pdisplayNameCacheEntry pdnce,int SettingType); //clistsettings.c
+void ReAssignExtraIcons(); //extraimage.c
+void ShutdownGdiPlus(); //gdiplus.cpp
+void TextOutWithGDIp(HDC hDestDC, int x, int y, LPCTSTR lpString, int nCount); //gdiplus.cpp
+void UninitCustomMenus(); //clistmenus.c
+void UnloadAvatarOverlayIcon(); //clc.c
+void UnLoadContactListModule(); //clistmod.c
+void UpdateAllAvatars(struct ClcData *dat); //cache_func.c
+ //cluiframes.c
+void gtaRenewText(HANDLE hContact);
+int ExtraImage_ExtraIDToColumnNum(int extra);
+int ExtraImage_ColumnNumToExtraID(int column);
+
+int LoadSkinButtonModule();
+void UninitSkinHotKeys();
+void GetDefaultFontSetting(int i,LOGFONTA *lf,COLORREF *colour);
+int CLUI_OnSkinLoad(WPARAM wParam, LPARAM lParam);
+HRESULT CluiLoadModule();
+HRESULT PreLoadContactListModule();
+HRESULT ClcLoadModule();
+HRESULT ToolbarLoadModule();
+HRESULT ToolbarButtonLoadModule();
+void CustomizeButton(HWND);
+
+// INTERFACES
+
+void cliCheckCacheItem(pdisplayNameCacheEntry pdnce);
+void cliFreeCacheItem( pdisplayNameCacheEntry p );
+void cliRebuildEntireList(HWND hwnd,struct ClcData *dat);
+void cliRecalcScrollBar(HWND hwnd,struct ClcData *dat);
+void CLUI_cliOnCreateClc(void);
+int cli_AddItemToGroup(struct ClcGroup *group, int iAboveItem);
+int cli_AddInfoItemToGroup(struct ClcGroup *group,int flags,const TCHAR *pszText);
+int cliGetGroupContentsCount(struct ClcGroup *group, int visibleOnly);
+int cliFindRowByText(HWND hwnd, struct ClcData *dat, const TCHAR *text, int prefixOk);
+int cliGetRowsPriorTo(struct ClcGroup *group,struct ClcGroup *subgroup,int contactIndex);
+int cli_IconFromStatusMode(const char *szProto,int nStatus, HANDLE hContact);
+int cli_RemoveEvent(HANDLE hContact, HANDLE hDbEvent);
+void cli_AddContactToTree(HWND hwnd,struct ClcData *dat,HANDLE hContact,int updateTotalCount,int checkHideOffline);
+void cli_DeleteItemFromTree(HWND hwnd, HANDLE hItem);
+void cli_FreeContact( struct ClcContact* );
+void cli_FreeGroup( struct ClcGroup* );
+char* cli_GetGroupCountsText(struct ClcData *dat, struct ClcContact *contact);
+void cli_ChangeContactIcon(HANDLE hContact,int iIcon,int add);
+LRESULT cli_ProcessExternalMessages(HWND hwnd,struct ClcData *dat,UINT msg,WPARAM wParam,LPARAM lParam);
+struct CListEvent* cliCreateEvent( void );
+struct CListEvent* cli_AddEvent(CLISTEVENT *cle);
+LRESULT CALLBACK cli_ContactListControlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+int cliShowHide(WPARAM wParam,LPARAM lParam);
+BOOL CLUI__cliInvalidateRect(HWND hWnd, CONST RECT* lpRect,BOOL bErase );
+int cliCompareContacts(const struct ClcContact *contact1,const struct ClcContact *contact2);
+int cliFindItem(HWND hwnd,struct ClcData *dat,HANDLE hItem,struct ClcContact **contact,struct ClcGroup **subgroup,int *isVisible);
+void cliTrayIconUpdateBase(const char *szChangedProto);
+void cliCluiProtocolStatusChanged(int status,const char * proto);
+HMENU cliBuildGroupPopupMenu(struct ClcGroup *group);
+void cliInvalidateDisplayNameCacheEntry(HANDLE hContact);
+void cliCheckCacheItem(pdisplayNameCacheEntry pdnce);
+void cli_SaveStateAndRebuildList(HWND hwnd, struct ClcData *dat);
+void CLUI_cli_LoadCluiGlobalOpts(void);
+INT_PTR cli_TrayIconProcessMessage(WPARAM wParam,LPARAM lParam);
+BOOL CLUI__cliInvalidateRect(HWND hWnd, CONST RECT* lpRect,BOOL bErase );
+
+struct ClcContact* cliCreateClcContact( void );
+ClcCacheEntryBase* cliCreateCacheItem(HANDLE hContact);
+ClcCacheEntryBase* cliGetCacheEntry(HANDLE hContact);
+
+// FUNCTION POINTERS
+extern BOOL (WINAPI *g_proc_UpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD);
+extern BOOL (WINAPI *g_proc_SetLayeredWindowAttributesNew)(HWND,COLORREF,BYTE,DWORD);
+
+#define WM_DWMCOMPOSITIONCHANGED 0x031E
+
+#define DWM_BB_ENABLE 0x00000001
+#define DWM_BB_BLURREGION 0x00000002
+#define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004
+struct DWM_BLURBEHIND
+{
+ DWORD dwFlags;
+ BOOL fEnable;
+ HRGN hRgnBlur;
+ BOOL fTransitionOnMaximized;
+};
+extern HRESULT (WINAPI *g_proc_DWMEnableBlurBehindWindow)(HWND hWnd, DWM_BLURBEHIND *pBlurBehind);
+
+extern tPaintCallbackProc CLCPaint_PaintCallbackProc(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData);
+extern BOOL (WINAPI *MySetProcessWorkingSetSize)(HANDLE,SIZE_T,SIZE_T);
+
+/* SkinEngine.c */
+
+
+BYTE SkinDBGetContactSettingByte(HANDLE hContact, const char* szSection, const char*szKey, BYTE bDefault);
+
+extern OVERLAYICONINFO g_pAvatarOverlayIcons[ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE + 1];
+extern OVERLAYICONINFO g_pStatusOverlayIcons[ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE + 1];
+
+
+#endif
diff --git a/plugins/Clist_modern/src/hdr/modern_defsettings.h b/plugins/Clist_modern/src/hdr/modern_defsettings.h
new file mode 100644
index 0000000000..c84d99840c
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_defsettings.h
@@ -0,0 +1,284 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2007 Artem Shpynov
+Copyright 2000-2008 Miranda ICQ/IM project,
+
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/////////////////////////////////////////////////////////////////////////
+/// This file contains default settings value predefinitions
+//////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#undef CLCDEFAULT_GROUPINDENT
+#undef CLCDEFAULT_SHOWIDLE
+#undef CLCDEFAULT_TEXTCOLOUR
+#undef CLCDEFAULT_SELBKCOLOUR
+#undef SETTING_ONTOP_DEFAULT
+#undef SETTING_TRAY1CLICK_DEFAULT
+
+#define SETTING_ENABLESKINEDITOR_DEFAULT 0 //"ModernData", "EnableSkinEditor"
+#define SETTING_TOOLWINDOW_DEFAULT 1 //"CList","ToolWindow"
+#define SETTING_ONTOP_DEFAULT 0 //"CList","OnTop"
+#define SETTING_MIN2TRAY_DEFAULT 1 //"CList","Min2Tray"
+#define SETTING_TRAY1CLICK_DEFAULT 1 //"CList","Tray1Click"
+#define SETTING_HIDEOFFLINE_DEFAULT 0 //"CList", "HideOffline"
+#define SETTING_HIDEEMPTYGROUPS_DEFAULT 0 //"CList","HideEmptyGroups"
+#define SETTING_USEGROUPS_DEFAULT 1 //"CList","UseGroups"
+#define SETTING_PLACEOFFLINETOROOT_DEFAULT 0 //"CList","PlaceOfflineToRoot"
+#define SETTING_ALWAYSPRIMARY_DEFAULT 0 //! "CList","AlwaysPrimary"
+#define SETTING_DISABLETRAYFLASH_DEFAULT 0 //! "CList","DisableTrayFlash"
+#define SETTING_ICONFLASHTIME_DEFAULT 550 //! "CList","IconFlashTime"
+#define SETTING_THINBORDER_DEFAULT 0 //! "CList","ThinBorder"
+#define SETTING_NOBORDER_DEFAULT 0 //! "CList","NoBorder"
+#define SETTING_WINDOWSHADOW_DEFAULT 0 //! "CList","WindowShadow"
+#define SETTING_ONDESKTOP_DEFAULT 0 //! "CList","OnDesktop"
+#define SETTING_DISABLEWORKINGSET_DEFAULT 1 //! "CList","DisableWorkingSet"
+#define SETTING_NOICONBLINF_DEFAULT 0 //! "CList","NoIconBlink"
+#define SETTING_ALWAYSVISICON_DEFAULT 0 //! "CList","AlwaysShowAlwaysVisIcon"
+
+#define SETTING_SHOWMAINMENU_DEFAULT 1 //"CLUI","ShowMainMenu"
+#define SETTING_SHOWCAPTION_DEFAULT 1 //"CLUI","ShowCaption"
+#define SETTING_CLIENTDRAG_DEFAULT 1 //"CLUI","ClientAreaDrag"
+#define SETTING_SHOWSBAR_DEFAULT 1 //! "CLUI","ShowSBar"
+#define SETTING_SBARPERPROTO_DEFAULT 0 //! "CLUI","SBarPerProto"
+#define SETTING_USECONNECTINGICON_DEFAULT 1 //! "CLUI","UseConnectingIcon"
+#define SETTING_SHOWXSTATUS_DEFAULT 6 //! "CLUI","ShowXStatus"
+#define SETTING_SHOWUNREADEMAILS_DEFAULT 0 //! "CLUI","ShowUnreadEmails"
+#define SETTING_SBARSHOW_DEFAULT 3 //! "CLUI","SBarShow"
+#define SETTING_SBARACCOUNTISCUSTOM_DEFAULT 0 //! "CLUI","AccountIsCustom"
+#define SETTING_SBARHIDEACCOUNT_DEFAULT 0 //! "CLUI","HideAccount"
+#define SETTING_SBARRIGHTCLK_DEFAULT 0 //! "CLUI","SBarRightClk"
+#define SETTING_EQUALSECTIONS_DEFAULT 0 //! "CLUI","EqualSections"
+#define SETTING_LEFTOFFSET_DEFAULT 0 //! "CLUI","LeftOffset"
+#define SETTING_RIGHTOFFSET_DEFAULT 0 //! "CLUI","RightOffset
+#define SETTING_TOPOFFSET_DEFAULT 0 //! "CLUI","TopOffset"
+#define SETTING_BOTTOMOFFSET_DEFAULT 0 //! "CLUI","BottomOffset
+#define SETTING_SPACEBETWEEN_DEFAULT 0 //! "CLUI","SpaceBetween"
+#define SETTING_ALIGN_DEFAULT 0 //! "CLUI","Align"
+#define SETTING_VALIGN_DEFAULT 1 //! "CLUI","VAlign"
+#define SETTING_PADDINGLEFT_DEFAULT 0 //! "CLUI","PaddingLeft_*"
+#define SETTING_PADDINGRIGHT_DEFAULT 0 //! "CLUI","PaddingRight_*"
+#define SETTING_DRAGTOSCROLL_DEFAULT 0 //! "CLUI","DragToScroll"
+#define SETTING_AUTOSIZE_DEFAULT 0 //! "CLUI","AutoSize"
+#define SETTING_LOCKSIZE_DEFAULT 0 //! "CLUI","LockSize"
+#define SETTING_MINHEIGTH_DEFAULT 0 //! "CLUI","MinHeight"
+#define SETTING_MINWIDTH_DEFAULT 18 //! "CLUI","MinWidth"
+#define SETTING_MAXSIZEHEIGHT_DEFAULT 75 //! "CLUI","MaxSizeHeight"
+#define SETTING_MINSIZEHEIGHT_DEFAULT 10 //! "CLUI","MinSizeHeight"
+#define SETTING_AUTOSIZEUPWARD_DEFAULT 0 //! "CLUI","AutoSizeUpward"
+#define SETTING_SNAPTOEDGES_DEFAULT 1 //! "CLUI","SnapToEdges"
+#define SETTING_DOCKTOSIDES_DEFAULT 1 //! "CLUI","DockToSides",
+
+#define SETTING_PROTOSPERLINE_DEFAULT 0 //! "CLUI","StatusBarProtosPerLine"
+#define SETTING_TEXTEFFECTID_DEFAULT 0xFF //! "StatusBar","TextEffectID"
+#define SETTING_TEXTEFFECTCOLOR1_DEFAULT 0 //! "StatusBar","TextEffectColor1"
+#define SETTING_TEXTEFFECTCOLOR2_DEFAULT 0 //! "StatusBar","TextEffectColor2"
+#define SETTING_SBHILIGHTMODE_DEFAULT 0 //! "StatusBar","HiLightMode"
+#define SETTING_HIDETOOLTIPTIME_DEFAULT 5000 //! "CLUIFrames","HideToolTipTime"
+
+#define SETTING_EXTRA_ICON_EMAIL_DEFAULT 0 //!
+#define SETTING_EXTRA_ICON_PROTO_DEFAULT 0 //!
+#define SETTING_EXTRA_ICON_SMS_DEFAULT 0 //!
+#define SETTING_EXTRA_ICON_ADV1_DEFAULT 1 //!
+#define SETTING_EXTRA_ICON_ADV2_DEFAULT 1 //!
+#define SETTING_EXTRA_ICON_WEB_DEFAULT 0 //!
+#define SETTING_EXTRA_ICON_CLIENT_DEFAULT 1 //!
+#define SETTING_EXTRA_ICON_VISMODE_DEFAULT 1 //!
+#define SETTING_EXTRA_ICON_ADV3_DEFAULT 1 //!
+#define SETTING_EXTRA_ICON_ADV4_DEFAULT 1 //!
+
+#define SETTING_EXTRACOLUMNSPACE_DEFAULT 18 //! "CLUI","ExtraColumnSpace"
+
+#define SETTING_HIDEBEHIND_DEFAULT 0 //! "ModernData","HideBehind" //(0-none, 1-leftedge, 2-rightedge)
+#define SETTING_BEHINDEDGE_DEFAULT 0 //! "ModernData", "BehindEdge"
+#define SETTING_SHOWDELAY_DEFAULT 3 //! "ModernData","ShowDelay"
+#define SETTING_HIDEDELAY_DEFAULT 3 //! "ModernData","HideDelay"
+#define SETTING_HIDEBEHINDBORDERSIZE_DEFAULT 0 //! "ModernData","HideBehindBorderSize"
+#define SETTING_AEROGLASS_DEFAULT 1 //! "ModernData","AeroGlass"
+
+#define SETTING_ROUNDCORNERS_DEFAULT 0 //! "CLC","RoundCorners"
+#define SETTING_GAPFRAMES_DEFAULT 1 //! "CLUIFrames","GapBetweenFrames"
+#define SETTING_GAPTITLEBAR_DEFAULT 1 //! "CLUIFrames","GapBetweenTitleBar"
+#define SETTING_LEFTCLIENTMARIGN_DEFAULT 0 //! "CLUI","LeftClientMargin"
+#define SETTING_RIGHTCLIENTMARIGN_DEFAULT 0 //! "CLUI","RightClientMargin"
+#define SETTING_TOPCLIENTMARIGN_DEFAULT 0 //! "CLUI","TopClientMargin"
+#define SETTING_BOTTOMCLIENTMARIGN_DEFAULT 0 //! "CLUI","BottomClientMargin"
+#define SETTING_KEYCOLOR_DEFAULT RGB(255,0,255) //! "ModernSettings","KeyColor"
+#define SETTING_LINEUNDERMENU_DEFAULT 0 //! "CLUI","LineUnderMenu"
+#define SETTING_SHOWONSTART_DEFAULT 0 //! "CList","ShowOnStart"
+#define SETTING_AUTOSIZE_DEFAULT 0 //! "CLUI","AutoSize"
+
+#define SETTING_INTERNALAWAYMSGREQUEST_DEFAULT 1 //"ModernData","InternalAwayMsgDiscovery"
+#define SETTING_REMOVEAWAYMSGFOROFFLINE_DEFAULT 1 //"ModernData","RemoveAwayMessageForOffline"
+#define SETTING_METAAVOIDDBLCLICK_DEFAULT 1 //"CLC","MetaDoubleClick"
+#define SETTING_METAIGNOREEMPTYEXTRA_DEFAULT 1 //"CLC","MetaIgnoreEmptyExtra"
+#define SETTING_METAHIDEEXTRA_DEFAULT 0 //"CLC","MetaHideExtra"
+#define SETTING_METAEXPANDING_DEFAULT 1 //"CLC","MetaExpanding"
+#define SETTING_METAAVOIDDBLCLICK_DEFAULT 1 //"CLC","MetaDoubleClick"
+#define SETTING_METAHIDEOFFLINESUB_DEFAULT 1 //"CLC","MetaHideOfflineSub"
+#define SETTING_USEMETAICON_DEFAULT 0 //"CLC","Meta"
+#define SETTING_DRAWOVERLAYEDSTATUS_DEFAULT 3 //todo replace by contstants
+
+
+#define SETTING_SORTBY1_DEFAULT SORTBY_RATE //"CList","SortBy1"
+#define SETTING_SORTBY2_DEFAULT SORTBY_NAME //"CList","SortBy2"
+#define SETTING_SORTBY3_DEFAULT SORTBY_STATUS //"CList","SortBy3"
+
+#define SETTING_PLACEOOFLINETOROOT_DEFAULT 0 //"CList","PlaceOfflineToRoot"
+#define SETTING_NOOFFLINEBOTTOM_DEFAULT 0 //"CList","NoOfflineBottom"
+#define SETTING_HIDEOFFLINEATROOT_DEFAULT 0 //"CLC","HideOfflineRoot"
+#define SETTING_HILIGHTMODE_DEFAULT 0 //todo replace by constant //"CLC","HiLightMode"
+
+#define SETTING_DISABLESKIN_DEFAULT 0 //"ModernData","DisableEngine"
+#define SETTING_ENABLELAYERING_DEFAULT 1 //! "ModernData","EnableLayering"
+#define SETTING_COMPACTMODE_DEFAULT 0 //"CLC","CompactMode"
+
+#define SETTING_EVENTAREAMODE_DEFAULT 1 //autohide todo replace by const //"CLUI","EventArea"
+#define SETTING_SHOWEVENTAREAFRAME_DEFAULT 1 //"CLUI","ShowEventArea"
+
+#define SETTING_TRAYOPTION_DEFAULT 15 //show combined icon
+#define SETTING_FADEIN_DEFAULT 0 //"CLUI","FadeInOut"
+
+//////////////////////////////////////////////////////////////////////////
+// ROW SETTINGS
+#define SETTING_ROWBORDER_DEFAULT 1 //"CList","RowBorder"
+#define SETTING_ROW_ADVANCEDLAYOUT_DEFAULT 0 //"ModernData","UseAdvancedRowLayout"
+#define SETTING_ROW_ROWBORDER_DEFAULT 1 //"CList","RowBorder"
+#define SETTING_VARIABLEROWHEIGHT_DEFAULT 1 //"CList","VariableRowHeight"
+#define SETTING_ALIGNLEFTTOLEFT_DEFAULT 0 //"CList","AlignLeftItemsToLeft"
+#define SETTING_ALIGNRIGHTORIGHT_DEFAULT 1 //"CList","AlignRightItemsToRight"
+#define SETTING_HIDEGROUPSICON_DEFAULT 0 //"CList","HideGroupsIcon"
+#define SETTING_ALIGNGROPCAPTION_DEFAULT 0 //left todo replace by const //"CList","AlignGroupCaptions"
+#define SETTINS_ROWITEMORDER_DEFAULT {ITEM_AVATAR, ITEM_ICON, ITEM_TEXT, ITEM_EXTRA_ICONS, ITEM_CONTACT_TIME}
+
+#define SETTINGS_SHOWAVATARS_DEFAULT 1 //"CList","AvatarsShow"
+#define SETTINGS_AVATARDRAWBORDER_DEFAULT 0 //"CList","AvatarsDrawBorders"
+#define SETTINGS_AVATARBORDERCOLOR_DEFAULT RGB(0,0,0) //"CList","AvatarsBorderColor"
+#define SETTINGS_AVATARROUNDCORNERS_DEFAULT 0 //"CList","AvatarsRoundCorners"
+#define SETTINGS_AVATARUSECUTOMCORNERSIZE_DEFAULT 0 //"CList","AvatarsUseCustomCornerSize"
+#define SETTINGS_AVATARCORNERSIZE_DEFAULT 4 //"CList","AvatarsCustomCornerSize"
+#define SETTINGS_AVATARIGNORESIZEFORROW_DEFAULT 0 //"CList","AvatarsIgnoreSizeForRow"
+#define SETTINGS_AVATARDRAWOVERLAY_DEFAULT 0 //"CList","AvatarsDrawOverlay"
+#define SETTINGS_AVATAROVERLAYTYPE_DEFAULT SETTING_AVATAR_OVERLAY_TYPE_NORMAL
+#define SETTING_AVATARHEIGHT_DEFAULT 24 //"CList","AvatarsSize"
+#define SETTING_AVATARWIDTH_DEFAULT 24 //"CList","AvatarsWidth"
+#define SETTINGS_AVATARINSEPARATE_DEFAULT 0 //"CList","AvatarsInSeparateWnd",
+
+
+
+#define SETTING_HIDEICONONAVATAR_DEFAULT 0 //"CList","IconHideOnAvatar"
+#define SETTING_ICONONAVATARPLACE_DEFAULT 0 //"CList","IconDrawOnAvatarSpace"
+#define SETTING_ICONIGNORESIZE_DEFAULT 0 //"CList","IconIgnoreSizeForRownHeight"
+#define SETTING_SHOWTIME_DEFAULT 0 //"CList","ContactTimeShow"
+#define SETTING_SHOWTIMEIFDIFF_DEFAULT 1 //"CList","ContactTimeShowOnlyIfDifferent"
+
+#define SETTING_TEXT_RTL_DEFAULT 0 //"CList","TextRTL"
+#define SETTING_TEXT_RIGHTALIGN_DEFAULT 0 //"CList","TextAlignToRight"
+#define SETTING_TEXT_SMILEY_DEFAULT 1 //"CList","TextReplaceSmileys"
+#define SETTING_TEXT_RESIZESMILEY_DEFAULT 1 //"CList","TextResizeSmileys"
+#define SETTING_TEXT_PROTOSMILEY_DEFAULT 1 //"CList","TextUseProtocolSmileys"
+#define SETTING_TEXT_IGNORESIZE_DEFAULT 0 //"CList","TextIgnoreSizeForRownHeight"
+
+#define SETTING_FIRSTLINE_SMILEYS_DEFAULT 1 //"CList","FirstLineDrawSmileys"
+#define SETTING_FIRSTLINE_APPENDNICK_DEFAULT 0 //"CList","FirstLineAppendNick"
+#define SETTING_FIRSTLINE_TRIMTEXT_DEFAULT 1 //"CList","TrimText"
+
+#define SETTING_SECONDLINE_SHOW_DEFAULT 1 //"CList","SecondLineShow"
+#define SETTING_SECONDLINE_TOPSPACE_DEFAULT 2 //"CList","SecondLineTopSpace"
+#define SETTING_SECONDLINE_SMILEYS_DEFAULT 1 //"CList","SecondLineDrawSmileys"
+#define SETTING_SECONDLINE_TYPE_DEFAULT TEXT_STATUS_MESSAGE //"CList","SecondLineType"
+#define SETTING_SECONDLINE_XSTATUS_DEFAULT 1 //"CList","SecondLineXStatusHasPriority"
+#define SETTING_SECONDLINE_XSTATUSNAMETEXT_DEFAULT 0 //"CList","SecondLineUseNameAndMessageForXStatus"
+#define SETTING_SECONDLINE_STATUSIFNOAWAY_DEFAULT 1 //"CList","SecondLineShowStatusIfNoAway"
+#define SETTING_SECONDLINE_LISTENINGIFNOAWAY_DEFAULT 1 //"CList","SecondLineShowListeningIfNoAway"
+
+#define SETTING_THIRDLINE_SHOW_DEFAULT 0 //"CList","ThirdLineShow"
+#define SETTING_THIRDLINE_TOPSPACE_DEFAULT 2 //"CList","ThirdLineTopSpace"
+#define SETTING_THIRDLINE_SMILEYS_DEFAULT 0 //"CList","ThirdLineDrawSmileys"
+#define SETTING_THIRDLINE_TYPE_DEFAULT TEXT_STATUS_MESSAGE //"CList","ThirdLineType"
+#define SETTING_THIRDLINE_XSTATUS_DEFAULT 1 //"ThirdLineXStatusHasPriority"
+#define SETTING_THIRDLINE_XSTATUSNAMETEXT_DEFAULT 0 //"ThirdLineUseNameAndMessageForXStatus"
+#define SETTING_THIRDLINE_STATUSIFNOAWAY_DEFAULT 0 //"CList","ThirdLineShowStatusIfNoAway"
+#define SETTING_THIRDLINE_LISTENINGIFNOAWAY_DEFAULT 0 //"ThirdLineShowListeningIfNoAway"
+
+
+#define SETTING_TRANSPARENT_DEFAULT 0 //"CList","Transparent"
+#define SETTING_AUTOALPHA_DEFAULT 150 //"CList","AutoAlpha"
+#define SETTING_CONFIRMDELETE_DEFAULT 1 //"CList","ConfirmDelete"
+#define SETTING_AUTOHIDE_DEFAULT 0 //"CList","AutoHide"
+#define SETTING_HIDETIME_DEFAULT 30 //"CList","HideTime"
+#define SETTING_CYCLETIME_DEFAULT 4 //"CList","CycleTime"
+#define SETTING_TRAYICON_DEFAULT SETTING_TRAYICON_SINGLE //"CList","TrayIcon"
+#define SETTING_ALWAYSSTATUS_DEFAULT 0 //"CList","AlwaysStatus"
+#define SETTING_ALWAYSMULTI_DEFAULT 0 //"CList","AlwaysMulti"
+
+#define SETTING_BLENDINACTIVESTATE_DEFAULT 0 //"CLC","BlendInActiveState"
+#define SETTING_BLEND25_DEFAULT 1 //NOT USED
+
+#define CLCDEFAULT_EXSTYLE (CLS_EX_EDITLABELS|CLS_EX_TRACKSELECT|CLS_EX_SHOWGROUPCOUNTS|CLS_EX_HIDECOUNTSWHENEMPTY|CLS_EX_TRACKSELECT|CLS_EX_NOTRANSLUCENTSEL) //plus CLS_EX_NOSMOOTHSCROLL is got from the system
+#define CLCDEFAULT_SCROLLTIME 150 //"CLC","ScrollTime"
+#define CLCDEFAULT_GROUPINDENT 20 //"CLC","SubIndent"
+#define CLCDEFAULT_BKCOLOUR GetSysColor(COLOR_3DFACE)
+#define CLCDEFAULT_USEBITMAP 0 //"StatusBar","UseBitmap"
+#define CLCDEFAULT_BKBMPUSE CLB_STRETCH //"StatusBar","BkBmpUse"
+#define CLCDEFAULT_OFFLINEMODES MODEF_OFFLINE //"CLC","OfflineModes"
+#define CLCDEFAULT_GREYOUTFLAGS 0 //"CLC","GreyoutFlags"
+#define CLCDEFAULT_FULLGREYOUTFLAGS (MODEF_OFFLINE|PF2_INVISIBLE|GREYF_UNFOCUS)
+#define CLCDEFAULT_SELBKCOLOUR RGB(100,100,100) //GetSysColor(COLOR_HIGHLIGHT)
+
+
+#define CLCDEFAULT_TEXTCOLOUR (g_CluiData.fDisableSkinEngine?GetSysColor(COLOR_WINDOWTEXT):RGB(0,0,0))
+#define CLCDEFAULT_MODERN_SELTEXTCOLOUR (g_CluiData.fDisableSkinEngine?GetSysColor(COLOR_HIGHLIGHTTEXT):RGB(0,0,128))
+#define CLCDEFAULT_MODERN_HOTTEXTCOLOUR (g_CluiData.fDisableSkinEngine?(IsWinVer98Plus()?CLCDEFAULT_MODERN_SELTEXTCOLOUR:GetSysColor(COLOR_HOTLIGHT)):RGB(0,0,255))
+#define CLCDEFAULT_MODERN_QUICKSEARCHCOLOUR RGB(255,255,0)
+#define CLCDEFAULT_LEFTMARGIN 0 //"CLC","LeftMargin"
+#define CLCDEFAULT_RIGHTMARGIN 2 //"CLC","RightMargin"
+#define CLCDEFAULT_GAMMACORRECT 1 //"CLC","GammaCorrect"
+#define CLCDEFAULT_SHOWIDLE 1 //"CLC","ShowIdle"
+#define CLCDEFAULT_NOVSCROLL 0 //"CLC","NoVScrollBar"
+#define CLCDEFAULT_INFOTIPTIME 750 //"! "CLC","InfoTipHoverTime"
+#define CLCDEFAULT_COLLICONTOLEFT 0 //"! "FrameTitleBar","AlignCOLLIconToLeft"
+
+#define SKIN_OFFSET_TOP_DEFAULT 0 //! "ModernSkin","SizeMarginOffset_Top"
+#define SKIN_OFFSET_BOTTOM_DEFAULT 0 //! "ModernSkin","SizeMarginOffset_Bottom"
+#define SKIN_OFFSET_LEFT_DEFAULT 0 //! "ModernSkin","SizeMarginOffset_Left"
+#define SKIN_OFFSET_RIGHT_DEFAULT 0 //! "ModernSkin","SizeMarginOffset_Right"
+#define SKIN_SPACEBEFOREGROUP_DEFAULT 0 //! "ModernSkin","SpaceBeforeGroup"
+
+
+
+
+
+
+
+#define SETTINGS_BARBTNWIDTH_DEFAULT 22 //"ModernToolBar", "option_Bar0_BtnWidth"
+#define SETTINGS_BARBTNHEIGHT_DEFAULT 22 //"ModernToolBar", "option_Bar0_BtnHeight"
+#define SETTINGS_BARBTNSPACE_DEFAULT 0 //"ModernToolBar", "option_Bar0_BtnSpace"
+#define SETTINGS_BARAUTOSIZE_DEFAULT 1 //"ModernToolBar", "option_Bar0_Autosize"
+#define SETTINGS_BARMULTILINE_DEFAULT 1 //"ModernToolBar", "option_Bar0_Multiline"
+
+#define SETTING_ENABLESOUNDS_DEFAULT 1 // !"Skin", "UseSound",
+
+
+
+
diff --git a/plugins/Clist_modern/src/hdr/modern_effectenum.h b/plugins/Clist_modern/src/hdr/modern_effectenum.h
new file mode 100644
index 0000000000..e3c5600dc6
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_effectenum.h
@@ -0,0 +1,93 @@
+#pragma once
+
+typedef signed char sbyte;
+typedef struct _MODERNEFFECTMATRIX
+{
+ sbyte matrix[25];
+ BYTE topEffect;
+ BYTE leftEffect;
+ BYTE rightEffect;
+ BYTE bottomEffect;
+ BYTE cycleCount; //low 7 bits
+}MODERNEFFECTMATRIX;
+
+typedef struct _MODERNEFFECT
+{
+ BYTE EffectID;
+ MODERNEFFECTMATRIX EffectMatrix;
+ DWORD EffectColor1;
+ DWORD EffectColor2;
+}MODERNEFFECT;
+
+#ifdef _EFFECTENUM_FULL_H
+ TCHAR * ModernEffectNames[]=
+#else
+ TCHAR * _ModernEffectNames[]=
+#endif
+{
+ _T("Shadow at left"),
+ _T("Shadow at right"),
+ _T("Outline"),
+ _T("Outline smooth"),
+ _T("Smooth bump"),
+ _T("Contour thin"),
+ _T("Contour heavy"),
+};
+
+#ifdef _EFFECTENUM_FULL_H
+MODERNEFFECTMATRIX ModernEffectsEnum[]={
+ { //Shadow at Left
+ { 0, 0, 0, 0, 0,
+ 0, 4, 16, 4, 4,
+ 0, 16, 64, 32, 16,
+ 0, 4, 32, 32, 16,
+ 0, 4, 16, 16, 16 }, 2,2,2,2,1},
+ { //Shadow at Right
+ { 0, 0, 0, 0, 0,
+ 4, 4, 16, 4, 0,
+ 16, 32, 64, 16, 0,
+ 16, 32, 32, 4, 0,
+ 16, 16, 16, 4, 0 }, 2,2,2,2,1},
+ { //Outline
+ { 0, 0, 0, 0, 0,
+ 0, 16, 16, 16, 0,
+ 0, 16, 32, 16, 0,
+ 0, 16, 16, 16, 0,
+ 0, 0, 0, 0, 0 }, 1,1,1,1,1},
+
+ { //Outline smooth
+ { 4, 4, 4, 4, 4,
+ 4, 8, 8, 8, 4,
+ 4, 8, 32, 8, 4,
+ 4, 8, 8, 8, 4,
+ 4, 4, 4, 4, 4 }, 2,2,2,2,1},
+
+ { //Smooth bump
+ { -2, 2, 2, 2, 2,
+ -2, -16, 16, 16, 2,
+ -2, -16, 48, 16, 2,
+ -2, -16,-16, 16, 2,
+ -2, -2, -2, -2, -2 }, 2,2,2,2,1+0x80},
+ { //Contour thin
+ { 0, 0, 0, 0, 0,
+ 0, 48, 64, 48, 0,
+ 0, 64, 64, 64, 0,
+ 0, 48, 64, 48, 0,
+ 0, 0, 0, 0, 0 }, 1,1,1,1,1},
+ { //Contour heavy
+ { 8, 16, 16, 16, 8,
+ 16, 64, 64, 64, 16,
+ 16, 64, 64, 64, 16,
+ 16, 64, 64, 64, 16,
+ 8, 16, 16, 16, 8 }, 2,2,2,2,1},
+
+};
+#endif
+#ifdef _EFFECTENUM_FULL_H
+ #define MAXPREDEFINEDEFFECTS sizeof(ModernEffectNames)/sizeof(ModernEffectNames[0])
+#else
+ #define MAXPREDEFINEDEFFECTS sizeof(_ModernEffectNames)/sizeof(_ModernEffectNames[0])
+ extern TCHAR * ModernEffectNames[];
+#endif
+extern BOOL SkinEngine_ResetTextEffect(HDC);
+extern BOOL SkinEngine_SelectTextEffect(HDC hdc, BYTE EffectID, DWORD FirstColor, DWORD SecondColor); \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_gettextasync.h b/plugins/Clist_modern/src/hdr/modern_gettextasync.h
new file mode 100644
index 0000000000..881e2b738d
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_gettextasync.h
@@ -0,0 +1,5 @@
+#pragma once
+void InitCacheAsync();
+void UninitCacheAsync();
+void gtaRenewText(HANDLE hContact);
+int gtaAddRequest(struct ClcData *dat,struct ClcContact *contact,HANDLE hContact); \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_global_structure.h b/plugins/Clist_modern/src/hdr/modern_global_structure.h
new file mode 100644
index 0000000000..09036459ec
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_global_structure.h
@@ -0,0 +1,92 @@
+#pragma once
+
+#ifndef modern_global_structure_h__
+#define modern_global_structure_h__
+
+typedef struct tagCLUIDATA
+{
+ /************************************
+ ** Global variables **
+ ************************************/
+
+ /* NotifyArea menu */
+ HMENU hMenuNotify;
+ WORD wNextMenuID;
+ int iIconNotify;
+ BOOL bEventAreaEnabled;
+ BOOL bNotifyActive;
+ DWORD dwFlags;
+ TCHAR * szNoEvents;
+ int hIconNotify;
+ HANDLE hUpdateContact;
+
+ /* Contact List View Mode */
+ TCHAR groupFilter[2048];
+ char protoFilter[2048];
+ char varFilter[2048];
+ DWORD lastMsgFilter;
+ char current_viewmode[256], old_viewmode[256];
+ BYTE boldHideOffline;
+ BYTE bOldUseGroups;
+ DWORD statusMaskFilter;
+ DWORD stickyMaskFilter;
+ DWORD filterFlags;
+ DWORD bFilterEffective;
+ BOOL bMetaAvail;
+ DWORD t_now;
+
+ // Modern Global Variables
+ BOOL fDisableSkinEngine;
+ BOOL fOnDesktop;
+ BOOL fSmoothAnimation;
+ BOOL fLayered;
+ BOOL fDocked;
+ BOOL fGDIPlusFail;
+ BOOL fSortNoOfflineBottom;
+ BOOL fAutoSize;
+ BOOL fAeroGlass;
+ HRGN hAeroGlassRgn;
+
+ BOOL mutexPreventDockMoving;
+ BOOL mutexOnEdgeSizing;
+ BOOL mutexPaintLock;
+
+ BYTE bCurrentAlpha;
+ BYTE bSTATE;
+ BYTE bBehindEdgeSettings;
+ BYTE bSortByOrder[3];
+
+ signed char nBehindEdgeState;
+
+ DWORD dwKeyColor;
+
+ HWND hwndEventFrame;
+
+ int LeftClientMargin;
+ int RightClientMargin;
+ int TopClientMargin;
+ int BottomClientMargin;
+
+ BOOL bInternalAwayMsgDiscovery;
+ BOOL bRemoveAwayMessageForOffline;
+
+ //hEventHandles
+
+ HANDLE hEventExtraImageListRebuilding;
+ HANDLE hEventExtraImageApplying;
+ HANDLE hEventExtraClick;
+ HANDLE hEventBkgrChanged;
+ HANDLE hEventPreBuildTrayMenu;
+ HANDLE hEventPreBuildFrameMenu;
+ HANDLE hEventPreBuildGroupMenu;
+ HANDLE hEventPreBuildSubGroupMenu;
+ HANDLE hEventStatusBarShowToolTip;
+ HANDLE hEventStatusBarHideToolTip;
+ HANDLE hEventSkinServicesCreated;
+
+ int nGapBetweenTitlebar;
+} CLUIDATA;
+
+EXTERN_C CLUIDATA g_CluiData;
+
+#endif // modern_global_structure_h__
diff --git a/plugins/Clist_modern/src/hdr/modern_image_array.h b/plugins/Clist_modern/src/hdr/modern_image_array.h
new file mode 100644
index 0000000000..130c51ce95
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_image_array.h
@@ -0,0 +1,104 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Created by Pescuma
+
+*/
+
+#pragma once
+
+#ifndef __IMAGE_ARRAY_H__
+# define __IMAGE_ARRAY_H__
+
+#include <windows.h>
+
+
+typedef struct _IMAGE_ARRAY_DATA_NODE
+{
+ int width;
+ int height;
+}
+IMAGE_ARRAY_DATA_NODE;
+
+typedef struct _IMAGE_ARRAY_DATA
+{
+ // Configuration
+ BOOL width_based;
+ int grow_step;
+ HDC hdc;
+
+ // Img data
+ HBITMAP img;
+ int width;
+ int height;
+ void * lpBits;
+
+ // CS
+ CRITICAL_SECTION cs;
+
+ // Array
+ IMAGE_ARRAY_DATA_NODE *nodes;
+ int nodes_size;
+ int nodes_allocated_size;
+}
+IMAGE_ARRAY_DATA, *LP_IMAGE_ARRAY_DATA;
+
+
+// Initialize data
+void ImageArray_Initialize(LP_IMAGE_ARRAY_DATA iad, BOOL width_based, int grow_step);
+
+// Free data but keep config
+void ImageArray_Clear(LP_IMAGE_ARRAY_DATA iad);
+
+// Free data
+// If keep_bitmap is TRUE, doesn't delete de bitmap and return its handle. Else, return NULL
+HBITMAP ImageArray_Free(LP_IMAGE_ARRAY_DATA iad, BOOL keep_bitmap);
+
+// Add image to the list (return the index of the image or -1 on error)
+// If pos == -1, add to the end of the list
+int ImageArray_AddImage(LP_IMAGE_ARRAY_DATA iad, HBITMAP hBmp, int pos);
+
+// Change an image in the list (return TRUE on success)
+BOOL ImageArray_ChangeImage(LP_IMAGE_ARRAY_DATA iad, HBITMAP hBmp, int pos);
+
+// Remove an image
+BOOL ImageArray_RemoveImage(LP_IMAGE_ARRAY_DATA iad, int pos);
+
+// Draw an image
+BOOL ImageArray_DrawImage(LP_IMAGE_ARRAY_DATA iad, int pos, HDC hdcDest, int nXDest, int nYDest, BYTE Alpha);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif // __IMAGE_ARRAY_H__
diff --git a/plugins/Clist_modern/src/hdr/modern_layered_window_engine.h b/plugins/Clist_modern/src/hdr/modern_layered_window_engine.h
new file mode 100644
index 0000000000..918bfabf37
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_layered_window_engine.h
@@ -0,0 +1,51 @@
+#pragma once
+#include "../m_api/m_skin_eng.h"
+
+// typedef int (/*__stdcall*/ *tPaintCallbackProc)(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgnUpdate, DWORD dFlags, void * CallBackData);
+
+class CLayeredWindowEngine
+{
+private:
+ /*class CLweInfo
+ {
+ HWND hWnd;
+ HRGN hInvalidRgn;
+ };
+ */
+ //typedef std::map<HWND, CLweInfo> WndInfos;
+
+ enum { state_invalid, state_normal };
+
+ //WndInfos m_infos;
+ DWORD m_hValidatorThread;
+ CRITICAL_SECTION m_cs;
+ int m_state;
+ volatile bool m_invalid;
+
+public:
+ CLayeredWindowEngine(void);
+ ~CLayeredWindowEngine(void);
+
+ void _init();
+ void _deinit();
+
+ void lock() { EnterCriticalSection( &m_cs ); }
+ void unlock() { LeaveCriticalSection( &m_cs ); }
+
+ int get_state();
+
+public:
+ static void __cdecl LweValidatorProc();
+
+ void LweValidatorProcWorker();
+
+ void LweValidatorWorker();
+ int LweInvalidateRect( HWND hWnd, const RECT * rect, BOOL bErase );
+ // int LweValidateWindowRect( HWND hWnd, RECT * rect );
+ // int RegisterWindow( HWND hwnd, tPaintCallbackProc pPaintCallBackProc );
+
+};
+
+extern CLayeredWindowEngine _lwe;
+
+#define _InvalidateRect _lwe.LweInvalidateRect \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_log.h b/plugins/Clist_modern/src/hdr/modern_log.h
new file mode 100644
index 0000000000..0696c280bd
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_log.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#ifndef __LOG_H__
+# define __LOG_H__
+
+#ifdef _DEBUG_LOG
+
+void Log(const char *file,int line,const char *fmt,...);
+#define logg() Log(__FILE__,__LINE__,"")
+#define log0(s) Log(__FILE__,__LINE__,s)
+#define log1(s,a) Log(__FILE__,__LINE__,s,a)
+#define log2(s,a,b) Log(__FILE__,__LINE__,s,a,b)
+#define log3(s,a,b,c) Log(__FILE__,__LINE__,s,a,b,c)
+#define log4(s,a,b,c,d) Log(__FILE__,__LINE__,s,a,b,c,d)
+
+#else
+
+#define logg()
+#define log0(s)
+#define log1(s,a)
+#define log2(s,a,b)
+#define log3(s,a,b,c)
+#define log4(s,a,b,c,d)
+
+#endif
+
+#endif // __LOG_H__ \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_popup.h b/plugins/Clist_modern/src/hdr/modern_popup.h
new file mode 100644
index 0000000000..d333ab1e36
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_popup.h
@@ -0,0 +1,48 @@
+/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+#pragma once
+
+#ifndef __POPUP_H__
+# define __POPUP_H__
+
+#include <m_popup.h>
+
+extern BOOL EnablePopups;
+
+
+#define POPUP_TYPE_NORMAL 0
+#define POPUP_TYPE_TEST 1
+#define POPUP_TYPE_ERROR 2
+
+// Show an popup
+void ShowPopup(const char *title, const char *description, int type);
+
+// Show an error popup
+void ShowErrPopup(const char *title, const char *description);
+
+// Show an trace popup
+void ShowTracePopup(const char *text);
+
+
+
+
+
+
+#endif // __POPUP_H__
diff --git a/plugins/Clist_modern/src/hdr/modern_row.h b/plugins/Clist_modern/src/hdr/modern_row.h
new file mode 100644
index 0000000000..47b9582c29
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_row.h
@@ -0,0 +1,86 @@
+#ifndef modern_row_h__
+#define modern_row_h__
+
+#pragma once
+
+
+// Types of cells
+#define TC_TEXT1 1
+#define TC_TEXT2 2
+#define TC_TEXT3 3
+#define TC_STATUS 4
+#define TC_AVATAR 5
+#define TC_EXTRA 6
+#define TC_EXTRA1 7
+#define TC_EXTRA2 8
+#define TC_EXTRA3 9
+#define TC_EXTRA4 10
+#define TC_EXTRA5 11
+#define TC_EXTRA6 12
+#define TC_EXTRA7 13
+#define TC_EXTRA8 14
+#define TC_EXTRA9 15
+#define TC_TIME 16
+#define TC_SPACE 17
+#define TC_FIXED 18
+
+
+#define TC_ELEMENTSCOUNT 18
+
+// Containers
+#define TC_ROOT 50
+#define TC_ROW 51
+#define TC_COL 52
+#define TC_FLOAT 53
+
+// Alignes
+#define TC_LEFT 0
+#define TC_HCENTER 100
+#define TC_RIGHT 101
+
+#define TC_TOP 0
+#define TC_VCENTER 102
+#define TC_BOTTOM 103
+
+// Sizes
+#define TC_WIDTH 104
+#define TC_HEIGHT 105
+
+
+
+// Ñòðóêòóðà, îïèñûâàþùàÿ êîíòåéíåð ýëåìåíòà êîíòàêòà
+//
+typedef struct tagRowCell
+{
+ int cont; // Òèï êîíòåéíåðà - êîíòàêò, ñòîðîêà, ñòîëáåö
+ int type; // Òèï ýëåìåíòà, ñîäåðæàùåãîñÿ â êîíòåéíåðå, åñëè 0 - ïóñòîé êîíòåéíåð
+ int halign; // Ãîðèçîíòàëüíîå âûðàâíèâàíèå âíóòðè êîíòåéíåðà
+ int valign; // Âåðòèêàëüíîå âûðàâíèâàíèå âíóòðè êîíòåéíåðà
+
+ int w; // Øèðèíà ýëåìåíòà êîíòàêòà, äëÿ òåêñòîâûõ ïîëåé èãíîðèðóåòñÿ
+ int h; // Âûñîòà ýëåìåíòà êîòíàêòà
+
+ BOOL sizing; // Ïàðàìåòð, ïîêàçûâàþùèé íàëè÷èå òåêñòîâûõ ïîëåé â äî÷åðíèõ êîíòåéíåðàõ
+ BOOL layer; // Ïàðàìåòð, ïîêàçûâàþùèé, ÷òî êîíòåéíåð îáðàçóåò íîâûé ñëîé
+
+ BOOL hasfixed; // Ïàðàìåòð ïîêàçûâàþùèé ÷òî åñòü âëîæåííûå ôèêñèðîâàííûå ýëåìåíòû
+ BOOL fitwidth; // Ïàðàìåòð óêàçûâàþùèé ÷òî ïîñëåäíèé ýëåìåíò çàïîëíÿåò âñå îñòàâøååñÿ
+ // Ïðîñòðàíñòâî (ðàññòÿãèâàåò ðîäèòåëÿ.îâåðëåé)
+
+ int fixed_width;
+ int full_width;
+
+ RECT r; // Ïðÿìîóãîëüíèê äëÿ ðèñîâàíèÿ ýëåìåíòà
+ struct tagRowCell * next; // Ïîëå ñâÿçè
+ struct tagRowCell * child; // Ïîëå ñâÿçè ñì. ôàéë îïèñàíèÿ
+} ROWCELL, *pROWCELL;
+
+// Ñòðóêòóðà äëÿ äîñòóïà ê êîíòåéíåðàì ýëåìåíòà êîíòàêòà âíóòðè äåðåâà îïèâàíèÿ
+#ifndef _CPPCODE
+ int cppCalculateRowHeight(ROWCELL *RowRoot);
+ void cppCalculateRowItemsPos(ROWCELL *RowRoot, int width);
+ ROWCELL *cppInitModernRow(ROWCELL ** tabAccess);
+ void cppDeleteTree(ROWCELL * RowRoot);
+#endif
+
+#endif // modern_row_h__ \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_rowheight_funcs.h b/plugins/Clist_modern/src/hdr/modern_rowheight_funcs.h
new file mode 100644
index 0000000000..57223cf3c0
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_rowheight_funcs.h
@@ -0,0 +1,70 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Created by Pescuma
+
+*/
+
+#pragma once
+
+#ifndef __ROWHEIGHT_FUNCS_H__
+# define __ROWHEIGHT_FUNCS_H__
+
+#include "modern_clc.h"
+
+#define ROW_SPACE_BEETWEEN_LINES 2
+#define ICON_HEIGHT 16
+#define ICON_WIDTH 16
+
+
+
+BOOL RowHeights_Initialize(struct ClcData *dat);
+void RowHeights_Free(struct ClcData *dat);
+void RowHeights_Clear(struct ClcData *dat);
+
+BOOL RowHeights_Alloc(struct ClcData *dat, int size);
+
+// Calc and store max row height
+int RowHeights_GetMaxRowHeight(struct ClcData *dat, HWND hwnd);
+
+// Calc and store row height
+int RowHeights_GetRowHeight(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item);
+
+// Calc and store row height for all itens in the list
+void RowHeights_CalcRowHeights(struct ClcData *dat, HWND hwnd);
+
+// Calc item top Y (using stored data)
+int cliGetRowTopY(struct ClcData *dat, int item);
+
+// Calc item bottom Y (using stored data)
+int cliGetRowBottomY(struct ClcData *dat, int item);
+
+// Calc total height of rows (using stored data)
+int cliGetRowTotalHeight(struct ClcData *dat);
+
+// Return the line that pos_y is at or -1 (using stored data). Y start at 0
+int cliRowHitTest(struct ClcData *dat, int pos_y);
+
+// Returns the height of the chosen row
+int cliGetRowHeight(struct ClcData *dat, int item);
+
+#endif // __ROWHEIGHT_FUNCS_H__
diff --git a/plugins/Clist_modern/src/hdr/modern_skinengine.h b/plugins/Clist_modern/src/hdr/modern_skinengine.h
new file mode 100644
index 0000000000..a2b365b2ba
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_skinengine.h
@@ -0,0 +1,148 @@
+#pragma once
+
+#ifndef ske_H_INC
+#define ske_H_INC
+
+#include "modern_skinselector.h"
+#include "modern_commonprototypes.h"
+
+/* Definitions */
+#define GetAValue(argb)((BYTE)((argb)>>24))
+
+#define DEFAULTSKINSECTION "ModernSkin"
+
+
+
+#define MAX_BUFF_SIZE 255*400
+#define MAXSN_BUFF_SIZE 255*1000
+
+/* External variables */
+
+/* Structs */
+
+typedef struct tagSKINOBJECTSLIST
+{
+ DWORD dwObjLPReserved;
+ DWORD dwObjLPAlocated;
+ char * szSkinPlace;
+ LISTMODERNMASK * pMaskList;
+ SKINOBJECTDESCRIPTOR * pObjects;
+ SortedList * pTextList;
+} SKINOBJECTSLIST;
+
+typedef struct tagGLYPHIMAGE
+{
+ char * szFileName;
+ DWORD dwLoadedTimes;
+ HBITMAP hGlyph;
+ BYTE isSemiTransp;
+} GLYPHIMAGE,*LPGLYPHIMAGE;
+
+typedef struct tagCURRWNDIMAGEDATA
+{
+ HDC hImageDC;
+ HDC hBackDC;
+ HDC hScreenDC;
+ HBITMAP hImageDIB, hImageOld;
+ HBITMAP hBackDIB, hBackOld;
+ BYTE * hImageDIBByte;
+ BYTE * hBackDIBByte;
+ int Width,Height;
+
+}CURRWNDIMAGEDATA;
+
+typedef struct tagEFFECTSSTACKITEM
+{
+ HDC hdc;
+ BYTE EffectID;
+ DWORD FirstColor;
+ DWORD SecondColor;
+} EFFECTSSTACKITEM;
+
+#pragma pack(push, 1)
+/* tga header */
+typedef struct
+{
+ BYTE id_lenght; /* size of image id */
+ BYTE colormap_type; /* 1 is has a colormap */
+ BYTE image_type; /* compression type */
+
+ short cm_first_entry; /* colormap origin */
+ short cm_length; /* colormap length */
+ BYTE cm_size; /* colormap size */
+
+ short x_origin; /* bottom left x coord origin */
+ short y_origin; /* bottom left y coord origin */
+
+ short width; /* picture width (in pixels) */
+ short height; /* picture height (in pixels) */
+
+ BYTE pixel_depth; /* bits per pixel: 8, 16, 24 or 32 */
+ BYTE image_descriptor; /* 24 bits = 0x00; 32 bits = 0x80 */
+
+} tga_header_t;
+#pragma pack(pop)
+
+
+class IniParser
+{
+public:
+ enum { FLAG_WITH_SETTINGS = 0,
+ FLAG_ONLY_OBJECTS = 1,
+ };
+
+ enum { IT_UNKNOWN, IT_FILE, IT_RESOURCE };
+
+ typedef HRESULT (*ParserCallback_t)( const char * szSection, const char * szKey, const char * szValue, IniParser * This );
+
+ IniParser( TCHAR * szFileName, BYTE flags = FLAG_WITH_SETTINGS );
+ IniParser( HINSTANCE hInst, const char * resourceName, const char * resourceType, BYTE flags = FLAG_ONLY_OBJECTS );
+ ~IniParser();
+
+ bool CheckOK() { return _isValid; }
+ HRESULT Parse( ParserCallback_t pLineCallBackProc, LPARAM lParam );
+
+ static HRESULT WriteStrToDb( const char * szSection, const char * szKey, const char * szValue, IniParser * This);
+ static int GetSkinFolder( IN const TCHAR * szFileName, OUT TCHAR * pszFolderName );
+
+private:
+
+ // common
+ enum { MAX_LINE_LEN = 512 };
+ int _eType;
+ bool _isValid;
+ char * _szSection;
+ ParserCallback_t _pLineCallBackProc;
+ BOOL _SecCheck;
+ int _nLine;
+
+ void _DoInit();
+ BOOL _DoParseLine( char * szLine );
+
+ // Processing File
+ HRESULT _DoParseFile();
+ FILE * _hFile;
+
+ // Processing resource
+ void _LoadResourceIni( HINSTANCE hInst, const char * resourceName, const char * resourceType );
+ HRESULT _DoParseResource();
+ const char * _RemoveTailings( const char * szLine, size_t& len );
+
+ HGLOBAL _hGlobalRes;
+ DWORD _dwSizeOfRes;
+ char * _pPosition;
+
+ BYTE _Flags;
+
+
+};
+
+
+int ske_UnloadSkin(SKINOBJECTSLIST * Skin);
+int ske_AddDescriptorToSkinObjectList (LPSKINOBJECTDESCRIPTOR lpDescr, SKINOBJECTSLIST* Skin);
+INT_PTR ske_Service_DrawGlyph(WPARAM wParam,LPARAM lParam);
+
+
+
+#endif
+
diff --git a/plugins/Clist_modern/src/hdr/modern_skinned_profile.h b/plugins/Clist_modern/src/hdr/modern_skinned_profile.h
new file mode 100644
index 0000000000..95ab85c606
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_skinned_profile.h
@@ -0,0 +1,245 @@
+#ifndef modern_skinned_profile_h__
+#define modern_skinned_profile_h__
+
+//#include "modern_commonheaders.h"
+//#include "modern_commonprototypes.h"
+
+#include <map>
+#include <string>
+//#include <atlstr.h>
+
+class MString
+{
+private:
+ TCHAR * _buffer;
+public:
+ MString() : _buffer( NULL ) {};
+ MString( const TCHAR * str ) { _buffer = str ? _tcsdup( str ) : NULL; }
+ MString( const MString& str ) { _buffer = str._buffer ? _tcsdup( str._buffer ) : NULL; }
+ MString& operator=( const MString& str )
+ {
+ if ( _buffer ) free( _buffer );
+ _buffer = str._buffer ? _tcsdup( str._buffer ) : NULL;
+ }
+ TCHAR* operator()( const MString& str ) { return _buffer; }
+ ~MString()
+ {
+ if ( _buffer )
+ free( _buffer );
+ _buffer = NULL;
+ }
+
+#ifdef _UNICODE
+ MString( const char * str)
+ {
+ if ( !str )
+ _buffer = NULL;
+ else
+ {
+ int cbLen = MultiByteToWideChar( 0, 0, str, -1, NULL, 0 );
+ wchar_t* _buffer = ( wchar_t* )malloc( sizeof( wchar_t )*(cbLen+1));
+ if ( _buffer == NULL ) return;
+ MultiByteToWideChar( 0, 0, str, -1, _buffer, cbLen );
+ _buffer[ cbLen ] = 0;
+ }
+ }
+#endif
+
+};
+
+class CAutoCriticalSection
+{
+public:
+ CAutoCriticalSection() //Init critical section here
+ : _pLinkedCS( NULL )
+ {
+ InitializeCriticalSection( &_CS );
+ _ifCSOwner = true;
+ _ifLocked = false;
+ }
+ CAutoCriticalSection( CAutoCriticalSection& Locker, bool doLock = true )
+ : _pLinkedCS ( &Locker )
+ {
+ _ifCSOwner = false;
+ _ifLocked = false;
+ if ( doLock )
+ Lock();
+ }
+ ~CAutoCriticalSection() // Leave if auto locker, and destroy if not
+ {
+ if ( _ifLocked )
+ Unlock();
+ if ( _ifCSOwner )
+ DeleteCriticalSection( &_CS );
+ }
+
+ void Lock() // Enter Section
+ {
+ if ( _ifLocked ) return;
+ if ( _ifCSOwner ) EnterCriticalSection( &_CS );
+ else _pLinkedCS->Lock();
+ _ifLocked = true;
+ return;
+ }
+ void Unlock() // Leave Section
+ {
+ if ( !_ifLocked ) return;
+ if ( _ifCSOwner ) LeaveCriticalSection( &_CS );
+ else _pLinkedCS->Unlock();
+ _ifLocked = false;
+ }
+
+private:
+ CRITICAL_SECTION _CS;
+ CAutoCriticalSection * _pLinkedCS;
+ bool _ifCSOwner;
+ bool _ifLocked;
+};
+
+class ValueVariant
+{
+public:
+ ValueVariant() : _type( VVT_EMPTY ) {};
+ ValueVariant( BYTE bValue ) : _type( VVT_BYTE ), _bValue( bValue ) {};
+ ValueVariant( WORD wValue ) : _type( VVT_WORD ), _wValue( wValue ) {};
+ ValueVariant( DWORD dwValue ) : _type( VVT_DWORD ), _dwValue( dwValue ) {};
+ ValueVariant( const MString& strValue ) : _type( VVT_STRING ), _strValue( strValue ) {};
+ ValueVariant( const char * szValue ) : _type( VVT_STRING ), _strValue( szValue ) {};
+#ifdef _UNICODE
+ ValueVariant( const wchar_t * szValue ) : _type( VVT_STRING ), _strValue( szValue ) {};
+#endif
+
+ BYTE GetByte()
+ {
+ switch ( _type )
+ {
+ case VVT_BYTE:
+ return ( BYTE ) _bValue;
+ case VVT_WORD:
+ case VVT_DWORD:
+ DebugBreak();
+ return ( BYTE ) _bValue;
+ default:
+ DebugBreak();
+ }
+ return 0;
+ }
+
+ WORD GetWord()
+ {
+ switch ( _type )
+ {
+ case VVT_WORD:
+ return ( WORD ) _wValue;
+
+ case VVT_BYTE:
+ case VVT_DWORD:
+ DebugBreak();
+ return ( WORD ) _wValue;
+ default:
+ DebugBreak();
+ }
+ return 0;
+ }
+
+ DWORD GetDword()
+ {
+ switch ( _type )
+ {
+ case VVT_DWORD:
+ return ( DWORD ) _dwValue;
+
+ case VVT_BYTE:
+ case VVT_WORD:
+ DebugBreak();
+ return ( DWORD ) _dwValue;
+ default:
+ DebugBreak();
+ }
+ return 0;
+ }
+ MString GetString()
+ {
+ switch ( _type )
+ {
+ case VVT_STRING:
+ return _strValue;
+
+ default:
+ DebugBreak();
+ }
+ return "";
+ }
+ const MString& GetStringStatic()
+ {
+ switch ( _type )
+ {
+ case VVT_STRING:
+ return _strValue;
+
+ default:
+ DebugBreak();
+ }
+ return _strValue;
+ }
+ bool IsEmpty() { return _type==VVT_EMPTY; }
+
+private:
+ enum
+ {
+ VVT_EMPTY = 0,
+ VVT_BYTE,
+ VVT_WORD,
+ VVT_DWORD,
+ VVT_STRING
+ };
+ int _type;
+ union
+ {
+ BYTE _bValue;
+ WORD _wValue;
+ DWORD _dwValue;
+ };
+ MString _strValue;
+
+};
+
+// this is single tone class to represent some profile settings to be skinned
+class CSkinnedProfile
+{
+private:
+ static CSkinnedProfile _me;
+ CSkinnedProfile();
+ ~CSkinnedProfile();
+
+private:
+ // Skinned profile holded attributes
+ MString _strSkinFilename;
+ bool _bLoadedFonts;
+ bool _bLoadedOthers;
+
+ typedef std::map<HashStringKeyNoCase, ValueVariant> ValueList_t;
+ typedef std::map<HashStringKeyNoCase, ValueList_t> KeyList_t;
+
+ KeyList_t SkinnedProfile;
+
+ ValueVariant* _GetValue( const char * szSection, const char * szKey );
+
+ CAutoCriticalSection _Lock; // critical section to matable skinned profile access
+
+public:
+ static CSkinnedProfile* SkinProfile() { return &_me; }
+
+ HRESULT Init();
+ HRESULT Clear();
+
+ static BYTE SpiGetSkinByte ( HANDLE hContact, const char * szSection, const char * szKey, const BYTE defValue );
+ static WORD SpiGetSkinWord ( HANDLE hContact, const char * szSection, const char * szKey, const WORD defValue );
+ static DWORD SpiGetSkinDword( HANDLE hContact, const char * szSection, const char * szKey, const DWORD defValue );
+ static BOOL SpiCheckSkinned( HANDLE hContact, const char * szSection, const char * szKey );
+
+};
+
+
+
+#endif // modern_skinned_profile_h__ \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_skinselector.h b/plugins/Clist_modern/src/hdr/modern_skinselector.h
new file mode 100644
index 0000000000..9509695ad3
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_skinselector.h
@@ -0,0 +1,88 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#pragma once
+
+#ifndef M_MOD_SKIN_SELECTOR_H_INC
+#define M_MOD_SKIN_SELECTOR_H_INC
+
+#include "newpluginapi.h"
+#include "modern_commonheaders.h"
+
+#define MAXVALUE 20
+
+#define MPF_EQUAL 1
+#define MPF_DIFF 2
+#define MPF_NOT_EQUAL ( MPF_DIFF|MPF_EQUAL )
+#define MPF_HASHED 4
+
+typedef struct tagMASKPARAM
+{
+ DWORD dwId;
+ BYTE bMaskParamFlag;
+ char* szName;
+ DWORD dwValueHash;
+ char* szValue;
+} MASKPARAM;
+
+
+typedef struct tagMODERNMASK
+{
+ MASKPARAM* pl_Params;
+ DWORD dwParamCnt;
+ union
+ {
+ void* pObject;
+ char* szObjectName;
+ };
+ DWORD dwMaskId;
+ BOOL bObjectFound;
+} MODERNMASK;
+
+typedef struct tagLISTMODERNMASK
+{
+ MODERNMASK* pl_Masks;
+ DWORD dwMaskCnt;
+} LISTMODERNMASK;
+
+/// PROTOTYPES
+int AddModernMaskToList(MODERNMASK * mm, LISTMODERNMASK * mmTemplateList);
+int AddStrModernMaskToList(DWORD maskID, char * szStr, char * objectName, LISTMODERNMASK * mmTemplateList, void * pObjectList);
+int SortMaskList(LISTMODERNMASK * mmList);
+
+int DeleteMaskByItID(DWORD mID,LISTMODERNMASK * mmTemplateList);
+int ClearMaskList(LISTMODERNMASK * mmTemplateList);
+int ExchangeMasksByID(DWORD mID1, DWORD mID2, LISTMODERNMASK * mmTemplateList);
+
+int ParseToModernMask(MODERNMASK * mm, char * szText);
+BOOL CompareModernMask(MODERNMASK * mmValue,MODERNMASK * mmTemplate);
+BOOL CompareStrWithModernMask(char * szValue,MODERNMASK * mmTemplate);
+MODERNMASK * FindMaskByStr(char * szValue,LISTMODERNMASK * mmTemplateList);
+DWORD mod_CalcHash(const char * a);
+char * ModernMaskToString(MODERNMASK * mm, char * buf, UINT bufsize);
+BOOL __inline wildcmp(const char * name, const char * mask, BYTE option);
+int RegisterObjectByParce(char * ObjectName, char * Params);
+SKINOBJECTDESCRIPTOR * skin_FindObjectByRequest(char * szValue,LISTMODERNMASK * mmTemplateList);
+SKINOBJECTDESCRIPTOR * skin_FindObjectByMask (MODERNMASK * mm,LISTMODERNMASK * mmTemplateList);
+TCHAR * GetParamNT(char * string, TCHAR * buf, int buflen, BYTE paramN, char Delim, BOOL SkipSpaces);
+int SkinDrawGlyphMask(HDC hdc, RECT * rcSize, RECT * rcClip, MODERNMASK * ModernMask);
+#endif
diff --git a/plugins/Clist_modern/src/hdr/modern_static_clui.h b/plugins/Clist_modern/src/hdr/modern_static_clui.h
new file mode 100644
index 0000000000..11e492e211
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_static_clui.h
@@ -0,0 +1,246 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+
+listed in contributors.txt.
+
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/************************************************************************/
+/** FILE CONTAINS HEADER PART FOR .../modernb/clui.c file **/
+/** **/
+/** !!! DO NOT INCLUDE IN TO OTHER FILES !!! **/
+/************************************************************************/
+
+/* Definitions */
+#pragma once
+
+#define TM_AUTOALPHA 1
+#define TM_DELAYEDSIZING 2
+#define TM_BRINGOUTTIMEOUT 3
+#define TM_BRINGINTIMEOUT 4
+#define TM_UPDATEBRINGTIMER 5
+#define TM_SMOTHALPHATRANSITION 20
+#define TM_WINDOWUPDATE 100
+#define TM_STATUSBARUPDATE 200
+
+
+
+
+#define MS_CLUI_SHOWMAINMENU "CList/ShowMainMenu"
+#define MS_CLUI_SHOWSTATUSMENU "CList/ShowStatusMenu"
+
+#define AC_SRC_NO_PREMULT_ALPHA 0x01
+#define AC_SRC_NO_ALPHA 0x02
+#define AC_DST_NO_PREMULT_ALPHA 0x10
+#define AC_DST_NO_ALPHA 0x20
+
+#define ANIMATION_STEP 40
+
+#define AEROGLASS_MINALPHA 24
+
+/* Declaration of prototypes in other modules */
+
+int ClcUnloadModule();
+int ClcGetShortData(struct ClcData* pData, struct SHORTDATA *pShortData);
+int ClcEnterDragToScroll(HWND hwnd, int Y);
+
+int CListMod_ContactListShutdownProc(WPARAM wParam,LPARAM lParam);
+int CListMod_HideWindow(HWND hwndContactList, int mode);
+
+int CListSettings_GetCopyFromCache(pdisplayNameCacheEntry pDest, DWORD flag);
+int CListSettings_SetToCache(pdisplayNameCacheEntry pSrc, DWORD flag);
+
+int CLUIServices_LoadModule(void);
+INT_PTR CLUIServices_SortList(WPARAM wParam,LPARAM lParam);
+INT_PTR CLUIServices_ProtocolStatusChanged(WPARAM wParam,LPARAM lParam);
+
+void Docking_GetMonitorRectFromWindow(HWND hWnd,RECT *rc);
+
+int EventArea_Create(HWND hCluiWnd);
+
+int ExtraImage_ExtraIDToColumnNum(int extra);
+void ExtraImage_LoadModule();
+void ExtraImage_ReloadExtraIcons();
+void ExtraImage_SetAllExtraIcons(HWND hwndList,HANDLE hContact);
+
+void GroupMenus_Init();
+
+int ModernSkinButtonLoadModule();
+int ModernSkinButton_ReposButtons(HWND parent, BYTE draw,RECT *r);
+
+void ske_ApplyTransluency();
+HBITMAP ske_CreateDIB32(int cx, int cy);
+HBITMAP ske_CreateDIB32Point(int cx, int cy, void ** bits);
+int ske_JustUpdateWindowImage();
+void ske_LoadSkinFromDB(void);
+int ske_RedrawCompleteWindow();
+int ske_UpdateWindowImage();
+int ske_ValidateFrameImageProc(RECT * r);
+
+HWND StatusBar_Create(HWND parent);
+
+void RowHeight_InitModernRow();
+
+int UnhookAll();
+
+
+/* External variables */
+
+
+/* Global variables */
+
+
+DWORD g_dwMainThreadID=0,
+ g_dwAwayMsgThreadID=0,
+ g_dwGetTextAsyncThreadID=0,
+ g_dwSmoothAnimationThreadID=0,
+ g_dwFillFontListThreadID=0;
+
+HMENU g_hMenuMain;
+BOOL g_bTransparentFlag=FALSE;
+
+BOOL g_mutex_bChangingMode=FALSE,
+ g_mutex_bSizing=FALSE;
+
+BOOL g_flag_bOnModulesLoadedCalled=FALSE;
+
+RECT g_rcEdgeSizingRect={0};
+
+BOOL (WINAPI *g_proc_SetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD);
+BOOL (WINAPI *g_proc_SetLayeredWindowAttributesNew)(HWND,COLORREF,BYTE,DWORD);
+BOOL (WINAPI *g_proc_AnimateWindow)(HWND hWnd,DWORD dwTime,DWORD dwFlags);
+
+/* Module function prototypes */
+
+int CLUI_IsInMainWindow(HWND hwnd);
+int CLUI_SizingOnBorder(POINT pt, int size);
+int CLUI_SmoothAlphaTransition(HWND hwnd, BYTE GoalAlpha, BOOL wParam);
+int CLUI_TestCursorOnBorders();
+
+static int CLUI_CreateTimerForConnectingIcon(WPARAM wParam,LPARAM lParam);
+static int CLUI_SmoothAlphaThreadTransition(HWND hwnd);
+
+/* structs */
+
+typedef struct tagPROTOTICKS{
+ int nIconsCount;
+ int nCycleStartTick;
+ char * szProto;
+ int nIndex;
+ BOOL bTimerCreated;
+ BOOL bGlobal;
+ HIMAGELIST himlIconList;
+} PROTOTICKS,*LPPROTOTICKS;
+
+typedef struct tagCHECKFILLING
+{
+ HDC hDC;
+ RECT rcRect;
+} CHECKFILLING;
+
+/* Module global variables */
+
+static BYTE bAlphaEnd;
+static BYTE bOldHideOffline;
+static BYTE bOldUseGroups;
+
+static WORD wBehindEdgeShowDelay,
+ wBehindEdgeHideDelay,
+ wBehindEdgeBorderSize;
+
+static BOOL mutex_bAnimationInProgress=FALSE,
+ mutex_bShowHideCalledFromAnimation=FALSE,
+ mutex_bIgnoreActivation=FALSE,
+ mutex_bDisableAutoUpdate=TRUE,
+ mutex_bDuringSizing=FALSE,
+ mutex_bDelayedSizing=FALSE; //TBC is it need?
+
+static BOOL flag_bFirstTimeCall=FALSE;
+
+static BOOL bTransparentFocus=TRUE,
+ bNeedFixSizingRect=FALSE,
+ bShowEventStarted=FALSE;
+
+static HANDLE hRenameMenuItem,
+ hShowAvatarMenuItem,
+ hHideAvatarMenuItem;
+
+static UINT uMsgGetProfile=0;
+
+static int nLastRequiredHeight=0,
+ nRequiredHeight=0,
+ nMirMenuState=0,
+ nStatusMenuState=0;
+
+static RECT rcNewWindowRect={0},
+ rcOldWindowRect ={0},
+ rcSizingRect={0},
+ rcCorrectSizeRect={0};
+
+static HANDLE hFrameContactTree;
+
+static PROTOTICKS CycleStartTick[64]={0};//max 64 protocols
+
+static int nAnimatedIconStep=100;
+
+
+
+int CheckFramesPos(RECT *wr); //cluiframes.c
+int CLUIFrames_ApplyNewSizes(int mode); //cluiframes.c
+int CLUIFrames_GetTotalHeight(); //cluiframes.c
+int CLUIFrames_RepaintSubContainers(); //cluiframes.c
+int CLUIFramesGetMinHeight(); //cluiframes.c
+
+int SizeFramesByWindowRect(RECT *r, HDWP * PosBatch, int mode); //cluiframes.c
+
+int InitSkinHotKeys();
+BOOL amWakeThread();
+BOOL gtaWakeThread();
+void CreateViewModeFrame();
+
+HIMAGELIST hAvatarOverlays=NULL;
+
+OVERLAYICONINFO g_pAvatarOverlayIcons[ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE + 1] =
+{
+ { "AVATAR_OVERLAY_OFFLINE", LPGEN("Offline"), IDI_AVATAR_OVERLAY_OFFLINE, -1},
+ { "AVATAR_OVERLAY_ONLINE", LPGEN("Online"), IDI_AVATAR_OVERLAY_ONLINE, -1},
+ { "AVATAR_OVERLAY_AWAY", LPGEN("Away"), IDI_AVATAR_OVERLAY_AWAY, -1},
+ { "AVATAR_OVERLAY_DND", LPGEN("DND"), IDI_AVATAR_OVERLAY_DND, -1},
+ { "AVATAR_OVERLAY_NA", LPGEN("NA"), IDI_AVATAR_OVERLAY_NA, -1},
+ { "AVATAR_OVERLAY_OCCUPIED", LPGEN("Occupied"), IDI_AVATAR_OVERLAY_OCCUPIED, -1},
+ { "AVATAR_OVERLAY_CHAT", LPGEN("Free for chat"), IDI_AVATAR_OVERLAY_CHAT, -1},
+ { "AVATAR_OVERLAY_INVISIBLE", LPGEN("Invisible"), IDI_AVATAR_OVERLAY_INVISIBLE, -1},
+ { "AVATAR_OVERLAY_PHONE", LPGEN("On the phone"), IDI_AVATAR_OVERLAY_PHONE, -1},
+ { "AVATAR_OVERLAY_LUNCH", LPGEN("Out to lunch"), IDI_AVATAR_OVERLAY_LUNCH, -1}
+};
+OVERLAYICONINFO g_pStatusOverlayIcons[ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE + 1] =
+{
+ { "STATUS_OVERLAY_OFFLINE", LPGEN("Offline"), IDI_STATUS_OVERLAY_OFFLINE, -1},
+ { "STATUS_OVERLAY_ONLINE", LPGEN("Online"), IDI_STATUS_OVERLAY_ONLINE, -1},
+ { "STATUS_OVERLAY_AWAY", LPGEN("Away"), IDI_STATUS_OVERLAY_AWAY, -1},
+ { "STATUS_OVERLAY_DND", LPGEN("DND"), IDI_STATUS_OVERLAY_DND, -1},
+ { "STATUS_OVERLAY_NA", LPGEN("NA"), IDI_STATUS_OVERLAY_NA, -1},
+ { "STATUS_OVERLAY_OCCUPIED", LPGEN("Occupied"), IDI_STATUS_OVERLAY_OCCUPIED, -1},
+ { "STATUS_OVERLAY_CHAT", LPGEN("Free for chat"), IDI_STATUS_OVERLAY_CHAT, -1},
+ { "STATUS_OVERLAY_INVISIBLE", LPGEN("Invisible"), IDI_STATUS_OVERLAY_INVISIBLE, -1},
+ { "STATUS_OVERLAY_PHONE", LPGEN("On the phone"), IDI_STATUS_OVERLAY_PHONE, -1},
+ { "STATUS_OVERLAY_LUNCH", LPGEN("Out to lunch"), IDI_STATUS_OVERLAY_LUNCH, -1}
+};
diff --git a/plugins/Clist_modern/src/hdr/modern_static_cluiframes_service.h b/plugins/Clist_modern/src/hdr/modern_static_cluiframes_service.h
new file mode 100644
index 0000000000..34403ad8cd
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_static_cluiframes_service.h
@@ -0,0 +1,192 @@
+//////////////////////////////////////////////////////////////////////////
+// WARNING
+//////////////////////////////////////////////////////////////////////////
+// TO BE INCLUDED ONLY TO modern_cluiframes.cpp
+//////////////////////////////////////////////////////////////////////////
+
+static int _us_DoSetFramePaintProc( WPARAM wParam,LPARAM lParam );
+static int _us_DoAddFrame( WPARAM wParam,LPARAM lParam );
+static int _us_DoRemoveFrame( WPARAM wParam,LPARAM lParam );
+static int _us_DoSetFrameOptions( WPARAM wParam,LPARAM lParam );
+static INT_PTR _us_DoGetFrameOptions( WPARAM wParam,LPARAM lParam );
+static int _us_DoUpdateFrame( WPARAM wParam,LPARAM lParam );
+static int _us_DoShowHideFrameTitle( WPARAM wParam,LPARAM lParam );
+static int _us_DoShowTitles( WPARAM wParam,LPARAM lParam );
+static int _us_DoHideTitles( WPARAM wParam,LPARAM lParam );
+static int _us_DoShowHideFrame( WPARAM wParam,LPARAM lParam );
+static int _us_DoShowAllFrames( WPARAM wParam,LPARAM lParam );
+static int _us_DoLockFrame( WPARAM wParam,LPARAM lParam );
+static int _us_DoCollapseFrame( WPARAM wParam,LPARAM lParam );
+static int _us_DoSetFrameBorder( WPARAM wParam,LPARAM lParam );
+static int _us_DoSetFrameAlign( WPARAM wParam,LPARAM lParam );
+static int _us_DoMoveFrame( WPARAM wParam,LPARAM lParam );
+static int _us_DoMoveFrameUp( WPARAM wParam,LPARAM lParam );
+static int _us_DoMoveFrameDown( WPARAM wParam,LPARAM lParam );
+static int _us_DoAlignFrameTop( WPARAM wParam,LPARAM lParam );
+static int _us_DoAlignFrameClient( WPARAM wParam,LPARAM lParam );
+static int _us_DoAlignFrameBottom( WPARAM wParam,LPARAM lParam );
+static int _us_DoSetFrameFloat( WPARAM wParam,LPARAM lParam );
+
+enum {
+ CFM_FIRST_MGS= WM_USER + 0x2FF,
+
+ CFM_SETFRAMEPAINTPROC,
+ CFM_ADDFRAME,
+ CFM_REMOVEFRAME,
+ CFM_SETFRAMEOPTIONS,
+ CFM_GETFRAMEOPTIONS,
+ CFM_UPDATEFRAME,
+ CFM_SHOWHIDEFRAMETITLE,
+ CFM_SHOWTITLES,
+ CFM_HIDETITLES,
+ CFM_SHOWHIDEFRAME,
+ CFM_SHOWALL,
+ CFM_LOCKFRAME,
+ CFM_COLLAPSEFRAME,
+ CFM_SETFRAMEBORDER,
+ CFM_SETFRAMEALIGN,
+ CFM_MOVEFRAME,
+ CFM_MOVEFRAMEUP,
+ CFM_MOVEFRAMEDOWN,
+ CFM_ALIGNFRAMETOP,
+ CFM_ALIGNFRAMEBOTTOM,
+ CFM_ALIGNFRAMECLIENT,
+ CFM_SETFRAMEFLOAT,
+
+ CFM_LAST_MSG
+};
+
+#define CLM_PROCESS( msg, proc ) case msg: result = proc( wParam, lParam); break;
+
+BOOL CALLBACK ProcessCLUIFrameInternalMsg(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT& result )
+{
+ if ( msg <= CFM_FIRST_MGS || msg >= CFM_LAST_MSG ) return FALSE;
+
+ switch ( msg )
+ {
+ CLM_PROCESS( CFM_SETFRAMEPAINTPROC, _us_DoSetFramePaintProc );
+ CLM_PROCESS( CFM_ADDFRAME, _us_DoAddFrame );
+ CLM_PROCESS( CFM_REMOVEFRAME, _us_DoRemoveFrame );
+ CLM_PROCESS( CFM_SETFRAMEOPTIONS, _us_DoSetFrameOptions );
+ CLM_PROCESS( CFM_GETFRAMEOPTIONS, _us_DoGetFrameOptions );
+ CLM_PROCESS( CFM_UPDATEFRAME, _us_DoUpdateFrame );
+ CLM_PROCESS( CFM_SHOWHIDEFRAMETITLE, _us_DoShowHideFrameTitle );
+ CLM_PROCESS( CFM_SHOWTITLES, _us_DoShowTitles );
+ CLM_PROCESS( CFM_HIDETITLES, _us_DoHideTitles );
+ CLM_PROCESS( CFM_SHOWHIDEFRAME, _us_DoShowHideFrame );
+ CLM_PROCESS( CFM_SHOWALL, _us_DoShowAllFrames );
+ CLM_PROCESS( CFM_LOCKFRAME, _us_DoLockFrame );
+ CLM_PROCESS( CFM_COLLAPSEFRAME, _us_DoCollapseFrame );
+ CLM_PROCESS( CFM_SETFRAMEBORDER, _us_DoSetFrameBorder );
+ CLM_PROCESS( CFM_SETFRAMEALIGN, _us_DoSetFrameAlign );
+ CLM_PROCESS( CFM_MOVEFRAME, _us_DoMoveFrame );
+ CLM_PROCESS( CFM_MOVEFRAMEUP, _us_DoMoveFrameUp );
+ CLM_PROCESS( CFM_MOVEFRAMEDOWN, _us_DoMoveFrameDown );
+ CLM_PROCESS( CFM_ALIGNFRAMETOP, _us_DoAlignFrameTop );
+ CLM_PROCESS( CFM_ALIGNFRAMEBOTTOM, _us_DoAlignFrameClient );
+ CLM_PROCESS( CFM_ALIGNFRAMECLIENT, _us_DoAlignFrameBottom );
+ CLM_PROCESS( CFM_SETFRAMEFLOAT, _us_DoSetFrameFloat );
+ default:
+ return FALSE; // Not Handled
+ }
+ return TRUE;
+}
+
+
+static INT_PTR CLUIFrames_SetFramePaintProc( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SETFRAMEPAINTPROC, wParam,lParam ) : 0; }
+
+static INT_PTR CLUIFrames_AddFrame( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_ADDFRAME, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_RemoveFrame( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_REMOVEFRAME, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_SetFrameOptions( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SETFRAMEOPTIONS, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_GetFrameOptions( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_GETFRAMEOPTIONS, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_UpdateFrame( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_UPDATEFRAME, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_ShowHideFrameTitle( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SHOWHIDEFRAMETITLE, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_ShowTitles( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SHOWTITLES, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_HideTitles( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_HIDETITLES, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_ShowHideFrame( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SHOWHIDEFRAME, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_ShowAllFrames( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SHOWALL, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_LockFrame( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_LOCKFRAME, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_CollapseFrame( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_COLLAPSEFRAME, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_SetFrameBorder( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SETFRAMEBORDER, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_SetFrameAlign( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SETFRAMEALIGN, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_MoveFrame( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_MOVEFRAME, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_MoveFrameUp( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_MOVEFRAMEUP, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_MoveFrameDown( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_MOVEFRAMEDOWN, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_AlignFrameTop( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_ALIGNFRAMETOP, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_AlignFrameClient( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_ALIGNFRAMEBOTTOM, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_AlignFrameBottom( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_ALIGNFRAMECLIENT, wParam, lParam ) : 0; }
+
+static INT_PTR CLUIFrames_SetFrameFloat( WPARAM wParam,LPARAM lParam )
+{ return ( pcli->hwndContactList ) ? SendMessage( pcli->hwndContactList, CFM_SETFRAMEFLOAT, wParam, lParam ) : 0; }
+
+static void CreateCluiFramesServices()
+{
+ CreateServiceFunction( MS_SKINENG_REGISTERPAINTSUB, CLUIFrames_SetFramePaintProc );
+ CreateServiceFunction( MS_CLIST_FRAMES_ADDFRAME, CLUIFrames_AddFrame );
+ CreateServiceFunction( MS_CLIST_FRAMES_REMOVEFRAME, CLUIFrames_RemoveFrame );
+
+ CreateServiceFunction( MS_CLIST_FRAMES_SETFRAMEOPTIONS, CLUIFrames_SetFrameOptions );
+ CreateServiceFunction( MS_CLIST_FRAMES_GETFRAMEOPTIONS, CLUIFrames_GetFrameOptions );
+ CreateServiceFunction( MS_CLIST_FRAMES_UPDATEFRAME, CLUIFrames_UpdateFrame );
+
+ CreateServiceFunction( MS_CLIST_FRAMES_SHFRAMETITLEBAR, CLUIFrames_ShowHideFrameTitle );
+ CreateServiceFunction( MS_CLIST_FRAMES_SHOWALLFRAMESTB, CLUIFrames_ShowTitles );
+ CreateServiceFunction( MS_CLIST_FRAMES_HIDEALLFRAMESTB, CLUIFrames_HideTitles );
+ CreateServiceFunction( MS_CLIST_FRAMES_SHFRAME, CLUIFrames_ShowHideFrame );
+ CreateServiceFunction( MS_CLIST_FRAMES_SHOWALLFRAMES, CLUIFrames_ShowAllFrames );
+
+ CreateServiceFunction( MS_CLIST_FRAMES_ULFRAME, CLUIFrames_LockFrame );
+ CreateServiceFunction( MS_CLIST_FRAMES_UCOLLFRAME, CLUIFrames_CollapseFrame );
+ CreateServiceFunction( MS_CLIST_FRAMES_SETUNBORDER, CLUIFrames_SetFrameBorder );
+
+ CreateServiceFunction( CLUIFRAMESSETALIGN, CLUIFrames_SetFrameAlign );
+ CreateServiceFunction( CLUIFRAMESMOVEUPDOWN, CLUIFrames_MoveFrame );
+ CreateServiceFunction( CLUIFRAMESMOVEUP, CLUIFrames_MoveFrameUp );
+ CreateServiceFunction( CLUIFRAMESMOVEDOWN, CLUIFrames_MoveFrameDown );
+
+ CreateServiceFunction( CLUIFRAMESSETALIGNALTOP, CLUIFrames_AlignFrameTop );
+ CreateServiceFunction( CLUIFRAMESSETALIGNALCLIENT, CLUIFrames_AlignFrameClient );
+ CreateServiceFunction( CLUIFRAMESSETALIGNALBOTTOM, CLUIFrames_AlignFrameBottom );
+
+ CreateServiceFunction( CLUIFRAMESSETFLOATING, CLUIFrames_SetFrameFloat );
+} \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_statusbar.h b/plugins/Clist_modern/src/hdr/modern_statusbar.h
new file mode 100644
index 0000000000..65d0ca2e57
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_statusbar.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#ifndef modern_statusbar_h__
+#define modern_statusbar_h__
+
+#include "modern_commonprototypes.h"
+#include "../m_api/m_xpTheme.h"
+
+int ModernDrawStatusBar(HWND hwnd, HDC hDC);
+int ModernDrawStatusBarWorker(HWND hWnd, HDC hDC);
+
+typedef struct tagSTATUSBARDATA
+{
+ BOOL sameWidth;
+ RECT rectBorders;
+ BYTE extraspace;
+ BYTE Align;
+ BYTE VAlign;
+ BYTE showProtoIcon;
+ BYTE showProtoName;
+ BYTE showStatusName;
+ HFONT BarFont;
+ DWORD fontColor;
+ BYTE connectingIcon;
+ BYTE TextEffectID;
+ DWORD TextEffectColor1;
+ DWORD TextEffectColor2;
+ BYTE xStatusMode; // 0-only main, 1-xStatus, 2-main as overlay
+ BYTE nProtosPerLine;
+ BYTE showProtoEmails;
+
+ HBITMAP hBmpBackground;
+ COLORREF bkColour;
+ DWORD backgroundBmpUse;
+ BOOL bkUseWinColors;
+
+ XPTHANDLE hTheme;
+
+ BOOL perProtoConfig;
+ BYTE SBarRightClk;
+
+} STATUSBARDATA;
+
+#endif // modern_statusbar_h__
diff --git a/plugins/Clist_modern/src/hdr/modern_statusmodes.h b/plugins/Clist_modern/src/hdr/modern_statusmodes.h
new file mode 100644
index 0000000000..f69f97abd9
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_statusmodes.h
@@ -0,0 +1,43 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+//add 1 to ID_STATUS_CONNECTING to mark retries (v0.1.0.1+)
+//eg ID_STATUS_CONNECTING+2 is the third connection attempt, or the second retry
+
+#pragma once
+
+#define ID_STATUS_CONNECTING 1
+//max retries is just a marker so that the clist knows what numbers represent
+//retries. It does not set any kind of limit on the number of retries you can
+//and/or should do.
+#define MAX_CONNECT_RETRIES 10000
+#define ID_STATUS_OFFLINE 40071
+#define ID_STATUS_ONLINE 40072
+#define ID_STATUS_AWAY 40073
+#define ID_STATUS_DND 40074
+#define ID_STATUS_NA 40075
+#define ID_STATUS_OCCUPIED 40076
+#define ID_STATUS_FREECHAT 40077
+#define ID_STATUS_INVISIBLE 40078
+#define ID_STATUS_ONTHEPHONE 40079
+#define ID_STATUS_OUTTOLUNCH 40080
+#define ID_STATUS_IDLE 40081 /* do not use as a m_cache_nStatus */
diff --git a/plugins/Clist_modern/src/hdr/modern_sync.h b/plugins/Clist_modern/src/hdr/modern_sync.h
new file mode 100644
index 0000000000..334d4696a7
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_sync.h
@@ -0,0 +1,98 @@
+#ifndef modern_sync_h__
+#define modern_sync_h__
+
+#include "hdr/modern_commonheaders.h"
+
+
+typedef INT_PTR (*PSYNCCALLBACKPROC)(WPARAM,LPARAM);
+
+int SyncCall(void * vproc, int count, ... );
+int SyncCallProxy( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam, CRITICAL_SECTION * cs = NULL );
+HRESULT SyncCallWinProcProxy( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam, int& nReturn );
+HRESULT SyncCallAPCProxy( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam, int& hReturn );
+
+LRESULT SyncOnWndProcCall( WPARAM wParam );
+
+// Experimental sync caller
+
+int DoCall( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam );
+
+// Have to be here due to MS Visual C++ does not support 'export' keyword
+
+// 3 params
+
+template<class RET, class A, class B, class C> class PARAMS3
+{
+ typedef RET(*proc_t)(A, B, C);
+ proc_t _proc; A _a; B _b; C _c; RET _ret;
+
+public:
+ PARAMS3( proc_t __proc, A __a, B __b, C __c ): _proc( __proc), _a (__a), _b(__b), _c(__c){};
+ static int DoSyncCall( WPARAM wParam, LPARAM lParam )
+ {
+ PARAMS3 * params = (PARAMS3 *) lParam;
+ params->_ret = params->_proc( params->_a, params->_b, params->_c );
+ return 0;
+ };
+ RET GetResult() { return _ret; }
+};
+
+template< class RET, class Ap, class Bp, class Cp, class A, class B, class C> RET Sync( RET(*proc)(Ap, Bp, Cp), A a, B b, C c )
+{
+ PARAMS3<RET, Ap, Bp, Cp> params( proc, a, b, c );
+ DoCall((PSYNCCALLBACKPROC) PARAMS3<RET, Ap, Bp, Cp>::DoSyncCall, 0, (LPARAM) &params );
+ return params.GetResult();
+};
+
+
+// 2 params
+
+template<class RET, class A, class B> class PARAMS2
+{
+ typedef RET(*proc_t)(A, B);
+ proc_t _proc; A _a; B _b; RET _ret;
+
+public:
+ PARAMS2( proc_t __proc, A __a, B __b ): _proc( __proc), _a (__a), _b(__b){};
+ static int DoSyncCall( WPARAM wParam, LPARAM lParam )
+ {
+ PARAMS2 * params = (PARAMS2 *) lParam;
+ params->_ret = params->_proc( params->_a, params->_b );
+ return 0;
+ };
+ RET GetResult() { return _ret; }
+};
+
+template< class RET, class Ap, class Bp, class A, class B> RET Sync( RET(*proc)(Ap, Bp), A a, B b )
+{
+ PARAMS2<RET, Ap, Bp> params( proc, a, b );
+ DoCall((PSYNCCALLBACKPROC) PARAMS2<RET, Ap, Bp>::DoSyncCall, 0, (LPARAM) &params );
+ return params.GetResult();
+};
+
+
+// 1 param
+template<class RET, class A> class PARAMS1
+{
+ typedef RET(*proc_t)(A);
+ proc_t _proc; A _a; RET _ret;
+
+public:
+ PARAMS1( proc_t __proc, A __a): _proc( __proc), _a (__a){};
+ static int DoSyncCall( WPARAM, LPARAM lParam )
+ {
+ PARAMS1 * params = (PARAMS1 *) lParam;
+ params->_ret = params->_proc( params->_a );
+ return 0;
+ };
+ RET GetResult() { return _ret; }
+};
+
+template< class RET, class Ap, class A> RET Sync( RET(*proc)(Ap), A a )
+{
+ PARAMS1<RET, Ap> params( proc, a );
+ DoCall((PSYNCCALLBACKPROC) PARAMS1<RET, Ap>::DoSyncCall, 0, (LPARAM) &params );
+ return params.GetResult();
+};
+
+#endif // modern_sync_h__ \ No newline at end of file
diff --git a/plugins/Clist_modern/src/hdr/modern_tstring.h b/plugins/Clist_modern/src/hdr/modern_tstring.h
new file mode 100644
index 0000000000..17fc9cf50c
--- /dev/null
+++ b/plugins/Clist_modern/src/hdr/modern_tstring.h
@@ -0,0 +1,58 @@
+#ifndef UNICODE //FIXME Build without UNICODE flag
+#define _AtlGetConversionACP() CP_THREAD_ACP
+#endif
+
+#include "MString.h"
+
+#ifdef UNICODE
+typedef CMStringA astring;
+typedef CMStringW wstring;
+
+class mbstring : public astring
+{
+ // It is prohibited to initialize by char* outside, use L"xxx"
+private:
+ mbstring( const char * pChar ) : astring( pChar ) {};
+ mbstring& operator=( const char * pChar ) { this->operator =( pChar ); return *this; }
+
+public:
+ mbstring() : astring() {};
+ mbstring( const mbstring& uStr ) : astring( uStr ) {};
+
+
+ mbstring( const wstring& tStr ) { *this = tStr.c_str(); }
+ mbstring& operator=( const wstring& tStr ) { this->operator =( tStr.c_str()); return *this; }
+
+ mbstring( const wchar_t * wChar );
+ mbstring& operator=( const astring& aStr );
+ mbstring& operator=( const wchar_t * wChar );
+ operator wstring();
+ operator astring();
+};
+
+
+class tstring : public wstring
+{
+public:
+ tstring() : wstring() {};
+ tstring(const wchar_t * pwChar) : wstring( pwChar ) {};
+
+
+ tstring(const astring& aStr) { *this = aStr.c_str(); }
+ tstring(const mbstring& utfStr) { *this = utfStr; }
+
+ tstring(const char * pChar);
+ tstring& operator=( const char * pChar );
+ tstring& operator=( const astring& aStr );
+ tstring& operator=( const mbstring& uStr );
+ operator astring();
+ operator mbstring() { return mbstring( this->c_str()); }
+};
+
+#else
+typedef CMStringA astring;
+typedef CMStringA wstring;
+typedef CMStringA tstring;
+typedef CMStringA mbstring;
+
+#endif
diff --git a/plugins/Clist_modern/src/init.cpp b/plugins/Clist_modern/src/init.cpp
new file mode 100644
index 0000000000..3faaa7e1dd
--- /dev/null
+++ b/plugins/Clist_modern/src/init.cpp
@@ -0,0 +1,244 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+//include
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_commonprototypes.h"
+#include "version.h"
+
+#include "hdr/modern_clui.h"
+#include "hdr/modern_clcpaint.h"
+
+//definitions
+
+#define CHECKRES(sub) if (sub != S_OK) return S_FALSE;
+
+HINSTANCE g_hInst = 0;
+CLIST_INTERFACE *pcli = NULL;
+CLIST_INTERFACE corecli = {0};
+CLUIDATA g_CluiData = {0};
+int hLangpack;
+
+TIME_API tmi;
+
+pfnTryEnterCriticalSection fnTryEnterCriticalSection;
+
+pfnGetAncestor fnGetAncestor;
+pfnGetMenuBarInfo fnGetMenuBarInfo;
+pfnGetScrollBarInfo fnGetScrollBarInfo;
+pfnMsgWaitForMultipleObjectsEx fnMsgWaitForMultipleObjectsEx;
+
+static HRESULT SubclassClistInterface();
+static HRESULT CreateHookableEvents();
+int EventArea_UnloadModule();
+
+__forceinline int MakeVer(int a, int b, int c, int d)
+{ return PLUGIN_MAKE_VERSION(a,b,c,d);
+}
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ "Modern Contact List",
+ MakeVer(PRODUCT_VERSION),
+ "Display contacts, event notifications, protocol status with advantage visual modifications. Supported MW modifications, enchanced metacontact cooperation.",
+ "Artem Shpynov, Ricardo Pescuma Domenecci and Anton Senko based on clist_mw by Bethoven",
+ "ashpynov@gmail.com" ,
+ "Copyright 2000-2010 Miranda-IM project",
+ "http://miranda-im.org/development",
+ UNICODE_AWARE,
+ //{043909B6-AAD8-4d82-8EB5-9F64CFE867CD}
+ {0x43909b6, 0xaad8, 0x4d82, { 0x8e, 0xb5, 0x9f, 0x64, 0xcf, 0xe8, 0x67, 0xcd }}
+};
+static const MUUID interfaces[] = {MIID_CLIST, MIID_LAST};
+
+PLUGININTERFACE const MUUID * MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID reserved)
+{
+ g_hInst = hInstDLL;
+ DisableThreadLibraryCalls(g_hInst);
+ return TRUE;
+}
+
+PLUGININTERFACE PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+PLUGININTERFACE int CListInitialise()
+{
+ HMODULE hKernel = GetModuleHandleA( "kernel32.dll" );
+ fnTryEnterCriticalSection = ( pfnTryEnterCriticalSection )GetProcAddress( hKernel, "TryEnterCriticalSection" );
+
+ HMODULE hUser = GetModuleHandleA( "user32.dll" );
+ fnGetMenuBarInfo = ( pfnGetMenuBarInfo )GetProcAddress( hUser, "GetMenuBarInfo" );
+ fnGetScrollBarInfo = ( pfnGetScrollBarInfo )GetProcAddress( hUser, "GetScrollBarInfo" );
+ fnMsgWaitForMultipleObjectsEx = ( pfnMsgWaitForMultipleObjectsEx )GetProcAddress( hUser, "MsgWaitForMultipleObjectsEx" );
+
+ if (( fnGetAncestor = ( pfnGetAncestor )GetProcAddress( hUser, "GetAncestor" )) == NULL )
+ fnGetAncestor = MyGetAncestor;
+
+ g_dwMainThreadID = GetCurrentThreadId();
+ mir_getTMI(&tmi);
+ mir_getLP( &pluginInfo );
+
+ CHECKRES ( PreLoadContactListModule ( ) );
+ CHECKRES ( SubclassClistInterface ( ) );
+ CHECKRES ( CreateHookableEvents ( ) );
+ CHECKRES ( XPThemesLoadModule ( ) );
+ CHECKRES ( SkinEngineLoadModule ( ) );
+ CHECKRES ( BackgroundsLoadModule ( ) );
+ CHECKRES ( CluiLoadModule ( ) );
+ CHECKRES ( ClcLoadModule ( ) );
+ CHECKRES ( ToolbarButtonLoadModule( ) );
+ CHECKRES ( ToolbarLoadModule() );
+
+ TRACE( "CListInitialise Modern Contact List ... Done\r\n" );
+
+ return S_OK;
+}
+
+// never called by a newer plugin loader.
+PLUGININTERFACE int Load(void)
+{
+ MessageBoxA(0,"You Running Old Miranda, use " MINIMAL_COREVERSION_STR " version!","Modern Clist",0);
+ return 1;
+}
+
+PLUGININTERFACE int Unload(void)
+{
+ TRACE("Unloading Clist Modern\r\n");
+
+ if (IsWindow(pcli->hwndContactList)) DestroyWindow(pcli->hwndContactList);
+ pcli->hwndContactList = NULL;
+
+ BackgroundsUnloadModule();
+ SkinEngineUnloadModule();
+ XPThemesUnloadModule();
+
+ UnloadAvatarOverlayIcon();
+ UninitSkinHotKeys();
+ FreeRowCell();
+ EventArea_UnloadModule();
+
+ TRACE("Unloading Clist Modern COMPLETE\r\n");
+ return 0;
+}
+
+
+static HRESULT SubclassClistInterface()
+{
+ // get the contact list interface
+ pcli = ( CLIST_INTERFACE* )CallService(MS_CLIST_RETRIEVE_INTERFACE, 0, (LPARAM)g_hInst);
+ if ((INT_PTR)pcli == CALLSERVICE_NOTFOUND || pcli->version < 6 )
+ {
+ MessageBoxA( NULL, "This version of plugin requires Miranda IM " MINIMAL_COREVERSION_STR " or later", "Fatal error", MB_OK );
+ return TRUE;
+ }
+ // OVERLOAD CLIST INTERFACE FUNCTIONS
+ //
+ // Naming convention is:
+ // 'cli*' - new handler without default core service calling
+ // 'save*' - pointer to stored default parent handle
+ // 'cli_*' - new handler with default core service calling
+
+ corecli = *pcli;
+
+ pcli->bDisplayLocked = TRUE;
+
+ pcli->pfnCheckCacheItem = (void (*)(ClcCacheEntryBase*)) cliCheckCacheItem;
+ pcli->pfnFreeCacheItem = (void(*)(ClcCacheEntryBase*)) cliFreeCacheItem;
+ pcli->pfnInvalidateDisplayNameCacheEntry = cliInvalidateDisplayNameCacheEntry;
+
+ pcli->pfnTrayIconUpdateBase = cliTrayIconUpdateBase;
+ pcli->pfnCluiProtocolStatusChanged = cliCluiProtocolStatusChanged;
+
+ pcli->pfnBeginRenameSelection = cliBeginRenameSelection;
+ pcli->pfnCreateClcContact = cliCreateClcContact;
+ pcli->pfnCreateCacheItem = cliCreateCacheItem;
+ pcli->pfnGetRowBottomY = cliGetRowBottomY;
+ pcli->pfnGetRowHeight = cliGetRowHeight;
+ pcli->pfnGetRowTopY = cliGetRowTopY;
+ pcli->pfnGetRowTotalHeight = cliGetRowTotalHeight;
+ pcli->pfnInvalidateRect = CLUI__cliInvalidateRect;
+ pcli->pfnGetCacheEntry = cliGetCacheEntry;
+ pcli->pfnOnCreateClc = CLUI::cliOnCreateClc;
+ pcli->pfnPaintClc = CLCPaint::cliPaintClc;
+ pcli->pfnRebuildEntireList = cliRebuildEntireList;
+ pcli->pfnRecalcScrollBar = cliRecalcScrollBar;
+ pcli->pfnRowHitTest = cliRowHitTest;
+ pcli->pfnScrollTo = cliScrollTo;
+ pcli->pfnShowHide = cliShowHide;
+ pcli->pfnHitTest = cliHitTest;
+ pcli->pfnCompareContacts = cliCompareContacts;
+ pcli->pfnBuildGroupPopupMenu = cliBuildGroupPopupMenu;
+ pcli->pfnGetIconFromStatusMode = cliGetIconFromStatusMode;
+ pcli->pfnFindItem = cliFindItem;
+ pcli->pfnGetRowByIndex = cliGetRowByIndex;
+ pcli->pfnGetRowsPriorTo = cliGetRowsPriorTo;
+ pcli->pfnGetGroupContentsCount = cliGetGroupContentsCount;
+ pcli->pfnCreateEvent = cliCreateEvent;
+ pcli->pfnFindRowByText = cliFindRowByText;
+
+ //partialy overloaded - call default handlers from inside
+ pcli->pfnIconFromStatusMode = cli_IconFromStatusMode;
+ pcli->pfnLoadCluiGlobalOpts = CLUI_cli_LoadCluiGlobalOpts;
+ pcli->pfnSortCLC = cli_SortCLC;
+ pcli->pfnAddGroup = cli_AddGroup;
+ pcli->pfnGetGroupCountsText = cli_GetGroupCountsText;
+ pcli->pfnAddContactToTree = cli_AddContactToTree;
+ pcli->pfnAddInfoItemToGroup = cli_AddInfoItemToGroup;
+ pcli->pfnAddItemToGroup = cli_AddItemToGroup;
+ pcli->pfnContactListWndProc = CLUI::cli_ContactListWndProc;
+ pcli->pfnDeleteItemFromTree = cli_DeleteItemFromTree;
+ pcli->pfnFreeContact = cli_FreeContact;
+ pcli->pfnFreeGroup = cli_FreeGroup;
+ pcli->pfnChangeContactIcon = cli_ChangeContactIcon;
+ pcli->pfnTrayIconProcessMessage = cli_TrayIconProcessMessage;
+ pcli->pfnSaveStateAndRebuildList = cli_SaveStateAndRebuildList;
+ pcli->pfnContactListControlWndProc = cli_ContactListControlWndProc;
+ pcli->pfnProcessExternalMessages = cli_ProcessExternalMessages;
+ pcli->pfnAddEvent = cli_AddEvent;
+ pcli->pfnRemoveEvent = cli_RemoveEvent;
+ pcli->pfnDocking_ProcessWindowMessage = Docking_ProcessWindowMessage;
+ return S_OK;
+}
+
+static HRESULT CreateHookableEvents()
+{
+ g_CluiData.hEventExtraImageListRebuilding = CreateHookableEvent(ME_CLIST_EXTRA_LIST_REBUILD);
+ g_CluiData.hEventExtraImageApplying = CreateHookableEvent(ME_CLIST_EXTRA_IMAGE_APPLY);
+ g_CluiData.hEventExtraClick = CreateHookableEvent(ME_CLIST_EXTRA_CLICK);
+ g_CluiData.hEventBkgrChanged = CreateHookableEvent(ME_BACKGROUNDCONFIG_CHANGED);
+ g_CluiData.hEventPreBuildTrayMenu = CreateHookableEvent(ME_CLIST_PREBUILDTRAYMENU);
+ g_CluiData.hEventPreBuildFrameMenu = CreateHookableEvent(ME_CLIST_PREBUILDFRAMEMENU);
+ g_CluiData.hEventPreBuildGroupMenu = CreateHookableEvent(ME_CLIST_PREBUILDGROUPMENU);
+ g_CluiData.hEventPreBuildSubGroupMenu = CreateHookableEvent(ME_CLIST_PREBUILDSUBGROUPMENU);
+ g_CluiData.hEventStatusBarShowToolTip = CreateHookableEvent(ME_CLIST_FRAMES_SB_SHOW_TOOLTIP);
+ g_CluiData.hEventStatusBarHideToolTip = CreateHookableEvent(ME_CLIST_FRAMES_SB_HIDE_TOOLTIP);
+ g_CluiData.hEventSkinServicesCreated = CreateHookableEvent(ME_SKIN_SERVICESCREATED);
+ return S_OK;
+}
diff --git a/plugins/Clist_modern/src/m_api/m_skin_eng.h b/plugins/Clist_modern/src/m_api/m_skin_eng.h
new file mode 100644
index 0000000000..78de34e2bb
--- /dev/null
+++ b/plugins/Clist_modern/src/m_api/m_skin_eng.h
@@ -0,0 +1,434 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#ifndef M_ske_H_INC
+#define M_ske_H_INC
+
+#include "newpluginapi.h"
+#include "m_clui.h"
+#include "../hdr/modern_commonheaders.h"
+
+
+/*defaults*/
+#define DEFAULT_FIT_MODE FM_STRETCH
+#define DEFAULT_STYLE ST_BRUSH
+#define DEFAULT_BKCOLOUR GetSysColor(COLOR_3DFACE)
+#define DEFAULT_SELBKCOLOUR GetSysColor(COLOR_HIGHLIGHT)
+#define SIZING_MARGIN 3
+
+/* Fit mode */
+#define FM_STRETCH 0
+#define FM_TILE_HORZ 1
+#define FM_TILE_VERT 2
+#define FM_TILE_BOTH 3
+
+/*Object types*/
+#define OT_ANY 0
+#define OT_GLYPHOBJECT 1
+#define OT_FONTOBJECT 2
+
+/*STYLE INDEXEX*/
+#define ST_SKIP 0
+#define ST_PARENT 1
+#define ST_BRUSH 2
+#define ST_IMAGE 3
+#define ST_SOLARIZE 4 //Not used yet.
+#define ST_FRAGMENT 5
+#define ST_GRADIENT 6
+
+//formats:
+#define ADT_TOP 0x00000000
+#define ADT_LEFT 0x00000000
+#define ADT_HCENTER 0x00000001
+#define ADT_RIGHT 0x00000002
+#define ADT_VCENTER 0x00000004
+#define ADT_BOTTOM 0x00000008
+//#define ADT_ECLIPSE 64
+
+
+/*SERVICES*/
+
+//toggle the 'hide offline contacts' flag and call CLUI
+//wParam=0
+//lParam=0
+#define MS_CLIST_TOGGLEHIDEOFFLINE "CList/ToggleHideOffline"
+
+#define MS_CLIST_TOGGLEGROUPS "CList/ToggleGroups"
+
+#define MS_CLIST_TOGGLESOUNDS "CList/ToggleSounds"
+
+// Add new object to skin object list.
+// wParam = pointer to SKINOBJECTDESCRIPTOR structure
+// lParam = 0 ( used for internal purposes: pointer to skin object list)
+#define MS_SKIN_REGISTEROBJECT "ModernList/RegisterObject"
+
+// Add new object to skin object list.
+// wParam = pointer to DEF_SKIN_OBJECT_PARAMS structure
+// lParam = 0 ( used for internal purposes: pointer to skin object list)
+#define MS_SKIN_REGISTERDEFOBJECT "ModernList/RegisterDefObject"
+
+typedef struct s_DEF_SKIN_OBJECT_PARAMS
+{
+ char * szObjectID;
+ BYTE defStyle;
+ DWORD defColor;
+ // SKINOBJECTSLIST * Skin;
+} DEF_SKIN_OBJECT_PARAMS;
+
+
+// Request painting glyph object
+// wParam = pointer to SKINDRAWREQUEST structure
+// lParam = 0
+#define MS_SKIN_DRAWGLYPH "ModernList/DrawGlyph"
+
+
+
+/* EVENTS */
+#define ME_SKIN_SERVICESCREATED "ModernList/ServicesCreated"
+
+/* DRAWGLYPH Request structure */
+typedef struct s_SKINDRAWREQUEST
+{
+ char szObjectID[255]; // Unic Object ID (path) to paint
+ RECT rcDestRect; // Rectangle to fit
+ RECT rcClipRect; // Rectangle to paint in.
+ HDC hDC; // Handler to device context to paint in.
+} SKINDRAWREQUEST,*LPSKINDRAWREQUEST;
+
+/* SKINOBJECTDESCRIPTOR opbject descriptor structure */
+typedef struct tagSKINOBJECTDESCRIPTOR
+{
+ BYTE bType; // One of OT_* values.
+ char* szObjectID; // Unic Object ID (path) [255] max
+ LPVOID Data; // Pointer to GLYPHOBJECT strycture if bType==OT_GLYPHOBJECT
+} SKINOBJECTDESCRIPTOR, *LPSKINOBJECTDESCRIPTOR;
+
+/* SKINOBJECTDESCRIPTOR opbject descriptor structure */
+typedef struct s_GLYPHOBJECT
+{
+ BYTE Style; // One of ST_* values
+ HBITMAP hGlyph; // Bitmap handler (for internal use only)
+ DWORD dwTop, dwLeft, dwBottom, dwRight; // Margins
+ char* szFileName; // FileName of image
+ DWORD dwColor; // Fill color
+ BYTE dwAlpha; // Constant alpha-transparency level
+ BYTE FitMode; // One of FM_* values
+ POINT clipArea; // Object image rect on full image
+ SIZE szclipArea; // Object image rect on full image
+ SortedList * plTextList; // List of GLYPHTEXT
+ LONG bmWidth;
+ LONG bmHeight;
+ BYTE bmBitsPixel;
+} GLYPHOBJECT,*LPGLYPHOBJECT;
+
+/* SKINTEXTDESCRIPTOR opbject descriptor structure */
+typedef struct s_GLYPHTEXT
+{
+ char * szGlyphTextID;
+ TCHAR * stText;
+ TCHAR * stValueText;
+ DWORD dwFlags;
+ DWORD dwColor; // Color (InvAA)(RR)(GG)(BB)
+ DWORD dwShadow; //ToDo: Color2/Shaddow
+ int iLeft,iTop,iRight,iBottom;
+ BYTE RelativeFlags;
+ char * szFontID;
+ HFONT hFont;
+ char * szObjectName;
+}GLYPHTEXT,*LPGLYPHTEXT;
+
+/* SKINTEXTDESCRIPTOR opbject descriptor structure */
+typedef struct s_SKINFONT
+{
+ char * szFontID;
+ HFONT hFont;
+}SKINFONT, *LPSKINFONT;
+
+/* HELPER FUNCTIONS */
+
+//Paint ObjectID as parent background for frame hwndIn
+int __inline SkinDrawWindowBack(HWND hwndIn, HDC hdc, RECT * rcClip, char * objectID);
+//Paint ObjectID
+int __inline SkinDrawGlyph(HDC hdc, RECT * rcSize, RECT * rcClip, char * objectID);
+//Register object with predefined style
+int __inline CreateGlyphedObjectDefStyle(char * ObjID,BYTE defStyle);
+int __inline CreateGlyphedObjectDefColor(char * ObjID,DWORD defColor);
+//Register default object
+int __inline CreateGlyphedObject(char * ObjID);
+
+
+
+//// Creating and registering objects
+//int __inline CreateGlyphedObject(char * ObjID)
+//{
+// DEF_SKIN_OBJECT_PARAMS prm={0};
+// prm.defColor=DEFAULT_BKCOLOUR;
+// prm.defStyle=DEFAULT_STYLE;
+// prm.szObjectID=ObjID;
+// return CallService(MS_SKIN_REGISTERDEFOBJECT,(WPARAM)&prm,0);
+//}
+static BOOL __inline ScreenToClientRect(HWND hWnd, LPRECT lpRect)
+{
+ BOOL ret;
+
+ POINT pt;
+
+ pt.x = lpRect->left;
+ pt.y = lpRect->top;
+
+ ret = ScreenToClient(hWnd, &pt);
+
+ if (!ret) return ret;
+
+ lpRect->left = pt.x;
+ lpRect->top = pt.y;
+
+
+ pt.x = lpRect->right;
+ pt.y = lpRect->bottom;
+
+ ret = ScreenToClient(hWnd, &pt);
+
+ lpRect->right = pt.x;
+ lpRect->bottom = pt.y;
+
+ return ret;
+}
+
+//int __inline CreateGlyphedObjectDefStyle(char * ObjID,BYTE defStyle)
+//{
+// DEF_SKIN_OBJECT_PARAMS prm={0};
+// prm.defColor=DEFAULT_BKCOLOUR;
+// prm.defStyle=defStyle;
+// prm.szObjectID=ObjID;
+// return CallService(MS_SKIN_REGISTERDEFOBJECT,(WPARAM)&prm,0);
+//}
+//int __inline CreateGlyphedObjectDefColor(char * ObjID,DWORD defColor)
+//{
+// DEF_SKIN_OBJECT_PARAMS prm={0};
+// prm.defColor=defColor;
+// prm.defStyle=ST_BRUSH;
+// prm.szObjectID=ObjID;
+// return CallService(MS_SKIN_REGISTERDEFOBJECT,(WPARAM)&prm,0);
+//}
+INT_PTR ske_Service_DrawGlyph(WPARAM wParam,LPARAM lParam);
+int __inline SkinDrawGlyph(HDC hdc, RECT * rcSize, RECT * rcClip, char * objectID)
+{
+ SKINDRAWREQUEST rq;
+ if (!objectID) return 0;
+ rq.hDC=hdc;
+ rq.rcDestRect=*rcSize;
+ rq.rcClipRect=*rcClip;
+ strncpy(rq.szObjectID,objectID,SIZEOF(rq.szObjectID));
+ return ske_Service_DrawGlyph((WPARAM)&rq,0);
+ //return CallService(MS_SKIN_DRAWGLYPH,(WPARAM)&rq,0);
+}
+//#include "../hdr/modern_skin_selector.h"
+
+//////////////////////////////////////////////
+// //
+// New Painting sequence servises //
+// //
+//////////////////////////////////////////////
+
+typedef struct sPAINT_REQUEST
+{
+ DWORD dStructSize; //size of structure
+ HWND hWnd; //called by window
+ HDC hDC; //context to draw on
+ RECT rcUpdate; //rectangle to be painted in (relative to Top-Left corner of Main window)
+ DWORD dwFlags; //drawing flags
+ void * CallbackData; //Data for passing to callback procedure
+ char Reserved[16]; //reserved for farther usage;
+} sPaintRequest;
+
+// Request to register sub for callback painting frame area
+// wParam = hWnd of called frame
+// lParam = pointer to tPaintCallBackProc (or NULL to remove)
+// return 1 - succes, 0 - failure
+#define MS_SKINENG_REGISTERPAINTSUB "SkinEngine/ske_Service_RegisterFramePaintCallbackProcedure"
+
+// Request to repaint frame or change/drop callback data immeadeately
+// wParam = hWnd of called frame
+// lParam = pointer to sPaintRequest (or NULL to redraw all)
+#define MS_SKINENG_UPTATEFRAMEIMAGE "SkinEngine/ske_Service_UpdateFrameImage"
+
+// Request to repaint frame or change/drop callback data
+// wParam = hWnd of called frame
+// lParam = pointer to sPaintRequest (or NULL to redraw all)
+// return 2 - already queued, data updated, 1-have been queued, 0 - failure
+#define MS_SKINENG_INVALIDATEFRAMEIMAGE "SkinEngine/ske_Service_InvalidateFrameImage"
+
+// Callback proc type
+typedef int (/*__stdcall*/ *tPaintCallbackProc)(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgnUpdate, DWORD dFlags, void * CallBackData);
+//tPaintCallbackProc PaintCallbackProc;
+
+// HELPER TO UPDATEIMAGEFRAME
+
+int __inline SkinEngUpdateImageFrame(HWND hwnd, RECT * rcUpdate, DWORD dwFlags, void * CallBackData)
+{
+ sPaintRequest sr={0};
+ sr.dStructSize=sizeof(sPaintRequest);
+ sr.hWnd=hwnd;
+ if (rcUpdate)
+ sr.rcUpdate=*rcUpdate;
+ sr.dwFlags=dwFlags;
+ sr.CallbackData=CallBackData;
+ return CallService(MS_SKINENG_UPTATEFRAMEIMAGE,(WPARAM)hwnd,(LPARAM)&sr);
+}
+
+int __inline SkinEngInvalidateImageFrame(HWND hwnd, CONST RECT * rcUpdate, DWORD dwFlags, void * CallBackData)
+{
+ sPaintRequest sr={0};
+ if (hwnd && (!g_CluiData.fLayered)) return InvalidateRect(hwnd,rcUpdate,dwFlags);
+ sr.dStructSize=sizeof(sPaintRequest);
+ sr.hWnd=hwnd;
+ if (rcUpdate)
+ sr.rcUpdate=*rcUpdate;
+ sr.dwFlags=dwFlags;
+ sr.CallbackData=CallBackData;
+ return CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,(WPARAM)hwnd,(LPARAM)&sr);
+}
+
+
+int __inline SkinInvalidateFrame(HWND hWnd, CONST RECT* lpRect)
+{
+ return SkinEngInvalidateImageFrame(hWnd,lpRect,0,0);
+}
+// Alpha channel GDI replacements/helpers
+
+//
+// Paints text with correct alpha channel
+// wParam - pointer to AlphaTextOutParams
+#define MS_SKINENG_ALPHATEXTOUT "SkinEngine/ske_AlphaTextOut"
+typedef struct _AlphaTextOutParams
+{
+ HDC hDC;
+ LPCTSTR lpString;
+ int nCount;
+ RECT * lpRect;
+ UINT format;
+ DWORD ARGBcolor;
+ char reserv[16];
+}AlphaTextOutParams;
+
+int __inline AlphaText(HDC hDC, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format, DWORD ARGBcolor)
+{
+ AlphaTextOutParams ap={0};
+ ap.hDC=hDC;
+ ap.lpString=lpString;
+ ap.nCount=nCount;
+ ap.lpRect=lpRect;
+ ap.format=format;
+ ap.ARGBcolor=ARGBcolor;
+ return CallService(MS_SKINENG_ALPHATEXTOUT,(WPARAM)&ap,0);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Paints text with correct alpha channel and effect, alternative to DrawText
+// wParam - pointer to DrawTextWithEffectParam
+
+typedef struct MODERNFONTEFFECT_tag
+{
+ BYTE effectIndex;
+ DWORD baseColour; // ARGB
+ DWORD secondaryColour; // ARGB
+}
+MODERNFONTEFFECT;
+
+typedef struct DrawTextWithEffectParam_tag
+{
+ int cbSize;
+ HDC hdc; // handle to DC
+ LPCTSTR lpchText; // text to draw
+ int cchText; // length of text to draw
+ LPRECT lprc; // rectangle coordinates
+ UINT dwDTFormat; // formatting options
+ MODERNFONTEFFECT * pEffect; // effect to be drawn on
+} DrawTextWithEffectParam;
+
+#define MS_DRAW_TEXT_WITH_EFFECTA "Modern/SkinEngine/DrawTextWithEffectA"
+#define MS_DRAW_TEXT_WITH_EFFECTW "Modern/SkinEngine/DrawTextWithEffectW"
+
+#ifdef UNICODE
+ #define MS_DRAW_TEXT_WITH_EFFECT MS_DRAW_TEXT_WITH_EFFECTW
+#else
+ #define MS_DRAW_TEXT_WITH_EFFECT MS_DRAW_TEXT_WITH_EFFECTA
+#endif
+
+// Helper
+int __inline DrawTextWithEffect( HDC hdc, LPCTSTR lpchText, int cchText, RECT * lprc, UINT dwDTFormat, MODERNFONTEFFECT * pEffect )
+{
+ DrawTextWithEffectParam params;
+ static BYTE bIfServiceExists = ServiceExists( MS_DRAW_TEXT_WITH_EFFECT ) ? 1 : 0;
+ if ( bIfServiceExists == 0 ) return DrawText ( hdc, lpchText, cchText, lprc, dwDTFormat );
+
+ // else
+ params.cbSize = sizeof( DrawTextWithEffectParam );
+ params.hdc = hdc;
+ params.lpchText = lpchText;
+ params.cchText = cchText;
+ params.lprc = lprc;
+ params.dwDTFormat = dwDTFormat;
+ params.pEffect = pEffect;
+ return CallService( MS_DRAW_TEXT_WITH_EFFECT, (WPARAM)&params, 0 );
+}
+
+
+typedef struct _ImageListFixParam
+{
+ HIMAGELIST himl;
+ int index;
+ HICON hicon;
+}ImageListFixParam;
+
+typedef struct _DrawIconFixParam
+{
+ HDC hdc;
+ int xLeft;
+ int yTop;
+ HICON hIcon;
+ int cxWidth;
+ int cyWidth;
+ UINT istepIfAniCur;
+ HBRUSH hbrFlickerFreeDraw;
+ UINT diFlags;
+} DrawIconFixParam;
+//wParam - pointer to DrawIconFixParam
+#define MS_SKINENG_DRAWICONEXFIX "SkinEngine/DrawIconEx_Fix"
+
+int __inline mod_DrawIconEx_helper(HDC hdc,int xLeft,int yTop,HICON hIcon,int cxWidth,int cyWidth, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags)
+{
+ DrawIconFixParam p={0};
+ p.hdc=hdc;
+ p.xLeft=xLeft;
+ p.yTop=yTop;
+ p.hIcon=hIcon;
+ p.cxWidth=cxWidth;
+ p.cyWidth=cyWidth;
+ p.istepIfAniCur=istepIfAniCur;
+ p.hbrFlickerFreeDraw=hbrFlickerFreeDraw;
+ p.diFlags=diFlags;
+ return CallService(MS_SKINENG_DRAWICONEXFIX,(WPARAM)&p,0);
+}
+#endif
diff --git a/plugins/Clist_modern/src/m_api/m_skinbutton.h b/plugins/Clist_modern/src/m_api/m_skinbutton.h
new file mode 100644
index 0000000000..43a3167ce3
--- /dev/null
+++ b/plugins/Clist_modern/src/m_api/m_skinbutton.h
@@ -0,0 +1,31 @@
+#include "m_button.h"
+
+#define MBM_UPDATETRANSPARENTFLAG WM_USER+52
+#define MBM_SETICOLIBHANDLE WM_USER+53
+#define MBM_REFRESHICOLIBICON WM_USER+54
+
+#define BUTTONSETID WM_USER+55
+#define BUTTONDRAWINPARENT WM_USER+56
+#define BUTTONSETMARGINS WM_USER+57
+#define BUTTONSETSENDONDOWN WM_USER+58
+
+
+#define SBF_ALIGN_TL_RIGHT 1
+#define SBF_ALIGN_TL_HCENTER 2
+#define SBF_ALIGN_TL_BOTTOM 4
+#define SBF_ALIGN_TL_VCENTER 8
+
+#define SBF_ALIGN_BR_RIGHT 16
+#define SBF_ALIGN_BR_HCENTER 32
+#define SBF_ALIGN_BR_BOTTOM 64
+#define SBF_ALIGN_BR_VCENTER 128
+
+#define SBF_CALL_ON_PRESS 256
+
+// Params for draw flag at Repos function
+#define SBRF_DO_NOT_DRAW 0
+#define SBRF_DO_REDRAW_ALL 1
+#define SBRF_DO_ALT_DRAW 2
+#define SBRF_REDRAW ( SBRF_DO_REDRAW_ALL|SBRF_DO_ALT_DRAW )
+
+#define BUTTONNEEDREDRAW 1256 \ No newline at end of file
diff --git a/plugins/Clist_modern/src/m_api/m_skinned_profile.h b/plugins/Clist_modern/src/m_api/m_skinned_profile.h
new file mode 100644
index 0000000000..0b0932bac6
--- /dev/null
+++ b/plugins/Clist_modern/src/m_api/m_skinned_profile.h
@@ -0,0 +1,44 @@
+#ifdef m_skinned_profile_h__
+#define m_skinned_profile_h__
+
+#define MS_SKINPROFILE_GET_INTERFACE
+
+#ifdef _cplusplus
+extern "C" {
+#endif //_cplusplus
+
+struct SKIN_PROFILE_INTERFACE
+{
+ DWORD cbSize;
+
+ int (*pfnGetByte) ( HANDLE, const char *, const char *, int, const char *szFile, const int nLine);
+ int (*pfnGetWord) ( HANDLE, const char *, const char *, int, const char *szFile, const int nLine);
+ int (*pfnGetDword)( HANDLE, const char *, const char *, int, const char *szFile, const int nLine);
+
+};
+
+#ifdef SPI_DECLARE_INTERFACE_INIT
+#include <m_database.h>
+__forceinline int mir_getSPI( struct SKIN_PROFILE_INTERFACE * pspi)
+{
+ if ( !ServiceExists( MS_SKINPROFILE_GET_INTERFACE ) )
+ {
+ pspi->pfnGetByte = DBGetContactSettingByte_Helper;
+ pspi->pfnGetWord = DBGetContactSettingWord_Helper;
+ pspi->pfnGetDword = DBGetContactSettingDword_Helper;
+ return 0;
+ }
+ else
+ {
+ pspi->cbSize = sizeof( struct SKIN_PROFILE_INTERFACE );
+ return CallService( MS_SKINPROFILE_GET_INTERFACE, 0, (LPARAM) pspi );
+ }
+}
+#endif
+
+#ifdef _cplusplus
+};
+#endif //_cplusplus
+
+
+#endif // m_skinned_profile_h__ \ No newline at end of file
diff --git a/plugins/Clist_modern/src/m_api/m_xpTheme.h b/plugins/Clist_modern/src/m_api/m_xpTheme.h
new file mode 100644
index 0000000000..63f1b0a5d3
--- /dev/null
+++ b/plugins/Clist_modern/src/m_api/m_xpTheme.h
@@ -0,0 +1,35 @@
+/* Wrapper for XP theme */
+typedef void * XPTHANDLE;
+typedef HANDLE HTHEME;
+
+XPTHANDLE xpt_AddThemeHandle(HWND hwnd, LPCWSTR className);
+void xpt_FreeThemeHandle(XPTHANDLE xptHandle);
+void xpt_FreeThemeForWindow(HWND hwnd);
+BOOL xpt_IsValidHandle(XPTHANDLE xptHandle);
+HRESULT xpt_DrawThemeBackground(XPTHANDLE xptHandle, HDC hdc, int type, int state, const RECT * sizeRect, const RECT * clipRect);
+HRESULT xpt_DrawThemeParentBackground(HWND hWnd, HDC hdc, const RECT * sizeRect);
+HRESULT xpt_DrawThemeText(XPTHANDLE xptHandle, HDC hdc, int type, int state, LPCTSTR lpStr, int len, DWORD flag1, DWORD flag2, const RECT * textRect);
+BOOL xpt_IsThemeBackgroundPartiallyTransparent(XPTHANDLE xptHandle, int type, int state);
+HRESULT xpt_DrawTheme(XPTHANDLE xptHandle, HWND hwnd, HDC hdc, int type, int state, const RECT *sizeRect, const RECT * clipRect);
+BOOL xpt_IsThemed(XPTHANDLE xptHandle);
+BOOL xpt_EnableThemeDialogTexture(HWND hwnd, DWORD flags);
+
+// next will be called only from one place
+HRESULT XPThemesLoadModule();
+void XPThemesUnloadModule();
+void xpt_OnWM_THEMECHANGED();
+
+
+//definitions
+
+
+//#include <tmschema.h>
+//TODO: ADD HERE other definitions of part and states from <tmschema.h>
+//WINDOW
+#define WP_CAPTION 1
+#define WP_SMALLCAPTION 2
+#define WP_SMALLMINCAPTION 4
+#define WP_SMALLMAXCAPTION 6
+
+#define CS_ACTIVE 1
+#define CS_INACTIVE 2 \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_aniavatars.cpp b/plugins/Clist_modern/src/modern_aniavatars.cpp
new file mode 100644
index 0000000000..88611fa1d0
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_aniavatars.cpp
@@ -0,0 +1,1300 @@
+/**************************************************************************\
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+****************************************************************************
+
+Created: Mar 9, 2007
+
+Author: Artem Shpynov aka FYR: ashpynov@gmail.com
+
+****************************************************************************
+
+File contains implementation of animated avatars in contact list
+
+\**************************************************************************/
+
+#include "hdr/modern_commonheaders.h"
+
+#define IMMEDIATE_DRAW (!AniAva.bSeparateWindow)
+
+void GDIPlus_ExtractAnimatedGIF (TCHAR * szName, int width, int height, HBITMAP * pBmp, int ** pframesDelay, int * pframesCount, SIZE * sizeAvatar);
+BOOL GDIPlus_IsAnimatedGif (TCHAR * szName);
+
+/* Next is module */
+#define ANIAVAWINDOWCLASS _T("MirandaModernAniAvatar")
+#define aacheck if ( !AniAva.bModuleStarted) return
+#define aalock EnterCriticalSection(&AniAva.CS)
+#define aaunlock LeaveCriticalSection(&AniAva.CS)
+
+#define AAO_HAS_BORDER 0x01
+#define AAO_ROUND_CORNERS 0x02
+#define AAO_HAS_OVERLAY 0x04
+#define AAO_OPAQUE 0x08
+//messages
+enum {
+ AAM_FIRST = WM_USER,
+ AAM_SETAVATAR , //sync WPARAM: TCHAR * filename, LPARAM: SIZE * size, RESULT: actual size
+ AAM_SETPOSITION, //async LPARAM: pointer to set pos info - the handler will empty it, RESULT: 0
+ AAM_REDRAW, //async
+ AAM_STOP, //async stops animation, timer, hide window - prepeare for deleting
+ AAM_PAUSE, //sync keep timer and window, but do not process painting -need before graphics change
+ AAM_RESUME, //async remobe previous flag. repaints if required
+ AAM_REMOVEAVATAR, //sync WPARAM: if y more then wParam, LPARAM: shift up to lParam( remove if values is same)
+ AAM_SETPARENT, //async WPARAM: handle of new parent window
+ AAM_SELFDESTROY, //sync
+ AAM_RENDER, //sync
+ AAM_LAST,
+};
+
+typedef struct _tagAniAva_Object
+{
+ HANDLE hContact;
+ HWND hWindow;
+ BOOL bInvalidPos;
+ BOOL bToBeDeleted;
+ DWORD dwAvatarUniqId;
+ SIZE ObjectSize;
+} ANIAVA_OBJECT;
+
+typedef struct _tagAniAva_Info
+{
+ DWORD dwAvatarUniqId;
+ TCHAR * tcsFilename;
+ int nRefCount;
+ int nStripTop;
+ int nFrameCount;
+ int * pFrameDelays;
+ SIZE FrameSize;
+} ANIAVA_INFO;
+
+typedef struct _tagAniAva_WindowInfo
+{
+ HWND hWindow;
+ RECT rcPos;
+ SIZE sizeAvatar;
+ BOOL StopTimer;
+ int TimerId;
+ int nFramesCount;
+ int * delaysInterval;
+ int currentFrame;
+
+ POINT ptFromPoint;
+
+ BOOL bPlaying;
+ int overlayIconIdx;
+ BYTE bAlpha;
+ BOOL bOrderTop;
+
+ BOOL bPaused; // was request do not draw
+ BOOL bPended; // till do not draw - was painting - need to be repaint
+} ANIAVA_WINDOWINFO;
+typedef struct _tagAniAva_PosInfo
+{
+ RECT rcPos;
+ int idxOverlay;
+ BYTE bAlpha;
+} ANIAVA_POSINFO;
+typedef struct _tagAniAvaSyncCallItem
+{
+ WPARAM wParam;
+ LPARAM lParam;
+ INT_PTR nResult;
+ HANDLE hDoneEvent;
+ PSYNCCALLBACKPROC pfnProc;
+} ANIAVA_SYNCCALLITEM;
+typedef struct _tagAniAvatarImageInfo
+{
+ POINT ptImagePos;
+ int nFramesCount;
+ int * pFrameDelays;
+ SIZE szSize;
+} ANIAVATARIMAGEINFO;
+
+//main structure to handle global
+typedef struct _tagAniAva
+{
+ //protection
+ BOOL bModuleStarted;
+ CRITICAL_SECTION CS;
+ //options
+ BYTE bFlags; // 0x1 has border, 0x2 has round corners, 0x4 has overlay, 0x8 background color
+ COLORREF borderColor;
+ BYTE cornerRadius;
+ COLORREF bkgColor;
+ HIMAGELIST overlayIconImageList;
+ //animations
+ HDC hAniAvaDC;
+ HBITMAP hAniAvaBitmap;
+ HBITMAP hAniAvaOldBitmap;
+ int width;
+ int height;
+ SortedList * AniAvatarList;
+ DWORD AnimationThreadID;
+ HANDLE AnimationThreadHandle;
+ HANDLE hExitEvent;
+ //Objects
+ SortedList * Objects;
+ BOOL bSeparateWindow;
+} ANIAVA;
+
+//module static declarations
+static void __AniAva_DebugRenderStrip();
+
+static void _AniAva_DestroyAvatarWindow( HWND hwnd);
+static void _AniAva_Clear_ANIAVA_WINDOWINFO(ANIAVA_WINDOWINFO * pavwi );
+static void _AniAva_RenderAvatar(ANIAVA_WINDOWINFO * dat, HDC hdcParent = NULL, RECT * rcInParent = NULL );
+static void _AniAva_PausePainting();
+static void _AniAva_ResumePainting();
+static void _AniAva_LoadOptions();
+static void _AniAva_ReduceAvatarImages(int startY, int dY, BOOL bDestroyWindow);
+static void _AniAva_AnimationTreadProc(HANDLE hExitEvent);
+static void _AniAva_RemoveAniAvaDC(ANIAVA * pAniAva);
+static void _AniAva_RealRemoveAvatar(DWORD UniqueID);
+static int _AniAva_LoadAvatarFromImage(TCHAR * szFileName, int width, int height, ANIAVATARIMAGEINFO * pRetAII);
+static int _AniAva_SortAvatarInfo(void * first, void * last);
+static BOOL _AniAva_GetAvatarImageInfo(DWORD dwAvatarUniqId, ANIAVATARIMAGEINFO * avii);
+static HWND _AniAva_CreateAvatarWindowSync(TCHAR *szFileName);
+
+static LRESULT CALLBACK _AniAva_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+//module variables
+static ANIAVA AniAva = {0};
+
+/// IMPLEMENTATION
+
+
+int _AniAva_OnModulesUnload(WPARAM wParam,LPARAM lParam)
+{
+ SetEvent(AniAva.hExitEvent);
+ return 0;
+}
+
+
+// Init AniAva module
+int AniAva_InitModule()
+{
+ memset(&AniAva,0,sizeof(AniAva));
+ if (g_CluiData.fGDIPlusFail) return 0;
+ if ( !( db_get_b(NULL,"CList","AvatarsAnimated",(ServiceExists(MS_AV_GETAVATARBITMAP) && !g_CluiData.fGDIPlusFail))
+ && db_get_b(NULL,"CList","AvatarsShow",SETTINGS_SHOWAVATARS_DEFAULT))) return 0;
+ {
+ WNDCLASSEX wc;
+ ZeroMemory(&wc, sizeof(wc));
+ wc.cbSize = sizeof(wc);
+ wc.lpszClassName = ANIAVAWINDOWCLASS;
+ wc.lpfnWndProc = _AniAva_WndProc;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.cbWndExtra = sizeof(ANIAVA_WINDOWINFO*);
+ wc.hbrBackground = 0;
+ wc.style = CS_GLOBALCLASS;
+ RegisterClassEx(&wc);
+ }
+ InitializeCriticalSection(&AniAva.CS);
+ AniAva.Objects = List_Create(0,2);
+ AniAva.AniAvatarList = List_Create(0,1);
+ AniAva.AniAvatarList->sortFunc = _AniAva_SortAvatarInfo;
+ AniAva.bModuleStarted = TRUE;
+ AniAva.hExitEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
+ AniAva.AnimationThreadID = (DWORD)mir_forkthread(_AniAva_AnimationTreadProc, (void*)AniAva.hExitEvent);
+ HookEvent(ME_SYSTEM_PRESHUTDOWN, _AniAva_OnModulesUnload);
+
+ _AniAva_LoadOptions();
+
+ return 1;
+}
+
+// Unload AniAva module
+int AniAva_UnloadModule()
+{
+ aacheck 0;
+ aalock;
+ {
+ int i;
+ AniAva.bModuleStarted = FALSE;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ if (AniAva.Objects->items[i])
+ _AniAva_DestroyAvatarWindow(((ANIAVA_OBJECT*)AniAva.Objects->items[i])->hWindow);
+
+ mir_free(AniAva.Objects->items[i]);
+ }
+ List_Destroy(AniAva.Objects);
+ mir_free(AniAva.Objects);
+
+ for (i=0; i < AniAva.AniAvatarList->realCount; i++)
+ {
+ ANIAVA_INFO * aai = (ANIAVA_INFO *)AniAva.AniAvatarList->items[i];
+ mir_free(aai->tcsFilename);
+ if (aai->pFrameDelays) free(aai->pFrameDelays);
+ mir_free(aai);
+ }
+ List_Destroy(AniAva.AniAvatarList);
+ mir_free(AniAva.AniAvatarList);
+ _AniAva_RemoveAniAvaDC(&AniAva);
+ SetEvent(AniAva.hExitEvent);
+ CloseHandle(AniAva.hExitEvent);
+ }
+ aaunlock;
+ DeleteCriticalSection(&AniAva.CS);
+ return 1;
+}
+// Update options
+int AniAva_UpdateOptions()
+{
+ BOOL bReloadAvatars = FALSE;
+ BOOL bBeEnabled = (!g_CluiData.fGDIPlusFail
+ && db_get_b(NULL,"CList","AvatarsAnimated",(ServiceExists(MS_AV_GETAVATARBITMAP) && !g_CluiData.fGDIPlusFail))
+ && db_get_b(NULL,"CList","AvatarsShow",SETTINGS_SHOWAVATARS_DEFAULT));
+ if (bBeEnabled && !AniAva.bModuleStarted)
+ {
+ AniAva_InitModule();
+ bReloadAvatars = TRUE;
+ }
+ else if ( !bBeEnabled && AniAva.bModuleStarted)
+ {
+ AniAva_UnloadModule();
+ bReloadAvatars = TRUE;
+ }
+ BOOL oldSeparate = AniAva.bSeparateWindow;
+ _AniAva_LoadOptions();
+ if ( oldSeparate != AniAva.bSeparateWindow )
+ {
+ AniAva_InvalidateAvatarPositions(NULL);
+ AniAva_RemoveInvalidatedAvatars();
+ }
+ if ( bReloadAvatars ) PostMessage(pcli->hwndContactTree,INTM_AVATARCHANGED,0,0);
+ else AniAva_RedrawAllAvatars(TRUE);
+ return 0;
+}
+// adds avatars to be displayed
+int AniAva_AddAvatar(HANDLE hContact, TCHAR * szFilename, int width, int heigth)
+{
+ int res = 0;
+ aacheck 0;
+ if ( !GDIPlus_IsAnimatedGif (szFilename))
+ return 0;
+ aalock;
+ {
+ //first try to find window for contact avatar
+ HWND hwnd = NULL;
+ int i;
+ ANIAVA_OBJECT * pavi;
+ ANIAVATARIMAGEINFO avii = {0};
+ SIZE szAva = { width, heigth };
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ pavi = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ if (pavi->hContact == hContact)
+ {
+ if (pavi->ObjectSize.cx == width && pavi->ObjectSize.cy == heigth)
+ {
+ hwnd = pavi->hWindow;
+ break;
+ }
+ else
+ {
+
+ _AniAva_DestroyAvatarWindow(pavi->hWindow);
+ pavi->hWindow = NULL;
+ _AniAva_RealRemoveAvatar(pavi->dwAvatarUniqId);
+ pavi->dwAvatarUniqId = 0;
+ break;
+ }
+ }
+ }
+ if (i == AniAva.Objects->realCount)
+ {
+ pavi = (ANIAVA_OBJECT *) mir_calloc( sizeof(ANIAVA_OBJECT));
+ pavi->hWindow = NULL;
+ pavi->hContact = hContact;
+ pavi->bInvalidPos = 0;
+ List_Insert( AniAva.Objects, pavi, AniAva.Objects->realCount);
+ }
+ //change avatar
+ pavi->bToBeDeleted = FALSE;
+ pavi->bInvalidPos = 0;
+ // now CreateAvatar
+ if (pavi->dwAvatarUniqId)
+ _AniAva_GetAvatarImageInfo(pavi->dwAvatarUniqId,&avii);
+ else
+ pavi->dwAvatarUniqId = _AniAva_LoadAvatarFromImage(szFilename, width, heigth, &avii);
+ if (hwnd)
+ SendMessage(hwnd, AAM_SETAVATAR, (WPARAM)&avii, (LPARAM) 0);
+ pavi->ObjectSize = avii.szSize;
+ res = MAKELONG(avii.szSize.cx, avii.szSize.cy);
+ }
+ aaunlock;
+ return res;
+}
+
+// call windows to set they parent in order to ensure valid zorder
+void AniAva_UpdateParent()
+{
+ aacheck;
+ aalock;
+ {
+ int i;
+ HWND parent = fnGetAncestor(pcli->hwndContactList,GA_PARENT);
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ SendMessage(pai->hWindow, AAM_SETPARENT, (WPARAM)parent,0);
+ }
+ }
+ aaunlock;
+}
+ANIAVA_OBJECT * FindAvatarByContact( HANDLE hContact )
+{
+ for ( int i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = ((ANIAVA_OBJECT *)AniAva.Objects->items[i]);
+ if (pai->hContact == hContact)
+ return pai;
+ }
+ return NULL;
+}
+
+int AniAva_RenderAvatar( HANDLE hContact, HDC hdcMem, RECT * rc )
+{
+ aacheck 0;
+ aalock;
+ ANIAVA_OBJECT * pai = FindAvatarByContact( hContact );
+ if ( pai )
+ SendMessage(pai->hWindow, AAM_RENDER, (WPARAM)hdcMem, (LPARAM) rc);
+ aaunlock;
+ return 0;
+}
+// update avatars pos
+int AniAva_SetAvatarPos(HANDLE hContact, RECT * rc, int overlayIdx, BYTE bAlpha)
+{
+ aacheck 0;
+ aalock;
+ if (AniAva.CS.LockCount>0)
+ {
+ aaunlock;
+ return 0;
+ }
+ {
+ ANIAVA_OBJECT * pai = FindAvatarByContact( hContact );
+ if ( pai )
+ {
+ ANIAVA_POSINFO * api = (ANIAVA_POSINFO *)malloc(sizeof(ANIAVA_POSINFO));
+ if ( !pai->hWindow)
+ {
+ HWND hwnd;
+ HWND parent;
+ ANIAVATARIMAGEINFO avii = {0};
+ //not found -> create window
+ char szName[150] = "AniAvaWnd_";
+ TCHAR * tszName;
+ _itoa((int)hContact,szName+10,16);
+
+ tszName = mir_a2t( szName );
+ hwnd = _AniAva_CreateAvatarWindowSync(tszName);
+ mir_free( tszName );
+ parent = fnGetAncestor(pcli->hwndContactList,GA_PARENT);
+ pai->hWindow = hwnd;
+ SendMessage(hwnd,AAM_SETPARENT,(WPARAM)parent,0);
+ if (_AniAva_GetAvatarImageInfo(pai->dwAvatarUniqId,&avii))
+ SendMessage(pai->hWindow, AAM_SETAVATAR, (WPARAM)&avii, (LPARAM) 0);
+ }
+ api->bAlpha = bAlpha;
+ api->idxOverlay = overlayIdx;
+ api->rcPos = *rc;
+ SendNotifyMessage(pai->hWindow, AAM_SETPOSITION, (WPARAM)0, (LPARAM) api);
+ // the AAM_SETPOSITION is responsible to destroy memory under api
+ pai->bInvalidPos = FALSE;
+ pai->bToBeDeleted = FALSE;
+ }
+ }
+ aaunlock;
+ return 1;
+}
+// remove avatar
+int AniAva_RemoveAvatar(HANDLE hContact)
+{
+ aacheck 0;
+ aalock;
+ {
+ int i;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ if (pai->hContact == hContact)
+ {
+ pai->bToBeDeleted = TRUE;
+ break;
+ }
+ }
+ }
+ aaunlock;
+ return 1;
+}
+// reset positions of avatars to be drawn (still be painted at same place)
+int AniAva_InvalidateAvatarPositions(HANDLE hContact)
+{
+ int i;
+ aacheck 0;
+ aalock;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ if (pai->hContact == hContact || !hContact)
+ {
+ pai->bInvalidPos++;
+ if (hContact) break;
+ }
+ }
+ aaunlock;
+ return 1;
+}
+// all avatars without validated position will be stop painted and probably removed
+int AniAva_RemoveInvalidatedAvatars()
+{
+ BOOL keepAvatar = FALSE;
+ aacheck 0;
+ aalock;
+
+ {
+ int i;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ if (pai->hWindow && (pai->bInvalidPos))
+ {
+ SendMessage(pai->hWindow,AAM_STOP,0,0);
+ if (pai->bInvalidPos)//>3)
+ {
+ //keepAvatar = TRUE;
+ //pai->bToBeDeleted = TRUE;
+ pai->bInvalidPos = 0;
+ _AniAva_DestroyAvatarWindow(pai->hWindow);
+ pai->hWindow = NULL;
+ }
+ }
+ if (pai->bToBeDeleted)
+ {
+ if (pai->hWindow) _AniAva_DestroyAvatarWindow(pai->hWindow);
+ pai->hWindow = NULL;
+ if ( !keepAvatar) _AniAva_RealRemoveAvatar(pai->dwAvatarUniqId);
+ mir_free(pai);
+ List_Remove(AniAva.Objects,i);
+ i--;
+ }
+ }
+ }
+ aaunlock;
+ return 1;
+}
+
+// repaint all avatars at positions (eg on main window movement)
+int AniAva_RedrawAllAvatars(BOOL updateZOrder)
+{
+ int i;
+ aacheck 0;
+ aalock;
+ updateZOrder = 1;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ if (updateZOrder)
+ SendMessage(pai->hWindow,AAM_REDRAW,(WPARAM)updateZOrder,0);
+ else
+ SendNotifyMessage(pai->hWindow,AAM_REDRAW,(WPARAM)updateZOrder,0);
+ }
+ aaunlock;
+ return 1;
+}
+
+//Static procedures
+static void CALLBACK _AniAva_SyncCallerUserAPCProc(DWORD_PTR dwParam)
+{
+ ANIAVA_SYNCCALLITEM* item = (ANIAVA_SYNCCALLITEM*) dwParam;
+ item->nResult = item->pfnProc(item->wParam, item->lParam);
+ SetEvent(item->hDoneEvent);
+}
+static INT_PTR _AniAva_CreateAvatarWindowSync_Worker(WPARAM tszName, LPARAM lParam)
+{
+ HWND hwnd = CreateWindowEx( WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_NOPARENTNOTIFY,ANIAVAWINDOWCLASS,(TCHAR*)tszName,WS_POPUP,
+ 0,0,1,1,pcli->hwndContactList, NULL, pcli->hInst, NULL );
+ return (INT_PTR)hwnd;
+}
+
+static HWND _AniAva_CreateAvatarWindowSync(TCHAR *szFileName)
+{
+ ANIAVA_SYNCCALLITEM item = {0};
+ int res = 0;
+ if ( !AniAva.AnimationThreadHandle) return NULL;
+ if (AniAva.AnimationThreadID == 0) return NULL;
+ item.wParam = (WPARAM) szFileName;
+ item.lParam = 0;
+ item.pfnProc = _AniAva_CreateAvatarWindowSync_Worker;
+ item.hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (GetCurrentThreadId() != AniAva.AnimationThreadID)
+ QueueUserAPC(_AniAva_SyncCallerUserAPCProc, AniAva.AnimationThreadHandle, (DWORD_PTR) &item);
+ else
+ _AniAva_SyncCallerUserAPCProc((DWORD_PTR) &item);
+ WaitForSingleObject(item.hDoneEvent, INFINITE);
+ CloseHandle(item.hDoneEvent);
+ return (HWND)item.nResult;
+}
+
+static void _AniAva_RealRemoveAvatar(DWORD UniqueID)
+{
+ int j,k;
+ for (j = 0; j < AniAva.AniAvatarList->realCount; j++)
+ {
+ ANIAVA_INFO * aai = (ANIAVA_INFO *) AniAva.AniAvatarList->items[j];
+ if (aai->dwAvatarUniqId == UniqueID)
+ {
+ aai->nRefCount--;
+ if (aai->nRefCount == 0)
+ {
+ _AniAva_PausePainting();
+ #ifdef _DEBUG
+ __AniAva_DebugRenderStrip();
+ #endif
+ mir_free(aai->tcsFilename);
+ if (aai->pFrameDelays) free(aai->pFrameDelays);
+ _AniAva_ReduceAvatarImages(aai->nStripTop,aai->FrameSize.cx*aai->nFrameCount, FALSE);
+ for (k = 0; k < AniAva.AniAvatarList->realCount; k++)
+ if (k != j) {
+ ANIAVA_INFO * taai = (ANIAVA_INFO *) AniAva.AniAvatarList->items[k];
+ if (taai->nStripTop>aai->nStripTop)
+ taai->nStripTop -= aai->FrameSize.cx*aai->nFrameCount;
+ }
+ if (AniAva.AniAvatarList->realCount>0)
+ {
+ //lets create hNewDC
+ HDC hNewDC;
+ HBITMAP hNewBmp, hNewOldBmp;
+
+ int newWidth = AniAva.width-aai->FrameSize.cx*aai->nFrameCount;
+ int newHeight = 0;
+ int i;
+ for (i=0; i < AniAva.AniAvatarList->realCount; i++)
+ if (i != j)
+ {
+ newHeight = max(newHeight,((ANIAVA_INFO *) AniAva.AniAvatarList->items[i])->FrameSize.cy);
+ }
+
+ hNewDC = CreateCompatibleDC(NULL);
+ hNewBmp = ske_CreateDIB32(newWidth,newHeight);
+ hNewOldBmp = (HBITMAP)SelectObject(hNewDC,hNewBmp);
+ // copy from old and from new strip
+ if (aai->nStripTop>0)
+ BitBlt(hNewDC,0,0,aai->nStripTop,newHeight,AniAva.hAniAvaDC,0,0, SRCCOPY);
+ if (aai->nStripTop+aai->FrameSize.cx*aai->nFrameCount < AniAva.width)
+ BitBlt(hNewDC,aai->nStripTop,0,AniAva.width-(aai->nStripTop+aai->FrameSize.cx*aai->nFrameCount),newHeight,AniAva.hAniAvaDC,aai->nStripTop+aai->FrameSize.cx*aai->nFrameCount,0, SRCCOPY);
+
+ _AniAva_RemoveAniAvaDC(&AniAva);
+ AniAva.hAniAvaDC = hNewDC;
+ AniAva.hAniAvaBitmap = hNewBmp;
+ AniAva.hAniAvaOldBitmap = hNewOldBmp;
+ AniAva.width = newWidth;
+ AniAva.height = newHeight;
+
+ }
+ else
+ {
+ _AniAva_RemoveAniAvaDC(&AniAva);
+ }
+ #ifdef _DEBUG
+ __AniAva_DebugRenderStrip();
+ #endif
+ List_Remove(AniAva.AniAvatarList, j);
+ mir_free(aai);
+ _AniAva_ResumePainting();
+ break;
+ }
+ }
+ }
+}
+static void _AniAva_RemoveAniAvaDC(ANIAVA * pAniAva)
+{
+ if (pAniAva->hAniAvaDC)
+ {
+ SelectObject(pAniAva->hAniAvaDC, pAniAva->hAniAvaOldBitmap);
+ DeleteObject(pAniAva->hAniAvaBitmap);
+ DeleteDC(pAniAva->hAniAvaDC);
+ pAniAva->hAniAvaDC = NULL;
+ pAniAva->height = 0;
+ pAniAva->width = 0;
+ pAniAva->hAniAvaBitmap = NULL;
+ }
+};
+
+static void _AniAva_DestroyAvatarWindow( HWND hwnd)
+{
+ SendMessage(hwnd,AAM_SELFDESTROY,0,0);
+}
+static int _AniAva_LoadAvatarFromImage(TCHAR * szFileName, int width, int height, ANIAVATARIMAGEINFO * pRetAII)
+{
+ ANIAVA_INFO aai = {0};
+ ANIAVA_INFO * paai = NULL;
+ BOOL fNeedInsertToList = FALSE;
+ int idx = 0;
+ aai.tcsFilename = szFileName;
+ aai.FrameSize.cx = width;
+ aai.FrameSize.cy = height;
+
+ if ( !List_GetIndex(AniAva.AniAvatarList,(void*)&aai,&idx)) idx = -1;
+ if (idx == -1) //item not present in list
+ {
+ HBITMAP hBitmap = NULL;
+ HDC hTempDC;
+ HBITMAP hOldBitmap;
+ HDC hNewDC;
+ HBITMAP hNewBmp;
+ HBITMAP hNewOldBmp;
+ int newWidth;
+ int newHeight;
+
+ paai = (ANIAVA_INFO *)mir_calloc(sizeof(ANIAVA_INFO));
+ paai->tcsFilename = mir_tstrdup(szFileName);
+ paai->dwAvatarUniqId = rand();
+ fNeedInsertToList = TRUE;
+ //get image strip
+ GDIPlus_ExtractAnimatedGIF (szFileName, width, height, &hBitmap, &(paai->pFrameDelays), &(paai->nFrameCount), &(paai->FrameSize));
+
+ //copy image to temp DC
+ hTempDC = CreateCompatibleDC(NULL);
+ hOldBitmap = (HBITMAP)SelectObject(hTempDC,hBitmap);
+
+ //lets create hNewDC
+ /*
+ newWidth = max(paai->FrameSize.cx*paai->nFrameCount,AniAva.width);
+ newHeight = AniAva.height+paai->FrameSize.cy;
+ */
+ newWidth = AniAva.width+paai->FrameSize.cx*paai->nFrameCount;
+ newHeight = max(paai->FrameSize.cy,AniAva.height);
+
+ hNewDC = CreateCompatibleDC(NULL);
+ hNewBmp = ske_CreateDIB32(newWidth,newHeight);
+ hNewOldBmp = (HBITMAP)SelectObject(hNewDC,hNewBmp);
+
+ _AniAva_PausePainting();
+ GdiFlush();
+ // copy from old and from new strip
+ BitBlt(hNewDC,0,0,AniAva.width,AniAva.height,AniAva.hAniAvaDC,0,0, SRCCOPY);
+ BitBlt(hNewDC,AniAva.width,0,paai->FrameSize.cx*paai->nFrameCount,paai->FrameSize.cy,hTempDC,0,0, SRCCOPY);
+
+ paai->nStripTop = AniAva.width;
+
+ GdiFlush();
+ //remove temp DC
+ SelectObject(hTempDC,hOldBitmap);
+ DeleteObject(hNewBmp);
+ DeleteDC(hTempDC);
+ DeleteObject(hBitmap);
+
+
+ //delete old
+ _AniAva_RemoveAniAvaDC(&AniAva);
+ //setNewDC;
+ AniAva.hAniAvaDC = hNewDC;
+ AniAva.hAniAvaBitmap = hNewBmp;
+ AniAva.hAniAvaOldBitmap = hNewOldBmp;
+ AniAva.width = newWidth;
+ AniAva.height = newHeight;
+ GdiFlush();
+ _AniAva_ResumePainting();
+ }
+ else
+ {
+ paai = (ANIAVA_INFO *)AniAva.AniAvatarList->items[idx];
+ }
+ if (paai)
+ {
+ paai->nRefCount++;
+ pRetAII->nFramesCount = paai->nFrameCount;
+ pRetAII->pFrameDelays = paai->pFrameDelays;
+ pRetAII->ptImagePos.x = paai->nStripTop;
+ pRetAII->ptImagePos.y = 0;
+ pRetAII->szSize = paai->FrameSize;
+ if (fNeedInsertToList)
+ {
+ //add to list
+ int idx = AniAva.AniAvatarList->realCount;
+ List_GetIndex(AniAva.AniAvatarList, paai,&idx);
+ List_Insert(AniAva.AniAvatarList, (void*)paai, idx);
+ }
+ return paai->dwAvatarUniqId;
+ }
+ return 0;
+}
+static BOOL _AniAva_GetAvatarImageInfo(DWORD dwAvatarUniqId, ANIAVATARIMAGEINFO * avii)
+{
+ int j;
+ BOOL res = FALSE;
+ for (j = 0; j < AniAva.AniAvatarList->realCount; j++)
+ {
+ ANIAVA_INFO * aai = (ANIAVA_INFO *) AniAva.AniAvatarList->items[j];
+ if (aai->dwAvatarUniqId == dwAvatarUniqId)
+ {
+ avii->nFramesCount = aai->nFrameCount;
+ avii->pFrameDelays = aai->pFrameDelays;
+ avii->ptImagePos.x = aai->nStripTop;
+ avii->ptImagePos.y = 0;
+ avii->szSize = aai->FrameSize;
+ res = TRUE;
+ break;
+ }
+ }
+ return res;
+}
+static void _AniAva_Clear_ANIAVA_WINDOWINFO(ANIAVA_WINDOWINFO * pavwi )
+{
+ pavwi->delaysInterval = NULL;
+ pavwi->nFramesCount = 0;
+ KillTimer(pavwi->hWindow,2);
+ pavwi->bPlaying = FALSE;
+ pavwi->TimerId = 0;
+}
+static void __AniAva_DebugRenderStrip()
+{
+ return;
+ #ifdef _DEBUG
+ {
+ HDC hDC_debug = GetDC(NULL);
+ BitBlt(hDC_debug,0,0,AniAva.width, AniAva.height,AniAva.hAniAvaDC,0,0,SRCCOPY);
+ DeleteDC(hDC_debug);
+ }
+ #endif
+}
+
+static void _AniAva_RenderAvatar(ANIAVA_WINDOWINFO * dat, HDC hdcParent /*= NULL*/, RECT * rcInParent /*= NULL */ )
+{
+ if (dat->bPaused>0) { dat->bPended = TRUE; return; }
+ else dat->bPended = FALSE;
+
+ if ( IMMEDIATE_DRAW && hdcParent == NULL ) return;
+ GdiFlush();
+#ifdef _DEBUG
+ __AniAva_DebugRenderStrip();
+#endif
+ if (dat->bPlaying && IsWindowVisible(dat->hWindow))
+ {
+ POINT ptWnd = {0};
+ SIZE szWnd = {dat->rcPos.right-dat->rcPos.left,dat->rcPos.bottom-dat->rcPos.top};
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0,g_CluiData.bCurrentAlpha*dat->bAlpha/256, AC_SRC_ALPHA };
+ POINT pt_from = {0,0};
+ HDC hDC_animation = GetDC(NULL);
+ HDC copyFromDC;
+ RECT clistRect;
+ HDC tempDC = NULL;
+ HBITMAP hBmp;
+ HBITMAP hOldBmp;
+
+ /*
+ int x = bf.SourceConstantAlpha;
+ x = (49152/(383-x))-129;
+ x = min(x,255); x = max(x,0);
+ bf.SourceConstantAlpha = x;
+ */
+ if ( AniAva.bFlags == 0 ) //simple and fastest method - no borders, round corners and etc. just copy
+ {
+ pt_from.x = dat->ptFromPoint.x+dat->currentFrame*dat->sizeAvatar.cx;
+ pt_from.y = dat->ptFromPoint.y;
+ copyFromDC = AniAva.hAniAvaDC;
+ }
+ else
+ {
+ // ... need to create additional hDC_animation
+ HRGN hRgn = NULL;
+ int cornerRadius = AniAva.cornerRadius;
+ tempDC = CreateCompatibleDC( NULL );
+ hBmp = ske_CreateDIB32( szWnd.cx, szWnd.cy );
+ hOldBmp = (HBITMAP)SelectObject(tempDC,hBmp);
+ if ( AniAva.bFlags & AAO_ROUND_CORNERS )
+ {
+ if ( !cornerRadius) //auto radius
+ cornerRadius = min(szWnd.cx, szWnd.cy )/5;
+ }
+ if ( AniAva.bFlags & AAO_HAS_BORDER )
+ {
+ // if has borders - create region (round corners) and fill it, remember internal as clipping
+ HBRUSH hBrush = CreateSolidBrush( AniAva.borderColor );
+ HBRUSH hOldBrush = (HBRUSH)SelectObject( tempDC, hBrush );
+ HRGN rgnOutside = CreateRoundRectRgn( 0, 0, szWnd.cx+1, szWnd.cy+1, cornerRadius << 1, cornerRadius << 1);
+ hRgn = CreateRoundRectRgn( 1, 1, szWnd.cx, szWnd.cy, cornerRadius << 1, cornerRadius << 1);
+ CombineRgn( rgnOutside,rgnOutside,hRgn,RGN_DIFF);
+ FillRgn( tempDC, rgnOutside, hBrush);
+ ske_SetRgnOpaque( tempDC, rgnOutside, TRUE);
+ SelectObject(tempDC, hOldBrush);
+ DeleteObject(hBrush);
+ DeleteObject(rgnOutside);
+ }
+ else if ( cornerRadius > 0 )
+ {
+ // else create clipping area (round corners)
+ hRgn = CreateRoundRectRgn(0, 0, szWnd.cx+1, szWnd.cy+1, cornerRadius << 1, cornerRadius << 1);
+ }
+ else
+ {
+ hRgn = CreateRectRgn(0, 0, szWnd.cx+1, szWnd.cy+1);
+ }
+ // select clip area
+ if ( hRgn )
+ ExtSelectClipRgn(tempDC, hRgn, RGN_AND);
+
+ if ( AniAva.bFlags & AAO_OPAQUE)
+ {
+ // if back color - fill clipping area
+ HBRUSH hBrush = CreateSolidBrush( AniAva.bkgColor );
+ HBRUSH hOldBrush = (HBRUSH)SelectObject( tempDC, hBrush );
+ FillRgn( tempDC, hRgn, hBrush );
+ ske_SetRgnOpaque( tempDC, hRgn, TRUE );
+ }
+ // draw avatar
+ if ( !(AniAva.bFlags & AAO_OPAQUE))
+ BitBlt(tempDC,0, 0, szWnd.cx, szWnd.cy , AniAva.hAniAvaDC , dat->ptFromPoint.x+dat->sizeAvatar.cx*dat->currentFrame, dat->ptFromPoint.y, SRCCOPY);
+ else
+ {
+ BLENDFUNCTION abf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ ske_AlphaBlend(tempDC,0, 0, szWnd.cx, szWnd.cy , AniAva.hAniAvaDC, dat->ptFromPoint.x+dat->sizeAvatar.cx*dat->currentFrame, dat->ptFromPoint.y, szWnd.cx, szWnd.cy, abf);
+ }
+ // reset clip area
+ if ( hRgn )
+ {
+ DeleteObject(hRgn);
+ hRgn = CreateRectRgn(0, 0, szWnd.cx, szWnd.cy);
+ SelectClipRgn(tempDC, hRgn);
+ DeleteObject(hRgn);
+ }
+
+ if (( AniAva.bFlags & AAO_HAS_OVERLAY )
+ && ( dat->overlayIconIdx != -1 )
+ && ( AniAva.overlayIconImageList ))
+ {
+ // if overlay - draw overlay icon
+ // position - on avatar
+ int x = szWnd.cx-ICON_WIDTH;
+ int y = szWnd.cy-ICON_HEIGHT;
+ ske_ImageList_DrawEx(AniAva.overlayIconImageList,
+ dat->overlayIconIdx&0xFFFF,
+ tempDC, x, y, ICON_WIDTH, ICON_HEIGHT,
+ CLR_NONE, CLR_NONE, ILD_NORMAL);
+ }
+ copyFromDC = tempDC;
+ }
+ // intersect visible area
+ // update layered window
+ GetWindowRect(pcli->hwndContactTree, &clistRect);
+ if (dat->rcPos.top < 0)
+ {
+ pt_from.y += -dat->rcPos.top;
+ szWnd.cy += dat->rcPos.top;
+ }
+ if (dat->rcPos.bottom>clistRect.bottom-clistRect.top)
+ szWnd.cy -= (dat->rcPos.bottom-(clistRect.bottom-clistRect.top));
+
+ ptWnd.x = dat->rcPos.left+clistRect.left;
+ ptWnd.y = (dat->rcPos.top>0 ? dat->rcPos.top :0)+clistRect.top;
+ if (szWnd.cy>0)
+ {
+ if ( hdcParent && rcInParent && IMMEDIATE_DRAW )
+ {
+ if ( AniAva.bFlags & AAO_OPAQUE )
+ BitBlt( hdcParent, rcInParent->left, rcInParent->top, szWnd.cx, szWnd.cy, copyFromDC, pt_from.x, pt_from.y, SRCCOPY);
+ else
+ {
+ BLENDFUNCTION abf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ ske_AlphaBlend( hdcParent, rcInParent->left, rcInParent->top, szWnd.cx, szWnd.cy, copyFromDC, pt_from.x, pt_from.y, szWnd.cx, szWnd.cy, abf);
+ }
+ }
+ else if ( !g_proc_UpdateLayeredWindow(dat->hWindow, hDC_animation, &ptWnd, &szWnd, copyFromDC, &pt_from, RGB(0,0,0), &bf, ULW_ALPHA ))
+ {
+ LONG exStyle;
+ exStyle = GetWindowLongPtr(dat->hWindow,GWL_EXSTYLE);
+ exStyle |= WS_EX_LAYERED;
+ SetWindowLongPtr(dat->hWindow,GWL_EXSTYLE,exStyle);
+ if ( !IMMEDIATE_DRAW )
+ SetWindowPos( pcli->hwndContactTree, dat->hWindow, 0, 0, 0, 0, SWP_ASYNCWINDOWPOS | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSENDCHANGING );
+ g_proc_UpdateLayeredWindow(dat->hWindow, hDC_animation, &ptWnd, &szWnd, copyFromDC, &pt_from, RGB(0,0,0), &bf, ULW_ALPHA );
+ }
+
+ g_CluiData.fAeroGlass = false;
+ CLUI_UpdateAeroGlass();
+ }
+ else
+ {
+ dat->bPlaying = FALSE;
+ }
+ ReleaseDC(NULL,hDC_animation);
+ if (tempDC)
+ {
+ SelectObject(tempDC, hOldBmp);
+ DeleteObject(hBmp);
+ DeleteDC(tempDC);
+ }
+ }
+ if ( !dat->bPlaying)
+ {
+ ShowWindow(dat->hWindow, SW_HIDE);
+ KillTimer(dat->hWindow,2); //stop animation till set pos will be called
+ }
+ GdiFlush();
+}
+static void _AniAva_PausePainting()
+{
+ int i;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ SendMessage(pai->hWindow,AAM_PAUSE,0,0);
+ }
+}
+static void _AniAva_ResumePainting()
+{
+ int i;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ SendNotifyMessage(pai->hWindow,AAM_RESUME,0,0);
+ }
+}
+
+static void _AniAva_ReduceAvatarImages(int startY, int dY, BOOL bDestroyWindow)
+{
+ int i;
+ for (i=0; i < AniAva.Objects->realCount; i++)
+ {
+ ANIAVA_OBJECT * pai = (ANIAVA_OBJECT *)AniAva.Objects->items[i];
+ int res = SendMessage(pai->hWindow,AAM_REMOVEAVATAR,(WPARAM)startY,(LPARAM)dY);
+ if (res == 0xDEAD && bDestroyWindow)
+ {
+ _AniAva_DestroyAvatarWindow(pai->hWindow);
+ mir_free(pai);
+ List_Remove(AniAva.Objects,i);
+ i--;
+ }
+ }
+}
+
+
+static void _AniAva_LoadOptions()
+{
+ aacheck;
+ aalock;
+ {
+ AniAva.bFlags = (db_get_b(NULL,"CList","AvatarsDrawBorders",SETTINGS_AVATARDRAWBORDER_DEFAULT)? AAO_HAS_BORDER :0) |
+ (db_get_b(NULL,"CList","AvatarsRoundCorners",SETTINGS_AVATARROUNDCORNERS_DEFAULT)? AAO_ROUND_CORNERS :0) |
+ (db_get_b(NULL,"CList","AvatarsDrawOverlay",SETTINGS_AVATARDRAWOVERLAY_DEFAULT)? AAO_HAS_OVERLAY :0) |
+ ((0) ? AAO_OPAQUE :0);
+
+ if (AniAva.bFlags & AAO_HAS_BORDER)
+ AniAva.borderColor = (COLORREF)db_get_dw(NULL,"CList","AvatarsBorderColor",SETTINGS_AVATARBORDERCOLOR_DEFAULT);;
+ if (AniAva.bFlags & AAO_ROUND_CORNERS)
+ AniAva.cornerRadius = db_get_b(NULL,"CList","AvatarsUseCustomCornerSize",SETTINGS_AVATARUSECUTOMCORNERSIZE_DEFAULT)? db_get_w(NULL,"CList","AvatarsCustomCornerSize",SETTINGS_AVATARCORNERSIZE_DEFAULT) : 0;
+ if (AniAva.bFlags & AAO_HAS_OVERLAY)
+ {
+ //check image list
+ BYTE type = db_get_b(NULL,"CList","AvatarsOverlayType",SETTINGS_AVATAROVERLAYTYPE_DEFAULT);
+ switch(type)
+ {
+ case SETTING_AVATAR_OVERLAY_TYPE_NORMAL:
+ AniAva.overlayIconImageList = hAvatarOverlays;
+ break;
+ case SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL:
+ case SETTING_AVATAR_OVERLAY_TYPE_CONTACT:
+ AniAva.overlayIconImageList = g_himlCListClc;
+ break;
+ default:
+ AniAva.overlayIconImageList = NULL;
+ }
+ }
+ if (AniAva.bFlags & AAO_OPAQUE)
+ AniAva.bkgColor = 0;
+ AniAva.bSeparateWindow = db_get_b(NULL,"CList","AvatarsInSeparateWnd",SETTINGS_AVATARINSEPARATE_DEFAULT);
+
+ }
+ aaunlock;
+}
+static void _AniAva_AnimationTreadProc(HANDLE hExitEvent)
+{
+ //wait forever till hExitEvent signalled
+ DWORD rc;
+ HANDLE hThread = 0;
+ DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),GetCurrentProcess(),&hThread,0,FALSE,DUPLICATE_SAME_ACCESS);
+ AniAva.AnimationThreadHandle = hThread;
+ SetThreadPriority(hThread,THREAD_PRIORITY_LOWEST);
+ for (;;)
+ {
+ if ( fnMsgWaitForMultipleObjectsEx )
+ rc = fnMsgWaitForMultipleObjectsEx(1,&hExitEvent, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
+ else
+ rc = MsgWaitForMultipleObjects(1,&hExitEvent, FALSE, INFINITE, QS_ALLINPUT);
+
+ ResetEvent(hExitEvent);
+ if ( rc == WAIT_OBJECT_0 + 1 )
+ {
+ MSG msg;
+ while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ if ( IsDialogMessage(msg.hwnd, &msg)) continue;
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ else if ( rc == WAIT_OBJECT_0 )
+ {
+ break;
+ }
+ }
+ CloseHandle(AniAva.AnimationThreadHandle);
+ AniAva.AnimationThreadHandle = NULL;
+}
+
+static int _AniAva_SortAvatarInfo(void * first, void * last)
+{
+ int res = 0;
+ ANIAVA_INFO * aai1 = (ANIAVA_INFO *)first;
+ ANIAVA_INFO * aai2 = (ANIAVA_INFO *)last;
+ if (aai1 && aai1->tcsFilename &&
+ aai2 && aai2->tcsFilename)
+ {
+ res = _tcsicmp(aai2->tcsFilename, aai1->tcsFilename);
+ }
+ else
+ {
+ int a1 = (aai1 && aai1->tcsFilename)? 1:0;
+ int a2 = (aai2 && aai2->tcsFilename)? 1:0;
+ res = a1-a2;
+ }
+
+ if (res == 0)
+ {
+ if ( aai1->FrameSize.cx == aai2->FrameSize.cx && aai1->FrameSize.cy == aai2->FrameSize.cy )
+ return 0;
+ else
+ return 1;
+ }
+ else
+ return res;
+}
+
+void _AniAva_InvalidateParent(ANIAVA_WINDOWINFO * dat)
+{
+ if ( !IMMEDIATE_DRAW ) return;
+ HWND hwndParent = pcli->hwndContactTree;
+ RECT rcPos = dat->rcPos;
+ pcli->pfnInvalidateRect( hwndParent, &rcPos, FALSE );
+}
+
+static LRESULT CALLBACK _AniAva_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ ANIAVA_WINDOWINFO * dat = NULL;
+ if (msg == WM_TIMER || msg == WM_DESTROY || (msg>AAM_FIRST && msg < AAM_LAST))
+ dat = (ANIAVA_WINDOWINFO *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ switch (msg)
+ {
+ case AAM_REMOVEAVATAR:
+ if (dat->ptFromPoint.x == (int)wParam) return 0xDEAD; //need to destroy window
+ else if (dat->ptFromPoint.x>(int)wParam) dat->ptFromPoint.x -= (int)lParam;
+ return 0;
+
+ case AAM_PAUSE:
+ dat->bPaused++;
+ return 0;
+
+ case AAM_RESUME:
+ dat->bPaused--;
+ if (dat->bPaused) return 0;
+ if (dat->bPended)
+ {
+ if ( !IMMEDIATE_DRAW )
+ _AniAva_RenderAvatar(dat);
+ }
+ dat->bPended = FALSE;
+ return 0;
+
+ case AAM_STOP:
+ if (dat->bPlaying)
+ {
+ dat->bPlaying = FALSE;
+ KillTimer(hwnd,2);
+ ShowWindow(hwnd, SW_HIDE);
+ }
+ return 0;
+
+ case AAM_SETAVATAR:
+ {
+ ANIAVATARIMAGEINFO *paaii = (ANIAVATARIMAGEINFO*)wParam;
+ _AniAva_Clear_ANIAVA_WINDOWINFO(dat);
+ dat->nFramesCount = paaii->nFramesCount;
+ dat->delaysInterval = paaii->pFrameDelays;
+ dat->sizeAvatar = paaii->szSize;
+ dat->ptFromPoint = paaii->ptImagePos;
+ dat->currentFrame = 0;
+ dat->bPlaying = FALSE;
+ return MAKELONG(dat->sizeAvatar.cx,dat->sizeAvatar.cy);
+ }
+
+ case AAM_SETPOSITION:
+ {
+ ANIAVA_POSINFO * papi = (ANIAVA_POSINFO *)lParam;
+ if ( !dat->delaysInterval) return 0;
+ if ( !papi) return 0;
+ dat->rcPos = papi->rcPos;
+ dat->overlayIconIdx = papi->idxOverlay;
+ dat->bAlpha = papi->bAlpha;
+ free(papi);
+ if ( !dat->bPlaying)
+ {
+ dat->bPlaying = TRUE;
+ ShowWindow(hwnd,SW_SHOWNA);
+ dat->currentFrame = 0;
+ KillTimer(hwnd,2);
+ SetTimer(hwnd,2,dat->delaysInterval[0],NULL);
+ }
+ if ( !IMMEDIATE_DRAW )
+ _AniAva_RenderAvatar(dat);
+ return 0;
+ }
+ case AAM_SETPARENT:
+ if ( IMMEDIATE_DRAW ) return 0;
+ dat->bOrderTop = ((HWND)wParam != GetDesktopWindow());
+ SetParent(hwnd,(HWND)wParam);
+ if (dat->bOrderTop)
+ {
+ SetWindowPos(hwnd,HWND_TOP,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_ASYNCWINDOWPOS);
+ }
+ else
+ {
+ LONG exStyle;
+ exStyle = GetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE);
+ SetWindowPos(pcli->hwndContactList,hwnd,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE/*|SWP_ASYNCWINDOWPOS*/);
+ if ( !(exStyle&WS_EX_TOPMOST))
+ SetWindowPos(pcli->hwndContactList,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE/*|SWP_ASYNCWINDOWPOS*/);
+ }
+ return 0;
+
+ case AAM_REDRAW:
+ if ( IMMEDIATE_DRAW )
+ return 0;
+ if ( wParam )
+ {
+ if (dat->bOrderTop)
+ {
+ SetWindowPos(hwnd,HWND_TOP,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_ASYNCWINDOWPOS);
+ }
+ else
+ {
+ LONG exStyle;
+ exStyle = GetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE);
+ SetWindowPos(pcli->hwndContactList,hwnd,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE/*|SWP_ASYNCWINDOWPOS*/);
+ if ( !(exStyle&WS_EX_TOPMOST))
+ SetWindowPos(pcli->hwndContactList,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE/*|SWP_ASYNCWINDOWPOS*/);
+ }
+ }
+
+ _AniAva_RenderAvatar( dat );
+ return 0;
+
+
+ case AAM_RENDER:
+ {
+ HDC hdc = ( HDC )wParam;
+ RECT* rect = ( RECT* )lParam;
+ _AniAva_RenderAvatar( dat, hdc, rect );
+ }
+ return 0;
+
+ case AAM_SELFDESTROY:
+ return DestroyWindow(hwnd);
+
+ case WM_CREATE:
+ {
+ LONG exStyle;
+ ANIAVA_WINDOWINFO * dat = (ANIAVA_WINDOWINFO *) mir_calloc(sizeof (ANIAVA_WINDOWINFO));
+ SetWindowLongPtr(hwnd,GWLP_USERDATA,(LONG_PTR)dat);
+ dat->hWindow = hwnd;
+ //ShowWindow(dat->hWindow,SW_SHOW);
+ //change layered mode
+ exStyle = GetWindowLongPtr(dat->hWindow,GWL_EXSTYLE);
+ exStyle |= WS_EX_LAYERED;
+ SetWindowLongPtr(dat->hWindow,GWL_EXSTYLE,exStyle);
+ exStyle = GetWindowLongPtr(dat->hWindow,GWL_STYLE);
+ exStyle &= ~WS_POPUP;
+ exStyle |= WS_CHILD;
+ SetWindowLongPtr(dat->hWindow,GWL_STYLE,exStyle);
+ break;
+ }
+ case WM_TIMER:
+ {
+ if ( !IsWindowVisible(hwnd))
+ {
+ DestroyWindow(hwnd);
+ return 0;
+ }
+ dat->currentFrame++;
+ if (dat->currentFrame >= dat->nFramesCount)
+ dat->currentFrame = 0;
+
+ if ( !IMMEDIATE_DRAW )
+ _AniAva_RenderAvatar( dat );
+ else
+ _AniAva_InvalidateParent( dat );
+
+ KillTimer(hwnd,2);
+ SetTimer(hwnd,2,dat->delaysInterval[dat->currentFrame]+1,NULL);
+ return 0;
+ }
+ case WM_DESTROY:
+ {
+ _AniAva_Clear_ANIAVA_WINDOWINFO(dat);
+ mir_free(dat);
+ SetWindowLongPtr(hwnd,GWLP_USERDATA,(LONG_PTR)NULL);
+ break;
+ }
+
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+#undef aacheck
+#undef aalock
+#undef aaunlock
+
+/////////////////////////////////////////////////////////////////
+// some stub
+
+HWND WINAPI MyGetAncestor( HWND hWnd, UINT option )
+{
+ if ( option == GA_PARENT )
+ return GetParent( hWnd );
+
+ if ( option == GA_ROOTOWNER ) {
+ HWND result = hWnd;
+ while( true ) {
+ HWND hParent = GetParent( result );
+ if ( !hParent )
+ return result;
+
+ result = hParent;
+ }
+ }
+
+ return NULL;
+}
diff --git a/plugins/Clist_modern/src/modern_awaymsg.cpp b/plugins/Clist_modern/src/modern_awaymsg.cpp
new file mode 100644
index 0000000000..342b3eefad
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_awaymsg.cpp
@@ -0,0 +1,232 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+/*
+* Author Artem Shpynov aka FYR
+* Copyright 2000-2008 Artem Shpynov
+*/
+
+//////////////////////////////////////////////////////////////////////////
+// Module to Request Away Messages
+
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_awaymsg.h"
+#include "newpluginapi.h"
+#include "hdr/modern_sync.h"
+
+#define AMASKPERIOD 3000
+#define amlock EnterCriticalSection(&amLockChain)
+#define amunlock LeaveCriticalSection(&amLockChain)
+
+typedef struct _tag_amChainItem {
+ HANDLE hContact;
+ _tag_amChainItem *Next;
+} AMCHAINITEM;
+
+static AMCHAINITEM * amFirstChainItem = NULL;
+static AMCHAINITEM * amLastChainItem = NULL;
+static CRITICAL_SECTION amLockChain;
+static HANDLE hamProcessEvent = NULL;
+static DWORD amRequestTick = 0;
+
+
+static int amAddHandleToChain(HANDLE hContact);
+static HANDLE amGetCurrentChain();
+static int amThreadProc(HWND hwnd);
+
+/*
+* Add contact handle to requests queue
+*/
+static int amAddHandleToChain(HANDLE hContact)
+{
+ AMCHAINITEM * workChain;
+ amlock;
+ {
+ //check that handle is present
+ AMCHAINITEM * wChain;
+ wChain = amFirstChainItem;
+ if (wChain)
+ do {
+ if (wChain->hContact == hContact)
+ {
+ amunlock;
+ return 0;
+ }
+ } while(wChain = (AMCHAINITEM *)wChain->Next);
+ }
+ if ( !amFirstChainItem)
+ {
+ amFirstChainItem = (AMCHAINITEM*)malloc(sizeof(AMCHAINITEM));
+ workChain = amFirstChainItem;
+ }
+ else
+ {
+ amLastChainItem->Next = (AMCHAINITEM*)malloc(sizeof(AMCHAINITEM));
+ workChain = (AMCHAINITEM *)amLastChainItem->Next;
+ }
+ amLastChainItem = workChain;
+ workChain->Next = NULL;
+ workChain->hContact = hContact;
+ amunlock;
+ SetEvent(hamProcessEvent);
+ return 1;
+}
+
+
+/*
+* Gets handle from queue for request
+*/
+static HANDLE amGetCurrentChain()
+{
+ AMCHAINITEM * workChain;
+ HANDLE res = NULL;
+ amlock;
+ if (amFirstChainItem)
+ {
+ res = amFirstChainItem->hContact;
+ workChain = amFirstChainItem->Next;
+ free(amFirstChainItem);
+ amFirstChainItem = (AMCHAINITEM *)workChain;
+ }
+ amunlock;
+ return res;
+}
+
+/*
+* Tread sub to ask protocol to retrieve away message
+*/
+static int amThreadProc(HWND hwnd)
+{
+ DWORD time;
+ HANDLE hContact;
+ HANDLE ACK = 0;
+ displayNameCacheEntry dnce;
+ memset( &dnce, 0, sizeof(dnce));
+
+ while (!MirandaExiting())
+ {
+ hContact = amGetCurrentChain();
+ while (hContact)
+ {
+ time = GetTickCount();
+ if ((time-amRequestTick) < AMASKPERIOD)
+ {
+ SleepEx(AMASKPERIOD-(time-amRequestTick)+10,TRUE);
+ if (MirandaExiting())
+ {
+ g_dwAwayMsgThreadID = 0;
+ return 0;
+ }
+ }
+ CListSettings_FreeCacheItemData(&dnce);
+ dnce.hContact = (HANDLE)hContact;
+ Sync(CLUI_SyncGetPDNCE, (WPARAM) 0,(LPARAM)&dnce);
+ if (dnce.ApparentMode != ID_STATUS_OFFLINE) //don't ask if contact is always invisible (should be done with protocol)
+ ACK = (HANDLE)CallContactService(hContact,PSS_GETAWAYMSG,0,0);
+ if ( !ACK)
+ {
+ ACKDATA ack;
+ ack.hContact = hContact;
+ ack.type = ACKTYPE_AWAYMSG;
+ ack.result = ACKRESULT_FAILED;
+ if (dnce.m_cache_cszProto)
+ ack.szModule = dnce.m_cache_cszProto;
+ else
+ ack.szModule = NULL;
+ ClcDoProtoAck(hContact, &ack);
+ }
+ CListSettings_FreeCacheItemData(&dnce);
+ amRequestTick = time;
+ hContact = amGetCurrentChain();
+ if (hContact)
+ {
+ DWORD i=0;
+ do
+ {
+ i++;
+ SleepEx(50,TRUE);
+ } while (i < AMASKPERIOD/50 && !MirandaExiting());
+ }
+ else break;
+ if (MirandaExiting())
+ {
+ g_dwAwayMsgThreadID = 0;
+ return 0;
+ }
+ }
+ WaitForSingleObjectEx(hamProcessEvent, INFINITE, TRUE);
+ ResetEvent(hamProcessEvent);
+ if (MirandaExiting())
+ {
+ g_dwAwayMsgThreadID = 0;
+ return 0;
+ }
+ }
+ g_dwAwayMsgThreadID = 0;
+ return 1;
+}
+
+BOOL amWakeThread()
+{
+ if (hamProcessEvent && g_dwAwayMsgThreadID)
+ {
+ SetEvent(hamProcessEvent);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+* Sub to be called outside on status changing to retrieve away message
+*/
+void amRequestAwayMsg(HANDLE hContact)
+{
+ char *szProto;
+ if ( !g_CluiData.bInternalAwayMsgDiscovery || !hContact)
+ return;
+ //Do not re-ask for chat rooms
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (szProto == NULL || db_get_b(hContact, szProto, "ChatRoom", 0) != 0)
+ return;
+ amAddHandleToChain(hContact);
+}
+
+void InitAwayMsgModule()
+{
+ InitializeCriticalSection(&amLockChain);
+ hamProcessEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
+ g_dwAwayMsgThreadID = (DWORD)mir_forkthread((pThreadFunc)amThreadProc,0);
+}
+
+void UninitAwayMsgModule()
+{
+ SetEvent(hamProcessEvent);
+ CloseHandle(hamProcessEvent);
+ amlock;
+ while (amGetCurrentChain());
+ amunlock;
+ DeleteCriticalSection(&amLockChain);
+}
diff --git a/plugins/Clist_modern/src/modern_cachefuncs.cpp b/plugins/Clist_modern/src/modern_cachefuncs.cpp
new file mode 100644
index 0000000000..2a14c77224
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_cachefuncs.cpp
@@ -0,0 +1,968 @@
+/* CODE STYLE */
+
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Created by Pescuma
+Modified by FYR
+
+*/
+
+/************************************************************************/
+/* Module for working with lines text and avatars */
+/************************************************************************/
+
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_cache_funcs.h"
+#include "newpluginapi.h"
+#include "./hdr/modern_gettextasync.h"
+#include "hdr/modern_sync.h"
+
+typedef BOOL (* ExecuteOnAllContactsFuncPtr) (struct ClcContact *contact, BOOL subcontact, void *param);
+
+
+/***********************************/
+/** Module static declarations **/
+/***********************************/
+
+/* Module Static Prototypes */
+
+static int CopySkipUnprintableChars(TCHAR *to, TCHAR * buf, DWORD size);
+
+static BOOL ExecuteOnAllContacts(struct ClcData *dat, ExecuteOnAllContactsFuncPtr func, void *param);
+static BOOL ExecuteOnAllContactsOfGroup(struct ClcGroup *group, ExecuteOnAllContactsFuncPtr func, void *param);
+int CLUI_SyncGetShortData(WPARAM wParam, LPARAM lParam);
+void CListSettings_FreeCacheItemData(pdisplayNameCacheEntry pDst);
+void CListSettings_FreeCacheItemDataOption( pdisplayNameCacheEntry pDst, DWORD flag );
+/*
+* Get time zone for contact
+*/
+void Cache_GetTimezone(struct ClcData *dat, HANDLE hContact)
+{
+ PDNCE pdnce = (PDNCE)pcli->pfnGetCacheEntry(hContact);
+ if (dat == NULL && pcli->hwndContactTree)
+ dat = (struct ClcData *)GetWindowLongPtr(pcli->hwndContactTree,0);
+
+ if (dat && dat->hWnd == pcli->hwndContactTree) {
+ DWORD flags = dat->contact_time_show_only_if_different ? TZF_DIFONLY : 0;
+ pdnce->hTimeZone = tmi.createByContact ? tmi.createByContact(hContact, flags) : 0;
+ }
+}
+
+/*
+* Get all lines of text
+*/
+
+void Cache_GetText(struct ClcData *dat, struct ClcContact *contact, BOOL forceRenew)
+{
+ Cache_GetFirstLineText(dat, contact);
+ if ( !dat->force_in_dialog) {
+ PDNCE pdnce = (PDNCE)pcli->pfnGetCacheEntry(contact->hContact);
+
+ if ((dat->second_line_show && (forceRenew || pdnce->szSecondLineText == NULL)) || (dat->third_line_show && (forceRenew || pdnce->szThirdLineText == NULL)))
+ gtaAddRequest(dat,contact, contact->hContact);
+ }
+}
+
+void CSmileyString::AddListeningToIcon(struct SHORTDATA *dat, pdisplayNameCacheEntry pdnce, TCHAR *szText, BOOL replace_smileys)
+{
+ iMaxSmileyHeight = 0;
+ DestroySmileyList();
+
+ if (szText == NULL) return;
+
+ int text_size = (int)_tcslen( szText );
+
+ plText = List_Create( 0, 1 );
+
+ // Add Icon
+ {
+ BITMAP bm;
+
+ ICONINFO icon;
+ ClcContactTextPiece *piece = (ClcContactTextPiece *) mir_alloc(sizeof(ClcContactTextPiece));
+
+ piece->type = TEXT_PIECE_TYPE_SMILEY;
+ piece->len = 0;
+ piece->smiley = g_hListeningToIcon;
+
+ piece->smiley_width = 16;
+ piece->smiley_height = 16;
+ if (GetIconInfo(piece->smiley, &icon)) {
+ if (GetObject(icon.hbmColor,sizeof(BITMAP),&bm)) {
+ piece->smiley_width = bm.bmWidth;
+ piece->smiley_height = bm.bmHeight;
+ }
+
+ DeleteObject(icon.hbmMask);
+ DeleteObject(icon.hbmColor);
+ }
+
+ dat->text_smiley_height = max(piece->smiley_height, dat->text_smiley_height);
+ iMaxSmileyHeight = max(piece->smiley_height, iMaxSmileyHeight);
+
+ List_Insert( plText, piece, plText->realCount);
+ }
+
+ // Add text
+ {
+ ClcContactTextPiece *piece = (ClcContactTextPiece *) mir_alloc(sizeof(ClcContactTextPiece));
+
+ piece->type = TEXT_PIECE_TYPE_TEXT;
+ piece->start_pos = 0;
+ piece->len = text_size;
+ List_Insert( plText, piece, plText->realCount);
+ }
+}
+
+void CSmileyString::_CopySmileyList( SortedList *plInput )
+{
+ // ASSERT( plText == NULL );
+
+ if ( !plInput || plInput->realCount == 0 ) return;
+ plText = List_Create( 0, 1 );
+ for ( int i=0; i < plInput->realCount; i++ )
+ {
+ ClcContactTextPiece *pieceFrom = (ClcContactTextPiece *) plInput->items[i];
+ if ( pieceFrom != NULL )
+ {
+ ClcContactTextPiece *piece = (ClcContactTextPiece *) mir_alloc( sizeof(ClcContactTextPiece));
+ *piece = *pieceFrom;
+ if ( pieceFrom->type == TEXT_PIECE_TYPE_SMILEY)
+ piece->smiley = CopyIcon( pieceFrom->smiley );
+ List_Insert( plText, piece, plText->realCount );
+ }
+ }
+}
+
+void CSmileyString::DestroySmileyList()
+{
+ //ASSERT( plText == NULL );
+
+ if ( plText == NULL ) return;
+
+ if ( IsBadReadPtr( plText, sizeof(SortedList))) {
+ plText = NULL;
+ return;
+ }
+
+ if ( plText->realCount != 0 ) {
+ for ( int i=0 ; i < plText->realCount ; i++ ) {
+ if ( plText->items[i] != NULL ) {
+ ClcContactTextPiece *piece = (ClcContactTextPiece *) plText->items[i];
+
+ if ( !IsBadWritePtr(piece, sizeof(ClcContactTextPiece))) {
+ if (piece->type == TEXT_PIECE_TYPE_SMILEY && piece->smiley != g_hListeningToIcon)
+ DestroyIcon_protect(piece->smiley);
+ mir_free(piece);
+ }
+ }
+ }
+ List_Destroy( plText );
+ }
+ mir_free(plText);
+
+ plText = NULL;
+}
+
+/*
+* Parsing of text for smiley
+*/
+
+void CSmileyString::ReplaceSmileys(struct SHORTDATA *dat, PDNCE pdnce, TCHAR * szText, BOOL replace_smileys)
+{
+ SMADD_BATCHPARSE2 sp = {0};
+ SMADD_BATCHPARSERES *spr;
+
+ int last_pos = 0;
+ iMaxSmileyHeight = 0;
+
+ DestroySmileyList();
+
+ if ( !dat->text_replace_smileys || !replace_smileys || szText == NULL)
+ return;
+
+ int text_size = (int)_tcslen( szText );
+
+ // Call service for the first time to see if needs to be used...
+ sp.cbSize = sizeof(sp);
+
+ if (dat->text_use_protocol_smileys) {
+ sp.Protocolname = pdnce->m_cache_cszProto;
+
+ if (db_get_b(NULL,"CLC","Meta",SETTING_USEMETAICON_DEFAULT) != 1 && pdnce->m_cache_cszProto != NULL && g_szMetaModuleName && strcmp(pdnce->m_cache_cszProto, g_szMetaModuleName) == 0) {
+ HANDLE hContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (LPARAM)pdnce->hContact, 0);
+ if (hContact != 0)
+ sp.Protocolname = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (LPARAM)hContact, 0);
+ }
+ }
+ else sp.Protocolname = "clist";
+
+ sp.str = szText;
+ sp.flag = SAFL_TCHAR;
+
+ spr = (SMADD_BATCHPARSERES*)CallService(MS_SMILEYADD_BATCHPARSE, 0, (LPARAM)&sp);
+
+ // Did not find a simley
+ if (spr == NULL || (INT_PTR)spr == CALLSERVICE_NOTFOUND)
+ return;
+
+ // Lets add smileys
+ plText = List_Create( 0, 1 );
+
+ for (unsigned i=0; i < sp.numSmileys; ++i) {
+ if (spr[i].hIcon != NULL) { // For deffective smileypacks
+ // Add text
+ if (spr[i].startChar - last_pos > 0) {
+ ClcContactTextPiece *piece = (ClcContactTextPiece *) mir_alloc(sizeof(ClcContactTextPiece));
+
+ piece->type = TEXT_PIECE_TYPE_TEXT;
+ piece->start_pos = last_pos ;//sp.str - text;
+ piece->len = spr[i].startChar - last_pos;
+ List_Insert(plText, piece, plText->realCount);
+ }
+
+ // Add smiley
+ {
+ BITMAP bm;
+ ICONINFO icon;
+ ClcContactTextPiece *piece = (ClcContactTextPiece *) mir_alloc(sizeof(ClcContactTextPiece));
+
+ piece->type = TEXT_PIECE_TYPE_SMILEY;
+ piece->len = spr[i].size;
+ piece->smiley = spr[i].hIcon;
+
+ piece->smiley_width = 16;
+ piece->smiley_height = 16;
+ if (GetIconInfo(piece->smiley, &icon)) {
+ if (GetObject(icon.hbmColor,sizeof(BITMAP),&bm)) {
+ piece->smiley_width = bm.bmWidth;
+ piece->smiley_height = bm.bmHeight;
+ }
+
+ DeleteObject(icon.hbmMask);
+ DeleteObject(icon.hbmColor);
+ }
+
+ dat->text_smiley_height = max( piece->smiley_height, dat->text_smiley_height );
+ iMaxSmileyHeight = max( piece->smiley_height, iMaxSmileyHeight );
+
+ List_Insert(plText, piece, plText->realCount);
+ }
+ }
+ // Get next
+ last_pos = spr[i].startChar + spr[i].size;
+ }
+ CallService(MS_SMILEYADD_BATCHFREE, 0, (LPARAM)spr);
+
+ // Add rest of text
+ if (last_pos < text_size) {
+ ClcContactTextPiece *piece = (ClcContactTextPiece *) mir_alloc(sizeof(ClcContactTextPiece));
+
+ piece->type = TEXT_PIECE_TYPE_TEXT;
+ piece->start_pos = last_pos;
+ piece->len = text_size-last_pos;
+
+ List_Insert(plText, piece, plText->realCount);
+ }
+}
+
+/*
+* Getting Status name
+* -1 for XStatus, 1 for Status
+*/
+int GetStatusName(TCHAR *text, int text_size, PDNCE pdnce, BOOL xstatus_has_priority)
+{
+ BOOL noAwayMsg = FALSE;
+ BOOL noXstatus = FALSE;
+ // Hide status text if Offline /// no offline
+ WORD nStatus = pdnce___GetStatus( pdnce );
+ if ((nStatus == ID_STATUS_OFFLINE || nStatus == 0) && g_CluiData.bRemoveAwayMessageForOffline) noAwayMsg = TRUE;
+ if (nStatus == ID_STATUS_OFFLINE || nStatus == 0) noXstatus = TRUE;
+ text[0] = '\0';
+ // Get XStatusName
+ if ( !noAwayMsg && !noXstatus && xstatus_has_priority && pdnce->hContact && pdnce->m_cache_cszProto) {
+ DBVARIANT dbv = {0};
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusName", &dbv)) {
+ //lstrcpyn(text, dbv.pszVal, text_size);
+ CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1);
+ db_free(&dbv);
+
+ if (text[0] != '\0')
+ return -1;
+ }
+ }
+
+ // Get Status name
+ {
+ TCHAR *tmp = (TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)nStatus, GSMDF_TCHAR_MY);
+ lstrcpyn(text, tmp, text_size);
+ //CopySkipUnprintableChars(text, dbv.pszVal, text_size-1);
+ if (text[0] != '\0')
+ return 1;
+ }
+
+ // Get XStatusName
+ if ( !noAwayMsg && !noXstatus && !xstatus_has_priority && pdnce->hContact && pdnce->m_cache_cszProto) {
+ DBVARIANT dbv = {0};
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusName", &dbv)) {
+ //lstrcpyn(text, dbv.pszVal, text_size);
+ CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1);
+ db_free(&dbv);
+
+ if (text[0] != '\0')
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+/*
+* Get Listening to information
+*/
+
+void GetListeningTo(TCHAR *text, int text_size, PDNCE pdnce)
+{
+ DBVARIANT dbv = {0};
+ WORD wStatus = pdnce___GetStatus( pdnce );
+ text[0] = _T('\0');
+
+ if (wStatus == ID_STATUS_OFFLINE || wStatus == 0)
+ return;
+
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "ListeningTo", &dbv)) {
+ CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1);
+ db_free(&dbv);
+ }
+}
+
+/*
+* Getting Status message (Away message)
+* -1 for XStatus, 1 for Status
+*/
+
+int GetStatusMessage(TCHAR *text, int text_size, PDNCE pdnce, BOOL xstatus_has_priority)
+{
+ DBVARIANT dbv = {0};
+ BOOL noAwayMsg = FALSE;
+ WORD wStatus = pdnce___GetStatus( pdnce );
+ text[0] = '\0';
+ // Hide status text if Offline /// no offline
+
+ if (wStatus == ID_STATUS_OFFLINE || wStatus == 0) noAwayMsg = TRUE;
+ // Get XStatusMsg
+ if ( !noAwayMsg && xstatus_has_priority && pdnce->hContact && pdnce->m_cache_cszProto) {
+ // Try to get XStatusMsg
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusMsg", &dbv)) {
+ //lstrcpyn(text, dbv.pszVal, text_size);
+ CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1);
+ db_free(&dbv);
+
+ if (text[0] != '\0')
+ return -1;
+ }
+ }
+
+ // Get StatusMsg
+ if (pdnce->hContact && text[0] == '\0') {
+ if ( !DBGetContactSettingTString(pdnce->hContact, "CList", "StatusMsg", &dbv)) {
+ //lstrcpyn(text, dbv.pszVal, text_size);
+ CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1);
+ db_free(&dbv);
+
+ if (text[0] != '\0')
+ return 1;
+ }
+ }
+
+ // Get XStatusMsg
+ if ( !noAwayMsg && !xstatus_has_priority && pdnce->hContact && pdnce->m_cache_cszProto && text[0] == '\0') {
+ // Try to get XStatusMsg
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusMsg", &dbv)) {
+ //lstrcpyn(text, dbv.pszVal, text_size);
+ CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1);
+ db_free(&dbv);
+
+ if (text[0] != '\0')
+ return -1;
+ }
+ }
+
+ return 1;
+}
+
+
+/*
+* Get the text for specified lines
+*/
+int Cache_GetLineText(PDNCE pdnce, int type, LPTSTR text, int text_size, TCHAR *variable_text, BOOL xstatus_has_priority,
+ BOOL show_status_if_no_away, BOOL show_listening_if_no_away, BOOL use_name_and_message_for_xstatus,
+ BOOL pdnce_time_show_only_if_different)
+{
+ text[0] = '\0';
+ switch(type) {
+ case TEXT_STATUS:
+ if (GetStatusName(text, text_size, pdnce, xstatus_has_priority) == -1 && use_name_and_message_for_xstatus) {
+ DBVARIANT dbv = {0};
+
+ // Try to get XStatusMsg
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusMsg", &dbv)) {
+ if (dbv.ptszVal != NULL && dbv.ptszVal[0] != 0) {
+ TCHAR *tmp = NEWTSTR_ALLOCA(text);
+ mir_sntprintf(text, text_size, _T("%s: %s"), tmp, dbv.ptszVal);
+ CopySkipUnprintableChars(text, text, text_size-1);
+ }
+ db_free(&dbv);
+ }
+ }
+
+ return TEXT_STATUS;
+
+ case TEXT_NICKNAME:
+ if (pdnce->hContact && pdnce->m_cache_cszProto) {
+ DBVARIANT dbv = {0};
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "Nick", &dbv)) {
+ lstrcpyn(text, dbv.ptszVal, text_size);
+ db_free(&dbv);
+ CopySkipUnprintableChars(text, text, text_size-1);
+ }
+ }
+
+ return TEXT_NICKNAME;
+
+ case TEXT_STATUS_MESSAGE:
+ if (GetStatusMessage(text, text_size, pdnce, xstatus_has_priority) == -1 && use_name_and_message_for_xstatus) {
+ DBVARIANT dbv = {0};
+
+ // Try to get XStatusName
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusName", &dbv)) {
+ if (dbv.pszVal != NULL && dbv.pszVal[0] != 0) {
+ TCHAR *tmp = NEWTSTR_ALLOCA(text);
+ mir_sntprintf(text, text_size, _T("%s: %s"), dbv.pszVal, tmp);
+ }
+ CopySkipUnprintableChars(text, text, text_size-1);
+ db_free(&dbv);
+ }
+ }
+ else if (use_name_and_message_for_xstatus && xstatus_has_priority) {
+ DBVARIANT dbv = {0};
+ // Try to get XStatusName
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusName", &dbv)) {
+ if (dbv.pszVal != NULL && dbv.pszVal[0] != 0)
+ mir_sntprintf(text, text_size, _T("%s"), dbv.pszVal);
+ CopySkipUnprintableChars(text, text, text_size-1);
+ db_free(&dbv);
+ }
+ }
+
+ if (text[0] == '\0') {
+ if (show_listening_if_no_away) {
+ Cache_GetLineText(pdnce, TEXT_LISTENING_TO, text, text_size, variable_text, xstatus_has_priority, 0, 0, use_name_and_message_for_xstatus, pdnce_time_show_only_if_different);
+ if (text[0] != '\0')
+ return TEXT_LISTENING_TO;
+ }
+
+ if (show_status_if_no_away) {
+ //re-request status if no away
+ return Cache_GetLineText(pdnce, TEXT_STATUS, text, text_size, variable_text, xstatus_has_priority, 0, 0, use_name_and_message_for_xstatus, pdnce_time_show_only_if_different);
+ }
+ }
+ return TEXT_STATUS_MESSAGE;
+
+ case TEXT_LISTENING_TO:
+ GetListeningTo(text, text_size, pdnce);
+ return TEXT_LISTENING_TO;
+
+ case TEXT_TEXT:
+ {
+ TCHAR *tmp = variables_parsedup(variable_text, pdnce->tszName, pdnce->hContact);
+ lstrcpyn(text, tmp, text_size);
+ mir_free(tmp);
+ CopySkipUnprintableChars(text, text, text_size-1);
+ }
+ return TEXT_TEXT;
+
+ case TEXT_CONTACT_TIME:
+ if (pdnce->hTimeZone) {
+ // Get pdnce time
+ text[0] = 0;
+ tmi.printDateTime( pdnce->hTimeZone, _T("t"), text, text_size, 0);
+ }
+
+ return TEXT_CONTACT_TIME;
+ }
+
+ return TEXT_EMPTY;
+}
+
+/*
+* Get the text for First Line
+*/
+void Cache_GetFirstLineText(struct ClcData *dat, struct ClcContact *contact)
+{
+ if (GetCurrentThreadId() != g_dwMainThreadID)
+ return;
+
+ PDNCE pdnce = (PDNCE)pcli->pfnGetCacheEntry(contact->hContact);
+ TCHAR *name = pcli->pfnGetContactDisplayName(contact->hContact,0);
+ if (dat->first_line_append_nick && (!dat->force_in_dialog)) {
+ DBVARIANT dbv = {0};
+ if ( !DBGetContactSettingTString(pdnce->hContact, pdnce->m_cache_cszProto, "Nick", &dbv)) {
+ TCHAR nick[SIZEOF(contact->szText)];
+ lstrcpyn(nick, dbv.ptszVal, SIZEOF(contact->szText));
+ db_free(&dbv);
+
+ // They are the same -> use the name to keep the case
+ if (_tcsicmp(name, nick) == 0)
+ lstrcpyn(contact->szText, name, SIZEOF(contact->szText));
+ else
+ // Append then
+ mir_sntprintf(contact->szText, SIZEOF(contact->szText), _T("%s - %s"), name, nick);
+ }
+ else lstrcpyn(contact->szText, name, SIZEOF(contact->szText));
+ }
+ else lstrcpyn(contact->szText, name, SIZEOF(contact->szText));
+
+ if ( !dat->force_in_dialog) {
+ struct SHORTDATA data = {0};
+ Sync(CLUI_SyncGetShortData,(WPARAM)pcli->hwndContactTree,(LPARAM)&data);
+ contact->ssText.ReplaceSmileys(&data, pdnce, contact->szText, dat->first_line_draw_smileys);
+ }
+}
+
+/*
+* Get the text for Second Line
+*/
+
+void Cache_GetSecondLineText(struct SHORTDATA *dat, PDNCE pdnce)
+{
+ TCHAR Text[240-MAXEXTRACOLUMNS] = {0};
+ int type = TEXT_EMPTY;
+
+ if (dat->second_line_show)
+ type = Cache_GetLineText(pdnce, dat->second_line_type, (TCHAR*)Text, SIZEOF(Text), dat->second_line_text,
+ dat->second_line_xstatus_has_priority,dat->second_line_show_status_if_no_away,dat->second_line_show_listening_if_no_away,
+ dat->second_line_use_name_and_message_for_xstatus, dat->contact_time_show_only_if_different);
+ Text[SIZEOF(Text)-1] = 0; //to be sure that it is null terminated string
+
+ mir_free(pdnce->szSecondLineText);
+
+ if (dat->second_line_show)// Text[0] != '\0')
+ pdnce->szSecondLineText = mir_tstrdup((TCHAR*)Text);
+ else
+ pdnce->szSecondLineText = NULL;
+
+ if (pdnce->szSecondLineText) {
+ if (type == TEXT_LISTENING_TO && pdnce->szSecondLineText[0] != _T('\0'))
+ pdnce->ssSecondLine.AddListeningToIcon(dat, pdnce, pdnce->szSecondLineText, dat->second_line_draw_smileys);
+ else
+ pdnce->ssSecondLine.ReplaceSmileys(dat, pdnce, pdnce->szSecondLineText, dat->second_line_draw_smileys);
+ }
+}
+
+/*
+* Get the text for Third Line
+*/
+void Cache_GetThirdLineText(struct SHORTDATA *dat, PDNCE pdnce)
+{
+ TCHAR Text[240-MAXEXTRACOLUMNS] = {0};
+ int type = TEXT_EMPTY;
+ if (dat->third_line_show)
+ type = Cache_GetLineText(pdnce, dat->third_line_type,(TCHAR*)Text, SIZEOF(Text), dat->third_line_text,
+ dat->third_line_xstatus_has_priority,dat->third_line_show_status_if_no_away,dat->third_line_show_listening_if_no_away,
+ dat->third_line_use_name_and_message_for_xstatus, dat->contact_time_show_only_if_different);
+
+ Text[SIZEOF(Text)-1] = 0; //to be sure that it is null terminated string
+
+ mir_free(pdnce->szThirdLineText);
+
+ if (dat->third_line_show)//Text[0] != '\0')
+ pdnce->szThirdLineText = mir_tstrdup((TCHAR*)Text);
+ else
+ pdnce->szThirdLineText = NULL;
+
+ if (pdnce->szThirdLineText) {
+ if (type == TEXT_LISTENING_TO && pdnce->szThirdLineText[0] != _T('\0'))
+ pdnce->ssThirdLine.AddListeningToIcon(dat, pdnce, pdnce->szThirdLineText, dat->third_line_draw_smileys);
+ else
+ pdnce->ssThirdLine.ReplaceSmileys(dat, pdnce, pdnce->szThirdLineText, dat->third_line_draw_smileys);
+ }
+}
+
+void RemoveTag(TCHAR *to, TCHAR *tag)
+{
+ TCHAR * st = to;
+ int len = (int)_tcslen(tag);
+ int lastsize = (int)_tcslen(to)+1;
+ while (st = _tcsstr(st,tag)) {
+ lastsize -= len;
+ memmove((void*)st,(void*)(st+len),(lastsize)*sizeof(TCHAR));
+ }
+}
+
+/*
+* Copy string with removing Escape chars from text
+* And BBcodes
+*/
+static int CopySkipUnprintableChars(TCHAR *to, TCHAR * buf, DWORD size)
+{
+ DWORD i;
+ BOOL keep = 0;
+ TCHAR * cp = to;
+ if ( !to) return 0;
+ if ( !buf) {
+ to[0] = '\0';
+ return 0;
+ }
+
+ for (i=0; i < size; i++) {
+ if (buf[i] == 0) break;
+ if (buf[i] > 0 && buf[i] < ' ') {
+ *cp = ' ';
+ if ( !keep) cp++;
+ keep = 1;
+ }
+ else {
+ keep = 0;
+ *cp = buf[i];
+ cp++;
+ }
+ }
+ *cp = 0;
+
+ //remove bbcodes: [b] [i] [u] <b> <i> <u>
+ RemoveTag(to,_T("[b]")); RemoveTag(to,_T("[/b]"));
+ RemoveTag(to,_T("[u]")); RemoveTag(to,_T("[/u]"));
+ RemoveTag(to,_T("[i]")); RemoveTag(to,_T("[/i]"));
+
+ RemoveTag(to,_T("<b>")); RemoveTag(to,_T("</b>"));
+ RemoveTag(to,_T("<u>")); RemoveTag(to,_T("</u>"));
+ RemoveTag(to,_T("<i>")); RemoveTag(to,_T("</i>"));
+
+ RemoveTag(to,_T("[B]")); RemoveTag(to,_T("[/b]"));
+ RemoveTag(to,_T("[U]")); RemoveTag(to,_T("[/u]"));
+ RemoveTag(to,_T("[I]")); RemoveTag(to,_T("[/i]"));
+
+ RemoveTag(to,_T("<B>")); RemoveTag(to,_T("</B>"));
+ RemoveTag(to,_T("<U>")); RemoveTag(to,_T("</U>"));
+ RemoveTag(to,_T("<I>")); RemoveTag(to,_T("</I>"));
+ return i;
+}
+
+// If ExecuteOnAllContactsFuncPtr returns FALSE, stop loop
+// Return TRUE if finished, FALSE if was stoped
+static BOOL ExecuteOnAllContacts(struct ClcData *dat, ExecuteOnAllContactsFuncPtr func, void *param)
+{
+ BOOL res;
+ res = ExecuteOnAllContactsOfGroup(&dat->list, func, param);
+ return res;
+}
+
+static BOOL ExecuteOnAllContactsOfGroup(struct ClcGroup *group, ExecuteOnAllContactsFuncPtr func, void *param)
+{
+ if ( !group)
+ return TRUE;
+
+ for (int scanIndex = 0 ; scanIndex < group->cl.count ; scanIndex++) {
+ if (group->cl.items[scanIndex]->type == CLCIT_CONTACT) {
+ if ( !func(group->cl.items[scanIndex], FALSE, param))
+ return FALSE;
+
+ if (group->cl.items[scanIndex]->SubAllocated > 0) {
+ for (int i=0 ; i < group->cl.items[scanIndex]->SubAllocated ; i++)
+ if ( !func(&group->cl.items[scanIndex]->subcontacts[i], TRUE, param))
+ return FALSE;
+ }
+ }
+ else if (group->cl.items[scanIndex]->type == CLCIT_GROUP)
+ if ( !ExecuteOnAllContactsOfGroup(group->cl.items[scanIndex]->group, func, param))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+* Avatar working routines
+*/
+BOOL UpdateAllAvatarsProxy(struct ClcContact *contact, BOOL subcontact, void *param)
+{
+ Cache_GetAvatar((struct ClcData *)param, contact);
+ return TRUE;
+}
+
+void UpdateAllAvatars(struct ClcData *dat)
+{
+ ExecuteOnAllContacts(dat,UpdateAllAvatarsProxy,dat);
+}
+
+BOOL ReduceAvatarPosition(struct ClcContact *contact, BOOL subcontact, void *param)
+{
+ if (contact->avatar_pos >= *((int *)param))
+ contact->avatar_pos--;
+
+ return TRUE;
+}
+
+void Cache_ProceedAvatarInList(struct ClcData *dat, struct ClcContact *contact)
+{
+ struct avatarCacheEntry * ace = contact->avatar_data;
+ int old_pos = contact->avatar_pos;
+
+ if (ace == NULL || ace->dwFlags == AVS_BITMAP_EXPIRED || ace->hbmPic == NULL) {
+ //Avatar was not ready or removed - need to remove it from cache
+ if (old_pos >= 0) {
+ ImageArray_RemoveImage(&dat->avatar_cache, old_pos);
+ // Update all items
+ ExecuteOnAllContacts(dat, ReduceAvatarPosition, (void *)&old_pos);
+ contact->avatar_pos = AVATAR_POS_DONT_HAVE;
+ return;
+ }
+ }
+ else if (contact->avatar_data->hbmPic != NULL) //Lets Add it
+ {
+ // Make bounds -> keep aspect radio
+ LONG width_clip;
+ LONG height_clip;
+ RECT rc = {0};
+
+ // Clipping width and height
+ width_clip = dat->avatars_maxwidth_size?dat->avatars_maxwidth_size:dat->avatars_maxheight_size;
+ height_clip = dat->avatars_maxheight_size;
+
+ if (height_clip * ace->bmWidth / ace->bmHeight <= width_clip)
+ width_clip = height_clip * ace->bmWidth / ace->bmHeight;
+ else
+ height_clip = width_clip * ace->bmHeight / ace->bmWidth;
+
+ if (wildcmpi(contact->avatar_data->szFilename,_T("*.gif"))) {
+ if (old_pos == AVATAR_POS_ANIMATED)
+ AniAva_RemoveAvatar(contact->hContact);
+
+ int res = AniAva_AddAvatar(contact->hContact, contact->avatar_data->szFilename, width_clip, height_clip);
+ if (res) {
+ contact->avatar_pos = AVATAR_POS_ANIMATED;
+ contact->avatar_size.cy = HIWORD(res);
+ contact->avatar_size.cx = LOWORD(res);
+ return;
+ }
+ }
+
+ // Create objs
+ void * pt;
+ HDC hdc = CreateCompatibleDC(dat->avatar_cache.hdc);
+ HBITMAP hDrawBmp = ske_CreateDIB32Point(width_clip, height_clip,&pt);
+ HBITMAP oldBmp = (HBITMAP)SelectObject(hdc, hDrawBmp);
+ //need to draw avatar bitmap here
+ {
+ RECT real_rc = {0,0,width_clip, height_clip};
+
+ int w = width_clip;
+ int h = height_clip;
+ if ( !g_CluiData.fGDIPlusFail) //Use gdi+ engine
+ DrawAvatarImageWithGDIp(hdc, 0, 0, w, h,ace->hbmPic,0,0,ace->bmWidth,ace->bmHeight,ace->dwFlags,255);
+ else {
+ if ( !(ace->dwFlags & AVS_PREMULTIPLIED)) {
+ HDC hdcTmp = CreateCompatibleDC(hdc);
+ RECT r = {0,0,w,h};
+ HDC hdcTmp2 = CreateCompatibleDC(hdc);
+ HBITMAP bmo = (HBITMAP)SelectObject(hdcTmp,ace->hbmPic);
+ HBITMAP b2 = ske_CreateDIB32(w,h);
+ HBITMAP bmo2 = (HBITMAP)SelectObject(hdcTmp2,b2);
+ SetStretchBltMode(hdcTmp, HALFTONE);
+ SetStretchBltMode(hdcTmp2, HALFTONE);
+ StretchBlt(hdcTmp2, 0, 0, w, h,
+ hdcTmp, 0, 0, ace->bmWidth, ace->bmHeight,
+ SRCCOPY);
+
+ ske_SetRectOpaque(hdcTmp2,&r);
+ BitBlt(hdc, rc.left, rc.top, w, h,hdcTmp2,0,0,SRCCOPY);
+ SelectObject(hdcTmp2,bmo2);
+ SelectObject(hdcTmp,bmo);
+ mod_DeleteDC(hdcTmp);
+ mod_DeleteDC(hdcTmp2);
+ DeleteObject(b2);
+ }
+ else {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0,255, AC_SRC_ALPHA };
+ HDC hdcTempAv = CreateCompatibleDC(hdc);
+ HBITMAP hbmTempAvOld;
+ hbmTempAvOld = (HBITMAP)SelectObject(hdcTempAv,ace->hbmPic);
+ ske_AlphaBlend(hdc, rc.left, rc.top, w, h, hdcTempAv, 0, 0,ace->bmWidth,ace->bmHeight, bf);
+ SelectObject(hdcTempAv, hbmTempAvOld);
+ mod_DeleteDC(hdcTempAv);
+ }
+ }
+ }
+ SelectObject(hdc,oldBmp);
+ DeleteDC(hdc);
+ // Add to list
+ if (old_pos >= 0) {
+ ImageArray_ChangeImage(&dat->avatar_cache, hDrawBmp, old_pos);
+ contact->avatar_pos = old_pos;
+ }
+ else contact->avatar_pos = ImageArray_AddImage(&dat->avatar_cache, hDrawBmp, -1);
+
+ if (old_pos == AVATAR_POS_ANIMATED && contact->avatar_pos != AVATAR_POS_ANIMATED)
+ AniAva_RemoveAvatar(contact->hContact);
+
+ DeleteObject(hDrawBmp);
+ }
+}
+
+void Cache_GetAvatar(struct ClcData *dat, struct ClcContact *contact)
+{
+ int old_pos = contact->avatar_pos;
+ if (g_CluiData.bSTATE != STATE_NORMAL
+ || (dat->use_avatar_service && !ServiceExists(MS_AV_GETAVATARBITMAP))) // workaround for avatar service and other wich destroys service on OK_TOEXIT
+ {
+ contact->avatar_pos = AVATAR_POS_DONT_HAVE;
+ contact->avatar_data = NULL;
+ return;
+ }
+ if (dat->use_avatar_service && ServiceExists(MS_AV_GETAVATARBITMAP))
+ {
+ if (dat->avatars_show && !db_get_b(contact->hContact, "CList", "HideContactAvatar", 0))
+ {
+ contact->avatar_data = (struct avatarCacheEntry *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)contact->hContact, 0);
+ if (contact->avatar_data == NULL || contact->avatar_data->cbSize != sizeof(struct avatarCacheEntry)
+ || contact->avatar_data->dwFlags == AVS_BITMAP_EXPIRED)
+ {
+ contact->avatar_data = NULL;
+ }
+
+ if (contact->avatar_data != NULL)
+ {
+ contact->avatar_data->t_lastAccess = (DWORD)time(NULL);
+ }
+ }
+ else
+ {
+ contact->avatar_data = NULL;
+ }
+ Cache_ProceedAvatarInList(dat, contact);
+ }
+ else
+ {
+ contact->avatar_pos = AVATAR_POS_DONT_HAVE;
+ if (dat->avatars_show && !db_get_b(contact->hContact, "CList", "HideContactAvatar", 0))
+ {
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingTString(contact->hContact, "ContactPhoto", "File", &dbv))
+ {
+ HBITMAP hBmp = (HBITMAP) CallService(MS_UTILS_LOADBITMAPT, 0, (LPARAM)dbv.ptszVal);
+ if (hBmp != NULL)
+ {
+ // Make bounds
+ BITMAP bm;
+ if (GetObject(hBmp,sizeof(BITMAP),&bm))
+ {
+ // Create data...
+ HDC hdc;
+ HBITMAP hDrawBmp,oldBmp;
+
+ // Make bounds -> keep aspect radio
+ LONG width_clip;
+ LONG height_clip;
+ RECT rc = {0};
+
+ // Clipping width and height
+ width_clip = dat->avatars_maxheight_size;
+ height_clip = dat->avatars_maxheight_size;
+
+ if (height_clip * bm.bmWidth / bm.bmHeight <= width_clip)
+ {
+ width_clip = height_clip * bm.bmWidth / bm.bmHeight;
+ }
+ else
+ {
+ height_clip = width_clip * bm.bmHeight / bm.bmWidth;
+ }
+
+ // Create objs
+ hdc = CreateCompatibleDC(dat->avatar_cache.hdc);
+ hDrawBmp = ske_CreateDIB32(width_clip, height_clip);
+ oldBmp = (HBITMAP)SelectObject(hdc, hDrawBmp);
+ SetBkMode(hdc,TRANSPARENT);
+ {
+ POINT org;
+ GetBrushOrgEx(hdc, &org);
+ SetStretchBltMode(hdc, HALFTONE);
+ SetBrushOrgEx(hdc, org.x, org.y, NULL);
+ }
+
+ rc.right = width_clip - 1;
+ rc.bottom = height_clip - 1;
+
+ // Draw bitmap 8//8
+ {
+ HDC dcMem = CreateCompatibleDC(hdc);
+ HBITMAP obmp = (HBITMAP)SelectObject(dcMem, hBmp);
+ StretchBlt(hdc, 0, 0, width_clip, height_clip,dcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
+ SelectObject(dcMem,obmp);
+ mod_DeleteDC(dcMem);
+ }
+ {
+ RECT rtr = {0};
+ rtr.right = width_clip+1;
+ rtr.bottom = height_clip+1;
+ ske_SetRectOpaque(hdc,&rtr);
+ }
+
+ hDrawBmp = (HBITMAP)GetCurrentObject(hdc, OBJ_BITMAP);
+ SelectObject(hdc,oldBmp);
+ mod_DeleteDC(hdc);
+
+ // Add to list
+ if (old_pos >= 0)
+ {
+ ImageArray_ChangeImage(&dat->avatar_cache, hDrawBmp, old_pos);
+ contact->avatar_pos = old_pos;
+ }
+ else
+ {
+ contact->avatar_pos = ImageArray_AddImage(&dat->avatar_cache, hDrawBmp, -1);
+ }
+
+ DeleteObject(hDrawBmp);
+ } // if (GetObject(hBmp,sizeof(BITMAP),&bm))
+ DeleteObject(hBmp);
+ } //if (hBmp != NULL)
+ }
+ db_free(&dbv);
+ }
+
+ // Remove avatar if needed
+ if (old_pos >= 0 && contact->avatar_pos == AVATAR_POS_DONT_HAVE)
+ {
+ ImageArray_RemoveImage(&dat->avatar_cache, old_pos);
+ // Update all items
+ ExecuteOnAllContacts(dat, ReduceAvatarPosition, (void *)&old_pos);
+ }
+ if (old_pos == AVATAR_POS_ANIMATED && contact->avatar_pos != AVATAR_POS_ANIMATED)
+ {
+ AniAva_RemoveAvatar( contact->hContact );
+ }
+ }
+}
diff --git a/plugins/Clist_modern/src/modern_callproc.cpp b/plugins/Clist_modern/src/modern_callproc.cpp
new file mode 100644
index 0000000000..ab26eb03eb
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_callproc.cpp
@@ -0,0 +1,20 @@
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_callproc.h"
+
+//////////////////////////////////////////////////////////////////////////
+// standard callback proc
+int CALLBACK __DoCallBack( LPARAM pvStorage)
+{
+ call::__baseCall * storage = (call::__baseCall *) pvStorage;
+ int res=storage->__DoCallStorageProc();
+ delete storage;
+ return res;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// To do: Replace __ProcessCall to switching threads etc
+// and specify _DoCallback as callback
+int call::__ProcessCall( __baseCall * pStorage, ASYNC_T async )
+{
+ return __DoCallBack( (LPARAM)pStorage);
+}
diff --git a/plugins/Clist_modern/src/modern_clc.cpp b/plugins/Clist_modern/src/modern_clc.cpp
new file mode 100644
index 0000000000..57d4da274b
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clc.cpp
@@ -0,0 +1,2107 @@
+// refactored step 1.
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/************************************************************************/
+/* Module responsible for working with contact list control */
+/************************************************************************/
+
+#include "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "m_skin.h"
+#include "hdr/modern_commonprototypes.h"
+
+#include "hdr/modern_clc.h"
+#include "hdr/modern_clist.h"
+#include "hdr/modern_clcpaint.h"
+
+#include "m_modernopt.h"
+
+int ModernOptInit(WPARAM wParam,LPARAM lParam);
+int ModernSkinOptInit(WPARAM wParam,LPARAM lParam);
+
+/*
+* Private module variables
+*/
+static HANDLE hShowInfoTipEvent;
+static POINT HitPoint;
+static BOOL fMouseUpped;
+static BYTE IsDragToScrollMode = 0;
+static int StartDragPos = 0;
+static int StartScrollPos = 0;
+HANDLE hSmileyAddOptionsChangedHook = NULL;
+HANDLE hIconChangedHook = NULL;
+HANDLE hAckHook = NULL;
+HANDLE hAvatarChanged = NULL;
+static BOOL g_bSortTimerIsSet = FALSE;
+static struct ClcContact * hitcontact = NULL;
+
+
+static int clcHookSmileyAddOptionsChanged(WPARAM wParam,LPARAM lParam);
+static int clcHookIconsChanged(WPARAM wParam, LPARAM lParam);
+static int clcHookBkgndConfigChanged(WPARAM wParam,LPARAM lParam);
+static int clcProceedDragToScroll(HWND hwnd, int Y);
+static int clcExitDragToScroll();
+
+
+static int clcHookModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ if (MirandaExiting())
+ return 0;
+
+ HookEvent(ME_MODERNOPT_INITIALIZE,ModernOptInit);
+ HookEvent(ME_MODERNOPT_INITIALIZE,ModernSkinOptInit);
+
+ if (ServiceExists(MS_MC_DISABLEHIDDENGROUP))
+ CallService(MS_MC_DISABLEHIDDENGROUP, (WPARAM)TRUE, (LPARAM)0);
+ if (ServiceExists(MS_MC_GETPROTOCOLNAME))
+ g_szMetaModuleName = (char *)CallService(MS_MC_GETPROTOCOLNAME, 0, 0);
+
+ // Get icons
+ int i;
+
+ TCHAR szMyPath[MAX_PATH];
+ GetModuleFileName(g_hInst, szMyPath, SIZEOF(szMyPath));
+
+ SKINICONDESC sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.cx = 16;
+ sid.cy = 16;
+ sid.ptszDefaultFile = szMyPath;
+ sid.flags = SIDF_PATH_TCHAR;
+
+ sid.pszSection = LPGEN("Contact List");
+ sid.pszDescription = LPGEN("Listening to");
+ sid.pszName = "LISTENING_TO_ICON";
+ sid.iDefaultIndex = - IDI_LISTENING_TO;
+ Skin_AddIcon(&sid);
+
+ sid.pszSection = LPGEN("Contact List/Avatar Overlay");
+ for (i=0; i < MAX_REGS(g_pAvatarOverlayIcons) ; i++) {
+ sid.pszDescription = g_pAvatarOverlayIcons[i].description;
+ sid.pszName = g_pAvatarOverlayIcons[i].name;
+ sid.iDefaultIndex = - g_pAvatarOverlayIcons[i].id;
+ Skin_AddIcon(&sid);
+ }
+
+ sid.pszSection = LPGEN("Contact List/Status Overlay");
+ for (i=0; i < MAX_REGS(g_pStatusOverlayIcons); i++) {
+ sid.pszDescription = g_pStatusOverlayIcons[i].description;
+ sid.pszName = g_pStatusOverlayIcons[i].name;
+ sid.iDefaultIndex = - g_pStatusOverlayIcons[i].id;
+ Skin_AddIcon(&sid);
+ }
+
+ clcHookIconsChanged(0,0);
+
+ hIconChangedHook = HookEvent(ME_SKIN2_ICONSCHANGED, clcHookIconsChanged);
+
+ // Register smiley category
+ if (ServiceExists(MS_SMILEYADD_REGISTERCATEGORY)) {
+ SMADD_REGCAT rc;
+
+ rc.cbSize = sizeof(rc);
+ rc.name = "clist";
+ rc.dispname = Translate("Contact List smileys");
+
+ CallService(MS_SMILEYADD_REGISTERCATEGORY, 0, (LPARAM)&rc);
+
+ hSmileyAddOptionsChangedHook = HookEvent(ME_SMILEYADD_OPTIONSCHANGED,clcHookSmileyAddOptionsChanged);
+ }
+
+ CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"List Background/CLC",0);
+ CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"Menu Background/Menu",0);
+ CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"StatusBar Background/StatusBar",0);
+ CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"Frames TitleBar BackGround/FrameTitleBar",0);
+
+ HookEvent(ME_BACKGROUNDCONFIG_CHANGED,clcHookBkgndConfigChanged);
+ HookEvent(ME_BACKGROUNDCONFIG_CHANGED,BgStatusBarChange);
+ HookEvent(ME_BACKGROUNDCONFIG_CHANGED,OnFrameTitleBarBackgroundChange);
+ HookEvent(ME_COLOUR_RELOAD, OnFrameTitleBarBackgroundChange);
+
+ AniAva_UpdateOptions();
+ return 0;
+}
+
+static int clcHookSmileyAddOptionsChanged(WPARAM wParam,LPARAM lParam)
+{
+ if (MirandaExiting()) return 0;
+ pcli->pfnClcBroadcast( CLM_AUTOREBUILD,0,0);
+ pcli->pfnClcBroadcast( INTM_INVALIDATE,0,0);
+ return 0;
+}
+
+static int clcHookProtoAck(WPARAM wParam,LPARAM lParam)
+{
+ return ClcDoProtoAck((HANDLE) wParam,(ACKDATA*) lParam);
+}
+static int clcHookIconsChanged(WPARAM wParam, LPARAM lParam)
+{
+ int i;
+ if (MirandaExiting()) return 0;
+ for (i=0 ; i < MAX_REGS(g_pAvatarOverlayIcons) ; i++)
+ {
+ g_pAvatarOverlayIcons[i].listID = -1;
+ g_pStatusOverlayIcons[i].listID = -1;
+ }
+ if (hAvatarOverlays) ImageList_Destroy(hAvatarOverlays);
+ hAvatarOverlays = ImageList_Create(16,16,ILC_MASK|ILC_COLOR32,MAX_REGS(g_pAvatarOverlayIcons)*2,1);
+ for (i=0 ; i < MAX_REGS(g_pAvatarOverlayIcons) ; i++)
+ {
+ HICON hIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)g_pAvatarOverlayIcons[i].name);
+ g_pAvatarOverlayIcons[i].listID = ImageList_AddIcon(hAvatarOverlays,hIcon);
+ CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)g_pAvatarOverlayIcons[i].name);
+
+ hIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)g_pStatusOverlayIcons[i].name);
+ g_pStatusOverlayIcons[i].listID = ImageList_AddIcon(hAvatarOverlays,hIcon);
+ CallService(MS_SKIN2_RELEASEICON, 0, (LPARAM)g_pStatusOverlayIcons[i].name);
+ }
+
+ g_hListeningToIcon = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"LISTENING_TO_ICON");
+
+ pcli->pfnClcBroadcast( INTM_INVALIDATE,0,0);
+ AniAva_UpdateOptions();
+ return 0;
+}
+
+static int clcHookSettingChanged(WPARAM wParam,LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam;
+ if (MirandaExiting()) return 0;
+ if ((HANDLE)wParam == NULL)
+ {
+ if (g_szMetaModuleName && !mir_strcmp(cws->szModule, g_szMetaModuleName))
+ {
+ if ( !mir_strcmp(cws->szSetting, "Enabled"))
+ pcli->pfnClcBroadcast( INTM_RELOADOPTIONS, wParam, lParam);
+ }
+ else if ( !mir_strcmp(cws->szModule, "CListGroups"))
+ {
+ pcli->pfnClcBroadcast( INTM_GROUPSCHANGED,wParam,lParam);
+ }
+ else if ( !strcmp(cws->szSetting,"XStatusId") || !strcmp(cws->szSetting,"XStatusName"))
+ {
+ CLUIServices_ProtocolStatusChanged(0,(LPARAM)cws->szModule);
+ }
+ }
+ else // (HANDLE)wParam != NULL
+ {
+ if ( !strcmp(cws->szSetting,"TickTS"))
+ {
+ pcli->pfnClcBroadcast( INTM_STATUSCHANGED,wParam,0);
+ }
+ else if (g_szMetaModuleName && !strcmp(cws->szModule,g_szMetaModuleName))
+ {
+ if ( !strcmp(cws->szSetting,"Handle"))
+ {
+ pcli->pfnClcBroadcast( INTM_NAMEORDERCHANGED,0,0);
+ }
+ else if ( !strcmp(cws->szSetting,"Default"))
+ {
+ pcli->pfnClcBroadcast( INTM_NAMEORDERCHANGED,0,0);
+ }
+ }
+ else if ( !strcmp(cws->szModule,"UserInfo"))
+ {
+ if ( !strcmp(cws->szSetting,"Timezone"))
+ pcli->pfnClcBroadcast( INTM_TIMEZONECHANGED,wParam,0);
+ }
+ else if ( !strcmp(cws->szModule,"CList"))
+ {
+ if ( !strcmp(cws->szSetting,"StatusMsg"))
+ pcli->pfnClcBroadcast( INTM_STATUSMSGCHANGED,wParam,0);
+
+ }
+ else if ( !strcmp(cws->szModule,"ContactPhoto"))
+ {
+ if ( !strcmp(cws->szSetting,"File"))
+ pcli->pfnClcBroadcast( INTM_AVATARCHANGED,wParam,0);
+ }
+ else
+ {
+ if ((!strcmp(cws->szSetting,"XStatusName") || !strcmp(cws->szSetting,"XStatusMsg")))
+ pcli->pfnClcBroadcast( INTM_STATUSMSGCHANGED,wParam,0);
+ else if ( !strcmp(cws->szSetting,"XStatusId"))
+ pcli->pfnClcBroadcast( INTM_STATUSCHANGED,wParam,0);
+ else if ( !strcmp(cws->szSetting,"Timezone"))
+ pcli->pfnClcBroadcast( INTM_TIMEZONECHANGED,wParam,0);
+ else if ( !strcmp(cws->szSetting,"ListeningTo"))
+ pcli->pfnClcBroadcast( INTM_STATUSMSGCHANGED,wParam,0);
+ else if ( !strcmp(cws->szSetting,"Transport") || !strcmp(cws->szSetting,"IsTransported")) {
+ pcli->pfnInvalidateDisplayNameCacheEntry((HANDLE)wParam);
+ pcli->pfnClcBroadcast( CLM_AUTOREBUILD,wParam,0);
+ }
+ }
+ }
+ return 0;
+}
+
+static int clcHookDbEventAdded(WPARAM wParam,LPARAM lParam)
+{
+ DBEVENTINFO dbei = {0};
+ g_CluiData.t_now = time(NULL);
+ if (wParam && lParam)
+ {
+ dbei.cbSize = sizeof(dbei);
+ dbei.pBlob = 0;
+ dbei.cbBlob = 0;
+ CallService(MS_DB_EVENT_GET, (WPARAM)lParam, (LPARAM)&dbei);
+ if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT))
+ {
+ PDNCE pdnce = (PDNCE)pcli->pfnGetCacheEntry((HANDLE)wParam);
+ db_set_dw((HANDLE)wParam, "CList", "mf_lastmsg", dbei.timestamp);
+ if (pdnce)
+ pdnce->dwLastMsgTime = dbei.timestamp;
+ }
+ }
+ return 0;
+}
+
+static int clcHookBkgndConfigChanged(WPARAM wParam,LPARAM lParam)
+{
+ pcli->pfnClcOptionsChanged();
+ return 0;
+}
+
+static int clcHookAvatarChanged(WPARAM wParam, LPARAM lParam)
+{
+ if (MirandaExiting()) return 0;
+ pcli->pfnClcBroadcast(INTM_AVATARCHANGED, wParam, lParam);
+ return 0;
+}
+
+static int clcExitDragToScroll()
+{
+ if ( !IsDragToScrollMode) return 0;
+ IsDragToScrollMode = 0;
+ ReleaseCapture();
+ return 1;
+}
+
+static int clcProceedDragToScroll(HWND hwnd, int Y)
+{
+ int pos,dy;
+ if ( !IsDragToScrollMode) return 0;
+ if (GetCapture() != hwnd) clcExitDragToScroll();
+ dy = StartDragPos-Y;
+ pos = StartScrollPos+dy;
+ if (pos < 0)
+ pos = 0;
+ SendMessage(hwnd, WM_VSCROLL,MAKEWPARAM(SB_THUMBTRACK,pos),0);
+ return 1;
+}
+
+
+
+static int clcSearchNextContact(HWND hwnd, struct ClcData *dat, int index, const TCHAR *text, int prefixOk, BOOL fSearchUp)
+{
+ struct ClcGroup *group = &dat->list;
+ int testlen = lstrlen(text);
+ BOOL fReturnAsFound = FALSE;
+ int nLastFound = -1;
+ if (index == -1) fReturnAsFound = TRUE;
+ group->scanIndex = 0;
+ for (;;)
+ {
+ if (group->scanIndex == group->cl.count)
+ {
+ group = group->parent;
+ if (group == NULL)
+ break;
+ group->scanIndex++;
+ continue;
+ }
+ if (group->cl.items[group->scanIndex]->type != CLCIT_DIVIDER)
+ {
+ if ((prefixOk && CSTR_EQUAL == CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, text, -1, group->cl.items[group->scanIndex]->szText, testlen)) ||
+ (!prefixOk && !lstrcmpi(text, group->cl.items[group->scanIndex]->szText)))
+ {
+ struct ClcGroup *contactGroup = group;
+ int contactScanIndex = group->scanIndex;
+ int foundindex;
+ for (; group; group = group->parent)
+ pcli->pfnSetGroupExpand(hwnd, dat, group, 1);
+ foundindex = pcli->pfnGetRowsPriorTo(&dat->list, contactGroup, contactScanIndex);
+ if (fReturnAsFound)
+ return foundindex;
+ else if (nLastFound != -1 && fSearchUp && foundindex == index)
+ return nLastFound;
+ else if ( !fSearchUp && foundindex == index)
+ fReturnAsFound = TRUE;
+ else
+ nLastFound = foundindex;
+ group = contactGroup;
+ group->scanIndex = contactScanIndex;
+ }
+ if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP)
+ {
+ if ( !(dat->exStyle & CLS_EX_QUICKSEARCHVISONLY) || group->cl.items[group->scanIndex]->group->expanded)
+ {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ continue;
+ }
+ }
+ }
+ group->scanIndex++;
+ }
+ return -1;
+}
+
+static BOOL clcItemNotHiddenOffline(struct ClcData * dat, struct ClcGroup* group, struct ClcContact * contact)
+{
+ PDNCE pdnce;
+
+ if ( !group) return FALSE;
+ if ( !contact) return FALSE;
+ if (group->hideOffline) return FALSE;
+ if (g_CluiData.bFilterEffective) return FALSE;
+
+ if (CLCItems_IsShowOfflineGroup(group)) return TRUE;
+
+ pdnce = (PDNCE)pcli->pfnGetCacheEntry( contact->hContact);
+ if ( !pdnce) return FALSE;
+ if (pdnce->m_cache_nNoHiddenOffline) return TRUE;
+
+ return FALSE;
+
+}
+static LRESULT clcOnCreate(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ dat = (struct ClcData*)mir_calloc(sizeof(struct ClcData));
+ SetWindowLongPtr(hwnd,0,(LONG_PTR)dat);
+ dat->hCheckBoxTheme = xpt_AddThemeHandle(hwnd, L"BUTTON");
+ dat->m_paintCouter = 0;
+ dat->hWnd = hwnd;
+ dat->use_avatar_service = ServiceExists(MS_AV_GETAVATARBITMAP);
+ if (dat->use_avatar_service)
+ {
+ if ( !hAvatarChanged)
+ hAvatarChanged = HookEvent(ME_AV_AVATARCHANGED, clcHookAvatarChanged);
+ }
+ //else
+ //{
+ ImageArray_Initialize(&dat->avatar_cache, FALSE, 20); //this array will be used to keep small avatars too
+ //}
+
+ RowHeights_Initialize(dat);
+
+ dat->NeedResort = 1;
+ dat->MetaIgnoreEmptyExtra = db_get_b(NULL,"CLC","MetaIgnoreEmptyExtra",SETTING_METAIGNOREEMPTYEXTRA_DEFAULT);
+
+ dat->IsMetaContactsEnabled = (!(GetWindowLongPtr(hwnd,GWL_STYLE)&CLS_MANUALUPDATE)) &&
+ g_szMetaModuleName && db_get_b(NULL,g_szMetaModuleName,"Enabled",1) && ServiceExists(MS_MC_GETDEFAULTCONTACT);
+
+ dat->expandMeta = db_get_b(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT);
+ dat->useMetaIcon = db_get_b(NULL,"CLC","Meta",SETTING_USEMETAICON_DEFAULT);
+ dat->drawOverlayedStatus = db_get_b(NULL,"CLC","DrawOverlayedStatus",SETTING_DRAWOVERLAYEDSTATUS_DEFAULT);
+ g_CluiData.bSortByOrder[0] = db_get_b(NULL,"CList","SortBy1",SETTING_SORTBY1_DEFAULT);
+ g_CluiData.bSortByOrder[1] = db_get_b(NULL,"CList","SortBy2",SETTING_SORTBY2_DEFAULT);
+ g_CluiData.bSortByOrder[2] = db_get_b(NULL,"CList","SortBy3",SETTING_SORTBY3_DEFAULT);
+ g_CluiData.fSortNoOfflineBottom = db_get_b(NULL,"CList","NoOfflineBottom",SETTING_NOOFFLINEBOTTOM_DEFAULT);
+ dat->menuOwnerID = -1;
+ dat->menuOwnerType = CLCIT_INVALID;
+ //InitDisplayNameCache(&dat->lCLCContactsCache);
+ //LoadCLCOptions(hwnd,dat);
+ corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ LoadCLCOptions(hwnd,dat);
+ if ( dat->contact_time_show || dat->second_line_type == TEXT_CONTACT_TIME || dat->third_line_type == TEXT_CONTACT_TIME )
+ CLUI_SafeSetTimer( hwnd, TIMERID_INVALIDATE, 5000, NULL );
+ else
+ KillTimer( hwnd, TIMERID_INVALIDATE );
+ //if (dat->force_in_dialog)
+ // pcli->pfnRebuildEntireList(hwnd,dat);
+ TRACE("Create New ClistControl TO END\r\n");
+ return 0;
+}
+
+
+
+static LRESULT clcOnHitTest(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ return DefWindowProc(hwnd,WM_NCHITTEST,wParam,lParam);
+}
+static LRESULT clcOnCommand(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct ClcContact *contact;
+ int hit = pcli->pfnGetRowByIndex(dat, dat->selection, &contact, NULL);
+ if (hit == -1) return 0;
+ if ( contact->type == CLCIT_CONTACT && CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM) contact->hContact)) return 0;
+
+ switch (LOWORD(wParam))
+ {
+ case POPUP_NEWSUBGROUP:
+ if (contact->type != CLCIT_GROUP)
+ return 0;
+ SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) & ~CLS_HIDEEMPTYGROUPS);
+ SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) | CLS_USEGROUPS);
+ CallService(MS_CLIST_GROUPCREATE, contact->groupId, 0);
+ return 0;
+ case POPUP_RENAMEGROUP:
+ pcli->pfnBeginRenameSelection(hwnd, dat);
+ return 0;
+ case POPUP_DELETEGROUP:
+ if (contact->type != CLCIT_GROUP)
+ return 0;
+ CallService(MS_CLIST_GROUPDELETE, contact->groupId, 0);
+ return 0;
+ case POPUP_GROUPSHOWOFFLINE:
+ if (contact->type != CLCIT_GROUP)
+ return 0;
+ CallService(MS_CLIST_GROUPSETFLAGS, contact->groupId,
+ MAKELPARAM(CLCItems_IsShowOfflineGroup(contact->group) ? 0 : GROUPF_SHOWOFFLINE, GROUPF_SHOWOFFLINE));
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD,0, 0);
+ return 0;
+ case POPUP_GROUPHIDEOFFLINE:
+ if (contact->type != CLCIT_GROUP)
+ return 0;
+ CallService(MS_CLIST_GROUPSETFLAGS, contact->groupId,
+ MAKELPARAM(contact->group->hideOffline ? 0 : GROUPF_HIDEOFFLINE, GROUPF_HIDEOFFLINE));
+ return 0;
+ }
+ if (contact->type == CLCIT_GROUP)
+ if (CallService(MO_PROCESSCOMMANDBYMENUIDENT,LOWORD(wParam),(LPARAM)hwnd))
+ return 0;
+ return 0;
+}
+
+static LRESULT clcOnSize(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+
+ pcli->pfnEndRename(hwnd,dat,1);
+ KillTimer(hwnd,TIMERID_INFOTIP);
+ KillTimer(hwnd,TIMERID_RENAME);
+ cliRecalcScrollBar(hwnd,dat);
+ if ( g_CluiData.fDisableSkinEngine || dat->force_in_dialog )
+ {
+ HBITMAP hBmp, hBmpMask, hoBmp, hoMaskBmp;
+ HDC hdc,hdcMem;
+ RECT rc = {0};
+ int depth;
+ HBRUSH hBrush;
+
+ GetClientRect(hwnd, &rc);
+ if (rc.right == 0)
+ return corecli.pfnContactListControlWndProc(hwnd,msg,wParam,lParam);;
+
+ rc.bottom = max ( dat->row_min_heigh, 1 );
+ //rc.bottom = 8;
+ //rc.right = 8;
+ hdc = GetDC(hwnd);
+ depth = GetDeviceCaps(hdc, BITSPIXEL);
+ if (depth < 16)
+ depth = 16;
+ hBmp = CreateBitmap(rc.right, rc.bottom, 1, depth, NULL);
+ hBmpMask = CreateBitmap(rc.right, rc.bottom, 1, 1, NULL);
+ hdcMem = CreateCompatibleDC(hdc);
+ hoBmp = (HBITMAP) SelectObject(hdcMem, hBmp);
+ hBrush = CreateSolidBrush(( dat->useWindowsColours || dat->force_in_dialog ) ? GetSysColor(COLOR_HIGHLIGHT) : dat->selBkColour);
+ FillRect(hdcMem, &rc, hBrush);
+ DeleteObject(hBrush);
+
+ hoMaskBmp = (HBITMAP)SelectObject(hdcMem, hBmpMask);
+ FillRect(hdcMem, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
+ SelectObject(hdcMem, hoMaskBmp);
+ SelectObject(hdcMem, hoBmp);
+ DeleteDC(hdcMem);
+ ReleaseDC(hwnd, hdc);
+ if (dat->himlHighlight)
+ ImageList_Destroy(dat->himlHighlight);
+ dat->himlHighlight = ImageList_Create(rc.right, rc.bottom, (IsWinVerXPPlus()? ILC_COLOR32 : ILC_COLOR16) | ILC_MASK, 1, 1);
+ ImageList_Add(dat->himlHighlight, hBmp, hBmpMask);
+ DeleteObject(hBmpMask);
+ DeleteObject(hBmp);
+ }
+ else if (dat->himlHighlight)
+ {
+ ImageList_Destroy(dat->himlHighlight);
+ dat->himlHighlight = NULL;
+ }
+ return 0;
+}
+
+static LRESULT clcOnChar(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (wParam == 27 && dat->szQuickSearch[0] == '\0') //escape and not quick search
+ {
+ // minimize clist
+ CListMod_HideWindow(pcli->hwndContactList, SW_HIDE);
+ }
+ return corecli.pfnContactListControlWndProc(hwnd,msg,wParam,lParam);
+}
+static LRESULT clcOnPaint(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HDC hdc;
+ PAINTSTRUCT ps;
+ if (IsWindowVisible(hwnd))
+ {
+ if ( !g_CluiData.fLayered || GetParent(hwnd) != pcli->hwndContactList)
+ {
+ hdc = BeginPaint(hwnd,&ps);
+ g_clcPainter.cliPaintClc(hwnd,dat,hdc,&ps.rcPaint);
+ EndPaint(hwnd,&ps);
+ }
+ else CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,(WPARAM)hwnd,0);
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+static LRESULT clcOnEraseBkGround(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ return 1;
+}
+
+static LRESULT clcOnKeyDown(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int selMoved = 0;
+ int changeGroupExpand = 0;
+ int pageSize;
+ if (wParam == VK_CONTROL)
+ return 0;
+ pcli->pfnHideInfoTip(hwnd,dat);
+
+ KillTimer(hwnd,TIMERID_INFOTIP);
+ KillTimer(hwnd,TIMERID_RENAME);
+
+ if (CallService(MS_CLIST_MENUPROCESSHOTKEY,wParam,MPCF_CONTACTMENU))
+ return 0;
+
+ {
+ RECT clRect;
+ GetClientRect(hwnd,&clRect);
+ if (dat->max_row_height) pageSize = clRect.bottom/dat->max_row_height;
+ else pageSize = 0;
+ }
+
+ switch(wParam)
+ {
+ case VK_DOWN:
+ case VK_UP:
+ {
+ if (dat->szQuickSearch[0] != '\0' && dat->selection != -1) //get next contact
+ {
+ //get next contact
+ int index = clcSearchNextContact(hwnd,dat,dat->selection,dat->szQuickSearch,1,(wParam == VK_UP));
+ if (index == -1)
+ {
+ MessageBeep(MB_OK);
+ return 0;
+ }
+ else
+ {
+ dat->selection = index;
+ pcli->pfnInvalidateRect(hwnd, NULL, FALSE);
+ pcli->pfnEnsureVisible(hwnd, dat, dat->selection, 0);
+ return 0;
+ }
+
+ }
+ else
+ {
+ if (wParam == VK_DOWN) dat->selection++;
+ if (wParam == VK_UP) dat->selection--;
+ selMoved = 1; break;
+ }
+ }
+ case VK_PRIOR: dat->selection -= pageSize; selMoved = 1; break;
+ case VK_NEXT: dat->selection += pageSize; selMoved = 1; break;
+ case VK_HOME: dat->selection = 0; selMoved = 1; break;
+ case VK_END: dat->selection = pcli->pfnGetGroupContentsCount(&dat->list,1)-1; selMoved = 1; break;
+ case VK_LEFT: changeGroupExpand = 1; break;
+ case VK_RIGHT: changeGroupExpand = 2; break;
+ case VK_RETURN: pcli->pfnDoSelectionDefaultAction(hwnd,dat); SetCapture(hwnd); return 0;
+ case VK_F2: cliBeginRenameSelection(hwnd,dat); /*SetCapture(hwnd);*/ return 0;
+ case VK_DELETE: pcli->pfnDeleteFromContactList(hwnd,dat); SetCapture(hwnd);return 0;
+ case VK_ESCAPE:
+ {
+ if ((dat->dragStage&DRAGSTAGEM_STAGE) == DRAGSTAGE_ACTIVE)
+ {
+ dat->iDragItem = -1;
+ dat->iInsertionMark = -1;
+ dat->dragStage = 0;
+ ReleaseCapture();
+ }
+ return 0;
+ }
+ default:
+ {
+ NMKEY nmkey;
+ nmkey.hdr.hwndFrom = hwnd;
+ nmkey.hdr.idFrom = GetDlgCtrlID(hwnd);
+ nmkey.hdr.code = NM_KEYDOWN;
+ nmkey.nVKey = wParam;
+ nmkey.uFlags = HIWORD(lParam);
+
+ if (SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nmkey))
+ {
+ SetCapture(hwnd);
+ return 0;
+ }
+ }
+ }
+ if (changeGroupExpand)
+ {
+ int hit;
+ struct ClcContact *contact;
+ struct ClcGroup *group;
+ dat->szQuickSearch[0] = 0;
+ hit = cliGetRowByIndex(dat,dat->selection,&contact,&group);
+ if (hit != -1)
+ {
+ if (contact->type == CLCIT_CONTACT && (contact->isSubcontact || contact->SubAllocated>0))
+ {
+ if (contact->isSubcontact && changeGroupExpand == 1)
+ {
+ dat->selection -= contact->isSubcontact;
+ selMoved = 1;
+ }
+ else if ( !contact->isSubcontact && contact->SubAllocated>0)
+ {
+ if (changeGroupExpand == 1 && !contact->SubExpanded)
+ {
+ dat->selection = cliGetRowsPriorTo(&dat->list,group,-1);
+ selMoved = 1;
+ }
+ else if (changeGroupExpand == 1 && contact->SubExpanded)
+ {
+ //Contract
+ struct ClcContact * ht = NULL;
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ contact->SubExpanded = 0;
+ db_set_b(contact->hContact,"CList","Expanded",0);
+ ht = contact;
+ dat->NeedResort = 1;
+ pcli->pfnSortCLC(hwnd,dat,1);
+ cliRecalcScrollBar(hwnd,dat);
+ hitcontact = NULL;
+ }
+ else if (changeGroupExpand == 2 && contact->SubExpanded)
+ {
+ dat->selection++;
+ selMoved = 1;
+ }
+ else if (changeGroupExpand == 2 && !contact->SubExpanded && dat->expandMeta)
+ {
+ struct ClcContact * ht = NULL;
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ contact->SubExpanded = 1;
+ db_set_b(contact->hContact,"CList","Expanded",1);
+ ht = contact;
+ dat->NeedResort = 1;
+ pcli->pfnSortCLC(hwnd,dat,1);
+ cliRecalcScrollBar(hwnd,dat);
+ if (ht)
+ {
+ int i=0;
+ struct ClcContact *contact2;
+ struct ClcGroup *group2;
+ if (FindItem(hwnd,dat,contact->hContact,&contact2,&group2,NULL,FALSE))
+ {
+ i = cliGetRowsPriorTo(&dat->list,group2,GetContactIndex(group2,contact2));
+ pcli->pfnEnsureVisible(hwnd,dat,i+contact->SubAllocated,0);
+ }
+ }
+ hitcontact = NULL;
+ }
+ }
+ }
+
+ else
+ {
+ if (changeGroupExpand == 1 && contact->type == CLCIT_CONTACT) {
+ if (group == &dat->list) {SetCapture(hwnd); return 0;}
+ dat->selection = cliGetRowsPriorTo(&dat->list,group,-1);
+ selMoved = 1;
+ }
+ else {
+ if (contact->type == CLCIT_GROUP)
+ {
+ if (changeGroupExpand == 1)
+ {
+ if ( !contact->group->expanded)
+ {
+ dat->selection--;
+ selMoved = 1;
+ }
+ else
+ {
+ pcli->pfnSetGroupExpand(hwnd,dat,contact->group,0);
+ }
+ }
+ else if (changeGroupExpand == 2)
+ {
+ pcli->pfnSetGroupExpand(hwnd,dat,contact->group,1);
+ dat->selection++;
+ selMoved = 1;
+ }
+ else {SetCapture(hwnd);return 0;}
+ }//
+ //
+ }
+
+ }
+ }
+ else {SetCapture(hwnd);return 0; }
+ }
+ if (selMoved)
+ {
+ dat->szQuickSearch[0] = 0;
+ if (dat->selection >= pcli->pfnGetGroupContentsCount(&dat->list,1))
+ dat->selection = pcli->pfnGetGroupContentsCount(&dat->list,1)-1;
+ if (dat->selection < 0) dat->selection = 0;
+ if (dat->bCompactMode)
+ SendMessage(hwnd,WM_SIZE,0,0);
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ pcli->pfnEnsureVisible(hwnd,dat,dat->selection,0);
+ UpdateWindow(hwnd);
+ SetCapture(hwnd);
+ return 0;
+ }
+ SetCapture(hwnd);
+ return 0;
+
+}
+
+void clcSetDelayTimer( UINT_PTR uIDEvent, HWND hwnd, int nDelay)
+{
+ KillTimer( hwnd, uIDEvent );
+ int delay = nDelay;
+ if ( delay == -1)
+ {
+ switch ( uIDEvent )
+ {
+ case TIMERID_DELAYEDRESORTCLC: delay = 10; break;
+ case TIMERID_RECALCSCROLLBAR: delay = 10; break;
+ case TIMERID_REBUILDAFTER: delay = 50; break;
+ default: delay = 100; break;
+ }
+ }
+ CLUI_SafeSetTimer( hwnd, uIDEvent, delay, NULL );
+}
+
+static LRESULT clcOnTimer(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(wParam) {
+ case TIMERID_INVALIDATE_FULL:
+ KillTimer(hwnd,TIMERID_INVALIDATE_FULL);
+ pcli->pfnRecalcScrollBar(hwnd,dat);
+ pcli->pfnInvalidateRect(hwnd,NULL,0);
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+
+ case TIMERID_INVALIDATE:
+ {
+ time_t cur_time = (time(NULL)/60);
+ if (cur_time != dat->last_tick_time)
+ {
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ dat->last_tick_time = cur_time;
+ }
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ }
+ case TIMERID_SUBEXPAND:
+ {
+ struct ClcContact * ht = NULL;
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ if (hitcontact && dat->expandMeta)
+ {
+ if (hitcontact->SubExpanded) hitcontact->SubExpanded = 0; else hitcontact->SubExpanded = 1;
+ db_set_b(hitcontact->hContact,"CList","Expanded",hitcontact->SubExpanded);
+ if (hitcontact->SubExpanded)
+ ht = &(hitcontact->subcontacts[hitcontact->SubAllocated-1]);
+ }
+
+ dat->NeedResort = 1;
+ pcli->pfnSortCLC(hwnd,dat,1);
+ cliRecalcScrollBar(hwnd,dat);
+ if (ht) {
+ int i=0;
+ struct ClcContact *contact;
+ struct ClcGroup *group;
+ if (FindItem(hwnd,dat,hitcontact->hContact,&contact,&group,NULL,FALSE))
+ {
+ i = cliGetRowsPriorTo(&dat->list,group,GetContactIndex(group,contact));
+ pcli->pfnEnsureVisible(hwnd,dat,i+hitcontact->SubAllocated,0);
+ }
+ }
+ hitcontact = NULL;
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ }
+ case TIMERID_DELAYEDRESORTCLC:
+ TRACE("Do sort on Timer\n");
+ KillTimer(hwnd,TIMERID_DELAYEDRESORTCLC);
+ pcli->pfnSortCLC(hwnd,dat,1);
+ pcli->pfnInvalidateRect(hwnd,NULL,FALSE);
+ return 0;
+
+ case TIMERID_RECALCSCROLLBAR:
+ KillTimer(hwnd,TIMERID_RECALCSCROLLBAR);
+ pcli->pfnRecalcScrollBar(hwnd,dat);
+ return 0;
+
+ default:
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ }
+ return 0;
+}
+
+
+static LRESULT clcOnActivate(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TRACE ("clcOnActivate\n");
+ if (dat->bCompactMode)
+ {
+ cliRecalcScrollBar(hwnd,dat);
+ if ( dat->hwndRenameEdit == NULL )
+ PostMessage( hwnd, WM_SIZE, 0, 0);
+ }
+ dat->dragStage |= DRAGSTAGEF_SKIPRENAME;
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+}
+static LRESULT clcOnSetCursor(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int lResult;
+
+ if ( !CLUI_IsInMainWindow(hwnd))
+ return DefWindowProc(hwnd,msg,wParam,lParam);
+
+ if (g_CluiData.nBehindEdgeState>0)
+ CLUI_ShowFromBehindEdge();
+
+ if (g_CluiData.bBehindEdgeSettings)
+ CLUI_UpdateTimer(0);
+
+ lResult = CLUI_TestCursorOnBorders();
+ return lResult ? lResult : DefWindowProc(hwnd,msg,wParam,lParam);
+}
+static LRESULT clcOnLButtonDown(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ {
+ POINT pt;
+ int k = 0;
+ pt.x = LOWORD(lParam);
+ pt.y = HIWORD(lParam);
+ ClientToScreen(hwnd,&pt);
+ k = CLUI_SizingOnBorder(pt,0);
+ if (k)
+ {
+ int io = dat->iHotTrack;
+ dat->iHotTrack = 0;
+ if (dat->exStyle&CLS_EX_TRACKSELECT)
+ {
+ pcli->pfnInvalidateItem(hwnd,dat,io);
+ }
+ if (k && GetCapture() == hwnd)
+ {
+ SendMessage(GetParent(hwnd),WM_PARENTNOTIFY,WM_LBUTTONDOWN,lParam);
+ }
+ return FALSE;
+ }
+ }
+ {
+ struct ClcContact *contact;
+ struct ClcGroup *group;
+ int hit;
+ DWORD hitFlags;
+ fMouseUpped = FALSE;
+ pcli->pfnHideInfoTip(hwnd,dat);
+ KillTimer(hwnd,TIMERID_INFOTIP);
+ KillTimer(hwnd,TIMERID_RENAME);
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+
+ pcli->pfnEndRename(hwnd,dat,1);
+ dat->ptDragStart.x = (short)LOWORD(lParam);
+ dat->ptDragStart.y = (short)HIWORD(lParam);
+ dat->szQuickSearch[0] = 0;
+ hit = cliHitTest(hwnd,dat,(short)LOWORD(lParam),(short)HIWORD(lParam),&contact,&group,&hitFlags);
+ if (GetFocus() != hwnd) SetFocus(hwnd);
+ if (hit != -1 && !(hitFlags&CLCHT_NOWHERE))
+ {
+ if ( hit == dat->selection && hitFlags&CLCHT_ONITEMLABEL && dat->exStyle&CLS_EX_EDITLABELS)
+ {
+ if ( !(dat->dragStage&DRAGSTAGEF_SKIPRENAME))
+ {
+ SetCapture(hwnd);
+ dat->iDragItem = dat->selection;
+ dat->dragStage = DRAGSTAGE_NOTMOVED|DRAGSTAGEF_MAYBERENAME;
+ dat->dragAutoScrolling = 0;
+ return TRUE;
+ }
+ else
+ {
+ dat->dragStage &= ~DRAGSTAGEF_SKIPRENAME;
+ return TRUE;
+ }
+
+ }
+ }
+ if (hit != -1 && !(hitFlags&CLCHT_NOWHERE) && contact->type == CLCIT_CONTACT && contact->SubAllocated && !contact->isSubcontact)
+ if (hitFlags&CLCHT_ONITEMICON && dat->expandMeta)
+ {
+ BYTE doubleClickExpand = db_get_b(NULL,"CLC","MetaDoubleClick",SETTING_METAAVOIDDBLCLICK_DEFAULT);
+
+ hitcontact = contact;
+ HitPoint.x = (short)LOWORD(lParam);
+ HitPoint.y = (short)HIWORD(lParam);
+ fMouseUpped = FALSE;
+ if ((GetKeyState(VK_SHIFT)&0x8000) || (GetKeyState(VK_CONTROL)&0x8000) || (GetKeyState(VK_MENU)&0x8000))
+ {
+ fMouseUpped = TRUE;
+ hitcontact = contact;
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ CLUI_SafeSetTimer(hwnd,TIMERID_SUBEXPAND,0,NULL);
+ }
+ }
+ else
+ hitcontact = NULL;
+
+ if (hit != -1 && !(hitFlags&CLCHT_NOWHERE) && contact->type == CLCIT_GROUP)
+ if (hitFlags&CLCHT_ONITEMICON)
+ {
+ struct ClcGroup *selgroup;
+ struct ClcContact *selcontact;
+ dat->selection = cliGetRowByIndex(dat,dat->selection,&selcontact,&selgroup);
+ pcli->pfnSetGroupExpand(hwnd,dat,contact->group,-1);
+ if (dat->selection != -1)
+ {
+ dat->selection = cliGetRowsPriorTo(&dat->list,selgroup,GetContactIndex(selgroup,selcontact));
+ if (dat->selection == -1) dat->selection = cliGetRowsPriorTo(&dat->list,contact->group,-1);
+ }
+ if (dat->bCompactMode)
+ {
+ SendMessage(hwnd,WM_SIZE,0,0);
+ }
+ else
+ {
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ UpdateWindow(hwnd);
+ }
+ return TRUE;
+ }
+ if (hit != -1 && !(hitFlags&CLCHT_NOWHERE) && hitFlags&CLCHT_ONITEMCHECK)
+ {
+ NMCLISTCONTROL nm;
+ contact->flags ^= CONTACTF_CHECKED;
+ if (contact->type == CLCIT_GROUP) pcli->pfnSetGroupChildCheckboxes(contact->group,contact->flags&CONTACTF_CHECKED);
+ pcli->pfnRecalculateGroupCheckboxes(hwnd,dat);
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ nm.hdr.code = CLN_CHECKCHANGED;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ nm.flags = 0;
+ nm.hItem = ContactToItemHandle(contact,&nm.flags);
+ SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm);
+ }
+ if ( !(hitFlags&(CLCHT_ONITEMICON|CLCHT_ONITEMLABEL|CLCHT_ONITEMCHECK)))
+ {
+ NMCLISTCONTROL nm;
+ nm.hdr.code = NM_CLICK;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ nm.flags = 0;
+ if (hit == -1 || hitFlags&CLCHT_NOWHERE) nm.hItem = NULL;
+ else nm.hItem = ContactToItemHandle(contact,&nm.flags);
+ nm.iColumn = hitFlags&CLCHT_ONITEMEXTRA?HIBYTE(HIWORD(hitFlags)):-1;
+ nm.pt = dat->ptDragStart;
+ SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm);
+ }
+ if (hitFlags&(CLCHT_ONITEMCHECK|CLCHT_ONITEMEXTRA))
+ return FALSE;
+
+ dat->selection = (hitFlags&CLCHT_NOWHERE)?-1:hit;
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+
+ UpdateWindow(hwnd);
+ if (dat->selection != -1 && (contact->type == CLCIT_CONTACT || contact->type == CLCIT_GROUP) && !(hitFlags&(CLCHT_ONITEMEXTRA|CLCHT_ONITEMCHECK|CLCHT_NOWHERE)))
+ {
+ SetCapture(hwnd);
+ dat->iDragItem = dat->selection;
+ dat->dragStage = DRAGSTAGE_NOTMOVED;
+ dat->dragAutoScrolling = 0;
+ }
+ if (dat->bCompactMode)
+ {
+ SendMessage(hwnd,WM_SIZE,0,0);
+ }
+ if (dat->selection != -1) pcli->pfnEnsureVisible(hwnd,dat,hit,0);
+ return TRUE;
+ }
+}
+
+
+
+static LRESULT clcOnCaptureChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if ((HWND)lParam != hwnd)
+ {
+ if (dat->iHotTrack != -1)
+ {
+ int i;
+ i = dat->iHotTrack;
+ dat->iHotTrack = -1;
+ pcli->pfnInvalidateItem(hwnd,dat,i);
+ pcli->pfnHideInfoTip(hwnd,dat);
+ }
+ }
+ return 0;
+}
+
+static LRESULT clcOnMouseMove(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ BOOL isOutside = FALSE;
+ if (CLUI_IsInMainWindow(hwnd))
+ {
+ if (g_CluiData.bBehindEdgeSettings) CLUI_UpdateTimer(0);
+ CLUI_TestCursorOnBorders();
+ }
+ if (clcProceedDragToScroll(hwnd, (short)HIWORD(lParam)))
+ return 0;
+
+ if ( dat->dragStage&DRAGSTAGEF_MAYBERENAME )
+ {
+ POINT pt;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ if ( abs(pt.x-dat->ptDragStart.x)>GetSystemMetrics(SM_CXDOUBLECLK)
+ || abs(pt.y-dat->ptDragStart.y)>GetSystemMetrics(SM_CYDOUBLECLK))
+ {
+ KillTimer( hwnd, TIMERID_RENAME );
+ dat->dragStage &= (~DRAGSTAGEF_MAYBERENAME);
+ }
+ }
+
+ if (dat->iDragItem == -1)
+ {
+ POINT pt;
+ HWND window;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ ClientToScreen(hwnd,&pt);
+ window = WindowFromPoint(pt);
+ if (window != hwnd) isOutside = TRUE;
+ }
+
+ if (hitcontact != NULL) {
+ int x = (short)LOWORD(lParam);
+ int y = (short)HIWORD(lParam);
+ int xm = GetSystemMetrics(SM_CXDOUBLECLK);
+ int ym = GetSystemMetrics(SM_CYDOUBLECLK);
+ if ( abs(HitPoint.x-x) > xm || abs(HitPoint.y-y) > ym) {
+ if (fMouseUpped) {
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ CLUI_SafeSetTimer(hwnd,TIMERID_SUBEXPAND,0,NULL);
+ fMouseUpped = FALSE;
+ }
+ else {
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ hitcontact = NULL;
+ fMouseUpped = FALSE;
+ }
+ }
+ }
+
+ if (dat->iDragItem == -1) {
+ DWORD flag = 0;
+ int iOldHotTrack = dat->iHotTrack;
+
+ if (dat->hwndRenameEdit != NULL || GetKeyState(VK_MENU)&0x8000 || GetKeyState(VK_F10)&0x8000)
+ return 0;
+
+ dat->iHotTrack = isOutside ? -1 : cliHitTest(hwnd,dat,(short)LOWORD(lParam),(short)HIWORD(lParam),NULL,NULL,&flag);
+
+ if (flag&CLCHT_NOWHERE)
+ dat->iHotTrack = -1;
+
+ if (iOldHotTrack != dat->iHotTrack || isOutside) {
+ if (iOldHotTrack == -1 && !isOutside)
+ SetCapture(hwnd);
+
+ if (dat->iHotTrack == -1 || isOutside)
+ ReleaseCapture();
+
+ if (dat->exStyle&CLS_EX_TRACKSELECT)
+ {
+ pcli->pfnInvalidateItem(hwnd,dat,iOldHotTrack);
+ pcli->pfnInvalidateItem(hwnd,dat,dat->iHotTrack);
+ }
+
+ pcli->pfnHideInfoTip(hwnd,dat);
+ }
+
+ KillTimer(hwnd,TIMERID_INFOTIP);
+
+ if (wParam == 0 && dat->hInfoTipItem == NULL)
+ {
+ dat->ptInfoTip.x = (short)LOWORD(lParam);
+ dat->ptInfoTip.y = (short)HIWORD(lParam);
+ CLUI_SafeSetTimer(hwnd,TIMERID_INFOTIP,dat->infoTipTimeout,NULL);
+ }
+ return 0;
+ }
+
+ if ((dat->dragStage&DRAGSTAGEM_STAGE) == DRAGSTAGE_NOTMOVED && !(dat->exStyle&CLS_EX_DISABLEDRAGDROP))
+ if (abs((short)LOWORD(lParam)-dat->ptDragStart.x) >= GetSystemMetrics(SM_CXDRAG) || abs((short)HIWORD(lParam)-dat->ptDragStart.y) >= GetSystemMetrics(SM_CYDRAG))
+ dat->dragStage = (dat->dragStage&~DRAGSTAGEM_STAGE)|DRAGSTAGE_ACTIVE;
+
+ if ((dat->dragStage&DRAGSTAGEM_STAGE) == DRAGSTAGE_ACTIVE) {
+ RECT clRect;
+ GetClientRect(hwnd,&clRect);
+
+ POINT pt;
+ pt.x = (short)LOWORD(lParam); pt.y = (short)HIWORD(lParam);
+ HCURSOR hNewCursor = LoadCursor(NULL, IDC_NO);
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ if (dat->dragAutoScrolling)
+ {KillTimer(hwnd,TIMERID_DRAGAUTOSCROLL); dat->dragAutoScrolling = 0;}
+ int target = GetDropTargetInformation(hwnd,dat,pt);
+ if (dat->dragStage&DRAGSTAGEF_OUTSIDE && target != DROPTARGET_OUTSIDE) {
+ NMCLISTCONTROL nm;
+ struct ClcContact *contact;
+ cliGetRowByIndex(dat,dat->iDragItem,&contact,NULL);
+ nm.hdr.code = CLN_DRAGSTOP;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ nm.flags = 0;
+ nm.hItem = ContactToItemHandle(contact,&nm.flags);
+ SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm);
+ dat->dragStage &= ~DRAGSTAGEF_OUTSIDE;
+ }
+
+ switch(target) {
+ case DROPTARGET_ONSELF:
+ break;
+
+ case DROPTARGET_ONCONTACT:
+ if (ServiceExists(MS_MC_ADDTOMETA))
+ {
+ struct ClcContact *contSour;
+ cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL);
+ if (contSour->type == CLCIT_CONTACT && g_szMetaModuleName && mir_strcmp(contSour->proto,g_szMetaModuleName))
+ {
+ if ( !contSour->isSubcontact)
+ hNewCursor = LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROPUSER)); /// Add to meta
+ else
+ hNewCursor = LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_DROPMETA));
+ }
+
+ }
+ break;
+
+ case DROPTARGET_ONMETACONTACT:
+ if (ServiceExists(MS_MC_ADDTOMETA))
+ {
+ struct ClcContact *contSour,*contDest;
+ cliGetRowByIndex(dat,dat->selection,&contDest,NULL);
+ cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL);
+ if (contSour->type == CLCIT_CONTACT && g_szMetaModuleName && mir_strcmp(contSour->proto,g_szMetaModuleName))
+ {
+ if ( !contSour->isSubcontact)
+ hNewCursor = LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROPUSER)); /// Add to meta
+ else
+ if (contSour->subcontacts == contDest)
+ hNewCursor = LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_DEFAULTSUB)); ///MakeDefault
+ else
+ hNewCursor = LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_REGROUP));
+ }
+ }
+ break;
+ case DROPTARGET_ONSUBCONTACT:
+ if (ServiceExists(MS_MC_ADDTOMETA))
+ {
+ struct ClcContact *contSour,*contDest;
+ cliGetRowByIndex(dat,dat->selection,&contDest,NULL);
+ cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL);
+ if (contSour->type == CLCIT_CONTACT && g_szMetaModuleName && mir_strcmp(contSour->proto,g_szMetaModuleName))
+ {
+ if ( !contSour->isSubcontact)
+ hNewCursor = LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROPUSER)); /// Add to meta
+ else
+ if (contDest->subcontacts == contSour->subcontacts)
+ break;
+ else
+ hNewCursor = LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_REGROUP));
+ }
+ }
+ break;
+
+ case DROPTARGET_ONGROUP:
+ hNewCursor = LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROPUSER));
+ break;
+
+ case DROPTARGET_INSERTION:
+ hNewCursor = LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROP));
+ break;
+
+ case DROPTARGET_OUTSIDE:
+ {
+ NMCLISTCONTROL nm;
+ struct ClcContact *contact;
+
+ if (pt.x >= 0 && pt.x < clRect.right && ((pt.y < 0 && pt.y>-dat->dragAutoScrollHeight) || (pt.y >= clRect.bottom && pt.y < clRect.bottom+dat->dragAutoScrollHeight)))
+ {
+ if ( !dat->dragAutoScrolling)
+ {
+ if (pt.y < 0) dat->dragAutoScrolling = -1;
+ else dat->dragAutoScrolling = 1;
+ CLUI_SafeSetTimer(hwnd,TIMERID_DRAGAUTOSCROLL,dat->scrollTime,NULL);
+ }
+ SendMessage(hwnd,WM_TIMER,TIMERID_DRAGAUTOSCROLL,0);
+ }
+
+ dat->dragStage |= DRAGSTAGEF_OUTSIDE;
+ cliGetRowByIndex(dat,dat->iDragItem,&contact,NULL);
+ nm.hdr.code = CLN_DRAGGING;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ nm.flags = 0;
+ nm.hItem = ContactToItemHandle(contact,&nm.flags);
+ nm.pt = pt;
+ if (SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm))
+ return 0;
+ break;
+ }
+ default:
+ {
+ struct ClcGroup *group = NULL;
+ cliGetRowByIndex(dat,dat->iDragItem,NULL,&group);
+ if (group && group->parent)
+ {
+ struct ClcContact *contSour;
+ cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL);
+ if ( !contSour->isSubcontact)
+ hNewCursor = LoadCursor(GetModuleHandle(NULL), MAKEINTRESOURCE(IDC_DROPUSER));
+ }
+ break;
+ }
+ }
+ SetCursor(hNewCursor);
+ }
+ return 0;
+}
+
+static LRESULT clcOnLButtonUp(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (clcExitDragToScroll())
+ return 0;
+
+ fMouseUpped = TRUE;
+
+ if (hitcontact != NULL && dat->expandMeta) {
+ BYTE doubleClickExpand = db_get_b(NULL,"CLC","MetaDoubleClick",SETTING_METAAVOIDDBLCLICK_DEFAULT);
+ CLUI_SafeSetTimer(hwnd,TIMERID_SUBEXPAND,GetDoubleClickTime()*doubleClickExpand,NULL);
+ }
+ else if (dat->iHotTrack == -1 && dat->iDragItem == -1)
+ ReleaseCapture();
+ if (dat->iDragItem == -1) return 0;
+ SetCursor((HCURSOR)GetClassLongPtr(hwnd,GCLP_HCURSOR));
+ if (dat->exStyle & CLS_EX_TRACKSELECT)
+ {
+ DWORD flags;
+ dat->iHotTrack = cliHitTest(hwnd,dat,(short)LOWORD(lParam),(short)HIWORD(lParam),NULL,NULL,&flags);
+ if (dat->iHotTrack == -1)
+ ReleaseCapture();
+ }
+ else if (hitcontact == NULL)
+ ReleaseCapture();
+ KillTimer(hwnd,TIMERID_DRAGAUTOSCROLL);
+ if (dat->dragStage == (DRAGSTAGE_NOTMOVED|DRAGSTAGEF_MAYBERENAME))
+ CLUI_SafeSetTimer(hwnd,TIMERID_RENAME,GetDoubleClickTime(),NULL);
+ else if ((dat->dragStage&DRAGSTAGEM_STAGE) == DRAGSTAGE_ACTIVE)
+ {
+ POINT pt;
+ int target;
+ TCHAR Wording[500];
+ int res = 0;
+ pt.x = (short)LOWORD(lParam); pt.y = (short)HIWORD(lParam);
+ target = GetDropTargetInformation(hwnd,dat,pt);
+ switch(target)
+ {
+ case DROPTARGET_ONSELF:
+ break;
+ case DROPTARGET_ONCONTACT:
+ if (ServiceExists(MS_MC_ADDTOMETA))
+ {
+ struct ClcContact *contDest, *contSour;
+ int res;
+ HANDLE handle,hcontact;
+
+ cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL);
+ cliGetRowByIndex(dat,dat->selection,&contDest,NULL);
+ hcontact = contSour->hContact;
+ if (contSour->type == CLCIT_CONTACT)
+ {
+
+ if (g_szMetaModuleName && mir_strcmp(contSour->proto,g_szMetaModuleName))
+ {
+ if ( !contSour->isSubcontact)
+ {
+ HANDLE hDest = contDest->hContact;
+ mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be converted to MetaContact and '%s' be added to it?"),contDest->szText, contSour->szText);
+ res = MessageBox(hwnd,Wording,TranslateT("Converting to MetaContact"),MB_OKCANCEL|MB_ICONQUESTION);
+ if (res == 1)
+ {
+ handle = (HANDLE)CallService(MS_MC_CONVERTTOMETA,(WPARAM)hDest,0);
+ if ( !handle) return 0;
+ CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle);
+ }
+ }
+ else
+ {
+ HANDLE handle,hcontact,hfrom,hdest;
+ hcontact = contSour->hContact;
+ hfrom = contSour->subcontacts->hContact;
+ hdest = contDest->hContact;
+ mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be converted to MetaContact and '%s' be added to it (remove it from '%s')?"), contDest->szText,contSour->szText,contSour->subcontacts->szText);
+ res = MessageBox(hwnd,Wording,TranslateT("Converting to MetaContact (Moving)"),MB_OKCANCEL|MB_ICONQUESTION);
+ if (res == 1)
+ {
+
+ handle = (HANDLE)CallService(MS_MC_CONVERTTOMETA,(WPARAM)hdest,0);
+ if ( !handle) return 0;
+
+ CallService(MS_MC_REMOVEFROMMETA,(WPARAM)0,(LPARAM)hcontact);
+ CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle);
+ }
+ }
+ }
+
+ }
+ }
+ break;
+ case DROPTARGET_ONMETACONTACT:
+ {
+ struct ClcContact *contDest, *contSour;
+ int res;
+ cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL);
+ cliGetRowByIndex(dat,dat->selection,&contDest,NULL);
+ if (contSour->type == CLCIT_CONTACT)
+ {
+
+ if (g_szMetaModuleName && strcmp(contSour->proto,g_szMetaModuleName))
+ {
+ if ( !contSour->isSubcontact)
+ {
+ HANDLE handle,hcontact;
+ hcontact = contSour->hContact;
+ handle = contDest->hContact;
+ mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do you want to contact '%s' be added to metacontact '%s'?"),contSour->szText, contDest->szText);
+ res = MessageBox(hwnd,Wording,TranslateT("Adding contact to MetaContact"),MB_OKCANCEL|MB_ICONQUESTION);
+ if (res == 1)
+ {
+
+ if ( !handle) return 0;
+ CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle);
+ }
+ }
+ else
+ {
+ if (contSour->subcontacts == contDest)
+ {
+ HANDLE hsour;
+ hsour = contSour->hContact;
+ mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be default ?"),contSour->szText);
+ res = MessageBox(hwnd,Wording,TranslateT("Set default contact"),MB_OKCANCEL|MB_ICONQUESTION);
+
+ if (res == 1)
+ {
+ CallService(MS_MC_SETDEFAULTCONTACT,(WPARAM)contDest->hContact,(LPARAM)hsour);
+ }
+ }
+ else
+ {
+ HANDLE handle,hcontact,hfrom;
+ hcontact = contSour->hContact;
+ hfrom = contSour->subcontacts->hContact;
+ handle = contDest->hContact;
+ mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be removed from MetaContact '%s' and added to '%s'?"), contSour->szText,contSour->subcontacts->szText,contDest->szText);
+ res = MessageBox(hwnd,Wording,TranslateT("Changing MetaContacts (Moving)"),MB_OKCANCEL|MB_ICONQUESTION);
+ if (res == 1)
+ {
+
+ if ( !handle) return 0;
+
+ CallService(MS_MC_REMOVEFROMMETA,(WPARAM)0,(LPARAM)hcontact);
+ CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case DROPTARGET_ONSUBCONTACT:
+ {
+ struct ClcContact *contDest, *contSour;
+ int res;
+ cliGetRowByIndex(dat,dat->iDragItem,&contSour,NULL);
+ cliGetRowByIndex(dat,dat->selection,&contDest,NULL);
+ if (contSour->type == CLCIT_CONTACT)
+ {
+ if (g_szMetaModuleName && strcmp(contSour->proto,g_szMetaModuleName))
+ {
+ if ( !contSour->isSubcontact)
+ {
+ HANDLE handle,hcontact;
+ hcontact = contSour->hContact;
+ handle = contDest->subcontacts->hContact;
+ mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be added to MetaContact '%s'?"), contSour->szText,contDest->subcontacts->szText);
+ res = MessageBox(hwnd,Wording,TranslateT("Changing MetaContacts (Moving)"),MB_OKCANCEL|MB_ICONQUESTION);
+ if (res == 1)
+ {
+
+ if ( !handle) return 0;
+ CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle);
+ }
+ }
+ else
+ {
+ if (contSour->subcontacts != contDest->subcontacts)
+ {
+ HANDLE handle,hcontact,hfrom;
+ hcontact = contSour->hContact;
+ hfrom = contSour->subcontacts->hContact;
+ handle = contDest->subcontacts->hContact;
+ mir_sntprintf(Wording,SIZEOF(Wording),TranslateT("Do You want contact '%s' to be removed from MetaContact '%s' and added to '%s'?"), contSour->szText,contSour->subcontacts->szText,contDest->subcontacts->szText);
+ res = MessageBox(hwnd,Wording,TranslateT("Changing MetaContacts (Moving)"),MB_OKCANCEL|MB_ICONQUESTION);
+ if (res == 1)
+ {
+
+ if ( !handle) return 0;
+
+ CallService(MS_MC_REMOVEFROMMETA,(WPARAM)0,(LPARAM)hcontact);
+ CallService(MS_MC_ADDTOMETA,(WPARAM)hcontact,(LPARAM)handle);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case DROPTARGET_ONGROUP:
+ corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ break;
+ case DROPTARGET_INSERTION:
+ {
+ struct ClcContact *contact, *destcontact;
+ struct ClcGroup *group, *destgroup;
+ BOOL NeedRename = FALSE;
+ TCHAR newName[128] = {0};
+ int newIndex,i;
+ pcli->pfnGetRowByIndex(dat, dat->iDragItem, &contact, &group);
+ i = pcli->pfnGetRowByIndex(dat, dat->iInsertionMark, &destcontact, &destgroup);
+ if (i != -1 && group->groupId != destgroup->groupId)
+ {
+ TCHAR * groupName = mir_tstrdup(pcli->pfnGetGroupName(contact->groupId,0));
+ TCHAR * shortGroup = NULL;
+ TCHAR * sourceGrName = mir_tstrdup(pcli->pfnGetGroupName(destgroup->groupId,0));
+ if (groupName) {
+ int len = (int)_tcslen(groupName);
+ do {len--;}while(len >= 0 && groupName[len] != '\\');
+ if (len >= 0) shortGroup = groupName+len+1;
+ else shortGroup = groupName;
+ }
+ if (shortGroup)
+ {
+ NeedRename = TRUE;
+ if (sourceGrName)
+ mir_sntprintf(newName,SIZEOF(newName),_T("%s\\%s"),sourceGrName,shortGroup);
+ else
+ mir_sntprintf(newName,SIZEOF(newName),_T("%s"),shortGroup);
+ }
+ mir_free(groupName);
+ mir_free(sourceGrName);
+ }
+ newIndex = CallService(MS_CLIST_GROUPMOVEBEFORE, contact->groupId, (destcontact && i != -1)?destcontact->groupId:0);
+ newIndex = newIndex?newIndex:contact->groupId;
+ if (NeedRename) pcli->pfnRenameGroup(newIndex,newName);
+ break;
+ }
+ case DROPTARGET_OUTSIDE:
+ corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ break;
+ default:
+ corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ break;
+
+ }
+ }
+
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ dat->iDragItem = -1;
+ dat->iInsertionMark = -1;
+ return 0;
+}
+static LRESULT clcOnLButtonDblClick(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ hitcontact = NULL;
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+}
+static LRESULT clcOnDestroy(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int i=0;
+
+ for (i=0;i <= FONTID_MODERN_MAX;i++)
+ {
+ if (dat->fontModernInfo[i].hFont) DeleteObject(dat->fontModernInfo[i].hFont);
+ dat->fontModernInfo[i].hFont = NULL;
+ }
+ if (dat->hMenuBackground)
+ {
+ DeleteObject(dat->hMenuBackground);
+ dat->hMenuBackground = NULL;
+ }
+ if ( !dat->bkChanged && dat->hBmpBackground)
+ {
+ DeleteObject(dat->hBmpBackground);
+ dat->hBmpBackground = NULL;
+ }
+
+ ImageArray_Clear(&dat->avatar_cache);
+ mod_DeleteDC(dat->avatar_cache.hdc);
+ ImageArray_Free(&dat->avatar_cache, FALSE);
+ if (dat->himlHighlight)
+ ImageList_Destroy(dat->himlHighlight);
+
+ RowHeights_Free(dat);
+ corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ xpt_FreeThemeForWindow(hwnd);
+ return 0;
+}
+static LRESULT clcOnIntmGroupChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct ClcContact *contact;
+ BYTE iExtraImage[MAXEXTRACOLUMNS];
+ WORD iWideExtraImage[MAXEXTRACOLUMNS];
+ BYTE flags = 0;
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ {
+ memset(iExtraImage, 0xFF, SIZEOF(iExtraImage));
+ memset((void*)iWideExtraImage, 0xFF, sizeof(iWideExtraImage));
+ }
+ else {
+ CopyMemory(iExtraImage, contact->iExtraImage, SIZEOF(iExtraImage));
+ CopyMemory((void*)iWideExtraImage, (void*)contact->iWideExtraImage, sizeof(iWideExtraImage));
+ flags = contact->flags;
+ }
+ pcli->pfnDeleteItemFromTree(hwnd, (HANDLE) wParam);
+ if (GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_SHOWHIDDEN || !db_get_b((HANDLE) wParam, "CList", "Hidden", 0)) {
+ NMCLISTCONTROL nm;
+ pcli->pfnAddContactToTree(hwnd, dat, (HANDLE) wParam, 1, 1);
+ if (pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL)) {
+ CopyMemory(contact->iExtraImage, iExtraImage, SIZEOF(iExtraImage));
+ CopyMemory((void*)contact->iWideExtraImage, (void*)iWideExtraImage, sizeof(iWideExtraImage));
+ if (flags & CONTACTF_CHECKED)
+ contact->flags |= CONTACTF_CHECKED;
+ }
+ nm.hdr.code = CLN_CONTACTMOVED;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ nm.flags = 0;
+ nm.hItem = (HANDLE) wParam;
+ SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM) & nm);
+ dat->NeedResort = 1;
+ }
+ SetTimer(hwnd,TIMERID_REBUILDAFTER,1,NULL);
+ return 0;
+}
+
+static LRESULT clcOnIntmIconChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct ClcContact *contact = NULL;
+ struct ClcGroup *group = NULL;
+ int recalcScrollBar = 0, shouldShow;
+ BOOL needRepaint = FALSE;
+ WORD status;
+ char *szProto;
+ int nHiddenStatus = 0;
+ BOOL image_is_special = FALSE;
+ RECT iconRect = {0};
+ int contacticon = CallService(MS_CLIST_GETCONTACTICON, wParam, 1);
+ HANDLE hSelItem = NULL;
+ struct ClcContact *selcontact = NULL;
+
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);
+ if (szProto == NULL)
+ status = ID_STATUS_OFFLINE;
+ else
+ status = GetContactCachedStatus((HANDLE) wParam);
+ image_is_special = (LOWORD(contacticon) != (LOWORD(lParam))); //check only base icons
+
+ nHiddenStatus = CLVM_GetContactHiddenStatus((HANDLE)wParam, szProto, dat);
+
+ DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE);
+ bool isVisiblebyFilter = (( ( style & CLS_SHOWHIDDEN ) && nHiddenStatus != -1 ) || !nHiddenStatus );
+ bool ifVisibleByClui = !pcli->pfnIsHiddenMode( dat, status );
+ bool isVisible = g_CluiData.bFilterEffective&CLVM_FILTER_STATUS ? TRUE : ifVisibleByClui;
+ bool isIconChanged = CallService(MS_CLIST_GETCONTACTICON, wParam, 0) != LOWORD(lParam);
+
+ shouldShow = isVisiblebyFilter && ( isVisible || isIconChanged ) ;
+
+ // XXX CLVM changed - this means an offline msg is flashing, so the contact should be shown
+
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, &group, NULL))
+ {
+ if (shouldShow && CallService(MS_DB_CONTACT_IS, wParam, 0))
+ {
+ if (dat->selection >= 0 && pcli->pfnGetRowByIndex(dat, dat->selection, &selcontact, NULL) != -1)
+ hSelItem = pcli->pfnContactToHItem(selcontact);
+ pcli->pfnAddContactToTree(hwnd, dat, (HANDLE) wParam, (style & CLS_CONTACTLIST) == 0, 0);
+ recalcScrollBar = 1;
+ needRepaint = TRUE;
+ pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL);
+ if (contact)
+ {
+ contact->iImage = lParam;
+ contact->image_is_special = image_is_special;
+ pcli->pfnNotifyNewContact(hwnd, (HANDLE) wParam);
+ dat->NeedResort = 1;
+ }
+ }
+ }
+ else
+ {
+ //item in list already
+ if (contact->iImage == lParam)
+ return 0;
+ if ( !shouldShow && !(style & CLS_NOHIDEOFFLINE) && (style & CLS_HIDEOFFLINE) && clcItemNotHiddenOffline(dat, group, contact))
+ {
+ shouldShow = TRUE;
+ }
+ if ( !shouldShow && !(style & CLS_NOHIDEOFFLINE) && ((style & CLS_HIDEOFFLINE) || group->hideOffline || g_CluiData.bFilterEffective)) // CLVM changed
+ {
+ if (dat->selection >= 0 && pcli->pfnGetRowByIndex(dat, dat->selection, &selcontact, NULL) != -1)
+ hSelItem = pcli->pfnContactToHItem(selcontact);
+ pcli->pfnRemoveItemFromGroup(hwnd, group, contact, (style & CLS_CONTACTLIST) == 0);
+ needRepaint = TRUE;
+ recalcScrollBar = 1;
+ dat->NeedResort = 1;
+ }
+ else if (contact)
+ {
+ contact->iImage = lParam;
+ if ( !pcli->pfnIsHiddenMode(dat, status))
+ contact->flags |= CONTACTF_ONLINE;
+ else
+ contact->flags &= ~CONTACTF_ONLINE;
+ contact->image_is_special = image_is_special;
+ if ( !image_is_special) //Only if it is status changing
+ {
+ dat->NeedResort = 1;
+ needRepaint = TRUE;
+ }
+ else if (dat->m_paintCouter == contact->lastPaintCounter) //if contacts is visible
+ {
+ needRepaint = TRUE;
+ }
+ }
+
+ }
+ if (hSelItem) {
+ struct ClcGroup *selgroup;
+ if (pcli->pfnFindItem(hwnd, dat, hSelItem, &selcontact, &selgroup, NULL))
+ dat->selection = pcli->pfnGetRowsPriorTo(&dat->list, selgroup, List_IndexOf(( SortedList* )&selgroup->cl, selcontact));
+ else
+ dat->selection = -1;
+ }
+ // dat->NeedResort = 1;
+ // SortClcByTimer(hwnd);
+ if (dat->NeedResort)
+ {
+ TRACE("Sort required\n");
+ clcSetDelayTimer( TIMERID_DELAYEDRESORTCLC, hwnd );
+ }
+ else if (needRepaint)
+ {
+ if (contact && contact->pos_icon.bottom != 0 && contact->pos_icon.right != 0)
+ CLUI__cliInvalidateRect(hwnd,&(contact->pos_icon),FALSE);
+ else
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ //try only needed rectangle
+ }
+
+ return 0;
+}
+
+static LRESULT clcOnIntmAvatarChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct ClcContact *contact;
+ if (FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL,FALSE))
+ {
+ Cache_GetAvatar(dat, contact);
+ }
+ else if (dat->use_avatar_service && !wParam)
+ {
+ UpdateAllAvatars(dat);
+ }
+ CLUI__cliInvalidateRect(hwnd, NULL, FALSE);
+ return 0;
+}
+
+static LRESULT clcOnIntmTimeZoneChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct ClcContact *contact;
+ if ( !FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL,FALSE))
+ return corecli.pfnContactListControlWndProc(hwnd,msg,wParam,lParam);
+
+ if (contact) //!IsBadWritePtr(contact, sizeof(struct ClcContact)))
+ {
+ Cache_GetTimezone(dat,contact->hContact);
+ Cache_GetText(dat, contact,1);
+ cliRecalcScrollBar(hwnd,dat);
+ }
+ return 0;
+}
+static LRESULT clcOnIntmNameChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct ClcContact *contact;
+ int ret = corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+
+ pcli->pfnInvalidateDisplayNameCacheEntry((HANDLE)wParam);
+ if ( !FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL,FALSE))
+ return ret;
+
+ lstrcpyn(contact->szText, pcli->pfnGetContactDisplayName((HANDLE)wParam,0),SIZEOF(contact->szText));
+ if (contact)//!IsBadWritePtr(contact, sizeof(struct ClcContact)))
+ {
+ Cache_GetText(dat,contact,1);
+ cliRecalcScrollBar(hwnd,dat);
+ }
+ dat->NeedResort = 1;
+ pcli->pfnSortContacts();
+
+ return ret;
+}
+
+static LRESULT clcOnIntmApparentModeChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int lResult = corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ if ( !ServiceExists("ExtraIcon/Register"))
+ ExtraImage_SetAllExtraIcons(pcli->hwndContactTree,(HANDLE)wParam);
+ return lResult;
+}
+
+static LRESULT clcOnIntmStatusMsgChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct ClcContact *contact;
+ HANDLE hContact = (HANDLE)wParam;
+ if (hContact == NULL || IsHContactInfo(hContact) || IsHContactGroup(hContact))
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ if ( !FindItem(hwnd,dat,hContact,&contact,NULL,NULL,FALSE))
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ if (contact)//!IsBadWritePtr(contact, sizeof(struct ClcContact)))
+ {
+ Cache_GetText(dat,contact,1);
+ cliRecalcScrollBar(hwnd,dat);
+ PostMessage(hwnd,INTM_INVALIDATE,0,0);
+ }
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+}
+
+static LRESULT clcOnIntmNotOnListChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *dbcws = (DBCONTACTWRITESETTING*)lParam;
+ struct ClcContact *contact;
+
+ if ( !FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL,TRUE))
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+
+ if (contact->type != CLCIT_CONTACT)
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+
+ if (dbcws->value.type == DBVT_DELETED || dbcws->value.bVal == 0)
+ contact->flags &= ~CONTACTF_NOTONLIST;
+ else
+ contact->flags |= CONTACTF_NOTONLIST;
+
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+}
+
+static LRESULT clcOnIntmScrollBarChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ if (GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_CONTACTLIST)
+ {
+ if (dat->noVScrollbar) ShowScrollBar(hwnd, SB_VERT, FALSE);
+ else pcli->pfnRecalcScrollBar(hwnd, dat);
+ }
+ return 0;
+}
+
+static LRESULT clcOnIntmStatusChanged(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ int ret = corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ if (wParam != 0)
+ {
+ pdisplayNameCacheEntry pdnce = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry((HANDLE)wParam);
+ if (pdnce && pdnce->m_cache_cszProto)
+ {
+ struct ClcContact *contact = NULL;
+ pdnce___SetStatus( pdnce, GetStatusForContact(pdnce->hContact,pdnce->m_cache_cszProto));
+ if ( !dat->force_in_dialog && (
+ (dat->second_line_show)// && dat->second_line_type == TEXT_STATUS)
+ || (dat->third_line_show)// && dat->third_line_type == TEXT_STATUS)
+ ))
+ gtaRenewText(pdnce->hContact);
+ SendMessage(hwnd,INTM_ICONCHANGED, wParam, (LPARAM) CallService(MS_CLIST_GETCONTACTICON, wParam, 1));
+ if (FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL,TRUE))
+ {
+ if (contact && contact->type == CLCIT_CONTACT)
+ {
+ if ( !contact->image_is_special && pdnce___GetStatus( pdnce )>ID_STATUS_OFFLINE)
+ contact->iImage = CallService(MS_CLIST_GETCONTACTICON, wParam, 1);
+ if (contact->isSubcontact
+ && contact->subcontacts
+ && contact->subcontacts->type == CLCIT_CONTACT)
+ pcli->pfnClcBroadcast( INTM_STATUSCHANGED,(WPARAM)contact->subcontacts->hContact,0); //forward status changing to host meta contact
+ }
+ }
+ }
+#ifdef _DEBUG
+ else
+ {
+ DebugBreak();
+ }
+#endif
+
+
+ }
+ if (db_get_b(NULL,"CList","PlaceOfflineToRoot",SETTING_PLACEOOFLINETOROOT_DEFAULT))
+ {
+ SendMessage(hwnd,CLM_AUTOREBUILD,0,0);
+ }
+ else
+ {
+ pcli->pfnSortContacts();
+ PostMessage(hwnd,INTM_INVALIDATE,0,0);
+ }
+ return ret;
+}
+
+
+
+static LRESULT clcOnIntmReloadOptions(struct ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ pcli->pfnLoadClcOptions(hwnd,dat);
+ LoadCLCOptions(hwnd,dat);
+ pcli->pfnSaveStateAndRebuildList(hwnd,dat);
+ pcli->pfnSortCLC(hwnd,dat,1);
+ if (IsWindowVisible(hwnd))
+ pcli->pfnInvalidateRect(GetParent(hwnd), NULL, FALSE);
+ return TRUE;
+}
+
+
+HRESULT ClcLoadModule()
+{
+ g_himlCListClc = (HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST,0,0);
+
+ HookEvent(ME_DB_CONTACT_SETTINGCHANGED, clcHookSettingChanged);
+ HookEvent(ME_OPT_INITIALISE, ClcOptInit);
+ hAckHook = (HANDLE)HookEvent(ME_PROTO_ACK, clcHookProtoAck);
+ HookEvent(ME_SYSTEM_MODULESLOADED, clcHookModulesLoaded);
+ HookEvent(ME_DB_EVENT_ADDED, clcHookDbEventAdded);
+ return S_OK;
+}
+
+int ClcUnloadModule()
+{
+ if ( g_CluiData.bOldUseGroups != (BYTE)-1 )
+ db_set_b(NULL,"CList","UseGroups",(BYTE)g_CluiData.bOldUseGroups );
+ if ( g_CluiData.boldHideOffline != (BYTE)-1 )
+ db_set_b(NULL,"CList","HideOffline",(BYTE)g_CluiData.boldHideOffline );
+
+ return 0;
+}
+
+int ClcDoProtoAck(HANDLE wParam,ACKDATA * ack)
+{
+ if (MirandaExiting()) return 0;
+ if (ack->type == ACKTYPE_STATUS)
+ {
+ int i;
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ for (i=0; i < pcli->hClcProtoCount; i++)
+ {
+ if ( !lstrcmpA(pcli->clcProto[i].szProto, ack->szModule))
+ {
+ pcli->clcProto[i].dwStatus = (WORD) ack->lParam;
+ if (pcli->clcProto[i].dwStatus >= ID_STATUS_OFFLINE)
+ pcli->pfnTrayIconUpdateBase(pcli->clcProto[i].szProto);
+ if ( !ServiceExists("ExtraIcon/Register"))
+ if (ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_VISMODE) != -1)
+ ExtraImage_SetAllExtraIcons(pcli->hwndContactTree,(HANDLE)NULL);
+ return 0;
+ }
+ }
+ }
+ }
+ else if (ack->type == ACKTYPE_AWAYMSG)
+ {
+ if (ack->result == ACKRESULT_SUCCESS && ack->lParam) {
+ {//Do not change DB if it is IRC protocol
+ if (ack->szModule != NULL)
+ if (db_get_b(ack->hContact, ack->szModule, "ChatRoom", 0) != 0) return 0;
+ }
+
+ db_set_ws(ack->hContact,"CList","StatusMsg",(const TCHAR *)ack->lParam);
+ gtaRenewText(ack->hContact);
+ }
+ else
+ {
+ //DBDeleteContactSetting(ack->hContact,"CList","StatusMsg");
+ //char a = '\0';
+ {//Do not change DB if it is IRC protocol
+ if (ack->szModule != NULL)
+ if (db_get_b(ack->hContact, ack->szModule, "ChatRoom", 0) != 0) return 0;
+ }
+ if (ack->hContact)
+ {
+ char * val = db_get_sa(ack->hContact,"CList","StatusMsg");
+ if (val) {
+ if ( !mir_bool_strcmpi(val,""))
+ db_set_s(ack->hContact,"CList","StatusMsg","");
+ else
+ gtaRenewText(ack->hContact);
+ mir_free(val);
+ }
+ }
+ //pcli->pfnClcBroadcast( INTM_STATUSMSGCHANGED,(WPARAM)ack->hContact,&a);
+ }
+ }
+ else if (ack->type == ACKTYPE_AVATAR)
+ {
+ if (ack->result == ACKRESULT_SUCCESS)
+ {
+ PROTO_AVATAR_INFORMATIONT *pai = (PROTO_AVATAR_INFORMATIONT*)ack->hProcess;
+ if (pai != NULL && pai->hContact != NULL)
+ pcli->pfnClcBroadcast( INTM_AVATARCHANGED,(WPARAM)pai->hContact,0);
+ }
+ }
+ else if (ack->type == ACKTYPE_EMAIL) {
+ CLUIUnreadEmailCountChanged(0,0);
+ }
+ return 0;
+}
+
+
+int ClcGetShortData(struct ClcData* pData, struct SHORTDATA *pShortData)
+{
+ if ( !pData || !pShortData) return -1;
+ pShortData->hWnd = pData->hWnd;
+ pShortData->text_replace_smileys = pData->text_replace_smileys;
+ pShortData->text_smiley_height = pData->text_smiley_height;
+ pShortData->text_use_protocol_smileys = pData->text_use_protocol_smileys;
+ pShortData->contact_time_show_only_if_different = pData->contact_time_show_only_if_different;
+ // Second line
+ pShortData->second_line_show = pData->second_line_show;
+ pShortData->second_line_draw_smileys = pData->second_line_draw_smileys;
+ pShortData->second_line_type = pData->second_line_type;
+
+ _tcsncpy(pShortData->second_line_text,pData->second_line_text,TEXT_TEXT_MAX_LENGTH);
+
+ pShortData->second_line_xstatus_has_priority = pData->second_line_xstatus_has_priority;
+ pShortData->second_line_show_status_if_no_away = pData->second_line_show_status_if_no_away;
+ pShortData->second_line_show_listening_if_no_away = pData->second_line_show_listening_if_no_away;
+ pShortData->second_line_use_name_and_message_for_xstatus = pData->second_line_use_name_and_message_for_xstatus;
+
+ pShortData->third_line_show = pData->third_line_show;
+ pShortData->third_line_draw_smileys = pData->third_line_draw_smileys;
+ pShortData->third_line_type = pData->third_line_type;
+
+ _tcsncpy(pShortData->third_line_text,pData->third_line_text,TEXT_TEXT_MAX_LENGTH);
+
+ pShortData->third_line_xstatus_has_priority = pData->third_line_xstatus_has_priority;
+ pShortData->third_line_show_status_if_no_away = pData->third_line_show_status_if_no_away;
+ pShortData->third_line_show_listening_if_no_away = pData->third_line_show_listening_if_no_away;
+ pShortData->third_line_use_name_and_message_for_xstatus = pData->third_line_use_name_and_message_for_xstatus;
+
+ return 0;
+}
+
+
+
+int ClcEnterDragToScroll(HWND hwnd, int Y)
+{
+ struct ClcData * dat;
+ if (IsDragToScrollMode) return 0;
+ dat = (struct ClcData*)GetWindowLongPtr(hwnd,0);
+ if ( !dat) return 0;
+ StartDragPos = Y;
+ StartScrollPos = dat->yScroll;
+ IsDragToScrollMode = 1;
+ SetCapture(hwnd);
+ return 1;
+}
+
+
+/*
+* Contact list control window procedure
+*/
+LRESULT CALLBACK cli_ContactListControlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+
+#define CASE_MSG_RET(msg, handler) case msg: return handler(dat, hwnd, msg, wParam, lParam);
+
+ struct ClcData *dat = (struct ClcData*)GetWindowLongPtr(hwnd,0);
+
+ if (msg >= CLM_FIRST && msg < CLM_LAST)
+ return cli_ProcessExternalMessages(hwnd,dat,msg,wParam,lParam);
+
+ switch (msg) {
+ CASE_MSG_RET( INTM_GROUPCHANGED, clcOnIntmGroupChanged );
+ CASE_MSG_RET( INTM_ICONCHANGED, clcOnIntmIconChanged );
+ CASE_MSG_RET( INTM_AVATARCHANGED, clcOnIntmAvatarChanged );
+ CASE_MSG_RET( INTM_TIMEZONECHANGED, clcOnIntmTimeZoneChanged );
+ CASE_MSG_RET( INTM_NAMECHANGED, clcOnIntmNameChanged );
+ CASE_MSG_RET( INTM_APPARENTMODECHANGED, clcOnIntmApparentModeChanged );
+ CASE_MSG_RET( INTM_STATUSMSGCHANGED, clcOnIntmStatusMsgChanged );
+ CASE_MSG_RET( INTM_NOTONLISTCHANGED, clcOnIntmNotOnListChanged );
+ CASE_MSG_RET( INTM_SCROLLBARCHANGED, clcOnIntmScrollBarChanged );
+ CASE_MSG_RET( INTM_STATUSCHANGED, clcOnIntmStatusChanged );
+ CASE_MSG_RET( INTM_RELOADOPTIONS, clcOnIntmReloadOptions );
+
+ CASE_MSG_RET( WM_CREATE, clcOnCreate );
+ CASE_MSG_RET( WM_NCHITTEST, clcOnHitTest );
+ CASE_MSG_RET( WM_COMMAND, clcOnCommand );
+ CASE_MSG_RET( WM_SIZE, clcOnSize );
+ CASE_MSG_RET( WM_CHAR, clcOnChar );
+ CASE_MSG_RET( WM_PAINT, clcOnPaint );
+ CASE_MSG_RET( WM_ERASEBKGND, clcOnEraseBkGround );
+ CASE_MSG_RET( WM_KEYDOWN, clcOnKeyDown );
+ CASE_MSG_RET( WM_TIMER, clcOnTimer );
+ CASE_MSG_RET( WM_ACTIVATE, clcOnActivate );
+ CASE_MSG_RET( WM_SETCURSOR, clcOnSetCursor );
+ CASE_MSG_RET( WM_LBUTTONDOWN, clcOnLButtonDown );
+ CASE_MSG_RET( WM_CAPTURECHANGED,clcOnCaptureChanged );
+ CASE_MSG_RET( WM_MOUSEMOVE, clcOnMouseMove );
+ CASE_MSG_RET( WM_LBUTTONUP, clcOnLButtonUp );
+ CASE_MSG_RET( WM_LBUTTONDBLCLK, clcOnLButtonDblClick );
+ CASE_MSG_RET( WM_DESTROY, clcOnDestroy );
+
+ default:
+ return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam);
+ }
+ return TRUE;
+}
diff --git a/plugins/Clist_modern/src/modern_clcidents.cpp b/plugins/Clist_modern/src/modern_clcidents.cpp
new file mode 100644
index 0000000000..903844eb9c
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clcidents.cpp
@@ -0,0 +1,299 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_commonprototypes.h"
+
+#define CacheArrSize 255
+struct ClcGroup *CacheIndex[CacheArrSize] = {NULL};
+bool CacheIndexClear = TRUE;
+
+/* the CLC uses 3 different ways to identify elements in its list, this file
+contains routines to convert between them.
+
+1) struct ClcContact/struct ClcGroup pair. Only ever used within the duration
+of a single operation, but used at some point in nearly everything
+2) index integer. The 0-based number of the item from the top. Only visible
+items are counted (ie not closed groups). Used for saving selection and drag
+highlight
+3) hItem handle. Either the hContact or (hGroup|HCONTACT_ISGROUP). Used
+exclusively externally
+
+1->2: cliGetRowsPriorTo()
+1->3: ContactToHItem()
+3->1: FindItem()
+2->1: GetRowByIndex()
+*/
+
+int GetContactIndex(struct ClcGroup *group,struct ClcContact *contact)
+{
+ for (int i=0; i < group->cl.count; i++)
+ if (group->cl.items[i]->hContact == contact->hContact) return i;
+ return -1;
+}
+
+int cliGetRowsPriorTo(struct ClcGroup *group,struct ClcGroup *subgroup,int contactIndex)
+{
+ int count = 0;
+ BYTE k;
+ int subcontactscount = 0;
+ k = db_get_b(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT);
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL) break;
+ group->scanIndex++;
+ continue;
+ }
+ if (group == subgroup && contactIndex-subcontactscount == group->scanIndex) return count;
+ count++;
+
+ /* if ((group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) && (group->cl.items[group->scanIndex].flags & CONTACTF_STATUSMSG)) {
+ count++;
+ }
+ */
+ if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) {
+ if (group->cl.items[group->scanIndex]->group == subgroup && contactIndex == -1)
+ return count-1;
+ if (group->cl.items[group->scanIndex]->group->expanded) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ subcontactscount = 0;
+ continue;
+ }
+ }
+ if (group == subgroup)
+ {
+ if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->SubAllocated)
+ {
+ int rows = (group->cl.items[group->scanIndex]->SubAllocated*group->cl.items[group->scanIndex]->SubExpanded*k);
+ if (group->scanIndex+rows >= contactIndex)
+ return count+(contactIndex-group->scanIndex)-1;
+ }
+ }
+ if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT)
+ {
+ count += (group->cl.items[group->scanIndex]->SubAllocated*group->cl.items[group->scanIndex]->SubExpanded*k);
+ subcontactscount += (group->cl.items[group->scanIndex]->SubAllocated*group->cl.items[group->scanIndex]->SubExpanded*k);
+ }
+ group->scanIndex++;
+ }
+ return -1;
+}
+
+int cliFindItem(HWND hwnd,struct ClcData *dat,HANDLE hItem,struct ClcContact **contact,struct ClcGroup **subgroup,int *isVisible)
+{
+ return FindItem(hwnd,dat, hItem,contact,subgroup,isVisible,FALSE);
+}
+
+int FindItem(HWND hwnd,struct ClcData *dat,HANDLE hItem,struct ClcContact **contact,struct ClcGroup **subgroup,int *isVisible, BOOL isIgnoreSubcontacts)
+{
+ int index = 0, i;
+ int nowVisible = 1;
+ struct ClcGroup *group;
+
+ group = &dat->list;
+
+ group->scanIndex = 0;
+ group = &dat->list;
+
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ struct ClcGroup *tgroup;
+ group = group->parent;
+ if (group == NULL) break;
+ nowVisible = 1;
+ for (tgroup = group;tgroup;tgroup = tgroup->parent)
+ {
+ if ( !tgroup->expanded)
+ {
+ nowVisible = 0;
+ break;
+ }
+ }
+ group->scanIndex++;
+ continue;
+ }
+ if (nowVisible) index++;
+ if ((IsHContactGroup(hItem) && group->cl.items[group->scanIndex]->type == CLCIT_GROUP && ((UINT_PTR)hItem&~HCONTACT_ISGROUP) == group->cl.items[group->scanIndex]->groupId) ||
+ (IsHContactContact(hItem) && group->cl.items[group->scanIndex]->type == CLCIT_CONTACT && group->cl.items[group->scanIndex]->hContact == hItem) ||
+ (IsHContactInfo(hItem) && group->cl.items[group->scanIndex]->type == CLCIT_INFO && group->cl.items[group->scanIndex]->hContact == (HANDLE)((UINT_PTR)hItem&~HCONTACT_ISINFO)))
+ {
+ if (isVisible) {
+ if ( !nowVisible) *isVisible = 0;
+ else {
+ int posy = cliGetRowTopY(dat,index+1);
+ if (posy < dat->yScroll)
+ *isVisible = 0;
+ else {
+ RECT clRect;
+ GetClientRect(hwnd,&clRect);
+ if (posy >= dat->yScroll+clRect.bottom) *isVisible = 0;
+ else *isVisible = 1;
+ }
+ }
+ }
+ if (contact) *contact = group->cl.items[group->scanIndex];
+ if (subgroup) *subgroup = group;
+
+ return 1;
+ }
+ if ( !isIgnoreSubcontacts &&
+ IsHContactContact(hItem) &&
+ group->cl.items[group->scanIndex]->type == CLCIT_CONTACT &&
+ group->cl.items[group->scanIndex]->SubAllocated > 0)
+ {
+ for (i=0; i < group->cl.items[group->scanIndex]->SubAllocated; i++)
+ {
+ if (group->cl.items[group->scanIndex]->subcontacts[i].hContact == hItem)
+ {
+#ifdef _DEBUG
+ if (IsBadWritePtr(&group->cl.items[group->scanIndex]->subcontacts[i], sizeof(struct ClcContact)))
+ {
+ log1("FindIltem->IsBadWritePtr | 2o [%08x]", &group->cl.items[group->scanIndex]->subcontacts[i]);
+ PostMessage(hwnd,CLM_AUTOREBUILD,0,0);
+
+ return 0;
+ }
+#endif
+ if (contact) *contact = &group->cl.items[group->scanIndex]->subcontacts[i];
+ if (subgroup) *subgroup = group;
+
+ return 1;
+ }
+ }
+ }
+
+ if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ nowVisible &= group->expanded;
+ continue;
+ }
+ group->scanIndex++;
+ }
+
+ return 0;
+}
+
+void ClearRowByIndexCache()
+{
+ if ( !CacheIndexClear)
+ {
+ memset(CacheIndex,0,sizeof(CacheIndex));
+ CacheIndexClear = TRUE;
+ };
+}
+int cliGetRowByIndex(struct ClcData *dat,int testindex,struct ClcContact **contact,struct ClcGroup **subgroup)
+{
+ int index = 0,i;
+ struct ClcGroup *group = &dat->list;
+
+ if (testindex < 0) return (-1);
+ {
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL) break;
+ group->scanIndex++;
+ continue;
+ }
+ if ((index>0) && (index < CacheArrSize))
+ {
+ CacheIndex[index] = group;
+ CacheIndexClear = FALSE;
+ };
+
+ if (testindex == index) {
+ if (contact) *contact = group->cl.items[group->scanIndex];
+ if (subgroup) *subgroup = group;
+ return index;
+ }
+
+ if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT)
+ if (group->cl.items[group->scanIndex]->SubAllocated)
+ if (group->cl.items[group->scanIndex]->SubExpanded && dat->expandMeta)
+ {
+ for (i=0;i < group->cl.items[group->scanIndex]->SubAllocated;i++)
+ {
+ if ((index>0) && (index < CacheArrSize))
+ {
+ CacheIndex[index] = group;
+ CacheIndexClear = FALSE;
+ };
+ index++;
+ if (testindex == index) {
+ if (contact)
+ {
+ *contact = &group->cl.items[group->scanIndex]->subcontacts[i];
+ (*contact)->subcontacts = group->cl.items[group->scanIndex];
+ }
+
+ if (subgroup) *subgroup = group;
+ return index;
+ }
+ }
+
+ }
+ index++;
+ if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP && group->cl.items[group->scanIndex]->group->expanded) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ continue;
+ }
+ group->scanIndex++;
+ }
+ };
+ return -1;
+}
+
+HANDLE ContactToHItem(struct ClcContact *contact)
+{
+ switch(contact->type) {
+case CLCIT_CONTACT:
+ return contact->hContact;
+case CLCIT_GROUP:
+ return (HANDLE)(contact->groupId|HCONTACT_ISGROUP);
+case CLCIT_INFO:
+ return (HANDLE)((DWORD_PTR)contact->hContact|HCONTACT_ISINFO);
+ }
+ return NULL;
+}
+
+HANDLE ContactToItemHandle(struct ClcContact *contact,DWORD *nmFlags)
+{
+ switch(contact->type) {
+case CLCIT_CONTACT:
+ return contact->hContact;
+case CLCIT_GROUP:
+ if (nmFlags) *nmFlags |= CLNF_ISGROUP;
+ return (HANDLE)contact->groupId;
+case CLCIT_INFO:
+ if (nmFlags) *nmFlags |= CLNF_ISINFO;
+ return (HANDLE)((DWORD_PTR)contact->hContact|HCONTACT_ISINFO);
+ }
+ return NULL;
+} \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_clcitems.cpp b/plugins/Clist_modern/src/modern_clcitems.cpp
new file mode 100644
index 0000000000..7a29b5e82a
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clcitems.cpp
@@ -0,0 +1,819 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_clist.h"
+#include "m_metacontacts.h"
+#include "hdr/modern_commonprototypes.h"
+
+void AddSubcontacts(struct ClcData *dat, struct ClcContact * cont, BOOL showOfflineHereGroup)
+{
+ int subcount,i,j;
+ HANDLE hsub;
+ pdisplayNameCacheEntry cacheEntry;
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(cont->hContact);
+ cont->SubExpanded = (db_get_b(cont->hContact,"CList","Expanded",0) && (db_get_b(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT)));
+ subcount = (int)CallService(MS_MC_GETNUMCONTACTS,(WPARAM)cont->hContact,0);
+
+ if (subcount <= 0) {
+ cont->isSubcontact = 0;
+ cont->subcontacts = NULL;
+ cont->SubAllocated = 0;
+ return;
+ }
+
+ cont->isSubcontact = 0;
+ mir_free(cont->subcontacts);
+ cont->subcontacts = (struct ClcContact *) mir_calloc(sizeof(struct ClcContact)*subcount);
+ cont->SubAllocated = subcount;
+ i=0;
+ for (j = 0; j < subcount; j++) {
+ WORD wStatus;
+
+ hsub = (HANDLE)CallService(MS_MC_GETSUBCONTACT,(WPARAM)cont->hContact,j);
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hsub);
+ wStatus = pdnce___GetStatus( cacheEntry );
+ if (showOfflineHereGroup || (!(db_get_b(NULL,"CLC","MetaHideOfflineSub",SETTING_METAHIDEOFFLINESUB_DEFAULT) && db_get_b(NULL,"CList","HideOffline",SETTING_HIDEOFFLINE_DEFAULT)) ||
+ wStatus != ID_STATUS_OFFLINE )
+ // &&
+ //(!cacheEntry->Hidden || style&CLS_SHOWHIDDEN)
+ )
+
+ {
+ cont->subcontacts[i].hContact = cacheEntry->hContact;
+
+ cont->subcontacts[i].avatar_pos = AVATAR_POS_DONT_HAVE;
+ Cache_GetAvatar(dat, &cont->subcontacts[i]);
+
+ cont->subcontacts[i].iImage = CallService(MS_CLIST_GETCONTACTICON,(WPARAM)cacheEntry->hContact,1);
+ memset(cont->subcontacts[i].iExtraImage,0xFF,sizeof(cont->subcontacts[i].iExtraImage));
+ memset((void*)cont->subcontacts[i].iWideExtraImage,0xFF,sizeof(cont->subcontacts[i].iWideExtraImage));
+ cont->subcontacts[i].proto = cacheEntry->m_cache_cszProto;
+ cont->subcontacts[i].type = CLCIT_CONTACT;
+ cont->subcontacts[i].flags = 0;//CONTACTF_ONLINE;
+ cont->subcontacts[i].isSubcontact = i+1;
+ cont->subcontacts[i].lastPaintCounter = 0;
+ cont->subcontacts[i].subcontacts = cont;
+ cont->subcontacts[i].image_is_special = FALSE;
+ //cont->subcontacts[i].status = cacheEntry->status;
+ Cache_GetTimezone(dat, (&cont->subcontacts[i])->hContact);
+ Cache_GetText(dat, &cont->subcontacts[i],1);
+
+ {
+ int apparentMode;
+ char *szProto;
+ int idleMode;
+ szProto = cacheEntry->m_cache_cszProto;
+ if (szProto != NULL && !pcli->pfnIsHiddenMode(dat,wStatus))
+ cont->subcontacts[i].flags |= CONTACTF_ONLINE;
+ apparentMode = szProto != NULL?cacheEntry->ApparentMode:0;
+ apparentMode = szProto != NULL?cacheEntry->ApparentMode:0;
+ if (apparentMode == ID_STATUS_OFFLINE) cont->subcontacts[i].flags |= CONTACTF_INVISTO;
+ else if (apparentMode == ID_STATUS_ONLINE) cont->subcontacts[i].flags |= CONTACTF_VISTO;
+ else if (apparentMode) cont->subcontacts[i].flags |= CONTACTF_VISTO|CONTACTF_INVISTO;
+ if (cacheEntry->NotOnList) cont->subcontacts[i].flags |= CONTACTF_NOTONLIST;
+ idleMode = szProto != NULL?cacheEntry->IdleTS:0;
+ if (idleMode) cont->subcontacts[i].flags |= CONTACTF_IDLE;
+ }
+ i++;
+ } }
+
+ cont->SubAllocated = i;
+ if ( !i && cont->subcontacts != NULL)
+ mir_free_and_nil(cont->subcontacts);
+}
+
+int cli_AddItemToGroup(struct ClcGroup *group,int iAboveItem)
+{
+ if ( group == NULL ) return 0;
+
+ iAboveItem = corecli.pfnAddItemToGroup( group, iAboveItem );
+ ClearRowByIndexCache();
+ return iAboveItem;
+}
+
+struct ClcGroup *cli_AddGroup(HWND hwnd,struct ClcData *dat,const TCHAR *szName,DWORD flags,int groupId,int calcTotalMembers)
+{
+ struct ClcGroup* result;
+ ClearRowByIndexCache();
+ if ( !dat->force_in_dialog && !(GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_SHOWHIDDEN))
+ if ( !lstrcmp(_T("-@-HIDDEN-GROUP-@-"),szName)) //group is hidden
+ {
+ ClearRowByIndexCache();
+ return NULL;
+ }
+ result = corecli.pfnAddGroup( hwnd, dat, szName, flags, groupId, calcTotalMembers);
+ /* ToDo: fix some times valid contact with valid group are placed to root
+ if ( result == NULL )
+ {
+ result = &dat->list;
+ }
+ */
+ ClearRowByIndexCache();
+ return result;
+}
+
+void cli_FreeContact(struct ClcContact *p)
+{
+ if ( p->SubAllocated) {
+ if ( p->subcontacts && !p->isSubcontact) {
+ int i;
+ for ( i=0 ; i < p->SubAllocated ; i++ ) {
+ p->subcontacts[i].ssText.DestroySmileyList();
+ if ( p->subcontacts[i].avatar_pos == AVATAR_POS_ANIMATED )
+ AniAva_RemoveAvatar( p->subcontacts[i].hContact );
+ p->subcontacts[i].avatar_pos = AVATAR_POS_DONT_HAVE;
+ }
+ mir_free_and_nil(p->subcontacts);
+ } }
+
+ p->ssText.DestroySmileyList();
+ if ( p->avatar_pos == AVATAR_POS_ANIMATED )
+ AniAva_RemoveAvatar( p->hContact );
+ p->avatar_pos = AVATAR_POS_DONT_HAVE;
+ corecli.pfnFreeContact( p );
+}
+
+void cli_FreeGroup( struct ClcGroup* group )
+{
+ corecli.pfnFreeGroup( group );
+ ClearRowByIndexCache();
+}
+
+int cli_AddInfoItemToGroup(struct ClcGroup *group,int flags,const TCHAR *pszText)
+{
+ int i = corecli.pfnAddInfoItemToGroup( group, flags, pszText );
+ ClearRowByIndexCache();
+ return i;
+}
+
+static void _LoadDataToContact(struct ClcContact * cont, struct ClcGroup *group, struct ClcData *dat, HANDLE hContact)
+{
+ pdisplayNameCacheEntry cacheEntry = NULL;
+ WORD apparentMode;
+ DWORD idleMode;
+ char * szProto;
+
+ if ( !cont) return;
+ cont->type = CLCIT_CONTACT;
+ cont->SubAllocated = 0;
+ cont->isSubcontact = 0;
+ cont->subcontacts = NULL;
+ cont->szText[0] = 0;
+ cont->lastPaintCounter = 0;
+ cont->image_is_special = FALSE;
+ cont->hContact = hContact;
+
+ pcli->pfnInvalidateDisplayNameCacheEntry(hContact);
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+
+ szProto = cacheEntry->m_cache_cszProto;
+ cont->proto = szProto;
+
+ if (szProto != NULL && !pcli->pfnIsHiddenMode(dat,pdnce___GetStatus( cacheEntry )))
+ cont->flags |= CONTACTF_ONLINE;
+
+ apparentMode = szProto != NULL?cacheEntry->ApparentMode:0;
+
+ if (apparentMode)
+ switch (apparentMode)
+ {
+ case ID_STATUS_OFFLINE:
+ cont->flags |= CONTACTF_INVISTO;
+ break;
+ case ID_STATUS_ONLINE:
+ cont->flags |= CONTACTF_VISTO;
+ break;
+ default:
+ cont->flags |= CONTACTF_VISTO|CONTACTF_INVISTO;
+ }
+
+ if (cacheEntry->NotOnList)
+ cont->flags |= CONTACTF_NOTONLIST;
+ idleMode = szProto != NULL?cacheEntry->IdleTS:0;
+
+ if (idleMode)
+ cont->flags |= CONTACTF_IDLE;
+
+
+ //Add subcontacts
+ if (szProto)
+ {
+ if ( g_szMetaModuleName && dat->IsMetaContactsEnabled && mir_strcmp(cont->proto,g_szMetaModuleName) == 0)
+ AddSubcontacts(dat,cont,CLCItems_IsShowOfflineGroup(group));
+ }
+ cont->lastPaintCounter = 0;
+ cont->avatar_pos = AVATAR_POS_DONT_HAVE;
+ Cache_GetAvatar(dat,cont);
+ Cache_GetText(dat,cont,1);
+ Cache_GetTimezone(dat,cont->hContact);
+ cont->iImage = CallService(MS_CLIST_GETCONTACTICON,(WPARAM)hContact,1);
+ cont->bContactRate = db_get_b(hContact, "CList", "Rate",0);
+}
+
+static struct ClcContact * AddContactToGroup(struct ClcData *dat,struct ClcGroup *group, pdisplayNameCacheEntry cacheEntry)
+{
+ HANDLE hContact;
+ int i;
+ if (cacheEntry == NULL) return NULL;
+ if (group == NULL) return NULL;
+ if (dat == NULL) return NULL;
+ hContact = cacheEntry->hContact;
+ dat->NeedResort = 1;
+ for (i = group->cl.count-1;i >= 0;i--)
+ if (group->cl.items[i]->type != CLCIT_INFO || !(group->cl.items[i]->flags&CLCIIF_BELOWCONTACTS)) break;
+ i = cli_AddItemToGroup(group,i+1);
+
+ _LoadDataToContact(group->cl.items[i], group, dat, hContact);
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ ClearRowByIndexCache();
+ return group->cl.items[i];
+}
+
+void * AddTempGroup(HWND hwnd,struct ClcData *dat,const TCHAR *szName,DWORD flags,int groupId,int calcTotalMembers)
+{
+ int i=0;
+ int f = 0;
+ TCHAR * szGroupName;
+ DWORD groupFlags;
+
+ if ( wildcmp( _T2A(szName), "-@-HIDDEN-GROUP-@-",0))
+ return NULL;
+
+ for (i = 1;;i++) {
+ szGroupName = pcli->pfnGetGroupName(i,&groupFlags);
+ if (szGroupName == NULL) break;
+ if ( !mir_tstrcmpi(szGroupName,szName)) f = 1;
+ }
+ if ( !f)
+ {
+ char buf[20];
+ TCHAR b2[255];
+ void * res = NULL;
+ mir_snprintf(buf,SIZEOF(buf),"%d",(i-1));
+ mir_sntprintf(b2,SIZEOF(b2),_T("#%s"),szName);
+ b2[0] = 1|GROUPF_EXPANDED;
+ db_set_ws(NULL,"CListGroups",buf,b2);
+ pcli->pfnGetGroupName(i,&groupFlags);
+ res = cli_AddGroup(hwnd,dat,szName,groupFlags,i,0);
+ return res;
+ }
+ return NULL;
+}
+
+void cli_AddContactToTree(HWND hwnd,struct ClcData *dat,HANDLE hContact,int updateTotalCount,int checkHideOffline)
+{
+ struct ClcGroup *group;
+ struct ClcContact * cont;
+ pdisplayNameCacheEntry cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ if (dat->IsMetaContactsEnabled && cacheEntry && cacheEntry->m_cache_nHiddenSubcontact) return; //contact should not be added
+ if ( !dat->IsMetaContactsEnabled && cacheEntry && g_szMetaModuleName && !mir_strcmp(cacheEntry->m_cache_cszProto,g_szMetaModuleName)) return;
+ corecli.pfnAddContactToTree(hwnd,dat,hContact,updateTotalCount,checkHideOffline);
+ if (FindItem(hwnd,dat,hContact,&cont,&group,NULL,FALSE))
+ _LoadDataToContact(cont, group, dat, hContact);
+ return;
+}
+
+void cli_DeleteItemFromTree(HWND hwnd,HANDLE hItem)
+{
+ struct ClcData *dat = (struct ClcData *) GetWindowLongPtr(hwnd, 0);
+ ClearRowByIndexCache();
+ corecli.pfnDeleteItemFromTree(hwnd, hItem);
+
+ //check here contacts are not resorting
+ if (hwnd == pcli->hwndContactTree)
+ pcli->pfnFreeCacheItem(pcli->pfnGetCacheEntry(hItem));
+ dat->NeedResort = 1;
+ ClearRowByIndexCache();
+}
+
+
+__inline BOOL CLCItems_IsShowOfflineGroup(struct ClcGroup* group)
+{
+ DWORD groupFlags = 0;
+ if ( !group) return FALSE;
+ if (group->hideOffline) return FALSE;
+ pcli->pfnGetGroupName(group->groupId,&groupFlags);
+ return (groupFlags&GROUPF_SHOWOFFLINE) != 0;
+}
+
+HANDLE SaveSelection( struct ClcData *dat )
+{
+ ClcContact * selcontact = NULL;
+
+ if ( pcli->pfnGetRowByIndex( dat, dat->selection, &selcontact, NULL ) == -1 )
+ return NULL;
+ else
+ return pcli->pfnContactToHItem( selcontact );
+}
+
+int RestoreSelection( struct ClcData *dat, HANDLE hSelected )
+{
+ ClcContact * selcontact = NULL;
+ ClcGroup * selgroup = NULL;
+
+ if ( !hSelected || !pcli->pfnFindItem( dat->hWnd, dat, hSelected, &selcontact, &selgroup, NULL))
+ {
+ dat->selection = -1;
+ return dat->selection;
+ }
+
+ if ( !selcontact->isSubcontact )
+ {
+ dat->selection = pcli->pfnGetRowsPriorTo( &dat->list, selgroup, List_IndexOf((SortedList*)&selgroup->cl, selcontact ));
+ }
+ else
+ {
+ dat->selection = pcli->pfnGetRowsPriorTo(&dat->list, selgroup, List_IndexOf((SortedList*)&selgroup->cl, selcontact->subcontacts ));
+
+ if (dat->selection != -1 )
+ dat->selection += selcontact->isSubcontact;
+ }
+ return dat->selection;
+
+}
+
+void cliRebuildEntireList(HWND hwnd,struct ClcData *dat)
+{
+ DWORD style = GetWindowLongPtr(hwnd,GWL_STYLE);
+ HANDLE hContact;
+ struct ClcContact * cont;
+ struct ClcGroup *group;
+ static int rebuildCounter = 0;
+
+ BOOL PlaceOfflineToRoot = db_get_b(NULL,"CList","PlaceOfflineToRoot",SETTING_PLACEOFFLINETOROOT_DEFAULT);
+ KillTimer(hwnd,TIMERID_REBUILDAFTER);
+
+ ClearRowByIndexCache();
+ ImageArray_Clear(&dat->avatar_cache);
+ RowHeights_Clear(dat);
+ RowHeights_GetMaxRowHeight(dat, hwnd);
+ TRACEVAR("Rebuild Entire List %d times\n",++rebuildCounter);
+
+ dat->list.expanded = 1;
+ dat->list.hideOffline = db_get_b(NULL,"CLC","HideOfflineRoot",SETTING_HIDEOFFLINEATROOT_DEFAULT) && style&CLS_USEGROUPS;
+ dat->list.cl.count = dat->list.cl.limit = 0;
+ dat->list.cl.increment = 50;
+ dat->NeedResort = 1;
+
+ HANDLE hSelected = SaveSelection( dat );
+ dat->selection = -1;
+ dat->HiLightMode = db_get_b(NULL,"CLC","HiLightMode",SETTING_HILIGHTMODE_DEFAULT);
+ {
+ int i;
+ TCHAR *szGroupName;
+ DWORD groupFlags;
+
+ for (i = 1;;i++) {
+ szGroupName = pcli->pfnGetGroupName(i,&groupFlags); //UNICODE
+ if (szGroupName == NULL) break;
+ cli_AddGroup(hwnd,dat,szGroupName,groupFlags,i,0);
+ }
+ }
+
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ while(hContact)
+ {
+ pdisplayNameCacheEntry cacheEntry = NULL;
+ int nHiddenStatus;
+ cont = NULL;
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+
+ nHiddenStatus = CLVM_GetContactHiddenStatus(hContact, NULL, dat);
+ if ((style&CLS_SHOWHIDDEN && nHiddenStatus != -1) || !nHiddenStatus)
+ {
+
+ if (lstrlen(cacheEntry->tszGroup) == 0)
+ group = &dat->list;
+ else {
+ group = cli_AddGroup(hwnd,dat,cacheEntry->tszGroup,(DWORD)-1,0,0);
+ }
+ if (group != NULL)
+ {
+ WORD wStatus = pdnce___GetStatus( cacheEntry );
+ if (wStatus == ID_STATUS_OFFLINE)
+ if (PlaceOfflineToRoot)
+ group = &dat->list;
+ group->totalMembers++;
+
+ if ( !(style&CLS_NOHIDEOFFLINE) && (style&CLS_HIDEOFFLINE || group->hideOffline))
+ {
+ if (cacheEntry->m_cache_cszProto == NULL) {
+ if ( !pcli->pfnIsHiddenMode(dat,ID_STATUS_OFFLINE) || cacheEntry->m_cache_nNoHiddenOffline || CLCItems_IsShowOfflineGroup(group))
+ cont = AddContactToGroup(dat,group,cacheEntry);
+ }
+ else
+ if ( !pcli->pfnIsHiddenMode(dat,wStatus) || cacheEntry->m_cache_nNoHiddenOffline || CLCItems_IsShowOfflineGroup(group))
+ cont = AddContactToGroup(dat,group,cacheEntry);
+ }
+ else cont = AddContactToGroup(dat,group,cacheEntry);
+ }
+ }
+ if (cont)
+ {
+ cont->SubAllocated = 0;
+ if (cont->proto && g_szMetaModuleName && dat->IsMetaContactsEnabled && strcmp(cont->proto,g_szMetaModuleName) == 0)
+ AddSubcontacts(dat,cont,CLCItems_IsShowOfflineGroup(group));
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0);
+ }
+
+ if (style&CLS_HIDEEMPTYGROUPS) {
+ group = &dat->list;
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL) break;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) {
+ if (group->cl.items[group->scanIndex]->group->cl.count == 0) {
+ group = pcli->pfnRemoveItemFromGroup(hwnd,group,group->cl.items[group->scanIndex],0);
+ }
+ else {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ }
+ continue;
+ }
+ group->scanIndex++;
+ }
+ }
+
+ pcli->pfnSortCLC(hwnd,dat,0);
+
+ RestoreSelection( dat, hSelected );
+
+}
+
+void cli_SortCLC( HWND hwnd, struct ClcData *dat, int useInsertionSort )
+{
+ HANDLE hSelected = SaveSelection( dat );
+
+ corecli.pfnSortCLC(hwnd,dat,useInsertionSort);
+
+ RestoreSelection( dat, hSelected );
+}
+
+int GetNewSelection(struct ClcGroup *group, int selection, int direction)
+{
+ int lastcount = 0, count = 0;//group->cl.count;
+ if (selection < 0) {
+ return 0;
+ }
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL) break;
+ group->scanIndex++;
+ continue;
+ }
+ if (count >= selection) return count;
+ lastcount = count;
+ count++;
+ if ( !direction) {
+ if (count>selection) return lastcount;
+ }
+ if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP && (group->cl.items[group->scanIndex]->group->expanded)) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ continue;
+ }
+ group->scanIndex++;
+ }
+ return lastcount;
+}
+
+struct SavedContactState_t {
+ HANDLE hContact;
+ BYTE iExtraImage[MAXEXTRACOLUMNS];
+ WORD iWideExtraImage[MAXEXTRACOLUMNS];
+ int checked;
+};
+
+struct SavedGroupState_t {
+ int groupId,expanded;
+};
+
+struct SavedInfoState_t {
+ int parentId;
+ struct ClcContact contact;
+};
+
+BOOL LOCK_RECALC_SCROLLBAR = FALSE;
+void cli_SaveStateAndRebuildList(HWND hwnd, struct ClcData *dat)
+{
+ LOCK_RECALC_SCROLLBAR = TRUE;
+
+ NMCLISTCONTROL nm;
+ int i, j;
+ OBJLIST<SavedGroupState_t> savedGroup( 4 );
+ OBJLIST<SavedContactState_t> savedContact( 4 );
+ OBJLIST<SavedInfoState_t> savedInfo( 4 );
+
+ struct ClcGroup *group;
+ struct ClcContact *contact;
+
+ pcli->pfnHideInfoTip(hwnd, dat);
+ KillTimer(hwnd, TIMERID_INFOTIP);
+ KillTimer(hwnd, TIMERID_RENAME);
+ pcli->pfnEndRename(hwnd, dat, 1);
+
+ dat->NeedResort = 1;
+ group = &dat->list;
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL)
+ break;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+
+ SavedGroupState_t* p = new SavedGroupState_t;
+ p->groupId = group->groupId;
+ p->expanded = group->expanded;
+ savedGroup.insert( p );
+ continue;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) {
+ SavedContactState_t* p = new SavedContactState_t;
+ p->hContact = group->cl.items[group->scanIndex]->hContact;
+ CopyMemory(p->iExtraImage, group->cl.items[group->scanIndex]->iExtraImage,
+ sizeof(group->cl.items[group->scanIndex]->iExtraImage));
+
+ CopyMemory((void*)p->iWideExtraImage, (void*)group->cl.items[group->scanIndex]->iWideExtraImage,
+ sizeof(group->cl.items[group->scanIndex]->iWideExtraImage));
+
+ p->checked = group->cl.items[group->scanIndex]->flags & CONTACTF_CHECKED;
+ savedContact.insert( p );
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_INFO) {
+ SavedInfoState_t* p = new SavedInfoState_t;
+ memset( p, 0, sizeof( SavedInfoState_t ));
+ if (group->parent == NULL)
+ p->parentId = -1;
+ else
+ p->parentId = group->groupId;
+ p->contact = *group->cl.items[group->scanIndex];
+ savedInfo.insert( p );
+ }
+ group->scanIndex++;
+ }
+
+ pcli->pfnFreeGroup(&dat->list);
+ pcli->pfnRebuildEntireList(hwnd, dat);
+
+ group = &dat->list;
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL)
+ break;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ for (i=0; i < savedGroup.getCount(); i++)
+ if (savedGroup[i].groupId == group->groupId) {
+ group->expanded = savedGroup[i].expanded;
+ break;
+ }
+ continue;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) {
+ for (i=0; i < savedContact.getCount(); i++)
+ if (savedContact[i].hContact == group->cl.items[group->scanIndex]->hContact) {
+ CopyMemory(group->cl.items[group->scanIndex]->iExtraImage, savedContact[i].iExtraImage,
+ sizeof(group->cl.items[group->scanIndex]->iExtraImage));
+
+ CopyMemory((void*)group->cl.items[group->scanIndex]->iWideExtraImage, (void*)savedContact[i].iWideExtraImage,
+ sizeof(group->cl.items[group->scanIndex]->iWideExtraImage));
+
+ if (savedContact[i].checked)
+ group->cl.items[group->scanIndex]->flags |= CONTACTF_CHECKED;
+ break;
+ }
+ }
+ group->scanIndex++;
+ }
+ savedGroup.destroy();
+ savedContact.destroy();
+
+ for (i=0; i < savedInfo.getCount(); i++) {
+ if (savedInfo[i].parentId == -1)
+ group = &dat->list;
+ else {
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) (savedInfo[i].parentId | HCONTACT_ISGROUP), &contact, NULL, NULL))
+ continue;
+ group = contact->group;
+ }
+ j = pcli->pfnAddInfoItemToGroup(group, savedInfo[i].contact.flags, _T(""));
+ *group->cl.items[j] = savedInfo[i].contact;
+ }
+ savedInfo.destroy();
+
+ LOCK_RECALC_SCROLLBAR = FALSE;
+ pcli->pfnRecalculateGroupCheckboxes(hwnd, dat);
+
+ pcli->pfnRecalcScrollBar(hwnd, dat);
+ nm.hdr.code = CLN_LISTREBUILT;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM) & nm);
+}
+
+
+WORD pdnce___GetStatus(pdisplayNameCacheEntry pdnce)
+{
+ if ( !pdnce)
+ return ID_STATUS_OFFLINE;
+ else
+ return pdnce->m_cache_nStatus;
+ /*
+ // this stub will replace direct usage of m_cache_nStatus and will be substituted by getting info from DB directrly
+ if ( !pdnce) return ID_STATUS_OFFLINE;
+ if ( !pdnce->m_cache_cszProto) return ID_STATUS_OFFLINE;
+ if ( !pdnce->hContact) return ID_STATUS_OFFLINE;
+ return DBGetContactSettingWord( pdnce->hContact, pdnce->m_cache_cszProto, "Status" , ID_STATUS_OFFLINE );
+ */
+}
+
+
+void pdnce___SetStatus( pdisplayNameCacheEntry pdnce, WORD wStatus )
+{
+ if (pdnce) pdnce->m_cache_nStatus = wStatus;
+}
+struct ClcContact* cliCreateClcContact( void )
+{
+ struct ClcContact* contact = (struct ClcContact*)mir_calloc(sizeof( struct ClcContact ));
+ memset((void*)contact->iWideExtraImage,0xFF,sizeof(contact->iWideExtraImage));
+ return contact;
+}
+
+ClcCacheEntryBase* cliCreateCacheItem( HANDLE hContact )
+{
+ pdisplayNameCacheEntry p = (pdisplayNameCacheEntry)mir_calloc(sizeof( displayNameCacheEntry ));
+ if ( p )
+ {
+ memset(p,0,sizeof( displayNameCacheEntry ));
+ p->hContact = hContact;
+ InvalidateDNCEbyPointer(hContact,p,0);
+ p->szSecondLineText = NULL;
+ p->szThirdLineText = NULL;
+ p->ssSecondLine.plText = NULL;
+ p->ssThirdLine.plText = NULL;
+ }
+ return (ClcCacheEntryBase*)p;
+}
+
+
+
+void cliInvalidateDisplayNameCacheEntry(HANDLE hContact)
+{
+ pdisplayNameCacheEntry p;
+ p = (pdisplayNameCacheEntry) pcli->pfnGetCacheEntry(hContact);
+ if (p) InvalidateDNCEbyPointer(hContact,p,0);
+ return;
+}
+
+char* cli_GetGroupCountsText(struct ClcData *dat, struct ClcContact *contact)
+{
+ char * res;
+
+ res = corecli.pfnGetGroupCountsText(dat, contact);
+
+ return res;
+}
+
+int cliGetGroupContentsCount(struct ClcGroup *group, int visibleOnly)
+{
+ int count = group->cl.count;
+ struct ClcGroup *topgroup = group;
+
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ if (group == topgroup)
+ break;
+ group = group->parent;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP && (!(visibleOnly&0x01) || group->cl.items[group->scanIndex]->group->expanded)) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ count += group->cl.count;
+ continue;
+ }
+ else if ((group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) &&
+ (group->cl.items[group->scanIndex]->subcontacts != NULL) &&
+ ((group->cl.items[group->scanIndex]->SubExpanded || (!visibleOnly))))
+ {
+ count += group->cl.items[group->scanIndex]->SubAllocated;
+ }
+ group->scanIndex++;
+ }
+ return count;
+}
+
+/*
+* checks the currently active view mode filter and returns true, if the contact should be hidden
+* if no view mode is active, it returns the CList/Hidden setting
+* also cares about sub contacts (if meta is active)
+*/
+
+int __fastcall CLVM_GetContactHiddenStatus(HANDLE hContact, char *szProto, struct ClcData *dat)
+{
+ int dbHidden = db_get_b(hContact, "CList", "Hidden", 0); // default hidden state, always respect it.
+ int filterResult = 1;
+ DBVARIANT dbv = {0};
+ char szTemp[64];
+ TCHAR szGroupMask[256];
+ DWORD dwLocalMask;
+ PDNCE pdnce = (PDNCE)pcli->pfnGetCacheEntry(hContact);
+ BOOL fEmbedded = dat->force_in_dialog;
+ // always hide subcontacts (but show them on embedded contact lists)
+
+ if (g_CluiData.bMetaAvail && dat != NULL && dat->IsMetaContactsEnabled && g_szMetaModuleName && db_get_b(hContact, g_szMetaModuleName, "IsSubcontact", 0))
+ return -1; //subcontact
+ if (pdnce && pdnce->isUnknown && !fEmbedded)
+ return 1; //'Unknown Contact'
+ if (pdnce && g_CluiData.bFilterEffective && !fEmbedded)
+ {
+ if (szProto == NULL)
+ szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ // check stickies first (priority), only if we really have stickies defined (CLVM_STICKY_CONTACTS is set).
+ if (g_CluiData.bFilterEffective & CLVM_STICKY_CONTACTS)
+ {
+ if ((dwLocalMask = db_get_dw(hContact, CLVM_MODULE, g_CluiData.current_viewmode, 0)) != 0) {
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_STICKYSTATUS)
+ {
+ WORD wStatus = db_get_w(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ return !((1 << (wStatus - ID_STATUS_OFFLINE)) & HIWORD(dwLocalMask));
+ }
+ return 0;
+ }
+ }
+ // check the proto, use it as a base filter result for all further checks
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_PROTOS) {
+ mir_snprintf(szTemp, SIZEOF(szTemp), "%s|", szProto);
+ filterResult = strstr(g_CluiData.protoFilter, szTemp) ? 1 : 0;
+ }
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_GROUPS) {
+ if ( !DBGetContactSettingTString(hContact, "CList", "Group", &dbv)) {
+ mir_sntprintf(szGroupMask, SIZEOF(szGroupMask), _T("%s|"), &dbv.ptszVal[0]);
+ filterResult = (g_CluiData.filterFlags & CLVM_PROTOGROUP_OP) ? (filterResult | (_tcsstr(g_CluiData.groupFilter, szGroupMask) ? 1 : 0)) : (filterResult & (_tcsstr(g_CluiData.groupFilter, szGroupMask) ? 1 : 0));
+ mir_free(dbv.ptszVal);
+ }
+ else if (g_CluiData.filterFlags & CLVM_INCLUDED_UNGROUPED)
+ filterResult = (g_CluiData.filterFlags & CLVM_PROTOGROUP_OP) ? filterResult : filterResult & 1;
+ else
+ filterResult = (g_CluiData.filterFlags & CLVM_PROTOGROUP_OP) ? filterResult : filterResult & 0;
+ }
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_STATUS) {
+ WORD wStatus = db_get_w(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ filterResult = (g_CluiData.filterFlags & CLVM_GROUPSTATUS_OP) ? ((filterResult | ((1 << (wStatus - ID_STATUS_OFFLINE)) & g_CluiData.statusMaskFilter ? 1 : 0))) : (filterResult & ((1 << (wStatus - ID_STATUS_OFFLINE)) & g_CluiData.statusMaskFilter ? 1 : 0));
+ }
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_LASTMSG)
+ {
+ DWORD now;
+ PDNCE pdnce = (PDNCE)pcli->pfnGetCacheEntry(hContact);
+ if (pdnce)
+ {
+ now = g_CluiData.t_now;
+ now -= g_CluiData.lastMsgFilter;
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_LASTMSG_OLDERTHAN)
+ filterResult = filterResult & (pdnce->dwLastMsgTime < now);
+ else if (g_CluiData.bFilterEffective & CLVM_FILTER_LASTMSG_NEWERTHAN)
+ filterResult = filterResult & (pdnce->dwLastMsgTime > now);
+ }
+ }
+ return (dbHidden | !filterResult);
+ }
+ else
+ return dbHidden;
+}
diff --git a/plugins/Clist_modern/src/modern_clcmsgs.cpp b/plugins/Clist_modern/src/modern_clcmsgs.cpp
new file mode 100644
index 0000000000..cef111c793
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clcmsgs.cpp
@@ -0,0 +1,262 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_commonprototypes.h"
+
+
+//processing of all the CLM_ messages incoming
+
+LRESULT cli_ProcessExternalMessages(HWND hwnd,struct ClcData *dat,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ ClcContact *contact;
+ ClcGroup *group;
+
+ switch(msg) {
+ case CLM_DELETEITEM:
+ pcli->pfnDeleteItemFromTree(hwnd, (HANDLE) wParam);
+ clcSetDelayTimer( TIMERID_DELAYEDRESORTCLC, hwnd, 1 ); //pcli->pfnSortCLC(hwnd, dat, 1);
+ clcSetDelayTimer( TIMERID_RECALCSCROLLBAR, hwnd, 2 ); //pcli->pfnRecalcScrollBar(hwnd, dat);
+ return 0;
+
+ case CLM_AUTOREBUILD:
+ if (dat->force_in_dialog)
+ pcli->pfnSaveStateAndRebuildList(hwnd, dat);
+ else {
+ clcSetDelayTimer( TIMERID_REBUILDAFTER, hwnd );
+ CLM_AUTOREBUILD_WAS_POSTED = FALSE;
+ }
+ return 0;
+
+ case CLM_SETEXTRACOLUMNSSPACE:
+ dat->extraColumnSpacing = (int)wParam;
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ return 0;
+
+ case CLM_SETFONT:
+ if (HIWORD(lParam) < 0 || HIWORD(lParam)>FONTID_MODERN_MAX) return 0;
+
+ dat->fontModernInfo[HIWORD(lParam)].hFont = (HFONT)wParam;
+ dat->fontModernInfo[HIWORD(lParam)].changed = 1;
+
+ RowHeights_GetMaxRowHeight(dat, hwnd);
+
+ if (LOWORD(lParam))
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ return 0;
+
+ case CLM_SETHIDEEMPTYGROUPS:
+ {
+ BOOL old = ((GetWindowLongPtr(hwnd,GWL_STYLE)&CLS_HIDEEMPTYGROUPS) != 0);
+ BOOL newval = old;
+ if (wParam) SetWindowLongPtr(hwnd,GWL_STYLE,GetWindowLongPtr(hwnd,GWL_STYLE)|CLS_HIDEEMPTYGROUPS);
+ else SetWindowLongPtr(hwnd,GWL_STYLE,GetWindowLongPtr(hwnd,GWL_STYLE)&~CLS_HIDEEMPTYGROUPS);
+ newval = ((GetWindowLongPtr(hwnd,GWL_STYLE)&CLS_HIDEEMPTYGROUPS) != 0);
+ if (newval != old)
+ SendMessage(hwnd,CLM_AUTOREBUILD,0,0);
+ }
+ return 0;
+
+ case CLM_SETTEXTCOLOR:
+ if (wParam < 0 || wParam>FONTID_MODERN_MAX) break;
+
+ dat->fontModernInfo[wParam].colour = lParam;
+ dat->force_in_dialog = TRUE;
+ // Issue 40: option knows nothing about moderns colors
+ // others who know have to set colors from lowest to highest
+ switch ( wParam ) {
+ case FONTID_CONTACTS:
+ dat->fontModernInfo[FONTID_SECONDLINE].colour = lParam;
+ dat->fontModernInfo[FONTID_THIRDLINE].colour = lParam;
+ dat->fontModernInfo[FONTID_AWAY].colour = lParam;
+ dat->fontModernInfo[FONTID_DND].colour = lParam;
+ dat->fontModernInfo[FONTID_NA].colour = lParam;
+ dat->fontModernInfo[FONTID_OCCUPIED].colour = lParam;
+ dat->fontModernInfo[FONTID_CHAT].colour = lParam;
+ dat->fontModernInfo[FONTID_INVISIBLE].colour = lParam;
+ dat->fontModernInfo[FONTID_PHONE].colour = lParam;
+ dat->fontModernInfo[FONTID_LUNCH].colour = lParam;
+ dat->fontModernInfo[FONTID_CONTACT_TIME].colour = lParam;
+ break;
+ case FONTID_OPENGROUPS:
+ dat->fontModernInfo[FONTID_CLOSEDGROUPS].colour = lParam;
+ break;
+ case FONTID_OPENGROUPCOUNTS:
+ dat->fontModernInfo[FONTID_CLOSEDGROUPCOUNTS].colour = lParam;
+ break;
+ }
+ return 0;
+
+ case CLM_GETNEXTITEM:
+ {
+ int i;
+ if (wParam != CLGN_ROOT) {
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) lParam, &contact, &group, NULL))
+ return (LRESULT) (HANDLE) NULL;
+ i = List_IndexOf((SortedList*)&group->cl,contact);
+ if (i < 0) return 0;
+ }
+ switch (wParam) {
+ case CLGN_ROOT:
+ if (dat->list.cl.count)
+ return (LRESULT) pcli->pfnContactToHItem(dat->list.cl.items[0]);
+ else
+ return (LRESULT) (HANDLE) NULL;
+ case CLGN_CHILD:
+ if (contact->type != CLCIT_GROUP)
+ return (LRESULT) (HANDLE) NULL;
+ group = contact->group;
+ if (group->cl.count == 0)
+ return (LRESULT) (HANDLE) NULL;
+ return (LRESULT) pcli->pfnContactToHItem(group->cl.items[0]);
+ case CLGN_PARENT:
+ return group->groupId | HCONTACT_ISGROUP;
+ case CLGN_NEXT:
+ do {
+ if (++i >= group->cl.count)
+ return NULL;
+ }
+ while (group->cl.items[i]->type == CLCIT_DIVIDER);
+ return (LRESULT) pcli->pfnContactToHItem(group->cl.items[i]);
+ case CLGN_PREVIOUS:
+ do {
+ if (--i < 0)
+ return NULL;
+ }
+ while (group->cl.items[i]->type == CLCIT_DIVIDER);
+ return (LRESULT) pcli->pfnContactToHItem(group->cl.items[i]);
+ case CLGN_NEXTCONTACT:
+ for (i++; i < group->cl.count; i++)
+ if (group->cl.items[i]->type == CLCIT_CONTACT)
+ break;
+ if (i >= group->cl.count)
+ return (LRESULT) (HANDLE) NULL;
+ return (LRESULT) pcli->pfnContactToHItem(group->cl.items[i]);
+ case CLGN_PREVIOUSCONTACT:
+ if (i >= group->cl.count)
+ return (LRESULT) (HANDLE) NULL;
+ for (i--; i >= 0; i--)
+ if (group->cl.items[i]->type == CLCIT_CONTACT)
+ break;
+ if (i < 0)
+ return (LRESULT) (HANDLE) NULL;
+ return (LRESULT) pcli->pfnContactToHItem(group->cl.items[i]);
+ case CLGN_NEXTGROUP:
+ for (i++; i < group->cl.count; i++)
+ if (group->cl.items[i]->type == CLCIT_GROUP)
+ break;
+ if (i >= group->cl.count)
+ return (LRESULT) (HANDLE) NULL;
+ return (LRESULT) pcli->pfnContactToHItem(group->cl.items[i]);
+ case CLGN_PREVIOUSGROUP:
+ if (i >= group->cl.count)
+ return (LRESULT) (HANDLE) NULL;
+ for (i--; i >= 0; i--)
+ if (group->cl.items[i]->type == CLCIT_GROUP)
+ break;
+ if (i < 0)
+ return (LRESULT) (HANDLE) NULL;
+ return (LRESULT) pcli->pfnContactToHItem(group->cl.items[i]);
+ }
+ return (LRESULT) (HANDLE) NULL;
+ }
+ return 0;
+ case CLM_SELECTITEM:
+ {
+ struct ClcGroup *tgroup;
+ int index = -1;
+ int mainindex = -1;
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, &group, NULL))
+ break;
+ for (tgroup = group; tgroup; tgroup = tgroup->parent)
+ pcli->pfnSetGroupExpand(hwnd, dat, tgroup, 1);
+
+ if ( !contact->isSubcontact)
+ {
+ index = List_IndexOf((SortedList*)&group->cl,contact);
+ mainindex = index;
+ }
+ else
+ {
+ index = List_IndexOf((SortedList*)&group->cl,contact->subcontacts);
+ mainindex = index;
+ index += contact->isSubcontact;
+ }
+
+ BYTE k = db_get_b(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT);
+ if (k) {
+ for (int i=0; i < mainindex; i++)
+ {
+ struct ClcContact *tempCont = group->cl.items[i];
+ if (tempCont->type == CLCIT_CONTACT && tempCont->SubAllocated && tempCont->SubExpanded)
+ index += tempCont->SubAllocated;
+ }
+ }
+
+ dat->selection = pcli->pfnGetRowsPriorTo(&dat->list, group, index);
+ pcli->pfnEnsureVisible(hwnd, dat, dat->selection, 0);
+ }
+ return 0;
+
+ case CLM_SETEXTRAIMAGE:
+ if (LOWORD(lParam) >= dat->extraColumnsCount)
+ return 0;
+
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ return 0;
+
+ contact->iExtraImage[LOWORD(lParam)] = (BYTE) HIWORD(lParam); //set oldstyle icon
+ contact->iWideExtraImage[LOWORD(lParam)] = (WORD) 0xFFFF; //reset wide icon
+ pcli->pfnInvalidateRect(hwnd, NULL, FALSE);
+ return 0;
+
+ case CLM_SETWIDEEXTRAIMAGE:
+ if (LOWORD(lParam) >= dat->extraColumnsCount)
+ return 0;
+
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ return 0;
+
+ contact->iExtraImage[LOWORD(lParam)] = (BYTE) 0xFF; //reset oldstyle icon
+ contact->iWideExtraImage[LOWORD(lParam)] = (WORD) HIWORD(lParam); //set wide icon
+ pcli->pfnInvalidateRect(hwnd, NULL, FALSE);
+ return 0;
+
+ case CLM_SETEXTRAIMAGELIST:
+ dat->himlExtraColumns = (HIMAGELIST) lParam;
+ dat->himlWideExtraColumns = (HIMAGELIST) wParam;
+ pcli->pfnInvalidateRect(hwnd, NULL, FALSE);
+ return 0;
+
+ case CLM_GETWIDEEXTRAIMAGE:
+ if (LOWORD(lParam) >= dat->extraColumnsCount)
+ return 0xFFFF;
+
+ if ( !pcli->pfnFindItem(hwnd, dat, (HANDLE) wParam, &contact, NULL, NULL))
+ return 0xFFFF;
+
+ return contact->iWideExtraImage[LOWORD(lParam)];
+ }
+ return corecli.pfnProcessExternalMessages(hwnd, dat, msg, wParam, lParam);
+}
diff --git a/plugins/Clist_modern/src/modern_clcopts.cpp b/plugins/Clist_modern/src/modern_clcopts.cpp
new file mode 100644
index 0000000000..2cce5a111c
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clcopts.cpp
@@ -0,0 +1,2068 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_defsettings.h"
+#include "hdr/modern_effectenum.h"
+#include "hdr/modern_sync.h"
+#include <m_modernopt.h>
+#include "m_fontservice.h"
+
+#define FONTF_NORMAL 0
+#define FONTF_BOLD 1
+#define FONTF_ITALIC 2
+#define FONTF_UNDERLINE 4
+
+struct FontOptionsList
+{
+ DWORD dwFlags;
+ int fontID;
+ TCHAR* szGroup;
+ TCHAR* szDescr;
+ COLORREF defColour;
+ TCHAR* szDefFace;
+ BYTE defCharset, defStyle;
+ char defSize;
+ FONTEFFECT defeffect;
+
+ COLORREF colour;
+ TCHAR szFace[LF_FACESIZE];
+ BYTE charset, style;
+ char size;
+};
+
+#define CLCGROUP LPGENT("Contact List/Contact names")
+#define CLCLINESGROUP LPGENT("Contact List/Row Items")
+#define CLCFRAMESGROUP LPGENT("Contact List/Frame texts")
+#define CLCCOLOURSGROUP LPGENT("Contact List/Special colours")
+
+#define DEFAULT_COLOUR RGB(0, 0, 0)
+#define DEFAULT_GREYCOLOUR RGB(128, 128, 128)
+#define DEFAULT_BACKCOLOUR RGB(255, 255, 255)
+
+#define DEFAULT_FAMILY _T("Arial")
+#define DEFAULT_EFFECT { 0, 0x00000000, 0x00000000 }
+
+#define DEFAULT_SIZE -11
+#define DEFAULT_SMALLSIZE -8
+
+static struct FontOptionsList fontOptionsList[] = {
+ { FIDF_CLASSGENERAL, FONTID_CONTACTS, CLCGROUP, LPGENT( "Standard contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_AWAY, CLCGROUP, LPGENT( "Away contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_DND, CLCGROUP, LPGENT( "DND contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_NA, CLCGROUP, LPGENT( "NA contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_OCCUPIED, CLCGROUP, LPGENT( "Occupied contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_CHAT, CLCGROUP, LPGENT( "Free for chat contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_INVISIBLE, CLCGROUP, LPGENT( "Invisible contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_PHONE, CLCGROUP, LPGENT( "On the phone contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_LUNCH, CLCGROUP, LPGENT( "Out to lunch contacts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_OFFLINE, CLCGROUP, LPGENT( "Offline contacts"), DEFAULT_GREYCOLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_INVIS, CLCGROUP, LPGENT( "Online contacts to whom you have a different visibility"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_OFFINVIS, CLCGROUP, LPGENT( "Offline contacts to whom you have a different visibility"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_NOTONLIST, CLCGROUP, LPGENT( "Contacts who are 'not on list'"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSHEADER, FONTID_OPENGROUPS, CLCGROUP, LPGENT( "Open groups"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_BOLD, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSHEADER, FONTID_OPENGROUPCOUNTS, CLCGROUP, LPGENT( "Open group member counts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSHEADER, FONTID_CLOSEDGROUPS, CLCGROUP, LPGENT( "Closed groups"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_BOLD, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSHEADER, FONTID_CLOSEDGROUPCOUNTS, CLCGROUP, LPGENT( "Closed group member counts"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSSMALL, FONTID_DIVIDERS, CLCGROUP, LPGENT( "Dividers"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+
+ { FIDF_CLASSSMALL, FONTID_SECONDLINE, CLCLINESGROUP, LPGENT( "Second line"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SMALLSIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSSMALL, FONTID_THIRDLINE, CLCLINESGROUP, LPGENT( "Third line"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SMALLSIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSSMALL, FONTID_CONTACT_TIME, CLCLINESGROUP, LPGENT( "Contact time"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SMALLSIZE, DEFAULT_EFFECT },
+
+ { FIDF_CLASSGENERAL, FONTID_STATUSBAR_PROTONAME, CLCFRAMESGROUP, LPGENT( "Status bar text"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_EVENTAREA, CLCFRAMESGROUP, LPGENT( "Event area text"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+ { FIDF_CLASSGENERAL, FONTID_VIEMODES, CLCFRAMESGROUP, LPGENT( "Current view mode text"), DEFAULT_COLOUR, DEFAULT_FAMILY, DEFAULT_CHARSET, FONTF_NORMAL, DEFAULT_SIZE, DEFAULT_EFFECT },
+};
+
+struct ColourOptionsList
+{
+ char * chGroup;
+ char * chName;
+ TCHAR* szGroup;
+ TCHAR* szDescr;
+ COLORREF defColour;
+};
+
+static struct ColourOptionsList colourOptionsList[] = {
+
+ { "CLC", "BkColour", CLCGROUP, LPGENT( "Background"), DEFAULT_BACKCOLOUR },
+ { "CLC", "Rows_BkColour", CLCLINESGROUP, LPGENT( "Background"), DEFAULT_BACKCOLOUR },
+ { "CLC", "Frames_BkColour", CLCFRAMESGROUP, LPGENT( "Background"), DEFAULT_BACKCOLOUR},
+
+ { "CLC", "HotTextColour", CLCCOLOURSGROUP, LPGENT( "Hot text"), CLCDEFAULT_MODERN_HOTTEXTCOLOUR },
+ { "CLC", "SelTextColour", CLCCOLOURSGROUP, LPGENT( "Selected text"), CLCDEFAULT_MODERN_SELTEXTCOLOUR },
+ { "CLC", "QuickSearchColour", CLCCOLOURSGROUP, LPGENT( "Quick search text"), CLCDEFAULT_MODERN_QUICKSEARCHCOLOUR},
+
+ { "Menu", "TextColour", CLCCOLOURSGROUP, LPGENT( "Menu text"), CLCDEFAULT_TEXTCOLOUR},
+ { "Menu", "SelTextColour", CLCCOLOURSGROUP, LPGENT( "Selected menu text"), CLCDEFAULT_MODERN_SELTEXTCOLOUR},
+ { "FrameTitleBar", "TextColour", CLCCOLOURSGROUP, LPGENT( "Frame title text"), CLCDEFAULT_TEXTCOLOUR },
+ { "StatusBar", "TextColour", CLCCOLOURSGROUP, LPGENT( "Statusbar text"), CLCDEFAULT_TEXTCOLOUR},
+ { "ModernSettings", "KeyColor", CLCCOLOURSGROUP, LPGENT( "3rd party frames transparent back colour"), SETTING_KEYCOLOR_DEFAULT},
+
+};
+
+void RegisterCLUIFonts( void )
+{
+ static bool registered = false;
+ if ( registered )
+ return;
+
+ FontIDT fontid = {0};
+ EffectIDT effectid = {0};
+ char idstr[10];
+ int i, index = 0;
+
+ fontid.cbSize = sizeof(fontid);
+ strncpy(fontid.dbSettingsGroup, "CLC", SIZEOF(fontid.dbSettingsGroup));
+
+ effectid.cbSize = sizeof(effectid);
+ strncpy(effectid.dbSettingsGroup, "CLC", SIZEOF(effectid.dbSettingsGroup));
+
+ for ( i=0; i < SIZEOF(fontOptionsList); i++, index++ ) {
+ fontid.flags = FIDF_DEFAULTVALID | FIDF_APPENDNAME | FIDF_SAVEPOINTSIZE | FIDF_ALLOWEFFECTS | FIDF_ALLOWREREGISTER | FIDF_NOAS;
+ fontid.flags |= fontOptionsList[i].dwFlags;
+
+ _tcsncpy(fontid.group, fontOptionsList[i].szGroup, SIZEOF(fontid.group));
+ _tcsncpy(fontid.name, fontOptionsList[i].szDescr, SIZEOF(fontid.name));
+ sprintf(idstr, "Font%d", fontOptionsList[i].fontID);
+ strncpy(fontid.prefix, idstr, SIZEOF(fontid.prefix));
+ fontid.order = i+1;
+
+ fontid.deffontsettings.charset = fontOptionsList[i].defCharset;
+ fontid.deffontsettings.colour = fontOptionsList[i].defColour;
+ fontid.deffontsettings.size = fontOptionsList[i].defSize;
+ fontid.deffontsettings.style = fontOptionsList[i].defStyle;
+ _tcsncpy(fontid.deffontsettings.szFace, fontOptionsList[i].szDefFace, SIZEOF(fontid.deffontsettings.szFace));
+
+ FontRegisterT(&fontid);
+
+ _tcsncpy(effectid.group, fontOptionsList[i].szGroup, SIZEOF(effectid.group));
+ _tcsncpy(effectid.name, fontOptionsList[i].szDescr, SIZEOF(effectid.name));
+ sprintf(idstr, "Font%d", fontOptionsList[i].fontID);
+ strncpy(effectid.setting, idstr, SIZEOF(effectid.setting));
+ effectid.order = i + 1;
+
+ effectid.defeffect.effectIndex = fontOptionsList[i].defeffect.effectIndex;
+ effectid.defeffect.baseColour = fontOptionsList[i].defeffect.baseColour;
+ effectid.defeffect.secondaryColour = fontOptionsList[i].defeffect.secondaryColour;
+
+ EffectRegisterT(&effectid);
+ }
+
+ ColourIDT colourid = {0};
+ colourid.cbSize = sizeof(colourid);
+
+ for ( i=0; i < SIZEOF( colourOptionsList); i++ ) {
+ _tcsncpy(colourid.group, colourOptionsList[i].szGroup, SIZEOF(colourid.group));
+ _tcsncpy(colourid.name, colourOptionsList[i].szDescr, SIZEOF(colourid.group));
+ strncpy(colourid.setting, colourOptionsList[i].chName, SIZEOF(colourid.setting));
+ strncpy(colourid.dbSettingsGroup, colourOptionsList[i].chGroup, SIZEOF(colourid.dbSettingsGroup));
+ colourid.defcolour = colourOptionsList[i].defColour;
+ colourid.order = i + 1;
+ ColourRegisterT(&colourid);
+ }
+ registered = true;
+}
+
+static INT_PTR CALLBACK DlgProcClistListOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcClistAdditionalOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcClcBkgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcStatusBarBkgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+DWORD GetDefaultExStyle(void)
+{
+ BOOL param;
+ DWORD ret = CLCDEFAULT_EXSTYLE;
+ if (SystemParametersInfo(SPI_GETLISTBOXSMOOTHSCROLLING,0,&param,FALSE) && !param)
+ ret |= CLS_EX_NOSMOOTHSCROLLING;
+ if (SystemParametersInfo(SPI_GETHOTTRACKING,0,&param,FALSE) && !param)
+ ret &= ~CLS_EX_TRACKSELECT;
+ return ret;
+}
+
+void GetFontSetting(int i,LOGFONT *lf,COLORREF *colour,BYTE *effect, COLORREF *eColour1,COLORREF *eColour2)
+{
+ DBVARIANT dbv = {0};
+ char idstr[32];
+
+ int index = 0;
+ for ( index = 0; index < SIZEOF(fontOptionsList); index++ )
+ if ( fontOptionsList[index].fontID == i )
+ break;
+
+ if ( index == SIZEOF(fontOptionsList))
+ return;
+
+ FontIDT fontid = {0};
+ fontid.cbSize = sizeof(fontid);
+ _tcsncpy( fontid.group, fontOptionsList[index].szGroup, SIZEOF( fontid.group ));
+ _tcsncpy( fontid.name, fontOptionsList[index].szDescr, SIZEOF( fontid.name ));
+
+ COLORREF col = CallService( MS_FONT_GETT, (WPARAM)&fontid, (LPARAM)lf );
+
+ if ( colour )
+ *colour = col;
+
+ if (effect) {
+ mir_snprintf(idstr,SIZEOF(idstr),"Font%dEffect",i);
+ *effect = db_get_b(NULL,"CLC",idstr,0);
+ mir_snprintf(idstr,SIZEOF(idstr),"Font%dEffectCol1",i);
+ *eColour1 = db_get_dw(NULL,"CLC",idstr,0);
+ mir_snprintf(idstr,SIZEOF(idstr),"Font%dEffectCol2",i);
+ *eColour2 = db_get_dw(NULL,"CLC",idstr,0);
+ }
+}
+
+
+static INT_PTR CALLBACK DlgProcClistOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcTrayOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcClistWindowOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static INT_PTR CALLBACK DlgProcClistBehaviourOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK DlgProcSBarOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+static UINT StatusBarExpertControls[] = {IDC_STATUSBAR_PER_PROTO, IDC_STATUSBAR_PROTO_LIST, IDC_SBAR_USE_ACCOUNT_SETTINGS, IDC_SBAR_HIDE_ACCOUNT_COMPLETELY};
+
+struct
+{
+ char *name; // Tab name
+ int id; // Dialog id
+ DLGPROC wnd_proc; // Dialog function
+ UINT* expertControls; // Expert Controls
+ int nExpertControls;
+ DWORD flag; // Expertonly
+}
+static clist_opt_items[] =
+{
+ { LPGEN("General"), IDD_OPT_CLIST, DlgProcClistOpts, NULL, 0, 0},
+ { LPGEN("Tray"), IDD_OPT_TRAY, DlgProcTrayOpts, NULL, 0, 0 },
+ { LPGEN("List"), IDD_OPT_CLC, DlgProcClistListOpts, NULL, 0, 0 },
+ { LPGEN("Window"), IDD_OPT_CLUI, DlgProcClistWindowOpts, NULL, 0, 0 },
+ { LPGEN("Behaviour"), IDD_OPT_CLUI_2, DlgProcClistBehaviourOpts, NULL, 0, 0 },
+ { LPGEN("Status Bar"), IDD_OPT_SBAR, DlgProcSBarOpts, StatusBarExpertControls, SIZEOF(StatusBarExpertControls), 0},
+ { LPGEN("Additional stuff"), IDD_OPT_META_CLC, DlgProcClistAdditionalOpts, NULL, 0, 0 }
+};
+
+int ClcOptInit(WPARAM wParam,LPARAM lParam)
+{
+ if (MirandaExiting())
+ return 0;
+
+ OPTIONSDIALOGPAGE odp = { 0 };
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = g_hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CLC);
+ odp.pszTitle = LPGEN("Contact List");
+ odp.pfnDlgProc = DlgProcClistListOpts;
+ odp.flags = ODPF_BOLDGROUPS;
+
+ for (int i=0; i < SIZEOF(clist_opt_items); i++) {
+ odp.pszTemplate = MAKEINTRESOURCEA(clist_opt_items[i].id);
+ odp.pszTab = clist_opt_items[i].name;
+ odp.pfnDlgProc = clist_opt_items[i].wnd_proc;
+ odp.flags = ODPF_BOLDGROUPS | clist_opt_items[i].flag;
+ odp.expertOnlyControls = clist_opt_items[i].expertControls;
+ odp.nExpertOnlyControls = clist_opt_items[i].nExpertControls;
+ Options_AddPage(wParam, &odp);
+ }
+
+ if (g_CluiData.fDisableSkinEngine) {
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_CLIST_LISTBKG);
+ odp.pszGroup = LPGEN("Skins");
+ odp.pszTitle = LPGEN("Contact List");
+ odp.pszTab = LPGEN("List Background");
+ odp.pfnDlgProc = DlgProcClcBkgOpts;
+ odp.flags = ODPF_BOLDGROUPS;
+ Options_AddPage(wParam, &odp);
+ }
+
+ return 0;
+}
+
+struct CheckBoxToStyleEx_t
+{
+ int id;
+ DWORD flag;
+ int neg;
+};
+static const struct CheckBoxToStyleEx_t checkBoxToStyleEx[] = {
+ {IDC_DISABLEDRAGDROP,CLS_EX_DISABLEDRAGDROP,0},
+ {IDC_NOTEDITLABELS,CLS_EX_EDITLABELS,1},
+ {IDC_SHOWSELALWAYS,CLS_EX_SHOWSELALWAYS,0},
+ {IDC_TRACKSELECT,CLS_EX_TRACKSELECT,0},
+ {IDC_SHOWGROUPCOUNTS,CLS_EX_SHOWGROUPCOUNTS,0},
+ {IDC_HIDECOUNTSWHENEMPTY,CLS_EX_HIDECOUNTSWHENEMPTY,0},
+ {IDC_DIVIDERONOFF,CLS_EX_DIVIDERONOFF,0},
+ {IDC_NOTNOTRANSLUCENTSEL,CLS_EX_NOTRANSLUCENTSEL,1},
+ {IDC_LINEWITHGROUPS,CLS_EX_LINEWITHGROUPS,0},
+ {IDC_QUICKSEARCHVISONLY,CLS_EX_QUICKSEARCHVISONLY,0},
+ {IDC_SORTGROUPSALPHA,CLS_EX_SORTGROUPSALPHA,0},
+ {IDC_NOTNOSMOOTHSCROLLING,CLS_EX_NOSMOOTHSCROLLING,1}
+};
+
+struct CheckBoxValues_t {
+ DWORD style;
+ TCHAR *szDescr;
+};
+static const struct CheckBoxValues_t greyoutValues[] = {
+ {GREYF_UNFOCUS,LPGENT("Not focused")},
+ {MODEF_OFFLINE,LPGENT("Offline")},
+ {PF2_ONLINE,LPGENT("Online")},
+ {PF2_SHORTAWAY,LPGENT("Away")},
+ {PF2_LONGAWAY,LPGENT("NA")},
+ {PF2_LIGHTDND,LPGENT("Occupied")},
+ {PF2_HEAVYDND,LPGENT("DND")},
+ {PF2_FREECHAT,LPGENT("Free for chat")},
+ {PF2_INVISIBLE,LPGENT("Invisible")},
+ {PF2_OUTTOLUNCH,LPGENT("Out to lunch")},
+ {PF2_ONTHEPHONE,LPGENT("On the phone")}
+};
+static const struct CheckBoxValues_t offlineValues[] =
+{
+ {MODEF_OFFLINE,LPGENT("Offline")},
+ {PF2_ONLINE,LPGENT("Online")},
+ {PF2_SHORTAWAY,LPGENT("Away")},
+ {PF2_LONGAWAY,LPGENT("NA")},
+ {PF2_LIGHTDND,LPGENT("Occupied")},
+ {PF2_HEAVYDND,LPGENT("DND")},
+ {PF2_FREECHAT,LPGENT("Free for chat")},
+ {PF2_INVISIBLE,LPGENT("Invisible")},
+ {PF2_OUTTOLUNCH,LPGENT("Out to lunch")},
+ {PF2_ONTHEPHONE,LPGENT("On the phone")}
+};
+
+static void FillCheckBoxTree(HWND hwndTree,const struct CheckBoxValues_t *values,int nValues,DWORD style)
+{
+ TVINSERTSTRUCT tvis;
+ int i;
+
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_STATE|TVIF_IMAGE;
+ for (i=0;i < nValues;i++) {
+ tvis.item.lParam = values[i].style;
+ tvis.item.pszText = TranslateTS(values[i].szDescr);
+ tvis.item.stateMask = TVIS_STATEIMAGEMASK;
+ tvis.item.state = INDEXTOSTATEIMAGEMASK((style&tvis.item.lParam) != 0?2:1);
+ tvis.item.iImage = tvis.item.iSelectedImage = (style&tvis.item.lParam) != 0?1:0;
+ TreeView_InsertItem(hwndTree,&tvis);
+ }
+}
+
+static DWORD MakeCheckBoxTreeFlags(HWND hwndTree)
+{
+ DWORD flags = 0;
+ TVITEMA tvi;
+
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM|TVIF_IMAGE;
+ tvi.hItem = TreeView_GetRoot(hwndTree);
+ while(tvi.hItem) {
+ TreeView_GetItem(hwndTree,&tvi);
+ if (tvi.iImage) flags |= tvi.lParam;
+ tvi.hItem = TreeView_GetNextSibling(hwndTree,tvi.hItem);
+ }
+ return flags;
+}
+
+static INT_PTR CALLBACK DlgProcClistAdditionalOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ LPNMHDR t;
+ t = ((LPNMHDR)lParam);
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_META, db_get_b(NULL,"CLC","Meta",SETTING_USEMETAICON_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+ CheckDlgButton(hwndDlg, IDC_METADBLCLK, db_get_b(NULL,"CLC","MetaDoubleClick",SETTING_METAAVOIDDBLCLICK_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+ CheckDlgButton(hwndDlg, IDC_METASUBEXTRA, db_get_b(NULL,"CLC","MetaHideExtra",SETTING_METAHIDEEXTRA_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+ CheckDlgButton(hwndDlg, IDC_METASUBEXTRA_IGN, db_get_b(NULL,"CLC","MetaIgnoreEmptyExtra",SETTING_METAAVOIDDBLCLICK_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+ CheckDlgButton(hwndDlg, IDC_METASUB_HIDEOFFLINE, db_get_b(NULL,"CLC","MetaHideOfflineSub",SETTING_METAHIDEOFFLINESUB_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+ CheckDlgButton(hwndDlg, IDC_METAEXPAND, db_get_b(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+ CheckDlgButton(hwndDlg, IDC_DISCOVER_AWAYMSG, db_get_b(NULL,"ModernData","InternalAwayMsgDiscovery",SETTING_INTERNALAWAYMSGREQUEST_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+ CheckDlgButton(hwndDlg, IDC_REMOVE_OFFLINE_AWAYMSG, db_get_b(NULL,"ModernData","RemoveAwayMessageForOffline",SETTING_REMOVEAWAYMSGFOROFFLINE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED); /// by FYR
+
+ SendDlgItemMessage(hwndDlg,IDC_SUBINDENTSPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_SUBINDENT),0);
+ SendDlgItemMessage(hwndDlg,IDC_SUBINDENTSPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_SUBINDENTSPIN,UDM_SETPOS,0,MAKELONG(db_get_b(NULL,"CLC","SubIndent",CLCDEFAULT_GROUPINDENT),0));
+
+ {
+ BYTE t = IsDlgButtonChecked(hwndDlg,IDC_METAEXPAND);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_METADBLCLK),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_METASUBEXTRA),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_METASUB_HIDEOFFLINE),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SUBINDENTSPIN),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SUBINDENT),t);
+
+ t = ServiceExists(MS_MC_GETMOSTONLINECONTACT);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_META),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_METADBLCLK),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_METASUB_HIDEOFFLINE),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_METAEXPAND),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_METASUBEXTRA),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_FRAME_META),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_FRAME_META_CAPT),!t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_SUBINDENTSPIN),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_SUBINDENT),t);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_SUBIDENTCAPT),t);
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_METAEXPAND) {
+ BYTE t = IsDlgButtonChecked(hwndDlg,IDC_METAEXPAND);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_METADBLCLK),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_METASUBEXTRA),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_METASUB_HIDEOFFLINE),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SUBINDENTSPIN),t);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SUBINDENT),t);
+ }
+ if ((LOWORD(wParam) == IDC_SUBINDENT) && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ return TRUE;
+
+ case WM_NOTIFY:
+ switch(t->idFrom) {
+ case 0:
+ switch (t->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CLC","Meta",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_META)); // by FYR
+ db_set_b(NULL,"CLC","MetaDoubleClick",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_METADBLCLK)); // by FYR
+ db_set_b(NULL,"CLC","MetaHideExtra",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_METASUBEXTRA)); // by FYR
+ db_set_b(NULL,"CLC","MetaIgnoreEmptyExtra",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_METASUBEXTRA_IGN)); // by FYR
+ db_set_b(NULL,"CLC","MetaHideOfflineSub",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_METASUB_HIDEOFFLINE)); // by FYR
+ db_set_b(NULL,"CLC","MetaExpanding",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_METAEXPAND));
+ db_set_b(NULL,"ModernData","InternalAwayMsgDiscovery",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DISCOVER_AWAYMSG));
+ db_set_b(NULL,"ModernData","RemoveAwayMessageForOffline",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_REMOVE_OFFLINE_AWAYMSG));
+
+ db_set_b(NULL,"CLC","SubIndent",(BYTE)SendDlgItemMessage(hwndDlg,IDC_SUBINDENTSPIN,UDM_GETPOS,0,0));
+ ClcOptionsChanged();
+ CLUI_ReloadCLUIOptions();
+ PostMessage(pcli->hwndContactList,WM_SIZE,0,0);
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK DlgProcClistListOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_GREYOUTOPTS),GWL_STYLE,GetWindowLongPtr(GetDlgItem(hwndDlg,IDC_GREYOUTOPTS),GWL_STYLE)|TVS_NOHSCROLL);
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_HIDEOFFLINEOPTS),GWL_STYLE,GetWindowLongPtr(GetDlgItem(hwndDlg,IDC_HIDEOFFLINEOPTS),GWL_STYLE)|TVS_NOHSCROLL);
+ {
+ HIMAGELIST himlCheckBoxes;
+ himlCheckBoxes = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_COLOR32|ILC_MASK,2,2);
+ ImageList_AddIcon(himlCheckBoxes,LoadSmallIconShared(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_NOTICK)));
+ ImageList_AddIcon(himlCheckBoxes,LoadSmallIconShared(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_TICK)));
+ TreeView_SetImageList(GetDlgItem(hwndDlg,IDC_GREYOUTOPTS),himlCheckBoxes,TVSIL_NORMAL);
+ TreeView_SetImageList(GetDlgItem(hwndDlg,IDC_HIDEOFFLINEOPTS),himlCheckBoxes,TVSIL_NORMAL);
+
+ DWORD exStyle = db_get_dw(NULL,"CLC","ExStyle",GetDefaultExStyle());
+ for (int i=0;i < SIZEOF(checkBoxToStyleEx);i++)
+ CheckDlgButton(hwndDlg,checkBoxToStyleEx[i].id,(exStyle&checkBoxToStyleEx[i].flag)^(checkBoxToStyleEx[i].flag*checkBoxToStyleEx[i].neg)?BST_CHECKED:BST_UNCHECKED);
+
+ UDACCEL accel[2] = {{0,10},{2,50}};
+ SendDlgItemMessage(hwndDlg,IDC_SMOOTHTIMESPIN,UDM_SETRANGE,0,MAKELONG(999,0));
+ SendDlgItemMessage(hwndDlg,IDC_SMOOTHTIMESPIN,UDM_SETACCEL,SIZEOF(accel),(LPARAM)&accel);
+ SendDlgItemMessage(hwndDlg,IDC_SMOOTHTIMESPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CLC","ScrollTime",CLCDEFAULT_SCROLLTIME),0));
+ }
+ CheckDlgButton(hwndDlg,IDC_IDLE,db_get_b(NULL,"CLC","ShowIdle",CLCDEFAULT_SHOWIDLE)?BST_CHECKED:BST_UNCHECKED);
+
+ SendDlgItemMessage(hwndDlg,IDC_GROUPINDENTSPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_GROUPINDENTSPIN,UDM_SETPOS,0,MAKELONG(db_get_b(NULL,"CLC","GroupIndent",CLCDEFAULT_GROUPINDENT),0));
+ CheckDlgButton(hwndDlg,IDC_GREYOUT,db_get_dw(NULL,"CLC","GreyoutFlags",CLCDEFAULT_GREYOUTFLAGS)?BST_CHECKED:BST_UNCHECKED);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SMOOTHTIME),IsDlgButtonChecked(hwndDlg,IDC_NOTNOSMOOTHSCROLLING));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_GREYOUTOPTS),IsDlgButtonChecked(hwndDlg,IDC_GREYOUT));
+ FillCheckBoxTree(GetDlgItem(hwndDlg,IDC_GREYOUTOPTS),greyoutValues,SIZEOF(greyoutValues),db_get_dw(NULL,"CLC","FullGreyoutFlags",CLCDEFAULT_FULLGREYOUTFLAGS));
+ FillCheckBoxTree(GetDlgItem(hwndDlg,IDC_HIDEOFFLINEOPTS),offlineValues,SIZEOF(offlineValues),db_get_dw(NULL,"CLC","OfflineModes",CLCDEFAULT_OFFLINEMODES));
+ CheckDlgButton(hwndDlg,IDC_NOSCROLLBAR,db_get_b(NULL,"CLC","NoVScrollBar",CLCDEFAULT_NOVSCROLL)?BST_CHECKED:BST_UNCHECKED);
+ return TRUE;
+
+ case WM_VSCROLL:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_NOTNOSMOOTHSCROLLING)
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SMOOTHTIME),IsDlgButtonChecked(hwndDlg,IDC_NOTNOSMOOTHSCROLLING));
+ if (LOWORD(wParam) == IDC_GREYOUT)
+ EnableWindow(GetDlgItem(hwndDlg,IDC_GREYOUTOPTS),IsDlgButtonChecked(hwndDlg,IDC_GREYOUT));
+ if ((/*LOWORD(wParam) == IDC_LEFTMARGIN || */ LOWORD(wParam) == IDC_SMOOTHTIME || LOWORD(wParam) == IDC_GROUPINDENT) && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom) {
+ case IDC_GREYOUTOPTS:
+ case IDC_HIDEOFFLINEOPTS:
+ if (((LPNMHDR)lParam)->code == NM_CLICK) {
+ TVHITTESTINFO hti;
+ hti.pt.x = (short)LOWORD(GetMessagePos());
+ hti.pt.y = (short)HIWORD(GetMessagePos());
+ ScreenToClient(((LPNMHDR)lParam)->hwndFrom,&hti.pt);
+ if (TreeView_HitTest(((LPNMHDR)lParam)->hwndFrom,&hti))
+ if (hti.flags&TVHT_ONITEMICON) {
+ TVITEMA tvi;
+ tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ tvi.hItem = hti.hItem;
+ TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom,&tvi);
+ tvi.iImage = tvi.iSelectedImage = tvi.iImage = !tvi.iImage;
+ //tvi.state = tvi.iImage?2:1;
+ TreeView_SetItem(((LPNMHDR)lParam)->hwndFrom,&tvi);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ }
+ }
+ break;
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ {
+ DWORD exStyle = 0;
+ for (int i=0;i < SIZEOF(checkBoxToStyleEx);i++)
+ if ((IsDlgButtonChecked(hwndDlg,checkBoxToStyleEx[i].id) == 0) == checkBoxToStyleEx[i].neg)
+ exStyle |= checkBoxToStyleEx[i].flag;
+ db_set_dw(NULL,"CLC","ExStyle",exStyle);
+ }
+ {
+ DWORD fullGreyoutFlags = MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg,IDC_GREYOUTOPTS));
+ db_set_dw(NULL,"CLC","FullGreyoutFlags",fullGreyoutFlags);
+ if (IsDlgButtonChecked(hwndDlg,IDC_GREYOUT))
+ db_set_dw(NULL,"CLC","GreyoutFlags",fullGreyoutFlags);
+ else
+ db_set_dw(NULL,"CLC","GreyoutFlags",0);
+ }
+
+ db_set_b(NULL,"CLC","ShowIdle",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_IDLE)?1:0));
+ db_set_dw(NULL,"CLC","OfflineModes",MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg,IDC_HIDEOFFLINEOPTS)));
+ db_set_w(NULL,"CLC","ScrollTime",(WORD)SendDlgItemMessage(hwndDlg,IDC_SMOOTHTIMESPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CLC","GroupIndent",(BYTE)SendDlgItemMessage(hwndDlg,IDC_GROUPINDENTSPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CLC","NoVScrollBar",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_NOSCROLLBAR)?1:0));
+
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+
+ case WM_DESTROY:
+ ImageList_Destroy(TreeView_GetImageList(GetDlgItem(hwndDlg,IDC_GREYOUTOPTS),TVSIL_NORMAL));
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK DlgProcStatusBarBkgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg,IDC_BITMAP,db_get_b(NULL,"StatusBar","UseBitmap",CLCDEFAULT_USEBITMAP)?BST_CHECKED:BST_UNCHECKED);
+ SendMessage(hwndDlg,WM_USER+10,0,0);
+ SendDlgItemMessage(hwndDlg,IDC_BKGCOLOUR,CPM_SETDEFAULTCOLOUR,0,CLCDEFAULT_BKCOLOUR);
+ // SendDlgItemMessage(hwndDlg,IDC_BKGCOLOUR,CPM_SETCOLOUR,0,DBGetContactSettingDword(NULL,"StatusBar","BkColour",CLCDEFAULT_BKCOLOUR));
+ SendDlgItemMessage(hwndDlg,IDC_SELCOLOUR,CPM_SETDEFAULTCOLOUR,0,CLCDEFAULT_SELBKCOLOUR);
+ SendDlgItemMessage(hwndDlg,IDC_SELCOLOUR,CPM_SETCOLOUR,0,db_get_dw(NULL,"StatusBar","SelBkColour",CLCDEFAULT_SELBKCOLOUR));
+ {
+ DBVARIANT dbv = {0};
+ if ( !DBGetContactSettingString(NULL,"StatusBar","BkBitmap",&dbv)) {
+ SetDlgItemTextA(hwndDlg,IDC_FILENAME,dbv.pszVal);
+ if (ServiceExists(MS_UTILS_PATHTOABSOLUTE)) {
+ char szPath[MAX_PATH];
+
+ if (CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)dbv.pszVal, (LPARAM)szPath))
+ SetDlgItemTextA(hwndDlg,IDC_FILENAME,szPath);
+ }
+ db_free(&dbv);
+ }
+ }
+
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE,db_get_b(NULL,"StatusBar","HiLightMode",SETTING_SBHILIGHTMODE_DEFAULT) == 0?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE1,db_get_b(NULL,"StatusBar","HiLightMode",SETTING_SBHILIGHTMODE_DEFAULT) == 1?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE2,db_get_b(NULL,"StatusBar","HiLightMode",SETTING_SBHILIGHTMODE_DEFAULT) == 2?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE3,db_get_b(NULL,"StatusBar","HiLightMode",SETTING_SBHILIGHTMODE_DEFAULT) == 3?BST_CHECKED:BST_UNCHECKED);
+ {
+ WORD bmpUse = db_get_w(NULL,"StatusBar","BkBmpUse",CLCDEFAULT_BKBMPUSE);
+ CheckDlgButton(hwndDlg,IDC_STRETCHH,bmpUse&CLB_STRETCHH?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_STRETCHV,bmpUse&CLB_STRETCHV?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_TILEH,bmpUse&CLBF_TILEH?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_TILEV,bmpUse&CLBF_TILEV?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_SCROLL,bmpUse&CLBF_SCROLL?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_PROPORTIONAL,bmpUse&CLBF_PROPORTIONAL?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_TILEVROWH,bmpUse&CLBF_TILEVTOROWHEIGHT?BST_CHECKED:BST_UNCHECKED);
+
+ HRESULT (STDAPICALLTYPE *MySHAutoComplete)(HWND,DWORD);
+ MySHAutoComplete = (HRESULT (STDAPICALLTYPE*)(HWND,DWORD))GetProcAddress(GetModuleHandle(_T("shlwapi")),"SHAutoComplete");
+ if (MySHAutoComplete)
+ MySHAutoComplete(GetDlgItem(hwndDlg,IDC_FILENAME),1);
+ }
+ return TRUE;
+
+ case WM_USER+10:
+ EnableWindow(GetDlgItem(hwndDlg,IDC_FILENAME),IsDlgButtonChecked(hwndDlg,IDC_BITMAP));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BROWSE),IsDlgButtonChecked(hwndDlg,IDC_BITMAP));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STRETCHH),IsDlgButtonChecked(hwndDlg,IDC_BITMAP));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STRETCHV),IsDlgButtonChecked(hwndDlg,IDC_BITMAP));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TILEH),IsDlgButtonChecked(hwndDlg,IDC_BITMAP));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TILEV),IsDlgButtonChecked(hwndDlg,IDC_BITMAP));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SCROLL),IsDlgButtonChecked(hwndDlg,IDC_BITMAP));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PROPORTIONAL),IsDlgButtonChecked(hwndDlg,IDC_BITMAP));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TILEVROWH),IsDlgButtonChecked(hwndDlg,IDC_BITMAP));
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_BROWSE) {
+ char str[MAX_PATH];
+ OPENFILENAMEA ofn = {0};
+ char filter[512];
+
+ GetDlgItemTextA(hwndDlg,IDC_FILENAME,str,SIZEOF(str));
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = hwndDlg;
+ ofn.hInstance = NULL;
+ CallService(MS_UTILS_GETBITMAPFILTERSTRINGS,SIZEOF(filter),(LPARAM)filter);
+ ofn.lpstrFilter = filter;
+ ofn.lpstrFile = str;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
+ ofn.nMaxFile = SIZEOF(str);
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.lpstrDefExt = "bmp";
+ if ( !GetOpenFileNameA(&ofn)) break;
+ SetDlgItemTextA(hwndDlg,IDC_FILENAME,str);
+ }
+ else if (LOWORD(wParam) == IDC_FILENAME && HIWORD(wParam) != EN_CHANGE) break;
+ if (LOWORD(wParam) == IDC_BITMAP) SendMessage(hwndDlg,WM_USER+10,0,0);
+ if (LOWORD(wParam) == IDC_FILENAME && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0;
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"StatusBar","UseBitmap",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_BITMAP));
+ {
+ COLORREF col;
+ col = SendDlgItemMessage(hwndDlg,IDC_BKGCOLOUR,CPM_GETCOLOUR,0,0);
+ if (col == CLCDEFAULT_BKCOLOUR) db_unset(NULL,"StatusBar","BkColour");
+ else db_set_dw(NULL,"StatusBar","BkColour",col);
+ col = SendDlgItemMessage(hwndDlg,IDC_SELCOLOUR,CPM_GETCOLOUR,0,0);
+ if (col == CLCDEFAULT_SELBKCOLOUR) db_unset(NULL,"StatusBar","SelBkColour");
+ else db_set_dw(NULL,"StatusBar","SelBkColour",col);
+ }
+ {
+ char str[MAX_PATH],strrel[MAX_PATH];
+ GetDlgItemTextA(hwndDlg,IDC_FILENAME,str,SIZEOF(str));
+ if (ServiceExists(MS_UTILS_PATHTORELATIVE)) {
+ if (CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)str, (LPARAM)strrel))
+ db_set_s(NULL,"StatusBar","BkBitmap",strrel);
+ else db_set_s(NULL,"StatusBar","BkBitmap",str);
+ }
+ else db_set_s(NULL,"StatusBar","BkBitmap",str);
+
+ }
+ {
+ WORD flags = 0;
+ if (IsDlgButtonChecked(hwndDlg,IDC_STRETCHH)) flags |= CLB_STRETCHH;
+ if (IsDlgButtonChecked(hwndDlg,IDC_STRETCHV)) flags |= CLB_STRETCHV;
+ if (IsDlgButtonChecked(hwndDlg,IDC_TILEH)) flags |= CLBF_TILEH;
+ if (IsDlgButtonChecked(hwndDlg,IDC_TILEV)) flags |= CLBF_TILEV;
+ if (IsDlgButtonChecked(hwndDlg,IDC_SCROLL)) flags |= CLBF_SCROLL;
+ if (IsDlgButtonChecked(hwndDlg,IDC_PROPORTIONAL)) flags |= CLBF_PROPORTIONAL;
+ if (IsDlgButtonChecked(hwndDlg,IDC_TILEVROWH)) flags |= CLBF_TILEVTOROWHEIGHT;
+
+ db_set_w(NULL,"StatusBar","BkBmpUse",flags);
+ }
+ {
+ int hil = 0;
+ if (IsDlgButtonChecked(hwndDlg,IDC_HILIGHTMODE1)) hil = 1;
+ if (IsDlgButtonChecked(hwndDlg,IDC_HILIGHTMODE2)) hil = 2;
+ if (IsDlgButtonChecked(hwndDlg,IDC_HILIGHTMODE3)) hil = 3;
+
+ db_set_b(NULL,"StatusBar","HiLightMode",(BYTE)hil);
+ }
+
+ ClcOptionsChanged();
+ //OnStatusBarBackgroundChange();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static int _GetNetVisibleProtoCount()
+{
+ int i,count,netProtoCount;
+ PROTOACCOUNT **accs;
+ ProtoEnumAccounts( &count, &accs );
+ for (i=0,netProtoCount = 0;i < count;i++)
+ {
+ if ( pcli->pfnGetProtocolVisibility(accs[i]->szModuleName) == 0 )
+ continue;
+ netProtoCount++;
+ }
+ return netProtoCount;
+}
+
+TCHAR *sortby[] = {_T("Name"), _T("Name (use locale settings)") , _T("Status"), _T("Last message time"), _T("Account Name"), _T("Rate"), _T("-Nothing-")};
+int sortbyValue[] = { SORTBY_NAME, SORTBY_NAME_LOCALE, SORTBY_STATUS, SORTBY_LASTMSG, SORTBY_PROTO ,SORTBY_RATE , SORTBY_NOTHING };
+static INT_PTR CALLBACK DlgProcClistOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)HookEventMessage(ME_DB_CONTACT_SETTINGCHANGED,hwndDlg,WM_USER+1));
+
+ CheckDlgButton(hwndDlg, IDC_HIDEOFFLINE, db_get_b(NULL,"CList","HideOffline",SETTING_HIDEOFFLINE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_HIDEEMPTYGROUPS, db_get_b(NULL,"CList","HideEmptyGroups",SETTING_HIDEEMPTYGROUPS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DISABLEGROUPS, db_get_b(NULL,"CList","UseGroups",SETTING_USEGROUPS_DEFAULT) ? BST_UNCHECKED : BST_CHECKED);
+ CheckDlgButton(hwndDlg, IDC_CONFIRMDELETE, db_get_b(NULL,"CList","ConfirmDelete",SETTING_CONFIRMDELETE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg,IDC_GAMMACORRECT,db_get_b(NULL,"CLC","GammaCorrect",CLCDEFAULT_GAMMACORRECT)?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE,db_get_b(NULL,"CLC","HiLightMode",SETTING_HILIGHTMODE_DEFAULT) == 0?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE1,db_get_b(NULL,"CLC","HiLightMode",SETTING_HILIGHTMODE_DEFAULT) == 1?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE2,db_get_b(NULL,"CLC","HiLightMode",SETTING_HILIGHTMODE_DEFAULT) == 2?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_HILIGHTMODE3,db_get_b(NULL,"CLC","HiLightMode",SETTING_HILIGHTMODE_DEFAULT) == 3?BST_CHECKED:BST_UNCHECKED);
+
+ int i, item;
+ int s1, s2, s3;
+ for (i=0; i < SIZEOF(sortby); i++)
+ {
+ item = SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_ADDSTRING,0,(LPARAM)TranslateTS(sortby[i]));
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_SETITEMDATA,item,(LPARAM)0);
+ item = SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_ADDSTRING,0,(LPARAM)TranslateTS(sortby[i]));
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_SETITEMDATA,item,(LPARAM)0);
+ item = SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_ADDSTRING,0,(LPARAM)TranslateTS(sortby[i]));
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_SETITEMDATA,item,(LPARAM)0);
+
+ }
+ s1 = db_get_b(NULL,"CList","SortBy1",SETTING_SORTBY1_DEFAULT);
+ s2 = db_get_b(NULL,"CList","SortBy2",SETTING_SORTBY2_DEFAULT);
+ s3 = db_get_b(NULL,"CList","SortBy3",SETTING_SORTBY3_DEFAULT);
+
+ for (i=0; i < SIZEOF(sortby); i++)
+ {
+ if (s1 == sortbyValue[i])
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_SETCURSEL,i,0);
+ if (s2 == sortbyValue[i])
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_SETCURSEL,i,0);
+ if (s3 == sortbyValue[i])
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_SETCURSEL,i,0);
+ }
+
+ CheckDlgButton(hwndDlg, IDC_NOOFFLINEMOVE, db_get_b(NULL,"CList","NoOfflineBottom",SETTING_NOOFFLINEBOTTOM_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_OFFLINETOROOT, db_get_b(NULL,"CList","PlaceOfflineToRoot",SETTING_PLACEOFFLINETOROOT_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ }
+ return TRUE;
+ case WM_COMMAND:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CList","HideOffline",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_HIDEOFFLINE));
+ db_set_b(NULL,"CList","HideEmptyGroups",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_HIDEEMPTYGROUPS));
+ db_set_b(NULL,"CList","UseGroups",(BYTE)!IsDlgButtonChecked(hwndDlg,IDC_DISABLEGROUPS));
+ db_set_b(NULL,"CList","ConfirmDelete",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_CONFIRMDELETE));
+
+ db_set_b(NULL,"CLC","GammaCorrect",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_GAMMACORRECT));
+ int hil = 0;
+ if (IsDlgButtonChecked(hwndDlg,IDC_HILIGHTMODE1)) hil = 1;
+ if (IsDlgButtonChecked(hwndDlg,IDC_HILIGHTMODE2)) hil = 2;
+ if (IsDlgButtonChecked(hwndDlg,IDC_HILIGHTMODE3)) hil = 3;
+ db_set_b(NULL,"CLC","HiLightMode",(BYTE)hil);
+
+ int s1 = SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_GETCURSEL,0,0);
+ int s2 = SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_GETCURSEL,0,0);
+ int s3 = SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_GETCURSEL,0,0);
+ if (s1 >= 0) s1 = sortbyValue[s1];
+ if (s2 >= 0) s2 = sortbyValue[s2];
+ if (s3 >= 0) s3 = sortbyValue[s3];
+ db_set_b(NULL,"CList","SortBy1",(BYTE)s1);
+ db_set_b(NULL,"CList","SortBy2",(BYTE)s2);
+ db_set_b(NULL,"CList","SortBy3",(BYTE)s3);
+
+ db_set_b(NULL,"CList","NoOfflineBottom",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_NOOFFLINEMOVE));
+ db_set_b(NULL,"CList","PlaceOfflineToRoot",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_OFFLINETOROOT));
+
+ pcli->pfnLoadContactTree(); /* this won't do job properly since it only really works when changes happen */
+ SendMessage(pcli->hwndContactTree,CLM_AUTOREBUILD,0,0); /* force reshuffle */
+ ClcOptionsChanged(); // Used to force loading avatar an list height related options
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK DlgProcTrayOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_NOOFFLINEMOVE, db_get_b( NULL,"CList", "NoOfflineBottom", SETTING_NOOFFLINEBOTTOM_DEFAULT ) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_OFFLINETOROOT, db_get_b( NULL,"CList", "PlaceOfflineToRoot", SETTING_PLACEOFFLINETOROOT_DEFAULT ) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_ONECLK, db_get_b( NULL,"CList", "Tray1Click", SETTING_TRAY1CLICK_DEFAULT ) ? BST_CHECKED : BST_UNCHECKED);
+ {
+ BYTE trayOption = db_get_b(NULL,"CLUI","XStatusTray",SETTING_TRAYOPTION_DEFAULT);
+ CheckDlgButton(hwndDlg, IDC_SHOWXSTATUS, (trayOption&3) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWNORMAL, (trayOption&2) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_TRANSPARENTOVERLAY, (trayOption&4) ? BST_CHECKED : BST_UNCHECKED);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWNORMAL),IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSPARENTOVERLAY),IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL));
+ }
+ CheckDlgButton(hwndDlg, IDC_ALWAYSSTATUS, db_get_b(NULL,"CList","AlwaysStatus",SETTING_ALWAYSSTATUS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_ALWAYSPRIMARY, !db_get_b(NULL,"CList","AlwaysPrimary",SETTING_ALWAYSPRIMARY_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_ALWAYSMULTI, !db_get_b(NULL,"CList","AlwaysMulti",SETTING_ALWAYSMULTI_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DONTCYCLE, db_get_b(NULL,"CList","TrayIcon",SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_SINGLE ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_CYCLE, db_get_b(NULL,"CList","TrayIcon",SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_CYCLE ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_MULTITRAY, db_get_b(NULL,"CList","TrayIcon",SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_MULTI ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DISABLEBLINK, db_get_b(NULL,"CList","DisableTrayFlash",SETTING_DISABLETRAYFLASH_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOW_AVATARS, db_get_b(NULL,"CList","AvatarsShow",SETTINGS_SHOWAVATARS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_SHOW_ANIAVATARS, db_get_b(NULL,"CList","AvatarsAnimated",(ServiceExists(MS_AV_GETAVATARBITMAP) && !g_CluiData.fGDIPlusFail)) == 1 ? BST_CHECKED : BST_UNCHECKED );
+
+ if (IsDlgButtonChecked(hwndDlg,IDC_DONTCYCLE)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIMESPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIME),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ALWAYSMULTI),FALSE);
+ }
+ if (IsDlgButtonChecked(hwndDlg,IDC_CYCLE)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PRIMARYSTATUS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ALWAYSMULTI),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ALWAYSPRIMARY),FALSE);
+ }
+ if (IsDlgButtonChecked(hwndDlg,IDC_MULTITRAY)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIMESPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIME),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PRIMARYSTATUS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ALWAYSPRIMARY),FALSE);
+ }
+ SendDlgItemMessage(hwndDlg,IDC_CYCLETIMESPIN,UDM_SETRANGE,0,MAKELONG(120,1));
+ SendDlgItemMessage(hwndDlg,IDC_CYCLETIMESPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","CycleTime",SETTING_CYCLETIME_DEFAULT),0));
+ {
+ int i,count,item;
+ PROTOACCOUNT **accs;
+ DBVARIANT dbv = {DBVT_DELETED};
+ db_get(NULL,"CList","PrimaryStatus",&dbv);
+ ProtoEnumAccounts( &count, &accs );
+ item = SendDlgItemMessage(hwndDlg,IDC_PRIMARYSTATUS,CB_ADDSTRING,0,(LPARAM)TranslateT("Global"));
+ SendDlgItemMessage(hwndDlg,IDC_PRIMARYSTATUS,CB_SETITEMDATA,item,(LPARAM)0);
+ for (i=0;i < count;i++) {
+ if ( !IsAccountEnabled( accs[i] ) || CallProtoService(accs[i]->szModuleName,PS_GETCAPS,PFLAGNUM_2,0) == 0)
+ continue;
+
+ item = SendDlgItemMessage(hwndDlg,IDC_PRIMARYSTATUS,CB_ADDSTRING,0,(LPARAM)accs[i]->tszAccountName);
+ SendDlgItemMessage(hwndDlg,IDC_PRIMARYSTATUS,CB_SETITEMDATA,item,(LPARAM)accs[i]);
+ if ((dbv.type == DBVT_ASCIIZ || dbv.type == DBVT_UTF8) && !strcmp(dbv.pszVal,accs[i]->szModuleName))
+ SendDlgItemMessage(hwndDlg,IDC_PRIMARYSTATUS,CB_SETCURSEL,item,0);
+ }
+ db_free(&dbv);
+ }
+ if (-1 == (int)SendDlgItemMessage(hwndDlg,IDC_PRIMARYSTATUS,CB_GETCURSEL,0,0))
+ SendDlgItemMessage(hwndDlg,IDC_PRIMARYSTATUS,CB_SETCURSEL,0,0);
+ SendDlgItemMessage(hwndDlg,IDC_BLINKSPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_BLINKTIME),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_BLINKSPIN,UDM_SETRANGE,0,MAKELONG(0x3FFF,250));
+ SendDlgItemMessage(hwndDlg,IDC_BLINKSPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","IconFlashTime",SETTING_ICONFLASHTIME_DEFAULT),0));
+ {
+ int i = _GetNetVisibleProtoCount();
+ if (i < 2)
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PRIMARYSTATUS),TRUE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIMESPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIME),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ALWAYSPRIMARY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ALWAYSPRIMARY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTITRAY),FALSE);
+ CheckDlgButton(hwndDlg,IDC_DONTCYCLE,TRUE);
+ }
+ }
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_SHOWXSTATUS || LOWORD(wParam) == IDC_SHOWNORMAL)
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWNORMAL),IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSPARENTOVERLAY),IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL));
+ }
+ if (LOWORD(wParam) == IDC_DONTCYCLE || LOWORD(wParam) == IDC_CYCLE || LOWORD(wParam) == IDC_MULTITRAY)
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PRIMARYSTATUS),IsDlgButtonChecked(hwndDlg,IDC_DONTCYCLE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIME),IsDlgButtonChecked(hwndDlg,IDC_CYCLE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CYCLETIMESPIN),IsDlgButtonChecked(hwndDlg,IDC_CYCLE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ALWAYSMULTI),IsDlgButtonChecked(hwndDlg,IDC_MULTITRAY));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ALWAYSPRIMARY),IsDlgButtonChecked(hwndDlg,IDC_DONTCYCLE));
+ }
+ if (LOWORD(wParam) == IDC_PRIMARYSTATUS && HIWORD(wParam) != CBN_SELCHANGE) break;
+ if (LOWORD(wParam) == IDC_BLINKTIME && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0; // dont make apply enabled during buddy set crap
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CList","Tray1Click",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_ONECLK));
+ db_set_b(NULL,"CList","AlwaysStatus",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_ALWAYSSTATUS));
+
+ db_set_b(NULL,"CList","AlwaysMulti",(BYTE)!IsDlgButtonChecked(hwndDlg,IDC_ALWAYSMULTI));
+ db_set_b(NULL,"CList","AlwaysPrimary",(BYTE)!IsDlgButtonChecked(hwndDlg,IDC_ALWAYSPRIMARY));
+
+ db_set_w(NULL,"CList","CycleTime",(WORD)SendDlgItemMessage(hwndDlg,IDC_CYCLETIMESPIN,UDM_GETPOS,0,0));
+ db_set_w(NULL,"CList","IconFlashTime",(WORD)SendDlgItemMessage(hwndDlg,IDC_BLINKSPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CList","DisableTrayFlash",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DISABLEBLINK));
+
+ if (_GetNetVisibleProtoCount()>1)
+ db_set_b(NULL,"CList","TrayIcon",(BYTE)(IsDlgButtonChecked(hwndDlg,IDC_DONTCYCLE)?SETTING_TRAYICON_SINGLE:(IsDlgButtonChecked(hwndDlg,IDC_CYCLE)?SETTING_TRAYICON_CYCLE:SETTING_TRAYICON_MULTI)));
+
+ {
+ BYTE xOptions = 0;
+ xOptions = IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS)?1:0;
+ xOptions |= (xOptions && IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL))?2:0;
+ xOptions |= (xOptions && IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENTOVERLAY))?4:0;
+ db_set_b(NULL,"CLUI","XStatusTray",xOptions);
+
+ int cursel = SendDlgItemMessage(hwndDlg,IDC_PRIMARYSTATUS,CB_GETCURSEL,0,0);
+ PROTOACCOUNT* pa = (PROTOACCOUNT*)SendDlgItemMessage(hwndDlg,IDC_PRIMARYSTATUS,CB_GETITEMDATA,cursel,0);
+ if ( !pa )
+ db_unset(NULL, "CList","PrimaryStatus");
+ else
+ db_set_s(NULL,"CList","PrimaryStatus", pa->szModuleName);
+ }
+ pcli->pfnTrayIconIconsChanged();
+ pcli->pfnLoadContactTree(); /* this won't do job properly since it only really works when changes happen */
+ SendMessage(pcli->hwndContactTree,CLM_AUTOREBUILD,0,0); /* force reshuffle */
+ ClcOptionsChanged(); // Used to force loading avatar an list height related options
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+void ClcOptionsChanged(void)
+{
+ pcli->pfnClcBroadcast( INTM_RELOADOPTIONS,0,0);
+ pcli->pfnClcBroadcast( INTM_INVALIDATE,0,0);
+}
+
+HWND g_hCLUIOptionsWnd = NULL;
+
+static INT_PTR CALLBACK DlgProcClistBehaviourOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_CLIENTDRAG, db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DRAGTOSCROLL, (db_get_b(NULL,"CLUI","DragToScroll",SETTING_DRAGTOSCROLL_DEFAULT) && !db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT)) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_AUTOSIZE, g_CluiData.fAutoSize ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_LOCKSIZING, db_get_b(NULL,"CLUI","LockSize",SETTING_LOCKSIZE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_BRINGTOFRONT, db_get_b(NULL,"CList","BringToFront",SETTING_BRINGTOFRONT_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+
+ SendDlgItemMessage(hwndDlg,IDC_MAXSIZESPIN,UDM_SETRANGE,0,MAKELONG(100,0));
+ SendDlgItemMessage(hwndDlg,IDC_MAXSIZESPIN,UDM_SETPOS,0,db_get_b(NULL,"CLUI","MaxSizeHeight",SETTING_MAXSIZEHEIGHT_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_MINSIZESPIN,UDM_SETRANGE,0,MAKELONG(100,0));
+ SendDlgItemMessage(hwndDlg,IDC_MINSIZESPIN,UDM_SETPOS,0,db_get_b(NULL,"CLUI","MinSizeHeight",SETTING_MINSIZEHEIGHT_DEFAULT));
+ CheckDlgButton(hwndDlg, IDC_AUTOSIZEUPWARD, db_get_b(NULL,"CLUI","AutoSizeUpward",SETTING_AUTOSIZEUPWARD_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SNAPTOEDGES, db_get_b(NULL,"CLUI","SnapToEdges",SETTING_SNAPTOEDGES_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_DOCKTOSIDES, db_get_b(NULL,"CLUI","DockToSides",SETTING_DOCKTOSIDES_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_EVENTAREA_NONE, db_get_b(NULL,"CLUI","EventArea",SETTING_EVENTAREAMODE_DEFAULT) == 0 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_EVENTAREA, db_get_b(NULL,"CLUI","EventArea",SETTING_EVENTAREAMODE_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_EVENTAREA_ALWAYS, db_get_b(NULL,"CLUI","EventArea",SETTING_EVENTAREAMODE_DEFAULT) == 2 ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hwndDlg, IDC_AUTOHIDE, db_get_b(NULL,"CList","AutoHide",SETTING_AUTOHIDE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN,UDM_SETRANGE,0,MAKELONG(900,1));
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","HideTime",SETTING_HIDETIME_DEFAULT),0));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIME),IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN),IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC01),IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ {
+ int i, item;
+ TCHAR *hidemode[] = {TranslateT("Hide to tray"), TranslateT("Behind left edge"), TranslateT("Behind right edge")};
+ for (i=0; i < SIZEOF(hidemode); i++) {
+ item = SendDlgItemMessage(hwndDlg,IDC_HIDEMETHOD,CB_ADDSTRING,0,(LPARAM)(hidemode[i]));
+ SendDlgItemMessage(hwndDlg,IDC_HIDEMETHOD,CB_SETITEMDATA,item,(LPARAM)0);
+ SendDlgItemMessage(hwndDlg,IDC_HIDEMETHOD,CB_SETCURSEL,db_get_b(NULL,"ModernData","HideBehind",SETTING_HIDEBEHIND_DEFAULT),0);
+ }
+ }
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN2,UDM_SETRANGE,0,MAKELONG(600,0));
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN2,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"ModernData","ShowDelay",SETTING_SHOWDELAY_DEFAULT),0));
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN3,UDM_SETRANGE,0,MAKELONG(600,0));
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN3,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"ModernData","HideDelay",SETTING_HIDEDELAY_DEFAULT),0));
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN4,UDM_SETRANGE,0,MAKELONG(50,1));
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN4,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"ModernData","HideBehindBorderSize",SETTING_HIDEBEHINDBORDERSIZE_DEFAULT),0));
+ {
+ int mode = SendDlgItemMessage(hwndDlg,IDC_HIDEMETHOD,CB_GETCURSEL,0,0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWDELAY),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDEDELAY),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN2),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN3),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN4),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDEDELAY2),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC5),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC6),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC7),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC8),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC10),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC13),mode != 0);
+ }
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_AUTOSIZE)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC21),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC22),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MAXSIZEHEIGHT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MAXSIZESPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MINSIZEHEIGHT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MINSIZESPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AUTOSIZEUPWARD),FALSE);
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_AUTOHIDE) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIME),IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN),IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC01),IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ }
+ else if (LOWORD(wParam) == IDC_DRAGTOSCROLL && IsDlgButtonChecked(hwndDlg,IDC_CLIENTDRAG)) {
+ CheckDlgButton(hwndDlg,IDC_CLIENTDRAG,FALSE);
+ }
+ else if (LOWORD(wParam) == IDC_CLIENTDRAG && IsDlgButtonChecked(hwndDlg,IDC_DRAGTOSCROLL)) {
+ CheckDlgButton(hwndDlg,IDC_DRAGTOSCROLL,FALSE);
+ }
+ else if (LOWORD(wParam) == IDC_AUTOSIZE) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC21),IsDlgButtonChecked(hwndDlg,IDC_AUTOSIZE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC22),IsDlgButtonChecked(hwndDlg,IDC_AUTOSIZE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MAXSIZEHEIGHT),IsDlgButtonChecked(hwndDlg,IDC_AUTOSIZE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MAXSIZESPIN),IsDlgButtonChecked(hwndDlg,IDC_AUTOSIZE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MINSIZEHEIGHT),IsDlgButtonChecked(hwndDlg,IDC_AUTOSIZE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MINSIZESPIN),IsDlgButtonChecked(hwndDlg,IDC_AUTOSIZE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AUTOSIZEUPWARD),IsDlgButtonChecked(hwndDlg,IDC_AUTOSIZE));
+ }
+ else if (LOWORD(wParam) == IDC_HIDEMETHOD)
+ {
+ int mode = SendDlgItemMessage(hwndDlg,IDC_HIDEMETHOD,CB_GETCURSEL,0,0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWDELAY),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDEDELAY),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN2),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN3),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN4),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDEDELAY2),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC5),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC6),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC7),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC8),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC10),mode != 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC13),mode != 0);
+ }
+ if ((LOWORD(wParam) == IDC_HIDETIME || LOWORD(wParam) == IDC_HIDEDELAY2 || LOWORD(wParam) == IDC_HIDEDELAY || LOWORD(wParam) == IDC_SHOWDELAY || LOWORD(wParam) == IDC_MAXSIZEHEIGHT || LOWORD(wParam) == IDC_MINSIZEHEIGHT) &&
+ (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()))
+ return 0;
+
+ // Enable apply button
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"ModernData","HideBehind",(BYTE)SendDlgItemMessage(hwndDlg,IDC_HIDEMETHOD,CB_GETCURSEL,0,0));
+ db_set_w(NULL,"ModernData","ShowDelay",(WORD)SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN2,UDM_GETPOS,0,0));
+ db_set_w(NULL,"ModernData","HideDelay",(WORD)SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN3,UDM_GETPOS,0,0));
+ db_set_w(NULL,"ModernData","HideBehindBorderSize",(WORD)SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN4,UDM_GETPOS,0,0));
+
+ db_set_b(NULL,"CLUI","DragToScroll",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DRAGTOSCROLL));
+ db_set_b(NULL,"CList","BringToFront",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_BRINGTOFRONT));
+ g_mutex_bChangingMode = TRUE;
+ db_set_b(NULL,"CLUI","ClientAreaDrag",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_CLIENTDRAG));
+ db_set_b(NULL,"CLUI","AutoSize",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_AUTOSIZE));
+ db_set_b(NULL,"CLUI","LockSize",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_LOCKSIZING));
+ db_set_b(NULL,"CLUI","MaxSizeHeight",(BYTE)GetDlgItemInt(hwndDlg,IDC_MAXSIZEHEIGHT,NULL,FALSE));
+ db_set_b(NULL,"CLUI","MinSizeHeight",(BYTE)GetDlgItemInt(hwndDlg,IDC_MINSIZEHEIGHT,NULL,FALSE));
+ db_set_b(NULL,"CLUI","AutoSizeUpward",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_AUTOSIZEUPWARD));
+ db_set_b(NULL,"CLUI","SnapToEdges",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_SNAPTOEDGES));
+
+ db_set_b(NULL,"CLUI","DockToSides",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DOCKTOSIDES));
+
+ db_set_b(NULL,"CLUI","EventArea",
+ (BYTE)(IsDlgButtonChecked(hwndDlg,IDC_EVENTAREA_ALWAYS)?2:(BYTE)IsDlgButtonChecked(hwndDlg,IDC_EVENTAREA)?1:0));
+
+ db_set_b(NULL,"CList","AutoHide",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ db_set_w(NULL,"CList","HideTime",(WORD)SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN,UDM_GETPOS,0,0));
+ CLUI_ChangeWindowMode();
+ SendMessage(pcli->hwndContactTree,WM_SIZE,0,0); //forces it to send a cln_listsizechanged
+ CLUI_ReloadCLUIOptions();
+ EventArea_ConfigureEventArea();
+ cliShowHide(0,1);
+ g_mutex_bChangingMode = FALSE;
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK DlgProcClistWindowOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ BOOL fEnabled = FALSE;
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ g_hCLUIOptionsWnd = hwndDlg;
+ CheckDlgButton(hwndDlg, IDC_ONTOP, db_get_b(NULL,"CList","OnTop",SETTING_ONTOP_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ {
+ //====== Activate/Deactivate Non-Layered items =======
+ fEnabled = !g_CluiData.fLayered || g_CluiData.fDisableSkinEngine;
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOOLWND),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MIN2TRAY),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BORDER),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_NOBORDERWND),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWCAPTION),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWMAINMENU),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TITLETEXT),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DROPSHADOW),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AEROGLASS),!fEnabled && (g_proc_DWMEnableBlurBehindWindow != NULL));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TITLEBAR_STATIC),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ROUNDCORNERS),fEnabled);
+ }
+ {
+ //====== Non-Layered Mode =====
+ CheckDlgButton(hwndDlg, IDC_TOOLWND, db_get_b(NULL,"CList","ToolWindow",SETTING_TOOLWINDOW_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_MIN2TRAY, db_get_b(NULL,"CList","Min2Tray",SETTING_MIN2TRAY_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_BORDER, db_get_b(NULL,"CList","ThinBorder",SETTING_THINBORDER_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_NOBORDERWND, db_get_b(NULL,"CList","NoBorder",SETTING_NOBORDER_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ if (IsDlgButtonChecked(hwndDlg,IDC_TOOLWND))
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MIN2TRAY),FALSE);
+ CheckDlgButton(hwndDlg, IDC_SHOWCAPTION, db_get_b(NULL,"CLUI","ShowCaption",SETTING_SHOWCAPTION_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWMAINMENU, db_get_b(NULL,"CLUI","ShowMainMenu",SETTING_SHOWMAINMENU_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MIN2TRAY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOOLWND),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TITLETEXT),FALSE);
+ }
+ if (IsDlgButtonChecked(hwndDlg,IDC_BORDER) || IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MIN2TRAY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOOLWND),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TITLETEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWCAPTION),FALSE);
+ }
+ CheckDlgButton(hwndDlg, IDC_DROPSHADOW, db_get_b(NULL,"CList","WindowShadow",SETTING_WINDOWSHADOW_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_ROUNDCORNERS, db_get_b(NULL,"CLC","RoundCorners",SETTING_ROUNDCORNERS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ } //====== End of Non-Layered Mode =====
+
+ CheckDlgButton(hwndDlg, IDC_FADEINOUT, db_get_b(NULL,"CLUI","FadeInOut",SETTING_FADEIN_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_ONDESKTOP, db_get_b(NULL,"CList","OnDesktop", SETTING_ONDESKTOP_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ SendDlgItemMessage(hwndDlg,IDC_FRAMESSPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_CAPTIONSSPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_FRAMESSPIN,UDM_SETPOS,0,db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_CAPTIONSSPIN,UDM_SETPOS,0,db_get_dw(NULL,"CLUIFrames","GapBetweenTitleBar",SETTING_GAPTITLEBAR_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_LEFTMARGINSPIN,UDM_SETRANGE,0,MAKELONG(250,0));
+ SendDlgItemMessage(hwndDlg,IDC_RIGHTMARGINSPIN,UDM_SETRANGE,0,MAKELONG(250,0));
+ SendDlgItemMessage(hwndDlg,IDC_TOPMARGINSPIN,UDM_SETRANGE,0,MAKELONG(250,0));
+ SendDlgItemMessage(hwndDlg,IDC_BOTTOMMARGINSPIN,UDM_SETRANGE,0,MAKELONG(250,0));
+ SendDlgItemMessage(hwndDlg,IDC_LEFTMARGINSPIN,UDM_SETPOS,0,db_get_b(NULL,"CLUI","LeftClientMargin",SETTING_LEFTCLIENTMARIGN_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_RIGHTMARGINSPIN,UDM_SETPOS,0,db_get_b(NULL,"CLUI","RightClientMargin",SETTING_RIGHTCLIENTMARIGN_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_TOPMARGINSPIN,UDM_SETPOS,0,db_get_b(NULL,"CLUI","TopClientMargin",SETTING_TOPCLIENTMARIGN_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_BOTTOMMARGINSPIN,UDM_SETPOS,0,db_get_b(NULL,"CLUI","BottomClientMargin",SETTING_BOTTOMCLIENTMARIGN_DEFAULT));
+
+ CheckDlgButton(hwndDlg, IDC_DISABLEENGINE, db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_AEROGLASS, db_get_b(NULL,"ModernData","AeroGlass",SETTING_AEROGLASS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_LAYERENGINE),(g_proc_UpdateLayeredWindow != NULL && !db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT))?TRUE:FALSE);
+ CheckDlgButton(hwndDlg, IDC_LAYERENGINE, ((db_get_b(NULL,"ModernData","EnableLayering",SETTING_ENABLELAYERING_DEFAULT) && g_proc_UpdateLayeredWindow != NULL) && !db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT)) ? BST_UNCHECKED:BST_CHECKED);
+
+ {
+ DBVARIANT dbv = {0};
+ TCHAR *s;
+ if ( !DBGetContactSettingTString(NULL,"CList","TitleText",&dbv))
+ s = dbv.ptszVal;
+ else
+ s = _T(MIRANDANAME);
+ SetDlgItemText(hwndDlg, IDC_TITLETEXT, s);
+ db_free(&dbv);
+
+ SendDlgItemMessage(hwndDlg,IDC_TITLETEXT,CB_ADDSTRING,0,(LPARAM)MIRANDANAME);
+
+ char szUin[20];
+ sprintf(szUin,"%u",db_get_dw(NULL,"ICQ","UIN",0));
+ SendDlgItemMessage(hwndDlg,IDC_TITLETEXT,CB_ADDSTRING,0,(LPARAM)szUin);
+
+ if ( !DBGetContactSettingString(NULL,"ICQ","Nick",&dbv)) {
+ SendDlgItemMessage(hwndDlg,IDC_TITLETEXT,CB_ADDSTRING,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ dbv.pszVal = NULL;
+ }
+ if ( !DBGetContactSettingString(NULL,"ICQ","FirstName",&dbv)) {
+ SendDlgItemMessage(hwndDlg,IDC_TITLETEXT,CB_ADDSTRING,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ dbv.pszVal = NULL;
+ }
+ if ( !DBGetContactSettingString(NULL,"ICQ","e-mail",&dbv)) {
+ SendDlgItemMessage(hwndDlg,IDC_TITLETEXT,CB_ADDSTRING,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ dbv.pszVal = NULL;
+ }
+ }
+ if ( !IsWinVer2000Plus()) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_FADEINOUT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSPARENT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DROPSHADOW),FALSE);
+ }
+ else CheckDlgButton(hwndDlg,IDC_TRANSPARENT,db_get_b(NULL,"CList","Transparent",SETTING_TRANSPARENT_DEFAULT)?BST_CHECKED:BST_UNCHECKED);
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC11),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC12),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSACTIVE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSINACTIVE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ACTIVEPERC),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_INACTIVEPERC),FALSE);
+ }
+ SendDlgItemMessage(hwndDlg,IDC_TRANSACTIVE,TBM_SETRANGE,FALSE,MAKELONG(1,255));
+ SendDlgItemMessage(hwndDlg,IDC_TRANSINACTIVE,TBM_SETRANGE,FALSE,MAKELONG(1,255));
+ SendDlgItemMessage(hwndDlg,IDC_TRANSACTIVE,TBM_SETPOS,TRUE,db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_TRANSINACTIVE,TBM_SETPOS,TRUE,db_get_b(NULL,"CList","AutoAlpha",SETTING_AUTOALPHA_DEFAULT));
+ SendMessage(hwndDlg,WM_HSCROLL,0x12345678,0);
+ return TRUE;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_TRANSPARENT) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC11),IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC12),IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSACTIVE),IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSINACTIVE),IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ACTIVEPERC),IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_INACTIVEPERC),IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT));
+ }
+ else if (LOWORD(wParam) == IDC_LAYERENGINE || LOWORD(wParam) == IDC_DISABLEENGINE)
+ { //====== Activate/Deactivate Non-Layered items =======
+ fEnabled = !(IsWindowEnabled(GetDlgItem(hwndDlg,IDC_LAYERENGINE)) && !IsDlgButtonChecked(hwndDlg,IDC_LAYERENGINE) && !IsDlgButtonChecked(hwndDlg,IDC_DISABLEENGINE));
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOOLWND),fEnabled && (IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION)) && !(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MIN2TRAY),fEnabled && (IsDlgButtonChecked(hwndDlg,IDC_TOOLWND) && IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION)) && !(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TITLETEXT),fEnabled && (IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION)) && !(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWCAPTION),fEnabled && !(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BORDER),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_NOBORDERWND),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWMAINMENU),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DROPSHADOW),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AEROGLASS),!fEnabled && (g_proc_DWMEnableBlurBehindWindow != NULL));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TITLEBAR_STATIC),fEnabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ROUNDCORNERS),fEnabled);
+ if (LOWORD(wParam) == IDC_DISABLEENGINE)
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_LAYERENGINE),!IsDlgButtonChecked(hwndDlg,IDC_DISABLEENGINE) && g_proc_UpdateLayeredWindow != NULL);
+ if (IsDlgButtonChecked(hwndDlg,IDC_DISABLEENGINE))
+ CheckDlgButton(hwndDlg,IDC_LAYERENGINE,BST_CHECKED);
+ }
+
+ }
+ else if (LOWORD(wParam) == IDC_ONDESKTOP && IsDlgButtonChecked(hwndDlg,IDC_ONDESKTOP)) {
+ CheckDlgButton(hwndDlg, IDC_ONTOP, BST_UNCHECKED);
+ }
+ else if (LOWORD(wParam) == IDC_ONTOP && IsDlgButtonChecked(hwndDlg,IDC_ONTOP)) {
+ CheckDlgButton(hwndDlg, IDC_ONDESKTOP, BST_UNCHECKED);
+ }
+ else if (LOWORD(wParam) == IDC_TOOLWND) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MIN2TRAY),!IsDlgButtonChecked(hwndDlg,IDC_TOOLWND));
+ }
+ else if (LOWORD(wParam) == IDC_SHOWCAPTION) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOOLWND),IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MIN2TRAY),!IsDlgButtonChecked(hwndDlg,IDC_TOOLWND) && IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TITLETEXT),IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION));
+ }
+ else if (LOWORD(wParam) == IDC_NOBORDERWND || LOWORD(wParam) == IDC_BORDER)
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOOLWND),(IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION)) && !(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MIN2TRAY),(IsDlgButtonChecked(hwndDlg,IDC_TOOLWND) && IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION)) && !(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TITLETEXT),(IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION)) && !(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWCAPTION),!(IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND) || IsDlgButtonChecked(hwndDlg,IDC_BORDER)));
+ if (LOWORD(wParam) == IDC_BORDER) CheckDlgButton(hwndDlg, IDC_NOBORDERWND,BST_UNCHECKED);
+ else CheckDlgButton(hwndDlg, IDC_BORDER,BST_UNCHECKED);
+
+ }
+ if ((LOWORD(wParam) == IDC_TITLETEXT || LOWORD(wParam) == IDC_MAXSIZEHEIGHT || LOWORD(wParam) == IDC_MINSIZEHEIGHT || LOWORD(wParam) == IDC_FRAMESGAP || LOWORD(wParam) == IDC_CAPTIONSGAP ||
+ LOWORD(wParam) == IDC_LEFTMARGIN || LOWORD(wParam) == IDC_RIGHTMARGIN || LOWORD(wParam) == IDC_TOPMARGIN || LOWORD(wParam) == IDC_BOTTOMMARGIN)
+ && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()))
+ return 0;
+ // Enable apply button
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_HSCROLL:
+ { char str[10];
+ sprintf(str,"%d%%",100*SendDlgItemMessage(hwndDlg,IDC_TRANSINACTIVE,TBM_GETPOS,0,0)/255);
+ SetDlgItemTextA(hwndDlg,IDC_INACTIVEPERC,str);
+ sprintf(str,"%d%%",100*SendDlgItemMessage(hwndDlg,IDC_TRANSACTIVE,TBM_GETPOS,0,0)/255);
+ SetDlgItemTextA(hwndDlg,IDC_ACTIVEPERC,str);
+ }
+ if (wParam != 0x12345678) SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CLUI","LeftClientMargin",(BYTE)SendDlgItemMessage(hwndDlg,IDC_LEFTMARGINSPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CLUI","RightClientMargin",(BYTE)SendDlgItemMessage(hwndDlg,IDC_RIGHTMARGINSPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CLUI","TopClientMargin",(BYTE)SendDlgItemMessage(hwndDlg,IDC_TOPMARGINSPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CLUI","BottomClientMargin",(BYTE)SendDlgItemMessage(hwndDlg,IDC_BOTTOMMARGINSPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"ModernData","DisableEngine",IsDlgButtonChecked(hwndDlg,IDC_DISABLEENGINE));
+ db_set_b(NULL,"ModernData","AeroGlass",IsDlgButtonChecked(hwndDlg,IDC_AEROGLASS));
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_DISABLEENGINE))
+ {
+ if (g_proc_UpdateLayeredWindow != NULL && IsDlgButtonChecked(hwndDlg,IDC_LAYERENGINE))
+ db_set_b(NULL,"ModernData","EnableLayering",0);
+ else
+ db_unset(NULL,"ModernData","EnableLayering");
+ }
+ g_CluiData.dwKeyColor = db_get_dw(NULL,"ModernSettings","KeyColor",(DWORD)SETTING_KEYCOLOR_DEFAULT);
+ db_set_b(NULL,"CList","OnDesktop",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_ONDESKTOP));
+ db_set_b(NULL,"CList","OnTop",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_ONTOP));
+ SetWindowPos(pcli->hwndContactList, IsDlgButtonChecked(hwndDlg,IDC_ONTOP)?HWND_TOPMOST:HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |SWP_NOACTIVATE);
+ db_set_b(NULL,"CLUI","DragToScroll",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DRAGTOSCROLL));
+
+ { //====== Non-Layered Mode ======
+ db_set_b(NULL,"CList","ToolWindow",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_TOOLWND));
+ db_set_b(NULL,"CLUI","ShowCaption",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOWCAPTION));
+ db_set_b(NULL,"CLUI","ShowMainMenu",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOWMAINMENU));
+ db_set_b(NULL,"CList","ThinBorder",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_BORDER));
+ db_set_b(NULL,"CList","NoBorder",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_NOBORDERWND));
+ {
+ TCHAR title[256];
+ GetDlgItemText(hwndDlg,IDC_TITLETEXT,title,SIZEOF(title));
+ db_set_ws(NULL,"CList","TitleText",title);
+ }
+ db_set_b(NULL,"CList","Min2Tray",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_MIN2TRAY));
+ db_set_b(NULL,"CList","WindowShadow",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_DROPSHADOW));
+ db_set_b(NULL,"CLC","RoundCorners",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_ROUNDCORNERS));
+ } //====== End of Non-Layered Mode ======
+ g_mutex_bChangingMode = TRUE;
+
+ if (IsDlgButtonChecked(hwndDlg,IDC_ONDESKTOP))
+ {
+ HWND hProgMan = FindWindow(_T("Progman"),NULL);
+ if (IsWindow(hProgMan))
+ {
+ SetParent(pcli->hwndContactList,hProgMan);
+ Sync( CLUIFrames_SetParentForContainers, (HWND)hProgMan );
+ g_CluiData.fOnDesktop = 1;
+ }
+ }
+ else
+ {
+ if (GetParent(pcli->hwndContactList))
+ {
+ SetParent(pcli->hwndContactList,NULL);
+ Sync( CLUIFrames_SetParentForContainers, (HWND)NULL );
+ }
+ g_CluiData.fOnDesktop = 0;
+ }
+ AniAva_UpdateParent();
+ db_set_b(NULL,"CLUI","FadeInOut",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_FADEINOUT));
+ g_CluiData.fSmoothAnimation = IsWinVer2000Plus() && (BYTE)IsDlgButtonChecked(hwndDlg,IDC_FADEINOUT);
+ {
+ int i1 = SendDlgItemMessage(hwndDlg,IDC_FRAMESSPIN,UDM_GETPOS,0,0);
+ int i2 = SendDlgItemMessage(hwndDlg,IDC_CAPTIONSSPIN,UDM_GETPOS,0,0);
+
+ db_set_dw(NULL,"CLUIFrames","GapBetweenFrames",(DWORD)i1);
+ db_set_dw(NULL,"CLUIFrames","GapBetweenTitleBar",(DWORD)i2);
+ Sync(CLUIFramesOnClistResize, (WPARAM)pcli->hwndContactList,(LPARAM)0);
+ }
+ db_set_b(NULL,"CList","Transparent",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT));
+ db_set_b(NULL,"CList","Alpha",(BYTE)SendDlgItemMessage(hwndDlg,IDC_TRANSACTIVE,TBM_GETPOS,0,0));
+ db_set_b(NULL,"CList","AutoAlpha",(BYTE)SendDlgItemMessage(hwndDlg,IDC_TRANSINACTIVE,TBM_GETPOS,0,0));
+ db_set_b(NULL,"CList","OnDesktop",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_ONDESKTOP));
+
+ ske_LoadSkinFromDB();
+ CLUI_UpdateLayeredMode();
+ CLUI_ChangeWindowMode();
+ SendMessage(pcli->hwndContactTree,WM_SIZE,0,0); //forces it to send a cln_listsizechanged
+ CLUI_ReloadCLUIOptions();
+ cliShowHide(0,1);
+ g_mutex_bChangingMode = FALSE;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+#include "hdr/modern_commonheaders.h"
+
+#define CLBF_TILEVTOROWHEIGHT 0x0100
+
+
+#define DEFAULT_BKCOLOUR GetSysColor(COLOR_3DFACE)
+#define DEFAULT_USEBITMAP 0
+#define DEFAULT_BKBMPUSE CLB_STRETCH
+#define DEFAULT_SELBKCOLOUR GetSysColor(COLOR_HIGHLIGHT)
+
+extern HINSTANCE g_hInst;
+
+char **bkgrList = NULL;
+int bkgrCount = 0;
+
+#define M_BKGR_UPDATE (WM_USER+10)
+#define M_BKGR_SETSTATE (WM_USER+11)
+#define M_BKGR_GETSTATE (WM_USER+12)
+
+#define M_BKGR_BACKCOLOR 0x01
+#define M_BKGR_SELECTCOLOR 0x02
+#define M_BKGR_ALLOWBITMAPS 0x04
+#define M_BKGR_STRETCH 0x08
+#define M_BKGR_TILE 0x10
+
+static int bitmapRelatedControls[] = {
+ IDC_FILENAME,IDC_BROWSE,IDC_STRETCHH,IDC_STRETCHV,IDC_TILEH,IDC_TILEV,
+ IDC_SCROLL,IDC_PROPORTIONAL,IDC_TILEVROWH
+};
+struct BkgrItem
+{
+ BYTE changed;
+ BYTE useBitmap;
+ COLORREF bkColor, selColor;
+ char filename[MAX_PATH];
+ WORD flags;
+ BYTE useWinColours;
+};
+struct BkgrData
+{
+ struct BkgrItem *item;
+ int indx;
+ int count;
+};
+
+static INT_PTR CALLBACK DlgProcClcBkgOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct BkgrData *dat = (struct BkgrData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ int indx;
+ HWND hList = GetDlgItem(hwndDlg, IDC_BKGRLIST);
+ TranslateDialogDefault(hwndDlg);
+
+ dat = (struct BkgrData*)mir_alloc(sizeof(struct BkgrData));
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
+ dat->count = bkgrCount;
+ dat->item = (struct BkgrItem*)mir_alloc(sizeof(struct BkgrItem)*dat->count);
+ dat->indx = CB_ERR;
+ for (indx = 0; indx < dat->count; indx++)
+ {
+ char *module = bkgrList[indx] + strlen(bkgrList[indx]) + 1;
+ int jndx;
+
+ dat->item[indx].changed = FALSE;
+ dat->item[indx].useBitmap = db_get_b(NULL,module, "UseBitmap", DEFAULT_USEBITMAP);
+ dat->item[indx].bkColor = db_get_dw(NULL,module, "BkColour", DEFAULT_BKCOLOUR);
+ dat->item[indx].selColor = db_get_dw(NULL,module, "SelBkColour", DEFAULT_SELBKCOLOUR);
+ dat->item[indx].useWinColours = db_get_b(NULL,module, "UseWinColours", CLCDEFAULT_USEWINDOWSCOLOURS);
+ {
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingString(NULL,module,"BkBitmap",&dbv))
+ {
+ int retval = CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)dbv.pszVal, (LPARAM)dat->item[indx].filename);
+ if ( !retval || retval == CALLSERVICE_NOTFOUND)
+ lstrcpynA(dat->item[indx].filename, dbv.pszVal, MAX_PATH);
+ mir_free(dbv.pszVal);
+ }
+ else
+ *dat->item[indx].filename = 0;
+ }
+ dat->item[indx].flags = db_get_w(NULL,module,"BkBmpUse", DEFAULT_BKBMPUSE);
+ jndx = SendMessageA(hList, CB_ADDSTRING, 0, (LPARAM)Translate(bkgrList[indx]));
+ SendMessage(hList, CB_SETITEMDATA, jndx, indx);
+ }
+ SendMessage(hList, CB_SETCURSEL, 0, 0);
+ PostMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_BKGRLIST, CBN_SELCHANGE), 0);
+ {
+ HRESULT (STDAPICALLTYPE *MySHAutoComplete)(HWND,DWORD);
+ MySHAutoComplete = (HRESULT (STDAPICALLTYPE*)(HWND,DWORD))GetProcAddress(GetModuleHandleA("shlwapi"),"SHAutoComplete");
+ if (MySHAutoComplete) MySHAutoComplete(GetDlgItem(hwndDlg,IDC_FILENAME),1);
+ }
+ return TRUE;
+ }
+ case WM_DESTROY:
+ if (dat) {
+ mir_free(dat->item);
+ mir_free(dat);
+ }
+
+ return TRUE;
+
+ case M_BKGR_GETSTATE:
+ {
+ int indx = wParam;
+ if (indx == CB_ERR || indx >= dat->count) break;
+ indx = SendDlgItemMessage(hwndDlg, IDC_BKGRLIST, CB_GETITEMDATA, indx, 0);
+
+ dat->item[indx].useBitmap = IsDlgButtonChecked(hwndDlg,IDC_BITMAP);
+ dat->item[indx].useWinColours = IsDlgButtonChecked(hwndDlg,IDC_USEWINCOL);
+ dat->item[indx].bkColor = SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_GETCOLOUR,0,0);
+ dat->item[indx].selColor = SendDlgItemMessage(hwndDlg, IDC_SELCOLOUR, CPM_GETCOLOUR,0,0);
+
+ GetDlgItemTextA(hwndDlg, IDC_FILENAME, dat->item[indx].filename, SIZEOF(dat->item[indx].filename));
+ {
+ WORD flags = 0;
+ if (IsDlgButtonChecked(hwndDlg,IDC_STRETCHH)) flags |= CLB_STRETCHH;
+ if (IsDlgButtonChecked(hwndDlg,IDC_STRETCHV)) flags |= CLB_STRETCHV;
+ if (IsDlgButtonChecked(hwndDlg,IDC_TILEH)) flags |= CLBF_TILEH;
+ if (IsDlgButtonChecked(hwndDlg,IDC_TILEV)) flags |= CLBF_TILEV;
+ if (IsDlgButtonChecked(hwndDlg,IDC_SCROLL)) flags |= CLBF_SCROLL;
+ if (IsDlgButtonChecked(hwndDlg,IDC_PROPORTIONAL)) flags |= CLBF_PROPORTIONAL;
+ if (IsDlgButtonChecked(hwndDlg,IDC_TILEVROWH)) flags |= CLBF_TILEVTOROWHEIGHT;
+ dat->item[indx].flags = flags;
+ }
+ break;
+ }
+ case M_BKGR_SETSTATE:
+ {
+ int flags;
+ int indx = wParam;
+ if (indx == -1) break;
+ flags = dat->item[indx].flags;
+ if (indx == CB_ERR || indx >= dat->count) break;
+ indx = SendDlgItemMessage(hwndDlg, IDC_BKGRLIST, CB_GETITEMDATA, indx, 0);
+
+ CheckDlgButton(hwndDlg, IDC_BITMAP, dat->item[indx].useBitmap?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_USEWINCOL, dat->item[indx].useWinColours?BST_CHECKED:BST_UNCHECKED);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BKGCOLOUR), !dat->item[indx].useWinColours);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SELCOLOUR), !dat->item[indx].useWinColours);
+
+ SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETDEFAULTCOLOUR, 0, DEFAULT_BKCOLOUR);
+ SendDlgItemMessage(hwndDlg, IDC_BKGCOLOUR, CPM_SETCOLOUR, 0, dat->item[indx].bkColor);
+ SendDlgItemMessage(hwndDlg, IDC_SELCOLOUR, CPM_SETDEFAULTCOLOUR, 0, DEFAULT_SELBKCOLOUR);
+ SendDlgItemMessage(hwndDlg, IDC_SELCOLOUR, CPM_SETCOLOUR, 0, dat->item[indx].selColor);
+ SetDlgItemTextA(hwndDlg, IDC_FILENAME, dat->item[indx].filename);
+
+ CheckDlgButton(hwndDlg,IDC_STRETCHH, flags&CLB_STRETCHH?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_STRETCHV,flags&CLB_STRETCHV?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_TILEH,flags&CLBF_TILEH?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_TILEV,flags&CLBF_TILEV?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_SCROLL,flags&CLBF_SCROLL?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_PROPORTIONAL,flags&CLBF_PROPORTIONAL?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,IDC_TILEVROWH,flags&CLBF_TILEVTOROWHEIGHT?BST_CHECKED:BST_UNCHECKED);
+
+ SendMessage(hwndDlg, M_BKGR_UPDATE, 0,0);
+ break;
+ }
+ case M_BKGR_UPDATE:
+ {
+ int isChecked = IsDlgButtonChecked(hwndDlg,IDC_BITMAP);
+ int indx;
+ for (indx = 0; indx < SIZEOF(bitmapRelatedControls); indx++)
+ EnableWindow(GetDlgItem(hwndDlg, bitmapRelatedControls[indx]),isChecked);
+ break;
+ }
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_BROWSE)
+ {
+ char str[MAX_PATH];
+ OPENFILENAMEA ofn = {0};
+ char filter[512];
+
+ GetDlgItemTextA(hwndDlg,IDC_FILENAME, str, SIZEOF(str));
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = hwndDlg;
+ ofn.hInstance = NULL;
+ CallService(MS_UTILS_GETBITMAPFILTERSTRINGS, SIZEOF(filter), (LPARAM)filter);
+ ofn.lpstrFilter = filter;
+ ofn.lpstrFile = str;
+ ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
+ ofn.nMaxFile = SIZEOF(str);
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.lpstrDefExt = "bmp";
+ if ( !GetOpenFileNameA(&ofn)) break;
+ SetDlgItemTextA(hwndDlg, IDC_FILENAME, str);
+ }
+ else
+ if (LOWORD(wParam) == IDC_FILENAME && HIWORD(wParam) != EN_CHANGE) break;
+ if (LOWORD(wParam) == IDC_BITMAP)
+ SendMessage(hwndDlg, M_BKGR_UPDATE, 0,0);
+ if (LOWORD(wParam) == IDC_FILENAME && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()))
+ return 0;
+ if (LOWORD(wParam) == IDC_BKGRLIST)
+ {
+ if (HIWORD(wParam) == CBN_SELCHANGE)
+ {
+ SendMessage(hwndDlg, M_BKGR_GETSTATE, dat->indx, 0);
+ SendMessage(hwndDlg, M_BKGR_SETSTATE, dat->indx = SendDlgItemMessage(hwndDlg, IDC_BKGRLIST, CB_GETCURSEL, 0,0), 0);
+ }
+ return 0;
+ }
+ {
+ int indx = SendDlgItemMessage(hwndDlg, IDC_BKGRLIST, CB_GETCURSEL, 0,0);
+ if (indx != CB_ERR && indx < dat->count)
+ {
+ indx = SendDlgItemMessage(hwndDlg, IDC_BKGRLIST, CB_GETITEMDATA, indx, 0);
+ dat->item[indx].changed = TRUE;
+
+ }
+ {
+ BOOL EnableColours = !IsDlgButtonChecked(hwndDlg,IDC_USEWINCOL);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BKGCOLOUR), EnableColours);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SELCOLOUR), EnableColours);
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0,0);
+ }
+ break;
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ SendMessage(hwndDlg, M_BKGR_GETSTATE, SendDlgItemMessage(hwndDlg, IDC_BKGRLIST, CB_GETCURSEL, 0,0), 0);
+ {
+ for (int indx = 0; indx < dat->count; indx++)
+ if (dat->item[indx].changed)
+ {
+ char *module = bkgrList[indx] + strlen(bkgrList[indx]) + 1;
+ db_set_b(NULL, module, "UseBitmap", (BYTE)dat->item[indx].useBitmap);
+
+ COLORREF col;
+ if ((col = dat->item[indx].bkColor) == DEFAULT_BKCOLOUR)
+ db_unset(NULL, module, "BkColour");
+ else
+ db_set_dw(NULL, module, "BkColour", col);
+
+ if ((col = dat->item[indx].selColor) == DEFAULT_SELBKCOLOUR)
+ db_unset(NULL, module, "SelBkColour");
+ else
+ db_set_dw(NULL, module, "SelBkColour", col);
+
+ db_set_b(NULL, module, "UseWinColours", (BYTE)dat->item[indx].useWinColours);
+
+ char str[MAX_PATH];
+ int retval = CallService(MS_UTILS_PATHTOABSOLUTE,
+ (WPARAM)dat->item[indx].filename,
+ (LPARAM)str);
+ if ( !retval || retval == CALLSERVICE_NOTFOUND)
+ db_set_s(NULL, module, "BkBitmap", dat->item[indx].filename);
+ else
+ db_set_s(NULL, module, "BkBitmap", str);
+
+ db_set_w(NULL, module, "BkBmpUse", dat->item[indx].flags);
+ dat->item[indx].changed = FALSE;
+ NotifyEventHooks(g_CluiData.hEventBkgrChanged, (WPARAM)module, 0);
+ }
+ return TRUE;
+ }
+ }
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR BkgrCfg_Register(WPARAM wParam,LPARAM lParam)
+{
+ char *szSetting = (char *)wParam;
+ char *value, *tok;
+ int len = strlen(szSetting) + 1;
+
+ value = (char *)mir_alloc(len + 4); // add room for flags (DWORD)
+ memcpy(value, szSetting, len);
+ tok = strchr(value, '/');
+ if (tok == NULL) {
+ mir_free(value);
+ return 1;
+ }
+ *tok = 0;
+ *(DWORD*)(value + len) = lParam;
+
+ bkgrList = (char **)mir_realloc(bkgrList, sizeof(char*)*(bkgrCount+1));
+ bkgrList[bkgrCount] = value;
+ bkgrCount++;
+ return 0;
+}
+
+HRESULT BackgroundsLoadModule()
+{
+ CreateServiceFunction(MS_BACKGROUNDCONFIG_REGISTER, BkgrCfg_Register);
+ return S_OK;
+}
+
+int BackgroundsUnloadModule(void)
+{
+ if (bkgrList != NULL) {
+ for (int indx = 0; indx < bkgrCount; indx++)
+ if (bkgrList[indx] != NULL)
+ mir_free(bkgrList[indx]);
+ mir_free(bkgrList);
+ }
+ DestroyHookableEvent(g_CluiData.hEventBkgrChanged);
+ g_CluiData.hEventBkgrChanged = NULL;
+
+ return 0;
+}
+
+
+
+
+
+enum
+{
+ CBVT_NONE,
+ CBVT_CHAR,
+ CBVT_INT,
+ CBVT_BYTE,
+ CBVT_DWORD,
+ CBVT_BOOL,
+};
+
+struct OptCheckBox
+{
+ UINT idc;
+
+ DWORD defValue; // should be full combined value for masked items!
+ DWORD dwBit;
+
+ BYTE dbType;
+ char *dbModule;
+ char *dbSetting;
+
+ BYTE valueType;
+ union
+ {
+ void *pValue;
+
+ char *charValue;
+ int *intValue;
+ BYTE *byteValue;
+ DWORD *dwordValue;
+ BOOL *boolValue;
+ };
+};
+
+DWORD OptCheckBox_LoadValue(struct OptCheckBox *cb)
+{
+ switch (cb->valueType)
+ {
+ case CBVT_NONE:
+ switch (cb->dbType)
+ {
+ case DBVT_BYTE:
+ return db_get_b(NULL, cb->dbModule, cb->dbSetting, cb->defValue);
+ case DBVT_WORD:
+ return db_get_w(NULL, cb->dbModule, cb->dbSetting, cb->defValue);
+ case DBVT_DWORD:
+ return db_get_dw(NULL, cb->dbModule, cb->dbSetting, cb->defValue);
+ }
+ break;
+
+ case CBVT_CHAR:
+ return *cb->charValue;
+ case CBVT_INT:
+ return *cb->intValue;
+ case CBVT_BYTE:
+ return *cb->byteValue;
+ case CBVT_DWORD:
+ return *cb->dwordValue;
+ case CBVT_BOOL:
+ return *cb->boolValue;
+ }
+
+ return cb->defValue;
+}
+
+void OptCheckBox_Load(HWND hwnd, struct OptCheckBox *cb)
+{
+ DWORD value = OptCheckBox_LoadValue(cb);
+ if (cb->dwBit) value &= cb->dwBit;
+ CheckDlgButton(hwnd, cb->idc, value ? BST_CHECKED : BST_UNCHECKED);
+}
+
+void OptCheckBox_Save(HWND hwnd, struct OptCheckBox *cb)
+{
+ DWORD value = IsDlgButtonChecked(hwnd, cb->idc) == BST_CHECKED;
+
+ if (cb->dwBit)
+ {
+ DWORD curValue = OptCheckBox_LoadValue(cb);
+ value = value ? (curValue | cb->dwBit) : (curValue & ~cb->dwBit);
+ }
+
+ switch (cb->dbType)
+ {
+ case DBVT_BYTE:
+ db_set_b(NULL, cb->dbModule, cb->dbSetting, (BYTE)value);
+ break;
+ case DBVT_WORD:
+ db_set_w(NULL, cb->dbModule, cb->dbSetting, (WORD)value);
+ break;
+ case DBVT_DWORD:
+ db_set_dw(NULL, cb->dbModule, cb->dbSetting, (DWORD)value);
+ break;
+ }
+
+ switch (cb->valueType)
+ {
+ case CBVT_CHAR:
+ *cb->charValue = (char)value;
+ break;
+ case CBVT_INT:
+ *cb->intValue = (int)value;
+ break;
+ case CBVT_BYTE:
+ *cb->byteValue = (BYTE)value;
+ break;
+ case CBVT_DWORD:
+ *cb->dwordValue = (DWORD)value;
+ break;
+ case CBVT_BOOL:
+ *cb->boolValue = (BOOL)value;
+ break;
+ }
+}
+
+static INT_PTR CALLBACK DlgProcModernOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ struct OptCheckBox opts[] =
+ {
+ //{IDC_, def, bit, dbtype, dbmodule, dbsetting, valtype, pval},
+ {IDC_ONTOP, SETTING_ONTOP_DEFAULT, 0, DBVT_BYTE, "CList", "OnTop"},
+ {IDC_AUTOHIDE, SETTING_AUTOHIDE_DEFAULT, 0, DBVT_BYTE, "CList", "AutoHide"},
+ {IDC_FADEINOUT, SETTING_FADEIN_DEFAULT, 0, DBVT_BYTE, "CLUI", "FadeInOut"},
+ {IDC_TRANSPARENT, SETTING_TRANSPARENT_DEFAULT, 0, DBVT_BYTE, "CList", "Transparent"},
+ {IDC_SHOWGROUPCOUNTS, GetDefaultExStyle(), CLS_EX_SHOWGROUPCOUNTS, DBVT_DWORD, "CLC", "ExStyle"},
+ {IDC_HIDECOUNTSWHENEMPTY, GetDefaultExStyle(), CLS_EX_HIDECOUNTSWHENEMPTY, DBVT_DWORD, "CLC", "ExStyle"},
+ {IDC_MINIMODE, SETTING_COMPACTMODE_DEFAULT, 0, DBVT_BYTE, "CLC", "CompactMode"},
+ {IDC_SHOW_AVATARS, SETTINGS_SHOWAVATARS_DEFAULT, 0, DBVT_BYTE, "CList","AvatarsShow"},
+ {IDC_SHOW_ANIAVATARS, FALSE, 0, DBVT_BYTE, "CList","AvatarsAnimated"},
+ {IDC_SHOW, SETTING_SHOWTIME_DEFAULT, 0, DBVT_BYTE, "CList", "ContactTimeShow"},
+ };
+
+ static bool bInit = true;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ {
+ bInit = true;
+
+ int i=0;
+ int item;
+ int s1, s2, s3;
+
+ TranslateDialogDefault(hwndDlg);
+ for (i=0; i < SIZEOF(opts); ++i)
+ OptCheckBox_Load(hwndDlg, opts+i);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIME),IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN),IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN,UDM_SETRANGE,0,MAKELONG(900,1));
+ SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","HideTime",SETTING_HIDETIME_DEFAULT),0));
+
+ if ( !IsWinVer2000Plus())
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_FADEINOUT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSPARENT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DROPSHADOW),FALSE);
+ }
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT))
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC11),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC12),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSACTIVE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSINACTIVE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ACTIVEPERC),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_INACTIVEPERC),FALSE);
+ }
+ SendDlgItemMessage(hwndDlg,IDC_TRANSACTIVE,TBM_SETRANGE,FALSE,MAKELONG(1,255));
+ SendDlgItemMessage(hwndDlg,IDC_TRANSINACTIVE,TBM_SETRANGE,FALSE,MAKELONG(1,255));
+ SendDlgItemMessage(hwndDlg,IDC_TRANSACTIVE,TBM_SETPOS,TRUE,db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT));
+ SendDlgItemMessage(hwndDlg,IDC_TRANSINACTIVE,TBM_SETPOS,TRUE,db_get_b(NULL,"CList","AutoAlpha",SETTING_AUTOALPHA_DEFAULT));
+ SendMessage(hwndDlg,WM_HSCROLL,0x12345678,0);
+
+
+ for (i=0; i < SIZEOF(sortby); i++)
+ {
+ item = SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_ADDSTRING,0,(LPARAM)TranslateTS(sortby[i]));
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_SETITEMDATA,item,(LPARAM)0);
+ item = SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_ADDSTRING,0,(LPARAM)TranslateTS(sortby[i]));
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_SETITEMDATA,item,(LPARAM)0);
+ item = SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_ADDSTRING,0,(LPARAM)TranslateTS(sortby[i]));
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_SETITEMDATA,item,(LPARAM)0);
+
+ }
+ s1 = db_get_b(NULL,"CList","SortBy1",SETTING_SORTBY1_DEFAULT);
+ s2 = db_get_b(NULL,"CList","SortBy2",SETTING_SORTBY2_DEFAULT);
+ s3 = db_get_b(NULL,"CList","SortBy3",SETTING_SORTBY3_DEFAULT);
+
+ for (i=0; i < SIZEOF(sortby); i++)
+ {
+ if (s1 == sortbyValue[i])
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_SETCURSEL,i,0);
+ if (s2 == sortbyValue[i])
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_SETCURSEL,i,0);
+ if (s3 == sortbyValue[i])
+ SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_SETCURSEL,i,0);
+ }
+
+ bInit = false;
+ return TRUE;
+ }
+
+ case WM_DESTROY:
+ bInit = true;
+ break;
+
+ case WM_HSCROLL:
+ { char str[10];
+ sprintf(str,"%d%%",100*SendDlgItemMessage(hwndDlg,IDC_TRANSINACTIVE,TBM_GETPOS,0,0)/255);
+ SetDlgItemTextA(hwndDlg,IDC_INACTIVEPERC,str);
+ sprintf(str,"%d%%",100*SendDlgItemMessage(hwndDlg,IDC_TRANSACTIVE,TBM_GETPOS,0,0)/255);
+ SetDlgItemTextA(hwndDlg,IDC_ACTIVEPERC,str);
+ if (wParam != 0x12345678)
+ if ( !bInit) SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+ }
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDC_AUTOHIDE:
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIME),IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HIDETIMESPIN),IsDlgButtonChecked(hwndDlg,IDC_AUTOHIDE));
+ break;
+ case IDC_TRANSPARENT:
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC11),IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC12),IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSACTIVE),IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSINACTIVE),IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ACTIVEPERC),IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_INACTIVEPERC),IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENT));
+ break;
+ }
+ if ( !bInit) SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR) lParam)->idFrom)
+ {
+ case 0:
+ switch (((LPNMHDR) lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ int i;
+
+ g_mutex_bChangingMode = TRUE;
+
+ for (i=0; i < SIZEOF(opts); ++i)
+ OptCheckBox_Save(hwndDlg, opts+i);
+
+ SetWindowPos(pcli->hwndContactList, IsDlgButtonChecked(hwndDlg,IDC_ONTOP)?HWND_TOPMOST:HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ db_set_w(NULL,"CList","HideTime",(WORD)SendDlgItemMessage(hwndDlg,IDC_HIDETIMESPIN,UDM_GETPOS,0,0));
+
+ db_set_b(NULL,"CList","Alpha",(BYTE)SendDlgItemMessage(hwndDlg,IDC_TRANSACTIVE,TBM_GETPOS,0,0));
+ db_set_b(NULL,"CList","AutoAlpha",(BYTE)SendDlgItemMessage(hwndDlg,IDC_TRANSINACTIVE,TBM_GETPOS,0,0));
+
+ {
+ int s1 = SendDlgItemMessage(hwndDlg,IDC_CLSORT1,CB_GETCURSEL,0,0);
+ int s2 = SendDlgItemMessage(hwndDlg,IDC_CLSORT2,CB_GETCURSEL,0,0);
+ int s3 = SendDlgItemMessage(hwndDlg,IDC_CLSORT3,CB_GETCURSEL,0,0);
+ if (s1 >= 0) s1 = sortbyValue[s1];
+ if (s2 >= 0) s2 = sortbyValue[s2];
+ if (s3 >= 0) s3 = sortbyValue[s3];
+ db_set_b(NULL,"CList","SortBy1",(BYTE)s1);
+ db_set_b(NULL,"CList","SortBy2",(BYTE)s2);
+ db_set_b(NULL,"CList","SortBy3",(BYTE)s3);
+ }
+
+ ClcOptionsChanged();
+ AniAva_UpdateOptions();
+ ske_LoadSkinFromDB();
+ CLUI_UpdateLayeredMode();
+ CLUI_ChangeWindowMode();
+ SendMessage(pcli->hwndContactTree,WM_SIZE,0,0); //forces it to send a cln_listsizechanged
+ CLUI_ReloadCLUIOptions();
+ cliShowHide(0,1);
+ g_mutex_bChangingMode = FALSE;
+ return TRUE;
+ }
+ }
+ break;
+ }
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+int ModernOptInit(WPARAM wParam,LPARAM lParam)
+{
+ static int iBoldControls[] =
+ {
+ IDC_TXT_TITLE1, IDC_TXT_TITLE2,
+ IDC_TXT_TITLE3, IDC_TXT_TITLE4,
+ IDC_TXT_TITLE5,
+ MODERNOPT_CTRL_LAST
+ };
+
+ MODERNOPTOBJECT obj = {0};
+
+ obj.cbSize = sizeof(obj);
+ obj.dwFlags = MODEROPT_FLG_TCHAR|MODEROPT_FLG_NORESIZE;
+ obj.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ obj.hInstance = g_hInst;
+ obj.iSection = MODERNOPT_PAGE_CLIST;
+ obj.iType = MODERNOPT_TYPE_SECTIONPAGE;
+ obj.iBoldControls = iBoldControls;
+ obj.lptzSubsection = _T("Fonts");
+ obj.lpzClassicGroup = NULL;
+ obj.lpzClassicPage = "Contact List";
+ obj.lpzHelpUrl = "http://wiki.miranda-im.org/";
+
+ obj.lpzTemplate = MAKEINTRESOURCEA(IDD_MODERNOPTS);
+ obj.pfnDlgProc = DlgProcModernOptions;
+ CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj);
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_clcpaint.cpp b/plugins/Clist_modern/src/modern_clcpaint.cpp
new file mode 100644
index 0000000000..20839cb12c
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clcpaint.cpp
@@ -0,0 +1,3385 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or ( at your option ) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+#include "hdr/modern_commonheaders.h"
+
+#include "m_clc.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_skinengine.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_row.h"
+#include "hdr/modern_clcpaint.h"
+
+CLCPaint g_clcPainter;
+
+DWORD CLCPaint::HASH[hi_LastItem] = {0};
+const char* CLCPaint::HASHTEXT[hi_LastItem] = {
+ "Module",
+ "ID",
+ "Type",
+ "Open",
+ "IsEmpty",
+ "SubPos",
+ "Protocol",
+ "RootGroup",
+ "Status",
+ "HasAvatar",
+ "GroupPos",
+ "Selected",
+ "Hot",
+ "Odd",
+ "Indent",
+ "Index",
+ "Name",
+ "Group",
+ "True",
+ "False",
+ "ONLINE",
+ "AWAY",
+ "DND",
+ "NA",
+ "OCCUPIED",
+ "FREECHAT",
+ "INVISIBLE",
+ "OUTTOLUNCH",
+ "ONTHEPHONE",
+ "IDLE",
+ "OFFLINE",
+ "Row",
+ "CL",
+ "SubContact",
+ "MetaContact",
+ "Contact",
+ "Divider",
+ "Info",
+ "First-Single",
+ "First",
+ "Middle",
+ "Mid",
+ "Single",
+ "Last",
+ "Rate",
+ "None",
+ "Low",
+ "Medium",
+ "High",
+ "State",
+ "Active",
+ "Inactive"
+ //ADD item here
+};
+const int CLCPaint::HORIZONTAL_SPACE = 2;
+const int CLCPaint::EXTRA_CHECKBOX_SPACE = 2;
+const int CLCPaint::EXTRA_SPACE = 2;
+const int CLCPaint::SELECTION_BORDER = 6;
+const int CLCPaint::MIN_TEXT_WIDTH = 20;
+const int CLCPaint::BUF2SIZE = 7;
+
+const BYTE CLCPaint::GIM_SELECTED_AFFECT = 1;
+const BYTE CLCPaint::GIM_HOT_AFFECT = 2;
+const BYTE CLCPaint::GIM_TEMP_AFFECT = 4;
+const BYTE CLCPaint::GIM_IDLE_AFFECT = 8;
+const BYTE CLCPaint::GIM_EXTRAICON_AFFECT = CLCPaint::GIM_SELECTED_AFFECT | CLCPaint::GIM_HOT_AFFECT | CLCPaint::GIM_IDLE_AFFECT | CLCPaint::GIM_TEMP_AFFECT;
+const BYTE CLCPaint::GIM_STATUSICON_AFFECT = CLCPaint::GIM_IDLE_AFFECT | CLCPaint::GIM_TEMP_AFFECT;
+const BYTE CLCPaint::GIM_AVATAR_AFFECT = CLCPaint::GIM_IDLE_AFFECT | CLCPaint::GIM_TEMP_AFFECT;
+
+CLCPaint::CLCPaint()
+{
+ _FillQuickHash();
+};
+
+void CLCPaint::cliPaintClc( HWND hwnd, struct ClcData *dat, HDC hdc, RECT *rcPaint )
+{
+ if ( MirandaExiting()) return;
+ g_CluiData.mutexPaintLock++;
+ g_clcPainter._PaintClc( hwnd, dat, hdc, rcPaint );
+ g_CluiData.mutexPaintLock--;
+}
+
+BOOL CLCPaint::IsForegroundWindow( HWND hWnd )
+{
+ HWND hWindow;
+ hWindow = hWnd;
+ while ( hWindow ) {
+ if ( GetForegroundWindow() == hWindow ) return TRUE;
+ hWindow = GetParent( hWindow );
+ }
+ return FALSE;
+}
+
+HFONT CLCPaint::ChangeToFont( HDC hdc, struct ClcData *dat, int id, int *fontHeight )
+{
+ if ( !dat )
+ dat = ( struct ClcData* )GetWindowLongPtr( pcli->hwndContactTree, 0 );
+
+ if ( !dat )
+ return NULL;
+
+ HFONT res = ( HFONT )SelectObject( hdc, dat->fontModernInfo[id].hFont );
+ SetTextColor( hdc, dat->fontModernInfo[id].colour );
+
+ if ( fontHeight )
+ *fontHeight = dat->fontModernInfo[id].fontHeight;
+ ske_ResetTextEffect( hdc );
+
+ if ( dat->hWnd == pcli->hwndContactTree && dat->fontModernInfo[id].effect != 0 )
+ ske_SelectTextEffect( hdc, dat->fontModernInfo[id].effect-1, dat->fontModernInfo[id].effectColour1, dat->fontModernInfo[id].effectColour2 );
+ else
+ ske_ResetTextEffect( hdc );
+
+ return res;
+}
+
+int CLCPaint::GetBasicFontID( struct ClcContact * contact )
+{
+ PDNCE pdnce = NULL;
+ if ( contact->type == CLCIT_CONTACT )
+ pdnce = ( PDNCE )pcli->pfnGetCacheEntry( contact->hContact );
+
+ switch ( contact->type )
+ {
+ case CLCIT_GROUP:
+ if ( contact->group->expanded )
+ return FONTID_OPENGROUPS;
+ else
+ return FONTID_CLOSEDGROUPS;
+ break;
+ case CLCIT_INFO:
+ if ( contact->flags & CLCIIF_GROUPFONT )
+ return FONTID_OPENGROUPS;
+ else
+ return FONTID_CONTACTS;
+ break;
+ case CLCIT_DIVIDER:
+ return FONTID_DIVIDERS;
+ break;
+ case CLCIT_CONTACT:
+ if ( contact->flags & CONTACTF_NOTONLIST )
+ return FONTID_NOTONLIST;
+ else if (( contact->flags&CONTACTF_INVISTO
+ && _GetRealStatus( contact, ID_STATUS_OFFLINE ) != ID_STATUS_INVISIBLE )
+ ||
+ ( contact->flags&CONTACTF_VISTO
+ && _GetRealStatus( contact, ID_STATUS_OFFLINE ) == ID_STATUS_INVISIBLE ))
+ {
+ // the contact is in the always visible list and the proto is invisible
+ // the contact is in the always invisible and the proto is in any other mode
+ return contact->flags & CONTACTF_ONLINE ? FONTID_INVIS : FONTID_OFFINVIS;
+ }
+ else
+ {
+ switch( pdnce___GetStatus( pdnce ))
+ {
+ case ID_STATUS_OFFLINE: return FONTID_OFFLINE;
+ case ID_STATUS_AWAY: return FONTID_AWAY;
+ case ID_STATUS_DND: return FONTID_DND;
+ case ID_STATUS_NA: return FONTID_NA;
+ case ID_STATUS_OCCUPIED: return FONTID_OCCUPIED;
+ case ID_STATUS_FREECHAT: return FONTID_CHAT;
+ case ID_STATUS_INVISIBLE: return FONTID_INVISIBLE;
+ case ID_STATUS_ONTHEPHONE: return FONTID_PHONE;
+ case ID_STATUS_OUTTOLUNCH: return FONTID_LUNCH;
+ default: return FONTID_CONTACTS;
+ }
+ }
+ break;
+ default:
+ return FONTID_CONTACTS;
+ }
+}
+
+void CLCPaint::GetTextSize( SIZE *text_size, HDC hdcMem, RECT free_row_rc, TCHAR *szText, SortedList *plText, UINT uTextFormat, int smiley_height )
+{
+ if ( szText == NULL || !szText[0] )
+ {
+ text_size->cy = 0;
+ text_size->cx = 0;
+ }
+ else
+ {
+ RECT text_rc = free_row_rc;
+ int free_width;
+ int free_height;
+
+ free_width = text_rc.right - text_rc.left;
+ free_height = text_rc.bottom - text_rc.top;
+
+ // Always need cy...
+ text_size->cy = ske_DrawText( hdcMem, szText, lstrlen( szText ), &text_rc, DT_CALCRECT | uTextFormat );
+ text_size->cy = min( text_size->cy, free_height );
+ if ( plText == NULL )
+ {
+ text_size->cx = min( text_rc.right - text_rc.left + 2, free_width );
+ }
+ else
+ {
+ // See each item of list
+ int i;
+
+ text_size->cy = min( max( text_size->cy, smiley_height ), free_height );
+
+ text_size->cx = 0;
+
+ for ( i=0; i < plText->realCount && text_size->cx < free_width; i++ )
+ {
+ ClcContactTextPiece *piece = ( ClcContactTextPiece * ) plText->items[i];
+
+ if ( piece->type == TEXT_PIECE_TYPE_TEXT )
+ {
+ text_rc = free_row_rc;
+
+ ske_DrawText( hdcMem, &szText[piece->start_pos], piece->len, &text_rc, DT_CALCRECT | uTextFormat );
+ text_size->cx = min( text_size->cx + text_rc.right - text_rc.left + 2, free_width );
+ }
+ else
+ {
+ double factor;
+
+ if ( piece->smiley_height > text_size->cy )
+ {
+ factor = text_size->cy / ( double ) piece->smiley_height;
+ }
+ else
+ {
+ factor = 1;
+ }
+
+ text_size->cx = min( text_size->cx + ( long )( factor * piece->smiley_width ), free_width );
+ }
+ }
+ }
+ }
+}
+
+void CLCPaint::AddParam( MODERNMASK * mpModernMask, DWORD dwParamHash, const char* const szValue, DWORD dwValueHash )
+{
+ static MASKPARAM param = {0}; //AddParameter will clear it so it can be static to avoid initializations
+ _FillParam( &param, dwParamHash, szValue, dwValueHash );
+ _AddParameter( mpModernMask, &param );
+}
+BOOL CLCPaint::CheckMiniMode( struct ClcData *dat, BOOL selected, BOOL hot )
+{
+ if (( !dat->bCompactMode /* not mini*/ )
+ || (( dat->bCompactMode&0x01 ) && selected /*mini on selected*/ )
+ /* || ( TRUE && hot )*/ ) return FALSE;
+ return TRUE;
+}
+
+tPaintCallbackProc CLCPaint::PaintCallbackProc( HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData )
+{
+ struct ClcData* dat = ( struct ClcData* )GetWindowLongPtr( hWnd, 0 );
+ if ( !dat ) return 0;
+ cliPaintClc( hWnd, dat, hDC, rcPaint );
+ return NULL;
+}
+
+void CLCPaint::_FillQuickHash()
+{
+ int i;
+ for ( i=0;i < hi_LastItem;i++ )
+ HASH[i] = mod_CalcHash( HASHTEXT[i] );
+}
+
+void CLCPaint::_SetHotTrackColour( HDC hdc, struct ClcData *dat )
+{
+ if ( dat->gammaCorrection ) {
+ COLORREF oldCol, newCol;
+ int oldLum, newLum;
+
+ oldCol = GetTextColor( hdc );
+ oldLum = ( GetRValue( oldCol )*30+GetGValue( oldCol )*59+GetBValue( oldCol )*11 )/100;
+ newLum = ( GetRValue( dat->hotTextColour )*30+GetGValue( dat->hotTextColour )*59+GetBValue( dat->hotTextColour )*11 )/100;
+ if ( newLum == 0 ) {
+ SetTextColor( hdc, dat->hotTextColour );
+ return;
+ }
+ if ( newLum >= oldLum+20 ) {
+ oldLum += 20;
+ newCol = RGB( GetRValue( dat->hotTextColour )*oldLum/newLum, GetGValue( dat->hotTextColour )*oldLum/newLum, GetBValue( dat->hotTextColour )*oldLum/newLum );
+ }
+ else if ( newLum <= oldLum ) {
+ int r, g, b;
+ r = GetRValue( dat->hotTextColour )*oldLum/newLum;
+ g = GetGValue( dat->hotTextColour )*oldLum/newLum;
+ b = GetBValue( dat->hotTextColour )*oldLum/newLum;
+ if ( r>255 ) {
+ g += ( r-255 )*3/7;
+ b += ( r-255 )*3/7;
+ r = 255;
+ }
+ if ( g>255 ) {
+ r += ( g-255 )*59/41;
+ if ( r>255 ) r = 255;
+ b += ( g-255 )*59/41;
+ g = 255;
+ }
+ if ( b>255 ) {
+ r += ( b-255 )*11/89;
+ if ( r>255 ) r = 255;
+ g += ( b-255 )*11/89;
+ if ( g>255 ) g = 255;
+ b = 255;
+ }
+ newCol = RGB( r, g, b );
+ }
+ else newCol = dat->hotTextColour;
+ SetTextColor( hdc, newCol );
+ }
+ else
+ SetTextColor( hdc, dat->hotTextColour );
+}
+
+int CLCPaint::_GetStatusOnlineness( int status )
+{
+ switch( status )
+ {
+ case ID_STATUS_FREECHAT: return 110;
+ case ID_STATUS_ONLINE: return 100;
+ case ID_STATUS_OCCUPIED: return 60;
+ case ID_STATUS_ONTHEPHONE: return 50;
+ case ID_STATUS_DND: return 40;
+ case ID_STATUS_AWAY: return 30;
+ case ID_STATUS_OUTTOLUNCH: return 20;
+ case ID_STATUS_NA: return 10;
+ case ID_STATUS_INVISIBLE: return 5;
+ }
+ return 0;
+}
+
+int CLCPaint::_GetGeneralisedStatus()
+{
+ int status = ID_STATUS_OFFLINE;
+ int statusOnlineness = 0;
+
+ for ( int i=0; i < pcli->hClcProtoCount; i++ )
+ {
+ int thisStatus = pcli->clcProto[i].dwStatus;
+ if ( thisStatus == ID_STATUS_INVISIBLE )
+ return ID_STATUS_INVISIBLE;
+
+ int thisOnlineness = _GetStatusOnlineness( thisStatus );
+ if ( thisOnlineness > statusOnlineness )
+ {
+ status = thisStatus;
+ statusOnlineness = thisOnlineness;
+ }
+ }
+ return status;
+}
+
+int CLCPaint::_GetRealStatus( struct ClcContact * pContact, int nStatus )
+{
+ if ( !pContact->proto )
+ return nStatus;
+
+ for ( int i=0; i < pcli->hClcProtoCount; i++ )
+ {
+ if ( !lstrcmpA( pcli->clcProto[i].szProto, pContact->proto ))
+ return pcli->clcProto[i].dwStatus;
+ }
+ return nStatus;
+}
+
+
+RECT CLCPaint::_GetRectangle( struct ClcData *dat, RECT *row_rc, RECT *free_row_rc, int *left_pos, int *right_pos, BOOL left, int real_width, int width, int height, int horizontal_space )
+{
+ RECT rc = *free_row_rc;
+ int width_tmp = width;
+ if ( left )
+ {
+ if ( dat->row_align_left_items_to_left )
+ width_tmp = real_width;
+
+ rc.left += ( width_tmp - real_width ) >> 1;
+ rc.right = rc.left + real_width;
+ rc.top += ( rc.bottom - rc.top - height ) >> 1;
+ rc.bottom = rc.top + height;
+ *left_pos += width_tmp + horizontal_space;
+ free_row_rc->left = row_rc->left + *left_pos;
+ }
+ else // if ( !left )
+ {
+ if ( dat->row_align_right_items_to_right )
+ width_tmp = real_width;
+
+ if ( width_tmp > rc.right - rc.left )
+ {
+ rc.left = rc.right + 1;
+ }
+ else
+ {
+ rc.left = max( rc.left + horizontal_space, rc.right - width_tmp ) + (( width_tmp - real_width ) >> 1 );
+ rc.right = min( rc.left + real_width, rc.right );
+ rc.top += max( 0, ( rc.bottom - rc.top - height ) >> 1 );
+ rc.bottom = min( rc.top + height, rc.bottom );
+
+ *right_pos += min( width_tmp + horizontal_space, free_row_rc->right - free_row_rc->left );
+ free_row_rc->right = row_rc->right - *right_pos;
+ }
+ }
+
+ return rc;
+}
+
+
+
+void CLCPaint::_DrawTextSmiley( HDC hdcMem, RECT * free_rc, SIZE * text_size, TCHAR *szText, int len, SortedList *plText, UINT uTextFormat, BOOL ResizeSizeSmiley )
+{
+ if ( szText == NULL )return;
+ uTextFormat &= ~DT_RIGHT;
+ if ( plText == NULL )
+ ske_DrawText( hdcMem, szText, len, free_rc, uTextFormat );
+ else
+ {
+ // Draw list
+ int i;
+ int pos_x = 0;
+ int row_height;
+ RECT tmp_rc = *free_rc;
+ if ( len == -1 ) len = (int)_tcslen( szText );
+ if ( uTextFormat & DT_RTLREADING )
+ i = plText->realCount - 1;
+ else
+ i=0;
+
+ // Get real height of the line
+ row_height = ske_DrawText( hdcMem, _T( "A" ), 1, &tmp_rc, DT_CALCRECT | uTextFormat );
+
+ // Just draw ellipsis
+ if ( free_rc->right <= free_rc->left )
+ {
+ if ( gl_TrimText ) ske_DrawText( hdcMem, _T( "..." ), 3, free_rc, uTextFormat & ~DT_END_ELLIPSIS );
+ }
+ else
+ {
+ // Draw text and smileys
+ for ( ; i < plText->realCount && i >= 0 && pos_x < text_size->cx && len > 0; i += ( uTextFormat & DT_RTLREADING ? -1 : 1 ))
+ {
+ ClcContactTextPiece *piece = ( ClcContactTextPiece * ) plText->items[i];
+ RECT text_rc = *free_rc;
+
+ if ( uTextFormat & DT_RTLREADING )
+ text_rc.right -= pos_x;
+ else
+ text_rc.left += pos_x;
+
+ if ( piece->type == TEXT_PIECE_TYPE_TEXT )
+ {
+ tmp_rc = text_rc;
+ tmp_rc.right += 50;
+ ske_DrawText( hdcMem, &szText[piece->start_pos], min( len, piece->len ), &tmp_rc, DT_CALCRECT | ( uTextFormat & ~DT_END_ELLIPSIS ));
+ pos_x += tmp_rc.right - tmp_rc.left + 2;
+
+ if ( uTextFormat & DT_RTLREADING )
+ text_rc.left = max( text_rc.left, text_rc.right - ( tmp_rc.right - tmp_rc.left ));
+
+ ske_DrawText( hdcMem, &szText[piece->start_pos], min( len, piece->len ), &text_rc, uTextFormat );
+ len -= piece->len;
+ }
+ else
+ {
+ float factor = 0;
+
+ if ( len < piece->len )
+ {
+ len = 0;
+ }
+ else
+ {
+ LONG fac_width, fac_height;
+ len -= piece->len;
+
+ if ( piece->smiley_height > row_height && ResizeSizeSmiley )
+ {
+ factor = row_height / ( float ) piece->smiley_height;
+ }
+ else
+ {
+ factor = 1;
+ }
+
+ fac_width = ( LONG )( piece->smiley_width * factor );
+ fac_height = ( LONG )( piece->smiley_height * factor );
+
+ if ( uTextFormat & DT_RTLREADING )
+ text_rc.left = max( text_rc.right - fac_width, text_rc.left );
+
+ if ( fac_width <= text_rc.right - text_rc.left )
+ {
+ text_rc.top += ( row_height - fac_height ) >> 1;
+
+ ske_DrawIconEx( hdcMem, text_rc.left, text_rc.top, piece->smiley,
+ fac_width, fac_height, 0, NULL, DI_NORMAL|(( factor < 1 )?128:0 )); //TO DO enchance drawing quality
+ }
+ else
+ {
+ ske_DrawText( hdcMem, _T( "..." ), 3, &text_rc, uTextFormat );
+ }
+
+ pos_x += fac_width;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void CLCPaint::_AddParameter( MODERNMASK * mpModernMask, MASKPARAM * lpParam )
+{
+ mpModernMask->pl_Params = ( MASKPARAM * )realloc( mpModernMask->pl_Params, ( mpModernMask->dwParamCnt+1 )*sizeof( MASKPARAM ));
+ memmove( &( mpModernMask->pl_Params[mpModernMask->dwParamCnt] ), lpParam, sizeof( MASKPARAM ));
+ mpModernMask->dwParamCnt++;
+ memset( lpParam, 0, sizeof( MASKPARAM ));
+}
+
+void CLCPaint::_FillParam( MASKPARAM * lpParam, DWORD dwParamHash, const char* const szValue, DWORD dwValueHash )
+{
+ lpParam->bMaskParamFlag = MPF_EQUAL|MPF_HASHED;
+ lpParam->dwId = dwParamHash;
+ if ( !dwValueHash && szValue && szValue[0] ) lpParam->dwValueHash = mod_CalcHash( szValue );
+ else lpParam->dwValueHash = dwValueHash;
+ if ( szValue ) lpParam->szValue = strdupn( szValue, strlen( szValue ));
+ else lpParam->szValue = NULL;
+}
+
+void CLCPaint::_AddParamShort( MODERNMASK * mpModernMask, DWORD dwParamIndex, DWORD dwValueIndex )
+{
+ AddParam( mpModernMask, HASH[dwParamIndex], HASHTEXT[dwValueIndex], HASH[dwValueIndex] );
+}
+
+
+MODERNMASK * CLCPaint::_GetCLCContactRowBackModernMask( struct ClcGroup * group, struct ClcContact * Drawing, int indent, int index, BOOL selected, BOOL hottrack, struct ClcData * dat )
+{
+ MODERNMASK * mpModernMask = NULL;
+ char buf[BUF2SIZE] = {0};
+ mpModernMask = ( MODERNMASK* )mir_calloc( sizeof( MODERNMASK ));
+
+ _AddParamShort( mpModernMask, hi_Module, hi_CL );
+ _AddParamShort( mpModernMask, hi_ID, hi_Row );
+ switch ( Drawing->type )
+ {
+ case CLCIT_GROUP:
+ {
+ _AddParamShort( mpModernMask, hi_Type, hi_Group );
+ _AddParamShort( mpModernMask, hi_Open, ( Drawing && Drawing->group && Drawing->group->expanded )?hi_True:hi_False );
+ _AddParamShort( mpModernMask, hi_IsEmpty, ( Drawing->group->cl.count == 0 )?hi_True:hi_False );
+ }
+ break;
+ case CLCIT_CONTACT:
+ {
+ struct ClcContact * mCont = Drawing;
+ if ( Drawing->isSubcontact )
+ {
+ _AddParamShort( mpModernMask, hi_Type, hi_SubContact );
+ if ( Drawing->isSubcontact == 1 && Drawing->subcontacts->SubAllocated == 1 )
+ _AddParamShort( mpModernMask, hi_SubPos, hi_First_Single );
+ else if ( Drawing->isSubcontact == 1 )
+ _AddParamShort( mpModernMask, hi_SubPos, hi_First );
+ else if ( Drawing->isSubcontact == Drawing->subcontacts->SubAllocated )
+ _AddParamShort( mpModernMask, hi_SubPos, hi_Last );
+ else
+ _AddParamShort( mpModernMask, hi_SubPos, hi_Middle );
+ mCont = Drawing->subcontacts;
+ }
+ else if ( Drawing->SubAllocated )
+ {
+ _AddParamShort( mpModernMask, hi_Type, hi_MetaContact );
+ _AddParamShort( mpModernMask, hi_Open, ( Drawing->SubExpanded )?hi_True:hi_False );
+ }
+ else
+ _AddParamShort( mpModernMask, hi_Type, hi_Contact );
+ AddParam( mpModernMask, HASH[hi_Protocol], Drawing->proto, 0 );
+ _AddParamShort( mpModernMask, hi_RootGroup, ( group && group->parent == NULL )?hi_True:hi_False );
+ switch( GetContactCachedStatus( Drawing->hContact ))
+ {
+ // case ID_STATUS_CONNECTING: AppendChar( buf, BUFSIZE, "CONNECTING" ); break;
+ case ID_STATUS_ONLINE: _AddParamShort( mpModernMask, hi_Status, hi_ONLINE ); break;
+ case ID_STATUS_AWAY: _AddParamShort( mpModernMask, hi_Status, hi_AWAY ); break;
+ case ID_STATUS_DND: _AddParamShort( mpModernMask, hi_Status, hi_DND ); break;
+ case ID_STATUS_NA: _AddParamShort( mpModernMask, hi_Status, hi_NA ); break;
+ case ID_STATUS_OCCUPIED: _AddParamShort( mpModernMask, hi_Status, hi_OCCUPIED ); break;
+ case ID_STATUS_FREECHAT: _AddParamShort( mpModernMask, hi_Status, hi_FREECHAT ); break;
+ case ID_STATUS_INVISIBLE: _AddParamShort( mpModernMask, hi_Status, hi_INVISIBLE ); break;
+ case ID_STATUS_OUTTOLUNCH: _AddParamShort( mpModernMask, hi_Status, hi_OUTTOLUNCH );break;
+ case ID_STATUS_ONTHEPHONE: _AddParamShort( mpModernMask, hi_Status, hi_ONTHEPHONE );break;
+ case ID_STATUS_IDLE: _AddParamShort( mpModernMask, hi_Status, hi_IDLE ); break;
+ default: _AddParamShort( mpModernMask, hi_Status, hi_OFFLINE );
+ }
+ _AddParamShort( mpModernMask, hi_HasAvatar, ( dat->avatars_show && Drawing->avatar_data != NULL )?hi_True:hi_False );
+ _AddParamShort( mpModernMask, hi_Rate, hi_None + Drawing->bContactRate );
+ break;
+ }
+ case CLCIT_DIVIDER:
+ {
+ _AddParamShort( mpModernMask, hi_Type, hi_Divider );
+ }
+ break;
+ case CLCIT_INFO:
+ {
+ _AddParamShort( mpModernMask, hi_Type, hi_Info );
+ }
+ break;
+ }
+ if ( group->scanIndex == 0 && group->cl.count == 1 )
+ _AddParamShort( mpModernMask, hi_GroupPos, hi_First_Single );
+ else if ( group->scanIndex == 0 )
+ _AddParamShort( mpModernMask, hi_GroupPos, hi_First );
+ else if ( group->scanIndex+1 == group->cl.count )
+ _AddParamShort( mpModernMask, hi_GroupPos, hi_Last );
+ else
+ _AddParamShort( mpModernMask, hi_GroupPos, hi_Mid );
+
+ _AddParamShort( mpModernMask, hi_Selected, ( selected )?hi_True:hi_False );
+ _AddParamShort( mpModernMask, hi_Hot, ( hottrack )?hi_True:hi_False );
+ _AddParamShort( mpModernMask, hi_Odd, ( index&1 )?hi_True:hi_False );
+
+ _itoa( indent, buf, BUF2SIZE );
+ AddParam( mpModernMask, HASH[hi_Indent], buf, 0 );
+ _itoa( index, buf, BUF2SIZE );
+ AddParam( mpModernMask, HASH[hi_Index], buf, 0 );
+ {
+ TCHAR * b2 = mir_tstrdup( Drawing->szText );
+ int i, m;
+ m = lstrlen( b2 );
+ for ( i=0; i < m;i++ )
+ if ( b2[i] == _T( ',' )) b2[i] = _T( '.' );
+ {
+ char* b3 = mir_utf8encodeT( b2 );
+ AddParam( mpModernMask, HASH[hi_Name], b3, 0 );
+ mir_free( b3 );
+ }
+
+ mir_free( b2 );
+ }
+ if ( group->parent )
+ {
+ TCHAR * b2 = mir_tstrdup( group->parent->cl.items[0]->szText );
+ int i, m;
+ m = lstrlen( b2 );
+ for ( i=0; i < m;i++ )
+ if ( b2[i] == _T( ',' )) b2[i] = _T( '.' );
+ {
+ char * b3 = mir_utf8encodeT( b2 );
+ AddParam( mpModernMask, HASH[hi_Group], b3, 0 );
+ mir_free( b3 );
+ }
+
+ mir_free( b2 );
+ }
+ return mpModernMask;
+}
+
+
+void CLCPaint::_RTLRect( RECT *rect, int width, int offset )
+{
+ int left, right;
+ if ( !rect ) return;
+ left = ( width )-rect->right;
+ right = ( width )-rect->left;
+ rect->left = left;//-offset;
+ rect->right = right;//-offset;
+ return;
+}
+
+void CLCPaint::_PaintRowItemsEx( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT row_rc, RECT free_row_rc, int left_pos, int right_pos, int selected, int hottrack, RECT *rcPaint )
+{
+ int i=0;
+ int dx = free_row_rc.left;
+ int dy = row_rc.top+dat->row_border;
+ int dg = 0;
+
+
+ // Let calc placeholder
+ int minheight = dat->row_min_heigh;
+ int mode2 = -1;
+ COLORREF colourFg = RGB( 0, 0, 0 );
+ BOOL InClistWindow = ( dat->hWnd == pcli->hwndContactTree );
+ PDNCE pdnce = NULL;
+ int height = RowHeight_CalcRowHeight( dat, hwnd, Drawing, -1 );
+
+ // TO DO DEPRECATE OLD ROW LAYOUT
+
+ if ( Drawing->type == CLCIT_CONTACT )
+ pdnce = ( PDNCE )pcli->pfnGetCacheEntry( Drawing->hContact );
+
+ if ( Drawing->type == CLCIT_GROUP &&
+ Drawing->group->parent->groupId == 0 &&
+ Drawing->group->parent->cl.items[0] != Drawing )
+ {
+ dg = dat->row_before_group_space;
+ free_row_rc.top += dg;
+ height -= dg;
+ }
+ if ( !InClistWindow || !gl_RowRoot || Drawing->type == CLCIT_GROUP )
+ {
+ // to do paint simple
+ RECT fr_rc = free_row_rc;
+
+ //1 draw icon
+ if ( !( Drawing->type == CLCIT_GROUP && InClistWindow && dat->row_hide_group_icon ))
+ {
+ int iImage = -1;
+ // Get image
+ if ( Drawing->type == CLCIT_GROUP )
+ {
+ iImage = Drawing->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT )
+ iImage = Drawing->iImage;
+ if ( iImage != -1 )
+ {
+ COLORREF colourFg;
+ int mode;
+ RECT p_rect = {0};
+ p_rect.top = fr_rc.top+(( fr_rc.bottom-fr_rc.top-ICON_HEIGHT )>>1 );
+ p_rect.left = fr_rc.left;
+ p_rect.right = p_rect.left+ICON_HEIGHT;
+ p_rect.bottom = p_rect.top+ICON_HEIGHT;
+ // Store pos
+ if ( dat->text_rtl != 0 ) _RTLRect( &p_rect, free_row_rc.right, dx );
+ Drawing->pos_icon = p_rect;
+ if ( hottrack )
+ {
+ colourFg = dat->hotTextColour;
+ mode = ILD_NORMAL;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
+ {
+ colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
+ mode = ILD_BLEND50;
+ }
+ else
+ {
+ colourFg = dat->selBkColour;
+ mode = ILD_NORMAL;
+ }
+
+ if ( Drawing->type == CLCIT_CONTACT && dat->showIdle && ( Drawing->flags&CONTACTF_IDLE ) &&
+ _GetRealStatus( Drawing, ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE )
+ {
+ mode = ILD_SELECTED;
+ }
+ _DrawStatusIcon( Drawing, dat, iImage, hdcMem, p_rect.left, p_rect.top, 0, 0, CLR_NONE, colourFg, mode );
+
+ }
+ fr_rc.left += ICON_HEIGHT+2;
+ }
+ //2 draw extra
+ {
+ RECT p_rect = {0};
+ p_rect.top = fr_rc.top+(( fr_rc.bottom-fr_rc.top-ICON_HEIGHT )>>1 );
+ //p_rect.left = fr_rc.left;
+ //p_rect.right = p_rect.left+ICON_HEIGHT;
+ p_rect.bottom = p_rect.top+ICON_HEIGHT;
+
+ if (( Drawing->type == CLCIT_GROUP || Drawing->type == CLCIT_CONTACT || Drawing->type == CLCIT_INFO )
+ && dat->extraColumnsCount > 0 && ( !InClistWindow || Drawing->type == CLCIT_CONTACT ))
+ {
+ int BlendedInActiveState = dat->dbbBlendInActiveState;
+ int BlendValue = dat->dbbBlend25 ? ILD_BLEND25 : ILD_BLEND50;
+ int iImage;
+ int count = 0;
+ RECT rc;
+ int x = 0;
+ for ( iImage = dat->extraColumnsCount-1; iImage >= 0 ; iImage-- )
+ {
+ COLORREF colourFg = dat->selBkColour;
+ int mode = BlendedInActiveState?BlendValue:ILD_NORMAL;
+ if ( Drawing->iExtraImage[iImage] == 0xFF && Drawing->iWideExtraImage[iImage] == 0xFFFF )
+ {
+ {
+ x += ( x>0 )?dat->extraColumnSpacing:ICON_HEIGHT;
+ SetRect( &rc, fr_rc.right-x, p_rect.top, fr_rc.right-x+ICON_HEIGHT, p_rect.bottom );
+ if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, 0 );
+ Drawing->pos_extra[iImage] = rc;
+ count++;
+ }
+ continue;
+ }
+
+ if ( selected ) mode = BlendedInActiveState?ILD_NORMAL:ILD_SELECTED;
+ else if ( hottrack )
+ {
+ mode = BlendedInActiveState?ILD_NORMAL:ILD_FOCUS;
+ colourFg = dat->hotTextColour;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
+ {
+ colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
+ mode = BlendValue;
+ }
+
+ x += ( x>0 )?dat->extraColumnSpacing:ICON_HEIGHT;
+ SetRect( &rc, fr_rc.right-x, p_rect.top, fr_rc.right-x+ICON_HEIGHT, p_rect.bottom );
+ if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, dx );
+ Drawing->pos_extra[iImage] = rc;
+ Drawing->pos_extra[iImage] = rc;
+ if ( Drawing->iExtraImage[iImage] != 0xFF )
+ ske_ImageList_DrawEx( dat->himlExtraColumns, Drawing->iExtraImage[iImage], hdcMem,
+ rc.left, rc.top, 0, 0, CLR_NONE, colourFg, mode );
+ else if ( Drawing->iWideExtraImage[iImage] != 0xFFFF )
+ ske_ImageList_DrawEx( dat->himlWideExtraColumns, Drawing->iWideExtraImage[iImage], hdcMem,
+ rc.left, rc.top, 0, 0, CLR_NONE, colourFg, mode );
+
+ }
+ fr_rc.right -= x;
+ }
+ }
+ //3 draw text
+ {
+ SIZE text_size = {0};
+ char * szCounts = NULL;
+ RECT text_rect = fr_rc;
+ RECT counts_rc = {0};
+ UINT uTextFormat = DT_LEFT|DT_VCENTER|( gl_TrimText?DT_END_ELLIPSIS:0 )|DT_SINGLELINE;
+ uTextFormat |= dat->text_rtl?DT_RTLREADING:0;
+ // Select font
+ ChangeToFont( hdcMem, dat, GetBasicFontID( Drawing ), NULL );
+
+ // Get text size
+ GetTextSize( &text_size, hdcMem, fr_rc, Drawing->szText, Drawing->ssText.plText, uTextFormat,
+ dat->text_resize_smileys ? 0 : Drawing->ssText.iMaxSmileyHeight );
+ // counters
+ if ( Drawing->type == CLCIT_GROUP && InClistWindow )
+ {
+ RECT nameRect = fr_rc;
+ RECT countRect = {0};
+ RECT count_rc = {0};
+ SIZE count_size = {0};
+ int space_width = 0;
+ char * szCounts = pcli->pfnGetGroupCountsText( dat, Drawing );
+ // Has to draw the count?
+ if ( szCounts && strlen( szCounts )>0 )
+ {
+ // calc width and height
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ ske_DrawText( hdcMem, _T( " " ), 1, &count_rc, DT_CALCRECT | DT_NOPREFIX );
+ count_size.cx = count_rc.right-count_rc.left;
+ space_width = count_size.cx;
+ count_rc.right = 0;
+ count_rc.left = 0;
+ ske_DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &count_rc, DT_CALCRECT );
+ count_size.cx += count_rc.right-count_rc.left;
+ count_size.cy = count_rc.bottom-count_rc.top;
+ }
+ // modify text rect
+ //if ( !RTL )
+ {
+ SIZE text_size = {0};
+ int wid = fr_rc.right-fr_rc.left;
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPS:FONTID_CLOSEDGROUPS, NULL );
+ GetTextSize( &text_size, hdcMem, fr_rc, Drawing->szText, Drawing->ssText.plText, 0, dat->text_resize_smileys ? 0 : Drawing->ssText.iMaxSmileyHeight );
+
+ if ( wid-count_size.cx > text_size.cx )
+ {
+
+ if ( dat->row_align_group_mode != 2 ) //center or left
+ {
+ int x = ( dat->row_align_group_mode == 1 )?( wid-( text_size.cx+count_size.cx ))>>1:0;
+ nameRect.left += x;
+ nameRect.right = nameRect.left+text_size.cx;
+ countRect.left = nameRect.right+space_width;
+ countRect.right = countRect.left+count_size.cx-space_width;
+ }
+ else
+ {
+ countRect.right = nameRect.right;
+ countRect.left = countRect.right-(( count_size.cx>0 )?( count_size.cx-space_width ):0 );
+ nameRect.right = countRect.left-(( count_size.cx>0 )?space_width:0 );
+ nameRect.left = nameRect.right-text_size.cx;
+ }
+
+ }
+
+ else
+ {
+ countRect.right = nameRect.right;
+ nameRect.right -= count_size.cx;
+ countRect.left = nameRect.right+space_width;
+ }
+ countRect.bottom = nameRect.bottom;
+ countRect.top = nameRect.top;
+ }
+
+
+
+ //if ( !( szCounts && strlen( szCounts )>0 ))
+ //uTextFormat |= ( dat->row_align_group_mode == 2 )?DT_RIGHT:( dat->row_align_group_mode == 1 )?DT_CENTER:DT_LEFT;
+
+ uTextFormat |= DT_VCENTER;
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPS:FONTID_CLOSEDGROUPS, NULL );
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ if ( dat->text_rtl != 0 ) _RTLRect( &nameRect, free_row_rc.right, dx );
+ _DrawTextSmiley( hdcMem, &nameRect, &text_size, Drawing->szText, lstrlen( Drawing->szText ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ if ( selected && dat->szQuickSearch[0] != '\0' )
+ {
+ SetTextColor( hdcMem, dat->quickSearchColour );
+ _DrawTextSmiley( hdcMem, &nameRect, &text_size, Drawing->szText, lstrlen( dat->szQuickSearch ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ }
+ if ( szCounts && strlen( szCounts )>0 )
+ {
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ if ( dat->text_rtl != 0 ) _RTLRect( &countRect, free_row_rc.right, dx );
+ ske_DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &countRect, uTextFormat );
+ }
+ {
+ RECT rc = fr_rc;
+ if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, dx );
+ Drawing->pos_rename_rect = rc;
+ }
+ Drawing->pos_label = nameRect;
+ return;
+ }
+ else if ( Drawing->type == CLCIT_GROUP )
+ {
+
+ szCounts = pcli->pfnGetGroupCountsText( dat, Drawing );
+ // Has to draw the count?
+ if ( szCounts && szCounts[0] )
+ {
+ RECT space_rc = fr_rc;
+
+ int text_width = 0;
+ SIZE space_size = {0};
+ SIZE counts_size = {0};
+ // Get widths
+ counts_rc = fr_rc;
+ DrawText( hdcMem, _T( " " ), 1, &space_rc, DT_CALCRECT | DT_NOPREFIX );
+
+ space_size.cx = space_rc.right - space_rc.left;
+ space_size.cy = min( space_rc.bottom - space_rc.top, fr_rc.bottom-fr_rc.top );
+
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &counts_rc, DT_CALCRECT );
+
+ counts_size.cx = counts_rc.right - counts_rc.left;
+ counts_size.cy = min( counts_rc.bottom - counts_rc.top, fr_rc.bottom-fr_rc.top );
+
+ text_width = fr_rc.right - fr_rc.left - space_size.cx - counts_size.cx;
+
+ if ( text_width > 4 )
+ {
+ text_size.cx = min( text_width, text_size.cx );
+ text_width = text_size.cx + space_size.cx + counts_size.cx;
+ }
+ else
+ {
+ text_width = text_size.cx;
+ space_size.cx = 0;
+ counts_size.cx = 0;
+ }
+ text_rect.right = text_rect.left+text_size.cx;
+ counts_rc = text_rect;
+ counts_rc.left = text_rect.right+space_size.cx;
+ counts_rc.right = counts_rc.left+counts_size.cx;
+ }
+ }
+ ChangeToFont( hdcMem, dat, GetBasicFontID( Drawing ), NULL );
+
+ // Set color
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ if ( dat->text_rtl != 0 ) _RTLRect( &text_rect, free_row_rc.right, dx );
+ _DrawTextSmiley( hdcMem, &text_rect, &text_size, Drawing->szText, lstrlen( Drawing->szText ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ if ( selected && dat->szQuickSearch[0] != '\0' )
+ {
+ SetTextColor( hdcMem, dat->quickSearchColour );
+ _DrawTextSmiley( hdcMem, &text_rect, &text_size, Drawing->szText, lstrlen( dat->szQuickSearch ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ }
+ if ( Drawing->type == CLCIT_GROUP && szCounts && szCounts[0] && counts_rc.right-counts_rc.left>0 )
+ {
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ if ( dat->text_rtl != 0 ) _RTLRect( &counts_rc, free_row_rc.right, dx );
+ if ( InClistWindow && g_CluiData.fLayered )
+ ske_DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &counts_rc, uTextFormat );
+ else
+ //88
+ ske_DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &counts_rc, uTextFormat );
+ if ( dat->text_rtl == 0 )
+ text_rect.right = counts_rc.right;
+ else
+ text_rect.left = counts_rc.left;
+ }
+ Drawing->pos_label = text_rect;
+ {
+ RECT rc = fr_rc;
+ if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, dx );
+ Drawing->pos_rename_rect = rc;
+ }
+
+ if (( !InClistWindow || !g_CluiData.fLayered ) && (( Drawing->type == CLCIT_DIVIDER ) || ( Drawing->type == CLCIT_GROUP && dat->exStyle&CLS_EX_LINEWITHGROUPS )))
+ {
+ //???
+ RECT rc = fr_rc;
+ if ( dat->text_rtl != 0 )
+ {
+ rc.left = Drawing->pos_rename_rect.left;
+ rc.right = text_rect.left-3;
+ }
+ else
+ rc.left = text_rect.right+3;
+ if ( rc.right-rc.left>4 )
+ {
+ rc.top += (( rc.bottom-rc.top )>>1 )-1;
+ rc.bottom = rc.top+2;
+ DrawEdge( hdcMem, &rc, BDR_SUNKENOUTER, BF_RECT );
+ ske_SetRectOpaque( hdcMem, &rc );
+ }
+ }
+
+ }
+ return;
+ }
+ minheight = max( minheight, height );
+ dy += ( minheight>height )?(( minheight-height )>>1 ):0;
+ // Call Placement
+ cppCalculateRowItemsPos( gl_RowRoot, free_row_rc.right-free_row_rc.left );
+ // Now paint
+ while (( gl_RowTabAccess[i] != NULL || ( i < 2 && Drawing->type == CLCIT_GROUP )) && !( i >= 2 && Drawing->type == CLCIT_GROUP ))
+ {
+
+ if ( gl_RowTabAccess[i]->r.right-gl_RowTabAccess[i]->r.left>0
+ && gl_RowTabAccess[i]->r.bottom-gl_RowTabAccess[i]->r.top>0 )
+ {
+ RECT p_rect = gl_RowTabAccess[i]->r;
+ OffsetRect( &p_rect, dx, dy );
+ if ( dat->text_rtl != 0 && gl_RowTabAccess[i]->type != TC_EXTRA /*each extra icon modified separately*/ ) _RTLRect( &p_rect, free_row_rc.right, 0 );
+ switch ( gl_RowTabAccess[i]->type )
+ {
+ case TC_TEXT1:
+ {
+ //paint text 1
+ SIZE text_size;
+ UINT uTextFormat = ( dat->text_rtl ? DT_RTLREADING : 0 ) ;
+ text_size.cx = p_rect.right-p_rect.left;
+ text_size.cy = p_rect.bottom-p_rect.top;
+ ChangeToFont( hdcMem, dat, GetBasicFontID( Drawing ), NULL );
+
+ uTextFormat |= ( gl_RowTabAccess[i]->valign == TC_VCENTER )?DT_VCENTER:( gl_RowTabAccess[i]->valign == TC_BOTTOM )?DT_BOTTOM:0;
+ uTextFormat |= ( gl_RowTabAccess[i]->halign == TC_HCENTER )?DT_CENTER:( gl_RowTabAccess[i]->halign == TC_RIGHT )?DT_RIGHT:0;
+
+ uTextFormat = uTextFormat | ( gl_TrimText?DT_END_ELLIPSIS:0 )|DT_SINGLELINE;
+ if ( Drawing->type == CLCIT_CONTACT )
+ {
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ _DrawTextSmiley( hdcMem, &p_rect, &text_size, Drawing->szText, lstrlen( Drawing->szText ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ if ( selected && dat->szQuickSearch[0] != '\0' )
+ {
+ SetTextColor( hdcMem, dat->quickSearchColour );
+ _DrawTextSmiley( hdcMem, &p_rect, &text_size, Drawing->szText, lstrlen( dat->szQuickSearch ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ }
+ Drawing->pos_rename_rect = p_rect;
+ {
+ SIZE size;
+ GetTextSize( &size, hdcMem, p_rect, Drawing->szText, Drawing->ssText.plText, 0, dat->text_resize_smileys ? 0 : Drawing->ssText.iMaxSmileyHeight );
+ Drawing->pos_label = p_rect;
+ Drawing->pos_label.right = min( Drawing->pos_label.right, Drawing->pos_label.left+size.cx );
+ }
+
+ }
+ else if ( Drawing->type == CLCIT_GROUP )
+ {
+ RECT nameRect = p_rect;
+ RECT countRect = {0};
+ RECT count_rc = {0};
+ SIZE count_size = {0};
+ int space_width = 0;
+ char * szCounts = pcli->pfnGetGroupCountsText( dat, Drawing );
+ // Has to draw the count?
+ if ( szCounts && strlen( szCounts )>0 )
+ {
+
+
+ // calc width and height
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ ske_DrawText( hdcMem, _T( " " ), 1, &count_rc, DT_CALCRECT | DT_NOPREFIX );
+ count_size.cx = count_rc.right-count_rc.left;
+ space_width = count_size.cx;
+ count_rc.right = 0;
+ count_rc.left = 0;
+ ske_DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &count_rc, DT_CALCRECT );
+ count_size.cx += count_rc.right-count_rc.left;
+ count_size.cy = count_rc.bottom-count_rc.top;
+ }
+ // modify text rect
+ //if ( !RTL )
+ {
+ SIZE text_size = {0};
+ int wid = p_rect.right-p_rect.left;
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPS:FONTID_CLOSEDGROUPS, NULL );
+ GetTextSize( &text_size, hdcMem, p_rect, Drawing->szText, Drawing->ssText.plText, 0, dat->text_resize_smileys ? 0 : Drawing->ssText.iMaxSmileyHeight );
+
+ if ( wid-count_size.cx > text_size.cx )
+ {
+
+ if ( dat->row_align_group_mode != 2 ) //center or left
+ {
+ int x = ( dat->row_align_group_mode == 1 )?( wid-( text_size.cx+count_size.cx ))>>1:0;
+ nameRect.left += x;
+ nameRect.right = nameRect.left+text_size.cx;
+ countRect.left = nameRect.right+space_width;
+ countRect.right = countRect.left+count_size.cx-space_width;
+ }
+ else
+ {
+ countRect.right = nameRect.right;
+ countRect.left = countRect.right-(( count_size.cx>0 )?( count_size.cx-space_width ):0 );
+ nameRect.right = countRect.left-(( count_size.cx>0 )?space_width:0 );
+ nameRect.left = nameRect.right-text_size.cx;
+ }
+
+ }
+
+ else
+ {
+ countRect.right = nameRect.right;
+ nameRect.right -= count_size.cx;
+ countRect.left = nameRect.right+space_width;
+ }
+ countRect.bottom = nameRect.bottom;
+ countRect.top = nameRect.top;
+ }
+
+
+
+ //if ( !( szCounts && strlen( szCounts )>0 ))
+ //uTextFormat |= ( dat->row_align_group_mode == 2 )?DT_RIGHT:( dat->row_align_group_mode == 1 )?DT_CENTER:DT_LEFT;
+
+ uTextFormat |= DT_VCENTER;
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPS:FONTID_CLOSEDGROUPS, NULL );
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ _DrawTextSmiley( hdcMem, &nameRect, &text_size, Drawing->szText, lstrlen( Drawing->szText ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ if ( selected && dat->szQuickSearch[0] != '\0' )
+ {
+ SetTextColor( hdcMem, dat->quickSearchColour );
+ _DrawTextSmiley( hdcMem, &nameRect, &text_size, Drawing->szText, lstrlen( dat->szQuickSearch ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ }
+ if ( szCounts && strlen( szCounts )>0 )
+ {
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ ske_DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &countRect, uTextFormat );
+ }
+ Drawing->pos_rename_rect = p_rect;
+ Drawing->pos_label = nameRect;
+ }
+ break;
+ }
+ case TC_TEXT2:
+ {
+ // paint text 2
+ //
+ // Select font
+ SIZE text_size;
+ UINT uTextFormat = ( dat->text_rtl ? DT_RTLREADING : 0 ) ;
+ {
+ if ( dat->second_line_show && dat->second_line_type == TEXT_CONTACT_TIME && pdnce->hTimeZone )
+ {
+ // Get contact time
+ TCHAR buf[70] = _T("");
+ mir_free_and_nil( pdnce->szSecondLineText );
+
+ tmi.printDateTime(pdnce->hTimeZone, _T("t"), buf, SIZEOF(buf), 0);
+ pdnce->szSecondLineText = mir_tstrdup( buf );
+ }
+ }
+ uTextFormat |= ( gl_RowTabAccess[i]->valign == TC_VCENTER )?DT_VCENTER:( gl_RowTabAccess[i]->valign == TC_BOTTOM )?DT_BOTTOM:0;
+ uTextFormat |= ( gl_RowTabAccess[i]->halign == TC_HCENTER )?DT_CENTER:( gl_RowTabAccess[i]->halign == TC_RIGHT )?DT_RIGHT:0;
+
+ text_size.cx = p_rect.right-p_rect.left;
+ text_size.cy = p_rect.bottom-p_rect.top;
+
+ ChangeToFont( hdcMem, dat, FONTID_SECONDLINE, NULL );
+ uTextFormat = uTextFormat | ( gl_TrimText?DT_END_ELLIPSIS:0 )|DT_SINGLELINE;
+ if ( Drawing->type == CLCIT_CONTACT )
+ _DrawTextSmiley( hdcMem, &p_rect, &text_size, pdnce->szSecondLineText, lstrlen( pdnce->szSecondLineText ), pdnce->ssSecondLine.plText, uTextFormat, dat->text_resize_smileys );
+ break;
+ }
+ case TC_TEXT3:
+ {
+ //paint text 3
+ // Select font
+ SIZE text_size;
+ UINT uTextFormat = ( dat->text_rtl ? DT_RTLREADING : 0 ) ;
+ {
+ if ( dat->third_line_show && dat->third_line_type == TEXT_CONTACT_TIME && pdnce->hTimeZone )
+ {
+ // Get contact time
+ TCHAR buf[70] = _T("");
+ mir_free( pdnce->szThirdLineText );
+
+ tmi.printDateTime(pdnce->hTimeZone, _T("t"), buf, SIZEOF(buf), 0);
+ pdnce->szThirdLineText = mir_tstrdup( buf );
+ }
+ }
+ uTextFormat |= ( gl_RowTabAccess[i]->valign == TC_VCENTER )?DT_VCENTER:( gl_RowTabAccess[i]->valign == TC_BOTTOM )?DT_BOTTOM:0;
+ uTextFormat |= ( gl_RowTabAccess[i]->halign == TC_HCENTER )?DT_CENTER:( gl_RowTabAccess[i]->halign == TC_RIGHT )?DT_RIGHT:0;
+
+ text_size.cx = p_rect.right-p_rect.left;
+ text_size.cy = p_rect.bottom-p_rect.top;
+
+ ChangeToFont( hdcMem, dat, FONTID_THIRDLINE, NULL );
+ uTextFormat = uTextFormat | ( gl_TrimText?DT_END_ELLIPSIS:0 )|DT_SINGLELINE;
+ if ( Drawing->type == CLCIT_CONTACT )
+ _DrawTextSmiley( hdcMem, &p_rect, &text_size, pdnce->szThirdLineText, lstrlen( pdnce->szThirdLineText ), pdnce->ssThirdLine.plText, uTextFormat, dat->text_resize_smileys );
+ break;
+ }
+ case TC_STATUS:
+ {
+
+ if (( Drawing->type == CLCIT_GROUP && !dat->row_hide_group_icon )
+ || ( Drawing->type == CLCIT_CONTACT && Drawing->iImage != -1
+ && !( dat->icon_hide_on_avatar && dat->avatars_show
+ && (( dat->use_avatar_service && Drawing->avatar_data != NULL ) ||
+ ( !dat->use_avatar_service && Drawing->avatar_pos != AVATAR_POS_DONT_HAVE )
+ )
+ && !Drawing->image_is_special )))
+ {
+ int iImage = -1;
+ // Get image
+ if ( Drawing->type == CLCIT_GROUP )
+ {
+ if ( !dat->row_hide_group_icon ) iImage = Drawing->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT;
+ else iImage = -1;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT )
+ iImage = Drawing->iImage;
+ if ( iImage != -1 )
+ {
+ COLORREF colourFg;
+ int mode;
+ // Store pos
+ Drawing->pos_icon = p_rect;
+ if ( hottrack )
+ {
+ colourFg = dat->hotTextColour;
+ mode = ILD_NORMAL;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
+ {
+ colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
+ mode = ILD_BLEND50;
+ }
+ else
+ {
+ colourFg = dat->selBkColour;
+ mode = ILD_NORMAL;
+ }
+
+ if ( Drawing->type == CLCIT_CONTACT && dat->showIdle && ( Drawing->flags&CONTACTF_IDLE ) &&
+ _GetRealStatus( Drawing, ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE )
+ {
+ mode = ILD_SELECTED;
+ }
+
+ _DrawStatusIcon( Drawing, dat, iImage, hdcMem, p_rect.left, p_rect.top, 0, 0, CLR_NONE, colourFg, mode );
+
+ }
+ }
+
+ break;
+ }
+ case TC_AVATAR:
+ {
+ BOOL hasAvatar = ( dat->use_avatar_service && Drawing->avatar_data != NULL ) || ( !dat->use_avatar_service && Drawing->avatar_pos != AVATAR_POS_DONT_HAVE );
+ BYTE blendmode = 255;
+ if ( hottrack )
+ blendmode = 255;
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
+ blendmode = 128;
+ if ( Drawing->type == CLCIT_CONTACT && dat->showIdle && ( Drawing->flags&CONTACTF_IDLE ) &&
+ _GetRealStatus( Drawing, ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE )
+ blendmode = 128;
+ if ( !hasAvatar ) //if no avatar then paint icon image
+ {
+ int iImage = Drawing->iImage;
+ if ( iImage != -1 )
+ {
+ COLORREF colourFg;
+ int mode;
+ // Store pos
+ Drawing->pos_icon = p_rect;
+ if ( hottrack )
+ {
+ colourFg = dat->hotTextColour;
+ mode = ILD_NORMAL;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
+ {
+ colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
+ mode = ILD_BLEND50;
+ }
+ else
+ {
+ colourFg = dat->selBkColour;
+ mode = ILD_NORMAL;
+ }
+
+ if ( Drawing->type == CLCIT_CONTACT && dat->showIdle && ( Drawing->flags&CONTACTF_IDLE ) &&
+ _GetRealStatus( Drawing, ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE )
+ {
+ mode = ILD_SELECTED;
+ }
+
+ _DrawStatusIcon( Drawing, dat, iImage, hdcMem, p_rect.left, p_rect.top, 0, 0, CLR_NONE, colourFg, mode );
+
+ }
+ }
+ else
+ {
+ HRGN rgn = NULL;
+ HRGN oldrgn;
+ int round_radius = 0;
+ int width = p_rect.right-p_rect.left;
+ int height = p_rect.bottom-p_rect.top;
+ // Store pos
+ Drawing->pos_avatar = p_rect;
+ oldrgn = CreateRectRgn( 0, 0, 0, 0 );
+ GetClipRgn( hdcMem, oldrgn );
+
+ // Round corners
+ if ( dat->avatars_round_corners )
+ {
+ if ( dat->avatars_use_custom_corner_size )
+ round_radius = dat->avatars_custom_corner_size;
+ else
+ round_radius = min( width, height ) / 5;
+ }
+ else
+ {
+ round_radius = 0;
+ }
+ if ( dat->avatars_draw_border )
+ {
+ HBRUSH hBrush = CreateSolidBrush( dat->avatars_border_color );
+ HBRUSH hOldBrush = ( HBRUSH )SelectObject( hdcMem, hBrush );
+ HRGN rgn2;
+ rgn = CreateRoundRectRgn( p_rect.left, p_rect.top, p_rect.right+1, p_rect.bottom+1, round_radius << 1, round_radius << 1 );
+ rgn2 = CreateRoundRectRgn( p_rect.left+1, p_rect.top+1, p_rect.right, p_rect.bottom, round_radius << 1, round_radius << 1 );
+ CombineRgn( rgn2, rgn, rgn2, RGN_DIFF );
+ // FrameRgn( hdcMem, rgn, hBrush, 1, 1 );
+ FillRgn( hdcMem, rgn2, hBrush );
+ ske_SetRgnOpaque( hdcMem, rgn2 );
+ SelectObject( hdcMem, hOldBrush );
+ DeleteObject( hBrush );
+ DeleteObject( rgn );
+ DeleteObject( rgn2 );
+ }
+ if ( dat->avatars_round_corners || dat->avatars_draw_border )
+ {
+ int k = dat->avatars_draw_border?1:0;
+ rgn = CreateRoundRectRgn( p_rect.left+k, p_rect.top+k, p_rect.right+1-k, p_rect.bottom+1-k, round_radius * 2, round_radius * 2 );
+ ExtSelectClipRgn( hdcMem, rgn, RGN_AND );
+ }
+
+ // Draw avatar
+ if ( dat->use_avatar_service )
+ /*if ( ServiceExists( MS_AV_BLENDDRAWAVATAR ))
+ {
+ AVATARDRAWREQUEST adr;
+
+ adr.cbSize = sizeof( AVATARDRAWREQUEST );
+ adr.hContact = Drawing->hContact;
+ adr.hTargetDC = hdcMem;
+ adr.rcDraw = p_rect;
+ adr.dwFlags = ( dat->avatars_draw_border ? AVDRQ_DRAWBORDER : 0 ) |
+ ( dat->avatars_round_corners ? AVDRQ_ROUNDEDCORNER : 0 ) |
+ AVDRQ_HIDEBORDERONTRANSPARENCY;
+ adr.clrBorder = dat->avatars_border_color;
+ adr.radius = round_radius;
+ adr.alpha = blendmode;
+
+ CallService( MS_AV_DRAWAVATAR, 0, ( LPARAM ) &adr );
+ }
+ else
+ */
+ {
+ int w = width;
+ int h = height;
+ if ( !g_CluiData.fGDIPlusFail ) //Use gdi+ engine
+ {
+ DrawAvatarImageWithGDIp( hdcMem, p_rect.left, p_rect.top, w, h, Drawing->avatar_data->hbmPic, 0, 0, Drawing->avatar_data->bmWidth, Drawing->avatar_data->bmHeight, Drawing->avatar_data->dwFlags, blendmode );
+ }
+ else
+ {
+ if ( !( Drawing->avatar_data->dwFlags&AVS_PREMULTIPLIED ))
+ {
+ HDC hdcTmp = CreateCompatibleDC( hdcMem );
+ RECT r = {0, 0, w, h};
+ HDC hdcTmp2 = CreateCompatibleDC( hdcMem );
+ HBITMAP bmo = ( HBITMAP )SelectObject( hdcTmp, Drawing->avatar_data->hbmPic );
+ HBITMAP b2 = ske_CreateDIB32( w, h );
+ HBITMAP bmo2 = ( HBITMAP )SelectObject( hdcTmp2, b2 );
+ SetStretchBltMode( hdcTmp, HALFTONE );
+ SetStretchBltMode( hdcTmp2, HALFTONE );
+ StretchBlt( hdcTmp2, 0, 0, w, h,
+ hdcTmp, 0, 0, Drawing->avatar_data->bmWidth, Drawing->avatar_data->bmHeight,
+ SRCCOPY );
+
+ ske_SetRectOpaque( hdcTmp2, &r );
+ BitBlt( hdcMem, p_rect.left, p_rect.top, w, h, hdcTmp2, 0, 0, SRCCOPY );
+ SelectObject( hdcTmp2, bmo2 );
+ SelectObject( hdcTmp, bmo );
+ mod_DeleteDC( hdcTmp );
+ mod_DeleteDC( hdcTmp2 );
+ DeleteObject( b2 );
+ }
+ else {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, blendmode, AC_SRC_ALPHA };
+ HDC hdcTempAv = CreateCompatibleDC( hdcMem );
+ HBITMAP hbmTempAvOld;
+ hbmTempAvOld = ( HBITMAP )SelectObject( hdcTempAv, Drawing->avatar_data->hbmPic );
+ ske_AlphaBlend( hdcMem, p_rect.left, p_rect.top, w, h, hdcTempAv, 0, 0, Drawing->avatar_data->bmWidth, Drawing->avatar_data->bmHeight, bf );
+ SelectObject( hdcTempAv, hbmTempAvOld );
+ mod_DeleteDC( hdcTempAv );
+ }
+ }
+ }
+ else
+ {
+ ImageArray_DrawImage( &dat->avatar_cache, Drawing->avatar_pos, hdcMem, p_rect.left, p_rect.top, 255 );
+ }
+ // Restore region
+ if ( dat->avatars_round_corners || dat->avatars_draw_border )
+ {
+ DeleteObject( rgn );
+ }
+ SelectClipRgn( hdcMem, oldrgn );
+ DeleteObject( oldrgn );
+
+
+ // Draw borders
+
+ //TODO fix overlays
+ // Draw overlay
+ if ( dat->avatars_draw_overlay && dat->avatars_maxheight_size >= ICON_HEIGHT + ( dat->avatars_draw_border ? 2 : 0 )
+ && GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE < MAX_REGS( g_pAvatarOverlayIcons ))
+ {
+ p_rect.top = p_rect.bottom - ICON_HEIGHT;
+ p_rect.left = p_rect.right - ICON_HEIGHT;
+
+ if ( dat->avatars_draw_border )
+ {
+ p_rect.top--;
+ p_rect.left--;
+ }
+
+ switch( dat->avatars_overlay_type )
+ {
+ case SETTING_AVATAR_OVERLAY_TYPE_NORMAL:
+ {
+ UINT a = blendmode;
+ a = ( a << 24 );
+ ske_ImageList_DrawEx( hAvatarOverlays, g_pAvatarOverlayIcons[GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE].listID,
+ hdcMem,
+ p_rect.left, p_rect.top, ICON_HEIGHT, ICON_HEIGHT,
+ CLR_NONE, CLR_NONE,
+ ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
+
+ //ske_DrawIconEx( hdcMem, p_rect.left, p_rect.top, g_pAvatarOverlayIcons[GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE].icon,
+ // ICON_HEIGHT, ICON_HEIGHT, 0, NULL, DI_NORMAL|a );
+ break;
+ }
+ case SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL:
+ {
+ int item;
+
+ item = ExtIconFromStatusMode( Drawing->hContact, Drawing->proto,
+ Drawing->proto == NULL ? ID_STATUS_OFFLINE : GetContactCachedStatus( Drawing->hContact ));
+ if ( item != -1 )
+ _DrawStatusIcon( Drawing, dat, item, hdcMem,
+ p_rect.left, p_rect.top, ICON_HEIGHT, ICON_HEIGHT,
+ CLR_NONE, CLR_NONE, ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
+ break;
+ }
+ case SETTING_AVATAR_OVERLAY_TYPE_CONTACT:
+ {
+ if ( Drawing->iImage != -1 )
+ _DrawStatusIcon( Drawing, dat, Drawing->iImage, hdcMem,
+ p_rect.left, p_rect.top, ICON_HEIGHT, ICON_HEIGHT,
+ CLR_NONE, CLR_NONE, ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
+ break;
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ case TC_EXTRA:
+ {
+
+ if ( Drawing->type == CLCIT_CONTACT &&
+ ( !Drawing->isSubcontact || dat->dbbMetaHideExtra == 0 && dat->extraColumnsCount > 0 ))
+ {
+ int BlendedInActiveState = dat->dbbBlendInActiveState;
+ int BlendValue = dat->dbbBlend25 ? ILD_BLEND25 : ILD_BLEND50;
+ int iImage;
+ int count = 0;
+ RECT rc;
+ int x = 0;
+ for ( iImage = 0; iImage < dat->extraColumnsCount ; iImage++ )
+ {
+ COLORREF colourFg = dat->selBkColour;
+ int mode = BlendedInActiveState?BlendValue:ILD_NORMAL;
+ if ( Drawing->iExtraImage[iImage] == 0xFF && Drawing->iWideExtraImage[iImage] == 0xFFFF )
+ {
+ if ( !dat->MetaIgnoreEmptyExtra )
+ {
+ SetRect( &rc, p_rect.left+x, p_rect.top, p_rect.left+x+ICON_HEIGHT, p_rect.bottom );
+ x += dat->extraColumnSpacing;
+ if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, 0 );
+ Drawing->pos_extra[iImage] = rc;
+ count++;
+ }
+ continue;
+ }
+
+ if ( selected ) mode = BlendedInActiveState?ILD_NORMAL:ILD_SELECTED;
+ else if ( hottrack )
+ {
+ mode = BlendedInActiveState?ILD_NORMAL:ILD_FOCUS;
+ colourFg = dat->hotTextColour;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
+ {
+ colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
+ mode = BlendValue;
+ }
+
+ SetRect( &rc, p_rect.left+x, p_rect.top, p_rect.left+x+ICON_HEIGHT, p_rect.bottom );
+ x += dat->extraColumnSpacing;
+ count++;
+ if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, 0 );
+ Drawing->pos_extra[iImage] = rc;
+ if ( Drawing->iExtraImage[iImage] != 0xFF )
+ ske_ImageList_DrawEx( dat->himlExtraColumns, Drawing->iExtraImage[iImage], hdcMem,
+ rc.left, rc.top, 0, 0, CLR_NONE, colourFg, mode );
+ else if ( Drawing->iWideExtraImage[iImage] != 0xFFFF )
+ ske_ImageList_DrawEx( dat->himlWideExtraColumns, Drawing->iWideExtraImage[iImage], hdcMem,
+ rc.left, rc.top, 0, 0, CLR_NONE, colourFg, mode );
+ }
+ }
+ break;
+ }
+ case TC_EXTRA1:
+ case TC_EXTRA2:
+ case TC_EXTRA3:
+ case TC_EXTRA4:
+ case TC_EXTRA5:
+ case TC_EXTRA6:
+ case TC_EXTRA7:
+ case TC_EXTRA8:
+ case TC_EXTRA9:
+ {
+ if ( Drawing->type == CLCIT_CONTACT &&
+ ( !Drawing->isSubcontact || dat->dbbMetaHideExtra == 0 && dat->extraColumnsCount > 0 ))
+ {
+ int eNum = gl_RowTabAccess[i]->type-TC_EXTRA1;
+ if ( eNum < dat->extraColumnsCount )
+ if ( Drawing->iExtraImage[eNum] != 0xFF || Drawing->iWideExtraImage[eNum] != 0xFFFF )
+ {
+ int mode = 0;
+ int BlendedInActiveState = dat->dbbBlendInActiveState;
+ int BlendValue = dat->dbbBlend25 ? ILD_BLEND25 : ILD_BLEND50;
+ if ( mode2 != -1 ) mode = mode2;
+ else
+ {
+ if ( selected ) mode = BlendedInActiveState?ILD_NORMAL:ILD_SELECTED;
+ else if ( hottrack )
+ {
+ mode = BlendedInActiveState?ILD_NORMAL:ILD_FOCUS;
+ colourFg = dat->hotTextColour;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST )
+ {
+ colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
+ mode = BlendValue;
+ }
+ mode2 = mode;
+ }
+ if ( dat->text_rtl != 0 ) _RTLRect( &p_rect, free_row_rc.right, 0 );
+ Drawing->pos_extra[eNum] = p_rect;
+ if ( Drawing->iExtraImage[eNum] != 0xFF )
+ ske_ImageList_DrawEx( dat->himlExtraColumns, Drawing->iExtraImage[eNum], hdcMem,
+ p_rect.left, p_rect.top, 0, 0, CLR_NONE, colourFg, mode );
+ else if ( Drawing->iWideExtraImage[eNum] != 0xFFFF )
+ ske_ImageList_DrawEx( dat->himlWideExtraColumns, Drawing->iWideExtraImage[eNum], hdcMem,
+ p_rect.left, p_rect.top, 0, 0, CLR_NONE, colourFg, mode );
+ }
+ }
+ }
+ case TC_TIME:
+ {
+ TCHAR szResult[80];
+
+ if ( !tmi.printDateTime(pdnce->hTimeZone, _T("t"), szResult, SIZEOF(szResult), 0))
+ {
+ // Select font
+ ChangeToFont( hdcMem, dat, FONTID_CONTACT_TIME, NULL );
+ ske_DrawText( hdcMem, szResult, lstrlen( szResult ), &p_rect, DT_NOPREFIX | DT_SINGLELINE|( dat->text_rtl ? DT_RTLREADING : 0 ));
+ }
+ break;
+ }
+ }
+ }
+ i++;
+ }
+ return;
+}
+
+
+
+
+void CLCPaint::_DrawStatusIcon( struct ClcContact * Drawing, struct ClcData *dat, int iImage, HDC hdcMem, int x, int y, int cx, int cy, DWORD colorbg, DWORD colorfg, int mode )
+{
+ if ( Drawing->type != CLCIT_CONTACT )
+ {
+ ske_ImageList_DrawEx( g_himlCListClc, LOWORD( iImage ), hdcMem,
+ x, y, cx, cy, colorbg, colorfg, mode );
+ }
+ else if ( Drawing->image_is_special )
+ {
+ ske_ImageList_DrawEx( g_himlCListClc, LOWORD( iImage ), hdcMem,
+ x, y, cx, cy, colorbg, colorfg, mode );
+ }
+ else if ( iImage != -1 && HIWORD( iImage ) && dat->drawOverlayedStatus )
+ {
+ int status = GetContactCachedStatus( Drawing->hContact );
+ if ( status < ID_STATUS_OFFLINE ) status = ID_STATUS_OFFLINE;
+ else if ( status>ID_STATUS_OUTTOLUNCH ) status = ID_STATUS_ONLINE;
+ ske_ImageList_DrawEx( g_himlCListClc, HIWORD( iImage ), hdcMem,
+ x, y, cx, cy, colorbg, colorfg, mode );
+ if ( dat->drawOverlayedStatus&2 ) //draw overlay
+ ske_ImageList_DrawEx( hAvatarOverlays, g_pStatusOverlayIcons[status-ID_STATUS_OFFLINE].listID, hdcMem,
+ x, y, cx, cy, colorbg, colorfg, mode );
+ }
+ else
+ {
+ ske_ImageList_DrawEx( g_himlCListClc, LOWORD( iImage ), hdcMem,
+ x, y, cx, cy, colorbg, colorfg, mode );
+ }
+}
+
+BOOL CLCPaint::_DrawNonEnginedBackground( HWND hwnd, HDC hdcMem, RECT * rcPaint, RECT clRect, struct ClcData * dat )
+{
+ if ( dat->hBmpBackground )
+ {
+ BITMAP bmp;
+ HBITMAP oldbm;
+ HDC hdcBmp;
+ int x, y;
+ int maxx, maxy;
+ int destw, desth;
+
+ // XXX: Halftone isnt supported on 9x, however the scretch problems dont happen on 98.
+ SetStretchBltMode( hdcMem, HALFTONE );
+
+
+ GetObject( dat->hBmpBackground, sizeof( bmp ), &bmp );
+ hdcBmp = CreateCompatibleDC( hdcMem );
+ oldbm = ( HBITMAP )SelectObject( hdcBmp, dat->hBmpBackground );
+ y = dat->backgroundBmpUse&CLBF_SCROLL?-dat->yScroll:0;
+ maxx = dat->backgroundBmpUse&CLBF_TILEH?clRect.right:1;
+ maxy = dat->backgroundBmpUse&CLBF_TILEV?maxy = rcPaint->bottom:y+1;
+ switch( dat->backgroundBmpUse&CLBM_TYPE ) {
+ case CLB_STRETCH:
+ if ( dat->backgroundBmpUse&CLBF_PROPORTIONAL ) {
+ if ( clRect.right*bmp.bmHeight < clRect.bottom*bmp.bmWidth ) {
+ desth = clRect.bottom;
+ destw = desth*bmp.bmWidth/bmp.bmHeight;
+ }
+ else {
+ destw = clRect.right;
+ desth = destw*bmp.bmHeight/bmp.bmWidth;
+ }
+ }
+ else {
+ destw = clRect.right;
+ desth = clRect.bottom;
+ }
+ break;
+ case CLB_STRETCHH:
+ if ( dat->backgroundBmpUse&CLBF_PROPORTIONAL ) {
+ destw = clRect.right;
+ desth = destw*bmp.bmHeight/bmp.bmWidth;
+ }
+ else {
+ destw = clRect.right;
+ desth = bmp.bmHeight;
+ if ( dat->backgroundBmpUse&CLBF_TILEVTOROWHEIGHT )
+ {
+ desth = dat->row_min_heigh;
+ }
+
+ }
+ break;
+ case CLB_STRETCHV:
+ if ( dat->backgroundBmpUse&CLBF_PROPORTIONAL ) {
+ desth = clRect.bottom;
+ destw = desth*bmp.bmWidth/bmp.bmHeight;
+ }
+ else {
+ destw = bmp.bmWidth;
+ desth = clRect.bottom;
+ }
+ break;
+ default: //clb_topleft
+ destw = bmp.bmWidth;
+ desth = bmp.bmHeight;
+ if ( dat->backgroundBmpUse&CLBF_TILEVTOROWHEIGHT )
+ {
+ desth = dat->row_min_heigh;
+ }
+ break;
+ }
+ for ( ;y < maxy;y += desth ) {
+ if ( y < rcPaint->top-desth ) continue;
+ for ( x = 0;x < maxx;x += destw )
+ StretchBlt( hdcMem, x, y, destw, desth, hdcBmp, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY );
+ }
+ SelectObject( hdcBmp, oldbm );
+ DeleteDC( hdcBmp );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+int CLCPaint::_DetermineDrawMode( HWND hWnd, struct ClcData *dat )
+{
+ int paintMode = DM_LAYERED; // by default
+
+ if ( dat->force_in_dialog )
+ paintMode = DM_CONTROL;
+ else if ( g_CluiData.fDisableSkinEngine )
+ paintMode = DM_CLASSIC;
+ else if ( !g_CluiData.fLayered )
+ paintMode = DM_NON_LAYERED;
+
+ if ( !(paintMode&DM_CONTROL) && !CLUI_IsInMainWindow( hWnd ))
+ paintMode |= DM_FLOAT;
+
+ LONG lStyle = GetWindowLongPtr( hWnd, GWL_STYLE );
+ int nStatus = _GetGeneralisedStatus();
+ if (( lStyle & WS_DISABLED )
+ || ( dat->greyoutFlags & pcli->pfnClcStatusToPf2( nStatus ))
+ || (( dat->greyoutFlags & GREYF_UNFOCUS) && ( GetFocus() != hWnd )))
+ paintMode |= DM_GRAY;
+
+ if ( lStyle&CLS_GREYALTERNATE )
+ paintMode |= DM_GREYALTERNATE;
+
+ return paintMode;
+}
+
+void CLCPaint::_PreparePaintContext( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT& clRect, _PaintContext& pc )
+{
+ if ( paintMode&DM_GRAY && !(paintMode&DM_LAYERED))
+ {
+ pc.hdcMem2 = CreateCompatibleDC( hdc );
+ if ( paintMode&DM_CLASSIC )
+ pc.hBmpOsb2 = CreateBitmap( clRect.right, clRect.bottom, 1, GetDeviceCaps( hdc, BITSPIXEL ), NULL );
+ else
+ pc.hBmpOsb2 = ske_CreateDIB32( clRect.right, clRect.bottom );
+ pc.oldbmp2 = (HBITMAP) SelectObject( pc.hdcMem2, pc.hBmpOsb2 );
+ pc.fRelease |= _PaintContext::release_hdcmem2;
+ }
+
+ if ( paintMode&( DM_DRAW_OFFSCREEN | DM_GRAY ) )
+ {
+ pc.hdcMem = CreateCompatibleDC( hdc );
+ pc.fRelease |= _PaintContext::release_hdcmem;
+ pc.hBmpOsb = ske_CreateDIB32( clRect.right, clRect.bottom );
+ pc.oldbmp = ( HBITMAP ) SelectObject( pc.hdcMem, pc.hBmpOsb );
+ }
+
+ if ( paintMode&DM_CONTROL && !dat->bkChanged )
+ {
+ pc.tmpbkcolour = GetSysColor( COLOR_3DFACE );
+ pc.tmpforecolour = GetSysColor( COLOR_BTNTEXT );
+ }
+ else
+ {
+ pc.tmpbkcolour = (!(paintMode&DM_CONTROL) && dat->bkChanged ) ? dat->bkColour : ( !dat->useWindowsColours ? dat->bkColour : GetSysColor( COLOR_3DFACE ));
+ pc.tmpforecolour = /*(paintMode&DM_CONTROL) ? */dat->fontModernInfo[FONTID_CONTACTS].colour;
+ }
+
+ if ( paintMode&DM_GREYALTERNATE )
+ {
+ int rDelta = ( GetRValue( pc.tmpbkcolour ) > GetRValue( pc.tmpforecolour )) ? -10 : 10;
+ int gDelta = ( GetGValue( pc.tmpbkcolour ) > GetGValue( pc.tmpforecolour )) ? -10 : 10;
+ int bDelta = ( GetBValue( pc.tmpbkcolour ) > GetBValue( pc.tmpforecolour )) ? -10 : 10;
+ int rValue = GetRValue( pc.tmpbkcolour ) + rDelta;
+ int gValue = GetRValue( pc.tmpbkcolour ) + gDelta;
+ int bValue = GetRValue( pc.tmpbkcolour ) + bDelta;
+
+ BYTE brValue = ( rValue >255) ? 255 : rValue < 0 ? 0 : (BYTE)rValue;
+ BYTE bgValue = ( gValue >255) ? 255 : gValue < 0 ? 0 : (BYTE)gValue;
+ BYTE bbValue = ( bValue >255) ? 255 : bValue < 0 ? 0 : (BYTE)bValue;
+
+ pc.hBrushAlternateGrey = CreateSolidBrush( GetNearestColor( pc.hdcMem, RGB( brValue, bgValue, bbValue )));
+ }
+
+ // Set some draw states
+ SetBkMode( pc.hdcMem, TRANSPARENT );
+ SetStretchBltMode( pc.hdcMem, HALFTONE );
+
+ POINT org;
+ GetBrushOrgEx( pc.hdcMem, &org );
+ SetBrushOrgEx( pc.hdcMem, org.x, org.y, NULL );
+}
+
+void CLCPaint::_DrawBackground( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT * rcPaint, RECT& clRect, _PaintContext& pc )
+{
+ if (paintMode & (DM_FLOAT | DM_CONTROL)) {
+ HBRUSH hBrush = CreateSolidBrush( pc.tmpbkcolour );
+ FillRect( pc.hdcMem, rcPaint, hBrush );
+ DeleteObject( hBrush );
+ ske_SetRectOpaque( pc.hdcMem, rcPaint );
+ if ( !( paintMode & DM_GREYALTERNATE))
+ SkinDrawGlyph( pc.hdcMem, &clRect, rcPaint, "CL,ID=Background,Type=Control" );
+ }
+ else if ( paintMode&DM_CLASSIC) {
+ if ( !_DrawNonEnginedBackground( hWnd, pc.hdcMem, rcPaint, clRect, dat )) {
+ HBRUSH hBrush = CreateSolidBrush( pc.tmpbkcolour );
+ FillRect( pc.hdcMem, rcPaint, hBrush );
+ DeleteObject( hBrush );
+ }
+ }
+ else {
+ if ( paintMode&DM_NON_LAYERED )
+ ske_BltBackImage( hWnd, (paintMode&DM_GRAY) ? pc.hdcMem2 : pc.hdcMem, rcPaint );
+
+ SkinDrawGlyph(pc.hdcMem, &clRect, rcPaint, "CL,ID=Background");
+ }
+}
+
+void CLCPaint::_DrawLines( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT* rcPaint, RECT& clRect, _PaintContext& pc )
+{
+ struct ClcContact *Drawing;
+ struct ClcGroup *group = &dat->list;
+ group->scanIndex = 0;
+ int indent = 0;
+ int subident = 0;
+ int subindex = -1;
+ int line_num = -1;
+ int y = -dat->yScroll;
+ BOOL is_foreground = IsForegroundWindow( hWnd );
+ LONG lStyle = GetWindowLongPtr( hWnd, GWL_STYLE );
+
+ while( y < rcPaint->bottom )
+ {
+ if ( subindex == -1 )
+ {
+ if ( group->scanIndex >= group->cl.count )
+ {
+ group = group->parent;
+ indent--;
+ if ( group == NULL ) break; // Finished list
+ group->scanIndex++;
+ continue;
+ }
+ }
+
+ line_num++;
+
+ // Draw line, if needed
+ if ( y > rcPaint->top - dat->row_heights[line_num] )
+ {
+ int selected;
+ int hottrack;
+ int left_pos;
+ int right_pos;
+ int free_row_height;
+ RECT row_rc;
+ RECT free_row_rc;
+ MODERNMASK * mpRequest = NULL;
+ RECT rc;
+
+ // Get item to draw
+ if ( group->scanIndex < group->cl.count )
+ {
+ if ( subindex == -1 ) {
+ Drawing = group->cl.items[group->scanIndex];
+ subident = 0;
+ }
+ else {
+ Drawing = &( group->cl.items[group->scanIndex]->subcontacts[subindex] );
+ subident = dat->subIndent;
+ }
+ }
+ else Drawing = NULL;
+
+ // Something to draw?
+ if ( Drawing ) {
+
+ // Calc row height
+ if ( !gl_RowRoot )
+ RowHeights_GetRowHeight( dat, hWnd, Drawing, line_num );
+ else
+ RowHeight_CalcRowHeight( dat, hWnd, Drawing, line_num );
+
+ // Init settings
+ selected = (( line_num == dat->selection ) && ( dat->hwndRenameEdit != NULL || dat->showSelAlways || dat->exStyle&CLS_EX_SHOWSELALWAYS || is_foreground ) && Drawing->type != CLCIT_DIVIDER );
+ hottrack = dat->exStyle&CLS_EX_TRACKSELECT && Drawing->type != CLCIT_DIVIDER && dat->iHotTrack == line_num;
+ left_pos = clRect.left + dat->leftMargin + indent * dat->groupIndent + subident;
+ right_pos = dat->rightMargin; // Border
+
+ SetRect( &row_rc, clRect.left, y, clRect.right, y + dat->row_heights[line_num] );
+ free_row_rc = row_rc;
+ free_row_rc.left += left_pos;
+ free_row_rc.right -= right_pos;
+ free_row_rc.top += dat->row_border;
+ free_row_rc.bottom -= dat->row_border;
+ free_row_height = free_row_rc.bottom - free_row_rc.top;
+
+ {
+ HRGN rgn = CreateRectRgn( row_rc.left, row_rc.top, row_rc.right, row_rc.bottom );
+ SelectClipRgn( pc.hdcMem, rgn );
+ DeleteObject( rgn );
+ }
+
+ // Store pos
+ Drawing->pos_indent = free_row_rc.left;
+ ZeroMemory( &Drawing->pos_check, sizeof( Drawing->pos_check ));
+ ZeroMemory( &Drawing->pos_avatar, sizeof( Drawing->pos_avatar ));
+ ZeroMemory( &Drawing->pos_icon, sizeof( Drawing->pos_icon ));
+ ZeroMemory( &Drawing->pos_label, sizeof( Drawing->pos_label ));
+ ZeroMemory( &Drawing->pos_rename_rect, sizeof( Drawing->pos_rename_rect ));
+ ZeroMemory( &Drawing->pos_extra, sizeof( Drawing->pos_extra ));
+
+
+ //**** Draw Background
+
+ // Alternating grey
+ if ( paintMode&DM_GREYALTERNATE && line_num&1 )
+ {
+ if ( paintMode&DM_CONTROL || dat->bkChanged )
+ {
+ FillRect( pc.hdcMem, &row_rc, pc.hBrushAlternateGrey );
+ }
+ else
+ SkinDrawGlyph( pc.hdcMem, &row_rc, rcPaint, "CL,ID=GreyAlternate" );
+ }
+ if ( ! (paintMode&(DM_CLASSIC|DM_CONTROL)))
+ {
+ // Row background
+ if ( !(paintMode&DM_CONTROL))
+ { //Build mpRequest string
+ mpRequest = _GetCLCContactRowBackModernMask( group, Drawing, indent, line_num, selected, hottrack, dat );
+ {
+ RECT mrc = row_rc;
+ if ( group->parent == 0
+ && group->scanIndex != 0
+ && group->scanIndex < group->cl.count
+ && group->cl.items[group->scanIndex]->type == CLCIT_GROUP )
+ {
+ mrc.top += dat->row_before_group_space;
+ }
+ SkinDrawGlyphMask( pc.hdcMem, &mrc, rcPaint, mpRequest );
+ }
+ }
+ if ( selected || hottrack )
+ {
+ RECT mrc = row_rc;
+ if ( Drawing->type == CLCIT_GROUP &&
+ Drawing->group->parent->groupId == 0 &&
+ Drawing->group->parent->cl.items[0] != Drawing )
+ {
+ mrc.top += dat->row_before_group_space;
+ }
+ // Selection background ( only if hole line - full/less )
+ if ( dat->HiLightMode == 1 ) // Full or default
+ {
+ if ( selected )
+ SkinDrawGlyph( pc.hdcMem, &mrc, rcPaint, "CL,ID=Selection" );
+ if ( hottrack )
+ SkinDrawGlyph( pc.hdcMem, &mrc, rcPaint, "CL,ID=HotTracking" );
+ }
+ else if ( dat->HiLightMode == 2 ) // Less
+ {
+ if ( selected )
+ SkinDrawGlyph( pc.hdcMem, &mrc, rcPaint, "CL,ID=Selection" ); //instead of free_row_rc
+ if ( hottrack )
+ SkinDrawGlyph( pc.hdcMem, &mrc, rcPaint, "CL,ID=HotTracking" );
+ }
+ }
+
+ }
+ else
+ {
+ int checkboxWidth;
+ if (( lStyle&CLS_CHECKBOXES && Drawing->type == CLCIT_CONTACT ) ||
+ ( lStyle&CLS_GROUPCHECKBOXES && Drawing->type == CLCIT_GROUP ) ||
+ ( Drawing->type == CLCIT_INFO && Drawing->flags&CLCIIF_CHECKBOX ))
+ checkboxWidth = dat->checkboxSize+2;
+ else checkboxWidth = 0;
+ //background
+ if ( selected ) {
+ switch ( dat->HiLightMode )
+ {
+ case 0:
+ case 1:
+ {
+ int i = y;
+ int row_height = row_rc.bottom-row_rc.top;
+ for ( i = y; i < y+row_height; i += max( dat->row_min_heigh, 1 ))
+ {
+ ImageList_DrawEx( dat->himlHighlight, 0, pc.hdcMem, 0, i, clRect.right,
+ min( y+row_height-i, max( dat->row_min_heigh, 1 )), CLR_NONE, CLR_NONE,
+ dat->exStyle&CLS_EX_NOTRANSLUCENTSEL?ILD_NORMAL:ILD_BLEND25 );
+ }
+ SetTextColor( pc.hdcMem, paintMode&DM_CONTROL ? GetSysColor( COLOR_HIGHLIGHTTEXT ) : dat->selTextColour );
+ break;
+ }
+
+ case 2:
+ {
+ int i;
+ int row_height = row_rc.bottom-row_rc.top-1;
+ for ( i = y+1; i < y+row_height; i += max( dat->row_min_heigh, 1 ))
+ {
+ ImageList_DrawEx( dat->himlHighlight, 0, pc.hdcMem, 1, i, clRect.right-2,
+ min( y+row_height-i, max( dat->row_min_heigh, 1 )), CLR_NONE, CLR_NONE,
+ dat->exStyle&CLS_EX_NOTRANSLUCENTSEL?ILD_NORMAL:ILD_BLEND25 );
+ }
+ SetTextColor( pc.hdcMem, paintMode&DM_CONTROL ? GetSysColor( COLOR_HIGHLIGHTTEXT ) : dat->selTextColour );
+ break;
+ }
+ }
+ }
+
+ }
+ //**** Checkboxes
+ if (( lStyle&CLS_CHECKBOXES && Drawing->type == CLCIT_CONTACT ) ||
+ ( lStyle&CLS_GROUPCHECKBOXES && Drawing->type == CLCIT_GROUP ) ||
+ ( Drawing->type == CLCIT_INFO && Drawing->flags&CLCIIF_CHECKBOX ))
+ {
+ //RECT rc;
+ rc = free_row_rc;
+ rc.right = rc.left + dat->checkboxSize;
+ rc.top += ( rc.bottom - rc.top - dat->checkboxSize ) >> 1;
+ rc.bottom = rc.top + dat->checkboxSize;
+
+ if ( dat->text_rtl != 0 ) _RTLRect( &rc, free_row_rc.right, 0 );
+
+ if ( xpt_IsThemed( dat->hCheckBoxTheme )) {
+ xpt_DrawThemeBackground( dat->hCheckBoxTheme, pc.hdcMem, BP_CHECKBOX, Drawing->flags&CONTACTF_CHECKED?( hottrack?CBS_CHECKEDHOT:CBS_CHECKEDNORMAL ):( hottrack?CBS_UNCHECKEDHOT:CBS_UNCHECKEDNORMAL ), &rc, &rc );
+ }
+ else DrawFrameControl( pc.hdcMem, &rc, DFC_BUTTON, DFCS_BUTTONCHECK|DFCS_FLAT|( Drawing->flags&CONTACTF_CHECKED?DFCS_CHECKED:0 )|( hottrack?DFCS_HOT:0 ));
+
+ left_pos += dat->checkboxSize + EXTRA_CHECKBOX_SPACE + HORIZONTAL_SPACE;
+ free_row_rc.left = row_rc.left + left_pos;
+
+ // Store pos
+ Drawing->pos_check = rc;
+ }
+ _PaintRowItems( hWnd, pc.hdcMem, dat, Drawing, row_rc, free_row_rc, left_pos, right_pos, selected, hottrack, rcPaint );
+ if ( mpRequest && !dat->force_in_dialog )
+ {
+ if ( mpRequest->pl_Params[1].szValue )
+ free( mpRequest->pl_Params[1].szValue );
+ mpRequest->pl_Params[1].szValue = strdupn( "Ovl", 3 );
+ mpRequest->pl_Params[1].dwValueHash = mod_CalcHash( "Ovl" );
+ {
+ RECT mrc = row_rc;
+ if ( Drawing->type == CLCIT_GROUP &&
+ Drawing->group->parent->groupId == 0 &&
+ Drawing->group->parent->cl.items[0] != Drawing )
+ {
+ mrc.top += dat->row_before_group_space;
+ }
+ SkinDrawGlyphMask( pc.hdcMem, &mrc, rcPaint, mpRequest );
+ }
+ SkinSelector_DeleteMask( mpRequest );
+ mir_free( mpRequest );
+ }
+ }
+ }
+ y += dat->row_heights[line_num];
+ //increment by subcontacts
+ if (( group->cl.items && group->scanIndex < group->cl.count && group->cl.items[group->scanIndex]->subcontacts != NULL && group->cl.items[group->scanIndex]->type != CLCIT_GROUP )
+ && ( group->cl.items[group->scanIndex]->SubExpanded && dat->expandMeta ))
+ {
+ if ( subindex < group->cl.items[group->scanIndex]->SubAllocated-1 )
+ subindex++;
+ else
+ subindex = -1;
+ }
+
+ if ( subindex == -1 && group->scanIndex < group->cl.count )
+ {
+ if ( group->cl.items[group->scanIndex]->type == CLCIT_GROUP && group->cl.items[group->scanIndex]->group->expanded )
+ {
+ group = group->cl.items[group->scanIndex]->group;
+ indent++;
+ group->scanIndex = 0;
+ subindex = -1;
+ continue;
+ }
+ group->scanIndex++;
+ }
+ else if ( group->scanIndex >= group->cl.count )
+ {
+ subindex = -1;
+ }
+ }
+ SelectClipRgn( pc.hdcMem, NULL );
+}
+
+
+void CLCPaint::_DrawInsertionMark( struct ClcData * dat, RECT& clRect, _PaintContext& pc )
+{
+ HBRUSH hBrush, hoBrush;
+ POINT pts[8];
+ HRGN hRgn;
+ int identation = dat->nInsertionLevel*dat->groupIndent;
+ int yt = cliGetRowTopY( dat, dat->iInsertionMark );
+
+ pts[0].y = yt - dat->yScroll - 4;
+ if ( pts[0].y < -3 ) pts[0].y = -3;
+ pts[0].x = 1+identation*( dat->text_rtl?0:1 );
+
+ pts[1].x = pts[0].x+2;
+ pts[1].y = pts[0].y+3;
+
+ pts[2].x = clRect.right-identation*( dat->text_rtl?1:0 )-4;
+ pts[2].y = pts[1].y;
+
+ pts[3].x = clRect.right-1-identation*( dat->text_rtl?1:0 );
+ pts[3].y = pts[0].y-1;
+
+ pts[4].x = pts[3].x; pts[4].y = pts[0].y+7;
+ pts[5].x = pts[2].x+1; pts[5].y = pts[1].y+2;
+ pts[6].x = pts[1].x; pts[6].y = pts[5].y;
+ pts[7].x = pts[0].x; pts[7].y = pts[4].y;
+ hRgn = CreatePolygonRgn( pts, sizeof( pts )/sizeof( pts[0] ), ALTERNATE );
+ hBrush = CreateSolidBrush( dat->fontModernInfo[FONTID_CONTACTS].colour );
+ hoBrush = ( HBRUSH )SelectObject( pc.hdcMem, hBrush );
+ FillRgn( pc.hdcMem, hRgn, hBrush );
+ ske_SetRgnOpaque( pc.hdcMem, hRgn );
+ SelectObject( pc.hdcMem, hoBrush );
+ DeleteObject( hBrush );
+}
+
+void CLCPaint::_CopyPaintToDest( HWND hWnd, struct ClcData * dat, HDC hdc, int paintMode, RECT* rcPaint, RECT& clRect, _PaintContext& pc )
+{
+ if ( !( paintMode&DM_GRAY ) && ( paintMode & DM_DRAW_OFFSCREEN ))
+ {
+ BitBlt( hdc, rcPaint->left, rcPaint->top, rcPaint->right-rcPaint->left, rcPaint->bottom-rcPaint->top, pc.hdcMem, rcPaint->left, rcPaint->top, SRCCOPY );
+ }
+
+ if (( paintMode&DM_GRAY ) && hdc && hdc != pc.hdcMem )
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 80, AC_SRC_ALPHA };
+ BOOL a = (( paintMode&DM_GRAY ) && (( paintMode&DM_NON_LAYERED)));
+ ske_AlphaBlend( a ? pc.hdcMem2 : hdc, rcPaint->left, rcPaint->top, rcPaint->right-rcPaint->left, rcPaint->bottom-rcPaint->top, pc.hdcMem, rcPaint->left, rcPaint->top, rcPaint->right-rcPaint->left, rcPaint->bottom-rcPaint->top, bf );
+ if ( a )
+ BitBlt( hdc, rcPaint->left, rcPaint->top, rcPaint->right-rcPaint->left, rcPaint->bottom-rcPaint->top, pc.hdcMem2, rcPaint->left, rcPaint->top, SRCCOPY );
+ }
+}
+void CLCPaint::_FreePaintContext( _PaintContext& pc )
+{
+ if ( pc.hBrushAlternateGrey ) DeleteObject( pc.hBrushAlternateGrey );
+ SelectObject( pc.hdcMem, (HFONT) GetStockObject( DEFAULT_GUI_FONT ));
+ if ( pc.fRelease&_PaintContext::release_hdcmem )
+ {
+ SelectObject( pc.hdcMem, pc.oldbmp );
+ DeleteObject( pc.hBmpOsb );
+ DeleteDC( pc.hdcMem );
+ }
+ if ( pc.fRelease&_PaintContext::release_hdcmem2)
+ {
+ SelectObject( pc.hdcMem2, pc.oldbmp2 );
+ DeleteObject( pc.hBmpOsb2 );
+ DeleteDC( pc.hdcMem2 );
+ }
+}
+void CLCPaint::_PaintClc( HWND hwnd, struct ClcData *dat, HDC hdc, RECT *_rcPaint )
+{
+ g_CluiData.t_now = time( NULL );
+
+ if ( _rcPaint && IsRectEmpty( _rcPaint )) return; // check if draw area is not empty
+ if ( !IsWindowVisible( hwnd )) return; // and window is visible
+
+ RECT clRect;
+ GetClientRect( hwnd, &clRect );
+
+ RECT * rcPaint = _rcPaint ? _rcPaint : &clRect; // if null is transmitted - use whole client area
+
+ // Invalidate ani avatars, avatars have to be validated in row paint routine below
+ if ( rcPaint->top == 0 && rcPaint->bottom == clRect.bottom && dat->avatars_show )
+ AniAva_InvalidateAvatarPositions( NULL );
+
+ // Now determine paint mode
+ int paintMode = _DetermineDrawMode( hwnd, dat );
+
+ // Preparing drawing contexts
+ _PaintContext pc( hdc );
+ _PreparePaintContext( hwnd, dat, hdc, paintMode, clRect, pc );
+
+ // Draw background
+ _DrawBackground( hwnd, dat, hdc, paintMode, rcPaint, clRect, pc );
+ // Draw lines
+ if ( dat->row_heights )
+ _DrawLines( hwnd, dat, hdc, paintMode, rcPaint, clRect, pc );
+
+ //insertion mark
+ if ( dat->iInsertionMark != -1 )
+ _DrawInsertionMark( dat, clRect, pc );
+
+ // BitBlt from memory to destination
+ _CopyPaintToDest( hwnd, dat, hdc, paintMode, rcPaint, clRect, pc );
+
+ // Free
+ _FreePaintContext( pc );
+
+ // all still non-validated animated avatars have to be removed
+ AniAva_RemoveInvalidatedAvatars();
+
+}
+
+void CLCPaint::_StoreItemPos( struct ClcContact *contact, int ItemType, RECT * rc )
+{
+ contact->ext_mpItemsDesc[contact->ext_nItemsNum].itemType = ItemType;
+ contact->ext_mpItemsDesc[contact->ext_nItemsNum].itemRect = *rc;
+ contact->ext_nItemsNum++;
+ switch ( ItemType )
+ {
+ case CIT_AVATAR:
+ contact->pos_avatar = *rc;
+ break;
+ case CIT_ICON:
+ contact->pos_icon = *rc;
+ break;
+ case CIT_TIME:
+ contact->pos_contact_time = *rc;
+ break;
+ case CIT_TEXT:
+ // RECT pos_label;//TODO label ( CIT_TEXT??? )
+ // RECT pos_rename; //TODO ( CIT_TEXT??? )
+ break;
+ case CIT_CHECKBOX:
+ break;
+ default:
+ if (( ItemType&CIT_EXTRA ) == CIT_EXTRA )
+ {
+ int iImage = ItemType&0x3F;
+ contact->pos_extra[iImage] = *rc;
+ }
+ break;
+ }
+}
+
+
+void CLCPaint::_CalcItemsPos( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *in_row_rc, RECT *in_free_row_rc, int left_pos, int right_pos, int selected, int hottrack )
+{
+ int item_iterator, item, item_text, text_left_pos;
+ BOOL left = TRUE; //TODO remove
+ RECT free_row_rc = *in_free_row_rc;
+ RECT row_rc = *in_row_rc;
+ Drawing->ext_nItemsNum = 0;
+ text_left_pos = row_rc.right;
+ // Now let's check what we have to draw
+ for ( item_iterator = 0 ; item_iterator < NUM_ITEM_TYPE && free_row_rc.left < free_row_rc.right ; item_iterator++ )
+ {
+ if ( Drawing->ext_nItemsNum >= SIZEOF( Drawing->ext_mpItemsDesc )) break;
+ if ( left )
+ item = item_iterator;
+ else
+ item = NUM_ITEM_TYPE - ( item_iterator - item_text );
+
+ switch( dat->row_items[item] )
+ {
+ case ITEM_AVATAR: ///////////////////////////////////////////////////////////////////////////////////////////////////
+ {
+ RECT rc;
+ int max_width;
+ int width;
+ int height;
+ BOOL miniMode;
+ if ( !dat->avatars_show || Drawing->type != CLCIT_CONTACT )
+ break;
+ miniMode = CheckMiniMode( dat, selected, hottrack );
+ AniAva_InvalidateAvatarPositions( Drawing->hContact );
+ if ( dat->icon_hide_on_avatar && dat->icon_draw_on_avatar_space )
+ max_width = max( dat->iconXSpace, dat->avatars_maxheight_size );
+ else
+ max_width = dat->avatars_maxheight_size;
+
+ // Has to draw?
+ if (( dat->use_avatar_service && Drawing->avatar_data == NULL )
+ || ( !dat->use_avatar_service && Drawing->avatar_pos == AVATAR_POS_DONT_HAVE )
+ || miniMode )
+ {
+ // Don't have to draw avatar
+
+ // Has to draw icon instead?
+ if ( dat->icon_hide_on_avatar && dat->icon_draw_on_avatar_space && Drawing->iImage != -1 )
+ {
+ RECT rc;
+
+ // Make rectangle
+ rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
+ left, dat->iconXSpace, max_width, ICON_HEIGHT, HORIZONTAL_SPACE );
+
+ if ( rc.left < rc.right )
+ {
+ /* center icon in avatar place */
+ if ( rc.right-rc.left>16 ) rc.left += (( ( rc.right-rc.left )-16 )>>1 );
+ if ( rc.bottom-rc.top>16 ) rc.top += (( ( rc.bottom-rc.top )-16 )>>1 );
+
+ // Store position
+ _StoreItemPos( Drawing, CIT_ICON, &rc );
+ }
+ }
+ else
+ {
+ // Has to keep the empty space??
+ if (( left && !dat->row_align_left_items_to_left ) || ( !left && !dat->row_align_right_items_to_right ))
+ {
+ // Make rectangle
+ rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
+ left, max_width, max_width, dat->avatars_maxheight_size, HORIZONTAL_SPACE );
+
+ // Store position
+ //StoreItemPos( Drawing, CIT_AVATAR, &rc );
+ //Drawing->pos_avatar = rc;
+ }
+ }
+ break;
+ }
+
+ // Has to draw avatar
+ if ( dat->avatar_cache.nodes && Drawing->avatar_pos > AVATAR_POS_DONT_HAVE ) {
+ width = dat->avatar_cache.nodes[Drawing->avatar_pos].width;
+ height = dat->avatar_cache.nodes[Drawing->avatar_pos].height;
+ }else if ( Drawing->avatar_pos == AVATAR_POS_ANIMATED ) {
+ width = Drawing->avatar_size.cx;
+ height = Drawing->avatar_size.cy;
+ }else {
+ width = 0;
+ height = 0;
+ }
+
+ // Make rectangle
+ rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
+ left, width, max_width, height, HORIZONTAL_SPACE );
+
+ rc.top = max( free_row_rc.top, rc.top );
+ rc.bottom = min( free_row_rc.bottom, rc.bottom );
+
+ if ( rc.left < rc.right ) {
+ // Store position
+ _StoreItemPos( Drawing, CIT_AVATAR, &rc );
+ }
+ //TO DO: CALC avatar overlays
+ break;
+ }
+ case ITEM_ICON: /////////////////////////////////////////////////////////////////////////////////////////////////////
+ {
+ RECT rc;
+ int iImage = -1;
+ BOOL has_avatar = (( dat->use_avatar_service && Drawing->avatar_data != NULL ) ||
+ ( !dat->use_avatar_service && Drawing->avatar_pos != AVATAR_POS_DONT_HAVE ))
+ && !( CheckMiniMode( dat, selected, hottrack ));
+
+ if ( Drawing->type == CLCIT_CONTACT
+ && dat->icon_hide_on_avatar
+ && !dat->icon_draw_on_avatar_space
+ && has_avatar
+ && !Drawing->image_is_special )
+ {
+ // Don't have to draw, but has to keep the empty space?
+ if (( left && !dat->row_align_left_items_to_left ) || ( !left && !dat->row_align_right_items_to_right ))
+ {
+ rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
+ left, dat->iconXSpace, dat->iconXSpace, ICON_HEIGHT, HORIZONTAL_SPACE );
+
+ if ( rc.left < rc.right ) {
+ // Store position
+ _StoreItemPos( Drawing, CIT_ICON, &rc );
+ }
+ }
+ break;
+ }
+ if ( Drawing->type == CLCIT_CONTACT
+ && dat->icon_hide_on_avatar
+ && dat->icon_draw_on_avatar_space
+ && ( !Drawing->image_is_special || !has_avatar ||
+ (
+ dat->avatars_draw_overlay
+ && dat->avatars_maxheight_size >= ICON_HEIGHT + ( dat->avatars_draw_border ? 2 : 0 )
+ && GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE < MAX_REGS( g_pAvatarOverlayIcons )
+ && dat->avatars_overlay_type == SETTING_AVATAR_OVERLAY_TYPE_CONTACT
+ )))
+ {
+ // Don't have to draw and don't have to keep the empty space
+ break;
+ }
+
+ // Get image
+ iImage = -1;
+ if ( Drawing->type == CLCIT_GROUP && !dat->row_hide_group_icon )
+ iImage = Drawing->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT;
+ else if ( Drawing->type == CLCIT_CONTACT )
+ iImage = Drawing->iImage;
+
+ // Has image to draw?
+ if ( iImage != -1 )
+ {
+ // Make rectangle
+ rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
+ left, dat->iconXSpace, dat->iconXSpace, ICON_HEIGHT, HORIZONTAL_SPACE );
+
+ if ( rc.left < rc.right )
+ {
+ // Store position
+ _StoreItemPos( Drawing, CIT_ICON, &rc );
+ }
+ }
+ break;
+ }
+ case ITEM_CONTACT_TIME: /////////////////////////////////////////////////////////////////////////////////////////////////////
+ {
+ PDNCE pdnce = ( PDNCE )(( Drawing->type == CLCIT_CONTACT )?pcli->pfnGetCacheEntry( Drawing->hContact ):NULL );
+ if ( Drawing->type == CLCIT_CONTACT && dat->contact_time_show && pdnce->hTimeZone )
+ {
+ TCHAR szResult[80];
+
+ if ( !tmi.printDateTime(pdnce->hTimeZone, _T("t"), szResult, SIZEOF(szResult), 0))
+ {
+ SIZE text_size;
+ RECT rc;
+
+ // Select font
+ ChangeToFont( hdcMem, dat, FONTID_CONTACT_TIME, NULL );
+
+ // Get text size
+ text_size.cy = ske_DrawText( hdcMem, szResult, lstrlen( szResult ), &rc, DT_CALCRECT | DT_NOPREFIX | DT_SINGLELINE );
+ text_size.cy = min( text_size.cy, free_row_rc.bottom - free_row_rc.top );
+ text_size.cx = rc.right - rc.left;
+
+ // Get rc
+ rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos, left,
+ text_size.cx, text_size.cx, text_size.cy, HORIZONTAL_SPACE );
+
+ if ( rc.left < rc.right )
+ {
+ // Store pos
+ Drawing->pos_contact_time = rc;
+ _StoreItemPos( Drawing, CIT_TIME, &rc );
+ }
+ }
+ }
+ break;
+ }
+ case ITEM_TEXT: /////////////////////////////////////////////////////////////////////////////////////////////////////
+ {
+ // Store init text position:
+ text_left_pos = left_pos;
+
+ left_pos += MIN_TEXT_WIDTH;
+ free_row_rc.left = row_rc.left + left_pos;
+
+ item_text = item;
+ left = FALSE;
+ break;
+ }
+ case ITEM_EXTRA_ICONS: //////////////////////////////////////////////////////////////////////////////////////////////
+ {
+ // Draw extra icons
+ if ( !Drawing->isSubcontact || dat->dbbMetaHideExtra == 0 && dat->extraColumnsCount > 0 )
+ {
+ int iImage;
+ int count = 0;
+ RECT rc;
+
+ for ( iImage = dat->extraColumnsCount-1 ; iImage >= 0 ; iImage -- )
+ {
+ if ( Drawing->iExtraImage[iImage] != 0xFF || Drawing->iWideExtraImage[iImage] != 0xFFFF || !dat->MetaIgnoreEmptyExtra )
+ {
+ rc = _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
+ left, dat->extraColumnSpacing, dat->extraColumnSpacing, ICON_HEIGHT, 0 );
+ if ( rc.left < rc.right )
+ {
+ // Store position
+ _StoreItemPos( Drawing, CIT_EXTRA|( iImage&0x3F ), &rc );
+ //Drawing->pos_extra[iImage] = rc;
+ count++;
+ }
+ }
+ }
+ // Add extra space
+ if ( count )
+ {
+ _GetRectangle( dat, &row_rc, &free_row_rc, &left_pos, &right_pos,
+ left, HORIZONTAL_SPACE, HORIZONTAL_SPACE, ICON_HEIGHT, 0 );
+ }
+ }
+ break;
+ }
+ }
+ }
+ if ( text_left_pos < free_row_rc.right )
+ {
+ // Draw text
+ RECT text_rc;
+ RECT selection_text_rc;
+ SIZE text_size = {0};
+ SIZE second_line_text_size = {0};
+ SIZE third_line_text_size = {0};
+ SIZE space_size = {0};
+ SIZE counts_size = {0};
+ char *szCounts = NULL;//mir_tstrdup( _T( "" ));
+ int free_width;
+ int free_height;
+ int max_bottom_selection_border = SELECTION_BORDER;
+ UINT uTextFormat = DT_NOPREFIX| /*DT_VCENTER |*/ DT_SINGLELINE | ( dat->text_rtl ? DT_RTLREADING : 0 ) | ( dat->text_align_right ? DT_RIGHT : 0 );
+
+ free_row_rc.left = text_left_pos;
+ free_width = free_row_rc.right - free_row_rc.left;
+ free_height = free_row_rc.bottom - free_row_rc.top;
+
+ // Select font
+ ChangeToFont( hdcMem, dat, GetBasicFontID( Drawing ), NULL );
+
+ // Get text size
+ GetTextSize( &text_size, hdcMem, free_row_rc, Drawing->szText, Drawing->ssText.plText, uTextFormat,
+ dat->text_resize_smileys ? 0 : Drawing->ssText.iMaxSmileyHeight );
+
+ // Get rect
+ text_rc = free_row_rc;
+
+ free_height -= text_size.cy;
+ text_rc.top += free_height >> 1;
+ text_rc.bottom = text_rc.top + text_size.cy;
+
+ if ( dat->text_align_right )
+ text_rc.left = max( free_row_rc.left, free_row_rc.right - text_size.cx );
+ else
+ text_rc.right = min( free_row_rc.right, free_row_rc.left + text_size.cx );
+
+ selection_text_rc = text_rc;
+
+ // If group, can have the size of count
+ if ( Drawing->type == CLCIT_GROUP )
+ {
+ int full_text_width = text_size.cx;
+ // Group conts?
+ szCounts = pcli->pfnGetGroupCountsText( dat, Drawing );
+
+ // Has to draw the count?
+ if ( szCounts && szCounts[0] )
+ {
+ RECT space_rc = free_row_rc;
+ RECT counts_rc = free_row_rc;
+ int text_width;
+
+ free_height = free_row_rc.bottom - free_row_rc.top;
+
+ // Get widths
+ ske_DrawText( hdcMem, _T( " " ), 1, &space_rc, DT_CALCRECT | DT_NOPREFIX );
+ space_size.cx = space_rc.right - space_rc.left;
+ space_size.cy = min( space_rc.bottom - space_rc.top, free_height );
+
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ DrawTextA( hdcMem, szCounts, lstrlenA( szCounts ), &counts_rc, DT_CALCRECT );
+
+ //Store position
+ //StoreItemPos( Drawing, CIT_SUBTEXT1, &counts_rc ); // Or not to comment?
+
+ counts_size.cx = counts_rc.right - counts_rc.left;
+ counts_size.cy = min( counts_rc.bottom - counts_rc.top, free_height );
+
+ text_width = free_row_rc.right - free_row_rc.left - space_size.cx - counts_size.cx;
+
+ if ( text_width > 4 )
+ {
+ text_size.cx = min( text_width, text_size.cx );
+ text_width = text_size.cx + space_size.cx + counts_size.cx;
+ }
+ else
+ {
+ text_width = text_size.cx;
+ space_size.cx = 0;
+ space_size.cy = 0;
+ counts_size.cx = 0;
+ counts_size.cy = 0;
+ }
+
+ // Get rect
+ free_height -= max( text_size.cy, counts_size.cy );
+ text_rc.top = free_row_rc.top + ( free_height >> 1 );
+ text_rc.bottom = text_rc.top + max( text_size.cy, counts_size.cy );
+
+ if ( dat->text_align_right )
+ text_rc.left = free_row_rc.right - text_width;
+ else
+ text_rc.right = free_row_rc.left + text_width;
+
+ selection_text_rc = text_rc;
+ full_text_width = text_width;
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPS:FONTID_CLOSEDGROUPS, NULL );
+ }
+
+ if ( dat->row_align_group_mode == 1 ) //center
+ {
+ int x;
+ x = free_row_rc.left+(( free_row_rc.right-free_row_rc.left-full_text_width )>>1 );
+ //int l = dat->leftMargin;
+ //int r = dat->rightMargin;
+ //x = l+row_rc.left+(( row_rc.right-row_rc.left-full_text_width-l-r )>>1 );
+ text_rc.left = x;
+ text_rc.right = x+full_text_width;
+ }
+ else if ( dat->row_align_group_mode == 2 ) //right
+ {
+ text_rc.left = free_row_rc.right-full_text_width;
+ text_rc.right = free_row_rc.right;
+ }
+ else //left
+ {
+ text_rc.left = free_row_rc.left;
+ text_rc.right = free_row_rc.left+full_text_width;
+ }
+
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && !CheckMiniMode( dat, selected, hottrack ))
+ {
+ int tmp;
+ PDNCE pdnce = ( PDNCE )(( Drawing->type == CLCIT_CONTACT )?pcli->pfnGetCacheEntry( Drawing->hContact ):NULL );
+ if ( dat->second_line_show && dat->second_line_type == TEXT_CONTACT_TIME && pdnce->hTimeZone)
+ {
+ // Get contact time
+ TCHAR buf[70] = _T("");
+ tmi.printDateTime(pdnce->hTimeZone, _T("t"), buf, SIZEOF(buf), 0);
+ mir_free( pdnce->szThirdLineText );
+ pdnce->szSecondLineText = mir_tstrdup( buf );
+ }
+
+ if ( dat->second_line_show && pdnce->szSecondLineText && pdnce->szSecondLineText[0]
+ && free_height > dat->second_line_top_space )
+ {
+ //RECT rc_tmp = free_row_rc;
+
+ ChangeToFont( hdcMem, dat, FONTID_SECONDLINE, NULL );
+
+ // Get sizes
+ GetTextSize( &second_line_text_size, hdcMem, free_row_rc, pdnce->szSecondLineText, pdnce->ssSecondLine.plText,
+ uTextFormat, dat->text_resize_smileys ? 0 : pdnce->ssSecondLine.iMaxSmileyHeight );
+
+ // Get rect
+ tmp = min( free_height, dat->second_line_top_space + second_line_text_size.cy );
+
+ free_height -= tmp;
+ text_rc.top = free_row_rc.top + ( free_height >> 1 );
+ text_rc.bottom = text_rc.top + free_row_rc.bottom - free_row_rc.top - free_height;
+
+ if ( dat->text_align_right )
+ text_rc.left = max( free_row_rc.left, min( text_rc.left, free_row_rc.right - second_line_text_size.cx ));
+ else
+ text_rc.right = min( free_row_rc.right, max( text_rc.right, free_row_rc.left + second_line_text_size.cx ));
+
+ selection_text_rc.top = text_rc.top;
+ selection_text_rc.bottom = min( selection_text_rc.bottom, selection_text_rc.top + text_size.cy );
+
+ max_bottom_selection_border = min( max_bottom_selection_border, dat->second_line_top_space / 2 );
+ }
+ if ( dat->third_line_show && dat->third_line_type == TEXT_CONTACT_TIME && pdnce->hTimeZone )
+ {
+ // Get contact time
+ TCHAR buf[70] = _T("");
+ tmi.printDateTime(pdnce->hTimeZone, _T("t"), buf, SIZEOF(buf), 0);
+ mir_free( pdnce->szThirdLineText );
+ pdnce->szThirdLineText = mir_tstrdup( buf );
+ }
+ if ( dat->third_line_show && pdnce->szThirdLineText != NULL && pdnce->szThirdLineText[0]
+ && free_height > dat->third_line_top_space )
+ {
+ //RECT rc_tmp = free_row_rc;
+
+ ChangeToFont( hdcMem, dat, FONTID_THIRDLINE, NULL );
+
+ // Get sizes
+ GetTextSize( &third_line_text_size, hdcMem, free_row_rc, pdnce->szThirdLineText, pdnce->ssThirdLine.plText,
+ uTextFormat, dat->text_resize_smileys ? 0 : pdnce->ssThirdLine.iMaxSmileyHeight );
+
+ // Get rect
+ tmp = min( free_height, dat->third_line_top_space + third_line_text_size.cy );
+
+ free_height -= tmp;
+ text_rc.top = free_row_rc.top + ( free_height >> 1 );
+ text_rc.bottom = text_rc.top + free_row_rc.bottom - free_row_rc.top - free_height;
+
+ if ( dat->text_align_right )
+ text_rc.left = max( free_row_rc.left, min( text_rc.left, free_row_rc.right - third_line_text_size.cx ));
+ else
+ text_rc.right = min( free_row_rc.right, max( text_rc.right, free_row_rc.left + third_line_text_size.cx ));
+
+ selection_text_rc.top = text_rc.top;
+ selection_text_rc.bottom = min( selection_text_rc.bottom, selection_text_rc.top + text_size.cy );
+
+ max_bottom_selection_border = min( max_bottom_selection_border, dat->third_line_top_space / 2 );
+ }
+
+ ChangeToFont( hdcMem, dat, GetBasicFontID( Drawing ), NULL );
+ }
+
+
+ selection_text_rc.left = text_rc.left;
+ selection_text_rc.right = text_rc.right;
+
+ Drawing->pos_label = text_rc;
+
+ selection_text_rc.top = max( selection_text_rc.top - SELECTION_BORDER, row_rc.top );
+ selection_text_rc.bottom = min( selection_text_rc.bottom + max_bottom_selection_border, row_rc.bottom );
+
+ if ( dat->text_align_right )
+ selection_text_rc.left = max( selection_text_rc.left - SELECTION_BORDER, free_row_rc.left );
+ else
+ selection_text_rc.right = min( selection_text_rc.right + SELECTION_BORDER, free_row_rc.right );
+ _StoreItemPos( Drawing, CIT_SELECTION, &selection_text_rc );
+
+ Drawing->pos_rename_rect = free_row_rc;
+
+ {
+ // Draw text
+ uTextFormat = uTextFormat | ( gl_TrimText?DT_END_ELLIPSIS:0 );
+
+ switch ( Drawing->type )
+ {
+ case CLCIT_DIVIDER:
+ {
+ //devider
+ RECT trc = free_row_rc;
+ RECT rc = free_row_rc;
+ rc.top += ( rc.bottom - rc.top ) >> 1;
+ rc.bottom = rc.top + 2;
+ rc.right = rc.left + (( rc.right - rc.left - text_size.cx )>>1 ) - 3;
+ trc.left = rc.right + 3;
+ trc.right = trc.left + text_size.cx + 6;
+ if ( text_size.cy < trc.bottom - trc.top )
+ {
+ trc.top += ( trc.bottom - trc.top - text_size.cy ) >> 1;
+ trc.bottom = trc.top + text_size.cy;
+ }
+ _StoreItemPos( Drawing, CIT_TEXT, &trc );
+ rc.left = rc.right + 6 + text_size.cx;
+ rc.right = free_row_rc.right;
+ break;
+ }
+ case CLCIT_GROUP:
+ {
+ RECT rc = text_rc;
+
+ // Get text rectangle
+ if ( dat->text_align_right )
+ rc.left = rc.right - text_size.cx;
+ else
+ rc.right = rc.left + text_size.cx;
+
+
+ if ( text_size.cy < rc.bottom - rc.top )
+ {
+ rc.top += ( rc.bottom - rc.top - text_size.cy ) >> 1;
+ rc.bottom = rc.top + text_size.cy;
+ }
+
+ // Draw text
+ _StoreItemPos( Drawing, CIT_TEXT, &rc );
+
+ // Has to draw the count?
+ if ( counts_size.cx > 0 )
+ {
+ RECT counts_rc = text_rc;
+ //counts_size.cx;
+ if ( dat->text_align_right )
+ counts_rc.right = text_rc.left + counts_size.cx;
+ else
+ counts_rc.left = text_rc.right - counts_size.cx;
+
+ if ( counts_size.cy < counts_rc.bottom - counts_rc.top )
+ {
+ counts_rc.top += ( counts_rc.bottom - counts_rc.top - counts_size.cy + 1 ) >> 1;
+ counts_rc.bottom = counts_rc.top + counts_size.cy;
+ }
+ // Draw counts
+ _StoreItemPos( Drawing, CIT_SUBTEXT1, &counts_rc );
+ }
+ break;
+ }
+ case CLCIT_CONTACT:
+ {
+
+ RECT free_rc = text_rc;
+ PDNCE pdnce = ( PDNCE )pcli->pfnGetCacheEntry( Drawing->hContact );
+ if ( text_size.cx > 0 && free_rc.bottom > free_rc.top )
+ {
+ RECT rc = free_rc;
+ rc.bottom = min( rc.bottom, rc.top + text_size.cy );
+
+ if ( text_size.cx < rc.right - rc.left )
+ {
+ if ( dat->text_align_right )
+ rc.left = rc.right - text_size.cx;
+ else
+ rc.right = rc.left + text_size.cx;
+ }
+ uTextFormat |= DT_VCENTER;
+ _StoreItemPos( Drawing, CIT_TEXT, &rc );
+ free_rc.top = rc.bottom;
+ }
+ uTextFormat &= ~DT_VCENTER;
+ if ( second_line_text_size.cx > 0 && free_rc.bottom > free_rc.top )
+ {
+ free_rc.top += dat->second_line_top_space;
+
+ if ( free_rc.bottom > free_rc.top )
+ {
+ RECT rc = free_rc;
+ rc.bottom = min( rc.bottom, rc.top + second_line_text_size.cy );
+
+ if ( second_line_text_size.cx < rc.right - rc.left )
+ {
+ if ( dat->text_align_right )
+ rc.left = rc.right - second_line_text_size.cx;
+ else
+ rc.right = rc.left + second_line_text_size.cx;
+ }
+ _StoreItemPos( Drawing, CIT_SUBTEXT1, &rc );
+ free_rc.top = rc.bottom;
+ }
+ }
+
+ if ( third_line_text_size.cx > 0 && free_rc.bottom > free_rc.top )
+ {
+ free_rc.top += dat->third_line_top_space;
+
+ if ( free_rc.bottom > free_rc.top )
+ {
+ RECT rc = free_rc;
+ rc.bottom = min( rc.bottom, rc.top + third_line_text_size.cy );
+
+ if ( third_line_text_size.cx < rc.right - rc.left )
+ {
+ if ( dat->text_align_right )
+ rc.left = rc.right - third_line_text_size.cx;
+ else
+ rc.right = rc.left + third_line_text_size.cx;
+ }
+ _StoreItemPos( Drawing, CIT_SUBTEXT2, &rc );
+ free_rc.top = rc.bottom;
+ }
+ }
+ break;
+ }
+ default: // CLCIT_INFO
+ {
+ _StoreItemPos( Drawing, CIT_TEXT, &text_rc );
+ }
+ }
+ }
+ }
+
+ *in_free_row_rc = free_row_rc;
+ *in_row_rc = row_rc;
+ Drawing->ext_fItemsValid = FALSE; /*TO DO: correctly implement placement recalculation*/
+}
+BOOL CLCPaint::__IsVisible( RECT * firtRect, RECT * secondRect )
+{
+ RECT res;
+ IntersectRect( &res, firtRect, secondRect );
+ return !IsRectEmpty( &res );
+}
+
+
+void CLCPaint::_GetBlendMode( IN struct ClcData *dat, IN struct ClcContact * Drawing, IN BOOL selected, IN BOOL hottrack, IN BOOL bFlag, OUT COLORREF * OutColourFg, OUT int * OutMode )
+{
+ COLORREF colourFg;
+ int mode;
+ int BlendedInActiveState = ( dat->dbbBlendInActiveState );
+ int BlendValue = dat->dbbBlend25 ? ILD_BLEND25 : ILD_BLEND50;
+ if ( selected && ( bFlag&GIM_SELECTED_AFFECT ))
+ {
+ colourFg = dat->selBkColour;
+ mode = BlendedInActiveState?ILD_NORMAL:ILD_SELECTED;
+ }
+ else if ( hottrack && ( bFlag&GIM_HOT_AFFECT ))
+ {
+ mode = BlendedInActiveState?ILD_NORMAL:ILD_FOCUS;
+ colourFg = dat->hotTextColour;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT && Drawing->flags&CONTACTF_NOTONLIST && ( bFlag&GIM_TEMP_AFFECT ))
+ {
+ colourFg = dat->fontModernInfo[FONTID_NOTONLIST].colour;
+ mode = BlendValue;
+ }
+ else
+ {
+ colourFg = dat->selBkColour;
+ mode = ILD_NORMAL;
+ }
+ if ( Drawing->type == CLCIT_CONTACT && dat->showIdle && ( Drawing->flags&CONTACTF_IDLE ) &&
+ _GetRealStatus( Drawing, ID_STATUS_OFFLINE ) != ID_STATUS_OFFLINE &&
+ ( bFlag&GIM_IDLE_AFFECT )
+ )
+ mode = ILD_SELECTED;
+ if ( OutColourFg ) *OutColourFg = colourFg;
+ if ( OutMode )
+ {
+ if ( OutColourFg ) *OutMode = mode; //return ILD_MODE if color requested
+ else *OutMode =
+ ( mode == ILD_BLEND50 )?128 :
+ ( mode == ILD_BLEND25 )?64 :
+ 255; //return alpha otherwise
+ }
+}
+
+void CLCPaint::_DrawContactAvatar( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *row_rc, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem )
+{
+ if ( Drawing->avatar_pos == AVATAR_POS_ANIMATED )
+ {
+ int overlayIdx = -1;
+ int blendmode = 255;
+ if ( dat->avatars_draw_overlay && dat->avatars_maxheight_size >= ICON_HEIGHT + ( dat->avatars_draw_border ? 2 : 0 )
+ && GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE < MAX_REGS( g_pAvatarOverlayIcons ))
+ {
+ switch( dat->avatars_overlay_type )
+ {
+ case SETTING_AVATAR_OVERLAY_TYPE_NORMAL:
+ overlayIdx = g_pAvatarOverlayIcons[GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE].listID;
+ break;
+ case SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL:
+ overlayIdx = ExtIconFromStatusMode( Drawing->hContact, Drawing->proto,
+ Drawing->proto == NULL ? ID_STATUS_OFFLINE : GetContactCachedStatus( Drawing->hContact ));
+ break;
+ case SETTING_AVATAR_OVERLAY_TYPE_CONTACT:
+ overlayIdx = Drawing->iImage;
+ break;
+ }
+ }
+ _GetBlendMode( dat, Drawing, selected, hottrack, GIM_AVATAR_AFFECT, NULL, &blendmode );
+ AniAva_SetAvatarPos( Drawing->hContact, prcItem, overlayIdx, blendmode );
+ AniAva_RenderAvatar( Drawing->hContact, hdcMem, prcItem );
+ }
+ else if ( Drawing->avatar_pos>AVATAR_POS_DONT_HAVE )
+ {
+ int round_radius = 0;
+ HRGN rgn;
+ int blendmode = 255;
+
+ _GetBlendMode( dat, Drawing, selected, hottrack, GIM_AVATAR_AFFECT, NULL, &blendmode );
+
+ //get round corner radius
+ if ( dat->avatars_round_corners )
+ {
+ if ( dat->avatars_use_custom_corner_size )
+ round_radius = dat->avatars_custom_corner_size;
+ else
+ round_radius = min( _rcWidth( prcItem ), _rcHeight( prcItem )) / 5;
+ }
+ // draw borders
+ if ( dat->avatars_draw_border )
+ {
+ HBRUSH hBrush = CreateSolidBrush( dat->avatars_border_color );
+ HBRUSH hOldBrush = ( HBRUSH )SelectObject( hdcMem, hBrush );
+ HRGN rgnOutside = CreateRoundRectRgn( prcItem->left, prcItem->top, prcItem->right+1, prcItem->bottom+1, round_radius << 1, round_radius << 1 );
+ HRGN rgnInside = CreateRoundRectRgn( prcItem->left+1, prcItem->top+1, prcItem->right, prcItem->bottom, round_radius << 1, round_radius << 1 );
+ CombineRgn( rgnOutside, rgnOutside, rgnInside, RGN_DIFF );
+ FillRgn( hdcMem, rgnOutside, hBrush );
+ ske_SetRgnOpaque( hdcMem, rgnOutside );
+ SelectObject( hdcMem, hOldBrush );
+ DeleteObject( hBrush );
+ DeleteObject( rgnInside );
+ DeleteObject( rgnOutside );
+ }
+
+ //set clip area to clip avatars within borders
+ if ( dat->avatars_round_corners || dat->avatars_draw_border )
+ {
+ int k = dat->avatars_draw_border?1:0;
+ rgn = CreateRoundRectRgn( prcItem->left+k, prcItem->top+k, prcItem->right+1-k, prcItem->bottom+1-k, round_radius * 2, round_radius * 2 );
+
+ }
+ else
+ rgn = CreateRectRgn( prcItem->left, prcItem->top, prcItem->right, prcItem->bottom );
+ ExtSelectClipRgn( hdcMem, rgn, RGN_AND );
+ // Draw avatar
+ ImageArray_DrawImage( &dat->avatar_cache, Drawing->avatar_pos, hdcMem, prcItem->left, prcItem->top, blendmode );
+
+ // Restore region
+ DeleteObject( rgn );
+ rgn = CreateRectRgn( row_rc->left, row_rc->top, row_rc->right, row_rc->bottom );
+ SelectClipRgn( hdcMem, rgn );
+ DeleteObject( rgn );
+ // Draw overlays
+ if ( dat->avatars_draw_overlay && dat->avatars_maxheight_size >= ICON_HEIGHT + ( dat->avatars_draw_border ? 2 : 0 )
+ && GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE < MAX_REGS( g_pAvatarOverlayIcons ))
+ {
+ POINT ptOverlay = { prcItem->right-ICON_HEIGHT, prcItem->bottom-ICON_HEIGHT };
+ if ( dat->avatars_draw_border )
+ {
+ ptOverlay.x--;
+ ptOverlay.y--;
+ }
+ switch( dat->avatars_overlay_type )
+ {
+ case SETTING_AVATAR_OVERLAY_TYPE_NORMAL:
+ {
+ ske_ImageList_DrawEx( hAvatarOverlays, g_pAvatarOverlayIcons[GetContactCachedStatus( Drawing->hContact ) - ID_STATUS_OFFLINE].listID,
+ hdcMem,
+ ptOverlay.x, ptOverlay.y, ICON_HEIGHT, ICON_HEIGHT,
+ CLR_NONE, CLR_NONE,
+ ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
+ break;
+ }
+ case SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL:
+ {
+ int item;
+
+ item = ExtIconFromStatusMode( Drawing->hContact, Drawing->proto,
+ Drawing->proto == NULL ? ID_STATUS_OFFLINE : GetContactCachedStatus( Drawing->hContact ));
+ if ( item != -1 )
+ _DrawStatusIcon( Drawing, dat, item, hdcMem,
+ ptOverlay.x, ptOverlay.y, ICON_HEIGHT, ICON_HEIGHT,
+ CLR_NONE, CLR_NONE, ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
+ break;
+ }
+ case SETTING_AVATAR_OVERLAY_TYPE_CONTACT:
+ {
+ if ( Drawing->iImage != -1 )
+ _DrawStatusIcon( Drawing, dat, Drawing->iImage, hdcMem,
+ ptOverlay.x, ptOverlay.y, ICON_HEIGHT, ICON_HEIGHT,
+ CLR_NONE, CLR_NONE, ( blendmode == 255 )?ILD_NORMAL:( blendmode == 128 )?ILD_BLEND50:ILD_BLEND25 );
+ break;
+ }
+ }
+ }
+ }
+}
+
+void CLCPaint::_DrawContactIcon( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem )
+{
+ //Draw Icon
+ int iImage = -1;
+ // Get image
+ if ( Drawing->type == CLCIT_GROUP )
+ {
+ if ( !dat->row_hide_group_icon ) iImage = Drawing->group->expanded ? IMAGE_GROUPOPEN : IMAGE_GROUPSHUT;
+ else iImage = -1;
+ }
+ else if ( Drawing->type == CLCIT_CONTACT )
+ iImage = Drawing->iImage;
+
+ // Has image to draw?
+ if ( iImage != -1 )
+ {
+ COLORREF colourFg;
+ int mode;
+ _GetBlendMode( dat, Drawing, selected, hottrack, GIM_STATUSICON_AFFECT, &colourFg, &mode );
+ _DrawStatusIcon( Drawing, dat, iImage, hdcMem,
+ prcItem->left, prcItem->top,
+ 0, 0, CLR_NONE, colourFg, mode );
+ }
+}
+
+void CLCPaint::_DrawContactText( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem, UINT uTextFormat )
+{
+ ChangeToFont( hdcMem, dat, GetBasicFontID( Drawing ), NULL );
+ if ( selected )
+ SetTextColor( hdcMem, dat->force_in_dialog ? GetSysColor( COLOR_HIGHLIGHTTEXT ) : dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+
+ if ( Drawing->type == CLCIT_GROUP )
+ {
+ ske_DrawText( hdcMem, Drawing->szText, -1, prcItem, uTextFormat );
+ if ( selected && dat->szQuickSearch[0] != '\0' )
+ {
+ SetTextColor( hdcMem, dat->quickSearchColour );
+ ske_DrawText( hdcMem, Drawing->szText, lstrlen( dat->szQuickSearch ), prcItem, uTextFormat );
+ }
+ }
+ else if ( Drawing->type == CLCIT_CONTACT )
+ {
+ SIZE text_size;
+ text_size.cx = _rcWidth( prcItem );
+ text_size.cy = _rcHeight( prcItem );
+ uTextFormat |= DT_VCENTER;
+ //get font
+ _DrawTextSmiley( hdcMem, prcItem, &text_size, Drawing->szText, -1, Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ if ( selected && dat->szQuickSearch[0] != '\0' )
+ {
+ SetTextColor( hdcMem, dat->quickSearchColour );
+ _DrawTextSmiley( hdcMem, prcItem, &text_size, Drawing->szText, lstrlen( dat->szQuickSearch ), Drawing->ssText.plText, uTextFormat, dat->text_resize_smileys );
+ }
+ }
+ else
+ {
+ ske_DrawText( hdcMem, Drawing->szText, -1, prcItem, uTextFormat );
+ }
+ text_rc.right = max( text_rc.right, prcItem->right );
+ text_rc.left = min( text_rc.left, prcItem->left );
+}
+void CLCPaint::_DrawContactSubText( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem, UINT uTextFormat, BYTE itemType )
+{
+ if ( Drawing->type == CLCIT_GROUP )
+ {
+ char * szCounts = pcli->pfnGetGroupCountsText( dat, Drawing );
+
+ // Has to draw the count?
+ if ( szCounts && szCounts[0] )
+ {
+ ChangeToFont( hdcMem, dat, Drawing->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS, NULL );
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ ske_DrawTextA( hdcMem, szCounts, -1, prcItem, uTextFormat );
+ ske_ResetTextEffect( hdcMem );
+ }
+ }
+ else if ( Drawing->type == CLCIT_CONTACT )
+ {
+ SIZE text_size = { _rcWidth( prcItem ), _rcHeight( prcItem ) };
+ PDNCE pdnce = ( PDNCE )(( Drawing->type == CLCIT_CONTACT )?pcli->pfnGetCacheEntry( Drawing->hContact ):NULL );
+ if ( pdnce )
+ {
+ ChangeToFont( hdcMem, dat, itemType == CIT_SUBTEXT1 ? FONTID_SECONDLINE : FONTID_THIRDLINE, NULL );
+ //draw second and third line
+ if ( selected )
+ SetTextColor( hdcMem, dat->selTextColour );
+ else if ( hottrack )
+ _SetHotTrackColour( hdcMem, dat );
+ uTextFormat |= DT_VCENTER;
+ if ( itemType == CIT_SUBTEXT1 )
+ _DrawTextSmiley( hdcMem, prcItem, &text_size, pdnce->szSecondLineText, -1, pdnce->ssSecondLine.plText, uTextFormat, dat->text_resize_smileys );
+ else
+ _DrawTextSmiley( hdcMem, prcItem, &text_size, pdnce->szThirdLineText, -1, pdnce->ssThirdLine.plText, uTextFormat, dat->text_resize_smileys );
+ }
+ }
+ text_rc.right = max( text_rc.right, prcItem->right );
+ text_rc.left = min( text_rc.left, prcItem->left );
+}
+void CLCPaint::_DrawContactTime( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * prcItem )
+{
+ TCHAR szResult[80];
+ PDNCE pdnce = ( PDNCE )(( Drawing->type == CLCIT_CONTACT )?pcli->pfnGetCacheEntry( Drawing->hContact ):NULL );
+
+ if ( !pdnce ) return;
+
+ if ( !tmi.printDateTime(pdnce->hTimeZone, _T("t"), szResult, SIZEOF(szResult), 0))
+ {
+ // Select font
+ ChangeToFont( hdcMem, dat, FONTID_CONTACT_TIME, NULL );
+ ske_DrawText( hdcMem, szResult, lstrlen( szResult ), prcItem, DT_NOPREFIX | DT_SINGLELINE );
+ }
+}
+
+void CLCPaint::_DrawContactSelection( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT *rcPaint, RECT * prcItem )
+{
+ // Selection background
+ if (( selected || hottrack ) && dat->HiLightMode == 0) {
+ if ( selected )
+ SkinDrawGlyph( hdcMem, prcItem, rcPaint, "Contact List/Selection" );
+ else if ( hottrack )
+ SkinDrawGlyph( hdcMem, prcItem, rcPaint, "Contact List/HotTracking" );
+ }
+}
+
+void CLCPaint::_DrawContactExtraIcon( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, int& selected, int& hottrack, RECT& text_rc, RECT * rc, int iImage )
+{
+ //Draw extra icon
+ COLORREF colourFg;
+ int mode;
+ if ( iImage != -1 )
+ {
+ _GetBlendMode( dat, Drawing, selected, hottrack, GIM_EXTRAICON_AFFECT, &colourFg, &mode );
+ if ( Drawing->iExtraImage[iImage] != 0xFF )
+ ske_ImageList_DrawEx( dat->himlExtraColumns, Drawing->iExtraImage[iImage], hdcMem,
+ rc->left, rc->top, 0, 0, CLR_NONE, colourFg, mode );
+ else if ( Drawing->iWideExtraImage[iImage] != 0xFFFF )
+ ske_ImageList_DrawEx( dat->himlWideExtraColumns, Drawing->iWideExtraImage[iImage], hdcMem,
+ rc->left, rc->top, 0, 0, CLR_NONE, colourFg, mode );
+ }
+}
+
+void CLCPaint::_DrawContactLine( HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *free_row_rc, RECT *rcPaint, RECT& text_rc )
+{ //draw line
+ RECT rc1 = *free_row_rc;
+ RECT rc2 = *free_row_rc;
+ rc1.right = text_rc.left-3;
+ rc2.left = text_rc.right+3;
+ rc1.top += ( rc1.bottom - rc1.top ) >> 1;
+ rc1.bottom = rc1.top + 2;
+ rc2.top += ( rc2.bottom - rc2.top ) >> 1;
+ rc2.bottom = rc2.top + 2;
+ {
+ RECT rcTemp = rc1;
+ IntersectRect( &rc1, &rcTemp, rcPaint );
+ }
+
+ { //Subtract icon rect from left and right.
+ RECT rcTemp;
+ IntersectRect( &rcTemp, &Drawing->pos_icon, &rc1 );
+ if ( !IsRectEmpty( &rcTemp )) rc1.right = rcTemp.left;
+ IntersectRect( &rcTemp, &Drawing->pos_icon, &rc2 );
+ if ( !IsRectEmpty( &rcTemp )) rc2.left = rcTemp.right;
+ }
+
+ if ( rc1.right-rc1.left >= 6 && !IsRectEmpty( &rc1 ))
+ {
+ DrawEdge( hdcMem, &rc1, BDR_SUNKENOUTER, BF_RECT );
+ ske_SetRectOpaque( hdcMem, &rc1 );
+ }
+ {
+ RECT rcTemp = rc2;
+ IntersectRect( &rc2, &rcTemp, rcPaint );
+ }
+ if ( rc2.right-rc2.left >= 6 && !IsRectEmpty( &rc2 ))
+ {
+ DrawEdge( hdcMem, &rc2, BDR_SUNKENOUTER, BF_RECT );
+ ske_SetRectOpaque( hdcMem, &rc2 );
+ }
+}
+
+void CLCPaint::_DrawContactItems( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT *row_rc, RECT *free_row_rc, int left_pos, int right_pos, int selected, int hottrack, RECT *rcPaint )
+{
+ int i;
+ RECT text_rc = {0};
+ UINT uTextFormat = DT_NOPREFIX |
+ /*DT_VCENTER |*/
+ DT_SINGLELINE |
+ ( dat->text_rtl ? DT_RTLREADING : 0 ) |
+ ( dat->text_align_right ? DT_RIGHT : 0 )|
+ ( gl_TrimText?DT_END_ELLIPSIS:0 )|
+ (( dat->force_in_dialog || dat->bkChanged ) ? DT_FORCENATIVERENDER:0 );
+
+ text_rc = *row_rc;
+
+ text_rc.right = row_rc->left;
+ text_rc.left = row_rc->right;
+
+ for ( i=0; i < Drawing->ext_nItemsNum; i++ )
+ {
+ RECT * prcItem = &( Drawing->ext_mpItemsDesc[i].itemRect );
+ if ( __IsVisible( rcPaint, prcItem ) || ( Drawing->ext_mpItemsDesc[i].itemType == CIT_AVATAR && Drawing->avatar_pos == AVATAR_POS_ANIMATED ))
+ {
+ switch( Drawing->ext_mpItemsDesc[i].itemType )
+ {
+ case CIT_AVATAR:
+ _DrawContactAvatar( hdcMem, dat, Drawing, row_rc, selected, hottrack, text_rc, prcItem );
+ break;
+ case CIT_ICON:
+ _DrawContactIcon( hdcMem, dat, Drawing, selected, hottrack, text_rc, prcItem );
+ break;
+ case CIT_TEXT:
+ _DrawContactText( hdcMem, dat, Drawing, selected, hottrack, text_rc, prcItem, uTextFormat );
+ break;
+ case CIT_SUBTEXT1:
+ case CIT_SUBTEXT2:
+ _DrawContactSubText( hdcMem, dat, Drawing, selected, hottrack, text_rc, prcItem, uTextFormat, Drawing->ext_mpItemsDesc[i].itemType );
+ break;
+ case CIT_TIME:
+ _DrawContactTime( hdcMem, dat, Drawing, selected, hottrack, text_rc, prcItem );
+ break;
+ case CIT_CHECKBOX:
+ //_DrawNothing no check boxes in skinned mode
+ break;
+ //other here
+ case CIT_SELECTION:
+ _DrawContactSelection( hdcMem, dat, Drawing, selected, hottrack, rcPaint, prcItem );
+ break;
+ default:
+ if ( Drawing->ext_mpItemsDesc[i].itemType&CIT_EXTRA )
+ _DrawContactExtraIcon( hdcMem, dat, Drawing, selected, hottrack, text_rc, prcItem, Drawing->ext_mpItemsDesc[i].itemType&0x3F );
+ break;
+ }
+ }
+ }
+ if (( Drawing->type == CLCIT_GROUP && dat->exStyle&CLS_EX_LINEWITHGROUPS )
+ || ( Drawing->type == CLCIT_DIVIDER ))
+ _DrawContactLine( hdcMem, dat, Drawing, free_row_rc, rcPaint, text_rc );
+}
+void CLCPaint::_PaintRowItems ( HWND hwnd, HDC hdcMem, struct ClcData *dat, struct ClcContact *Drawing, RECT row_rc, RECT free_row_rc, int left_pos, int right_pos, int selected, int hottrack, RECT *rcPaint )
+{
+ //Extended LAYOUT
+ if ( gl_RowRoot && ( dat->hWnd == pcli->hwndContactTree ))
+ {
+ _PaintRowItemsEx( hwnd, hdcMem, dat, Drawing, row_rc, free_row_rc, left_pos, right_pos, selected, hottrack, rcPaint );
+ ske_ResetTextEffect( hdcMem );
+ return;
+ }
+ //END OFF Extended LAYOUT
+ if ( !Drawing->ext_fItemsValid ) _CalcItemsPos( hwnd, hdcMem, dat, Drawing, &row_rc, &free_row_rc, left_pos, right_pos, selected, hottrack );
+ _DrawContactItems( hwnd, hdcMem, dat, Drawing, &row_rc, &free_row_rc, left_pos, right_pos, selected, hottrack, rcPaint );
+ ske_ResetTextEffect( hdcMem );
+}
+
+/* TODO Render items
+
+V avatar
+V avatars overlays
+V avatar clipping if ignore avatar height for row height calculation is set
+V icon
+V text
+V time
+V extra icons
+V selection/hot
+V groups and divider lines
+
+Milestones to implement Extended row layout
+
+- 1. Implement separate Row item position calculation and drawing
+V a. Separation of painting and positions calculation
+V b. Use Items rect array for hit test
+. c. Calculate row height via appropriate function
+. d. Invalidate row items only when needed
+
+. 2. Implement extended row item layout
+. a. layout template parsing
+. b. calculate positions according to template
+. c. GUI to modify template
+. d. skin defined template
+*/
diff --git a/plugins/Clist_modern/src/modern_clcutils.cpp b/plugins/Clist_modern/src/modern_clcutils.cpp
new file mode 100644
index 0000000000..9e6066c13a
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clcutils.cpp
@@ -0,0 +1,870 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_defsettings.h"
+
+//loads of stuff that didn't really fit anywhere else
+
+BOOL RectHitTest(RECT *rc, int testx, int testy)
+{
+ return testx >= rc->left && testx < rc->right && testy >= rc->top && testy < rc->bottom;
+}
+
+int cliHitTest(HWND hwnd,struct ClcData *dat,int testx,int testy,struct ClcContact **contact,struct ClcGroup **group,DWORD *flags)
+{
+ struct ClcContact *hitcontact = NULL;
+ struct ClcGroup *hitgroup = NULL;
+ int hit = -1;
+ RECT clRect;
+ if (CLUI_TestCursorOnBorders() != 0)
+ {
+ if (flags) *flags = CLCHT_NOWHERE;
+ return -1;
+ }
+ if (flags) *flags = 0;
+ GetClientRect(hwnd,&clRect);
+ if (testx < 0 || testy < 0 || testy >= clRect.bottom || testx >= clRect.right) {
+ if (flags) {
+ if (testx < 0) *flags |= CLCHT_TOLEFT;
+ else if (testx >= clRect.right) *flags |= CLCHT_TORIGHT;
+ if (testy < 0) *flags |= CLCHT_ABOVE;
+ else if (testy >= clRect.bottom) *flags |= CLCHT_BELOW;
+ }
+ return -1;
+ }
+ if (testx < dat->leftMargin) {
+ if (flags) *flags |= CLCHT_INLEFTMARGIN|CLCHT_NOWHERE;
+ return -1;
+ }
+
+ // Get hit item
+ hit = cliRowHitTest(dat, dat->yScroll + testy);
+
+ if (hit != -1)
+ hit = cliGetRowByIndex(dat, hit, &hitcontact, &hitgroup);
+
+ if (hit == -1) {
+ if (flags) *flags |= CLCHT_NOWHERE|CLCHT_BELOWITEMS;
+ return -1;
+ }
+ if (contact) *contact = hitcontact;
+ if (group) *group = hitgroup;
+ /////////
+
+ if (((testx < hitcontact->pos_indent) && !dat->text_rtl) ||
+ ((testx>clRect.right-hitcontact->pos_indent) && dat->text_rtl))
+ {
+ if (flags) *flags |= CLCHT_ONITEMINDENT;
+ return hit;
+ }
+
+ if (RectHitTest(&hitcontact->pos_check, testx, testy))
+ {
+ if (flags) *flags |= CLCHT_ONITEMCHECK;
+ return hit;
+ }
+
+ if (RectHitTest(&hitcontact->pos_avatar, testx, testy))
+ {
+ if (flags) *flags |= CLCHT_ONITEMICON;
+ return hit;
+ }
+
+ if (RectHitTest(&hitcontact->pos_icon, testx, testy))
+ {
+ if (flags) *flags |= CLCHT_ONITEMICON;
+ return hit;
+ }
+
+ // if (testx>hitcontact->pos_extra) {
+ // if (flags)
+ {
+ // int c = -1;
+ int i;
+ for (i=0; i < dat->extraColumnsCount; i++)
+ {
+ if (RectHitTest(&hitcontact->pos_extra[i], testx, testy))
+ {
+ if (flags) *flags |= CLCHT_ONITEMEXTRA|(i << 24);
+ return hit;
+ }
+ }
+ }
+
+ if (dat->HiLightMode == 1)
+ {
+ if (flags) *flags |= CLCHT_ONITEMLABEL;
+ return hit;
+ }
+
+ if (RectHitTest(&hitcontact->pos_label, testx, testy))
+ {
+ if (flags) *flags |= CLCHT_ONITEMLABEL;
+ return hit;
+ }
+
+ if (flags) *flags |= CLCHT_NOWHERE;
+ return hit;
+}
+
+void cliScrollTo(HWND hwnd,struct ClcData *dat,int desty,int noSmooth)
+{
+ DWORD startTick,nowTick;
+ int oldy = dat->yScroll;
+ RECT clRect,rcInvalidate;
+ int maxy,previousy;
+
+ if (dat->iHotTrack != -1 && dat->yScroll != desty) {
+ pcli->pfnInvalidateItem(hwnd,dat,dat->iHotTrack);
+ dat->iHotTrack = -1;
+ ReleaseCapture();
+ }
+ GetClientRect(hwnd,&clRect);
+ rcInvalidate = clRect;
+ //maxy = dat->rowHeight*GetGroupContentsCount(&dat->list,2)-clRect.bottom;
+ maxy = cliGetRowTotalHeight(dat)-clRect.bottom;
+ if (desty>maxy) desty = maxy;
+ if (desty < 0) desty = 0;
+ if (abs(desty-dat->yScroll) < 4) noSmooth = 1;
+ if ( !noSmooth && dat->exStyle&CLS_EX_NOSMOOTHSCROLLING) noSmooth = 1;
+ previousy = dat->yScroll;
+
+ BOOL keyDown = ( ( GetKeyState( VK_UP )
+ | GetKeyState( VK_DOWN )
+ | GetKeyState( VK_LEFT )
+ | GetKeyState( VK_RIGHT )
+ | GetKeyState( VK_PRIOR )
+ | GetKeyState( VK_NEXT )
+ | GetKeyState( VK_HOME )
+ | GetKeyState( VK_END )) & 0x8000 );
+
+ if ( !noSmooth && !keyDown)
+ {
+ startTick = GetTickCount();
+ for (;;) {
+ nowTick = GetTickCount();
+ if (nowTick >= startTick+dat->scrollTime) break;
+ dat->yScroll = oldy+(desty-oldy)*(int)(nowTick-startTick)/dat->scrollTime;
+ if (/*dat->backgroundBmpUse&CLBF_SCROLL || dat->hBmpBackground == NULL && */FALSE)
+ ScrollWindowEx(hwnd,0,previousy-dat->yScroll,NULL,NULL,NULL,NULL,SW_INVALIDATE);
+ else
+ {
+ CallService(MS_SKINENG_UPTATEFRAMEIMAGE,(WPARAM) hwnd, (LPARAM) 0);
+ //InvalidateRectZ(hwnd,NULL,FALSE);
+ }
+ previousy = dat->yScroll;
+ SetScrollPos(hwnd,SB_VERT,dat->yScroll,TRUE);
+ CallService(MS_SKINENG_UPTATEFRAMEIMAGE,(WPARAM) hwnd, (LPARAM) 0);
+ UpdateWindow(hwnd);
+ }
+ }
+ dat->yScroll = desty;
+ if ((dat->backgroundBmpUse&CLBF_SCROLL || dat->hBmpBackground == NULL) && FALSE)
+ ScrollWindowEx(hwnd,0,previousy-dat->yScroll,NULL,NULL,NULL,NULL,SW_INVALIDATE);
+ else
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ SetScrollPos(hwnd,SB_VERT,dat->yScroll,TRUE);
+}
+
+
+void cliRecalcScrollBar(HWND hwnd,struct ClcData *dat)
+{
+ SCROLLINFO si = {0};
+ RECT clRect;
+ NMCLISTCONTROL nm;
+ if (LOCK_RECALC_SCROLLBAR) return;
+
+ RowHeights_CalcRowHeights(dat, hwnd);
+
+ GetClientRect(hwnd,&clRect);
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ si.nMin = 0;
+ si.nMax = cliGetRowTotalHeight(dat)-1;
+ si.nPage = clRect.bottom;
+ si.nPos = dat->yScroll;
+
+ nm.hdr.code = CLN_LISTSIZECHANGE;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = 0;//GetDlgCtrlID(hwnd);
+ nm.pt.y = si.nMax;
+
+ SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&nm); //post
+
+ GetClientRect(hwnd,&clRect);
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ si.nMin = 0;
+ si.nMax = cliGetRowTotalHeight(dat)-1;
+ si.nPage = clRect.bottom;
+ si.nPos = dat->yScroll;
+
+ if ( GetWindowLongPtr(hwnd,GWL_STYLE)&CLS_CONTACTLIST ) {
+ if ( dat->noVScrollbar == 0 ) SetScrollInfo(hwnd,SB_VERT,&si,TRUE);
+ //else SetScrollInfo(hwnd,SB_VERT,&si,FALSE);
+ }
+ else
+ SetScrollInfo(hwnd,SB_VERT,&si,TRUE);
+ g_mutex_bSizing = 1;
+ cliScrollTo(hwnd,dat,dat->yScroll,1);
+ g_mutex_bSizing = 0;
+}
+
+
+static WNDPROC OldRenameEditWndProc;
+static LRESULT CALLBACK RenameEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg)
+ {
+ case WM_KEYDOWN:
+ switch(wParam)
+ {
+ case VK_RETURN:
+ pcli->pfnEndRename(GetParent(hwnd),(struct ClcData*)GetWindowLongPtr(hwnd,GWLP_USERDATA),1);
+ return 0;
+ case VK_ESCAPE:
+ pcli->pfnEndRename(GetParent(hwnd),(struct ClcData*)GetWindowLongPtr(hwnd,GWLP_USERDATA),0);
+ return 0;
+ }
+ break;
+ case WM_GETDLGCODE:
+ if (lParam)
+ {
+ MSG *msg = (MSG*)lParam;
+ if (msg->message == WM_KEYDOWN && msg->wParam == VK_TAB) return 0;
+ if (msg->message == WM_CHAR && msg->wParam == '\t') return 0;
+ }
+ return DLGC_WANTMESSAGE;
+ case WM_KILLFOCUS:
+ pcli->pfnEndRename(GetParent(hwnd),(struct ClcData*)GetWindowLongPtr(hwnd,GWLP_USERDATA),1);
+ SendMessage(pcli->hwndContactTree,WM_SIZE,0,0);
+ return 0;
+ }
+ return CallWindowProc(OldRenameEditWndProc,hwnd,msg,wParam,lParam);
+}
+
+void cliBeginRenameSelection(HWND hwnd,struct ClcData *dat)
+{
+ struct ClcContact *contact;
+ struct ClcGroup *group;
+ int indent,x,y,subident, h,w;
+ RECT clRect;
+ RECT r;
+
+
+ KillTimer(hwnd,TIMERID_RENAME);
+ ReleaseCapture();
+ dat->iHotTrack = -1;
+ dat->selection = cliGetRowByIndex(dat,dat->selection,&contact,&group);
+ if (dat->selection == -1) return;
+ if (contact->type != CLCIT_CONTACT && contact->type != CLCIT_GROUP) return;
+
+ if (contact->type == CLCIT_CONTACT && contact->isSubcontact)
+ subident = dat->subIndent;
+ else
+ subident = 0;
+
+ for (indent = 0;group->parent;indent++,group = group->parent);
+ GetClientRect(hwnd,&clRect);
+ x = indent*dat->groupIndent+dat->iconXSpace-2+subident;
+ w = clRect.right-x;
+ y = cliGetRowTopY(dat, dat->selection)-dat->yScroll;
+ h = dat->row_heights[dat->selection];
+ {
+ int i;
+ for (i=0; i <= FONTID_MODERN_MAX; i++)
+ if (h < dat->fontModernInfo[i].fontHeight+4) h = dat->fontModernInfo[i].fontHeight+4;
+ }
+ //TODO contact->pos_label
+
+
+ {
+
+ RECT rectW;
+ int h2;
+ GetWindowRect(hwnd,&rectW);
+ // w = contact->pos_full_first_row.right-contact->pos_full_first_row.left;
+ // h = contact->pos_full_first_row.bottom-contact->pos_full_first_row.top;
+ //w = clRect.right-x;
+ //w = clRect.right-x;
+ //x += rectW.left;//+contact->pos_full_first_row.left;
+ //y += rectW.top;//+contact->pos_full_first_row.top;
+ x = contact->pos_rename_rect.left+rectW.left;
+ y = contact->pos_label.top+rectW.top;
+ w = contact->pos_rename_rect.right-contact->pos_rename_rect.left;
+ h2 = contact->pos_label.bottom-contact->pos_label.top+4;
+ h = h2;//max(h,h2);
+
+ }
+
+ {
+ int a = 0;
+ if (contact->type == CLCIT_GROUP)
+ {
+ if (dat->row_align_group_mode == 1) a |= ES_CENTER;
+ else if (dat->row_align_group_mode == 2) a |= ES_RIGHT;
+ }
+ if (dat->text_rtl) a |= EN_ALIGN_RTL_EC;
+ if (contact->type == CLCIT_GROUP)
+ dat->hwndRenameEdit = CreateWindow(_T("EDIT"),contact->szText,WS_POPUP|WS_BORDER|ES_AUTOHSCROLL|a,x,y,w,h,hwnd,NULL,g_hInst,NULL);
+ else
+ dat->hwndRenameEdit = CreateWindow(_T("EDIT"),pcli->pfnGetContactDisplayName(contact->hContact,0),WS_POPUP|WS_BORDER|ES_AUTOHSCROLL|a,x,y,w,h,hwnd,NULL,g_hInst,NULL);
+ }
+ SetWindowLongPtr(dat->hwndRenameEdit,GWL_STYLE,GetWindowLongPtr(dat->hwndRenameEdit,GWL_STYLE)&(~WS_CAPTION)|WS_BORDER);
+ SetWindowLongPtr(dat->hwndRenameEdit,GWLP_USERDATA,(LONG_PTR)dat);
+ OldRenameEditWndProc = (WNDPROC)SetWindowLongPtr(dat->hwndRenameEdit,GWLP_WNDPROC,(LONG_PTR)RenameEditSubclassProc);
+ SendMessage(dat->hwndRenameEdit,WM_SETFONT,(WPARAM)(contact->type == CLCIT_GROUP?dat->fontModernInfo[FONTID_OPENGROUPS].hFont:dat->fontModernInfo[FONTID_CONTACTS].hFont),0);
+ SendMessage(dat->hwndRenameEdit,EM_SETMARGINS,EC_LEFTMARGIN|EC_RIGHTMARGIN|EC_USEFONTINFO,0);
+ SendMessage(dat->hwndRenameEdit,EM_SETSEL,0,(LPARAM)(-1));
+ // SetWindowLongPtr(dat->hwndRenameEdit,GWLP_USERDATA,(LONG_PTR)hwnd);
+ r.top = 1;
+ r.bottom = h-1;
+ r.left = 0;
+ r.right = w;
+
+ //ES_MULTILINE
+
+ SendMessage(dat->hwndRenameEdit,EM_SETRECT,0,(LPARAM)(&r));
+
+ CLUI_ShowWindowMod(dat->hwndRenameEdit,SW_SHOW);
+ SetWindowPos(dat->hwndRenameEdit,HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
+ SetFocus(dat->hwndRenameEdit);
+}
+
+int GetDropTargetInformation(HWND hwnd,struct ClcData *dat,POINT pt)
+{
+ RECT clRect;
+ int hit;
+ struct ClcContact *contact = NULL,*movecontact = NULL;
+ struct ClcGroup *group,*movegroup;
+ DWORD hitFlags;
+ int nSetSelection = -1;
+
+ GetClientRect(hwnd,&clRect);
+ dat->selection = dat->iDragItem;
+ dat->iInsertionMark = -1;
+ dat->nInsertionLevel = 0;
+ if ( !PtInRect(&clRect,pt)) return DROPTARGET_OUTSIDE;
+
+ hit = cliHitTest(hwnd,dat,pt.x,pt.y,&contact,&group,&hitFlags);
+ cliGetRowByIndex(dat,dat->iDragItem,&movecontact,&movegroup);
+ if (hit == dat->iDragItem) return DROPTARGET_ONSELF;
+ if (hit == -1 || hitFlags&CLCHT_ONITEMEXTRA || !movecontact) return DROPTARGET_ONNOTHING;
+
+ if (movecontact->type == CLCIT_GROUP) {
+ struct ClcContact *bottomcontact = NULL,*topcontact = NULL;
+ struct ClcGroup *topgroup = NULL, *bottomgroup = NULL;
+ int topItem = -1,bottomItem = -1;
+ int ok = 0;
+ if (pt.y+dat->yScroll < cliGetRowTopY(dat,hit)+dat->insertionMarkHitHeight || contact->type != CLCIT_GROUP) {
+ //could be insertion mark (above)
+ topItem = hit-1; bottomItem = hit;
+ bottomcontact = contact;
+ bottomgroup = group;
+ topItem = cliGetRowByIndex(dat,topItem,&topcontact,&topgroup);
+ ok = 1;
+ } else if ((pt.y+dat->yScroll >= cliGetRowTopY(dat,hit+1)-dat->insertionMarkHitHeight)
+ || (contact->type == CLCIT_GROUP && contact->group->expanded && contact->group->cl.count>0))
+ {
+ //could be insertion mark (below)
+ topItem = hit; bottomItem = hit+1;
+ topcontact = contact; topgroup = group;
+ bottomItem = cliGetRowByIndex(dat,bottomItem,&bottomcontact,&bottomgroup);
+ ok = 1;
+ }
+ if (ok)
+ {
+ if (bottomItem == -1 && contact->type == CLCIT_GROUP)
+ {
+ bottomItem = topItem+1;
+ }
+ else
+ {
+ if (bottomItem == -1 && contact->type != CLCIT_GROUP && contact->groupId == 0)
+ {
+ if (contact->type != CLCIT_GROUP && contact->groupId == 0)
+ {
+ bottomItem = topItem;
+ cliGetRowByIndex(dat,bottomItem,&bottomcontact,&bottomgroup);
+ }
+ }
+ if (bottomItem != -1 && bottomcontact->type != CLCIT_GROUP)
+ {
+ struct ClcGroup * gr = bottomgroup;
+ do
+ {
+ bottomItem = cliGetRowByIndex(dat,bottomItem-1,&bottomcontact,&bottomgroup);}
+ while (bottomItem >= 0 && bottomcontact->type != CLCIT_GROUP && bottomgroup == gr);
+ nSetSelection = bottomItem;
+ bottomItem = cliGetRowByIndex(dat,bottomItem+1,&bottomcontact,&bottomgroup);
+ }
+ }
+
+ if (bottomItem == -1) bottomItem = topItem+1;
+ {
+ int bi = cliGetRowByIndex(dat,bottomItem,&bottomcontact,&bottomgroup);
+ if (bi != -1)
+ {
+ group = bottomgroup;
+ if (bottomcontact == movecontact || group == movecontact->group) return DROPTARGET_ONSELF;
+ dat->nInsertionLevel = -1; // decreasing here
+ for (;group;group = group->parent)
+ {
+ dat->nInsertionLevel++;
+ if (group == movecontact->group) return DROPTARGET_ONSELF;
+ }
+ }
+ }
+ dat->iInsertionMark = bottomItem;
+ dat->selection = nSetSelection;
+ return DROPTARGET_INSERTION;
+ }
+ }
+ if (contact->type == CLCIT_GROUP)
+ {
+ if (dat->iInsertionMark == -1)
+ {
+ if (movecontact->type == CLCIT_GROUP)
+ { //check not moving onto its own subgroup
+ dat->iInsertionMark = hit+1;
+ for (;group;group = group->parent)
+ {
+ dat->nInsertionLevel++;
+ if (group == movecontact->group) return DROPTARGET_ONSELF;
+ }
+ }
+ dat->selection = hit;
+ return DROPTARGET_ONGROUP;
+ }
+ }
+ dat->selection = hit;
+
+ if (g_szMetaModuleName && !mir_strcmp(contact->proto,g_szMetaModuleName) && (ServiceExists(MS_MC_ADDTOMETA))) return DROPTARGET_ONMETACONTACT;
+ if (contact->isSubcontact && (ServiceExists(MS_MC_ADDTOMETA))) return DROPTARGET_ONSUBCONTACT;
+ return DROPTARGET_ONCONTACT;
+}
+COLORREF sttGetColor(char * module, char * color, COLORREF defColor)
+{
+ BOOL useWinColor = db_get_b(NULL, module, "UseWinColours",CLCDEFAULT_USEWINDOWSCOLOURS);
+ if (useWinColor) return defColor;
+ else return db_get_dw(NULL, module, color, defColor);
+}
+void RegisterCLUIFonts( void );
+void LoadCLCFonts( HWND hwnd, struct ClcData *dat )
+{
+ RegisterCLUIFonts();
+
+ HDC hdc = GetDC(hwnd);
+ HFONT holdfont = (HFONT)GetCurrentObject( hdc, OBJ_FONT );
+
+ for ( int i=0 ; i <= FONTID_MODERN_MAX; i++ )
+ {
+ if ( !dat->fontModernInfo[i].changed && dat->fontModernInfo[i].hFont )
+ {
+ DeleteObject(dat->fontModernInfo[i].hFont);
+ }
+ LOGFONT lf;
+
+ // Issue 40: Do not reload font colors for embedded clists
+ // Parent window is responsible to re-set fonts colors if needed
+ GetFontSetting( i, &lf, dat->force_in_dialog ? NULL: &dat->fontModernInfo[i].colour, &dat->fontModernInfo[i].effect, &dat->fontModernInfo[i].effectColour1, &dat->fontModernInfo[i].effectColour2 );
+ dat->fontModernInfo[i].hFont = CreateFontIndirect( &lf );
+ dat->fontModernInfo[i].changed = 0;
+
+ SelectObject( hdc, dat->fontModernInfo[i].hFont );
+ SIZE fontSize;
+ GetTextExtentPoint32A( hdc, "x", 1, &fontSize );
+ dat->fontModernInfo[i].fontHeight = fontSize.cy;
+ }
+ SelectObject( hdc, holdfont );
+ ReleaseDC( hwnd, hdc );
+}
+
+void LoadCLCOptions(HWND hwnd, struct ClcData *dat )
+{
+ int i;
+
+ g_CluiData.fDisableSkinEngine = db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT);
+
+ LoadCLCFonts( hwnd, dat );
+
+ g_CluiData.bSortByOrder[0] = db_get_b(NULL,"CList","SortBy1",SETTING_SORTBY1_DEFAULT);
+ g_CluiData.bSortByOrder[1] = db_get_b(NULL,"CList","SortBy2",SETTING_SORTBY2_DEFAULT);
+ g_CluiData.bSortByOrder[2] = db_get_b(NULL,"CList","SortBy3",SETTING_SORTBY3_DEFAULT);
+ g_CluiData.fSortNoOfflineBottom = db_get_b(NULL,"CList","NoOfflineBottom",SETTING_NOOFFLINEBOTTOM_DEFAULT);
+
+ // Row
+ dat->row_min_heigh = db_get_w(NULL,"CList","MinRowHeight",CLCDEFAULT_ROWHEIGHT);
+ dat->row_border = db_get_w(NULL,"CList","RowBorder",SETTING_ROWBORDER_DEFAULT);
+ dat->row_before_group_space = ((hwnd != pcli->hwndContactTree && pcli->hwndContactTree != NULL)
+ || !db_get_b(NULL,"ModernData","UseAdvancedRowLayout",SETTING_ROW_ADVANCEDLAYOUT_DEFAULT))?0:db_get_w(NULL,"ModernSkin","SpaceBeforeGroup",SKIN_SPACEBEFOREGROUP_DEFAULT);
+ dat->row_variable_height = db_get_b(NULL,"CList","VariableRowHeight",SETTING_VARIABLEROWHEIGHT_DEFAULT);
+ dat->row_align_left_items_to_left = db_get_b(NULL,"CList","AlignLeftItemsToLeft",SETTING_ALIGNLEFTTOLEFT_DEFAULT);
+ dat->row_hide_group_icon = db_get_b(NULL,"CList","HideGroupsIcon",SETTING_HIDEGROUPSICON_DEFAULT);
+ dat->row_align_right_items_to_right = db_get_b(NULL,"CList","AlignRightItemsToRight",SETTING_ALIGNRIGHTORIGHT_DEFAULT);
+ //TODO: Add to settings
+ dat->row_align_group_mode = db_get_b(NULL,"CList","AlignGroupCaptions",SETTING_ALIGNGROPCAPTION_DEFAULT);
+ if (pcli->hwndContactTree == NULL || dat->hWnd == pcli->hwndContactTree)
+ {
+
+ int defItemsOrder[NUM_ITEM_TYPE] = SETTINS_ROWITEMORDER_DEFAULT;
+ for (i=0 ; i < NUM_ITEM_TYPE ; i++)
+ {
+ char tmp[128];
+ mir_snprintf(tmp, SIZEOF(tmp), "RowPos%d", i);
+ dat->row_items[i] = db_get_w(NULL, "CList", tmp, defItemsOrder[i]);
+ }
+ }
+ else
+ {
+ int defItems[] = {ITEM_ICON, ITEM_TEXT, ITEM_EXTRA_ICONS,};
+ for (i=0 ; i < NUM_ITEM_TYPE; i++)
+ dat->row_items[i] = (i < SIZEOF(defItems)) ? defItems[i] : -1;
+ }
+
+ // Avatar
+ if (pcli->hwndContactTree == hwnd || pcli->hwndContactTree == NULL)
+ {
+ dat->avatars_show = db_get_b(NULL,"CList","AvatarsShow",SETTINGS_SHOWAVATARS_DEFAULT);
+ dat->avatars_draw_border = db_get_b(NULL,"CList","AvatarsDrawBorders",SETTINGS_AVATARDRAWBORDER_DEFAULT);
+ dat->avatars_border_color = (COLORREF)db_get_dw(NULL,"CList","AvatarsBorderColor",SETTINGS_AVATARBORDERCOLOR_DEFAULT);
+ dat->avatars_round_corners = db_get_b(NULL,"CList","AvatarsRoundCorners",SETTINGS_AVATARROUNDCORNERS_DEFAULT);
+ dat->avatars_use_custom_corner_size = db_get_b(NULL,"CList","AvatarsUseCustomCornerSize",SETTINGS_AVATARUSECUTOMCORNERSIZE_DEFAULT);
+ dat->avatars_custom_corner_size = db_get_w(NULL,"CList","AvatarsCustomCornerSize",SETTINGS_AVATARCORNERSIZE_DEFAULT);
+ dat->avatars_ignore_size_for_row_height = db_get_b(NULL,"CList","AvatarsIgnoreSizeForRow",SETTINGS_AVATARIGNORESIZEFORROW_DEFAULT);
+ dat->avatars_draw_overlay = db_get_b(NULL,"CList","AvatarsDrawOverlay",SETTINGS_AVATARDRAWOVERLAY_DEFAULT);
+ dat->avatars_overlay_type = db_get_b(NULL,"CList","AvatarsOverlayType",SETTINGS_AVATAROVERLAYTYPE_DEFAULT);
+ dat->avatars_maxheight_size = db_get_w(NULL,"CList","AvatarsSize",SETTING_AVATARHEIGHT_DEFAULT);
+ dat->avatars_maxwidth_size = db_get_w(NULL,"CList","AvatarsWidth",SETTING_AVATARWIDTH_DEFAULT);
+ }
+ else
+ {
+ dat->avatars_show = 0;
+ dat->avatars_draw_border = 0;
+ dat->avatars_border_color = 0;
+ dat->avatars_round_corners = 0;
+ dat->avatars_use_custom_corner_size = 0;
+ dat->avatars_custom_corner_size = 4;
+ dat->avatars_ignore_size_for_row_height = 0;
+ dat->avatars_draw_overlay = 0;
+ dat->avatars_overlay_type = SETTING_AVATAR_OVERLAY_TYPE_NORMAL;
+ dat->avatars_maxheight_size = 30;
+ dat->avatars_maxwidth_size = 0;
+ }
+
+ // Icon
+ if (pcli->hwndContactTree == hwnd || pcli->hwndContactTree == NULL)
+ {
+ dat->icon_hide_on_avatar = db_get_b(NULL,"CList","IconHideOnAvatar",SETTING_HIDEICONONAVATAR_DEFAULT);
+ dat->icon_draw_on_avatar_space = db_get_b(NULL,"CList","IconDrawOnAvatarSpace",SETTING_ICONONAVATARPLACE_DEFAULT);
+ dat->icon_ignore_size_for_row_height = db_get_b(NULL,"CList","IconIgnoreSizeForRownHeight",SETTING_ICONIGNORESIZE_DEFAULT);
+ }
+ else
+ {
+ dat->icon_hide_on_avatar = 0;
+ dat->icon_draw_on_avatar_space = 0;
+ dat->icon_ignore_size_for_row_height = 0;
+ }
+
+ // Contact time
+ if (pcli->hwndContactTree == hwnd || pcli->hwndContactTree == NULL)
+ {
+ dat->contact_time_show = db_get_b(NULL,"CList","ContactTimeShow",SETTING_SHOWTIME_DEFAULT);
+ dat->contact_time_show_only_if_different = db_get_b(NULL,"CList","ContactTimeShowOnlyIfDifferent",SETTING_SHOWTIMEIFDIFF_DEFAULT);
+ }
+ else
+ {
+ dat->contact_time_show = 0;
+ dat->contact_time_show_only_if_different = 0;
+ }
+
+ // Text
+ dat->text_rtl = db_get_b(NULL,"CList","TextRTL",SETTING_TEXT_RTL_DEFAULT);
+ dat->text_align_right = db_get_b(NULL,"CList","TextAlignToRight",SETTING_TEXT_RIGHTALIGN_DEFAULT);
+ dat->text_replace_smileys = db_get_b(NULL,"CList","TextReplaceSmileys",SETTING_TEXT_SMILEY_DEFAULT);
+ dat->text_resize_smileys = db_get_b(NULL,"CList","TextResizeSmileys",SETTING_TEXT_RESIZESMILEY_DEFAULT);
+ dat->text_smiley_height = 0;
+ dat->text_use_protocol_smileys = db_get_b(NULL,"CList","TextUseProtocolSmileys",SETTING_TEXT_PROTOSMILEY_DEFAULT);
+
+ if (pcli->hwndContactTree == hwnd || pcli->hwndContactTree == NULL)
+ {
+ dat->text_ignore_size_for_row_height = db_get_b(NULL,"CList","TextIgnoreSizeForRownHeight",SETTING_TEXT_IGNORESIZE_DEFAULT);
+ }
+ else
+ {
+ dat->text_ignore_size_for_row_height = 0;
+ }
+
+ // First line
+ dat->first_line_draw_smileys = db_get_b(NULL,"CList","FirstLineDrawSmileys",SETTING_FIRSTLINE_SMILEYS_DEFAULT);
+ dat->first_line_append_nick = db_get_b(NULL,"CList","FirstLineAppendNick",SETTING_FIRSTLINE_APPENDNICK_DEFAULT);
+ gl_TrimText = db_get_b(NULL,"CList","TrimText",SETTING_FIRSTLINE_TRIMTEXT_DEFAULT);
+
+ // Second line
+ if (pcli->hwndContactTree == hwnd || pcli->hwndContactTree == NULL)
+ {
+ dat->second_line_show = db_get_b(NULL,"CList","SecondLineShow",SETTING_SECONDLINE_SHOW_DEFAULT);
+ dat->second_line_top_space = db_get_w(NULL,"CList","SecondLineTopSpace",SETTING_SECONDLINE_TOPSPACE_DEFAULT);
+ dat->second_line_draw_smileys = db_get_b(NULL,"CList","SecondLineDrawSmileys",SETTING_SECONDLINE_SMILEYS_DEFAULT);
+ dat->second_line_type = db_get_w(NULL,"CList","SecondLineType",SETTING_SECONDLINE_TYPE_DEFAULT);
+ {
+ DBVARIANT dbv = {0};
+
+ if ( !DBGetContactSettingTString(NULL, "CList","SecondLineText", &dbv))
+ {
+ lstrcpyn(dat->second_line_text, dbv.ptszVal, SIZEOF(dat->second_line_text)-1);
+ dat->second_line_text[SIZEOF(dat->second_line_text)-1] = _T('\0');
+ db_free(&dbv);
+ }
+ else
+ {
+ dat->second_line_text[0] = _T('\0');
+ }
+ }
+ dat->second_line_xstatus_has_priority = db_get_b(NULL,"CList","SecondLineXStatusHasPriority",SETTING_SECONDLINE_XSTATUS_DEFAULT);
+ dat->second_line_show_status_if_no_away = db_get_b(NULL,"CList","SecondLineShowStatusIfNoAway",SETTING_SECONDLINE_STATUSIFNOAWAY_DEFAULT);
+ dat->second_line_show_listening_if_no_away = db_get_b(NULL,"CList","SecondLineShowListeningIfNoAway",SETTING_SECONDLINE_LISTENINGIFNOAWAY_DEFAULT);
+ dat->second_line_use_name_and_message_for_xstatus = db_get_b(NULL,"CList","SecondLineUseNameAndMessageForXStatus",SETTING_SECONDLINE_XSTATUSNAMETEXT_DEFAULT);
+ }
+ else
+ {
+ dat->second_line_show = 0;
+ dat->second_line_top_space = 0;
+ dat->second_line_draw_smileys = 0;
+ dat->second_line_type = 0;
+ dat->second_line_text[0] = _T('\0');
+ dat->second_line_xstatus_has_priority = 0;
+ dat->second_line_use_name_and_message_for_xstatus = 0;
+ }
+
+
+ // Third line
+ if (pcli->hwndContactTree == hwnd || pcli->hwndContactTree == NULL)
+ {
+ dat->third_line_show = db_get_b(NULL,"CList","ThirdLineShow",SETTING_THIRDLINE_SHOW_DEFAULT);
+ dat->third_line_top_space = db_get_w(NULL,"CList","ThirdLineTopSpace",SETTING_THIRDLINE_TOPSPACE_DEFAULT);
+ dat->third_line_draw_smileys = db_get_b(NULL,"CList","ThirdLineDrawSmileys",SETTING_THIRDLINE_SMILEYS_DEFAULT);
+ dat->third_line_type = db_get_w(NULL,"CList","ThirdLineType",SETTING_THIRDLINE_TYPE_DEFAULT);
+ {
+ DBVARIANT dbv = {0};
+
+ if ( !DBGetContactSettingTString(NULL, "CList","ThirdLineText", &dbv))
+ {
+ lstrcpyn(dat->third_line_text, dbv.ptszVal, SIZEOF(dat->third_line_text)-1);
+ dat->third_line_text[SIZEOF(dat->third_line_text)-1] = _T('\0');
+ db_free(&dbv);
+ }
+ else
+ {
+ dat->third_line_text[0] = _T('\0');
+ }
+ }
+ dat->third_line_xstatus_has_priority = db_get_b(NULL,"CList","ThirdLineXStatusHasPriority",SETTING_THIRDLINE_XSTATUS_DEFAULT);
+ dat->third_line_show_status_if_no_away = db_get_b(NULL,"CList","ThirdLineShowStatusIfNoAway",SETTING_THIRDLINE_STATUSIFNOAWAY_DEFAULT);
+ dat->third_line_show_listening_if_no_away = db_get_b(NULL,"CList","ThirdLineShowListeningIfNoAway",SETTING_THIRDLINE_LISTENINGIFNOAWAY_DEFAULT);
+ dat->third_line_use_name_and_message_for_xstatus = db_get_b(NULL,"CList","ThirdLineUseNameAndMessageForXStatus",SETTING_THIRDLINE_XSTATUSNAMETEXT_DEFAULT);
+ }
+ else
+ {
+ dat->third_line_show = 0;
+ dat->third_line_top_space = 0;
+ dat->third_line_draw_smileys = 0;
+ dat->third_line_type = TEXT_STATUS_MESSAGE;
+ dat->third_line_text[0] = _T('\0');
+ dat->third_line_xstatus_has_priority = 1;
+ dat->third_line_use_name_and_message_for_xstatus = 0;
+ }
+
+ dat->leftMargin = db_get_b(NULL,"CLC","LeftMargin",CLCDEFAULT_LEFTMARGIN);
+ dat->rightMargin = db_get_b(NULL,"CLC","RightMargin",CLCDEFAULT_RIGHTMARGIN);
+ dat->exStyle = db_get_dw(NULL,"CLC","ExStyle",GetDefaultExStyle());
+ dat->scrollTime = db_get_w(NULL,"CLC","ScrollTime",CLCDEFAULT_SCROLLTIME);
+ dat->force_in_dialog = (pcli->hwndContactTree)?(hwnd != pcli->hwndContactTree):0;
+ dat->groupIndent = db_get_b(NULL,"CLC","GroupIndent",CLCDEFAULT_GROUPINDENT);
+ dat->subIndent = db_get_b(NULL,"CLC","SubIndent",CLCDEFAULT_GROUPINDENT);
+ dat->gammaCorrection = db_get_b(NULL,"CLC","GammaCorrect",CLCDEFAULT_GAMMACORRECT);
+ dat->showIdle = db_get_b(NULL,"CLC","ShowIdle",CLCDEFAULT_SHOWIDLE);
+ dat->noVScrollbar = db_get_b(NULL,"CLC","NoVScrollBar",CLCDEFAULT_NOVSCROLL);
+ SendMessage(hwnd,INTM_SCROLLBARCHANGED,0,0);
+
+ if (dat->hBmpBackground) {DeleteObject(dat->hBmpBackground); dat->hBmpBackground = NULL;}
+ if (dat->hMenuBackground) {DeleteObject(dat->hMenuBackground); dat->hMenuBackground = NULL;}
+
+ dat->useWindowsColours = db_get_b(NULL, "CLC", "UseWinColours", CLCDEFAULT_USEWINDOWSCOLOURS);
+
+ if (g_CluiData.fDisableSkinEngine)
+ {
+ DBVARIANT dbv;
+ if ( !dat->bkChanged)
+ {
+ dat->bkColour = sttGetColor("CLC","BkColour",GetSysColor(COLOR_3DFACE));
+ {
+ if (db_get_b(NULL,"CLC","UseBitmap",CLCDEFAULT_USEBITMAP))
+ {
+ if ( !DBGetContactSettingString(NULL,"CLC","BkBitmap",&dbv))
+ {
+ dat->hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ }
+ }
+ dat->backgroundBmpUse = db_get_w(NULL,"CLC","BkBmpUse",CLCDEFAULT_BKBMPUSE);
+ }
+ dat->MenuBkColor = sttGetColor("Menu","BkColour",CLCDEFAULT_BKCOLOUR);
+ dat->MenuBkHiColor = sttGetColor("Menu","SelBkColour",CLCDEFAULT_SELBKCOLOUR);
+
+ dat->MenuTextColor = sttGetColor("Menu","TextColour",CLCDEFAULT_TEXTCOLOUR);
+ dat->MenuTextHiColor = sttGetColor("Menu","SelTextColour",CLCDEFAULT_MODERN_SELTEXTCOLOUR);
+
+ if (db_get_b(NULL,"Menu","UseBitmap",CLCDEFAULT_USEBITMAP)) {
+ if ( !DBGetContactSettingString(NULL,"Menu","BkBitmap",&dbv)) {
+ dat->hMenuBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ }
+ dat->MenuBmpUse = db_get_w(NULL,"Menu","BkBmpUse",CLCDEFAULT_BKBMPUSE);
+ }
+
+ dat->greyoutFlags = db_get_dw(NULL,"CLC","GreyoutFlags",CLCDEFAULT_GREYOUTFLAGS);
+ dat->offlineModes = db_get_dw(NULL,"CLC","OfflineModes",CLCDEFAULT_OFFLINEMODES);
+ dat->selBkColour = sttGetColor("CLC","SelBkColour",CLCDEFAULT_SELBKCOLOUR);
+ dat->selTextColour = db_get_dw(NULL,"CLC","SelTextColour",CLCDEFAULT_MODERN_SELTEXTCOLOUR);
+ dat->hotTextColour = db_get_dw(NULL,"CLC","HotTextColour",CLCDEFAULT_MODERN_HOTTEXTCOLOUR);
+ dat->quickSearchColour = db_get_dw(NULL,"CLC","QuickSearchColour",CLCDEFAULT_MODERN_QUICKSEARCHCOLOUR);
+ if ( !g_szMetaModuleName && ServiceExists(MS_MC_GETPROTOCOLNAME)) g_szMetaModuleName = (char *)CallService(MS_MC_GETPROTOCOLNAME, 0, 0);
+ dat->IsMetaContactsEnabled = (!(GetWindowLongPtr(hwnd,GWL_STYLE)&CLS_MANUALUPDATE)) &&
+ g_szMetaModuleName && db_get_b(NULL,g_szMetaModuleName,"Enabled",1) && ServiceExists(MS_MC_GETDEFAULTCONTACT);
+
+ if (pcli->hwndContactTree == NULL || dat->hWnd == pcli->hwndContactTree)
+ dat->MetaIgnoreEmptyExtra = db_get_b(NULL,"CLC","MetaIgnoreEmptyExtra",SETTING_METAIGNOREEMPTYEXTRA_DEFAULT);
+ else
+ dat->MetaIgnoreEmptyExtra = FALSE;
+
+ dat->expandMeta = db_get_b(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT);
+ dat->useMetaIcon = db_get_b(NULL,"CLC","Meta",SETTING_USEMETAICON_DEFAULT);
+
+ dat->drawOverlayedStatus = db_get_b(NULL,"CLC","DrawOverlayedStatus",SETTING_DRAWOVERLAYEDSTATUS_DEFAULT);
+
+ dat->dbbMetaHideExtra = db_get_b(NULL,"CLC","MetaHideExtra",SETTING_METAHIDEEXTRA_DEFAULT);
+ dat->dbbBlendInActiveState = db_get_b(NULL,"CLC","BlendInActiveState",SETTING_BLENDINACTIVESTATE_DEFAULT);
+ dat->dbbBlend25 = db_get_b(NULL,"CLC","Blend25%",SETTING_BLENDINACTIVESTATE_DEFAULT);
+ dat->bCompactMode = db_get_b(NULL,"CLC","CompactMode",SETTING_COMPACTMODE_DEFAULT);
+ if ((pcli->hwndContactTree == hwnd || pcli->hwndContactTree == NULL))
+ {
+ IvalidateDisplayNameCache(16);
+
+ }
+
+ {
+ NMHDR hdr;
+ hdr.code = CLN_OPTIONSCHANGED;
+ hdr.hwndFrom = hwnd;
+ hdr.idFrom = 0;//GetDlgCtrlID(hwnd);
+ SendMessage(GetParent(hwnd),WM_NOTIFY,0,(LPARAM)&hdr);
+ }
+ SendMessage(hwnd,WM_SIZE,0,0);
+
+}
+
+int ExpandMetaContact(HWND hwnd, struct ClcContact * contact, struct ClcData * dat, BOOL bExpand)
+{
+ struct ClcContact * ht = NULL;
+ KillTimer(hwnd,TIMERID_SUBEXPAND);
+ if (contact->type != CLCIT_CONTACT || contact->SubAllocated == 0 || contact->SubExpanded == bExpand || !db_get_b(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT)) return 0;
+ contact->SubExpanded = bExpand;
+ db_set_b(contact->hContact,"CList","Expanded",contact->SubExpanded);
+ dat->NeedResort = 1;
+ pcli->pfnSortCLC(hwnd,dat,1);
+ cliRecalcScrollBar(hwnd,dat);
+ return contact->SubExpanded;
+}
+
+int cliFindRowByText(HWND hwnd, struct ClcData *dat, const TCHAR *text, int prefixOk)
+{
+ struct ClcGroup *group = &dat->list;
+ int testlen = lstrlen(text);
+ struct ClcContact *contact = NULL;
+ int SubCount = 0;
+
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL)
+ break;
+ group->scanIndex++;
+ continue;
+ }
+ contact = group->cl.items[group->scanIndex];
+ if (contact->type != CLCIT_DIVIDER)
+ {
+ if ((prefixOk && !_tcsnicmp(text, contact->szText, testlen)) ||
+ (!prefixOk && !lstrcmpi(text, contact->szText)))
+ {
+ struct ClcGroup *contactGroup = group;
+ int contactScanIndex = group->scanIndex;
+ for (; group; group = group->parent)
+ pcli->pfnSetGroupExpand(hwnd, dat, group, 1);
+ return pcli->pfnGetRowsPriorTo(&dat->list, contactGroup, contactScanIndex+SubCount);
+ }
+ if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP)
+ {
+ if ( !(dat->exStyle & CLS_EX_QUICKSEARCHVISONLY) || group->cl.items[group->scanIndex]->group->expanded) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ SubCount = 0;
+ continue;
+ }
+ }
+ }
+ if (contact->type == CLCIT_CONTACT && contact->SubAllocated)
+ {
+ if ( !(dat->exStyle & CLS_EX_QUICKSEARCHVISONLY) || contact->SubExpanded )
+ {
+ int i=0;
+ for (i=0; i < contact->SubAllocated; i++)
+ {
+ struct ClcContact * subcontact = &(contact->subcontacts[i]);
+ if ((prefixOk && !_tcsnicmp(text, subcontact->szText, testlen)) ||
+ (!prefixOk && !lstrcmpi(text, subcontact->szText)))
+ {
+ struct ClcGroup *contactGroup = group;
+ int contactScanIndex = group->scanIndex;
+ for (; group; group = group->parent)
+ pcli->pfnSetGroupExpand(hwnd, dat, group, 1);
+ if ( !contact->SubExpanded)
+ ExpandMetaContact(hwnd, contact, dat, 1 );
+ return pcli->pfnGetRowsPriorTo(&dat->list, contactGroup, contactScanIndex+SubCount+i+1);
+ }
+ }
+ }
+ }
+ if (contact->type == CLCIT_CONTACT && contact->SubAllocated && contact->SubExpanded)
+ SubCount += contact->SubAllocated;
+ group->scanIndex++;
+ }
+ return -1;
+} \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_clistevents.cpp b/plugins/Clist_modern/src/modern_clistevents.cpp
new file mode 100644
index 0000000000..4453329c66
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clistevents.cpp
@@ -0,0 +1,624 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2003 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "./hdr/modern_cluiframes.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_clcpaint.h"
+
+/**************************************************/
+/* Notify Event Area Frame implementation */
+/**************************************************/
+
+/* Declarations */
+static HANDLE hNotifyFrame = NULL;
+static int EventArea_PaintCallbackProc(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData);
+static int EventArea_Draw(HWND hwnd, HDC hDC);
+static int EventArea_DrawWorker(HWND hwnd, HDC hDC);
+static void EventArea_HideShowNotifyFrame();
+static LRESULT CALLBACK EventArea_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+int EventArea_Create(HWND hCluiWnd);
+int EventArea_UnloadModule();
+void EventArea_ConfigureEventArea();
+
+/**************************************************/
+
+HWND g_hwndEventArea = 0;
+
+struct CListEvent {
+ int imlIconIndex;
+ int flashesDone;
+ CLISTEVENT cle;
+
+ int menuId;
+ int imlIconOverlayIndex;
+};
+
+static struct CListEvent *event;
+static int eventCount;
+static int disableTrayFlash;
+static int disableIconFlash;
+
+
+struct CListImlIcon {
+ int index;
+ HICON hIcon;
+};
+
+static struct CListImlIcon *imlIcon;
+static int imlIconCount;
+static UINT flashTimerId;
+static int iconsOn;
+
+
+struct NotifyMenuItemExData {
+ HANDLE hContact;
+ int iIcon; // icon index in the image list
+ HICON hIcon; // corresponding icon handle
+ HANDLE hDbEvent;
+};
+
+static CLISTEVENT* MyGetEvent(int iSelection)
+{
+ int i;
+
+ for (i=0; i < pcli->events.count; i++) {
+ struct CListEvent* p = pcli->events.items[i];
+ if (p->menuId == iSelection)
+ return &p->cle;
+ }
+ return NULL;
+}
+
+
+CListEvent* cliCreateEvent( void )
+{
+ CListEvent *p = (CListEvent *)mir_calloc(sizeof(CListEvent));
+ return p;
+}
+
+struct CListEvent* cli_AddEvent(CLISTEVENT *cle)
+{
+ struct CListEvent* p = corecli.pfnAddEvent(cle);
+ if ( p == NULL )
+ return NULL;
+
+ if (1) {
+ if (p->cle.hContact != 0 && p->cle.hDbEvent != (HANDLE) 1 && !(p->cle.flags & CLEF_ONLYAFEW)) {
+ int j;
+ struct NotifyMenuItemExData *nmi = 0;
+ char *szProto;
+ TCHAR *szName;
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA | MIIM_BITMAP | MIIM_ID;
+ if (p->cle.pszService && ( !strncmp("SRMsg/ReadMessage", p->cle.pszService, SIZEOF("SRMsg/ReadMessage"))
+ || !strncmp("GChat/DblClickEvent", p->cle.pszService, SIZEOF("GChat/DblClickEvent"))))
+
+ {
+ // dup check only for msg events
+ for (j = 0; j < GetMenuItemCount(g_CluiData.hMenuNotify); j++) {
+ if (GetMenuItemInfo(g_CluiData.hMenuNotify, j, TRUE, &mii) != 0) {
+ nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
+ if (nmi != 0 && (HANDLE) nmi->hContact == (HANDLE) p->cle.hContact && nmi->iIcon == p->imlIconIndex)
+ return p;
+ } } }
+
+ szProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) p->cle.hContact, 0);
+ szName = pcli->pfnGetContactDisplayName(p->cle.hContact, 0);
+ if (szProto && szName) {
+ nmi = (struct NotifyMenuItemExData *) malloc(sizeof(struct NotifyMenuItemExData));
+ if (nmi) {
+ TCHAR szBuffer[128];
+ TCHAR* szStatus = pcli->pfnGetStatusModeDescription(db_get_w(p->cle.hContact, szProto, "Status", ID_STATUS_OFFLINE), 0);
+ TCHAR szwProto[64];
+ MultiByteToWideChar(CP_ACP, 0, szProto, -1, szwProto, 64);
+ szwProto[63] = 0;
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s: %s (%s)"), szwProto, szName, szStatus);
+ szBuffer[127] = 0;
+ AppendMenu(g_CluiData.hMenuNotify, MF_BYCOMMAND | MF_STRING, g_CluiData.wNextMenuID, szBuffer);
+ mii.hbmpItem = HBMMENU_CALLBACK;
+ nmi->hContact = p->cle.hContact;
+ nmi->iIcon = p->imlIconIndex;
+ nmi->hIcon = p->cle.hIcon;
+ nmi->hDbEvent = p->cle.hDbEvent;
+ mii.dwItemData = (ULONG_PTR) nmi;
+ mii.wID = g_CluiData.wNextMenuID;
+ SetMenuItemInfo(g_CluiData.hMenuNotify, g_CluiData.wNextMenuID, FALSE, &mii);
+ p-> menuId = g_CluiData.wNextMenuID;
+ g_CluiData.wNextMenuID++;
+ if (g_CluiData.wNextMenuID > 0x7fff)
+ g_CluiData.wNextMenuID = 1;
+ g_CluiData.iIconNotify = p->imlIconIndex;
+ }
+ }
+ }
+
+ else if (p->cle.hContact != 0 && (p->cle.flags & CLEF_ONLYAFEW))
+ {
+ g_CluiData.iIconNotify = p->imlIconIndex;
+ g_CluiData.hUpdateContact = p->cle.hContact;
+ }
+ if (pcli->events.count > 0) {
+ g_CluiData.bEventAreaEnabled = TRUE;
+ if (g_CluiData.bNotifyActive == FALSE) {
+ g_CluiData.bNotifyActive = TRUE;
+ EventArea_HideShowNotifyFrame();
+ }
+ }
+ CLUI__cliInvalidateRect(g_CluiData.hwndEventFrame, NULL, FALSE);
+ }
+
+ return p;
+}
+
+
+int cli_RemoveEvent(HANDLE hContact, HANDLE hDbEvent)
+{
+ int i;
+ int res = 0;
+
+ // Find the event that should be removed
+ for (i=0; i < pcli->events.count; i++)
+ {
+ if ((pcli->events.items[i]->cle.hContact == hContact) && (pcli->events.items[i]->cle.hDbEvent == hDbEvent))
+ {
+ break;
+ }
+ }
+
+ // Event was not found
+ if (i == pcli->events.count)
+ return 1;
+
+ // remove event from the notify menu
+ if (1)
+ {
+ if (pcli->events.items[i]->menuId > 0)
+ {
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA;
+ if (GetMenuItemInfo(g_CluiData.hMenuNotify, pcli->events.items[i]->menuId, FALSE, &mii) != 0)
+ {
+ struct NotifyMenuItemExData *nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
+ if (nmi && nmi->hContact == hContact && nmi->hDbEvent == hDbEvent)
+ {
+ free(nmi);
+ DeleteMenu(g_CluiData.hMenuNotify, pcli->events.items[i]->menuId, MF_BYCOMMAND);
+ }
+ }
+ }
+ }
+
+ res = corecli.pfnRemoveEvent(hContact, hDbEvent);
+
+ if (pcli->events.count == 0)
+ {
+ g_CluiData.bNotifyActive = FALSE;
+ EventArea_HideShowNotifyFrame();
+ }
+
+ if (hContact == g_CluiData.hUpdateContact || (INT_PTR)hDbEvent == 1)
+ g_CluiData.hUpdateContact = 0;
+ CLUI__cliInvalidateRect(g_CluiData.hwndEventFrame, NULL, FALSE);
+ return res;
+}
+
+
+/* Implementations */
+
+struct event_area_t
+{
+ HBITMAP hBmpBackground;
+ COLORREF bkColour;
+ int useWinColors;
+ int backgroundBmpUse;
+
+ event_area_t():
+ hBmpBackground( NULL),
+ bkColour( CLCDEFAULT_BKCOLOUR ),
+ useWinColors( CLCDEFAULT_USEWINDOWSCOLOURS ),
+ backgroundBmpUse( CLCDEFAULT_USEBITMAP )
+ {}
+};
+
+static event_area_t event_area;
+
+static BOOL sttDrawEventAreaBackground(HWND hwnd, HDC hdc, RECT * rect)
+{
+ BOOL bFloat = (GetParent(hwnd) != pcli->hwndContactList);
+ if (g_CluiData.fDisableSkinEngine || !g_CluiData.fLayered || bFloat)
+ {
+ RECT rc;
+
+ if (rect) rc = *rect;
+ else GetClientRect(hwnd,&rc);
+
+ if ( !event_area.hBmpBackground && !event_area.useWinColors)
+ {
+ HBRUSH hbr = CreateSolidBrush(event_area.bkColour);
+ FillRect(hdc, &rc, hbr);
+ DeleteObject(hbr);
+ }
+ else
+ {
+ DrawBackGround(hwnd,hdc,event_area.hBmpBackground,event_area.bkColour,event_area.backgroundBmpUse);
+ }
+ }
+ return TRUE;
+}
+
+COLORREF sttGetColor(char * module, char * color, COLORREF defColor); //clcutils
+
+static int ehhEventAreaBackgroundSettingsChanged(WPARAM wParam, LPARAM lParam)
+{
+ if (event_area.hBmpBackground)
+ {
+ DeleteObject(event_area.hBmpBackground);
+ event_area.hBmpBackground = NULL;
+ }
+ if (g_CluiData.fDisableSkinEngine)
+ {
+ DBVARIANT dbv;
+ event_area.bkColour = sttGetColor("EventArea","BkColour",CLCDEFAULT_BKCOLOUR);
+ if (db_get_b(NULL,"EventArea","UseBitmap",CLCDEFAULT_USEBITMAP)) {
+ if ( !DBGetContactSettingString(NULL,"EventArea","BkBitmap",&dbv)) {
+ event_area.hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ }
+ event_area.useWinColors = db_get_b(NULL, "EventArea", "UseWinColours", CLCDEFAULT_USEWINDOWSCOLOURS);
+ event_area.backgroundBmpUse = db_get_w(NULL, "EventArea", "BkBmpUse", CLCDEFAULT_BKBMPUSE);
+ }
+ PostMessage(pcli->hwndContactList,WM_SIZE,0,0);
+ return 0;
+}
+
+void EventArea_ConfigureEventArea()
+{
+ int iCount = pcli->events.count;
+
+ g_CluiData.dwFlags &= ~(CLUI_FRAME_AUTOHIDENOTIFY|CLUI_FRAME_SHOWALWAYS);
+ if (db_get_b(NULL,"CLUI","EventArea",SETTING_EVENTAREAMODE_DEFAULT) == 1) g_CluiData.dwFlags |= CLUI_FRAME_AUTOHIDENOTIFY;
+ if (db_get_b(NULL,"CLUI","EventArea",SETTING_EVENTAREAMODE_DEFAULT) == 2) g_CluiData.dwFlags |= CLUI_FRAME_SHOWALWAYS;
+
+ if (g_CluiData.dwFlags & CLUI_FRAME_SHOWALWAYS)
+ g_CluiData.bNotifyActive = 1;
+ else if (g_CluiData.dwFlags & CLUI_FRAME_AUTOHIDENOTIFY)
+ g_CluiData.bNotifyActive = iCount > 0 ? 1 : 0;
+ else
+ g_CluiData.bNotifyActive = 0;
+
+ EventArea_HideShowNotifyFrame();
+}
+
+
+static int EventArea_PaintCallbackProc(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData)
+{
+ return EventArea_Draw(hWnd,hDC);
+}
+
+static int EventArea_Draw(HWND hwnd, HDC hDC)
+{
+ if (hwnd == (HWND)-1) return 0;
+ if (GetParent(hwnd) == pcli->hwndContactList)
+ return EventArea_DrawWorker(hwnd,hDC);
+ else
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ return 0;
+}
+
+static int EventArea_DrawWorker(HWND hWnd, HDC hDC)
+{
+ RECT rc;
+ HFONT hOldFont;
+ GetClientRect(hWnd,&rc);
+ if ( g_CluiData.fDisableSkinEngine )
+ {
+ sttDrawEventAreaBackground( hWnd, hDC, &rc );
+ }
+ else
+ {
+ SkinDrawGlyph(hDC,&rc,&rc,"Main,ID=EventArea");
+ }
+ hOldFont = g_clcPainter.ChangeToFont(hDC,NULL,FONTID_EVENTAREA,NULL);
+ SetBkMode(hDC,TRANSPARENT);
+ //ske_DrawText(hDC,_T("DEBUG"),lstrlen(_T("DEBUG")),&rc,0);
+ {
+ int iCount = GetMenuItemCount(g_CluiData.hMenuNotify);
+ rc.left += 26;
+ if (g_CluiData.hUpdateContact != 0)
+ {
+ TCHAR *szName = pcli->pfnGetContactDisplayName(g_CluiData.hUpdateContact, 0);
+ int iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) g_CluiData.hUpdateContact, 0);
+
+ ske_ImageList_DrawEx(g_himlCListClc, iIcon, hDC, rc.left, (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL);
+ rc.left += 18;
+ ske_DrawText(hDC, szName, -1, &rc, DT_VCENTER | DT_SINGLELINE);
+ ske_ImageList_DrawEx(g_himlCListClc, (int)g_CluiData.iIconNotify, hDC, 4, (rc.bottom + rc.top - 16) / 2, 16, 16, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ }
+ else if (iCount > 0)
+ {
+ MENUITEMINFO mii = {0};
+ struct NotifyMenuItemExData *nmi;
+ TCHAR *szName;
+ int iIcon;
+
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA;
+ GetMenuItemInfo(g_CluiData.hMenuNotify, iCount - 1, TRUE, &mii);
+ nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
+ szName = pcli->pfnGetContactDisplayName(nmi->hContact, 0);
+ iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) nmi->hContact, 0);
+ ske_ImageList_DrawEx(g_himlCListClc, iIcon, hDC, rc.left, (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL);
+ rc.left += 18;
+ ske_ImageList_DrawEx(g_himlCListClc, nmi->iIcon, hDC, 4, (rc.bottom + rc.top) / 2 - 8, 16, 16, CLR_NONE, CLR_NONE, ILD_NORMAL);
+ ske_DrawText(hDC, szName, -1, &rc, DT_VCENTER | DT_SINGLELINE);
+ }
+ else
+ {
+ HICON hIcon = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_BLANK), IMAGE_ICON, 16, 16, 0);
+ ske_DrawText(hDC, g_CluiData.szNoEvents, lstrlen(g_CluiData.szNoEvents), &rc, DT_VCENTER | DT_SINGLELINE);
+ ske_DrawIconEx(hDC, 4, (rc.bottom + rc.top - 16) / 2, hIcon, 16, 16, 0, 0, DI_NORMAL | DI_COMPAT);
+ DestroyIcon(hIcon);
+ }
+ }
+ ske_ResetTextEffect(hDC);
+ SelectObject(hDC,hOldFont);
+ return 0;
+}
+
+static void EventArea_HideShowNotifyFrame()
+{
+ int dwVisible = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, hNotifyFrame), 0) & F_VISIBLE;
+ int desired;
+
+ if (g_CluiData.dwFlags & CLUI_FRAME_SHOWALWAYS)
+ desired = TRUE;
+ else if (g_CluiData.dwFlags & CLUI_FRAME_AUTOHIDENOTIFY)
+ desired = g_CluiData.bNotifyActive ? TRUE : FALSE;
+ else
+ desired = FALSE;
+
+ if (desired)
+ {
+ if ( !dwVisible)
+ CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)hNotifyFrame, 0);
+ }
+ else
+ {
+ if (dwVisible)
+ CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)hNotifyFrame, 0);
+ }
+}
+
+
+int EventArea_Create(HWND hCluiWnd)
+{
+
+ CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"Event Area Background/EventArea",0);
+ HookEvent(ME_BACKGROUNDCONFIG_CHANGED,ehhEventAreaBackgroundSettingsChanged);
+ ehhEventAreaBackgroundSettingsChanged(0,0);
+
+ WNDCLASS wndclass = {0};
+ TCHAR pluginname[] = _T("EventArea");
+ int h = GetSystemMetrics(SM_CYSMICON)+2;
+ if (GetClassInfo(g_hInst,pluginname,&wndclass) == 0)
+ {
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = EventArea_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = pluginname;
+ RegisterClass(&wndclass);
+ }
+ g_CluiData.hwndEventFrame = CreateWindow(pluginname,pluginname,WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN,
+ 0,0,0,h,hCluiWnd,NULL,g_hInst,NULL);
+ // register frame
+
+ {
+ CLISTFrame Frame;
+ memset(&Frame,0,sizeof(Frame));
+ Frame.cbSize = sizeof(CLISTFrame);
+ Frame.hWnd = g_CluiData.hwndEventFrame;
+ Frame.align = alBottom;
+ Frame.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ Frame.Flags = (db_get_b(NULL,"CLUI","ShowEventArea",SETTING_SHOWEVENTAREAFRAME_DEFAULT)?F_VISIBLE:0)|F_LOCKED|F_NOBORDER|F_NO_SUBCONTAINER|F_TCHAR;
+ Frame.height = h;
+ Frame.tname = _T("EventArea"); //do not translate
+ Frame.TBtname = TranslateT("Event Area");
+ hNotifyFrame = (HANDLE)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&Frame,(LPARAM)0);
+ CallService(MS_SKINENG_REGISTERPAINTSUB,(WPARAM)Frame.hWnd,(LPARAM)EventArea_PaintCallbackProc); //$$$$$ register sub for frame
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME,-1,0);
+ EventArea_HideShowNotifyFrame();
+ }
+ g_CluiData.szNoEvents = TranslateT("No Events");
+ g_CluiData.hMenuNotify = CreatePopupMenu();
+ g_CluiData.wNextMenuID = 1;
+ EventArea_ConfigureEventArea();
+ return 0;
+}
+
+int EventArea_UnloadModule()
+{
+ // remove frame window
+ // remove all events data from menu
+ DestroyMenu( g_CluiData.hMenuNotify );
+ return 0;
+}
+
+#define IDC_NOTIFYBUTTON 1900
+static LRESULT CALLBACK EventArea_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg)
+ {
+ case WM_MEASUREITEM:
+ {
+ MEASUREITEMSTRUCT *lpi = (LPMEASUREITEMSTRUCT) lParam;
+ MENUITEMINFOA mii = {0};
+
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA | MIIM_ID;
+ if (GetMenuItemInfoA(g_CluiData.hMenuNotify, lpi->itemID, FALSE, &mii) != 0) {
+ if (mii.dwItemData == lpi->itemData)
+ {
+ lpi->itemWidth = 8 + 16;
+ lpi->itemHeight = 0;
+ return TRUE;
+ }
+ }
+ break;
+ }
+ case WM_DRAWITEM:
+ {
+ LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam;
+ if (dis->hwndItem == (HWND) g_CluiData.hMenuNotify)
+ {
+ MENUITEMINFOA mii = {0};
+
+ struct NotifyMenuItemExData *nmi = 0;
+ int iIcon;
+
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA;
+ if (GetMenuItemInfoA(g_CluiData.hMenuNotify, (UINT) dis->itemID, FALSE, &mii) != 0)
+ {
+ nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
+ if (nmi)
+ {
+ iIcon = CallService(MS_CLIST_GETCONTACTICON, (WPARAM) nmi->hContact, 0);
+ ske_ImageList_DrawEx(g_himlCListClc, nmi->iIcon, dis->hDC, 2, (dis->rcItem.bottom + dis->rcItem.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL);
+ ske_ImageList_DrawEx(g_himlCListClc, iIcon, dis->hDC, 2+GetSystemMetrics(SM_CXSMICON)+2, (dis->rcItem.bottom + dis->rcItem.top - GetSystemMetrics(SM_CYSMICON)) / 2, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), CLR_NONE, CLR_NONE, ILD_NORMAL);
+ return TRUE;
+ }
+ }
+ }
+ break;
+ }
+ case WM_LBUTTONUP:
+ if (g_CluiData.bEventAreaEnabled)
+ SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDC_NOTIFYBUTTON, 0), 0);
+ break;
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_NOTIFYBUTTON) {
+ int iSelection;
+ MENUITEMINFO mii = {0};
+ POINT pt;
+ struct NotifyMenuItemExData *nmi = 0;
+ int iCount = GetMenuItemCount(g_CluiData.hMenuNotify);
+ BOOL result;
+
+ GetCursorPos(&pt);
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_DATA;
+ if (iCount > 1)
+ iSelection = TrackPopupMenu(g_CluiData.hMenuNotify, TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL);
+ else
+ iSelection = GetMenuItemID(g_CluiData.hMenuNotify, 0);
+ result = GetMenuItemInfo(g_CluiData.hMenuNotify, (UINT) iSelection, FALSE, &mii);
+ if (result != 0) {
+ nmi = (struct NotifyMenuItemExData *) mii.dwItemData;
+ if (nmi) {
+ CLISTEVENT *cle = MyGetEvent(iSelection);
+ if (cle) {
+ CLISTEVENT *cle1 = NULL;
+ CallService(cle->pszService, (WPARAM) NULL, (LPARAM) cle);
+ // re-obtain the pointer, it may already be invalid/point to another event if the
+ // event we're interested in was removed by the service (nasty one...)
+ cle1 = MyGetEvent(iSelection);
+ if (cle1 != NULL)
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM) cle->hContact, (LPARAM) cle->hDbEvent);
+ }
+ }
+ }
+ break;
+ }
+ break;
+ case WM_SIZE:
+ if ( !g_CluiData.fLayered)InvalidateRect(hwnd,NULL,FALSE);
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ case WM_ERASEBKGND:
+ return 1;
+ case WM_PAINT:
+ {
+ if (GetParent(hwnd) == pcli->hwndContactList && g_CluiData.fLayered)
+ CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,(WPARAM)hwnd,0);
+ else if (GetParent(hwnd) == pcli->hwndContactList && !g_CluiData.fLayered)
+ {
+ HDC hdc, hdc2;
+ HBITMAP hbmp,hbmpo;
+ RECT rc = {0};
+ GetClientRect(hwnd,&rc);
+ rc.right++;
+ rc.bottom++;
+ hdc = GetDC(hwnd);
+ hdc2 = CreateCompatibleDC(hdc);
+ hbmp = ske_CreateDIB32(rc.right,rc.bottom);
+ hbmpo = (HBITMAP)SelectObject(hdc2,hbmp);
+ ske_BltBackImage(hwnd,hdc2,&rc);
+ EventArea_DrawWorker(hwnd,hdc2);
+ BitBlt(hdc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,
+ hdc2,rc.left,rc.top,SRCCOPY);
+ SelectObject(hdc2,hbmpo);
+ DeleteObject(hbmp);
+ mod_DeleteDC(hdc2);
+ SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
+ ReleaseDC(hwnd,hdc);
+ ValidateRect(hwnd,NULL);
+ }
+ else
+ {
+ HDC hdc, hdc2;
+ HBITMAP hbmp, hbmpo;
+ RECT rc;
+ PAINTSTRUCT ps;
+ HBRUSH br = GetSysColorBrush(COLOR_3DFACE);
+ GetClientRect(hwnd,&rc);
+ hdc = BeginPaint(hwnd,&ps);
+ hdc2 = CreateCompatibleDC(hdc);
+ hbmp = ske_CreateDIB32(rc.right,rc.bottom);
+ hbmpo = (HBITMAP)SelectObject(hdc2,hbmp);
+ FillRect(hdc2,&ps.rcPaint,br);
+ EventArea_DrawWorker(hwnd,hdc2);
+ BitBlt(hdc,ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right-ps.rcPaint.left,ps.rcPaint.bottom-ps.rcPaint.top,
+ hdc2,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY);
+ SelectObject(hdc2,hbmpo);
+ DeleteObject(hbmp);
+ mod_DeleteDC(hdc2);
+ ps.fErase = FALSE;
+ EndPaint(hwnd,&ps);
+ }
+ }
+ default:
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return TRUE;
+}
diff --git a/plugins/Clist_modern/src/modern_clistmenus.cpp b/plugins/Clist_modern/src/modern_clistmenus.cpp
new file mode 100644
index 0000000000..1cb178028d
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clistmenus.cpp
@@ -0,0 +1,217 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_clist.h"
+#include "m_genmenu.h"
+#include "m_clui.h"
+#include "hdr/modern_commonprototypes.h"
+
+int LoadFavoriteContactMenu();
+int UnloadFavoriteContactMenu();
+
+#pragma hdrstop
+
+INT_PTR CloseAction(WPARAM wParam,LPARAM lParam)
+{
+ int k;
+ g_CluiData.bSTATE = STATE_PREPEARETOEXIT; // workaround for avatar service and other wich destroys service on OK_TOEXIT
+ do
+ { k = CallService(MS_SYSTEM_OKTOEXIT,(WPARAM)0,(LPARAM)0);
+ }
+ while (!k);
+
+ if ( k ) {
+ DestroyWindow(pcli->hwndContactList);
+ }
+
+ return 0;
+}
+
+int InitCustomMenus(void)
+{
+ CreateServiceFunction( "CloseAction", CloseAction );
+ LoadFavoriteContactMenu();
+ return 0;
+}
+
+void UninitCustomMenus(void)
+{
+ UnloadFavoriteContactMenu();
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// FAVORITE CONTACT SYSTEM
+//
+//////////////////////////////////////////////////////////////////////////
+
+#define CLUI_FAVSETRATE "CLUI/SetContactRate" //LParam is rate, Wparam is contact handle
+#define CLUI_FAVTOGGLESHOWOFFLINE "CLUI/ToggleContactShowOffline"
+
+static HANDLE hFavoriteContactMenu = NULL;
+static HANDLE *hFavoriteContactMenuItems = NULL;
+static HANDLE hShowIfOflineItem = NULL;
+static HANDLE hOnContactMenuBuild_FAV = NULL;
+
+
+
+static int FAV_OnContactMenuBuild(WPARAM wParam,LPARAM lParam)
+{
+ CLISTMENUITEM mi;
+ BOOL NeedFree = FALSE;
+ BYTE bContactRate = db_get_b((HANDLE)wParam, "CList", "Rate",0);
+ //if (hFavoriteContactMenu)
+
+ static TCHAR * FAVMENUROOTNAME = _T("&Contact rate");
+
+ TCHAR *rates[] = {
+ _T( "None" ),
+ _T( "Low" ),
+ _T( "Medium" ),
+ _T( "High" )
+ };
+
+ char* iconsName[] = {
+ LPGEN( "Contact rate None" ),
+ LPGEN( "Contact rate Low" ),
+ LPGEN( "Contact rate Medium" ),
+ LPGEN( "Contact rate High" )
+ };
+
+ if ( bContactRate >SIZEOF( rates ) - 1 )
+ bContactRate = SIZEOF( rates ) - 1;
+
+ BOOL bModifyMenu = FALSE;
+ int i;
+ TCHAR * name = NULL;
+
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.hIcon = CLUI_LoadIconFromExternalFile("clisticons.dll",8,TRUE,TRUE,iconsName[bContactRate],"Contact List",Translate(iconsName[bContactRate]),-IDI_FAVORITE_0 - bContactRate, &NeedFree);
+ mi.pszPopupName = (char *)-1;
+ mi.position = 0;
+ if ( !bContactRate)
+ mi.ptszName = FAVMENUROOTNAME;
+ else
+ {
+ int bufsize = (lstrlen(FAVMENUROOTNAME)+lstrlen(rates[bContactRate])+15)*sizeof(TCHAR);
+ name = (TCHAR*)_alloca(bufsize);
+ mir_sntprintf(name,bufsize/sizeof(TCHAR),_T("%s (%s)"),FAVMENUROOTNAME,rates[bContactRate]);
+ mi.ptszName = name;
+ }
+ mi.flags = CMIF_ROOTPOPUP|CMIF_TCHAR;
+ if ( !hFavoriteContactMenu)
+ hFavoriteContactMenu = Menu_AddContactMenuItem(&mi);
+ else
+ {
+ mi.flags |= CMIM_FLAGS|CMIM_ICON|CMIM_NAME;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hFavoriteContactMenu, (LPARAM)&mi);
+ bModifyMenu = TRUE;
+ }
+ {
+ OptParam op;
+ op.Handle = hFavoriteContactMenu;
+ op.Setting = OPT_MENUITEMSETUNIQNAME;
+ op.Value = (INT_PTR)"ModernClistMenu_ContactRate";
+ CallService(MO_SETOPTIONSMENUITEM,(WPARAM)0,(LPARAM)&op);
+ }
+
+ CallService(MS_SKIN2_RELEASEICON,(WPARAM)mi.hIcon,0);
+ if (mi.hIcon && NeedFree) DestroyIcon(mi.hIcon);
+
+ mi.pszPopupName = (char*)hFavoriteContactMenu;
+ if ( !hFavoriteContactMenuItems) {
+ hFavoriteContactMenuItems = (HANDLE*)malloc(sizeof(HANDLE)*SIZEOF(rates));
+ memset(hFavoriteContactMenuItems,0,sizeof(HANDLE)*SIZEOF(rates));
+ }
+
+ for (i=0; i < SIZEOF(rates); i++) {
+ mi.hIcon = mi.hIcon = CLUI_LoadIconFromExternalFile("clisticons.dll",8+i,TRUE,TRUE,iconsName[i],"Contact List",Translate(iconsName[i]),-IDI_FAVORITE_0 - i, &NeedFree);
+ mi.ptszName = rates[i];
+ mi.flags = CMIF_CHILDPOPUP|CMIF_TCHAR|((bContactRate == i)?CMIF_CHECKED:0);
+ mi.pszService = CLUI_FAVSETRATE;
+ mi.popupPosition = i;
+ if (bModifyMenu && hFavoriteContactMenuItems[i]) {
+ mi.flags |= CMIM_FLAGS|CMIM_ICON;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hFavoriteContactMenuItems[i], (LPARAM)&mi);
+ }
+ else hFavoriteContactMenuItems[i] = Menu_AddContactMenuItem(&mi);
+ CallService(MS_SKIN2_RELEASEICON,(WPARAM)mi.hIcon,0);
+ if (mi.hIcon && NeedFree) DestroyIcon(mi.hIcon);
+ }
+
+ mi.hIcon = NULL;
+ mi.ptszName = _T("Show even if offline");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_TCHAR|(db_get_b((HANDLE)wParam,"CList","noOffline",0)?CMIF_CHECKED:0);
+ mi.pszService = CLUI_FAVTOGGLESHOWOFFLINE;
+ mi.popupPosition = i+100000000;
+ mi.position = -100000000;
+ if (bModifyMenu && hShowIfOflineItem) {
+ mi.flags |= CMIM_FLAGS|CMIM_ICON;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hShowIfOflineItem, (LPARAM)&mi);
+ }
+ else hShowIfOflineItem = Menu_AddContactMenuItem(&mi);
+
+ return 0;
+}
+
+INT_PTR FAV_SetRate(WPARAM hContact, LPARAM nRate)
+{
+ if (hContact)
+ {
+ db_set_b((HANDLE)hContact, "CList", "Rate",(BYTE)nRate);
+ }
+ return 0;
+}
+
+INT_PTR FAV_ToggleShowOffline(WPARAM hContact,LPARAM lParam)
+{
+ if (hContact)
+ {
+ db_set_b((HANDLE)hContact,"CList","noOffline",
+ db_get_b((HANDLE)hContact,"CList","noOffline",0)?0:1);
+ }
+ return 0;
+}
+
+int LoadFavoriteContactMenu()
+{
+ CreateServiceFunction(CLUI_FAVSETRATE,FAV_SetRate);
+ CreateServiceFunction(CLUI_FAVTOGGLESHOWOFFLINE,FAV_ToggleShowOffline);
+ hOnContactMenuBuild_FAV = HookEvent(ME_CLIST_PREBUILDCONTACTMENU,FAV_OnContactMenuBuild);
+ return 0;
+}
+
+int UnloadFavoriteContactMenu()
+{
+ if (hFavoriteContactMenuItems)
+ free (hFavoriteContactMenuItems);
+ hFavoriteContactMenuItems = NULL;
+
+ if (hFavoriteContactMenu)
+ CallService(MO_REMOVEMENUITEM,(WPARAM)hFavoriteContactMenu,0);
+ hFavoriteContactMenu = NULL;
+
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_clistmod.cpp b/plugins/Clist_modern/src/modern_clistmod.cpp
new file mode 100644
index 0000000000..fb182af5ec
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clistmod.cpp
@@ -0,0 +1,567 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include <m_file.h>
+#include <m_addcontact.h>
+#include "hdr/modern_clist.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_sync.h"
+#include "hdr/modern_clui.h"
+#include <m_modernopt.h>
+pfnMyMonitorFromPoint MyMonitorFromPoint = NULL;
+pfnMyMonitorFromWindow MyMonitorFromWindow = NULL;
+pfnMyGetMonitorInfo MyGetMonitorInfo = NULL;
+
+static HANDLE hookSystemShutdown_CListMod = NULL;
+HANDLE hookOptInitialise_CList = NULL,
+ hookOptInitialise_Skin = NULL,
+ hookContactAdded_CListSettings = NULL;
+
+
+int CListMod_HideWindow(HWND hwndContactList, int mode);
+
+void GroupMenus_Init(void);
+int AddMainMenuItem(WPARAM wParam,LPARAM lParam);
+int AddContactMenuItem(WPARAM wParam,LPARAM lParam);
+void UninitCListEvents(void);
+int ContactAdded(WPARAM wParam,LPARAM lParam);
+int GetContactDisplayName(WPARAM wParam,LPARAM lParam);
+int CListOptInit(WPARAM wParam,LPARAM lParam);
+int SkinOptInit(WPARAM wParam,LPARAM lParam);
+int ModernSkinOptInit(WPARAM wParam,LPARAM lParam);
+int EventsProcessContactDoubleClick(HANDLE hContact);
+
+INT_PTR TrayIconPauseAutoHide(WPARAM wParam,LPARAM lParam);
+INT_PTR ContactChangeGroup(WPARAM wParam,LPARAM lParam);
+
+void InitTrayMenus(void);
+void UninitTrayMenu();
+
+HIMAGELIST hCListImages = NULL;
+
+BOOL (WINAPI *MySetProcessWorkingSetSize)(HANDLE,SIZE_T,SIZE_T);
+
+//returns normal icon or combined with status overlay. Needs to be destroyed.
+HICON cliGetIconFromStatusMode(HANDLE hContact, const char *szProto,int status)
+{
+ HICON hIcon = NULL;
+ HICON hXIcon = NULL;
+ // check if options is turned on
+ BYTE trayOption = db_get_b(NULL,"CLUI","XStatusTray",SETTING_TRAYOPTION_DEFAULT);
+ if (trayOption&3 && szProto != NULL)
+ {
+ // check service exists
+ char str[MAXMODULELABELLENGTH];
+ strcpy(str,szProto);
+ strcat(str,"/GetXStatusIcon");
+ if (ServiceExists(str))
+ {
+ // check status is online
+ if (status>ID_STATUS_OFFLINE)
+ {
+ // get xicon
+ hXIcon = (HICON)CallService(str,0,0);
+ if (hXIcon)
+ {
+ // check overlay mode
+ if (trayOption&2)
+ {
+ // get overlay
+ HICON MainOverlay = (HICON)GetMainStatusOverlay(status);
+ hIcon = ske_CreateJoinedIcon(hXIcon,MainOverlay,(trayOption&4)?192:0);
+ DestroyIcon_protect(hXIcon);
+ DestroyIcon_protect(MainOverlay);
+ }
+ else
+ {
+ // paint it
+ hIcon = hXIcon;
+ }
+ }
+ }
+ }
+ }
+ if ( !hIcon)
+ {
+ hIcon = ske_ImageList_GetIcon(g_himlCListClc,ExtIconFromStatusMode(hContact,szProto,status),ILD_NORMAL);
+ }
+ // if not ready take normal icon
+ return hIcon;
+}
+////////// By FYR/////////////
+int ExtIconFromStatusMode(HANDLE hContact, const char *szProto,int status)
+{
+ /*pdisplayNameCacheEntry cacheEntry;
+ if ((DBGetContactSettingByte(NULL,"CLC","Meta",0) != 1) && szProto != NULL)
+ {
+ if (meta_module && mir_strcmp(szProto,meta_module) == 0)
+ {
+ hContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT,(UINT)hContact,0);
+ if (hContact != 0)
+ {
+ szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(UINT)hContact,0);
+ status = DBGetContactSettingWord(hContact,szProto,"Status",ID_STATUS_OFFLINE);
+ }
+ }
+ }
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ if (cacheEntry->isTransport>0) return GetTrasportStatusIconIndex(cacheEntry->isTransport-1,status);
+ */
+ return pcli->pfnIconFromStatusMode(szProto,status,hContact);
+}
+/////////// End by FYR ////////
+int cli_IconFromStatusMode(const char *szProto,int nStatus, HANDLE hContact)
+{
+ int result = -1;
+ if (hContact && szProto)
+ {
+ char * szActProto = (char*)szProto;
+ char AdvancedService[255] = {0};
+ int nActStatus = nStatus;
+ HANDLE hActContact = hContact;
+ if ( !db_get_b(NULL,"CLC","Meta",SETTING_USEMETAICON_DEFAULT) && g_szMetaModuleName && !mir_strcmp(szActProto,g_szMetaModuleName))
+ {
+ // substitute params by mostonline contact datas
+ HANDLE hMostOnlineContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT,(WPARAM)hActContact,0);
+ if (hMostOnlineContact)
+ {
+ pdisplayNameCacheEntry cacheEntry;
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hMostOnlineContact);
+ if (cacheEntry && cacheEntry->m_cache_cszProto)
+ {
+ szActProto = cacheEntry->m_cache_cszProto;
+ nActStatus = pdnce___GetStatus( cacheEntry );
+ hActContact = hMostOnlineContact;
+ }
+ }
+ }
+ mir_snprintf(AdvancedService,SIZEOF(AdvancedService),"%s%s",szActProto,"/GetAdvancedStatusIcon");
+
+ if (ServiceExists(AdvancedService))
+ result = CallService(AdvancedService,(WPARAM)hActContact, (LPARAM)0);
+
+ if (result == -1 || !(LOWORD(result)))
+ {
+ //Get normal Icon
+ int basicIcon = corecli.pfnIconFromStatusMode(szActProto,nActStatus,NULL);
+ if (result != -1 && basicIcon != 1) result |= basicIcon;
+ else result = basicIcon;
+ }
+ }
+ else
+ {
+ result = corecli.pfnIconFromStatusMode(szProto,nStatus,NULL);
+ }
+ return result;
+}
+
+
+int GetContactIconC(pdisplayNameCacheEntry cacheEntry)
+{
+ return ExtIconFromStatusMode(cacheEntry->hContact,cacheEntry->m_cache_cszProto,cacheEntry->m_cache_cszProto == NULL ? ID_STATUS_OFFLINE : pdnce___GetStatus( cacheEntry ));
+}
+
+//lParam
+// 0 - default - return icon id in order: transport status icon, protostatus icon, meta is affected
+
+
+INT_PTR GetContactIcon(WPARAM wParam,LPARAM lParam)
+{
+ char *szProto;
+ int status;
+ int res;
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0);
+ if (szProto == NULL)
+ status = ID_STATUS_OFFLINE;
+ else
+ status = db_get_w((HANDLE) wParam, szProto, "Status", ID_STATUS_OFFLINE);
+ res = ExtIconFromStatusMode((HANDLE)wParam,szProto,szProto == NULL?ID_STATUS_OFFLINE:status); //by FYR
+ if (lParam == 0 && res != -1) res &= 0xFFFF;
+ return res;
+}
+
+void UnLoadContactListModule() //unhooks noncritical events
+{
+ UninitTrayMenu();
+ UninitCustomMenus();
+}
+
+int CListMod_ContactListShutdownProc(WPARAM wParam,LPARAM lParam)
+{
+ FreeDisplayNameCache();
+ return 0;
+}
+
+INT_PTR CLUIGetCapsService(WPARAM wParam,LPARAM lParam)
+{
+ if (lParam)
+ {
+ switch (lParam)
+ {
+ case 0:
+ return 0;
+ case CLUIF2_PLUGININFO:
+ return (INT_PTR)&pluginInfo;
+ case CLUIF2_CLISTTYPE:
+ return 0x0107;
+ case CLUIF2_EXTRACOLUMNCOUNT:
+ return EXTRA_ICON_COUNT;
+ case CLUIF2_USEREXTRASTART:
+ return EXTRA_ICON_ADV3;
+ }
+ return 0;
+ }
+ else
+ {
+ switch (wParam)
+ {
+ case CLUICAPS_FLAGS1:
+ return CLUIF_HIDEEMPTYGROUPS|CLUIF_DISABLEGROUPS|CLUIF_HASONTOPOPTION|CLUIF_HASAUTOHIDEOPTION;
+ case CLUICAPS_FLAGS2:
+ return MAKELONG(EXTRACOLUMNCOUNT,1);
+ }
+ }
+ return 0;
+}
+HRESULT PreLoadContactListModule()
+{
+ /* Global data initialization */
+ {
+ g_CluiData.fOnDesktop = FALSE;
+ g_CluiData.dwKeyColor = RGB(255,0,255);
+ g_CluiData.bCurrentAlpha = 255;
+ }
+
+ //initialize firstly hooks
+ //clist interface is empty yet so handles should check
+ CreateServiceFunction(MS_CLIST_GETCONTACTICON, GetContactIcon);
+ return S_OK;
+}
+
+INT_PTR SvcActiveSkin(WPARAM wParam, LPARAM lParam);
+INT_PTR SvcPreviewSkin(WPARAM wParam, LPARAM lParam);
+INT_PTR SvcApplySkin(WPARAM wParam, LPARAM lParam);
+
+HRESULT CluiLoadModule()
+{
+ CreateServiceFunction(MS_CLUI_GETCAPS,CLUIGetCapsService);
+
+ InitDisplayNameCache();
+ hookSystemShutdown_CListMod = HookEvent(ME_SYSTEM_SHUTDOWN,CListMod_ContactListShutdownProc);
+ hookOptInitialise_CList = HookEvent(ME_OPT_INITIALISE,CListOptInit);
+ hookOptInitialise_Skin = HookEvent(ME_OPT_INITIALISE,SkinOptInit);
+
+ CreateServiceFunction("ModernSkinSel/Active", SvcActiveSkin);
+ CreateServiceFunction("ModernSkinSel/Preview", SvcPreviewSkin);
+ CreateServiceFunction("ModernSkinSel/Apply", SvcApplySkin);
+
+ hookContactAdded_CListSettings = HookEvent(ME_DB_CONTACT_ADDED,ContactAdded);
+ CreateServiceFunction(MS_CLIST_TRAYICONPROCESSMESSAGE,cli_TrayIconProcessMessage);
+ CreateServiceFunction(MS_CLIST_PAUSEAUTOHIDE,TrayIconPauseAutoHide);
+ CreateServiceFunction(MS_CLIST_CONTACTCHANGEGROUP,ContactChangeGroup);
+ CreateServiceFunction(MS_CLIST_TOGGLEHIDEOFFLINE,ToggleHideOffline);
+
+ CreateServiceFunction(MS_CLIST_TOGGLEGROUPS,ToggleGroups);
+ CreateServiceFunction(MS_CLIST_TOGGLESOUNDS,ToggleSounds);
+ CreateServiceFunction(MS_CLIST_SETUSEGROUPS,SetUseGroups);
+
+
+ CreateServiceFunction(MS_CLIST_GETCONTACTICON,GetContactIcon);
+
+ MySetProcessWorkingSetSize = (BOOL (WINAPI*)(HANDLE,SIZE_T,SIZE_T))GetProcAddress(GetModuleHandle(_T("kernel32")),"SetProcessWorkingSetSize");
+ hCListImages = ImageList_Create(16, 16, ILC_MASK|ILC_COLOR32, 32, 0);
+ InitCustomMenus();
+ InitTray();
+ {
+ HINSTANCE hUser = GetModuleHandleA("USER32");
+ MyMonitorFromPoint = ( pfnMyMonitorFromPoint )GetProcAddress( hUser,"MonitorFromPoint" );
+ MyMonitorFromWindow = ( pfnMyMonitorFromWindow )GetProcAddress( hUser, "MonitorFromWindow" );
+ MyGetMonitorInfo = ( pfnMyGetMonitorInfo )GetProcAddress( hUser, "GetMonitorInfoW");
+ }
+ CLUI::InitClui();
+
+ return S_OK;
+}
+
+/*
+Begin of Hrk's code for bug
+*/
+#define GWVS_HIDDEN 1
+#define GWVS_VISIBLE 2
+#define GWVS_COVERED 3
+#define GWVS_PARTIALLY_COVERED 4
+
+int GetWindowVisibleState(HWND, int, int);
+__inline DWORD GetDIBPixelColor(int X, int Y, int Width, int Height, int ByteWidth, BYTE * ptr)
+{
+ DWORD res = 0;
+ if (X >= 0 && X < Width && Y >= 0 && Y < Height && ptr)
+ res = *((DWORD*)(ptr+ByteWidth*(Height-Y-1)+X*4));
+ return res;
+}
+
+int GetWindowVisibleState(HWND hWnd, int iStepX, int iStepY) {
+ RECT rc = { 0 };
+ POINT pt = { 0 };
+ register int i=0,
+ j = 0,
+ width = 0,
+ height = 0,
+ iCountedDots = 0,
+ iNotCoveredDots = 0;
+ HWND hAux = 0;
+
+ if (hWnd == NULL) {
+ SetLastError(0x00000006); //Wrong handle
+ return -1;
+ }
+ //Some defaults now. The routine is designed for thin and tall windows.
+ if (iStepX <= 0) iStepX = 8;
+ if (iStepY <= 0) iStepY = 16;
+
+ HWND hwndFocused = GetFocus();
+
+ if (IsIconic(hWnd) || !IsWindowVisible(hWnd))
+ return GWVS_HIDDEN;
+ else if ( db_get_b(NULL,"CList","OnDesktop",SETTING_ONDESKTOP_DEFAULT) || !db_get_b(NULL, "CList", "BringToFront", SETTING_BRINGTOFRONT_DEFAULT))
+ return GWVS_VISIBLE;
+ else if ( hwndFocused == pcli->hwndContactList || GetParent(hwndFocused) == pcli->hwndContactList )
+ return GWVS_VISIBLE;
+ else
+ {
+ int hstep,vstep;
+ BITMAP bmp;
+ HBITMAP WindowImage;
+ int maxx = 0;
+ int maxy = 0;
+ int wx = 0;
+ int dx,dy;
+ BYTE *ptr = NULL;
+ HRGN rgn = NULL;
+ WindowImage = g_CluiData.fLayered?ske_GetCurrentWindowImage():0;
+ if (WindowImage && g_CluiData.fLayered)
+ {
+ GetObject(WindowImage,sizeof(BITMAP),&bmp);
+ ptr = (BYTE*)bmp.bmBits;
+ maxx = bmp.bmWidth;
+ maxy = bmp.bmHeight;
+ wx = bmp.bmWidthBytes;
+ }
+ else
+ {
+ RECT rc;
+ int i=0;
+ rgn = CreateRectRgn(0,0,1,1);
+ GetWindowRect(hWnd,&rc);
+ GetWindowRgn(hWnd,rgn);
+ OffsetRgn(rgn,rc.left,rc.top);
+ GetRgnBox(rgn,&rc);
+ i = i;
+ //maxx = rc.right;
+ //maxy = rc.bottom;
+ }
+ GetWindowRect(hWnd, &rc);
+ {
+ RECT rcMonitor = {0};
+ Docking_GetMonitorRectFromWindow(hWnd,&rcMonitor);
+ rc.top = rc.top < rcMonitor.top?rcMonitor.top:rc.top;
+ rc.left = rc.left < rcMonitor.left?rcMonitor.left:rc.left;
+ rc.bottom = rc.bottom>rcMonitor.bottom?rcMonitor.bottom:rc.bottom;
+ rc.right = rc.right>rcMonitor.right?rcMonitor.right:rc.right;
+ }
+ width = rc.right - rc.left;
+ height = rc.bottom- rc.top;
+ dx = -rc.left;
+ dy = -rc.top;
+ hstep = width/iStepX;
+ vstep = height/iStepY;
+ hstep = hstep>0?hstep:1;
+ vstep = vstep>0?vstep:1;
+
+ for (i = rc.top; i < rc.bottom; i += vstep) {
+ pt.y = i;
+ for (j = rc.left; j < rc.right; j += hstep) {
+ BOOL po = FALSE;
+ pt.x = j;
+ if (rgn)
+ po = PtInRegion(rgn,j,i);
+ else
+ {
+ DWORD a = (GetDIBPixelColor(j+dx,i+dy,maxx,maxy,wx,ptr)&0xFF000000)>>24;
+ a = ((a*g_CluiData.bCurrentAlpha)>>8);
+ po = (a>16);
+ }
+ if (po || (!rgn && ptr == 0))
+ {
+ BOOL hWndFound = FALSE;
+ HWND hAuxOld = NULL;
+ hAux = WindowFromPoint(pt);
+ do
+ {
+ if (hAux == hWnd)
+ {
+ hWndFound = TRUE;
+ break;
+ }
+ //hAux = GetParent(hAux);
+ hAuxOld = hAux;
+ hAux = fnGetAncestor(hAux,GA_ROOTOWNER);
+ if (hAuxOld == hAux)
+ {
+ TCHAR buf[255];
+ GetClassName(hAux,buf,SIZEOF(buf));
+ if ( !lstrcmp(buf,CLUIFrameSubContainerClassName))
+ {
+ hWndFound = TRUE;
+ break;
+ }
+ }
+ }while(hAux != NULL && hAuxOld != hAux);
+
+ if (hWndFound) //There's window!
+ iNotCoveredDots++; //Let's count the not covered dots.
+ iCountedDots++; //Let's keep track of how many dots we checked.
+ }
+ }
+ }
+ if (rgn) DeleteObject(rgn);
+ if ( iCountedDots - iNotCoveredDots < 2) //Every dot was not covered: the window is visible.
+ return GWVS_VISIBLE;
+ else if (iNotCoveredDots == 0) //They're all covered!
+ return GWVS_COVERED;
+ else //There are dots which are visible, but they are not as many as the ones we counted: it's partially covered.
+ return GWVS_PARTIALLY_COVERED;
+ }
+}
+BYTE g_bCalledFromShowHide = 0;
+int cliShowHide(WPARAM wParam,LPARAM lParam)
+{
+ BOOL bShow = FALSE;
+
+ int iVisibleState = GetWindowVisibleState(pcli->hwndContactList,0,0);
+ int method;
+ method = db_get_b(NULL, "ModernData", "HideBehind", SETTING_HIDEBEHIND_DEFAULT);; //(0-none, 1-leftedge, 2-rightedge);
+ if (method)
+ {
+ if (db_get_b(NULL, "ModernData", "BehindEdge", SETTING_BEHINDEDGE_DEFAULT) == 0 && lParam != 1)
+ {
+ //hide
+ CLUI_HideBehindEdge();
+ }
+ else
+ {
+ CLUI_ShowFromBehindEdge();
+ }
+ bShow = TRUE;
+ iVisibleState = GWVS_HIDDEN;
+ }
+
+ if ( !method && db_get_b(NULL, "ModernData", "BehindEdge", SETTING_BEHINDEDGE_DEFAULT)>0)
+ {
+ g_CluiData.bBehindEdgeSettings = db_get_b(NULL, "ModernData", "BehindEdge", SETTING_BEHINDEDGE_DEFAULT);
+ CLUI_ShowFromBehindEdge();
+ g_CluiData.bBehindEdgeSettings = 0;
+ g_CluiData.nBehindEdgeState = 0;
+ db_unset(NULL, "ModernData", "BehindEdge");
+ }
+
+ //bShow is FALSE when we enter the switch if no hide behind edge.
+ switch (iVisibleState) {
+ case GWVS_PARTIALLY_COVERED:
+ bShow = TRUE; break;
+ case GWVS_COVERED: //Fall through (and we're already falling)
+ bShow = TRUE; break;
+ case GWVS_HIDDEN:
+ bShow = TRUE; break;
+ case GWVS_VISIBLE: //This is not needed, but goes for readability.
+ bShow = FALSE; break;
+ case -1: //We can't get here, both pcli->hwndContactList and iStepX and iStepY are right.
+ return 0;
+ }
+
+ if ((bShow == TRUE || lParam == 1))
+ {
+ Sync( CLUIFrames_ActivateSubContainers, TRUE );
+ CLUI_ShowWindowMod(pcli->hwndContactList, SW_RESTORE);
+
+ if ( !db_get_b(NULL,"CList","OnDesktop",SETTING_ONDESKTOP_DEFAULT))
+ {
+ Sync(CLUIFrames_OnShowHide, pcli->hwndContactList,1); //TO BE PROXIED
+ SetWindowPos(pcli->hwndContactList, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |SWP_NOACTIVATE);
+ g_bCalledFromShowHide = 1;
+ if ( !db_get_b(NULL,"CList","OnTop",SETTING_ONTOP_DEFAULT))
+ SetWindowPos(pcli->hwndContactList, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
+ g_bCalledFromShowHide = 0;
+ }
+ else
+ {
+ SetWindowPos(pcli->hwndContactList, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
+ Sync(CLUIFrames_OnShowHide, pcli->hwndContactList,1);
+ SetForegroundWindow(pcli->hwndContactList);
+ }
+ db_set_b(NULL,"CList","State",SETTING_STATE_NORMAL);
+
+ RECT rcWindow;
+ GetWindowRect(pcli->hwndContactList,&rcWindow);
+ if (Utils_AssertInsideScreen(&rcWindow) == 1)
+ {
+ MoveWindow(pcli->hwndContactList, rcWindow.left, rcWindow.top,
+ rcWindow.right - rcWindow.left, rcWindow.bottom - rcWindow.top, TRUE);
+ }
+
+ //if (DBGetContactSettingByte(NULL,"CList","OnDesktop",SETTING_ONDESKTOP_DEFAULT))
+ // SetWindowPos(pcli->hwndContactList, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+
+ }
+ else { //It needs to be hidden
+ if (GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE) & WS_EX_TOOLWINDOW)
+ {
+ CListMod_HideWindow(pcli->hwndContactList, SW_HIDE);
+ db_set_b(NULL,"CList","State",SETTING_STATE_HIDDEN);
+ }
+ else
+ {
+ if (db_get_b(NULL,"CList","Min2Tray",SETTING_MIN2TRAY_DEFAULT)) {
+ CLUI_ShowWindowMod(pcli->hwndContactList, SW_HIDE);
+ db_set_b(NULL,"CList","State",SETTING_STATE_HIDDEN);
+ }
+ else
+ {
+ CLUI_ShowWindowMod(pcli->hwndContactList, SW_MINIMIZE);
+ db_set_b(NULL,"CList","State",SETTING_STATE_MINIMIZED);
+ }
+ }
+
+ if (MySetProcessWorkingSetSize != NULL)
+ MySetProcessWorkingSetSize(GetCurrentProcess(),-1,-1);
+ }
+ return 0;
+}
+
+int CListMod_HideWindow(HWND hwndContactList, int mode)
+{
+ KillTimer(pcli->hwndContactList,1/*TM_AUTOALPHA*/);
+ if ( !CLUI_HideBehindEdge()) return CLUI_SmoothAlphaTransition(pcli->hwndContactList, 0, 1);
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_clistopts.cpp b/plugins/Clist_modern/src/modern_clistopts.cpp
new file mode 100644
index 0000000000..d5d46dc1cb
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clistopts.cpp
@@ -0,0 +1,1282 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "m_clc.h"
+#include "hdr/modern_commonprototypes.h"
+
+static UINT expertOnlyControls[] = {IDC_ALWAYSSTATUS};
+
+static INT_PTR CALLBACK DlgProcItemRowOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ SendDlgItemMessage(hwndDlg,IDC_MIN_ROW_HEIGHT_SPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_MIN_ROW_HEIGHT),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_MIN_ROW_HEIGHT_SPIN,UDM_SETRANGE,0,MAKELONG(255,0));
+ SendDlgItemMessage(hwndDlg,IDC_MIN_ROW_HEIGHT_SPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","MinRowHeight",CLCDEFAULT_ROWHEIGHT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_ROW_BORDER_SPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_ROW_BORDER),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_ROW_BORDER_SPIN,UDM_SETRANGE,0,MAKELONG(255,0));
+ SendDlgItemMessage(hwndDlg,IDC_ROW_BORDER_SPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","RowBorder",SETTING_ROWBORDER_DEFAULT),0));
+
+ CheckDlgButton(hwndDlg, IDC_VARIABLE_ROW_HEIGHT, db_get_b(NULL,"CList","VariableRowHeight",SETTING_VARIABLEROWHEIGHT_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_ALIGN_TO_LEFT, db_get_b(NULL,"CList","AlignLeftItemsToLeft",SETTING_ALIGNLEFTTOLEFT_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_ALIGN_TO_RIGHT, db_get_b(NULL,"CList","AlignRightItemsToRight",SETTING_ALIGNRIGHTORIGHT_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+
+ CheckDlgButton(hwndDlg, IDC_MINIMODE, db_get_b(NULL,"CLC","CompactMode",SETTING_COMPACTMODE_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+
+ SendDlgItemMessage(hwndDlg,IDC_LEFTMARGINSPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_LEFTMARGIN),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_LEFTMARGINSPIN,UDM_SETRANGE,0,MAKELONG(64,0));
+ SendDlgItemMessage(hwndDlg,IDC_LEFTMARGINSPIN,UDM_SETPOS,0,MAKELONG(db_get_b(NULL,"CLC","LeftMargin",CLCDEFAULT_LEFTMARGIN),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_RIGHTMARGINSPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_RIGHTMARGIN),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_RIGHTMARGINSPIN,UDM_SETRANGE,0,MAKELONG(64,0));
+ SendDlgItemMessage(hwndDlg,IDC_RIGHTMARGINSPIN,UDM_SETPOS,0,MAKELONG(db_get_b(NULL,"CLC","RightMargin",CLCDEFAULT_RIGHTMARGIN),0));
+
+ // Listbox
+ {
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_LIST_ORDER);
+ for (int i=0 ; i < NUM_ITEM_TYPE ; i++) {
+ char tmp[128];
+ int type;
+ int pos = 0;
+
+ mir_snprintf(tmp, SIZEOF(tmp), "RowPos%d", i);
+ type = db_get_w(NULL, "CList", tmp, i);
+
+ switch(type) {
+ case ITEM_AVATAR:
+ pos = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM) TranslateT("Avatar"));
+ break;
+ case ITEM_ICON:
+ pos = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM) TranslateT("Icon"));
+ break;
+ case ITEM_TEXT:
+ pos = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM) TranslateT("Text"));
+ break;
+ case ITEM_EXTRA_ICONS:
+ pos = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM) TranslateT("Extra icons"));
+ break;
+ case ITEM_CONTACT_TIME:
+ pos = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM) TranslateT("Contact time"));
+ break;
+ }
+ SendMessage(hwndList, LB_SETITEMDATA, pos, type);
+ }
+
+ // Buttons
+ switch(SendMessage(hwndList, LB_GETCURSEL, 0, 0)) {
+ case LB_ERR:
+ EnableWindow(GetDlgItem(hwndDlg,IDC_UP),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DOWN),FALSE);
+ break;
+ case 0:
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DOWN),FALSE);
+ break;
+ case 3:
+ EnableWindow(GetDlgItem(hwndDlg,IDC_UP),FALSE);
+ break;
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_UP) {
+ if (HIWORD(wParam) != BN_CLICKED)
+ return 0;
+
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_LIST_ORDER);
+ int pos = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
+ if (pos == LB_ERR)
+ return 0;
+ int type = SendMessage(hwndList, LB_GETITEMDATA, pos, 0);
+
+ // Switch items
+ SendMessage(hwndList, LB_DELETESTRING, pos, 0);
+
+ switch(type) {
+ case ITEM_AVATAR:
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos-1, (LPARAM) TranslateT("Avatar"));
+ break;
+ case ITEM_ICON:
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos-1, (LPARAM) TranslateT("Icon"));
+ break;
+ case ITEM_TEXT:
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos-1, (LPARAM) TranslateT("Text"));
+ break;
+ case ITEM_EXTRA_ICONS:
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos-1, (LPARAM) TranslateT("Extra icons"));
+ break;
+ case ITEM_CONTACT_TIME:
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos-1, (LPARAM) TranslateT("Contact time"));
+ break;
+ }
+ SendMessage(hwndList, LB_SETITEMDATA, pos, type);
+ SendMessage(hwndList, LB_SETCURSEL, pos, 0);
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ }
+
+ if (LOWORD(wParam) == IDC_DOWN)
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_LIST_ORDER);
+ int pos = SendMessage(hwndList, LB_GETCURSEL, 0, 0);
+
+ if (pos != LB_ERR)
+ {
+ int type = SendMessage(hwndList, LB_GETITEMDATA, pos, 0);
+
+ // Switch items
+ SendMessage(hwndList, LB_DELETESTRING, pos, 0);
+
+ switch(type)
+ {
+ case ITEM_AVATAR:
+ {
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos+1, (LPARAM) TranslateT("Avatar"));
+ break;
+ }
+ case ITEM_ICON:
+ {
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos+1, (LPARAM) TranslateT("Icon"));
+ break;
+ }
+ case ITEM_TEXT:
+ {
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos+1, (LPARAM) TranslateT("Text"));
+ break;
+ }
+ case ITEM_EXTRA_ICONS:
+ {
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos+1, (LPARAM) TranslateT("Extra icons"));
+ break;
+ }
+ case ITEM_CONTACT_TIME:
+ {
+ pos = SendMessage(hwndList, LB_INSERTSTRING, pos+1, (LPARAM) TranslateT("Contact time"));
+ break;
+ }
+ }
+ SendMessage(hwndList, LB_SETITEMDATA, pos, type);
+ SendMessage(hwndList, LB_SETCURSEL, pos, 0);
+
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ }
+ else return 0;
+ }
+ else return 0;
+ }
+
+ if (LOWORD(wParam) == IDC_LIST_ORDER || LOWORD(wParam) == IDC_UP || LOWORD(wParam) == IDC_DOWN) {
+ int pos = SendMessage(GetDlgItem(hwndDlg, IDC_LIST_ORDER), LB_GETCURSEL, 0, 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_UP),pos != LB_ERR && pos > 0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DOWN),pos != LB_ERR && pos < 4);
+ }
+
+ if (LOWORD(wParam) == IDC_LIST_ORDER) return 0;
+ if (LOWORD(wParam) == IDC_MIN_ROW_HEIGHT && HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())
+ return 0; // dont make apply enabled during buddy set crap
+ if ((LOWORD(wParam) == IDC_LEFTMARGIN || LOWORD(wParam) == IDC_RIGHTMARGIN || LOWORD(wParam) == IDC_ROW_BORDER) && HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())
+ return 0; // dont make apply enabled during buddy set crap
+
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_w(NULL,"CList","MinRowHeight",(WORD)SendDlgItemMessage(hwndDlg,IDC_MIN_ROW_HEIGHT_SPIN,UDM_GETPOS,0,0));
+ db_set_w(NULL,"CList","RowBorder",(WORD)SendDlgItemMessage(hwndDlg,IDC_ROW_BORDER_SPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CList","VariableRowHeight", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_VARIABLE_ROW_HEIGHT));
+ db_set_b(NULL,"CList","AlignLeftItemsToLeft", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_ALIGN_TO_LEFT));
+ db_set_b(NULL,"CList","AlignRightItemsToRight", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_ALIGN_TO_RIGHT));
+ db_set_b(NULL,"CLC","CompactMode", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_MINIMODE));
+ db_set_b(NULL,"CLC","LeftMargin",(BYTE)SendDlgItemMessage(hwndDlg,IDC_LEFTMARGINSPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CLC","RightMargin",(BYTE)SendDlgItemMessage(hwndDlg,IDC_RIGHTMARGINSPIN,UDM_GETPOS,0,0));
+ {
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_LIST_ORDER);
+ for (int i=0 ; i < NUM_ITEM_TYPE ; i++) {
+ char tmp[128];
+ mir_snprintf(tmp, SIZEOF(tmp), "RowPos%d", i);
+ db_set_w(NULL,"CList",tmp,(WORD)SendMessage(hwndList, LB_GETITEMDATA, i, 0));
+ }
+ }
+
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static INT_PTR CALLBACK DlgProcItemAvatarOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_SHOW_AVATARS, db_get_b(NULL,"CList","AvatarsShow",SETTINGS_SHOWAVATARS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_SHOW_ANIAVATARS, db_get_b(NULL,"CList","AvatarsAnimated",(ServiceExists(MS_AV_GETAVATARBITMAP) && !g_CluiData.fGDIPlusFail)) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_AVATAR_FASTDRAW, db_get_b(NULL,"CList","AvatarsInSeparateWnd",SETTINGS_AVATARINSEPARATE_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_AVATAR_DRAW_BORDER, db_get_b(NULL,"CList","AvatarsDrawBorders",SETTINGS_AVATARDRAWBORDER_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_AVATAR_ROUND_CORNERS, db_get_b(NULL,"CList","AvatarsRoundCorners",SETTINGS_AVATARROUNDCORNERS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK, db_get_b(NULL,"CList","AvatarsUseCustomCornerSize",SETTINGS_AVATARUSECUTOMCORNERSIZE_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_AVATAR_IGNORE_SIZE, db_get_b(NULL,"CList","AvatarsIgnoreSizeForRow",SETTINGS_AVATARIGNORESIZEFORROW_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_AVATAR_OVERLAY_ICONS, db_get_b(NULL,"CList","AvatarsDrawOverlay",SETTINGS_AVATARDRAWOVERLAY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+
+ switch(db_get_b(NULL,"CList","AvatarsOverlayType",SETTINGS_AVATAROVERLAYTYPE_DEFAULT)) {
+ case SETTING_AVATAR_OVERLAY_TYPE_NORMAL:
+ CheckDlgButton(hwndDlg, IDC_AVATAR_OVERLAY_ICON_NORMAL, BST_CHECKED);
+ break;
+ case SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL:
+ CheckDlgButton(hwndDlg, IDC_AVATAR_OVERLAY_ICON_PROTOCOL, BST_CHECKED);
+ break;
+ case SETTING_AVATAR_OVERLAY_TYPE_CONTACT:
+ CheckDlgButton(hwndDlg, IDC_AVATAR_OVERLAY_ICON_CONTACT, BST_CHECKED);
+ break;
+ }
+
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_SIZE_SPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_AVATAR_SIZE),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_SIZE_SPIN,UDM_SETRANGE,0,MAKELONG(255,1));
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_SIZE_SPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","AvatarsSize",SETTING_AVATARHEIGHT_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_WIDTH_SPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_AVATAR_WIDTH),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_WIDTH_SPIN,UDM_SETRANGE,0,MAKELONG(255,0));
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_WIDTH_SPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","AvatarsWidth",SETTING_AVATARWIDTH_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN,UDM_SETRANGE,0,MAKELONG(255,1));
+ SendDlgItemMessage(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","AvatarsCustomCornerSize",SETTINGS_AVATARCORNERSIZE_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg, IDC_AVATAR_BORDER_COLOR, CPM_SETCOLOUR, 0, (COLORREF)db_get_dw(NULL,"CList","AvatarsBorderColor",SETTINGS_AVATARBORDERCOLOR_DEFAULT));
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_SHOW_AVATARS)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_DRAW_BORDER),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR_L),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_ROUND_CORNERS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_IGNORE_SIZE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICONS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_NORMAL),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_PROTOCOL),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_CONTACT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_L),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_SPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_PIXELS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_WIDTH),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_WIDTH_SPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_PIXELS2),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_ANIAVATARS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_PIXELS3),FALSE);
+ EnableWindow( GetDlgItem( hwndDlg, IDC_AVATAR_FASTDRAW), FALSE );
+ }
+
+ if ( !IsDlgButtonChecked( hwndDlg, IDC_SHOW_ANIAVATARS ))
+ EnableWindow( GetDlgItem( hwndDlg, IDC_AVATAR_FASTDRAW), FALSE );
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_AVATAR_DRAW_BORDER)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR_L),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR),FALSE);
+ }
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_AVATAR_ROUND_CORNERS)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN),FALSE);
+ }
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN),FALSE);
+ }
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICONS)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_NORMAL),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_PROTOCOL),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_CONTACT),FALSE);
+ }
+
+ if ( !ServiceExists(MS_AV_GETAVATARBITMAP) || g_CluiData.fGDIPlusFail) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_ANIAVATARS),FALSE);
+ SetDlgItemText(hwndDlg, IDC_SHOW_ANIAVATARS, TranslateT("Animate Avatars (GDI+ and Avatar Service module (avs.dll) are required)"));
+ }
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_SHOW_AVATARS) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_SHOW_AVATARS);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_DRAW_BORDER),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR_L),enabled && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_DRAW_BORDER));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR),enabled && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_DRAW_BORDER));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_ROUND_CORNERS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_IGNORE_SIZE),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICONS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_NORMAL),enabled && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICONS));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_PROTOCOL),enabled && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICONS));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_CONTACT),enabled && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICONS));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_L),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_SPIN),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_PIXELS2),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_PIXELS3),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_ANIAVATARS),enabled && (ServiceExists(MS_AV_GETAVATARBITMAP) && !g_CluiData.fGDIPlusFail));
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_WIDTH),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_WIDTH_SPIN),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_SIZE_PIXELS),enabled);
+
+ EnableWindow( GetDlgItem( hwndDlg, IDC_AVATAR_FASTDRAW), enabled && IsDlgButtonChecked( hwndDlg, IDC_SHOW_ANIAVATARS ));
+ }
+ else if (LOWORD(wParam) == IDC_SHOW_ANIAVATARS)
+ EnableWindow( GetDlgItem( hwndDlg, IDC_AVATAR_FASTDRAW), IsDlgButtonChecked( hwndDlg, IDC_SHOW_ANIAVATARS ));
+
+ else if (LOWORD(wParam) == IDC_AVATAR_DRAW_BORDER) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_SHOW_AVATARS) && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_DRAW_BORDER);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR_L),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR),enabled);
+ }
+
+ else if (LOWORD(wParam) == IDC_AVATAR_ROUND_CORNERS) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_SHOW_AVATARS) && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_ROUND_CORNERS);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN),enabled);
+ }
+
+ else if (LOWORD(wParam) == IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_AVATAR_ROUND_CORNERS);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE),enabled && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN),enabled && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK));
+ }
+
+ else if (LOWORD(wParam) == IDC_AVATAR_OVERLAY_ICONS) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_SHOW_AVATARS) && IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICONS);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_NORMAL),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_PROTOCOL),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_OVERLAY_ICON_CONTACT),enabled);
+ }
+ else if (LOWORD(wParam) == IDC_AVATAR_SIZE && HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())
+ return 0; // dont make apply enabled during buddy set crap
+ else if (LOWORD(wParam) == IDC_AVATAR_CUSTOM_CORNER_SIZE && HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())
+ return 0; // dont make apply enabled during buddy set crap
+
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CList","AvatarsShow", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW_AVATARS));
+ db_set_b(NULL,"CList","AvatarsAnimated", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW_ANIAVATARS));
+ db_set_b(NULL,"CList","AvatarsInSeparateWnd", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_AVATAR_FASTDRAW));
+
+ db_set_b(NULL,"CList","AvatarsDrawBorders", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_AVATAR_DRAW_BORDER));
+ db_set_dw(NULL,"CList","AvatarsBorderColor", (DWORD)SendDlgItemMessage(hwndDlg, IDC_AVATAR_BORDER_COLOR, CPM_GETCOLOUR, 0, 0));
+ db_set_b(NULL,"CList","AvatarsRoundCorners", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_AVATAR_ROUND_CORNERS));
+ db_set_b(NULL,"CList","AvatarsIgnoreSizeForRow", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_AVATAR_IGNORE_SIZE));
+ db_set_b(NULL,"CList","AvatarsUseCustomCornerSize", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK));
+ db_set_w(NULL,"CList","AvatarsCustomCornerSize",(WORD)SendDlgItemMessage(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CList","AvatarsDrawOverlay", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICONS));
+ db_set_w(NULL,"CList","AvatarsSize",(WORD)SendDlgItemMessage(hwndDlg,IDC_AVATAR_SIZE_SPIN,UDM_GETPOS,0,0));
+ db_set_w(NULL,"CList","AvatarsWidth",(WORD)SendDlgItemMessage(hwndDlg,IDC_AVATAR_WIDTH_SPIN,UDM_GETPOS,0,0));
+
+ if (IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICON_NORMAL))
+ db_set_b(NULL,"CList","AvatarsOverlayType",SETTING_AVATAR_OVERLAY_TYPE_NORMAL);
+ else if (IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICON_PROTOCOL))
+ db_set_b(NULL,"CList","AvatarsOverlayType",SETTING_AVATAR_OVERLAY_TYPE_PROTOCOL);
+ else if (IsDlgButtonChecked(hwndDlg,IDC_AVATAR_OVERLAY_ICON_CONTACT))
+ db_set_b(NULL,"CList","AvatarsOverlayType",SETTING_AVATAR_OVERLAY_TYPE_CONTACT);
+ ClcOptionsChanged();
+ AniAva_UpdateOptions();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+static INT_PTR CALLBACK DlgProcItemIconOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_HIDE_ICON_ON_AVATAR, db_get_b(NULL,"CList","IconHideOnAvatar",SETTING_HIDEICONONAVATAR_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_DRAW_ON_AVATAR_SPACE, db_get_b(NULL,"CList","IconDrawOnAvatarSpace",SETTING_ICONONAVATARPLACE_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_ICONBLINK, db_get_b(NULL,"CList","NoIconBlink",SETTING_NOICONBLINF_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_HIDE_GROUPSICON, db_get_b(NULL,"CList","HideGroupsIcon",SETTING_HIDEGROUPSICON_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_NOTCHECKICONSIZE, db_get_b(NULL,"CList","IconIgnoreSizeForRownHeight",SETTING_ICONIGNORESIZE_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_ALWAYS_VISIBLEICON, db_get_b(NULL,"CList","AlwaysShowAlwaysVisIcon",SETTING_ALWAYSVISICON_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_USEXSTATUS, (db_get_b(NULL,"CLC","DrawOverlayedStatus",SETTING_DRAWOVERLAYEDSTATUS_DEFAULT)&1) ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_DRAWSTATUSOVERLAY, (db_get_b(NULL,"CLC","DrawOverlayedStatus",SETTING_DRAWOVERLAYEDSTATUS_DEFAULT)&2) ? BST_CHECKED : BST_UNCHECKED );
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAWSTATUSOVERLAY),IsDlgButtonChecked(hwndDlg,IDC_USEXSTATUS));
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_HIDE_ICON_ON_AVATAR))
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAW_ON_AVATAR_SPACE),FALSE);
+
+ if (ServiceExists("ExtraIcon/Register"))
+ ShowWindow(GetDlgItem(hwndDlg, IDC_ALWAYS_VISIBLEICON), SW_HIDE);
+
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_HIDE_ICON_ON_AVATAR) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_HIDE_ICON_ON_AVATAR);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAW_ON_AVATAR_SPACE),enabled);
+ }
+ else if (LOWORD(wParam) == IDC_USEXSTATUS)
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAWSTATUSOVERLAY),IsDlgButtonChecked(hwndDlg,IDC_USEXSTATUS));
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CList","IconHideOnAvatar", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_HIDE_ICON_ON_AVATAR));
+ db_set_b(NULL,"CList","IconDrawOnAvatarSpace", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_DRAW_ON_AVATAR_SPACE));
+ db_set_b(NULL,"CList","HideGroupsIcon", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_HIDE_GROUPSICON));
+ db_set_b(NULL,"CList","NoIconBlink", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_ICONBLINK));
+ db_set_b(NULL,"CList","IconIgnoreSizeForRownHeight", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_NOTCHECKICONSIZE));
+ db_set_b(NULL,"CList","AlwaysShowAlwaysVisIcon", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_ALWAYS_VISIBLEICON));
+ {
+ BYTE ovr = IsDlgButtonChecked(hwndDlg,IDC_USEXSTATUS)?1:0;
+ if (ovr) ovr += IsDlgButtonChecked(hwndDlg,IDC_DRAWSTATUSOVERLAY)?2:0;
+ db_set_b(NULL,"CLC","DrawOverlayedStatus", ovr );
+ }
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+static INT_PTR CALLBACK DlgProcItemContactTimeOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_SHOW, db_get_b(NULL,"CList","ContactTimeShow",SETTING_SHOWTIME_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_SHOW_ONLY_IF_DIFFERENT, db_get_b(NULL,"CList","ContactTimeShowOnlyIfDifferent",SETTING_SHOWTIMEIFDIFF_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ break;
+
+ case WM_COMMAND:
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CList","ContactTimeShow", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW));
+ db_set_b(NULL,"CList","ContactTimeShowOnlyIfDifferent", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW_ONLY_IF_DIFFERENT));
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+static INT_PTR CALLBACK DlgProcItemTextOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_RTL, db_get_b(NULL,"CList","TextRTL",SETTING_TEXT_RTL_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ //TODO: init IDC_ALIGNGROUPCOMBO from DBGetContactSettingByte(NULL,"CList","AlignGroupCaptions",SETTING_ALIGNGROPCAPTION_DEFAULT);
+ {
+ int item;
+ TCHAR *align[] = {_T("Left align group names"), _T("Center group names"), _T("Right align group names")};
+ for (int i=0; i < sizeof(align)/sizeof(char*); i++)
+ item = SendDlgItemMessage(hwndDlg,IDC_ALIGNGROUPCOMBO,CB_ADDSTRING,0,(LPARAM)TranslateTS(align[i]));
+ SendDlgItemMessage(hwndDlg,IDC_ALIGNGROUPCOMBO,CB_SETCURSEL,db_get_b(NULL,"CList","AlignGroupCaptions",SETTING_ALIGNGROPCAPTION_DEFAULT),0);
+ }
+ CheckDlgButton(hwndDlg, IDC_ALIGN_RIGHT, db_get_b(NULL,"CList","TextAlignToRight",SETTING_TEXT_RIGHTALIGN_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_REPLACE_SMILEYS, db_get_b(NULL,"CList","TextReplaceSmileys",SETTING_TEXT_SMILEY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_RESIZE_SMILEYS, db_get_b(NULL,"CList","TextResizeSmileys",SETTING_TEXT_RESIZESMILEY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_USE_PROTOCOL_SMILEYS, db_get_b(NULL,"CList","TextUseProtocolSmileys",SETTING_TEXT_PROTOSMILEY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_IGNORE_SIZE, db_get_b(NULL,"CList","TextIgnoreSizeForRownHeight",SETTING_TEXT_IGNORESIZE_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+
+ CheckDlgButton(hwndDlg, IDC_DRAW_SMILEYS_ON_FIRST_LINE, db_get_b(NULL,"CList","FirstLineDrawSmileys",SETTING_FIRSTLINE_SMILEYS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_APPEND_NICK, db_get_b(NULL,"CList","FirstLineAppendNick",SETTING_FIRSTLINE_APPENDNICK_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_TRIM_TEXT, db_get_b(NULL,"CList","TrimText",SETTING_FIRSTLINE_TRIMTEXT_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ {
+ bool smileAddPresent = ServiceExists(MS_SMILEYADD_BATCHPARSE) != 0;
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_REPLACE_SMILEYS), smileAddPresent ? SW_SHOW : SW_HIDE);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_USE_PROTOCOL_SMILEYS), smileAddPresent ? SW_SHOW : SW_HIDE);
+ //CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_RESIZE_SMILEYS), smileAddPresent ? SW_SHOW : SW_HIDE);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_DRAW_SMILEYS_ON_FIRST_LINE), smileAddPresent ? SW_SHOW : SW_HIDE);
+ }
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_REPLACE_SMILEYS))
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_PROTOCOL_SMILEYS),FALSE);
+
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_REPLACE_SMILEYS) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_REPLACE_SMILEYS);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_PROTOCOL_SMILEYS),enabled);
+ //EnableWindow(GetDlgItem(hwndDlg,IDC_RESIZE_SMILEYS),enabled); //Commented out for listening to icon
+ }
+ if (LOWORD(wParam) != IDC_ALIGNGROUPCOMBO || (LOWORD(wParam) == IDC_ALIGNGROUPCOMBO && HIWORD(wParam) == CBN_SELCHANGE))
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CList","TextRTL", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_RTL));
+ //TODO: Store IDC_ALIGNGROUPCOMBO at DBGetContactSettingByte(NULL,"CList","AlignGroupCaptions",SETTING_ALIGNGROPCAPTION_DEFAULT);
+ db_set_b(NULL,"CList","AlignGroupCaptions",(BYTE)SendDlgItemMessage(hwndDlg,IDC_ALIGNGROUPCOMBO,CB_GETCURSEL,0,0));
+ db_set_b(NULL,"CList","TextAlignToRight", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_ALIGN_RIGHT));
+ db_set_b(NULL,"CList","TextReplaceSmileys", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_REPLACE_SMILEYS));
+ db_set_b(NULL,"CList","TextResizeSmileys", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_RESIZE_SMILEYS));
+ db_set_b(NULL,"CList","TextUseProtocolSmileys", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_USE_PROTOCOL_SMILEYS));
+ db_set_b(NULL,"CList","TextIgnoreSizeForRownHeight", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_IGNORE_SIZE));
+ db_set_b(NULL,"CList","FirstLineDrawSmileys", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_DRAW_SMILEYS_ON_FIRST_LINE));
+ db_set_b(NULL,"CList","FirstLineAppendNick", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_APPEND_NICK));
+ db_set_b(NULL,"CList","TrimText", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_TRIM_TEXT));
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static INT_PTR CALLBACK DlgProcItemSecondLineOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_SHOW, db_get_b(NULL,"CList","SecondLineShow",SETTING_SECONDLINE_SHOW_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+
+ SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_TOP_SPACE),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_SETRANGE,0,MAKELONG(255,0));
+ SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","SecondLineTopSpace",SETTING_SECONDLINE_TOPSPACE_DEFAULT),0));
+
+ CheckDlgButton(hwndDlg, IDC_DRAW_SMILEYS, db_get_b(NULL,"CList","SecondLineDrawSmileys",SETTING_SECONDLINE_SMILEYS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ {
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingTString(NULL, "CList","SecondLineText", &dbv)) {
+ SetWindowText(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), dbv.ptszVal);
+ db_free(&dbv);
+ }
+ }
+ SendMessage(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), EM_SETLIMITTEXT, TEXT_TEXT_MAX_LENGTH, 0);
+ {
+ int radio;
+ radio = db_get_w(NULL,"CList","SecondLineType",TEXT_STATUS_MESSAGE);
+
+ CheckDlgButton(hwndDlg, IDC_STATUS, radio == TEXT_STATUS ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_NICKNAME, radio == TEXT_NICKNAME ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_STATUS_MESSAGE, radio == TEXT_STATUS_MESSAGE ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_LISTENING_TO, radio == TEXT_LISTENING_TO ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_CONTACT_TIME, radio == TEXT_CONTACT_TIME ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_TEXT, radio == TEXT_TEXT ? BST_CHECKED : BST_UNCHECKED );
+ }
+ CheckDlgButton(hwndDlg, IDC_XSTATUS_HAS_PRIORITY, db_get_b(NULL,"CList","SecondLineXStatusHasPriority",SETTING_SECONDLINE_XSTATUS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOW_STATUS_IF_NOAWAY, db_get_b(NULL,"CList","SecondLineShowStatusIfNoAway",SETTING_SECONDLINE_STATUSIFNOAWAY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOW_LISTENING_IF_NOAWAY, db_get_b(NULL,"CList","SecondLineShowListeningIfNoAway",SETTING_SECONDLINE_LISTENINGIFNOAWAY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_USE_NAME_AND_MESSAGE, db_get_b(NULL,"CList","SecondLineUseNameAndMessageForXStatus",SETTING_SECONDLINE_XSTATUSNAMETEXT_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_SHOW))
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_PROTOCOL_SMILEYS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE_SPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAW_SMILEYS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_NICKNAME),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS_MESSAGE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_LISTENING_TO),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CONTACT_TIME),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TOP),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_PIXELS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE),FALSE);
+ }
+ else {
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_TEXT)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L),FALSE);
+ }
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_STATUS) && !IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE),FALSE);
+ }
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY),FALSE);
+ }
+ }
+
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_DRAW_SMILEYS), ServiceExists(MS_SMILEYADD_BATCHPARSE) ? SW_SHOW : SW_HIDE);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_VARIABLES_L), ServiceExists(MS_VARS_FORMATSTRING) ? SW_SHOW : SW_HIDE);
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_TEXT || LOWORD(wParam) == IDC_STATUS || LOWORD(wParam) == IDC_NICKNAME || LOWORD(wParam) == IDC_STATUS_MESSAGE
+ || LOWORD(wParam) == IDC_LISTENING_TO || LOWORD(wParam) == IDC_CONTACT_TIME) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), IsDlgButtonChecked(hwndDlg,IDC_TEXT)
+ && IsDlgButtonChecked(hwndDlg,IDC_SHOW));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L), IsDlgButtonChecked(hwndDlg,IDC_TEXT)
+ && IsDlgButtonChecked(hwndDlg,IDC_SHOW));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY), IsDlgButtonChecked(hwndDlg,IDC_SHOW) &&
+ (IsDlgButtonChecked(hwndDlg,IDC_STATUS)
+ || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY), IsDlgButtonChecked(hwndDlg,IDC_SHOW) &&
+ (IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY), IsDlgButtonChecked(hwndDlg,IDC_SHOW) &&
+ (IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE), IsDlgButtonChecked(hwndDlg,IDC_SHOW) &&
+ (IsDlgButtonChecked(hwndDlg,IDC_STATUS)
+ || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ }
+ else if (LOWORD(wParam) == IDC_SHOW) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_SHOW);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_PROTOCOL_SMILEYS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE_SPIN),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAW_SMILEYS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_NICKNAME),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CONTACT_TIME),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS_MESSAGE),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_LISTENING_TO),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TEXT),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT),enabled && IsDlgButtonChecked(hwndDlg,IDC_TEXT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TOP),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_PIXELS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TEXT),enabled);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), enabled && IsDlgButtonChecked(hwndDlg,IDC_TEXT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L), enabled && IsDlgButtonChecked(hwndDlg,IDC_TEXT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY), enabled && (IsDlgButtonChecked(hwndDlg,IDC_STATUS)
+ || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY), enabled && IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY), enabled && IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE), enabled && (IsDlgButtonChecked(hwndDlg,IDC_STATUS)
+ || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ }
+
+ if (LOWORD(wParam) == IDC_TOP_SPACE && HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())
+ return 0; // dont make apply enabled during buddy set crap
+
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CList","SecondLineShow", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW));
+ db_set_w(NULL,"CList","SecondLineTopSpace", (WORD)SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CList","SecondLineDrawSmileys", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_DRAW_SMILEYS));
+ {
+ int radio;
+ if (IsDlgButtonChecked(hwndDlg,IDC_STATUS))
+ radio = TEXT_STATUS;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_NICKNAME))
+ radio = TEXT_NICKNAME;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_TEXT))
+ radio = TEXT_TEXT;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_CONTACT_TIME))
+ radio = TEXT_CONTACT_TIME;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_LISTENING_TO))
+ radio = TEXT_LISTENING_TO;
+ else
+ radio = TEXT_STATUS_MESSAGE;
+ db_set_w(NULL,"CList","SecondLineType", (WORD)radio);
+ }
+ {
+ TCHAR t[TEXT_TEXT_MAX_LENGTH];
+
+ GetWindowText(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), t, SIZEOF(t));
+ t[TEXT_TEXT_MAX_LENGTH - 1] = '\0';
+
+ db_set_ws(NULL, "CList", "SecondLineText", t);
+ }
+
+ db_set_b(NULL,"CList","SecondLineXStatusHasPriority", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_XSTATUS_HAS_PRIORITY));
+ db_set_b(NULL,"CList","SecondLineShowStatusIfNoAway", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY));
+ db_set_b(NULL,"CList","SecondLineShowListeningIfNoAway", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY));
+ db_set_b(NULL,"CList","SecondLineUseNameAndMessageForXStatus", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_USE_NAME_AND_MESSAGE));
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static INT_PTR CALLBACK DlgProcItemThirdLineOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ CheckDlgButton(hwndDlg, IDC_SHOW, db_get_b(NULL,"CList","ThirdLineShow",SETTING_THIRDLINE_SHOW_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+
+ SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_SETBUDDY,(WPARAM)GetDlgItem(hwndDlg,IDC_TOP_SPACE),0); // set buddy
+ SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_SETRANGE,0,MAKELONG(255,0));
+ SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_SETPOS,0,MAKELONG(db_get_w(NULL,"CList","ThirdLineTopSpace",SETTING_THIRDLINE_TOPSPACE_DEFAULT),0));
+
+ CheckDlgButton(hwndDlg, IDC_DRAW_SMILEYS, db_get_b(NULL,"CList","ThirdLineDrawSmileys",SETTING_THIRDLINE_SMILEYS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ {
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingTString(NULL, "CList","ThirdLineText", &dbv)) {
+ SetWindowText(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), dbv.ptszVal);
+ db_free(&dbv);
+ }
+ }
+ SendMessage(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), EM_SETLIMITTEXT, TEXT_TEXT_MAX_LENGTH, 0);
+ {
+ int radio = db_get_w(NULL,"CList","ThirdLineType",SETTING_THIRDLINE_TYPE_DEFAULT);
+ CheckDlgButton(hwndDlg, IDC_STATUS, radio == TEXT_STATUS ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_NICKNAME, radio == TEXT_NICKNAME ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_STATUS_MESSAGE, radio == TEXT_STATUS_MESSAGE ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_LISTENING_TO, radio == TEXT_LISTENING_TO ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_CONTACT_TIME, radio == TEXT_CONTACT_TIME ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton(hwndDlg, IDC_TEXT, radio == TEXT_TEXT ? BST_CHECKED : BST_UNCHECKED );
+ }
+
+ CheckDlgButton(hwndDlg, IDC_XSTATUS_HAS_PRIORITY, db_get_b(NULL,"CList","ThirdLineXStatusHasPriority",SETTING_THIRDLINE_XSTATUS_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOW_STATUS_IF_NOAWAY, db_get_b(NULL,"CList","ThirdLineShowStatusIfNoAway",SETTING_THIRDLINE_STATUSIFNOAWAY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOW_LISTENING_IF_NOAWAY, db_get_b(NULL,"CList","ThirdLineShowListeningIfNoAway",SETTING_THIRDLINE_LISTENINGIFNOAWAY_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_USE_NAME_AND_MESSAGE, db_get_b(NULL,"CList","ThirdLineUseNameAndMessageForXStatus",SETTING_THIRDLINE_XSTATUSNAMETEXT_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED);
+
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_SHOW)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_PROTOCOL_SMILEYS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE_SPIN),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAW_SMILEYS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_NICKNAME),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS_MESSAGE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_LISTENING_TO),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CONTACT_TIME),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TOP),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_PIXELS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY),FALSE);
+ }
+ else {
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_TEXT)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L),FALSE);
+ }
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_STATUS) && !IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE),FALSE);
+ }
+ if ( !IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY),FALSE);
+ }
+ }
+
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_DRAW_SMILEYS), ServiceExists(MS_SMILEYADD_BATCHPARSE) ? SW_SHOW : SW_HIDE);
+ CLUI_ShowWindowMod(GetDlgItem(hwndDlg,IDC_VARIABLES_L), ServiceExists(MS_VARS_FORMATSTRING) ? SW_SHOW : SW_HIDE);
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_TEXT || LOWORD(wParam) == IDC_STATUS || LOWORD(wParam) == IDC_NICKNAME || LOWORD(wParam) == IDC_STATUS_MESSAGE
+ || LOWORD(wParam) == IDC_LISTENING_TO || LOWORD(wParam) == IDC_CONTACT_TIME) {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), IsDlgButtonChecked(hwndDlg,IDC_TEXT)
+ && IsDlgButtonChecked(hwndDlg,IDC_SHOW));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L), IsDlgButtonChecked(hwndDlg,IDC_TEXT)
+ && IsDlgButtonChecked(hwndDlg,IDC_SHOW));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY), IsDlgButtonChecked(hwndDlg,IDC_SHOW) &&
+ (IsDlgButtonChecked(hwndDlg,IDC_STATUS)
+ || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE), IsDlgButtonChecked(hwndDlg,IDC_SHOW) && (IsDlgButtonChecked(hwndDlg,IDC_STATUS) || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY), IsDlgButtonChecked(hwndDlg,IDC_SHOW) && (IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY), IsDlgButtonChecked(hwndDlg,IDC_SHOW) && (IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ }
+ else if (LOWORD(wParam) == IDC_SHOW) {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_SHOW);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_PROTOCOL_SMILEYS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE_SPIN),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TOP_SPACE),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DRAW_SMILEYS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_NICKNAME),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUS_MESSAGE),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_LISTENING_TO),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_CONTACT_TIME),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TEXT),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT),enabled && IsDlgButtonChecked(hwndDlg,IDC_TEXT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TOP),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_PIXELS),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATIC_TEXT),enabled);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), enabled && IsDlgButtonChecked(hwndDlg,IDC_TEXT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_VARIABLES_L), enabled && IsDlgButtonChecked(hwndDlg,IDC_TEXT));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_XSTATUS_HAS_PRIORITY), enabled && (IsDlgButtonChecked(hwndDlg,IDC_STATUS)
+ || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_NAME_AND_MESSAGE), enabled && (IsDlgButtonChecked(hwndDlg,IDC_STATUS)
+ || IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE)));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY), enabled && IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY), enabled && IsDlgButtonChecked(hwndDlg,IDC_STATUS_MESSAGE));
+ }
+
+ if (LOWORD(wParam) == IDC_TOP_SPACE && HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())
+ return 0; // dont make apply enabled during buddy set crap
+
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ db_set_b(NULL,"CList","ThirdLineShow", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW));
+ db_set_w(NULL,"CList","ThirdLineTopSpace", (WORD)SendDlgItemMessage(hwndDlg,IDC_TOP_SPACE_SPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CList","ThirdLineDrawSmileys", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_DRAW_SMILEYS));
+ {
+ int radio;
+ if (IsDlgButtonChecked(hwndDlg,IDC_STATUS))
+ radio = TEXT_STATUS;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_NICKNAME))
+ radio = TEXT_NICKNAME;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_TEXT))
+ radio = TEXT_TEXT;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_CONTACT_TIME))
+ radio = TEXT_CONTACT_TIME;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_LISTENING_TO))
+ radio = TEXT_LISTENING_TO;
+ else
+ radio = TEXT_STATUS_MESSAGE;
+ db_set_w(NULL,"CList","ThirdLineType", (WORD)radio);
+ }
+ {
+ TCHAR t[TEXT_TEXT_MAX_LENGTH];
+
+ GetWindowText(GetDlgItem(hwndDlg,IDC_VARIABLE_TEXT), t, SIZEOF(t));
+ t[TEXT_TEXT_MAX_LENGTH - 1] = '\0';
+
+ db_set_ws(NULL, "CList", "ThirdLineText", t);
+ }
+
+ db_set_b(NULL,"CList","ThirdLineXStatusHasPriority", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_XSTATUS_HAS_PRIORITY));
+ db_set_b(NULL,"CList","ThirdLineUseNameAndMessageForXStatus", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_USE_NAME_AND_MESSAGE));
+ db_set_b(NULL,"CList","ThirdLineShowStatusIfNoAway", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW_STATUS_IF_NOAWAY));
+ db_set_b(NULL,"CList","ThirdLineShowListeningIfNoAway", (BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOW_LISTENING_IF_NOAWAY));
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+/* Extra icons settings */
+typedef struct _OrderTreeData
+{
+ BYTE ID;
+ TCHAR * Name;
+ BYTE Position;
+ char * KeyName;
+ BOOL Visible;
+ BOOL fReserved;
+} *pOrderTreeData, TOrderTreeData;
+
+static TOrderTreeData OrderTreeData[] =
+{
+ {EXTRA_ICON_VISMODE, _T("Visibility/Chat activity"), EXTRA_ICON_VISMODE, "EXTRA_ICON_VISMODE", SETTING_EXTRA_ICON_VISMODE_DEFAULT,0},
+ {EXTRA_ICON_EMAIL, _T("E-mail"), EXTRA_ICON_EMAIL, "EXTRA_ICON_EMAIL", SETTING_EXTRA_ICON_EMAIL_DEFAULT, 0},
+ {EXTRA_ICON_PROTO, _T("Protocol"), EXTRA_ICON_PROTO, "EXTRA_ICON_PROTO", SETTING_EXTRA_ICON_PROTO_DEFAULT, 0},
+ {EXTRA_ICON_SMS, _T("Phone/SMS"), EXTRA_ICON_SMS, "EXTRA_ICON_SMS", SETTING_EXTRA_ICON_SMS_DEFAULT, 0},
+ {EXTRA_ICON_WEB, _T("Web page"), EXTRA_ICON_WEB, "EXTRA_ICON_WEB", SETTING_EXTRA_ICON_WEB_DEFAULT, 0},
+ {EXTRA_ICON_CLIENT, _T("Client (fingerprint.dll is required)"), EXTRA_ICON_CLIENT,"EXTRA_ICON_CLIENT", SETTING_EXTRA_ICON_CLIENT_DEFAULT, 0},
+ {EXTRA_ICON_ADV1, _T("Advanced #1"), EXTRA_ICON_ADV1, "EXTRA_ICON_ADV1", SETTING_EXTRA_ICON_ADV1_DEFAULT, 0},
+ {EXTRA_ICON_ADV2, _T("Advanced #2"), EXTRA_ICON_ADV2, "EXTRA_ICON_ADV2", SETTING_EXTRA_ICON_ADV2_DEFAULT, 0},
+ {EXTRA_ICON_ADV3, _T("Advanced #3"), EXTRA_ICON_ADV3, "EXTRA_ICON_ADV3", SETTING_EXTRA_ICON_ADV3_DEFAULT, 0},
+ {EXTRA_ICON_ADV4, _T("Advanced #4"), EXTRA_ICON_ADV4, "EXTRA_ICON_ADV4", SETTING_EXTRA_ICON_ADV4_DEFAULT, 0}
+};
+
+#define PrVer 4
+
+static char **settingname;
+static int nArrayLen;
+
+static int OrderEnumProc (const char *szSetting,LPARAM lParam)
+{
+ if (szSetting == NULL) return 0;
+ if ( !wildcmp((char*) szSetting,(char *) lParam,0)) return 0;
+ nArrayLen++;
+ settingname = (char **)realloc(settingname,nArrayLen*sizeof(char *));
+ settingname[nArrayLen-1] = _strdup(szSetting);
+ return 0;
+};
+
+static int DeleteAllSettingInOrder()
+{
+ DBCONTACTENUMSETTINGS dbces;
+ nArrayLen = 0;
+
+ dbces.pfnEnumProc = OrderEnumProc;
+ dbces.szModule = CLUIFrameModule;
+ dbces.ofsSettings = 0;
+ dbces.lParam = (LPARAM)"ORDER_EXTRA_*";
+
+ CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces);
+
+ //delete all settings
+ if (nArrayLen == 0)
+ return 0;
+
+ for (int i=0; i < nArrayLen; i++) {
+ db_unset(0, CLUIFrameModule, settingname[i]);
+ free(settingname[i]);
+ }
+ free(settingname);
+ settingname = NULL;
+
+ return 0;
+}
+
+static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+{
+ pOrderTreeData A = (pOrderTreeData)lParam1;
+ pOrderTreeData B = (pOrderTreeData)lParam2;
+ return (int)(A->Position)-(int)(B->Position);
+}
+
+static int FillOrderTree(HWND hwndDlg, HWND Tree)
+{
+ TVINSERTSTRUCT tvis = {0};
+ TreeView_DeleteAllItems(Tree);
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ if (db_get_b(NULL,CLUIFrameModule,"ExtraCountStored",0) != SIZEOF(OrderTreeData)) {
+ DeleteAllSettingInOrder();
+ db_set_b(NULL,CLUIFrameModule,"ExtraCountStored",SIZEOF(OrderTreeData));
+ }
+
+ for (int i=0; i < SIZEOF(OrderTreeData); i++) {
+ char buf[256];
+ sprintf(buf,"ORDER_%s",OrderTreeData[i].KeyName);
+ OrderTreeData[i].Position = (BYTE)db_get_b(NULL,CLUIFrameModule,buf,i);
+ OrderTreeData[i].Visible = (BOOL)db_get_b(NULL,CLUIFrameModule,OrderTreeData[i].KeyName,1);
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.lParam = (LPARAM)(&(OrderTreeData[i]));
+ tvis.item.pszText = TranslateTS(OrderTreeData[i].Name);
+ tvis.item.iImage = tvis.item.iSelectedImage = OrderTreeData[i].Visible;
+ TreeView_InsertItem(Tree,&tvis);
+ }
+
+ TVSORTCB sort = {0};
+ sort.hParent = NULL;
+ sort.lParam = 0;
+ sort.lpfnCompare = CompareFunc;
+ TreeView_SortChildrenCB(Tree,&sort,0);
+ return 0;
+}
+
+static int SaveOrderTree(HWND hwndDlg, HWND Tree)
+{
+ HTREEITEM ht;
+ BYTE pos = 0;
+ TVITEMA tvi = {0};
+ tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM;
+ ht = TreeView_GetRoot(Tree);
+ do {
+ TOrderTreeData * it = NULL;
+ tvi.hItem = ht;
+ TreeView_GetItemA(Tree,&tvi);
+ it = (TOrderTreeData*)(tvi.lParam);
+ {
+ char buf[250];
+ sprintf(buf,"ORDER_%s",it->KeyName);
+ db_set_b(NULL,CLUIFrameModule,buf,pos);
+ db_set_b(NULL,CLUIFrameModule,it->KeyName, it->Visible);
+ }
+ ht = TreeView_GetNextSibling(Tree,ht);
+ pos++;
+ }
+ while (ht);
+
+ return 0;
+}
+
+int LoadPositionsFromDB(BYTE * OrderPos)
+{
+ if (db_get_b(NULL,CLUIFrameModule,"ExtraCountStored",0) != SIZEOF(OrderTreeData)) {
+ DeleteAllSettingInOrder();
+ db_set_b(NULL,CLUIFrameModule,"ExtraCountStored",SIZEOF(OrderTreeData));
+ }
+
+ for (int i=0; i < SIZEOF(OrderTreeData); i++) {
+ char buf[256];
+ sprintf(buf,"ORDER_%s",OrderTreeData[i].KeyName);
+ OrderPos[OrderTreeData[i].ID-1] = (BYTE)db_get_b(NULL,CLUIFrameModule,buf,i);
+ }
+ return 0;
+}
+
+static int dragging = 0;
+static HANDLE hDragItem = NULL;
+
+INT_PTR CALLBACK DlgProcExtraIconsOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_EXTRAORDER),GWL_STYLE,GetWindowLongPtr(GetDlgItem(hwndDlg,IDC_EXTRAORDER),GWL_STYLE)|TVS_NOHSCROLL);
+ {
+ HIMAGELIST himlCheckBoxes;
+ himlCheckBoxes = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_COLOR32|ILC_MASK,2,2);
+ ImageList_AddIcon(himlCheckBoxes,LoadSmallIconShared(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_NOTICK)));
+ ImageList_AddIcon(himlCheckBoxes,LoadSmallIconShared(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_TICK)));
+ TreeView_SetImageList(GetDlgItem(hwndDlg,IDC_EXTRAORDER),himlCheckBoxes,TVSIL_NORMAL);
+ }
+ FillOrderTree(hwndDlg,GetDlgItem(hwndDlg,IDC_EXTRAORDER));
+ return TRUE;
+
+ case WM_COMMAND:
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom) {
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ SaveOrderTree(hwndDlg,GetDlgItem(hwndDlg,IDC_EXTRAORDER));
+ ReAssignExtraIcons();
+ CLUI_ReloadCLUIOptions();
+ ClcOptionsChanged();
+ return TRUE;
+ }
+ break;
+
+ case IDC_EXTRAORDER:
+ switch (((LPNMHDR)lParam)->code) {
+ case NM_CLICK:
+ {
+ TVHITTESTINFO hti;
+ hti.pt.x = (short)LOWORD(GetMessagePos());
+ hti.pt.y = (short)HIWORD(GetMessagePos());
+ ScreenToClient(((LPNMHDR)lParam)->hwndFrom,&hti.pt);
+ if (TreeView_HitTest(((LPNMHDR)lParam)->hwndFrom,&hti))
+ if (hti.flags & TVHT_ONITEMICON)
+ {
+ TVITEMA tvi;
+ tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ tvi.hItem = hti.hItem;
+ TreeView_GetItemA(((LPNMHDR)lParam)->hwndFrom,&tvi);
+ tvi.iImage = tvi.iSelectedImage = !tvi.iImage;
+ ((TOrderTreeData *)tvi.lParam)->Visible = tvi.iImage;
+ TreeView_SetItem(((LPNMHDR)lParam)->hwndFrom,&tvi);
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ }
+ }
+ break;
+
+ case TVN_BEGINDRAGA:
+ case TVN_BEGINDRAGW:
+ SetCapture(hwndDlg);
+ dragging = 1;
+ hDragItem = ((LPNMTREEVIEWA)lParam)->itemNew.hItem;
+ TreeView_SelectItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),hDragItem);
+ break;
+ }
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ if ( dragging) {
+ TVHITTESTINFO hti;
+ hti.pt.x = (short)LOWORD(lParam);
+ hti.pt.y = (short)HIWORD(lParam);
+ ClientToScreen(hwndDlg,&hti.pt);
+ ScreenToClient(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&hti.pt);
+ TreeView_HitTest(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&hti);
+ if (hti.flags & (TVHT_ONITEM|TVHT_ONITEMRIGHT)) {
+ HTREEITEM it = hti.hItem;
+ hti.pt.y -= TreeView_GetItemHeight(GetDlgItem(hwndDlg,IDC_EXTRAORDER))/2;
+ TreeView_HitTest(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&hti);
+ //TreeView_SetInsertMark(GetDlgItem(hwndDlg,IDC_EXTRAORDER),hti.hItem,1);
+ if ( !(hti.flags&TVHT_ABOVE))
+ TreeView_SetInsertMark(GetDlgItem(hwndDlg,IDC_EXTRAORDER),hti.hItem,1);
+ else
+ TreeView_SetInsertMark(GetDlgItem(hwndDlg,IDC_EXTRAORDER),it,0);
+ }
+ else {
+ if (hti.flags&TVHT_ABOVE) SendDlgItemMessage(hwndDlg,IDC_EXTRAORDER,WM_VSCROLL,MAKEWPARAM(SB_LINEUP,0),0);
+ if (hti.flags&TVHT_BELOW) SendDlgItemMessage(hwndDlg,IDC_EXTRAORDER,WM_VSCROLL,MAKEWPARAM(SB_LINEDOWN,0),0);
+ TreeView_SetInsertMark(GetDlgItem(hwndDlg,IDC_EXTRAORDER),NULL,0);
+ }
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ if ( dragging) {
+ TreeView_SetInsertMark(GetDlgItem(hwndDlg,IDC_EXTRAORDER),NULL,0);
+ dragging = 0;
+ ReleaseCapture();
+
+ TVHITTESTINFO hti;
+ TVITEM tvi;
+ hti.pt.x = (short)LOWORD(lParam);
+ hti.pt.y = (short)HIWORD(lParam);
+ ClientToScreen(hwndDlg,&hti.pt);
+ ScreenToClient(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&hti.pt);
+ hti.pt.y -= TreeView_GetItemHeight(GetDlgItem(hwndDlg,IDC_EXTRAORDER))/2;
+ TreeView_HitTest(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&hti);
+ if (hDragItem == hti.hItem) break;
+ if (hti.flags&TVHT_ABOVE) hti.hItem = TVI_FIRST;
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ tvi.hItem = (HTREEITEM)hDragItem;
+ TreeView_GetItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&tvi);
+ if (hti.flags&(TVHT_ONITEM|TVHT_ONITEMRIGHT) || (hti.hItem == TVI_FIRST)) {
+ TVINSERTSTRUCT tvis;
+ TCHAR name[128];
+ tvis.item.mask = TVIF_HANDLE|TVIF_PARAM|TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ tvis.item.stateMask = 0xFFFFFFFF;
+ tvis.item.pszText = name;
+ tvis.item.cchTextMax = sizeof(name);
+ tvis.item.hItem = (HTREEITEM)hDragItem;
+ tvis.item.iImage = tvis.item.iSelectedImage = ((TOrderTreeData *)tvi.lParam)->Visible;
+ TreeView_GetItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&tvis.item);
+ TreeView_DeleteItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),hDragItem);
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = hti.hItem;
+ TreeView_SelectItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),TreeView_InsertItem(GetDlgItem(hwndDlg,IDC_EXTRAORDER),&tvis));
+ SendMessage((GetParent(hwndDlg)), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ ImageList_Destroy(TreeView_SetImageList(GetDlgItem(hwndDlg,IDC_EXTRAORDER),NULL,TVSIL_NORMAL));
+ break;
+ }
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct
+{
+ char *name; // Tab name
+ int id; // Dialog id
+ DLGPROC wnd_proc; // Dialog function
+}
+static row_opt_items[] =
+{
+ { LPGEN("Row"), IDD_OPT_ITEM_ROW, DlgProcItemRowOpts },
+#ifdef _DEBUG
+ { LPGEN("Row design"), IDD_OPT_ROWTMPL, DlgTmplEditorOpts },
+#endif
+ { LPGEN("Avatar"), IDD_OPT_ITEM_AVATAR, DlgProcItemAvatarOpts },
+ { LPGEN("Icon"), IDD_OPT_ITEM_ICON, DlgProcItemIconOpts },
+ { LPGEN("Contact time"), IDD_OPT_ITEM_CONTACT_TIME, DlgProcItemContactTimeOpts },
+ { LPGEN("Text"), IDD_OPT_ITEM_TEXT, DlgProcItemTextOpts },
+ { LPGEN("Second Line"), IDD_OPT_ITEM_SECOND_LINE, DlgProcItemSecondLineOpts },
+ { LPGEN("Third Line"), IDD_OPT_ITEM_THIRD_LINE, DlgProcItemThirdLineOpts },
+ { LPGEN("Extra Icons"), IDD_OPT_ITEM_EXTRAICONS, DlgProcExtraIconsOpts}
+};
+
+int CListOptInit(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+ odp.cbSize = sizeof(odp);
+ odp.position = -200000000;
+ odp.hInstance = g_hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ITEMS);
+ odp.pszGroup = LPGEN("Contact List");
+ odp.pszTitle = LPGEN("Row items");
+ odp.flags = ODPF_BOLDGROUPS;
+
+ BOOL hasExtraIconsService = ServiceExists("ExtraIcon/Register");
+ for (int i=0; i < SIZEOF(row_opt_items); i++) {
+ if (hasExtraIconsService && row_opt_items[i].id == IDD_OPT_ITEM_EXTRAICONS)
+ continue;
+
+ odp.pszTemplate = MAKEINTRESOURCEA(row_opt_items[i].id);
+ odp.pszTab = row_opt_items[i].name;
+ odp.pfnDlgProc = row_opt_items[i].wnd_proc;
+ Options_AddPage(wParam, &odp);
+ }
+
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_clistsettings.cpp b/plugins/Clist_modern/src/modern_clistsettings.cpp
new file mode 100644
index 0000000000..cbea7018e0
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clistsettings.cpp
@@ -0,0 +1,531 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "m_clc.h"
+#include "hdr/modern_clist.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_awaymsg.h"
+
+void InsertContactIntoTree(HANDLE hContact,int status);
+static displayNameCacheEntry *displayNameCache;
+void CListSettings_FreeCacheItemDataOption( pdisplayNameCacheEntry pDst, DWORD flag );
+
+int PostAutoRebuidMessage(HWND hwnd);
+static int displayNameCacheSize;
+
+BOOL CLM_AUTOREBUILD_WAS_POSTED = FALSE;
+SortedList *clistCache = NULL;
+char *GetProtoForContact(HANDLE hContact);
+int GetStatusForContact(HANDLE hContact,char *szProto);
+TCHAR *UnknownConctactTranslatedName = NULL;
+
+void InvalidateDNCEbyPointer(HANDLE hContact,pdisplayNameCacheEntry pdnce,int SettingType);
+
+static int handleCompare( void* c1, void* c2 )
+{
+ INT_PTR p1, p2;
+
+ displayNameCacheEntry * dnce1 = (displayNameCacheEntry *)c1;
+ displayNameCacheEntry * dnce2 = (displayNameCacheEntry *)c2;
+
+ p1 = (INT_PTR)dnce1->hContact;
+ p2 = (INT_PTR)dnce2->hContact;
+
+ if ( p1 == p2 )
+ return 0;
+
+ return (int)(p1 - p2);
+}
+
+void InitCacheAsync();
+void UninitCacheAsync();
+
+void InitDisplayNameCache(void)
+{
+ int i=0;
+ InitCacheAsync();
+ InitAwayMsgModule();
+ clistCache = List_Create( 0, 50 );
+ clistCache->sortFunc = handleCompare;
+}
+
+void FreeDisplayNameCache()
+{
+ UninitCacheAsync();
+ UninitAwayMsgModule();
+ if ( clistCache != NULL ) {
+ int i;
+ for ( i=0; i < clistCache->realCount; i++) {
+ pcli->pfnFreeCacheItem(( ClcCacheEntryBase* )clistCache->items[i] );
+ mir_free_and_nil( clistCache->items[i] );
+ }
+
+ List_Destroy( clistCache );
+ mir_free(clistCache);
+ clistCache = NULL;
+ }
+}
+
+ClcCacheEntryBase* cliGetCacheEntry(HANDLE hContact)
+{
+ ClcCacheEntryBase* p;
+ int idx;
+ if ( !clistCache) return NULL;
+ if ( !List_GetIndex( clistCache, &hContact, &idx )) {
+ if (( p = pcli->pfnCreateCacheItem( hContact )) != NULL ) {
+ List_Insert( clistCache, p, idx );
+ pcli->pfnInvalidateDisplayNameCacheEntry( hContact );
+ }
+ }
+ else p = ( ClcCacheEntryBase* )clistCache->items[idx];
+ pcli->pfnCheckCacheItem( p );
+ return p;
+}
+
+void CListSettings_FreeCacheItemData(pdisplayNameCacheEntry pDst)
+{
+ CListSettings_FreeCacheItemDataOption( pDst, CCI_ALL);
+}
+
+void CListSettings_FreeCacheItemDataOption( pdisplayNameCacheEntry pDst, DWORD flag )
+{
+ if ( !pDst)
+ return;
+
+ if ( flag & CCI_NAME)
+ pDst->freeName();
+
+ if ( flag & CCI_GROUP )
+ mir_free_and_nil(pDst->tszGroup);
+
+ if ( flag & CCI_LINES ) {
+ mir_free_and_nil(pDst->szSecondLineText);
+ mir_free_and_nil(pDst->szThirdLineText);
+ pDst->ssSecondLine.DestroySmileyList();
+ pDst->ssThirdLine.DestroySmileyList();
+ }
+}
+
+int CListSettings_GetCopyFromCache(pdisplayNameCacheEntry pDest, DWORD flag);
+int CListSettings_SetToCache(pdisplayNameCacheEntry pSrc, DWORD flag);
+
+
+void CListSettings_CopyCacheItems(pdisplayNameCacheEntry pDst, pdisplayNameCacheEntry pSrc, DWORD flag)
+{
+ if ( !pDst || !pSrc) return;
+ CListSettings_FreeCacheItemDataOption(pDst, flag);
+
+ if ( flag & CCI_NAME ) {
+ pDst->isUnknown = pSrc->isUnknown;
+ if (pSrc->isUnknown)
+ pDst->tszName = pSrc->tszName;
+ else
+ pDst->tszName = mir_tstrdup(pSrc->tszName);
+ }
+
+ if ( flag & CCI_GROUP ) pDst->tszGroup = mir_tstrdup(pSrc->tszGroup);
+ if ( flag & CCI_PROTO ) pDst->m_cache_cszProto = pSrc->m_cache_cszProto;
+ if ( flag & CCI_STATUS ) pDst->m_cache_nStatus = pSrc->m_cache_nStatus;
+
+ if ( flag & CCI_LINES ) {
+ mir_free( pDst->szThirdLineText );
+ pDst->szThirdLineText = mir_tstrdup( pSrc->szThirdLineText );
+
+ mir_free( pDst->szSecondLineText );
+ pDst->szSecondLineText = mir_tstrdup( pSrc->szSecondLineText );
+
+ pDst->ssThirdLine = pSrc->ssThirdLine;
+ pDst->ssSecondLine = pSrc->ssSecondLine;
+ }
+
+ if ( flag & CCI_TIME)
+ pDst->hTimeZone = pSrc->hTimeZone;
+
+ if ( flag & CCI_OTHER) {
+ pDst->bIsHidden = pSrc->bIsHidden;
+ pDst->m_cache_nNoHiddenOffline = pSrc->m_cache_nNoHiddenOffline;
+ pDst->m_cache_bProtoNotExists = pSrc->m_cache_bProtoNotExists;
+
+ pDst->m_cache_nHiddenSubcontact = pSrc->m_cache_nHiddenSubcontact;
+ pDst->i = pSrc->i;
+ pDst->ApparentMode = pSrc->ApparentMode;
+ pDst->NotOnList = pSrc->NotOnList;
+ pDst->IdleTS = pSrc->IdleTS;
+ pDst->ClcContact = pSrc->ClcContact;
+ pDst->IsExpanded = pSrc->IsExpanded;
+ }
+}
+
+int CListSettings_GetCopyFromCache(pdisplayNameCacheEntry pDest, DWORD flag)
+{
+ if ( !pDest || !pDest->hContact)
+ return -1;
+
+ pdisplayNameCacheEntry pSource = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(pDest->hContact);
+ if ( !pSource)
+ return -1;
+
+ CListSettings_CopyCacheItems(pDest, pSource, flag);
+ return 0;
+}
+
+int CListSettings_SetToCache(pdisplayNameCacheEntry pSrc, DWORD flag)
+{
+ if ( !pSrc || !pSrc->hContact)
+ return -1;
+
+ pdisplayNameCacheEntry pDst = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(pSrc->hContact);
+ if ( !pDst)
+ return -1;
+
+ CListSettings_CopyCacheItems(pDst, pSrc, flag);
+ return 0;
+}
+
+void cliFreeCacheItem( pdisplayNameCacheEntry p )
+{
+ HANDLE hContact = p->hContact;
+ TRACEVAR("cliFreeCacheItem hContact = %d",hContact);
+ p->freeName();
+ mir_free_and_nil(p->tszGroup);
+ mir_free_and_nil(p->szSecondLineText);
+ mir_free_and_nil(p->szThirdLineText);
+ p->ssSecondLine.DestroySmileyList();
+ p->ssThirdLine.DestroySmileyList();
+}
+
+void cliCheckCacheItem(pdisplayNameCacheEntry pdnce)
+{
+ if (pdnce == NULL)
+ return;
+
+ if (pdnce->hContact == NULL) { //selfcontact
+ if ( !pdnce->tszName)
+ pdnce->getName();
+ return;
+ }
+
+ if (pdnce->m_cache_cszProto == NULL && pdnce->m_cache_bProtoNotExists == FALSE) {
+ pdnce->m_cache_cszProto = GetProtoForContact(pdnce->hContact);
+ if (pdnce->m_cache_cszProto == NULL)
+ pdnce->m_cache_bProtoNotExists = FALSE;
+ else if (CallService(MS_PROTO_ISPROTOCOLLOADED,0,(LPARAM)pdnce->m_cache_cszProto) == (int)NULL && 0)
+ pdnce->m_cache_bProtoNotExists = TRUE;
+ else if (pdnce->m_cache_cszProto && pdnce->tszName)
+ pdnce->freeName();
+ }
+
+ if (pdnce->tszName == NULL)
+ pdnce->getName();
+
+ else if (pdnce->isUnknown && pdnce->m_cache_cszProto && pdnce->m_cache_bProtoNotExists == TRUE && g_flag_bOnModulesLoadedCalled) {
+ if (CallService(MS_PROTO_ISPROTOCOLLOADED,0,(LPARAM)pdnce->m_cache_cszProto) == 0) {
+ pdnce->m_cache_bProtoNotExists = FALSE;
+ pdnce->getName();
+ }
+ }
+
+ if (pdnce___GetStatus( pdnce ) == 0) //very strange look status sort is broken let always reread status
+ pdnce___SetStatus( pdnce , GetStatusForContact(pdnce->hContact,pdnce->m_cache_cszProto));
+
+ if (pdnce->tszGroup == NULL) {
+ DBVARIANT dbv = {0};
+ if ( !DBGetContactSettingTString(pdnce->hContact,"CList","Group",&dbv)) {
+ pdnce->tszGroup = mir_tstrdup(dbv.ptszVal);
+ db_free(&dbv);
+ }
+ else pdnce->tszGroup = mir_tstrdup(_T(""));
+ }
+
+ if (pdnce->bIsHidden == -1)
+ pdnce->bIsHidden = db_get_b(pdnce->hContact,"CList","Hidden",0);
+
+ pdnce->m_cache_nHiddenSubcontact = g_szMetaModuleName && db_get_b(pdnce->hContact,g_szMetaModuleName,"IsSubcontact",0);
+
+ if (pdnce->m_cache_nNoHiddenOffline == -1)
+ pdnce->m_cache_nNoHiddenOffline = db_get_b(pdnce->hContact,"CList","noOffline",0);
+
+ if (pdnce->IdleTS == -1)
+ pdnce->IdleTS = db_get_dw(pdnce->hContact,pdnce->m_cache_cszProto,"IdleTS",0);
+
+ if (pdnce->ApparentMode == -1)
+ pdnce->ApparentMode = db_get_w(pdnce->hContact,pdnce->m_cache_cszProto,"ApparentMode",0);
+
+ if (pdnce->NotOnList == -1)
+ pdnce->NotOnList = db_get_b(pdnce->hContact,"CList","NotOnList",0);
+
+ if (pdnce->IsExpanded == -1)
+ pdnce->IsExpanded = db_get_b(pdnce->hContact,"CList","Expanded",0);
+
+ if (pdnce->dwLastMsgTime == 0) {
+ pdnce->dwLastMsgTime = db_get_dw(pdnce->hContact, "CList", "mf_lastmsg", 0);
+ if (pdnce->dwLastMsgTime == 0)
+ pdnce->dwLastMsgTime = CompareContacts2_getLMTime(pdnce->hContact);
+ }
+}
+
+void IvalidateDisplayNameCache(DWORD mode)
+{
+ if ( clistCache != NULL )
+ {
+ int i;
+ for ( i=0; i < clistCache->realCount; i++)
+ {
+ PDNCE pdnce = (PDNCE)clistCache->items[i];
+ if (mode&16)
+ {
+ InvalidateDNCEbyPointer(pdnce->hContact,pdnce,16);
+ }
+ }
+ }
+}
+
+void InvalidateDNCEbyPointer(HANDLE hContact, pdisplayNameCacheEntry pdnce, int SettingType)
+{
+ if (hContact == NULL || pdnce == NULL)
+ return;
+
+ if (SettingType == 16) {
+ pdnce->ssSecondLine.DestroySmileyList();
+ mir_free_and_nil(pdnce->szSecondLineText);
+ pdnce->ssThirdLine.DestroySmileyList();
+ mir_free_and_nil(pdnce->szThirdLineText);
+ pdnce->ssSecondLine.iMaxSmileyHeight = 0;
+ pdnce->ssThirdLine.iMaxSmileyHeight = 0;
+ pdnce->hTimeZone = NULL;
+ pdnce->dwLastMsgTime = 0;
+ Cache_GetTimezone(NULL,pdnce->hContact);
+ SettingType &= ~16;
+ }
+
+ if (SettingType >= DBVT_WCHAR) {
+ pdnce->freeName();
+ mir_free_and_nil(pdnce->tszGroup);
+ pdnce->m_cache_cszProto = NULL;
+ return;
+ }
+
+ if (SettingType == -1 || SettingType == DBVT_DELETED) {
+ pdnce->freeName();
+ mir_free_and_nil(pdnce->tszGroup);
+ pdnce->m_cache_cszProto = NULL;
+ }
+ // in other cases clear all binary cache
+ else pdnce->dwLastMsgTime = 0;
+
+ pdnce->bIsHidden = -1;
+ pdnce->m_cache_nHiddenSubcontact = -1;
+ pdnce->m_cache_bProtoNotExists = FALSE;
+ pdnce___SetStatus(pdnce, 0);
+ pdnce->IdleTS = -1;
+ pdnce->ApparentMode = -1;
+ pdnce->NotOnList = -1;
+ pdnce->isUnknown = FALSE;
+ pdnce->m_cache_nNoHiddenOffline = -1;
+ pdnce->IsExpanded = -1;
+}
+
+char *GetContactCachedProtocol(HANDLE hContact)
+{
+ pdisplayNameCacheEntry cacheEntry = NULL;
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ if (cacheEntry && cacheEntry->m_cache_cszProto)
+ return cacheEntry->m_cache_cszProto;
+
+ return NULL;
+}
+
+char* GetProtoForContact(HANDLE hContact)
+{
+ return (char*)CallService(MS_PROTO_GETCONTACTBASEACCOUNT,(WPARAM)hContact,0);
+}
+
+int GetStatusForContact(HANDLE hContact,char *szProto)
+{
+ return (szProto) ? (int)(db_get_w((HANDLE)hContact,szProto,"Status",ID_STATUS_OFFLINE)) : ID_STATUS_OFFLINE;
+}
+
+void displayNameCacheEntry::freeName()
+{
+ if ( !isUnknown)
+ mir_free(tszName);
+ else
+ isUnknown = false;
+ tszName = NULL;
+}
+
+void displayNameCacheEntry::getName()
+{
+ if (UnknownConctactTranslatedName == NULL)
+ UnknownConctactTranslatedName = TranslateT("(Unknown Contact)");
+
+ freeName();
+
+ if (m_cache_bProtoNotExists || !m_cache_cszProto) {
+LBL_Unknown:
+ tszName = UnknownConctactTranslatedName;
+ isUnknown = true;
+ return;
+ }
+
+ tszName = pcli->pfnGetContactDisplayName(hContact, GCDNF_NOCACHE);
+ if ( !lstrcmp(tszName, UnknownConctactTranslatedName)) {
+ mir_free(tszName);
+ goto LBL_Unknown;
+ }
+
+ isUnknown = false;
+}
+
+int GetContactInfosForSort(HANDLE hContact,char **Proto,TCHAR **Name,int *Status)
+{
+ pdisplayNameCacheEntry cacheEntry = NULL;
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ if (cacheEntry != NULL)
+ {
+ if (Proto != NULL) *Proto = cacheEntry->m_cache_cszProto;
+ if (Name != NULL) *Name = cacheEntry->tszName;
+ if (Status != NULL) *Status = pdnce___GetStatus( cacheEntry );
+ }
+ return (0);
+};
+
+
+int GetContactCachedStatus(HANDLE hContact)
+{
+ pdisplayNameCacheEntry cacheEntry = NULL;
+ cacheEntry = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ return pdnce___GetStatus( cacheEntry );
+}
+
+int ContactAdded(WPARAM wParam,LPARAM lParam)
+{
+ if ( !MirandaExiting()) {
+ HANDLE hContact = (HANDLE)wParam;
+ cli_ChangeContactIcon(hContact,ExtIconFromStatusMode(hContact,(char*)GetContactCachedProtocol(hContact),ID_STATUS_OFFLINE),1); ///by FYR
+ pcli->pfnSortContacts();
+ }
+ return 0;
+}
+
+int ContactSettingChanged(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ if (MirandaExiting() || !pcli || !clistCache || hContact == NULL)
+ return 0;
+
+ pdisplayNameCacheEntry pdnce = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ if (pdnce == NULL) {
+ TRACE("!!! Very bad pdnce not found.");
+ return 0;
+ }
+
+ if (pdnce->m_cache_bProtoNotExists || !pdnce->m_cache_cszProto)
+ return 0;
+
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam;
+ if ( !strcmp(cws->szModule, pdnce->m_cache_cszProto)) {
+ InvalidateDNCEbyPointer(hContact, pdnce, cws->value.type);
+
+ if ( !strcmp(cws->szSetting,"IsSubcontact"))
+ PostMessage(pcli->hwndContactTree,CLM_AUTOREBUILD,0,0);
+
+ if ( !mir_strcmp(cws->szSetting, "Status") || wildcmp((char*)cws->szSetting, (char*) "Status?",2)) {
+ if (g_szMetaModuleName && !mir_strcmp(cws->szModule,g_szMetaModuleName) && mir_strcmp(cws->szSetting, "Status")) {
+ int res = 0;
+ if (pcli->hwndContactTree && g_flag_bOnModulesLoadedCalled)
+ res = PostAutoRebuidMessage(pcli->hwndContactTree);
+
+ if ((db_get_w(NULL,"CList","SecondLineType",SETTING_SECONDLINE_TYPE_DEFAULT) == TEXT_STATUS_MESSAGE || db_get_w(NULL,"CList","ThirdLineType",SETTING_THIRDLINE_TYPE_DEFAULT) == TEXT_STATUS_MESSAGE) && pdnce->hContact && pdnce->m_cache_cszProto)
+ amRequestAwayMsg(hContact);
+
+ return 0;
+ }
+
+ if (pdnce->bIsHidden != 1) {
+ pdnce___SetStatus( pdnce , cws->value.wVal ); //dont use direct set
+ if (cws->value.wVal == ID_STATUS_OFFLINE)
+ if (g_CluiData.bRemoveAwayMessageForOffline)
+ db_set_s(hContact,"CList","StatusMsg","");
+
+ if ((db_get_w(NULL,"CList","SecondLineType",0) == TEXT_STATUS_MESSAGE || db_get_w(NULL,"CList","ThirdLineType",0) == TEXT_STATUS_MESSAGE) && pdnce->hContact && pdnce->m_cache_cszProto)
+ amRequestAwayMsg(hContact);
+
+ pcli->pfnClcBroadcast( INTM_STATUSCHANGED,wParam,0);
+ cli_ChangeContactIcon(hContact, ExtIconFromStatusMode(hContact,cws->szModule, cws->value.wVal), 0); //by FYR
+ pcli->pfnSortContacts();
+ }
+ else {
+ if ( !(!mir_strcmp(cws->szSetting, "LogonTS") || !mir_strcmp(cws->szSetting, "TickTS") || !mir_strcmp(cws->szSetting, "InfoTS")))
+ pcli->pfnSortContacts();
+
+ return 0;
+ }
+ }
+ }
+
+ if ( !strcmp(cws->szModule,"CList")) {
+ //name is null or (setting is myhandle)
+ if ( !strcmp(cws->szSetting,"Rate"))
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+
+ else if (pdnce->tszName == NULL || !strcmp(cws->szSetting,"MyHandle"))
+ InvalidateDNCEbyPointer(hContact,pdnce,cws->value.type);
+
+ else if ( !strcmp(cws->szSetting,"Group"))
+ InvalidateDNCEbyPointer(hContact,pdnce,cws->value.type);
+
+ else if ( !strcmp(cws->szSetting,"Hidden")) {
+ InvalidateDNCEbyPointer(hContact,pdnce,cws->value.type);
+ if (cws->value.type == DBVT_DELETED || cws->value.bVal == 0)
+ {
+ char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,wParam,0);
+ cli_ChangeContactIcon(hContact,ExtIconFromStatusMode(hContact,szProto,szProto == NULL?ID_STATUS_OFFLINE:db_get_w(hContact,szProto,"Status",ID_STATUS_OFFLINE)),1); //by FYR
+ }
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD,0, 0);
+ }
+ else if ( !strcmp(cws->szSetting,"noOffline")) {
+ InvalidateDNCEbyPointer(hContact,pdnce,cws->value.type);
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD,0, 0);
+ }
+ }
+ else if ( !strcmp(cws->szModule,"Protocol")) {
+ if ( !strcmp(cws->szSetting,"p")) {
+ char *szProto;
+ InvalidateDNCEbyPointer(hContact,pdnce,cws->value.type);
+ if (cws->value.type == DBVT_DELETED) szProto = NULL;
+ else szProto = cws->value.pszVal;
+ cli_ChangeContactIcon(hContact,ExtIconFromStatusMode(hContact,szProto,szProto == NULL?ID_STATUS_OFFLINE:db_get_w(hContact,szProto,"Status",ID_STATUS_OFFLINE)),0); //by FYR
+ }
+ }
+
+ return 0;
+}
+
+int PostAutoRebuidMessage(HWND hwnd)
+{
+ if ( !CLM_AUTOREBUILD_WAS_POSTED)
+ CLM_AUTOREBUILD_WAS_POSTED = PostMessage(hwnd,CLM_AUTOREBUILD,0,0);
+ return CLM_AUTOREBUILD_WAS_POSTED;
+}
diff --git a/plugins/Clist_modern/src/modern_clisttray.cpp b/plugins/Clist_modern/src/modern_clisttray.cpp
new file mode 100644
index 0000000000..28963f200d
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clisttray.cpp
@@ -0,0 +1,736 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include <m_clui.h>
+#include "hdr/modern_clist.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_statusbar.h"
+
+int cliShowHide(WPARAM wParam,LPARAM lParam);
+int g_mutex_bOnTrayRightClick = 0;
+
+BOOL g_bMultiConnectionMode = FALSE;
+static int RefreshTimerId = 0; /////by FYR
+static VOID CALLBACK RefreshTimerProc(HWND hwnd,UINT message,UINT idEvent,DWORD dwTime); ///// by FYR
+static HMENU hMainMenu, hStatusMenu;
+BOOL IS_WM_MOUSE_DOWN_IN_TRAY;
+
+BOOL g_trayTooltipActive = FALSE;
+POINT tray_hover_pos = {0};
+
+// don't move to win2k.h, need new and old versions to work on 9x/2000/XP
+#define NIF_STATE 0x00000008
+#define NIF_INFO 0x00000010
+
+#ifndef _INC_SHLWAPI
+
+typedef struct _DllVersionInfo {
+ DWORD cbSize;
+ DWORD dwMajorVersion; // Major version
+ DWORD dwMinorVersion; // Minor version
+ DWORD dwBuildNumber; // Build number
+ DWORD dwPlatformID; // DLLVER_PLATFORM_*
+} DLLVERSIONINFO;
+
+#define DLLVER_PLATFORM_WINDOWS 0x00000001 // Windows 95
+#define DLLVER_PLATFORM_NT 0x00000002 // Windows NT
+typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *);
+
+#endif
+
+void mir_strset(TCHAR ** dest, TCHAR *source)
+{
+ if (*dest) mir_free_and_nil(*dest);
+ if (source) *dest = mir_tstrdup(source);
+}
+
+static DLLVERSIONINFO dviShell;
+BOOL g_MultiConnectionMode = FALSE;
+char * g_szConnectingProto = NULL;
+int GetStatusVal(int status)
+{
+ switch ( status ) {
+ case ID_STATUS_OFFLINE: return 50;
+ case ID_STATUS_ONLINE: return 100;
+ case ID_STATUS_FREECHAT: return 110;
+ case ID_STATUS_INVISIBLE: return 120;
+ case ID_STATUS_AWAY: return 200;
+ case ID_STATUS_DND: return 210;
+ case ID_STATUS_NA: return 220;
+ case ID_STATUS_OCCUPIED: return 230;
+ case ID_STATUS_ONTHEPHONE: return 400;
+ case ID_STATUS_OUTTOLUNCH: return 410;
+ }
+ if (status < ID_STATUS_OFFLINE && status>0) return 600; //connecting is most priority
+ return 0;
+}
+
+int GetStatusOrder(int currentStatus, int newStatus)
+{
+ int current = GetStatusVal(currentStatus);
+ int newstat = GetStatusVal(newStatus);
+ return (current>newstat)?currentStatus:newStatus;
+}
+
+INT_PTR CListTray_GetGlobalStatus(WPARAM wparam,LPARAM lparam)
+{
+ int curstatus = 0;
+ int i;
+ int connectingCount = 0;
+ for (i=0;i < pcli->hClcProtoCount;i++)
+ {
+ if ( !pcli->pfnGetProtocolVisibility(pcli->clcProto[i].szProto)) continue;
+ if (pcli->clcProto[i].dwStatus >= ID_STATUS_CONNECTING &&
+ pcli->clcProto[i].dwStatus < ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES)
+ {
+ connectingCount++;
+ if (connectingCount == 1) g_szConnectingProto = pcli->clcProto[i].szProto;
+ }
+ curstatus = GetStatusOrder(curstatus,pcli->clcProto[i].dwStatus);
+ }
+ if (connectingCount == 0)
+ {
+ //g_szConnectingProto = NULL;
+ g_bMultiConnectionMode = FALSE;
+ }
+ else if (connectingCount>1)
+ g_bMultiConnectionMode = TRUE;
+ else
+ g_bMultiConnectionMode = FALSE;
+ return curstatus?curstatus:ID_STATUS_OFFLINE;
+}
+
+int GetAverageMode()
+{
+ int count,netProtoCount,i;
+ int averageMode = 0;
+ PROTOACCOUNT **accs;
+ ProtoEnumAccounts( &count, &accs );
+ for (i=0,netProtoCount = 0;i < count;i++) {
+ if ( pcli->pfnGetProtocolVisibility(accs[i]->szModuleName) == 0 ) continue;
+ pcli->cycleStep = i;
+ netProtoCount++;
+ if (averageMode == 0) averageMode = CallProtoService(accs[i]->szModuleName,PS_GETSTATUS,0,0);
+ else if (averageMode != CallProtoService(accs[i]->szModuleName,PS_GETSTATUS,0,0)) {averageMode = -1; break;}
+ }
+ return averageMode;
+}
+
+////////////////////////////////////////////////////////////
+///// Need to refresh trays icon after timely changing/////
+////////////////////////////////////////////////////////////
+
+static VOID CALLBACK RefreshTimerProc(HWND hwnd,UINT message,UINT idEvent,DWORD dwTime)
+{
+ int count,i;
+ PROTOACCOUNT **accs;
+
+ if (RefreshTimerId) {KillTimer(NULL,RefreshTimerId); RefreshTimerId = 0;}
+
+ ProtoEnumAccounts( &count, &accs );
+ for (i=0; i < count; i++)
+ if ( pcli->pfnGetProtocolVisibility(accs[i]->szModuleName))
+ pcli->pfnTrayIconUpdateBase(accs[i]->szModuleName);
+
+}
+//////// End by FYR /////////
+
+void cliTrayIconUpdateBase(const char *szChangedProto)
+{
+ int i,count,netProtoCount,changed = -1;
+ PROTOACCOUNT **accs;
+ int averageMode = 0;
+ HWND hwnd = pcli->hwndContactList;
+
+ if ( !szChangedProto) return;
+
+ if ( !pcli->pfnGetProtocolVisibility(szChangedProto)) return;
+
+ pcli->pfnLockTray();
+ if ( pcli->cycleTimerId ) {
+ KillTimer( NULL, pcli->cycleTimerId);
+ pcli->cycleTimerId = 0;
+ }
+ ProtoEnumAccounts( &count, &accs );
+ for (i=0,netProtoCount = 0;i < count;i++) {
+ if ( pcli->pfnGetProtocolVisibility(accs[i]->szModuleName) == 0 ) continue;
+ netProtoCount++;
+ if ( !lstrcmpA(szChangedProto,accs[i]->szModuleName)) pcli->cycleStep = i;
+ if (averageMode == 0) averageMode = CallProtoService(accs[i]->szModuleName,PS_GETSTATUS,0,0);
+ else if (averageMode != CallProtoService(accs[i]->szModuleName,PS_GETSTATUS,0,0)) {averageMode = -1; break;}
+ }
+
+ if (netProtoCount>1) {
+ if (averageMode >= ID_STATUS_OFFLINE) {
+ if (db_get_b(NULL,"CList","TrayIcon",SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_MULTI) {
+ if (db_get_b(NULL,"CList","AlwaysMulti",SETTING_ALWAYSMULTI_DEFAULT))
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,szChangedProto,averageMode),szChangedProto);
+ else if (pcli->trayIcon && pcli->trayIcon[0].szProto != NULL) {
+ pcli->pfnTrayIconDestroy(hwnd);
+ pcli->pfnTrayIconInit(hwnd);
+ }
+ else
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,NULL,averageMode),NULL);
+ }
+ else
+ {
+ if (db_get_b(NULL,"CList","TrayIcon",SETTING_TRAYICON_DEFAULT) == SETTING_TRAYICON_SINGLE
+ && db_get_b(NULL,"CList","AlwaysPrimary",SETTING_ALWAYSPRIMARY_DEFAULT))
+ {
+ DBVARIANT dbv = {DBVT_DELETED};
+ char *szProto;
+ if (DBGetContactSettingString(NULL,"CList","PrimaryStatus",&dbv)) szProto = NULL;
+ else szProto = dbv.pszVal;
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,szProto,averageMode),NULL);
+ mir_free(szProto);
+ }
+ else
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,NULL,averageMode),NULL);
+ }
+ }
+ else {
+ switch(db_get_b(NULL,"CList","TrayIcon",SETTING_TRAYICON_DEFAULT)) {
+ case SETTING_TRAYICON_SINGLE:
+ {
+ DBVARIANT dbv = {DBVT_DELETED};
+ char *szProto;
+ int status;
+ if (DBGetContactSettingString(NULL,"CList","PrimaryStatus",&dbv)) szProto = NULL;
+ else szProto = dbv.pszVal;
+ status = CallProtoService(szChangedProto,PS_GETSTATUS,0,0);
+
+ if ((g_StatusBarData.connectingIcon == 1) && status >= ID_STATUS_CONNECTING && status <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES) {
+ //
+ HICON hIcon;
+ // 1 check if multi connecting icon
+ CListTray_GetGlobalStatus(0,0);
+ if (g_bMultiConnectionMode)
+ if (_strcmpi(szChangedProto,g_szConnectingProto))
+ { pcli->pfnUnlockTray(); return; }
+ else
+ hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)"",1);
+ else
+ hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)szChangedProto,0);
+ if (hIcon) {
+ changed = pcli->pfnTrayIconSetBaseInfo(hIcon,NULL);
+ db_free(&dbv);
+ break;
+ }
+ }
+ else
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,szProto,szProto?CallProtoService(szProto,PS_GETSTATUS,0,0):CallService(MS_CLIST_GETSTATUSMODE,0,0)),NULL);
+
+ db_free(&dbv);
+ }
+ break;
+
+ case SETTING_TRAYICON_CYCLE:
+ {
+ int status = szChangedProto ? CallProtoService(szChangedProto,PS_GETSTATUS,0,0) : averageMode;
+ if ((g_StatusBarData.connectingIcon == 1 && CListTray_GetGlobalStatus(0,0)
+ && ((status >= ID_STATUS_CONNECTING && status <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES) || g_bMultiConnectionMode )))
+ {
+ //connecting
+ status = status;
+ //stop cycling
+ if (pcli->cycleTimerId)
+ KillTimer(NULL,pcli->cycleTimerId);
+ pcli->cycleTimerId = 0;
+ {
+ HICON hIcon;
+ // 1 check if multi connecting icon
+ if (g_bMultiConnectionMode)
+ if (_strcmpi(szChangedProto,g_szConnectingProto))
+ { pcli->pfnUnlockTray(); return; }
+ else
+ hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)"",1);
+ else
+ hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)szChangedProto,0);
+ if (hIcon)
+ changed = pcli->pfnTrayIconSetBaseInfo(hIcon,NULL);
+ }
+ }
+ else
+ {
+ pcli->cycleTimerId = CLUI_SafeSetTimer(NULL,0,db_get_w(NULL,"CList","CycleTime",SETTING_CYCLETIME_DEFAULT)*1000,pcli->pfnTrayCycleTimerProc);
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,szChangedProto,status),NULL);
+ }
+
+ }
+ break;
+
+ case SETTING_TRAYICON_MULTI:
+ if ( !pcli->trayIcon)
+ pcli->pfnTrayIconRemove(NULL,NULL);
+ else if ( db_get_b(NULL,"CList","AlwaysMulti",SETTING_ALWAYSMULTI_DEFAULT )) {
+ if (pcli->pfnGetProtocolVisibility(szChangedProto))
+ {
+
+ int status;
+ status = CallProtoService(szChangedProto,PS_GETSTATUS,0,0);
+ if ((g_StatusBarData.connectingIcon == 1) && status >= ID_STATUS_CONNECTING && status <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES)
+ {
+ //
+ HICON hIcon;
+ hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)szChangedProto,0);;
+ if (hIcon)
+ changed = pcli->pfnTrayIconSetBaseInfo(hIcon,szChangedProto);
+ }
+ else
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,szChangedProto,CallProtoService(szChangedProto,PS_GETSTATUS,0,0)),szChangedProto);
+ }
+ }
+ else if (pcli->pfnGetProtocolVisibility(szChangedProto)) {
+ int i;
+ int avg;
+ avg = GetAverageMode();
+ i = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,szChangedProto,CallProtoService(szChangedProto,PS_GETSTATUS,0,0)),szChangedProto);
+ if (i < 0 /* || (avg != -1)*/) {
+ pcli->pfnTrayIconDestroy(hwnd);
+ pcli->pfnTrayIconInit(hwnd);
+ }
+ else {
+ int status;
+ changed = i;
+ status = CallProtoService(szChangedProto,PS_GETSTATUS,0,0);
+ if ((g_StatusBarData.connectingIcon == 1) && status >= ID_STATUS_CONNECTING && status <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES) {
+ //
+ HICON hIcon;
+ hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)szChangedProto,0);;
+ if (hIcon) {
+ changed = pcli->pfnTrayIconSetBaseInfo(hIcon,szChangedProto);
+ } } } }
+ break;
+ } }
+ }
+ else if ( pcli->pfnGetProtocolVisibility( szChangedProto ))
+ {
+ DBVARIANT dbv = {DBVT_DELETED};
+ char *szProto;
+ int status = CallProtoService(szChangedProto,PS_GETSTATUS,0,0);
+
+ if ((g_StatusBarData.connectingIcon == 1) && status >= ID_STATUS_CONNECTING && status <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES)
+ {
+ HICON hIcon = ( HICON )CLUI_GetConnectingIconService((WPARAM)szChangedProto,0);;
+ if (hIcon)
+ changed = pcli->pfnTrayIconSetBaseInfo(hIcon,NULL);
+ }
+ else if (status >= ID_STATUS_OFFLINE && status <= ID_STATUS_IDLE)
+ {
+ if (DBGetContactSettingString(NULL,"CList","PrimaryStatus",&dbv))
+ szProto = NULL;
+ else
+ szProto = dbv.pszVal;
+ changed = pcli->pfnTrayIconSetBaseInfo(cliGetIconFromStatusMode(NULL,szProto,status),NULL);
+ mir_free(szProto);
+ }
+ }
+
+ if (changed != -1) // && pcli->trayIcon[changed].isBase)
+ pcli->pfnTrayIconUpdate(pcli->trayIcon[changed].hBaseIcon,NULL,szChangedProto,1); // by FYR (No suitable protocol)
+ { pcli->pfnUnlockTray(); return; }
+}
+
+static UINT_PTR autoHideTimerId;
+
+static VOID CALLBACK TrayIconAutoHideTimer(HWND hwnd,UINT message,UINT_PTR idEvent,DWORD dwTime)
+{
+ HWND hwndClui, ActiveWindow;
+ KillTimer(hwnd,idEvent);
+ hwndClui = pcli->hwndContactList;
+ ActiveWindow = GetActiveWindow();
+ if (ActiveWindow == hwndClui) return;
+ if (CLUI_CheckOwnedByClui(ActiveWindow)) return;
+ //CLUI_ShowWindowMod(hwndClui,SW_HIDE);
+ CListMod_HideWindow(hwndClui, SW_HIDE);
+ if (MySetProcessWorkingSetSize != NULL)
+ MySetProcessWorkingSetSize(GetCurrentProcess(),-1,-1);
+}
+
+INT_PTR TrayIconPauseAutoHide(WPARAM wParam,LPARAM lParam)
+{
+ if (db_get_b(NULL,"CList","AutoHide",SETTING_AUTOHIDE_DEFAULT))
+ {
+ if (GetActiveWindow() != pcli->hwndContactList
+ && GetWindow(GetParent(GetActiveWindow()),GW_OWNER) != pcli->hwndContactList)
+ {
+ KillTimer(NULL,autoHideTimerId);
+ autoHideTimerId = CLUI_SafeSetTimer(NULL,0,1000*db_get_w(NULL,"CList","HideTime",SETTING_HIDETIME_DEFAULT),TrayIconAutoHideTimer);
+ } }
+
+ return 0;
+}
+
+void DestroyTrayMenu(HMENU hMenu)
+{
+ int cnt = GetMenuItemCount(hMenu);
+ for (int i=0; i < cnt; ++i)
+ {
+ HMENU hSubMenu = GetSubMenu(hMenu, i);
+ if (hSubMenu == hStatusMenu || hSubMenu == hMainMenu)
+ RemoveMenu(hMenu, i--, MF_BYPOSITION);
+ }
+ DestroyMenu(hMenu);
+}
+
+INT_PTR cli_TrayIconProcessMessage(WPARAM wParam,LPARAM lParam)
+{
+ MSG *msg = (MSG*)wParam;
+ switch(msg->message) {
+ case WM_EXITMENULOOP:
+ if (pcli->bTrayMenuOnScreen)
+ pcli->bTrayMenuOnScreen = FALSE;
+ break;
+
+ // case WM_DRAWITEM:
+ // return CallService(MS_CLIST_MENUDRAWITEM,msg->wParam,msg->lParam);
+
+ // case WM_MEASUREITEM:
+ // return CallService(MS_CLIST_MENUMEASUREITEM,msg->wParam,msg->lParam);
+
+
+ case WM_ACTIVATE:
+ {
+ HWND h1,h2,h4;
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ h1 = (HWND)msg->lParam;
+ h2 = h1?GetParent(h1):NULL;
+ h4 = pcli->hwndContactList;
+ if (db_get_b(NULL,"CList","AutoHide",SETTING_AUTOHIDE_DEFAULT)) {
+ if (LOWORD(msg->wParam) == WA_INACTIVE && h2 != h4)
+ autoHideTimerId = CLUI_SafeSetTimer(NULL,0,1000*db_get_w(NULL,"CList","HideTime",SETTING_HIDETIME_DEFAULT),TrayIconAutoHideTimer);
+ else {
+ KillTimer(NULL,autoHideTimerId);
+ autoHideTimerId = 0;
+ }
+ }
+ else if (autoHideTimerId) {
+ KillTimer(NULL, autoHideTimerId);
+ autoHideTimerId = 0;
+ }
+ }
+ return FALSE; //to avoid autohideTimer in core
+
+ case TIM_CALLBACK:
+ if ((GetAsyncKeyState(VK_CONTROL)&0x8000) && msg->lParam == WM_LBUTTONDOWN && !db_get_b(NULL,"CList","Tray1Click",SETTING_TRAY1CLICK_DEFAULT)) {
+ POINT pt;
+ HMENU hMenu;
+ hMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,(WPARAM)0,(LPARAM)0);
+ g_mutex_bOnTrayRightClick = 1;
+ IS_WM_MOUSE_DOWN_IN_TRAY = 1;
+ SetForegroundWindow(msg->hwnd);
+ SetFocus(msg->hwnd);
+ GetCursorPos(&pt);
+ pcli->bTrayMenuOnScreen = TRUE;
+ TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, msg->hwnd, NULL);
+ PostMessage(msg->hwnd, WM_NULL, 0, 0);
+ g_mutex_bOnTrayRightClick = 0;
+ IS_WM_MOUSE_DOWN_IN_TRAY = 0;
+ }
+ else if (msg->lParam == WM_MBUTTONDOWN || msg->lParam == WM_LBUTTONDOWN || msg->lParam == WM_RBUTTONDOWN) {
+ IS_WM_MOUSE_DOWN_IN_TRAY = 1;
+ }
+ else if (msg->lParam == WM_RBUTTONUP) {
+ POINT pt;
+ HMENU hMenu;
+ hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDTRAY,(WPARAM)0,(LPARAM)0);
+ g_mutex_bOnTrayRightClick = 1;
+
+ SetForegroundWindow(msg->hwnd);
+ SetFocus(msg->hwnd);
+
+ GetCursorPos(&pt);
+ pcli->bTrayMenuOnScreen = TRUE;
+ TrackPopupMenu(hMenu, TPM_TOPALIGN | TPM_LEFTALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, msg->hwnd, NULL);
+ DestroyTrayMenu(hMenu);
+ PostMessage(msg->hwnd, WM_NULL, 0, 0);
+ }
+ else break;
+ *((LRESULT*)lParam) = 0;
+ return TRUE;
+ }
+ return corecli.pfnTrayIconProcessMessage(wParam, lParam);
+}
+
+//////////////////////////////TRAY MENU/////////////////////////
+HANDLE hTrayMenuObject;
+
+HANDLE hTrayMainMenuItemProxy;
+HANDLE hTrayStatusMenuItemProxy;
+HANDLE hTrayHideShowMainMenuItem;
+
+//traymenu exec param(ownerdata)
+typedef struct{
+ char *szServiceName;
+ int Param1;
+}TrayMenuExecParam,*lpTrayMenuExecParam;
+
+/*
+wparam = handle to the menu item returned by MS_CLIST_ADDCONTACTMENUITEM
+return 0 on success.
+*/
+static INT_PTR RemoveTrayMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ CallService(MO_REMOVEMENUITEM,wParam,0);
+ return 0;
+}
+
+static INT_PTR BuildTrayMenu(WPARAM wParam,LPARAM lParam)
+{
+ int tick;
+ HMENU hMenu;
+ ListParam param;
+
+ memset(&param,0,sizeof(param));
+ param.MenuObjectHandle = hTrayMenuObject;
+
+ //hMenu = hMainMenu;
+ hMenu = CreatePopupMenu();
+ //hMenu = wParam;
+ tick = GetTickCount();
+
+ NotifyEventHooks(g_CluiData.hEventPreBuildTrayMenu,0,0);
+
+ CallService(MO_BUILDMENU,(WPARAM)hMenu,(LPARAM)&param);
+ //DrawMenuBar((HWND)CallService("CLUI/GetHwnd",0,0));
+ tick = GetTickCount()-tick;
+ return (INT_PTR)hMenu;
+}
+
+static INT_PTR AddTrayMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ TMO_MenuItem tmi;
+ CLISTMENUITEM *mi = (CLISTMENUITEM*)lParam;
+ if ( !pcli->pfnConvertMenu(mi, &tmi))
+ return NULL;
+
+ lpTrayMenuExecParam mmep = (lpTrayMenuExecParam)mir_alloc(sizeof(TrayMenuExecParam));
+ if ( mmep == NULL)
+ return 0;
+
+ //we need just one parametr.
+ mmep->szServiceName = mir_strdup(mi->pszService);
+ mmep->Param1 = mi->popupPosition;
+ tmi.ownerdata = mmep;
+
+ OptParam op;
+ op.Handle = (HANDLE)CallService(MO_ADDNEWMENUITEM,(WPARAM)hTrayMenuObject,(LPARAM)&tmi);
+ op.Setting = OPT_MENUITEMSETUNIQNAME;
+ op.Value = (INT_PTR)mi->pszService;
+ CallService(MO_SETOPTIONSMENUITEM,(WPARAM)0,(LPARAM)&op);
+ return (INT_PTR)op.Handle;
+
+ // mainItemCount++;
+ // return MENU_CUSTOMITEMMAIN|(mainMenuItem[mainItemCount-1].id);
+}
+
+INT_PTR TrayMenuonAddService(WPARAM wParam,LPARAM lParam) {
+
+ MENUITEMINFO *mii = (MENUITEMINFO* )wParam;
+ if (mii == NULL) return 0;
+
+ if (hTrayHideShowMainMenuItem == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_STATE;
+ mii->fState |= MFS_DEFAULT;
+
+ }
+ if (hTrayMainMenuItemProxy == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0);
+ }
+
+ if (hTrayStatusMenuItemProxy == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ }
+
+ return(TRUE);
+}
+
+//called with:
+//wparam - ownerdata
+//lparam - lparam from winproc
+INT_PTR TrayMenuExecService(WPARAM wParam,LPARAM lParam) {
+ if (wParam != 0)
+ {
+ lpTrayMenuExecParam mmep = (lpTrayMenuExecParam)wParam;
+ if ( !mir_strcmp(mmep->szServiceName,"Help/AboutCommand"))
+ {
+ //bug in help.c,it used wparam as parent window handle without reason.
+ mmep->Param1 = 0;
+ }
+ CallService(mmep->szServiceName,mmep->Param1,lParam);
+ }
+ return(1);
+}
+
+INT_PTR FreeOwnerDataTrayMenu (WPARAM wParam,LPARAM lParam)
+{
+
+ lpTrayMenuExecParam mmep;
+ mmep = (lpTrayMenuExecParam)lParam;
+ if (mmep != NULL){
+ FreeAndNil((void**)&mmep->szServiceName);
+ FreeAndNil((void**)&mmep);
+ }
+
+ return(0);
+}
+
+void InitTrayMenus(void)
+{
+ TMenuParam tmp;
+ OptParam op;
+
+ CreateServiceFunction("CLISTMENUSTRAY/ExecService",TrayMenuExecService);
+ CreateServiceFunction("CLISTMENUSTRAY/FreeOwnerDataTrayMenu",FreeOwnerDataTrayMenu);
+ CreateServiceFunction("CLISTMENUSTRAY/TrayMenuonAddService",TrayMenuonAddService);
+
+ CreateServiceFunction("CList/AddTrayMenuItem",AddTrayMenuItem);
+ CreateServiceFunction(MS_CLIST_REMOVETRAYMENUITEM,RemoveTrayMenuItem);
+ CreateServiceFunction(MS_CLIST_MENUBUILDTRAY,BuildTrayMenu);
+
+
+ //Tray menu
+ memset(&tmp,0,sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ tmp.CheckService = NULL;
+ tmp.ExecService = "CLISTMENUSTRAY/ExecService";
+ tmp.name = "TrayMenu";
+ hTrayMenuObject = (HANDLE)CallService(MO_CREATENEWMENUOBJECT,(WPARAM)0,(LPARAM)&tmp);
+
+
+ op.Handle = hTrayMenuObject;
+ op.Setting = OPT_USERDEFINEDITEMS;
+ op.Value = TRUE;
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ op.Handle = hTrayMenuObject;
+ op.Setting = OPT_MENUOBJECT_SET_FREE_SERVICE;
+ op.Value = (INT_PTR)"CLISTMENUSTRAY/FreeOwnerDataTrayMenu";
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ op.Handle = hTrayMenuObject;
+ op.Setting = OPT_MENUOBJECT_SET_ONADD_SERVICE;
+ op.Value = (INT_PTR)"CLISTMENUSTRAY/TrayMenuonAddService";
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ {
+ //add exit command to menu
+ CLISTMENUITEM mi;
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 900000;
+ mi.pszService = "CloseAction";
+ mi.pszName = LPGEN("E&xit");
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_EXIT);
+ AddTrayMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100000;
+ mi.pszService = MS_CLIST_SHOWHIDE;
+ mi.pszName = LPGEN("&Hide/Show");
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_SHOWHIDE);
+ hTrayHideShowMainMenuItem = (HANDLE)AddTrayMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 200000;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_FINDUSER);
+ mi.pszService = "FindAdd/FindAddCommand";
+ mi.pszName = LPGEN("&Find/Add Contacts...");
+ AddTrayMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 300000;
+ mi.flags = CMIF_ICONFROMICOLIB; // eternity #004
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_MAINMENU); // eternity #004
+ mi.pszService = "FakeService_1";
+ mi.pszName = LPGEN("&Main Menu");
+ hTrayMainMenuItemProxy = (HANDLE)AddTrayMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon); // eternity #004
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 300100;
+ mi.pszService = "FakeService_2";
+ mi.flags = CMIF_ICONFROMICOLIB; // eternity #004
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_STATUS); // eternity #004
+ mi.pszName = LPGEN("&Status");
+ hTrayStatusMenuItemProxy = (HANDLE)AddTrayMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon); // eternity #004
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 400000;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_OPTIONS);
+ mi.pszService = "Options/OptionsCommand";
+ mi.pszName = LPGEN("&Options...");
+ AddTrayMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 500000;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_MIRANDA);
+ mi.pszService = "Help/AboutCommand";
+ mi.pszName = LPGEN("&About");
+ AddTrayMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+ }
+
+ hMainMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0);
+ hStatusMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+}
+
+void UninitTrayMenu()
+{
+ if (hTrayMenuObject && ServiceExists(MO_REMOVEMENUOBJECT))
+ CallService(MO_REMOVEMENUOBJECT,(WPARAM)hTrayMenuObject,0);
+ hTrayMenuObject = NULL;
+}
+
+void InitTray(void)
+{
+ InitTrayMenus();
+ return;
+}
+
+//////////////////////////////END TRAY MENU/////////////////////////
diff --git a/plugins/Clist_modern/src/modern_clui.cpp b/plugins/Clist_modern/src/modern_clui.cpp
new file mode 100644
index 0000000000..fe27bc2a34
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_clui.cpp
@@ -0,0 +1,3111 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+
+listed in contributors.txt.
+
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "hdr/modern_commonheaders.h"
+
+#include "m_clc.h"
+#include "m_clui.h"
+#include "m_skin.h"
+#include "m_api/m_skinbutton.h"
+#include "hdr/modern_skinengine.h"
+#include "hdr/modern_statusbar.h"
+
+#include "hdr/modern_static_clui.h"
+#include <locale.h>
+#include "hdr/modern_clcpaint.h"
+#include "hdr/modern_sync.h"
+
+int ContactSettingChanged(WPARAM, LPARAM);
+
+HRESULT (WINAPI *g_proc_DWMEnableBlurBehindWindow)(HWND hWnd, DWM_BLURBEHIND *pBlurBehind);
+BOOL CALLBACK ProcessCLUIFrameInternalMsg(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT& result );
+void DestroyTrayMenu(HMENU hMenu);
+
+// new sources
+#ifdef _MSC_VER
+#include <crtdbg.h>
+#endif
+
+//////////////// CLUI CLASS IMPLEMENTATION /////////////////////////////////
+#include "hdr/modern_clui.h"
+
+#define STATIC_METHOD
+
+CLUI* CLUI::m_pCLUI = NULL;
+BOOL CLUI::m_fMainMenuInited = FALSE;
+HWND CLUI::m_hWnd = NULL;
+
+void CLUI::cliOnCreateClc(void)
+{
+ STATIC_METHOD;
+ _ASSERT( m_pCLUI );
+ m_pCLUI->CreateCluiFrames();
+}
+
+int CLUI::OnEvent_ModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ STATIC_METHOD;
+
+ g_CluiData.bMetaAvail = ServiceExists(MS_MC_GETDEFAULTCONTACT) ? TRUE : FALSE;
+ setlocale(LC_ALL, ""); //fix for case insensitive comparing
+
+ if (ServiceExists(MS_MC_DISABLEHIDDENGROUP))
+ CallService(MS_MC_DISABLEHIDDENGROUP, (WPARAM)TRUE, (LPARAM)0);
+
+ if (ServiceExists(MS_MC_GETPROTOCOLNAME))
+ g_szMetaModuleName = (char *)CallService(MS_MC_GETPROTOCOLNAME, 0, 0);
+
+ CLUIServices_ProtocolStatusChanged(0,0);
+ SleepEx(0,TRUE);
+ g_flag_bOnModulesLoadedCalled = TRUE;
+ ///pcli->pfnInvalidateDisplayNameCacheEntry(INVALID_HANDLE_VALUE);
+ SendMessage(pcli->hwndContactList,UM_CREATECLC,0,0); //$$$
+ InitSkinHotKeys();
+ g_CluiData.bSTATE = STATE_NORMAL;
+ ske_RedrawCompleteWindow();
+
+ return 0;
+}
+
+int CLUI::OnEvent_FontReload(WPARAM wParam,LPARAM lParam)
+{
+ STATIC_METHOD;
+
+ pcli->pfnClcBroadcast( INTM_RELOADOPTIONS, wParam, lParam );
+
+ g_CluiData.dwKeyColor = db_get_dw(NULL,"ModernSettings","KeyColor",(DWORD)SETTING_KEYCOLOR_DEFAULT);
+
+ CLUI__cliInvalidateRect( pcli->hwndContactList, 0, 0 );
+
+ return 0;
+}
+
+int CLUI::OnEvent_ContactMenuPreBuild(WPARAM wParam, LPARAM lParam)
+{
+ TCHAR cls[128];
+ HANDLE hItem;
+ HWND hwndClist = GetFocus();
+ CLISTMENUITEM mi;
+ if (MirandaExiting()) return 0;
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS;
+ GetClassName(hwndClist,cls,SIZEOF(cls));
+ hwndClist = (!lstrcmp(CLISTCONTROL_CLASS,cls))?hwndClist:pcli->hwndContactList;
+ hItem = (HANDLE)SendMessage(hwndClist,CLM_GETSELECTION,0,0);
+ if ( !hItem) {
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ }
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hRenameMenuItem, (LPARAM)&mi);
+
+ if ( !hItem || !IsHContactContact(hItem) || !db_get_b(NULL,"CList","AvatarsShow",SETTINGS_SHOWAVATARS_DEFAULT))
+ {
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hShowAvatarMenuItem, (LPARAM)&mi);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideAvatarMenuItem, (LPARAM)&mi);
+ }
+ else
+ {
+ int has_avatar;
+
+ if (ServiceExists(MS_AV_GETAVATARBITMAP))
+ {
+ has_avatar = CallService(MS_AV_GETAVATARBITMAP, (WPARAM)hItem, 0);
+ }
+ else
+ {
+ DBVARIANT dbv = {0};
+ if (DBGetContactSettingTString(hItem, "ContactPhoto", "File", &dbv))
+ {
+ has_avatar = 0;
+ }
+ else
+ {
+ has_avatar = 1;
+ db_free(&dbv);
+ }
+ }
+
+ if (db_get_b(hItem, "CList", "HideContactAvatar", 0))
+ {
+ mi.flags = CMIM_FLAGS | (has_avatar ? 0 : CMIF_GRAYED);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hShowAvatarMenuItem, (LPARAM)&mi);
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideAvatarMenuItem, (LPARAM)&mi);
+ }
+ else
+ {
+ mi.flags = CMIM_FLAGS | CMIF_HIDDEN;
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hShowAvatarMenuItem, (LPARAM)&mi);
+ mi.flags = CMIM_FLAGS | (has_avatar ? 0 : CMIF_GRAYED);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideAvatarMenuItem, (LPARAM)&mi);
+ }
+ }
+
+ return 0;
+}
+int CLUI::OnEvent_DBSettingChanging(WPARAM wParam,LPARAM lParam)
+{
+ if (ServiceExists("ExtraIcon/Register"))
+ return 0;
+
+ DBCONTACTWRITESETTING *dbcws = (DBCONTACTWRITESETTING *)lParam;
+ if (wParam == 0) return 0;
+ if (dbcws == NULL) return(0);
+ if (MirandaExiting()) return 0;
+
+ if (( dbcws->value.type == DBVT_WORD && !mir_strcmp(dbcws->szSetting,"ApparentMode")) ||
+ ( dbcws->value.type == DBVT_ASCIIZ &&
+ (( !mir_strcmp(dbcws->szSetting,"e-mail") ||
+ !mir_strcmp(dbcws->szSetting,"Mye-mail0") ||
+ !mir_strcmp(dbcws->szSetting,"Cellular")) ||
+ ( !mir_strcmp(dbcws->szModule,"UserInfo") &&
+ ( !mir_strcmp(dbcws->szSetting,"MyPhone0") ||
+ !mir_strcmp(dbcws->szSetting,"Mye-mail0"))))))
+ ExtraImage_SetAllExtraIcons(pcli->hwndContactTree,(HANDLE)wParam);
+ return(0);
+};
+INT_PTR CLUI::Service_ShowMainMenu(WPARAM wParam,LPARAM lParam)
+{
+ HMENU hMenu;
+ POINT pt;
+ hMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0);
+ GetCursorPos(&pt);
+ TrackPopupMenu(hMenu,TPM_TOPALIGN|TPM_LEFTALIGN|TPM_LEFTBUTTON,pt.x,pt.y,0,pcli->hwndContactList,NULL);
+ return 0;
+}
+INT_PTR CLUI::Service_ShowStatusMenu(WPARAM wParam,LPARAM lParam)
+{
+ HMENU hMenu;
+ POINT pt;
+ hMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ GetCursorPos(&pt);
+ TrackPopupMenu(hMenu,TPM_TOPALIGN|TPM_LEFTALIGN|TPM_LEFTBUTTON,pt.x,pt.y,0,pcli->hwndContactList,NULL);
+ return 0;
+}
+
+INT_PTR CLUI::Service_Menu_ShowContactAvatar(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE) wParam;
+
+ db_set_b(hContact, "CList", "HideContactAvatar", 0);
+
+ pcli->pfnClcBroadcast( INTM_AVATARCHANGED,wParam,0);
+ return 0;
+}
+
+INT_PTR CLUI::Service_Menu_HideContactAvatar(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE) wParam;
+
+ db_set_b(hContact, "CList", "HideContactAvatar", 1);
+
+ pcli->pfnClcBroadcast( INTM_AVATARCHANGED,wParam,0);
+ return 0;
+}
+
+
+
+HRESULT CLUI::CreateCluiFrames()
+{
+ g_hMenuMain = GetMenu(pcli->hwndContactList);
+ MENUITEMINFO mii;
+ ZeroMemory(&mii,sizeof(mii));
+ mii.cbSize = MENUITEMINFO_V4_SIZE;
+ mii.fMask = MIIM_SUBMENU;
+ mii.hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0);
+ SetMenuItemInfo(g_hMenuMain,0,TRUE,&mii);
+ mii.hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ SetMenuItemInfo(g_hMenuMain,1,TRUE,&mii);
+
+ CreateCLCWindow(CluiWnd());
+
+ CLUI_ChangeWindowMode();
+
+ RegisterAvatarMenu();
+
+ CLUI_ReloadCLUIOptions();
+
+ CreateUIFrames();
+
+ HookEvent(ME_SYSTEM_MODULESLOADED,CLUI::OnEvent_ModulesLoaded);
+ HookEvent(ME_SKIN2_ICONSCHANGED,CLUI_IconsChanged);
+ HookEvent(ME_FONT_RELOAD, CLUI::OnEvent_FontReload);
+ return S_OK;
+}
+CLUI::CLUI() :
+m_hUserDll( NULL ),
+m_hDwmapiDll( NULL )
+{
+ m_pCLUI = this;
+ g_CluiData.bSTATE = STATE_CLUI_LOADING;
+ LoadDllsRuntime();
+ hFrameContactTree = NULL;
+
+ CLUIServices_LoadModule();
+
+ // Call InitGroup menus before
+ GroupMenus_Init();
+
+ CreateServiceFunction(MS_CLUI_SHOWMAINMENU,Service_ShowMainMenu);
+ CreateServiceFunction(MS_CLUI_SHOWSTATUSMENU,Service_ShowStatusMenu);
+
+
+ //TODO Add Row template loading here.
+
+ RowHeight_InitModernRow();
+ nLastRequiredHeight = 0;
+
+ LoadCLUIFramesModule();
+ ExtraImage_LoadModule();
+
+ g_CluiData.boldHideOffline = -1;
+ bOldHideOffline = db_get_b(NULL,"CList","HideOffline",SETTING_HIDEOFFLINE_DEFAULT);
+
+ g_CluiData.bOldUseGroups = -1;
+ bOldUseGroups = db_get_b( NULL,"CList","UseGroups", SETTING_USEGROUPS_DEFAULT );
+}
+
+CLUI::~CLUI()
+{
+ FreeLibrary(m_hUserDll);
+ FreeLibrary(m_hDwmapiDll);
+ m_pCLUI = NULL;
+}
+
+HRESULT CLUI::LoadDllsRuntime()
+{
+ m_hUserDll = LoadLibrary(_T("user32.dll"));
+ if (m_hUserDll)
+ {
+ g_proc_UpdateLayeredWindow = (BOOL (WINAPI *)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD))GetProcAddress(m_hUserDll, "UpdateLayeredWindow");
+ g_proc_SetLayeredWindowAttributesNew = (BOOL (WINAPI *)(HWND,COLORREF,BYTE,DWORD))GetProcAddress(m_hUserDll, "SetLayeredWindowAttributes");
+ g_proc_AnimateWindow = (BOOL (WINAPI*)(HWND,DWORD,DWORD))GetProcAddress(m_hUserDll,"AnimateWindow");
+
+ g_CluiData.fLayered = (g_proc_UpdateLayeredWindow != NULL) && !db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT);
+ g_CluiData.fSmoothAnimation = IsWinVer2000Plus() && db_get_b(NULL, "CLUI", "FadeInOut", SETTING_FADEIN_DEFAULT);
+ g_CluiData.fLayered = (g_CluiData.fLayered*db_get_b(NULL, "ModernData", "EnableLayering", g_CluiData.fLayered)) && !db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT);
+ }
+
+ if (IsWinVerVistaPlus())
+ {
+ m_hDwmapiDll = LoadLibrary(_T("dwmapi.dll"));
+ if (m_hDwmapiDll)
+ {
+ g_proc_DWMEnableBlurBehindWindow = (HRESULT (WINAPI *)(HWND, DWM_BLURBEHIND *))GetProcAddress(m_hDwmapiDll, "DwmEnableBlurBehindWindow");
+ }
+ }
+ g_CluiData.fAeroGlass = FALSE;
+
+ return S_OK;
+}
+HRESULT CLUI::RegisterAvatarMenu()
+{
+ CLISTMENUITEM mi;
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = 0;
+ mi.pszContactOwner = NULL; //on every contact
+ CreateServiceFunction("CList/ShowContactAvatar",CLUI::Service_Menu_ShowContactAvatar);
+ mi.position = 2000150000;
+ mi.hIcon = LoadSmallIcon(g_hInst,MAKEINTRESOURCE(IDI_SHOW_AVATAR));
+ mi.pszName = LPGEN("Show Contact &Avatar");
+ mi.pszService = "CList/ShowContactAvatar";
+ hShowAvatarMenuItem = Menu_AddContactMenuItem(&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ CreateServiceFunction("CList/HideContactAvatar",CLUI::Service_Menu_HideContactAvatar);
+ mi.position = 2000150001;
+ mi.hIcon = LoadSmallIcon(g_hInst,MAKEINTRESOURCE(IDI_HIDE_AVATAR));
+ mi.pszName = LPGEN("Hide Contact &Avatar");
+ mi.pszService = "CList/HideContactAvatar";
+ hHideAvatarMenuItem = Menu_AddContactMenuItem(&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ HookEvent(ME_CLIST_PREBUILDCONTACTMENU, CLUI::OnEvent_ContactMenuPreBuild);
+
+ return S_OK;
+}
+
+HRESULT CLUI::CreateCLCWindow(const HWND hwndClui)
+{
+ ClcWnd() = CreateWindow(CLISTCONTROL_CLASS,_T(""),
+ WS_CHILD|WS_CLIPCHILDREN|CLS_CONTACTLIST
+ |(db_get_b(NULL,"CList","UseGroups",SETTING_USEGROUPS_DEFAULT)?CLS_USEGROUPS:0)
+ |(db_get_b(NULL,"CList","HideOffline",SETTING_HIDEOFFLINE_DEFAULT)?CLS_HIDEOFFLINE:0)
+ |(db_get_b(NULL,"CList","HideEmptyGroups",SETTING_HIDEEMPTYGROUPS_DEFAULT)?CLS_HIDEEMPTYGROUPS:0
+ |CLS_MULTICOLUMN
+ ),
+ 0,0,0,0,hwndClui,NULL,g_hInst,NULL);
+
+ return S_OK;
+}
+
+HRESULT CLUI::CreateUIFrames()
+{
+ EventArea_Create(pcli->hwndContactList);
+ CreateViewModeFrame();
+ pcli->hwndStatus = StatusBar_Create(pcli->hwndContactList);
+
+ return S_OK;
+}
+
+
+
+HRESULT CLUI::FillAlphaChannel( HDC hDC, RECT * prcParent, BYTE bAlpha)
+{
+
+ RECT rcWindow;
+ GetWindowRect( m_hWnd, &rcWindow );
+
+ HRGN hRgn = CreateRectRgn(0,0,0,0);
+
+ if ( GetWindowRgn(m_hWnd,hRgn) == ERROR )
+ {
+ DeleteObject(hRgn);
+ hRgn = CreateRectRgn(rcWindow.left ,rcWindow.top ,rcWindow.right,rcWindow.bottom);
+ }
+
+ OffsetRgn(hRgn,-prcParent->left,-prcParent->top);
+
+ RECT rcBounds;
+ GetRgnBox(hRgn,&rcBounds);
+
+ if ( IsRectEmpty(&rcBounds))
+ {
+ DeleteObject(hRgn);
+ return S_FALSE;
+ }
+
+ DWORD dwRgnSize = GetRegionData( hRgn, 0, NULL );
+ RGNDATA * rgnData = (RGNDATA *)malloc(dwRgnSize);
+ GetRegionData(hRgn,dwRgnSize,rgnData);
+
+ RECT * pRect = (RECT *)rgnData->Buffer;
+
+ for (DWORD i=0; i < rgnData->rdh.nCount; i++)
+ ske_SetRectOpaque( hDC, &pRect[i] );
+
+ free(rgnData);
+ DeleteObject(hRgn);
+
+ return S_OK;
+}
+
+HRESULT CLUI::CreateCLC()
+{
+ INIT < CLISTFrame> Frame;
+
+ Frame.hWnd = ClcWnd();
+ Frame.align = alClient;
+ Frame.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ Frame.Flags = F_VISIBLE|/*F_SHOWTB|*/F_SHOWTBTIP|F_NO_SUBCONTAINER|F_TCHAR;
+ Frame.tname = LPGENT("My Contacts");
+ Frame.TBtname = TranslateT("My Contacts");
+ hFrameContactTree = (HWND)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&Frame,(LPARAM)0);
+
+ CallService(MS_SKINENG_REGISTERPAINTSUB,(WPARAM)Frame.hWnd,(LPARAM)CLCPaint::PaintCallbackProc);
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_TBTIPNAME,hFrameContactTree),(LPARAM)Translate("My Contacts"));
+
+ ExtraImage_ReloadExtraIcons();
+
+ nLastRequiredHeight = 0;
+ if ( g_CluiData.current_viewmode[0] == '\0' )
+ {
+ if (bOldHideOffline != (BYTE)-1)
+ CallService( MS_CLIST_SETHIDEOFFLINE,(WPARAM)bOldHideOffline, 0);
+ else
+ CallService( MS_CLIST_SETHIDEOFFLINE,(WPARAM)0, 0);
+ if (bOldUseGroups != (BYTE)-1)
+ CallService( MS_CLIST_SETUSEGROUPS ,(WPARAM)bOldUseGroups, 0);
+ else
+ CallService( MS_CLIST_SETUSEGROUPS ,(WPARAM)bOldUseGroups, 0);
+ }
+ nLastRequiredHeight = 0;
+ mutex_bDisableAutoUpdate = 0;
+
+ HookEvent(ME_DB_CONTACT_SETTINGCHANGED, ContactSettingChanged);
+ HookEvent(ME_DB_CONTACT_SETTINGCHANGED,CLUI::OnEvent_DBSettingChanging);
+ return S_OK;
+
+};
+HRESULT CLUI::SnappingToEdge( WINDOWPOS * lpWindowPos )
+{
+ //by ZORG
+ if ( MyMonitorFromWindow == NULL || MyGetMonitorInfo == NULL )
+ return S_FALSE;
+
+ if (db_get_b(NULL,"CLUI","SnapToEdges",SETTING_SNAPTOEDGES_DEFAULT))
+ {
+ RECT* dr;
+ MONITORINFO monInfo;
+ HMONITOR curMonitor = MyMonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST);
+
+ monInfo.cbSize = sizeof(monInfo);
+ MyGetMonitorInfo(curMonitor, &monInfo);
+
+ dr = &(monInfo.rcWork);
+
+ // Left side
+ if ( lpWindowPos->x < dr->left + SNAPTOEDGESENSIVITY && lpWindowPos->x > dr->left - SNAPTOEDGESENSIVITY && g_CluiData.bBehindEdgeSettings != 1)
+ lpWindowPos->x = dr->left;
+
+ // Right side
+ if ( dr->right - lpWindowPos->x - lpWindowPos->cx < SNAPTOEDGESENSIVITY && dr->right - lpWindowPos->x - lpWindowPos->cx > -SNAPTOEDGESENSIVITY && g_CluiData.bBehindEdgeSettings != 2)
+ lpWindowPos->x = dr->right - lpWindowPos->cx;
+
+ // Top side
+ if ( lpWindowPos->y < dr->top + SNAPTOEDGESENSIVITY && lpWindowPos->y > dr->top - SNAPTOEDGESENSIVITY)
+ lpWindowPos->y = dr->top;
+
+ // Bottom side
+ if ( dr->bottom - lpWindowPos->y - lpWindowPos->cy < SNAPTOEDGESENSIVITY && dr->bottom - lpWindowPos->y - lpWindowPos->cy > -SNAPTOEDGESENSIVITY)
+ lpWindowPos->y = dr->bottom - lpWindowPos->cy;
+ }
+ return S_OK;
+}
+
+HICON GetMainStatusOverlay(int STATUS)
+{
+ return ImageList_GetIcon(hAvatarOverlays,g_pStatusOverlayIcons[STATUS-ID_STATUS_OFFLINE].listID,ILD_NORMAL);
+}
+
+void UnloadAvatarOverlayIcon()
+{
+ for (int i=0 ; i < MAX_REGS(g_pAvatarOverlayIcons); i++) {
+ g_pAvatarOverlayIcons[i].listID = -1;
+ g_pStatusOverlayIcons[i].listID = -1;
+ }
+ ImageList_Destroy(hAvatarOverlays);
+ hAvatarOverlays = NULL;
+ DestroyIcon_protect(g_hListeningToIcon);
+ g_hListeningToIcon = NULL;
+}
+
+BOOL CLUI_CheckOwnedByClui(HWND hWnd)
+{
+ HWND hWndMid, hWndClui;
+ if ( !hWnd) return FALSE;
+ hWndClui = pcli->hwndContactList;
+ hWndMid = fnGetAncestor(hWnd,GA_ROOTOWNER);
+ if (hWndMid == hWndClui) return TRUE;
+ {
+ TCHAR buf[255];
+ GetClassName(hWndMid,buf,254);
+ if ( !mir_tstrcmpi(buf,CLUIFrameSubContainerClassName)) return TRUE;
+ }
+ return FALSE;
+}
+
+int CLUI_ShowWindowMod(HWND hWnd, int nCmd)
+{
+ int res = 0;
+
+ if (hWnd == pcli->hwndContactList && (nCmd == SW_HIDE || nCmd == SW_MINIMIZE))
+ {
+ AniAva_InvalidateAvatarPositions(NULL);
+ AniAva_RemoveInvalidatedAvatars();
+ }
+
+ if (hWnd == pcli->hwndContactList
+ && !g_mutex_bChangingMode
+ && nCmd == SW_HIDE
+ && !g_CluiData.fLayered
+ && IsWinVerXPPlus()
+ && db_get_b(NULL,"CList","WindowShadow",SETTING_WINDOWSHADOW_DEFAULT))
+ {
+ ShowWindow(hWnd,SW_MINIMIZE); //removing of shadow
+ return ShowWindow(hWnd,nCmd);
+ }
+ if (hWnd == pcli->hwndContactList
+ && !g_mutex_bChangingMode
+ && nCmd == SW_RESTORE
+ && !g_CluiData.fLayered
+ && IsWinVerXPPlus()
+ && g_CluiData.fSmoothAnimation
+ && !g_bTransparentFlag
+ )
+ {
+ if (db_get_b(NULL,"CList","WindowShadow",SETTING_WINDOWSHADOW_DEFAULT))
+ {
+ CLUI_SmoothAlphaTransition(hWnd, 255, 1);
+ }
+ else
+ {
+
+ int ret = ShowWindow(hWnd,nCmd);
+ CLUI_SmoothAlphaTransition(hWnd, 255, 1);
+ return ret;
+ }
+ }
+ return ShowWindow(hWnd,nCmd);
+}
+
+static BOOL CLUI_WaitThreadsCompletion(HWND hwnd)
+{
+ static BYTE bEntersCount = 0;
+ static const BYTE bcMAX_AWAITING_RETRY = 10; //repeat awaiting only 10 times
+ TRACE("CLUI_WaitThreadsCompletion Enter");
+ if (bEntersCount < bcMAX_AWAITING_RETRY
+ && ( g_mutex_nCalcRowHeightLock ||
+ g_CluiData.mutexPaintLock ||
+ g_dwAwayMsgThreadID ||
+ g_dwGetTextAsyncThreadID ||
+ g_dwSmoothAnimationThreadID ||
+ g_dwFillFontListThreadID)
+ && !Miranda_Terminated())
+ {
+ TRACE("Waiting threads");
+ TRACEVAR("g_mutex_nCalcRowHeightLock: %x",g_mutex_nCalcRowHeightLock);
+ TRACEVAR("g_CluiData.mutexPaintLock: %x",g_CluiData.mutexPaintLock);
+ TRACEVAR("g_dwAwayMsgThreadID: %x",g_dwAwayMsgThreadID);
+ TRACEVAR("g_dwGetTextAsyncThreadID: %x",g_dwGetTextAsyncThreadID);
+ TRACEVAR("g_dwSmoothAnimationThreadID: %x",g_dwSmoothAnimationThreadID);
+ TRACEVAR("g_dwFillFontListThreadID: %x",g_dwFillFontListThreadID);
+ bEntersCount++;
+ SleepEx(10,TRUE);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void CLUI_UpdateLayeredMode()
+{
+ g_CluiData.fDisableSkinEngine = db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT);
+ if (IsWinVer2000Plus())
+ {
+ BOOL tLayeredFlag = TRUE;
+ tLayeredFlag &= (db_get_b(NULL, "ModernData", "EnableLayering", tLayeredFlag) && !g_CluiData.fDisableSkinEngine);
+
+ if (g_CluiData.fLayered != tLayeredFlag)
+ {
+ LONG exStyle;
+ BOOL fWasVisible = IsWindowVisible(pcli->hwndContactList);
+ if (fWasVisible) ShowWindow(pcli->hwndContactList,SW_HIDE);
+ //change layered mode
+ exStyle = GetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE);
+ if (tLayeredFlag)
+ exStyle |= WS_EX_LAYERED;
+ else
+ exStyle &= ~WS_EX_LAYERED;
+ SetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE,exStyle&~WS_EX_LAYERED);
+ SetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE,exStyle);
+ g_CluiData.fLayered = tLayeredFlag;
+ Sync(CLUIFrames_SetLayeredMode, tLayeredFlag,pcli->hwndContactList);
+ CLUI_ChangeWindowMode();
+ Sync(CLUIFrames_OnClistResize_mod, (WPARAM)0, (LPARAM)0 );
+ if (fWasVisible) ShowWindow(pcli->hwndContactList,SW_SHOW);
+ }
+ }
+}
+
+void CLUI_UpdateAeroGlass()
+{
+ BOOL tAeroGlass = db_get_b(NULL, "ModernData", "AeroGlass", SETTING_AEROGLASS_DEFAULT) && (g_CluiData.fLayered);
+ if (g_proc_DWMEnableBlurBehindWindow && (tAeroGlass != g_CluiData.fAeroGlass))
+ {
+ if (g_CluiData.hAeroGlassRgn)
+ {
+ DeleteObject(g_CluiData.hAeroGlassRgn);
+ g_CluiData.hAeroGlassRgn = 0;
+ }
+
+ DWM_BLURBEHIND bb = {0};
+ bb.dwFlags = DWM_BB_ENABLE;
+ bb.fEnable = tAeroGlass;
+
+ if (tAeroGlass)
+ {
+ g_CluiData.hAeroGlassRgn = ske_CreateOpaqueRgn(AEROGLASS_MINALPHA, true);
+ bb.hRgnBlur = g_CluiData.hAeroGlassRgn;
+ bb.dwFlags |= DWM_BB_BLURREGION;
+ }
+
+ g_proc_DWMEnableBlurBehindWindow(pcli->hwndContactList, &bb);
+ g_CluiData.fAeroGlass = tAeroGlass;
+ }
+}
+
+extern int CLUIFrames_UpdateBorders();
+
+void CLUI_ChangeWindowMode()
+{
+ BOOL storedVisMode = FALSE;
+ LONG style,styleEx;
+ LONG oldStyle,oldStyleEx;
+ LONG styleMask = WS_CLIPCHILDREN|WS_BORDER|WS_CAPTION|WS_MINIMIZEBOX|WS_POPUPWINDOW|WS_CLIPCHILDREN|WS_THICKFRAME|WS_SYSMENU;
+ LONG styleMaskEx = WS_EX_TOOLWINDOW|WS_EX_LAYERED;
+ LONG curStyle,curStyleEx;
+ if ( !pcli->hwndContactList) return;
+
+ g_mutex_bChangingMode = TRUE;
+ g_bTransparentFlag = IsWinVer2000Plus() && db_get_b( NULL,"CList","Transparent",SETTING_TRANSPARENT_DEFAULT);
+ g_CluiData.fSmoothAnimation = IsWinVer2000Plus() && db_get_b(NULL, "CLUI", "FadeInOut", SETTING_FADEIN_DEFAULT);
+ if (g_bTransparentFlag == 0 && g_CluiData.bCurrentAlpha != 0)
+ g_CluiData.bCurrentAlpha = 255;
+ //2- Calculate STYLES and STYLESEX
+ if ( !g_CluiData.fLayered)
+ {
+ style = 0;
+ styleEx = 0;
+ if (db_get_b(NULL,"CList","ThinBorder",SETTING_THINBORDER_DEFAULT) || (db_get_b(NULL,"CList","NoBorder",SETTING_NOBORDER_DEFAULT)))
+ {
+ style = WS_CLIPCHILDREN| (db_get_b(NULL,"CList","ThinBorder",SETTING_THINBORDER_DEFAULT)?WS_BORDER:0);
+ styleEx = WS_EX_TOOLWINDOW;
+ styleMaskEx |= WS_EX_APPWINDOW;
+ }
+ else if (db_get_b(NULL,"CLUI","ShowCaption",SETTING_SHOWCAPTION_DEFAULT) && db_get_b(NULL,"CList","ToolWindow",SETTING_TOOLWINDOW_DEFAULT))
+ {
+ styleEx = WS_EX_TOOLWINDOW/*|WS_EX_WINDOWEDGE*/;
+ style = WS_CAPTION|WS_POPUPWINDOW|WS_CLIPCHILDREN|WS_THICKFRAME;
+ styleMaskEx |= WS_EX_APPWINDOW;
+ }
+ else if (db_get_b(NULL,"CLUI","ShowCaption",SETTING_SHOWCAPTION_DEFAULT))
+ {
+ style = WS_CAPTION|WS_SYSMENU|WS_POPUPWINDOW|WS_CLIPCHILDREN|WS_THICKFRAME|WS_MINIMIZEBOX;
+ }
+ else
+ {
+ style = WS_POPUPWINDOW|WS_CLIPCHILDREN|WS_THICKFRAME;
+ styleEx = WS_EX_TOOLWINDOW/*|WS_EX_WINDOWEDGE*/;
+ styleMaskEx |= WS_EX_APPWINDOW;
+ }
+ }
+ else
+ {
+ style = WS_CLIPCHILDREN;
+ styleEx = WS_EX_TOOLWINDOW;
+ styleMaskEx |= WS_EX_APPWINDOW;
+ }
+ //3- TODO Update Layered mode
+ if (g_bTransparentFlag && g_CluiData.fLayered)
+ styleEx |= WS_EX_LAYERED;
+
+ //4- Set Title
+ {
+ TCHAR titleText[255] = {0};
+ DBVARIANT dbv = {0};
+ if (DBGetContactSettingTString(NULL,"CList","TitleText",&dbv))
+ lstrcpyn(titleText,_T(MIRANDANAME),SIZEOF(titleText));
+ else
+ {
+ lstrcpyn(titleText,dbv.ptszVal,SIZEOF(titleText));
+ db_free(&dbv);
+ }
+ SetWindowText(pcli->hwndContactList,titleText);
+ }
+ // < ->
+ //1- If visible store it and hide
+
+ if (g_CluiData.fLayered && (db_get_b(NULL,"CList","OnDesktop", SETTING_ONDESKTOP_DEFAULT)))// && !flag_bFirstTimeCall))
+ {
+ SetParent(pcli->hwndContactList,NULL);
+ Sync( CLUIFrames_SetParentForContainers, (HWND) NULL );
+ UpdateWindow(pcli->hwndContactList);
+ g_CluiData.fOnDesktop = 0;
+ }
+ //5- TODO Apply Style
+ oldStyleEx = curStyleEx = GetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE);
+ oldStyle = curStyle = GetWindowLongPtr(pcli->hwndContactList,GWL_STYLE);
+
+ curStyleEx = (curStyleEx & ~styleMaskEx) | styleEx;
+ curStyle = (curStyle & ~styleMask) | style;
+ if (oldStyleEx != curStyleEx || oldStyle != curStyle)
+ {
+ if (IsWindowVisible(pcli->hwndContactList))
+ {
+ storedVisMode = TRUE;
+ mutex_bShowHideCalledFromAnimation = TRUE;
+ ShowWindow(pcli->hwndContactList,SW_HIDE);
+ Sync(CLUIFrames_OnShowHide, pcli->hwndContactList,0);
+ }
+ SetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE,curStyleEx);
+ SetWindowLongPtr(pcli->hwndContactList,GWL_STYLE,curStyle);
+ }
+
+ CLUI_UpdateAeroGlass();
+
+ if (g_CluiData.fLayered || !db_get_b(NULL,"CLUI","ShowMainMenu",SETTING_SHOWMAINMENU_DEFAULT))
+ {
+ HMENU m = GetMenu(pcli->hwndContactList);
+ SetMenu(pcli->hwndContactList,NULL);
+ }
+ else
+ SetMenu(pcli->hwndContactList,g_hMenuMain);
+
+ if (g_CluiData.fLayered && (db_get_b(NULL,"CList","OnDesktop", SETTING_ONDESKTOP_DEFAULT)))
+ ske_UpdateWindowImage();
+
+
+ //6- Pin to desktop mode
+ if (db_get_b(NULL,"CList","OnDesktop", SETTING_ONDESKTOP_DEFAULT))
+ {
+ HWND hProgMan = FindWindow(_T("Progman"),NULL);
+ if (IsWindow(hProgMan))
+ {
+ SetParent(pcli->hwndContactList,hProgMan);
+ Sync( CLUIFrames_SetParentForContainers, (HWND) hProgMan );
+ g_CluiData.fOnDesktop = 1;
+ }
+ }
+ else
+ {
+ // HWND parent = GetParent(pcli->hwndContactList);
+ // HWND progman = FindWindow(_T("Progman"),NULL);
+ // if (parent == progman)
+ {
+ SetParent(pcli->hwndContactList,NULL);
+ Sync(CLUIFrames_SetParentForContainers, (HWND) NULL);
+ }
+ g_CluiData.fOnDesktop = 0;
+ }
+
+ //7- if it was visible - show
+ if (storedVisMode)
+ {
+ ShowWindow(pcli->hwndContactList,SW_SHOW);
+ Sync(CLUIFrames_OnShowHide, pcli->hwndContactList,1);
+ }
+ mutex_bShowHideCalledFromAnimation = FALSE;
+
+ CLUIFrames_UpdateBorders();
+
+ if ( !g_CluiData.fLayered)
+ {
+ HRGN hRgn1;
+ RECT r;
+ int v,h;
+ int w = 10;
+ GetWindowRect(pcli->hwndContactList,&r);
+ h = (r.right-r.left)>(w*2)?w:(r.right-r.left);
+ v = (r.bottom-r.top)>(w*2)?w:(r.bottom-r.top);
+ h = (h < v)?h:v;
+ hRgn1 = CreateRoundRectRgn(0,0,(r.right-r.left+1),(r.bottom-r.top+1),h,h);
+ if ((db_get_b(NULL,"CLC","RoundCorners",SETTING_ROUNDCORNERS_DEFAULT)) && (!CallService(MS_CLIST_DOCKINGISDOCKED,0,0)))
+ SetWindowRgn(pcli->hwndContactList,hRgn1,1);
+ else
+ {
+ DeleteObject(hRgn1);
+ SetWindowRgn(pcli->hwndContactList,NULL,1);
+ }
+
+ RedrawWindow(pcli->hwndContactList,NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_FRAME|RDW_UPDATENOW|RDW_ALLCHILDREN);
+ }
+ g_mutex_bChangingMode = FALSE;
+ flag_bFirstTimeCall = TRUE;
+ AniAva_UpdateParent();
+}
+struct _tagTimerAsync
+{
+ HWND hwnd;
+ int ID;
+ int Timeout;
+ TIMERPROC proc;
+};
+static UINT_PTR SetTimerSync(WPARAM wParam , LPARAM lParam)
+{
+ struct _tagTimerAsync * call = (struct _tagTimerAsync *) wParam;
+ return SetTimer(call->hwnd, call->ID ,call->Timeout, call->proc);
+}
+
+UINT_PTR CLUI_SafeSetTimer(HWND hwnd, int ID, int Timeout, TIMERPROC proc)
+{
+ struct _tagTimerAsync param = { hwnd, ID, Timeout, proc };
+ return Sync(SetTimerSync, (WPARAM) &param, (LPARAM) 0);
+}
+
+int CLUI_UpdateTimer(BYTE BringIn)
+{
+ if (g_CluiData.nBehindEdgeState == 0)
+ {
+ KillTimer(pcli->hwndContactList,TM_BRINGOUTTIMEOUT);
+ CLUI_SafeSetTimer(pcli->hwndContactList,TM_BRINGOUTTIMEOUT,wBehindEdgeHideDelay*100,NULL);
+ }
+ if (bShowEventStarted == 0 && g_CluiData.nBehindEdgeState>0 )
+ {
+ KillTimer(pcli->hwndContactList,TM_BRINGINTIMEOUT);
+ bShowEventStarted = (BOOL)CLUI_SafeSetTimer(pcli->hwndContactList,TM_BRINGINTIMEOUT,wBehindEdgeShowDelay*100,NULL);
+ }
+ return 0;
+}
+
+int CLUI_HideBehindEdge()
+{
+ int method = g_CluiData.bBehindEdgeSettings;
+ if (method)
+ {
+ // if (DBGetContactSettingByte(NULL, "ModernData", "BehindEdge", SETTING_BEHINDEDGE_DEFAULT) == 0)
+ {
+ RECT rcScreen;
+ RECT rcWindow;
+ int bordersize = 0;
+ //Need to be moved out of screen
+ bShowEventStarted = 0;
+ //1. get work area rectangle
+ Docking_GetMonitorRectFromWindow(pcli->hwndContactList,&rcScreen);
+ //SystemParametersInfo(SPI_GETWORKAREA,0,&rcScreen,FALSE);
+ //2. move out
+ bordersize = wBehindEdgeBorderSize;
+ GetWindowRect(pcli->hwndContactList,&rcWindow);
+ switch (method)
+ {
+ case 1: //left
+ rcWindow.left = rcScreen.left-(rcWindow.right-rcWindow.left)+bordersize;
+ break;
+ case 2: //right
+ rcWindow.left = rcScreen.right-bordersize;
+ break;
+ }
+ g_CluiData.mutexPreventDockMoving = 0;
+ SetWindowPos(pcli->hwndContactList,NULL,rcWindow.left,rcWindow.top,0,0,SWP_NOZORDER|SWP_NOSIZE|SWP_NOACTIVATE);
+ Sync(CLUIFrames_OnMoving,pcli->hwndContactList,&rcWindow);
+ g_CluiData.mutexPreventDockMoving = 1;
+
+ //3. store setting
+ db_set_b(NULL, "ModernData", "BehindEdge",method);
+ g_CluiData.nBehindEdgeState = method;
+ return 1;
+ }
+ return 2;
+ }
+ return 0;
+}
+
+
+int CLUI_ShowFromBehindEdge()
+{
+ int method = g_CluiData.bBehindEdgeSettings;
+ bShowEventStarted = 0;
+ if (g_mutex_bOnTrayRightClick)
+ {
+ g_mutex_bOnTrayRightClick = 0;
+ return 0;
+ }
+ if (method)// && (DBGetContactSettingByte(NULL, "ModernData", "BehindEdge", SETTING_BEHINDEDGE_DEFAULT) == 0))
+ {
+ RECT rcScreen;
+ RECT rcWindow;
+ int bordersize = 0;
+ //Need to be moved out of screen
+
+ //1. get work area rectangle
+ //SystemParametersInfo(SPI_GETWORKAREA,0,&rcScreen,FALSE);
+ Docking_GetMonitorRectFromWindow(pcli->hwndContactList,&rcScreen);
+ //2. move out
+ bordersize = wBehindEdgeBorderSize;
+ GetWindowRect(pcli->hwndContactList,&rcWindow);
+ switch (method)
+ {
+ case 1: //left
+ rcWindow.left = rcScreen.left;
+ break;
+ case 2: //right
+ rcWindow.left = rcScreen.right-(rcWindow.right-rcWindow.left);
+ break;
+ }
+ g_CluiData.mutexPreventDockMoving = 0;
+ SetWindowPos(pcli->hwndContactList,NULL,rcWindow.left,rcWindow.top,0,0,SWP_NOZORDER|SWP_NOSIZE);
+ Sync(CLUIFrames_OnMoving,pcli->hwndContactList,&rcWindow);
+ g_CluiData.mutexPreventDockMoving = 1;
+
+ //3. store setting
+ db_set_b(NULL, "ModernData", "BehindEdge",0);
+ g_CluiData.nBehindEdgeState = 0;
+ }
+ return 0;
+}
+
+
+int CLUI_IsInMainWindow(HWND hwnd)
+{
+ if (hwnd == pcli->hwndContactList) return 1;
+ if (GetParent(hwnd) == pcli->hwndContactList) return 2;
+ return 0;
+}
+
+int CLUI_OnSkinLoad(WPARAM wParam, LPARAM lParam)
+{
+ ske_LoadSkinFromDB();
+
+ return 0;
+}
+
+
+
+
+static LPPROTOTICKS CLUI_GetProtoTicksByProto(char * szProto)
+{
+ int i;
+
+ for (i=0;i < 64;i++)
+ {
+ if (CycleStartTick[i].szProto == NULL) break;
+ if (mir_strcmp(CycleStartTick[i].szProto,szProto)) continue;
+ return(&CycleStartTick[i]);
+ }
+ for (i=0;i < 64;i++)
+ {
+ if (CycleStartTick[i].szProto == NULL)
+ {
+ CycleStartTick[i].szProto = mir_strdup(szProto);
+ CycleStartTick[i].nCycleStartTick = 0;
+ CycleStartTick[i].nIndex = i;
+ CycleStartTick[i].bGlobal = ( szProto[0] == 0 );
+ CycleStartTick[i].himlIconList = NULL;
+ return(&CycleStartTick[i]);
+ }
+ }
+ return (NULL);
+}
+
+static int CLUI_GetConnectingIconForProtoCount(char *szAccoName)
+{
+ char fileFull[MAX_PATH];
+ static char szFolderPath[MAX_PATH] = "";
+
+ int count = 8;
+
+ if ( !szFolderPath[0] )
+ {
+ char szRelativePath[MAX_PATH];
+ GetModuleFileNameA(GetModuleHandle(NULL), szRelativePath, MAX_PATH);
+ char *str = strrchr( szRelativePath, '\\' );
+ if ( str != NULL ) *str = 0;
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)szRelativePath, (LPARAM)szFolderPath);
+ }
+
+ if ( szAccoName )
+ {
+ // first of all try to find by account name( or empty - global )
+ mir_snprintf( fileFull, SIZEOF(fileFull), "%s\\Icons\\proto_conn_%s.dll", szFolderPath, szAccoName );
+ count = ExtractIconExA(fileFull,-1,NULL,NULL,1);
+ if ( count ) return count;
+
+ if ( szAccoName[0] )
+ {
+ // second try to find by protocol name
+ PROTOACCOUNT * acc = ProtoGetAccount( szAccoName );
+ if ( acc && !acc->bOldProto )
+ {
+ mir_snprintf( fileFull, SIZEOF(fileFull), "%s\\Icons\\proto_conn_%s.dll", szFolderPath, acc->szProtoName );
+ count = ExtractIconExA(fileFull,-1,NULL,NULL,1);
+ if ( count ) return count;
+ }
+ }
+ }
+ // third try global
+ mir_snprintf( fileFull, SIZEOF(fileFull), "%s\\Icons\\proto_conn.dll", szFolderPath );
+ count = ExtractIconExA(fileFull,-1,NULL,NULL,1);
+ if ( count ) return count;
+
+ return 8;
+}
+
+static HICON CLUI_ExtractIconFromPath(const char *path, BOOL * needFree)
+{
+ char *comma;
+ char file[MAX_PATH],fileFull[MAX_PATH];
+ int n;
+ HICON hIcon;
+ lstrcpynA(file,path,sizeof(file));
+ comma = strrchr(file,',');
+ if (comma == NULL) n = 0;
+ else {n = atoi(comma+1); *comma = 0;}
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)file, (LPARAM)fileFull);
+ hIcon = NULL;
+ ExtractIconExA(fileFull,n,NULL,&hIcon,1);
+ if (needFree)
+ {
+ *needFree = (hIcon != NULL);
+ }
+ return hIcon;
+}
+
+HICON CLUI_LoadIconFromExternalFile(char *filename,int i,BOOL UseLibrary,bool registerit,char *IconName,char *SectName,char *Description,int internalidx, BOOL * needFree)
+{
+ char szPath[MAX_PATH],szMyPath[MAX_PATH], szFullPath[MAX_PATH],*str;
+ HICON hIcon = NULL;
+ BOOL has_proto_icon = FALSE;
+ SKINICONDESC sid = {0};
+ if (needFree) *needFree = FALSE;
+ GetModuleFileNameA(GetModuleHandle(NULL), szPath, MAX_PATH);
+ GetModuleFileNameA(g_hInst, szMyPath, MAX_PATH);
+ str = strrchr(szPath,'\\');
+ if (str != NULL) *str = 0;
+ if (UseLibrary&2)
+ mir_snprintf(szMyPath, SIZEOF(szMyPath), "%s\\Icons\\%s", szPath, filename);
+ mir_snprintf(szFullPath, SIZEOF(szFullPath), "%s\\Icons\\%s,%d", szPath, filename, i);
+ if (str != NULL) *str = '\\';
+ if (UseLibrary&2)
+ {
+ BOOL nf;
+ HICON hi = CLUI_ExtractIconFromPath(szFullPath,&nf);
+ if (hi) has_proto_icon = TRUE;
+ if (hi && nf) DestroyIcon(hi);
+ }
+ if ( !UseLibrary) {
+ hIcon = CLUI_ExtractIconFromPath(szFullPath,needFree);
+ if (hIcon) return hIcon;
+ if (UseLibrary)
+ {
+ mir_snprintf(szFullPath, SIZEOF(szFullPath), "%s,%d", szMyPath, internalidx);
+ hIcon = CLUI_ExtractIconFromPath(szFullPath,needFree);
+ if (hIcon) return hIcon;
+ }
+ }
+ else {
+ if (registerit && IconName != NULL && SectName != NULL) {
+ sid.cbSize = sizeof(sid);
+ sid.cx = 16;
+ sid.cy = 16;
+ sid.hDefaultIcon = (has_proto_icon || !(UseLibrary&2))?NULL:(HICON)CallService(MS_SKIN_LOADPROTOICON,(WPARAM)NULL,(LPARAM)(-internalidx));
+ sid.pszSection = SectName;
+ sid.pszName = IconName;
+ sid.pszDescription = Description;
+ sid.pszDefaultFile = internalidx < 0?szMyPath:szPath;
+
+ sid.iDefaultIndex = (UseLibrary&2)?i:(internalidx < 0)?internalidx:-internalidx;
+ Skin_AddIcon(&sid);
+ }
+ return ((HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)IconName));
+ }
+
+
+
+
+ return (HICON)0;
+}
+
+static HICON CLUI_GetConnectingIconForProto(char *szAccoName, int b)
+{
+ char szFullPath[MAX_PATH];
+ HICON hIcon = NULL;
+ BOOL needFree;
+ b = b-1;
+
+ if ( szAccoName )
+ {
+ mir_snprintf(szFullPath, SIZEOF(szFullPath), "proto_conn_%s.dll",szAccoName);
+ hIcon = CLUI_LoadIconFromExternalFile(szFullPath,b+1,FALSE,FALSE,NULL,NULL,NULL,0,&needFree);
+ if (hIcon) return hIcon;
+
+ if ( szAccoName[0] )
+ {
+ // second try to find by protocol name
+ PROTOACCOUNT * acc = ProtoGetAccount( szAccoName );
+ if ( acc && !acc->bOldProto )
+ {
+ mir_snprintf( szFullPath, SIZEOF(szFullPath), "proto_conn_%s.dll", acc->szProtoName );
+ hIcon = CLUI_LoadIconFromExternalFile(szFullPath,b+1,FALSE,FALSE,NULL,NULL,NULL,0,&needFree);
+ if ( hIcon ) return hIcon;
+ }
+ }
+ }
+ // third try global
+ mir_snprintf( szFullPath, SIZEOF(szFullPath), "proto_conn.dll" );
+ hIcon = CLUI_LoadIconFromExternalFile(szFullPath,b+1,FALSE,FALSE,NULL,NULL,NULL,0,&needFree);
+ if ( hIcon ) return hIcon;
+
+ hIcon = LoadSmallIcon(g_hInst,(TCHAR *)(IDI_ICQC1+b+1));
+ return(hIcon);
+}
+
+
+INT_PTR CLUI_GetConnectingIconService(WPARAM wParam,LPARAM lParam)
+{
+ int b;
+ PROTOTICKS *pt = NULL;
+ HICON hIcon = NULL;
+
+ char *szProto = (char *)wParam;
+ if ( !szProto) return 0;
+
+ pt = CLUI_GetProtoTicksByProto(szProto);
+
+ if (pt != NULL)
+ {
+ if (pt->nCycleStartTick == 0)
+ {
+ CLUI_CreateTimerForConnectingIcon(ID_STATUS_CONNECTING,wParam);
+ pt = CLUI_GetProtoTicksByProto(szProto);
+ }
+ }
+ if (pt != NULL)
+ {
+ if (pt->nCycleStartTick != 0 && pt->nIconsCount != 0)
+ {
+ b = ((GetTickCount()-pt->nCycleStartTick)/(nAnimatedIconStep))%(pt->nIconsCount);
+ // if (lParam)
+ // hIcon = CLUI_GetConnectingIconForProto("Global",b);
+ // else
+ if (pt->himlIconList)
+ hIcon = ske_ImageList_GetIcon(pt->himlIconList,b,ILD_NORMAL);
+ else
+ hIcon = NULL;
+ //hIcon = CLUI_GetConnectingIconForProto(szProto,b);
+ };
+ }
+
+
+ return (INT_PTR)hIcon;
+};
+
+
+static int CLUI_CreateTimerForConnectingIcon(WPARAM wParam,LPARAM lParam)
+{
+
+ int status = (int)wParam;
+ char *szProto = (char *)lParam;
+ if ( !szProto) return (0);
+ if ( !status) return (0);
+
+ if ((g_StatusBarData.connectingIcon == 1) && status >= ID_STATUS_CONNECTING && status <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES)
+ {
+
+ PROTOTICKS *pt = NULL;
+ int cnt;
+
+ pt = CLUI_GetProtoTicksByProto(szProto);
+ if (pt != NULL)
+ {
+ if (pt->nCycleStartTick == 0)
+ {
+ KillTimer(pcli->hwndContactList,TM_STATUSBARUPDATE+pt->nIndex);
+ cnt = CLUI_GetConnectingIconForProtoCount(szProto);
+ if (cnt != 0)
+ {
+ int i=0;
+ nAnimatedIconStep = 100;/*DBGetContactSettingWord(NULL,"CLUI","DefaultStepConnectingIcon",100);*/
+ pt->nIconsCount = cnt;
+ if (pt->himlIconList) ImageList_Destroy(pt->himlIconList);
+ pt->himlIconList = ImageList_Create(16,16,ILC_MASK|ILC_COLOR32,cnt,1);
+ for (i=0; i < cnt; i++)
+ {
+ HICON ic = CLUI_GetConnectingIconForProto(szProto,i);
+ if (ic) ImageList_AddIcon(pt->himlIconList,ic);
+ DestroyIcon_protect(ic);
+ }
+ CLUI_SafeSetTimer(pcli->hwndContactList,TM_STATUSBARUPDATE+pt->nIndex,(int)(nAnimatedIconStep)/1,0);
+ pt->bTimerCreated = 1;
+ pt->nCycleStartTick = GetTickCount();
+ }
+
+ };
+ };
+ }
+ return 0;
+}
+
+static BOOL CALLBACK BroadcastEnumChildProc(HWND hwndChild, LPARAM lParam)
+{
+ MSG * pMsg = (MSG*)lParam;
+ SendNotifyMessage( hwndChild, pMsg->message, pMsg->wParam, pMsg->lParam );
+ EnumChildWindows( hwndChild, BroadcastEnumChildProc, lParam );
+ return TRUE;
+}
+
+static LRESULT BroadCastMessageToChild(HWND hwnd, int message, WPARAM wParam, LPARAM lParam )
+{
+ MSG msg = {0};
+ msg.hwnd = hwnd;
+ msg.lParam = lParam;
+ msg.wParam = wParam;
+ msg.message = message;
+ EnumChildWindows(hwnd, BroadcastEnumChildProc, (LPARAM) &msg);
+ return 1;
+}
+
+int CLUI_ReloadCLUIOptions()
+{
+ KillTimer(pcli->hwndContactList,TM_UPDATEBRINGTIMER);
+ g_CluiData.bBehindEdgeSettings = db_get_b(NULL, "ModernData", "HideBehind", SETTING_HIDEBEHIND_DEFAULT);
+ wBehindEdgeShowDelay = db_get_w(NULL,"ModernData","ShowDelay",SETTING_SHOWDELAY_DEFAULT);
+ wBehindEdgeHideDelay = db_get_w(NULL,"ModernData","HideDelay",SETTING_HIDEDELAY_DEFAULT);
+ wBehindEdgeBorderSize = db_get_w(NULL,"ModernData","HideBehindBorderSize",SETTING_HIDEBEHINDBORDERSIZE_DEFAULT);
+
+ g_CluiData.fAutoSize = db_get_b(NULL,"CLUI","AutoSize",SETTING_AUTOSIZE_DEFAULT);
+ g_CluiData.bInternalAwayMsgDiscovery = db_get_b(NULL,"ModernData","InternalAwayMsgDiscovery",SETTING_INTERNALAWAYMSGREQUEST_DEFAULT);
+ g_CluiData.bRemoveAwayMessageForOffline = db_get_b(NULL,"ModernData","RemoveAwayMessageForOffline",SETTING_REMOVEAWAYMSGFOROFFLINE_DEFAULT);
+ //window borders
+ if (g_CluiData.fDisableSkinEngine) {
+ g_CluiData.LeftClientMargin = 0;
+ g_CluiData.RightClientMargin = 0;
+ g_CluiData.TopClientMargin = 0;
+ g_CluiData.BottomClientMargin = 0;
+ } else {
+ //window borders
+ g_CluiData.LeftClientMargin = (int)db_get_b(NULL,"CLUI","LeftClientMargin",SETTING_LEFTCLIENTMARIGN_DEFAULT);
+ g_CluiData.RightClientMargin = (int)db_get_b(NULL,"CLUI","RightClientMargin",SETTING_RIGHTCLIENTMARIGN_DEFAULT);
+ g_CluiData.TopClientMargin = (int)db_get_b(NULL,"CLUI","TopClientMargin",SETTING_TOPCLIENTMARIGN_DEFAULT);
+ g_CluiData.BottomClientMargin = (int)db_get_b(NULL,"CLUI","BottomClientMargin",SETTING_BOTTOMCLIENTMARIGN_DEFAULT);
+ }
+ BroadCastMessageToChild(pcli->hwndContactList, WM_THEMECHANGED, 0, 0);
+
+ NotifyEventHooks(g_CluiData.hEventBkgrChanged, 0, 0);
+ return 0;
+}
+
+void CLUI_DisconnectAll()
+{
+ PROTOACCOUNT **accs;
+ int nProtoCount;
+ int nProto;
+
+ ProtoEnumAccounts( &nProtoCount, &accs );
+ for (nProto = 0; nProto < nProtoCount; nProto++)
+ if ( IsAccountEnabled( accs[nProto] ))
+ CallProtoService( accs[nProto]->szModuleName, PS_SETSTATUS, ID_STATUS_OFFLINE, 0 );
+}
+
+static int CLUI_DrawMenuBackGround(HWND hwnd, HDC hdc, int item, int state)
+{
+ RECT ra,r1;
+ // HBRUSH hbr;
+ HRGN treg,treg2;
+ struct ClcData * dat;
+
+ if ( !fnGetMenuBarInfo )
+ return 1;
+
+ dat = (struct ClcData*)GetWindowLongPtr(pcli->hwndContactTree,0);
+ if ( !dat) return 1;
+ GetWindowRect(hwnd,&ra);
+ {
+ MENUBARINFO mbi = {0};
+ mbi.cbSize = sizeof(MENUBARINFO);
+ fnGetMenuBarInfo(hwnd,OBJID_MENU, 0, &mbi);
+ if ( !(mbi.rcBar.right-mbi.rcBar.left>0 && mbi.rcBar.bottom-mbi.rcBar.top>0)) return 1;
+ r1 = mbi.rcBar;
+ r1.bottom += !db_get_b(NULL,"CLUI","LineUnderMenu",SETTING_LINEUNDERMENU_DEFAULT);
+ if (item < 1)
+ {
+ treg = CreateRectRgn(mbi.rcBar.left,mbi.rcBar.top,mbi.rcBar.right,r1.bottom);
+ if (item == 0) //should remove item clips
+ {
+ int t;
+ for (t = 1; t <= 2; t++)
+ {
+ fnGetMenuBarInfo(hwnd,OBJID_MENU, t, &mbi);
+ treg2 = CreateRectRgn(mbi.rcBar.left,mbi.rcBar.top,mbi.rcBar.right,mbi.rcBar.bottom);
+ CombineRgn(treg,treg,treg2,RGN_DIFF);
+ DeleteObject(treg2);
+ }
+
+ }
+ }
+ else
+ {
+ fnGetMenuBarInfo(hwnd,OBJID_MENU, item, &mbi);
+ treg = CreateRectRgn(mbi.rcBar.left,mbi.rcBar.top,mbi.rcBar.right,mbi.rcBar.bottom+!db_get_b(NULL,"CLUI","LineUnderMenu",SETTING_LINEUNDERMENU_DEFAULT));
+ }
+ OffsetRgn(treg,-ra.left,-ra.top);
+ r1.left -= ra.left;
+ r1.top -= ra.top;
+ r1.bottom -= ra.top;
+ r1.right -= ra.left;
+ }
+ //SelectClipRgn(hdc,NULL);
+ SelectClipRgn(hdc,treg);
+ DeleteObject(treg);
+ {
+ RECT rc;
+ HWND hwnd = pcli->hwndContactList;
+ GetWindowRect(hwnd,&rc);
+ OffsetRect(&rc,-rc.left, -rc.top);
+ FillRect(hdc,&r1,GetSysColorBrush(COLOR_MENU));
+ ske_SetRectOpaque(hdc,&r1);
+ //ske_BltBackImage(hwnd,hdc,&r1);
+ }
+ if ( !g_CluiData.fDisableSkinEngine)
+ SkinDrawGlyph(hdc,&r1,&r1,"Main,ID=MenuBar");
+ else
+ {
+ HBRUSH hbr = NULL;
+ if (dat->hMenuBackground)
+ {
+ BITMAP bmp;
+ HBITMAP oldbm;
+ HDC hdcBmp;
+ int x,y;
+ int maxx,maxy;
+ int destw,desth;
+ RECT clRect = r1;
+
+
+ // XXX: Halftone isnt supported on 9x, however the scretch problems dont happen on 98.
+ SetStretchBltMode(hdc, HALFTONE);
+
+ GetObject(dat->hMenuBackground,sizeof(bmp),&bmp);
+ hdcBmp = CreateCompatibleDC(hdc);
+ oldbm = (HBITMAP)SelectObject(hdcBmp,dat->hMenuBackground);
+ y = clRect.top;
+ x = clRect.left;
+ maxx = dat->MenuBmpUse&CLBF_TILEH?maxx = r1.right:x+1;
+ maxy = dat->MenuBmpUse&CLBF_TILEV?maxy = r1.bottom:y+1;
+ switch(dat->MenuBmpUse&CLBM_TYPE) {
+ case CLB_STRETCH:
+ if (dat->MenuBmpUse&CLBF_PROPORTIONAL) {
+ if (clRect.right-clRect.left*bmp.bmHeight < clRect.bottom-clRect.top*bmp.bmWidth)
+ {
+ desth = clRect.bottom-clRect.top;
+ destw = desth*bmp.bmWidth/bmp.bmHeight;
+ }
+ else
+ {
+ destw = clRect.right-clRect.left;
+ desth = destw*bmp.bmHeight/bmp.bmWidth;
+ }
+ }
+ else {
+ destw = clRect.right-clRect.left;
+ desth = clRect.bottom-clRect.top;
+ }
+ break;
+ case CLB_STRETCHH:
+ if (dat->MenuBmpUse&CLBF_PROPORTIONAL) {
+ destw = clRect.right-clRect.left;
+ desth = destw*bmp.bmHeight/bmp.bmWidth;
+ }
+ else {
+ destw = clRect.right-clRect.left;
+ desth = bmp.bmHeight;
+ }
+ break;
+ case CLB_STRETCHV:
+ if (dat->MenuBmpUse&CLBF_PROPORTIONAL) {
+ desth = clRect.bottom-clRect.top;
+ destw = desth*bmp.bmWidth/bmp.bmHeight;
+ }
+ else {
+ destw = bmp.bmWidth;
+ desth = clRect.bottom-clRect.top;
+ }
+ break;
+ default: //clb_topleft
+ destw = bmp.bmWidth;
+ desth = bmp.bmHeight;
+ break;
+ }
+ if (desth && destw)
+ for (y = clRect.top;y < maxy;y += desth) {
+ for (x = clRect.left;x < maxx;x += destw)
+ StretchBlt(hdc,x,y,destw,desth,hdcBmp,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
+ }
+ SelectObject(hdcBmp,oldbm);
+ DeleteDC(hdcBmp);
+
+ }
+
+ else
+ {
+ hbr = CreateSolidBrush(dat->MenuBkColor);
+ FillRect(hdc,&r1,hbr);
+ DeleteObject(hbr);
+ }
+ if (item != 0 && state&(ODS_SELECTED))
+ {
+ hbr = CreateSolidBrush(dat->MenuBkHiColor);
+ FillRect(hdc,&r1,hbr);
+ DeleteObject(hbr);
+ }
+ }
+ SelectClipRgn(hdc,NULL);
+ return 0;
+}
+
+int CLUI_SizingGetWindowRect(HWND hwnd,RECT * rc)
+{
+ if (mutex_bDuringSizing && hwnd == pcli->hwndContactList)
+ *rc = rcSizingRect;
+ else
+ GetWindowRect(hwnd,rc);
+ return 1;
+}
+
+
+int CLUI_SyncGetPDNCE(WPARAM wParam, LPARAM lParam)
+{
+ //log0("CLUI_SyncGetPDNCE");
+ return CListSettings_GetCopyFromCache((pdisplayNameCacheEntry)lParam, wParam ? (DWORD) wParam : CCI_ALL );
+}
+
+int CLUI_SyncSetPDNCE(WPARAM wParam, LPARAM lParam)
+{
+ //log0("CLUI_SyncSetPDNCE");
+ return CListSettings_SetToCache((pdisplayNameCacheEntry)lParam, wParam ? (DWORD) wParam : CCI_ALL );
+}
+
+int CLUI_SyncGetShortData(WPARAM wParam, LPARAM lParam)
+{
+ HWND hwnd = (HWND) wParam;
+ struct ClcData * dat = (struct ClcData * )GetWindowLongPtr(hwnd,0);
+ //log0("CLUI_SyncGetShortData");
+ return ClcGetShortData(dat,(struct SHORTDATA *)lParam);
+}
+
+int CLUI_SyncSmoothAnimation(WPARAM wParam, LPARAM lParam)
+{
+ return CLUI_SmoothAlphaThreadTransition((HWND)lParam);
+}
+
+
+
+int CLUI_IconsChanged(WPARAM wParam,LPARAM lParam)
+{
+ if (MirandaExiting()) return 0;
+ DrawMenuBar(pcli->hwndContactList);
+ ExtraImage_ReloadExtraIcons();
+ ExtraImage_SetAllExtraIcons(pcli->hwndContactTree,0);
+ // need to update tray cause it use combined icons
+ pcli->pfnTrayIconIconsChanged(); //TODO: remove as soon as core will include icolib
+ ske_RedrawCompleteWindow();
+ // pcli->pfnClcBroadcast( INTM_INVALIDATE,0,0);
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+void CLUI_cli_LoadCluiGlobalOpts()
+{
+ BOOL tLayeredFlag = FALSE;
+ tLayeredFlag = IsWinVer2000Plus();
+ tLayeredFlag &= db_get_b(NULL, "ModernData", "EnableLayering", tLayeredFlag);
+
+ if (tLayeredFlag)
+ {
+ if (db_get_b(NULL,"CList","WindowShadow",SETTING_WINDOWSHADOW_DEFAULT) == 1)
+ db_set_b(NULL,"CList","WindowShadow",2);
+ }
+ else
+ {
+ if (db_get_b(NULL,"CList","WindowShadow",SETTING_WINDOWSHADOW_DEFAULT) == 2)
+ db_set_b(NULL,"CList","WindowShadow",1);
+ }
+ corecli.pfnLoadCluiGlobalOpts();
+}
+
+
+int CLUI_TestCursorOnBorders()
+{
+ HWND hwnd = pcli->hwndContactList;
+ HCURSOR hCurs1 = NULL;
+ RECT r;
+ POINT pt;
+ int k = 0, t = 0, fx,fy;
+ HWND hAux;
+ BOOL mouse_in_window = 0;
+ HWND gf = GetForegroundWindow();
+ GetCursorPos(&pt);
+ hAux = WindowFromPoint(pt);
+ if (CLUI_CheckOwnedByClui(hAux))
+ {
+ if (g_bTransparentFlag) {
+ if ( !bTransparentFocus && gf != hwnd) {
+ CLUI_SmoothAlphaTransition(hwnd, db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT), 1);
+ //g_proc_SetLayeredWindowAttributes(hwnd, RGB(0,0,0), (BYTE)DBGetContactSettingByte(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT), LWA_ALPHA);
+ bTransparentFocus = 1;
+ CLUI_SafeSetTimer(hwnd, TM_AUTOALPHA,250,NULL);
+ }
+ }
+ }
+
+ mutex_bIgnoreActivation = 0;
+ GetWindowRect(hwnd,&r);
+ /*
+ * Size borders offset (contract)
+ */
+ r.top += db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Top",SKIN_OFFSET_TOP_DEFAULT);
+ r.bottom -= db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Bottom",SKIN_OFFSET_BOTTOM_DEFAULT);
+ r.left += db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Left",SKIN_OFFSET_LEFT_DEFAULT);
+ r.right -= db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Right",SKIN_OFFSET_RIGHT_DEFAULT);
+
+ if (r.right < r.left) r.right = r.left;
+ if (r.bottom < r.top) r.bottom = r.top;
+
+ /*
+ * End of size borders offset (contract)
+ */
+
+ hAux = WindowFromPoint(pt);
+ while(hAux != NULL)
+ {
+ if (hAux == hwnd) {mouse_in_window = 1; break;}
+ hAux = GetParent(hAux);
+ }
+ fx = GetSystemMetrics(SM_CXFULLSCREEN);
+ fy = GetSystemMetrics(SM_CYFULLSCREEN);
+ if (g_CluiData.fDocked || g_CluiData.nBehindEdgeState == 0)
+ //if (g_CluiData.fDocked) || ((pt.x < fx-1) && (pt.y < fy-1) && pt.x>1 && pt.y>1)) // workarounds for behind the edge.
+ {
+ //ScreenToClient(hwnd,&pt);
+ //GetClientRect(hwnd,&r);
+ if (pt.y <= r.bottom && pt.y >= r.bottom-SIZING_MARGIN && !g_CluiData.fAutoSize) k = 6;
+ else if (pt.y >= r.top && pt.y <= r.top+SIZING_MARGIN && !g_CluiData.fAutoSize) k = 3;
+ if (pt.x <= r.right && pt.x >= r.right-SIZING_MARGIN && g_CluiData.bBehindEdgeSettings != 2) k += 2;
+ else if (pt.x >= r.left && pt.x <= r.left+SIZING_MARGIN && g_CluiData.bBehindEdgeSettings != 1) k += 1;
+ if ( !(pt.x >= r.left && pt.x <= r.right && pt.y >= r.top && pt.y <= r.bottom)) k = 0;
+ k *= mouse_in_window;
+ hCurs1 = LoadCursor(NULL, IDC_ARROW);
+ if (g_CluiData.nBehindEdgeState <= 0 && (!(db_get_b(NULL,"CLUI","LockSize",SETTING_LOCKSIZE_DEFAULT))))
+ switch(k)
+ {
+ case 1:
+ case 2:
+ if ( !g_CluiData.fDocked || (g_CluiData.fDocked == 2 && k == 1) || (g_CluiData.fDocked == 1 && k == 2)){hCurs1 = LoadCursor(NULL, IDC_SIZEWE); break;}
+ case 3: if ( !g_CluiData.fDocked) {hCurs1 = LoadCursor(NULL, IDC_SIZENS); break;}
+ case 4: if ( !g_CluiData.fDocked) {hCurs1 = LoadCursor(NULL, IDC_SIZENWSE); break;}
+ case 5: if ( !g_CluiData.fDocked) {hCurs1 = LoadCursor(NULL, IDC_SIZENESW); break;}
+ case 6: if ( !g_CluiData.fDocked) {hCurs1 = LoadCursor(NULL, IDC_SIZENS); break;}
+ case 7: if ( !g_CluiData.fDocked) {hCurs1 = LoadCursor(NULL, IDC_SIZENESW); break;}
+ case 8: if ( !g_CluiData.fDocked) {hCurs1 = LoadCursor(NULL, IDC_SIZENWSE); break;}
+ }
+ if (hCurs1) SetCursor(hCurs1);
+ return k;
+ }
+
+ return 0;
+}
+
+int CLUI_SizingOnBorder(POINT pt, int PerformSize)
+{
+ if ( !(db_get_b(NULL,"CLUI","LockSize",SETTING_LOCKSIZE_DEFAULT)))
+ {
+ RECT r;
+ HWND hwnd = pcli->hwndContactList;
+ int sizeOnBorderFlag = 0;
+ GetWindowRect(hwnd,&r);
+ /*
+ * Size borders offset (contract)
+ */
+ r.top += db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Top",SKIN_OFFSET_TOP_DEFAULT);
+ r.bottom -= db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Bottom",SKIN_OFFSET_BOTTOM_DEFAULT);
+ r.left += db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Left",SKIN_OFFSET_LEFT_DEFAULT);
+ r.right -= db_get_dw(NULL,"ModernSkin","SizeMarginOffset_Right",SKIN_OFFSET_RIGHT_DEFAULT);
+
+ if (r.right < r.left) r.right = r.left;
+ if (r.bottom < r.top) r.bottom = r.top;
+
+ /*
+ * End of size borders offset (contract)
+ */
+ if ( !g_CluiData.fAutoSize )
+ {
+ if ( pt.y <= r.bottom && pt.y >= r.bottom - SIZING_MARGIN ) sizeOnBorderFlag = SCF_BOTTOM;
+ else if ( pt.y >= r.top && pt.y <= r.top + SIZING_MARGIN ) sizeOnBorderFlag = SCF_TOP;
+ }
+
+ if ( pt.x <= r.right && pt.x >= r.right - SIZING_MARGIN ) sizeOnBorderFlag += SCF_RIGHT;
+ else if ( pt.x >= r.left && pt.x <= r.left + SIZING_MARGIN ) sizeOnBorderFlag += SCF_LEFT;
+
+ if ( !(pt.x >= r.left && pt.x <= r.right && pt.y >= r.top && pt.y <= r.bottom)) sizeOnBorderFlag = SCF_NONE;
+
+ if (sizeOnBorderFlag && PerformSize)
+ {
+ ReleaseCapture();
+ SendMessage(hwnd, WM_SYSCOMMAND, SC_SIZE + sizeOnBorderFlag,MAKELPARAM(pt.x,pt.y));
+ return sizeOnBorderFlag;
+ }
+ else return sizeOnBorderFlag;
+ }
+ return SCF_NONE;
+}
+int CLUI_SyncSmoothAnimation(WPARAM wParam, LPARAM lParam);
+static void CLUI_SmoothAnimationThreadProc(HWND hwnd)
+{
+ // return;
+ if ( !mutex_bAnimationInProgress)
+ {
+ g_dwSmoothAnimationThreadID = 0;
+ return; /// Should be some locked to avoid painting against contact deletion.
+ }
+ do
+ {
+ if ( !g_mutex_bLockUpdating)
+ {
+ if ( !MirandaExiting())
+ Sync(CLUI_SyncSmoothAnimation, (WPARAM)0, (LPARAM)hwnd );
+ SleepEx(20,TRUE);
+ if (MirandaExiting())
+ {
+ g_dwSmoothAnimationThreadID = 0;
+ return;
+ }
+ }
+ else SleepEx(0,TRUE);
+
+ } while (mutex_bAnimationInProgress);
+ g_dwSmoothAnimationThreadID = 0;
+ return;
+}
+
+static int CLUI_SmoothAlphaThreadTransition(HWND hwnd)
+{
+ int step;
+ int a;
+
+ step = (g_CluiData.bCurrentAlpha>bAlphaEnd)?-1*ANIMATION_STEP:ANIMATION_STEP;
+ a = g_CluiData.bCurrentAlpha+step;
+ if ((step >= 0 && a >= bAlphaEnd) || (step <= 0 && a <= bAlphaEnd))
+ {
+ mutex_bAnimationInProgress = 0;
+ g_CluiData.bCurrentAlpha = bAlphaEnd;
+ if (g_CluiData.bCurrentAlpha == 0)
+ {
+ g_CluiData.bCurrentAlpha = 1;
+ ske_JustUpdateWindowImage();
+ mutex_bShowHideCalledFromAnimation = 1;
+ CLUI_ShowWindowMod(pcli->hwndContactList,0);
+ Sync(CLUIFrames_OnShowHide, hwnd,0);
+ mutex_bShowHideCalledFromAnimation = 0;
+ g_CluiData.bCurrentAlpha = 0;
+ if ( !g_CluiData.fLayered) RedrawWindow(pcli->hwndContactList,NULL,NULL,RDW_ERASE|RDW_FRAME);
+ return 0;
+ }
+ }
+ else g_CluiData.bCurrentAlpha = a;
+ ske_JustUpdateWindowImage();
+ return 1;
+}
+
+int CLUI_SmoothAlphaTransition(HWND hwnd, BYTE GoalAlpha, BOOL wParam)
+{
+
+ if ((!g_CluiData.fLayered
+ && (!g_CluiData.fSmoothAnimation && !g_bTransparentFlag)) || !g_proc_SetLayeredWindowAttributesNew)
+ {
+ if (GoalAlpha>0 && wParam != 2)
+ {
+ if ( !IsWindowVisible(hwnd))
+ {
+ mutex_bShowHideCalledFromAnimation = 1;
+ CLUI_ShowWindowMod(pcli->hwndContactList,SW_RESTORE);
+ Sync(CLUIFrames_OnShowHide, hwnd,1);
+ mutex_bShowHideCalledFromAnimation = 0;
+ g_CluiData.bCurrentAlpha = GoalAlpha;
+ ske_UpdateWindowImage();
+
+ }
+ }
+ else if (GoalAlpha == 0 && wParam != 2)
+ {
+ if (IsWindowVisible(hwnd))
+ {
+ mutex_bShowHideCalledFromAnimation = 1;
+ CLUI_ShowWindowMod(pcli->hwndContactList,0);
+ Sync(CLUIFrames_OnShowHide, hwnd,0);
+ g_CluiData.bCurrentAlpha = GoalAlpha;
+ mutex_bShowHideCalledFromAnimation = 0;
+
+ }
+ }
+ return 0;
+ }
+ if (g_CluiData.bCurrentAlpha == GoalAlpha && 0)
+ {
+ if (mutex_bAnimationInProgress)
+ {
+ KillTimer(hwnd,TM_SMOTHALPHATRANSITION);
+ mutex_bAnimationInProgress = 0;
+ }
+ return 0;
+ }
+ if (mutex_bShowHideCalledFromAnimation) return 0;
+ if (wParam != 2) //not from timer
+ {
+ bAlphaEnd = GoalAlpha;
+ if ( !mutex_bAnimationInProgress)
+ {
+ if ((!IsWindowVisible(hwnd) || g_CluiData.bCurrentAlpha == 0) && bAlphaEnd>0 )
+ {
+ mutex_bShowHideCalledFromAnimation = 1;
+ CLUI_ShowWindowMod(pcli->hwndContactList,SW_SHOWNA);
+ Sync(CLUIFrames_OnShowHide, hwnd,SW_SHOW);
+ mutex_bShowHideCalledFromAnimation = 0;
+ g_CluiData.bCurrentAlpha = 1;
+ ske_UpdateWindowImage();
+ }
+ if (IsWindowVisible(hwnd) && !g_dwSmoothAnimationThreadID)
+ {
+ mutex_bAnimationInProgress = 1;
+ if (g_CluiData.fSmoothAnimation)
+ g_dwSmoothAnimationThreadID = (DWORD)mir_forkthread((pThreadFunc)CLUI_SmoothAnimationThreadProc,pcli->hwndContactList);
+
+ }
+ }
+ }
+
+ {
+ int step;
+ int a;
+ step = (g_CluiData.bCurrentAlpha>bAlphaEnd)?-1*ANIMATION_STEP:ANIMATION_STEP;
+ a = g_CluiData.bCurrentAlpha+step;
+ if ((step >= 0 && a >= bAlphaEnd) || (step <= 0 && a <= bAlphaEnd) || g_CluiData.bCurrentAlpha == bAlphaEnd || !g_CluiData.fSmoothAnimation) //stop animation;
+ {
+ KillTimer(hwnd,TM_SMOTHALPHATRANSITION);
+ mutex_bAnimationInProgress = 0;
+ if (bAlphaEnd == 0)
+ {
+ g_CluiData.bCurrentAlpha = 1;
+ ske_UpdateWindowImage();
+ mutex_bShowHideCalledFromAnimation = 1;
+ CLUI_ShowWindowMod(pcli->hwndContactList,0);
+ Sync(CLUIFrames_OnShowHide, pcli->hwndContactList,0);
+ mutex_bShowHideCalledFromAnimation = 0;
+ g_CluiData.bCurrentAlpha = 0;
+ }
+ else
+ {
+ g_CluiData.bCurrentAlpha = bAlphaEnd;
+ ske_UpdateWindowImage();
+ }
+ }
+ else
+ {
+ g_CluiData.bCurrentAlpha = a;
+ ske_UpdateWindowImage();
+ }
+ }
+
+ return 0;
+}
+
+BOOL CLUI__cliInvalidateRect(HWND hWnd, CONST RECT* lpRect,BOOL bErase )
+{
+ if (g_mutex_bSetAllExtraIconsCycle)
+ return FALSE;
+ if (CLUI_IsInMainWindow(hWnd) && g_CluiData.fLayered)// && IsWindowVisible(hWnd))
+ {
+ if (IsWindowVisible(hWnd))
+ return SkinInvalidateFrame( hWnd, lpRect );
+ else
+ {
+ g_flag_bFullRepaint = 1;
+ return 0;
+ }
+ }
+ else
+ return InvalidateRect(hWnd,lpRect,bErase);
+ return 1;
+}
+
+static BOOL FileExists(TCHAR * tszFilename)
+{
+ BOOL result = FALSE;
+ FILE * f = _tfopen(tszFilename,_T("r"));
+ if (f == NULL) return FALSE;
+ fclose(f);
+ return TRUE;
+}
+
+HANDLE RegisterIcolibIconHandle(char * szIcoID, char *szSectionName, char * szDescription, TCHAR * tszDefaultFile, int iDefaultIndex, HINSTANCE hDefaultModuleInst, int iDefaultResource )
+{
+ TCHAR fileFull[MAX_PATH] = {0};
+ SKINICONDESC sid = {0};
+ HANDLE hIcolibItem = NULL;
+ sid.cbSize = sizeof(sid);
+ sid.cx = 16;
+ sid.cy = 16;
+ sid.pszSection = szSectionName;
+ sid.pszName = szIcoID;
+ sid.flags |= SIDF_PATH_TCHAR;
+ sid.pszDescription = szDescription;
+
+ if (tszDefaultFile)
+ {
+ CallService( MS_UTILS_PATHTOABSOLUTET, ( WPARAM )tszDefaultFile, ( LPARAM )fileFull );
+ if ( !FileExists(fileFull)) fileFull[0] = _T('\0');
+ }
+ if (fileFull[0] != _T('\0'))
+ {
+ sid.ptszDefaultFile = fileFull;
+ sid.iDefaultIndex = iDefaultIndex;
+ sid.hDefaultIcon = NULL;
+ }
+ else
+ {
+ sid.pszDefaultFile = NULL;
+ sid.iDefaultIndex = 0;
+ sid.hDefaultIcon = LoadSmallIcon( hDefaultModuleInst, MAKEINTRESOURCE(iDefaultResource));
+ }
+ hIcolibItem = Skin_AddIcon(&sid);
+ if ( sid.hDefaultIcon ) DestroyIcon(sid.hDefaultIcon);
+ return hIcolibItem;
+}
+
+// MAIN WINPROC MESSAGE HANDLERS
+LRESULT CLUI::PreProcessWndProc( UINT msg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
+{
+ // proxy CLUI Messages
+ LRESULT result = 0;
+ if ( ProcessCLUIFrameInternalMsg( m_hWnd, msg, wParam, lParam, result ))
+ {
+ bHandled = TRUE;
+ return result;
+ }
+
+ /*
+ This registers a window message with RegisterWindowMessage() and then waits for such a message,
+ if it gets it, it tries to open a file mapping object and then maps it to this process space,
+ it expects 256 bytes of data (incl. NULL) it will then write back the profile it is using the DB to fill in the answer.
+
+ The caller is expected to create this mapping object and tell us the ID we need to open ours.
+ */
+ if (g_CluiData.bSTATE == STATE_EXITING && msg != WM_DESTROY)
+ {
+ bHandled = TRUE;
+ return 0;
+ }
+ if (msg == uMsgGetProfile && wParam != 0) /* got IPC message */
+ {
+ HANDLE hMap;
+ char szName[MAX_PATH];
+ int rc = 0;
+ mir_snprintf( szName, SIZEOF(szName), "Miranda::%u", wParam ); // caller will tell us the ID of the map
+ hMap = OpenFileMappingA( FILE_MAP_ALL_ACCESS,FALSE, szName );
+ if ( hMap != NULL )
+ {
+ void *hView = NULL;
+ hView = MapViewOfFile( hMap, FILE_MAP_ALL_ACCESS, 0, 0, MAX_PATH );
+ if (hView)
+ {
+ char szFilePath[MAX_PATH], szProfile[MAX_PATH];
+ CallService( MS_DB_GETPROFILEPATH,MAX_PATH,(LPARAM)&szFilePath );
+ CallService( MS_DB_GETPROFILENAME,MAX_PATH,(LPARAM)&szProfile );
+ _snprintf((char*)hView, MAX_PATH, "%s\\%s", szFilePath, szProfile );
+ UnmapViewOfFile( hView );
+ rc = 1;
+ }
+ CloseHandle( hMap );
+ }
+ bHandled = TRUE;
+ return rc;
+ }
+ return FALSE;
+}
+
+
+LRESULT CLUI::OnSizingMoving( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ if (g_CluiData.fLayered)
+ {
+ if (msg == WM_SIZING)
+ {
+ static int a = 0;
+ RECT* wp = (RECT*)lParam;
+ if (bNeedFixSizingRect && (rcCorrectSizeRect.bottom != 0 || rcCorrectSizeRect.top != 0))
+ {
+ if (wParam != WMSZ_BOTTOM) wp->bottom = rcCorrectSizeRect.bottom;
+ if (wParam != WMSZ_TOP) wp->top = rcCorrectSizeRect.top;
+ }
+ bNeedFixSizingRect = 0;
+ rcSizingRect = *wp;
+ mutex_bDuringSizing = 1;
+ return 1;
+ }
+
+ if (msg == WM_WINDOWPOSCHANGING)
+ {
+
+
+ WINDOWPOS * wp;
+ HDWP PosBatch;
+ RECT work_rect = {0};
+ RECT temp_rect = {0};
+ wp = (WINDOWPOS *)lParam;
+ GetWindowRect(m_hWnd,&rcOldWindowRect);
+
+ // Ïðèëèïàíèå ê êðàÿì by ZorG
+ CLUI::SnappingToEdge(wp);
+
+ if ((rcOldWindowRect.bottom-rcOldWindowRect.top != wp->cy || rcOldWindowRect.right-rcOldWindowRect.left != wp->cx) && !(wp->flags&SWP_NOSIZE))
+ {
+ {
+ if ( !(wp->flags&SWP_NOMOVE))
+ {
+ rcNewWindowRect.left = wp->x;
+ rcNewWindowRect.top = wp->y;
+ }
+ else
+ {
+ rcNewWindowRect.left = rcOldWindowRect.left;
+ rcNewWindowRect.top = rcOldWindowRect.top;
+ }
+ rcNewWindowRect.right = rcNewWindowRect.left+wp->cx;
+ rcNewWindowRect.bottom = rcNewWindowRect.top+wp->cy;
+ work_rect = rcNewWindowRect;
+ }
+ //resize frames (batch)
+ {
+ PosBatch = BeginDeferWindowPos(1);
+ SizeFramesByWindowRect(&work_rect,&PosBatch,0);
+ }
+ //Check rect after frames resize
+ {
+ GetWindowRect(m_hWnd,&temp_rect);
+ }
+ //Here work_rect should be changed to fit possible changes in cln_listsizechange
+ if (bNeedFixSizingRect)
+ {
+ work_rect = rcSizingRect;
+ wp->x = work_rect.left;
+ wp->y = work_rect.top;
+ wp->cx = work_rect.right-work_rect.left;
+ wp->cy = work_rect.bottom-work_rect.top;
+ wp->flags &= ~(SWP_NOMOVE);
+ }
+ //reposition buttons and new size applying
+ {
+ ModernSkinButton_ReposButtons( m_hWnd, SBRF_DO_NOT_DRAW, &work_rect );
+ ske_PrepeareImageButDontUpdateIt(&work_rect);
+ g_CluiData.mutexPreventDockMoving = 0;
+ ske_UpdateWindowImageRect(&work_rect);
+ EndDeferWindowPos(PosBatch);
+ g_CluiData.mutexPreventDockMoving = 1;
+ }
+ Sleep(0);
+ mutex_bDuringSizing = 0;
+ DefWindowProc(m_hWnd,msg,wParam,lParam);
+ return SendMessage(m_hWnd,WM_WINDOWPOSCHANGED,wParam,lParam);
+ }
+ else
+ {
+ SetRect(&rcCorrectSizeRect,0,0,0,0);
+ // bNeedFixSizingRect = 0;
+ }
+ return DefWindowProc(m_hWnd,msg,wParam,lParam);
+ }
+ }
+
+ else if (msg == WM_WINDOWPOSCHANGING)
+ {
+ // Snaping if it is not in LayeredMode
+ WINDOWPOS * wp;
+ wp = (WINDOWPOS *)lParam;
+ CLUI::SnappingToEdge( wp );
+ return DefWindowProc(m_hWnd,msg,wParam,lParam);
+ }
+ switch (msg)
+ {
+ case WM_DISPLAYCHANGE:
+ SendMessage(pcli->hwndContactTree, WM_SIZE, 0, 0);
+ return TRUE;
+
+ case WM_EXITSIZEMOVE:
+ {
+ int res = DefWindowProc(m_hWnd, msg, wParam, lParam);
+ ReleaseCapture();
+ TRACE("WM_EXITSIZEMOVE\n");
+ SendMessage(m_hWnd, WM_ACTIVATE, (WPARAM)WA_ACTIVE, (LPARAM)m_hWnd);
+ return res;
+ }
+
+ case WM_SIZING:
+ return DefWindowProc(m_hWnd, msg, wParam, lParam);;
+
+ case WM_MOVE:
+ {
+ RECT rc;
+ CallWindowProc(DefWindowProc, m_hWnd, msg, wParam, lParam);
+ mutex_bDuringSizing = 0;
+ GetWindowRect(m_hWnd, &rc);
+ CheckFramesPos(&rc);
+ Sync(CLUIFrames_OnMoving,m_hWnd,&rc);
+ if ( !IsIconic(m_hWnd)) {
+ if ( !CallService(MS_CLIST_DOCKINGISDOCKED,0,0))
+ { //if g_CluiData.fDocked, dont remember pos (except for width)
+ db_set_dw(NULL,"CList","Height",(DWORD)(rc.bottom - rc.top));
+ db_set_dw(NULL,"CList","x",(DWORD)rc.left);
+ db_set_dw(NULL,"CList","y",(DWORD)rc.top);
+ }
+ db_set_dw(NULL,"CList","Width",(DWORD)(rc.right - rc.left));
+ }
+ return TRUE;
+ }
+ case WM_SIZE:
+ {
+ RECT rc;
+ if (g_mutex_bSizing) return 0;
+ if (wParam != SIZE_MINIMIZED /* && IsWindowVisible(m_hWnd)*/)
+ {
+ if ( pcli->hwndContactList == NULL )
+ return 0;
+
+ if ( !g_CluiData.fLayered && !g_CluiData.fDisableSkinEngine)
+ ske_ReCreateBackImage(TRUE,NULL);
+
+ GetWindowRect(m_hWnd, &rc);
+ CheckFramesPos(&rc);
+ ModernSkinButton_ReposButtons( m_hWnd, SBRF_DO_NOT_DRAW, &rc);
+ ModernSkinButton_ReposButtons( m_hWnd, SBRF_REDRAW, NULL);
+ if (g_CluiData.fLayered)
+ CallService(MS_SKINENG_UPTATEFRAMEIMAGE,(WPARAM)m_hWnd,0);
+
+ if ( !g_CluiData.fLayered)
+ {
+ g_mutex_bSizing = 1;
+ Sync(CLUIFrames_OnClistResize_mod,(WPARAM)m_hWnd,(LPARAM)1);
+ CLUIFrames_ApplyNewSizes(2);
+ CLUIFrames_ApplyNewSizes(1);
+ SendMessage(m_hWnd,CLN_LISTSIZECHANGE,0,0);
+ g_mutex_bSizing = 0;
+ }
+
+ // ske_RedrawCompleteWindow();
+ if ( !CallService(MS_CLIST_DOCKINGISDOCKED,0,0))
+ { //if g_CluiData.fDocked, dont remember pos (except for width)
+ db_set_dw(NULL,"CList","Height",(DWORD)(rc.bottom - rc.top));
+ db_set_dw(NULL,"CList","x",(DWORD)rc.left);
+ db_set_dw(NULL,"CList","y",(DWORD)rc.top);
+ }
+ else SetWindowRgn(m_hWnd,NULL,0);
+ db_set_dw(NULL,"CList","Width",(DWORD)(rc.right - rc.left));
+
+ if ( !g_CluiData.fLayered)
+ {
+ HRGN hRgn1;
+ RECT r;
+ int v,h;
+ int w = 10;
+ GetWindowRect(m_hWnd,&r);
+ h = (r.right-r.left)>(w*2)?w:(r.right-r.left);
+ v = (r.bottom-r.top)>(w*2)?w:(r.bottom-r.top);
+ h = (h < v)?h:v;
+ hRgn1 = CreateRoundRectRgn(0,0,(r.right-r.left+1),(r.bottom-r.top+1),h,h);
+ if ((db_get_b(NULL,"CLC","RoundCorners",SETTING_ROUNDCORNERS_DEFAULT)) && (!CallService(MS_CLIST_DOCKINGISDOCKED,0,0)))
+ SetWindowRgn(m_hWnd,hRgn1,FALSE);
+ else
+ {
+ DeleteObject(hRgn1);
+ SetWindowRgn(m_hWnd,NULL,FALSE);
+ }
+ RedrawWindow(m_hWnd,NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_FRAME|RDW_UPDATENOW|RDW_ALLCHILDREN);
+ }
+ }
+ else {
+ if (db_get_b(NULL,"CList","Min2Tray",SETTING_MIN2TRAY_DEFAULT)) {
+ CLUI_ShowWindowMod(m_hWnd, SW_HIDE);
+ db_set_b(NULL,"CList","State",SETTING_STATE_HIDDEN);
+ }
+ else db_set_b(NULL,"CList","State",SETTING_STATE_MINIMIZED);
+ if (MySetProcessWorkingSetSize != NULL)
+ MySetProcessWorkingSetSize(GetCurrentProcess(),-1,-1);
+ }
+
+ return TRUE;
+ }
+ case WM_WINDOWPOSCHANGING:
+ {
+ WINDOWPOS *wp = (WINDOWPOS *)lParam;
+ if (wp->flags&SWP_HIDEWINDOW && mutex_bAnimationInProgress)
+ return 0;
+ if (g_CluiData.fOnDesktop)
+ wp->flags |= SWP_NOACTIVATE|SWP_NOZORDER;
+ return DefWindowProc(m_hWnd, msg, wParam, lParam);
+ }
+ }
+ return 0;
+}
+
+LRESULT CLUI::OnThemeChanged( UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ )
+{
+ xpt_OnWM_THEMECHANGED();
+ return FALSE;
+}
+
+LRESULT CLUI::OnDwmCompositionChanged( UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ )
+{
+ g_CluiData.fAeroGlass = false;
+ CLUI_UpdateAeroGlass();
+ return FALSE;
+}
+
+LRESULT CLUI::OnSyncCall( UINT /*msg*/, WPARAM wParam, LPARAM /*lParam*/ )
+{
+ return SyncOnWndProcCall( wParam );
+}
+
+LRESULT CLUI::OnUpdate( UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ )
+{
+ if ( g_flag_bPostWasCanceled )
+ return FALSE;
+ return ske_ValidateFrameImageProc( NULL );
+}
+
+LRESULT CLUI::OnInitMenu( UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ )
+{
+ if ( !CLUI::IsMainMenuInited()) {
+ if ( ServiceExists( MS_CLIST_MENUBUILDMAIN ))
+ CallService( MS_CLIST_MENUBUILDMAIN, 0, 0 );
+ CLUI::m_fMainMenuInited = TRUE;
+ }
+ return FALSE;
+}
+
+LRESULT CLUI::OnNcPaint( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ int lRes = DefWindowProc( m_hWnd, msg, wParam, lParam );
+ if ( !g_CluiData.fLayered && db_get_b( NULL,"CLUI","ShowMainMenu",SETTING_SHOWMAINMENU_DEFAULT )) {
+ HDC hdc = NULL;
+ if ( msg == WM_PRINT ) hdc = (HDC)wParam;
+ if ( !hdc ) hdc = GetWindowDC( m_hWnd );
+ CLUI_DrawMenuBackGround( m_hWnd, hdc, 0, 0 );
+ if ( msg != WM_PRINT ) ReleaseDC( m_hWnd, hdc );
+ }
+ return lRes;
+}
+
+LRESULT CLUI::OnEraseBkgnd( UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ )
+{
+ return TRUE;
+}
+
+LRESULT CLUI::OnNcCreate( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ ((LPCREATESTRUCT)lParam )->style &= ~(CS_HREDRAW | CS_VREDRAW);
+ return DefCluiWndProc( msg, wParam, lParam );
+}
+
+LRESULT CLUI::OnPaint( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ if ( !g_CluiData.fLayered && IsWindowVisible(m_hWnd)) {
+ RECT w = {0};
+ RECT w2 = {0};
+ PAINTSTRUCT ps = {0};
+ HDC hdc;
+ HBITMAP hbmp,oldbmp;
+ HDC paintDC;
+
+ GetClientRect(m_hWnd,&w);
+ if ( !(w.right>0 && w.bottom>0)) return DefWindowProc(m_hWnd, msg, wParam, lParam);
+
+ if ( !g_CluiData.fDisableSkinEngine)
+ {
+ paintDC = GetDC(m_hWnd);
+ w2 = w;
+ hdc = CreateCompatibleDC(paintDC);
+ hbmp = ske_CreateDIB32(w.right,w.bottom);
+ oldbmp = (HBITMAP)SelectObject(hdc,hbmp);
+ ske_ReCreateBackImage(FALSE,NULL);
+ BitBlt(paintDC,w2.left,w2.top,w2.right-w2.left,w2.bottom-w2.top,g_pCachedWindow->hBackDC,w2.left,w2.top,SRCCOPY);
+ SelectObject(hdc,oldbmp);
+ DeleteObject(hbmp);
+ mod_DeleteDC(hdc);
+ ReleaseDC(m_hWnd,paintDC);
+ }
+ else {
+ HDC hdc = BeginPaint(m_hWnd,&ps);
+ ske_BltBackImage(m_hWnd,hdc,&ps.rcPaint);
+ ps.fErase = FALSE;
+ EndPaint(m_hWnd,&ps);
+ }
+
+ ValidateRect(m_hWnd,NULL);
+ }
+
+ if (0 && (db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT) || db_get_dw(NULL,"CLUIFrames","GapBetweenTitleBar",SETTING_GAPTITLEBAR_DEFAULT)))
+ {
+ if (IsWindowVisible(m_hWnd)) {
+ if (g_CluiData.fLayered)
+ SkinInvalidateFrame(m_hWnd,NULL);
+ else {
+ RECT w = {0};
+ RECT w2 = {0};
+ PAINTSTRUCT ps = {0};
+ GetWindowRect(m_hWnd,&w);
+ OffsetRect(&w,-w.left,-w.top);
+ BeginPaint(m_hWnd,&ps);
+ if ((ps.rcPaint.bottom-ps.rcPaint.top)*(ps.rcPaint.right-ps.rcPaint.left) == 0)
+ w2 = w;
+ else
+ w2 = ps.rcPaint;
+ SkinDrawGlyph(ps.hdc,&w,&w2,"Main,ID=Background,Opt=Non-Layered");
+ ps.fErase = FALSE;
+ EndPaint(m_hWnd,&ps);
+ }
+ }
+ }
+ return DefWindowProc(m_hWnd, msg, wParam, lParam);
+}
+
+LRESULT CLUI::OnCreate( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ TranslateMenu(GetMenu(m_hWnd));
+ DrawMenuBar(m_hWnd);
+ CLUIServices_ProtocolStatusChanged(0,0);
+
+ { MENUITEMINFO mii;
+ ZeroMemory(&mii,sizeof(mii));
+ mii.cbSize = MENUITEMINFO_V4_SIZE;
+ mii.fMask = MIIM_TYPE|MIIM_DATA;
+ mii.dwItemData = MENU_MIRANDAMENU;
+ mii.fType = MFT_OWNERDRAW;
+ mii.dwTypeData = NULL;
+ SetMenuItemInfo(GetMenu(m_hWnd),0,TRUE,&mii);
+
+ // mii.fMask = MIIM_TYPE;
+ mii.fType = MFT_OWNERDRAW;
+ mii.dwItemData = MENU_STATUSMENU;
+ SetMenuItemInfo(GetMenu(m_hWnd),1,TRUE,&mii);
+
+ // mii.fMask = MIIM_TYPE;
+ mii.fType = MFT_OWNERDRAW;
+ mii.dwItemData = MENU_MINIMIZE;
+ SetMenuItemInfo(GetMenu(m_hWnd),2,TRUE,&mii);
+ }
+ //PostMessage(m_hWnd, M_CREATECLC, 0, 0);
+ //pcli->hwndContactList = m_hWnd;
+ uMsgGetProfile = RegisterWindowMessage(_T("Miranda::GetProfile")); // don't localise
+ bTransparentFocus = 1;
+ return FALSE;
+}
+
+LRESULT CLUI::OnSetAllExtraIcons( UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ )
+{
+ return FALSE;
+}
+
+LRESULT CLUI::OnCreateClc( UINT /*msg*/, WPARAM /*wParam*/, LPARAM /*lParam*/ )
+{
+ CreateCLC();
+ if ( db_get_b( NULL, "CList", "ShowOnStart", SETTING_SHOWONSTART_DEFAULT ))
+ cliShowHide((WPARAM) m_hWnd, (LPARAM)TRUE );
+ PostMessage( pcli->hwndContactTree, CLM_AUTOREBUILD, 0, 0 );
+ return FALSE;
+}
+
+LRESULT CLUI::OnLButtonDown( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ POINT pt;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ ClientToScreen( m_hWnd, &pt );
+
+ if ( CLUI_SizingOnBorder( pt, 1 ))
+ {
+ mutex_bIgnoreActivation = TRUE;
+ return FALSE;
+ }
+ return DefCluiWndProc( msg, wParam, lParam );
+}
+LRESULT CLUI::OnParentNotify( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ switch ( wParam )
+ {
+ case WM_LBUTTONDOWN:
+ {
+ POINT pt;
+
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ ClientToScreen( m_hWnd, &pt );
+ wParam = 0;
+ lParam = 0;
+
+ if ( CLUI_SizingOnBorder( pt,1 ))
+ {
+ mutex_bIgnoreActivation = TRUE;
+ return 0;
+ }
+ }
+ }
+ return DefWindowProc(m_hWnd, msg, wParam, lParam);;
+}
+
+LRESULT CLUI::OnSetFocus( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ if ( hFrameContactTree && ( !CallService( MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM( FO_FLOATING, hFrameContactTree ), 0 )))
+ {
+ SetFocus(pcli->hwndContactTree);
+ }
+
+ return FALSE;
+}
+
+LRESULT CLUI::OnStatusBarUpdateTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ int status,i;
+ PROTOTICKS *pt = NULL;
+
+ for (i=0;i < 64;i++)
+ {
+
+ pt = &CycleStartTick[i];
+
+ if (pt->szProto != NULL && pt->bTimerCreated == 1)
+ {
+ if (pt->bGlobal)
+ status = g_bMultiConnectionMode?ID_STATUS_CONNECTING:0;
+ else
+ status = CallProtoService(pt->szProto,PS_GETSTATUS,0,0);
+
+ if ( !(status >= ID_STATUS_CONNECTING && status <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES))
+ {
+ pt->nCycleStartTick = 0;
+ ImageList_Destroy(pt->himlIconList);
+ pt->himlIconList = NULL;
+ KillTimer(m_hWnd,TM_STATUSBARUPDATE+pt->nIndex);
+ pt->bTimerCreated = 0;
+ }
+ }
+
+ };
+
+ pt = &CycleStartTick[wParam-TM_STATUSBARUPDATE];
+ {
+ if (IsWindowVisible(pcli->hwndStatus)) pcli->pfnInvalidateRect(pcli->hwndStatus,NULL,0);//InvalidateRectZ(pcli->hwndStatus,NULL,TRUE);
+ //if (DBGetContactSettingByte(NULL,"CList","TrayIcon",SETTING_TRAYICON_DEFAULT) != SETTING_TRAYICON_CYCLE)
+ if (pt->bGlobal)
+ cliTrayIconUpdateBase(g_szConnectingProto);
+ else
+ cliTrayIconUpdateBase(pt->szProto);
+
+ }
+ pcli->pfnInvalidateRect(pcli->hwndStatus,NULL,TRUE);
+ return DefCluiWndProc( msg, wParam, lParam );
+}
+
+LRESULT CLUI::OnAutoAlphaTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ int inwnd;
+
+ if (GetForegroundWindow() == m_hWnd)
+ {
+ KillTimer(m_hWnd,TM_AUTOALPHA);
+ inwnd = 1;
+ }
+ else
+ {
+ POINT pt;
+ HWND hwndPt;
+ pt.x = (short)LOWORD(GetMessagePos());
+ pt.y = (short)HIWORD(GetMessagePos());
+ hwndPt = WindowFromPoint(pt);
+
+ inwnd = FALSE;
+ inwnd = CLUI_CheckOwnedByClui(hwndPt);
+ if ( ! inwnd )
+ inwnd = ( GetCapture() == pcli->hwndContactList );
+
+ }
+ if (inwnd != bTransparentFocus)
+ { //change
+ HWND hwn = GetCapture();
+ hwn = hwn;
+ bTransparentFocus = inwnd;
+ if (bTransparentFocus) CLUI_SmoothAlphaTransition(m_hWnd, (BYTE)db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT), 1);
+ else
+ {
+ CLUI_SmoothAlphaTransition(m_hWnd, (BYTE)(g_bTransparentFlag?db_get_b(NULL,"CList","AutoAlpha",SETTING_AUTOALPHA_DEFAULT):255), 1);
+ }
+ }
+ if ( !bTransparentFocus) KillTimer(m_hWnd,TM_AUTOALPHA);
+ return TRUE;
+}
+LRESULT CLUI::OnSmoothAlphaTransitionTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ CLUI_SmoothAlphaTransition(m_hWnd, 0, 2);
+ return TRUE;
+}
+LRESULT CLUI::OnDelayedSizingTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ if ( mutex_bDelayedSizing && !mutex_bDuringSizing )
+ {
+ mutex_bDelayedSizing = 0;
+ KillTimer( m_hWnd,TM_DELAYEDSIZING );
+ pcli->pfnClcBroadcast( INTM_SCROLLBARCHANGED, 0, 0 );
+ }
+ return TRUE;
+}
+LRESULT CLUI::OnBringOutTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ //hide
+ KillTimer(m_hWnd,TM_BRINGINTIMEOUT);
+ KillTimer(m_hWnd,TM_BRINGOUTTIMEOUT);
+ bShowEventStarted = 0;
+ POINT pt; GetCursorPos(&pt);
+ HWND hAux = WindowFromPoint(pt);
+ BOOL mouse_in_window = CLUI_CheckOwnedByClui(hAux);
+ if ( !mouse_in_window && GetForegroundWindow() != m_hWnd )
+ CLUI_HideBehindEdge();
+ return TRUE;
+}
+LRESULT CLUI::OnBringInTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ //show
+ KillTimer(m_hWnd,TM_BRINGINTIMEOUT);
+ bShowEventStarted = 0;
+ KillTimer(m_hWnd,TM_BRINGOUTTIMEOUT);
+ POINT pt; GetCursorPos(&pt);
+ HWND hAux = WindowFromPoint(pt);
+ BOOL mouse_in_window = FALSE;
+ while(hAux != NULL)
+ {
+ if (hAux == m_hWnd) { mouse_in_window = TRUE; break;}
+ hAux = GetParent(hAux);
+ }
+ if ( mouse_in_window )
+ CLUI_ShowFromBehindEdge();
+ return TRUE;
+}
+LRESULT CLUI::OnUpdateBringTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ CLUI_UpdateTimer( 0 );
+ return TRUE;
+}
+
+LRESULT CLUI::OnTimer( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ if ( MirandaExiting()) return FALSE;
+
+ if ((int)wParam >= TM_STATUSBARUPDATE && (int)wParam <= TM_STATUSBARUPDATE+64 )
+ {
+ if ( !pcli->hwndStatus ) return FALSE;
+ else return OnStatusBarUpdateTimer( msg, wParam, lParam );
+ }
+
+ switch ( wParam )
+ {
+ case TM_AUTOALPHA: return OnAutoAlphaTimer( msg, wParam, lParam );
+ case TM_SMOTHALPHATRANSITION: return OnSmoothAlphaTransitionTimer( msg, wParam, lParam );
+ case TM_DELAYEDSIZING: return OnDelayedSizingTimer( msg, wParam, lParam );
+ case TM_BRINGOUTTIMEOUT: return OnBringOutTimer( msg, wParam, lParam );
+ case TM_BRINGINTIMEOUT: return OnBringInTimer( msg, wParam, lParam );
+ case TM_UPDATEBRINGTIMER: return OnUpdateBringTimer( msg, wParam, lParam );
+ default: return DefCluiWndProc( msg, wParam, lParam );
+ }
+ return TRUE;
+}
+
+
+LRESULT CLUI::OnActivate( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ BOOL IsOption = FALSE;
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ SendMessage(pcli->hwndContactTree, WM_ACTIVATE, wParam, lParam);
+ if (db_get_b(NULL, "ModernData", "HideBehind", SETTING_HIDEBEHIND_DEFAULT))
+ {
+ if (wParam == WA_INACTIVE && ((HWND)lParam != m_hWnd) && GetParent((HWND)lParam) != m_hWnd && !IsOption)
+ {
+ if ( !g_bCalledFromShowHide) CLUI_UpdateTimer(0);
+ }
+ else if ( !g_bCalledFromShowHide )
+ {
+ CLUI_ShowFromBehindEdge();
+ }
+ }
+
+ if ( !IsWindowVisible(m_hWnd) || mutex_bShowHideCalledFromAnimation)
+ {
+ KillTimer(m_hWnd,TM_AUTOALPHA);
+ return 0;
+ }
+ if (wParam == WA_INACTIVE && ((HWND)lParam != m_hWnd) && !CLUI_CheckOwnedByClui((HWND)lParam) && !IsOption)
+ {
+ if (g_bTransparentFlag)
+ if (bTransparentFocus)
+ CLUI_SafeSetTimer(m_hWnd, TM_AUTOALPHA,250,NULL);
+
+ }
+ else {
+ if ( !db_get_b(NULL,"CList","OnTop",SETTING_ONTOP_DEFAULT))
+ Sync(CLUIFrames_ActivateSubContainers,TRUE);
+ if (g_bTransparentFlag) {
+ KillTimer(m_hWnd,TM_AUTOALPHA);
+ CLUI_SmoothAlphaTransition(m_hWnd, db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT), 1);
+ bTransparentFocus = 1;
+ }
+ }
+ RedrawWindow(m_hWnd,NULL,NULL,RDW_INVALIDATE|RDW_ALLCHILDREN);
+ if (g_bTransparentFlag)
+ {
+ BYTE alpha;
+ if (wParam != WA_INACTIVE || CLUI_CheckOwnedByClui((HWND)lParam) || IsOption || ((HWND)lParam == m_hWnd) || GetParent((HWND)lParam) == m_hWnd) alpha = db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT);
+ else
+ alpha = g_bTransparentFlag?db_get_b(NULL,"CList","AutoAlpha",SETTING_AUTOALPHA_DEFAULT):255;
+ CLUI_SmoothAlphaTransition(m_hWnd, alpha, 1);
+ if (IsOption) DefWindowProc(m_hWnd,msg,wParam,lParam);
+ else return 1;
+ }
+ return DefWindowProc(m_hWnd,msg,wParam,lParam);
+}
+
+LRESULT CLUI::OnSetCursor( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ HWND gf = GetForegroundWindow();
+ if (g_CluiData.nBehindEdgeState >= 0) CLUI_UpdateTimer(1);
+ if (g_bTransparentFlag) {
+ if ( !bTransparentFocus && gf != m_hWnd)
+ {
+ CLUI_SmoothAlphaTransition(m_hWnd, db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT), 1);
+ bTransparentFocus = 1;
+ CLUI_SafeSetTimer(m_hWnd, TM_AUTOALPHA,250,NULL);
+ }
+ }
+ int k = CLUI_TestCursorOnBorders();
+ return k ? k : 1;
+}
+
+LRESULT CLUI::OnMouseActivate( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+
+ if ( mutex_bIgnoreActivation )
+ {
+ mutex_bIgnoreActivation = 0;
+ return( MA_NOACTIVATEANDEAT );
+ }
+ int lRes = DefWindowProc(m_hWnd,msg,wParam,lParam);
+ CLUIFrames_RepaintSubContainers();
+ return lRes;
+}
+
+LRESULT CLUI::OnNcLButtonDown( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ POINT pt;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ int k = CLUI_SizingOnBorder(pt,1);
+ return k ? k : DefWindowProc( m_hWnd, msg, wParam, lParam );
+}
+
+LRESULT CLUI::OnNcLButtonDblClk( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ if (wParam == HTMENU || wParam == HTCAPTION)
+ {
+ RECT rc;
+ GetWindowRect(m_hWnd, &rc);
+ POINT pt;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ if ( pt.x > rc.right - 16 && pt.x < rc.right )
+ return CallService(MS_CLIST_SHOWHIDE, 0, 0);
+ }
+ return DefCluiWndProc( msg, wParam, lParam );
+}
+
+LRESULT CLUI::OnNcHitTest( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ LRESULT result;
+ result = DefWindowProc(m_hWnd,WM_NCHITTEST,wParam,lParam);
+
+ if ((g_CluiData.fAutoSize) && ( result == HTSIZE || result == HTTOP ||
+ result == HTTOPLEFT || result == HTTOPRIGHT ||
+ result == HTBOTTOM || result == HTBOTTOMRIGHT ||
+ result == HTBOTTOMLEFT))
+ return HTCLIENT;
+
+ if (result == HTMENU)
+ {
+ int t;
+ POINT pt;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ t = MenuItemFromPoint(m_hWnd,g_hMenuMain,pt);
+
+ if (t == -1 && (db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT)))
+ return HTCAPTION;
+ }
+
+ if (result == HTCLIENT)
+ {
+ POINT pt;
+ int k;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ k = CLUI_SizingOnBorder(pt,0);
+ if ( !k && (db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT)))
+ return HTCAPTION;
+ else return k+9;
+ }
+ return result;
+}
+
+LRESULT CLUI::OnShowWindow( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ BYTE gAlpha;
+
+ if (lParam) return 0;
+ if (mutex_bShowHideCalledFromAnimation) return 1;
+ {
+
+ if ( !wParam) gAlpha = 0;
+ else
+ gAlpha = (db_get_b(NULL,"CList","Transparent",SETTING_TRANSPARENT_DEFAULT)?db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT):255);
+ if (wParam)
+ {
+ g_CluiData.bCurrentAlpha = 0;
+ Sync(CLUIFrames_OnShowHide, pcli->hwndContactList,1);
+ ske_RedrawCompleteWindow();
+ }
+ CLUI_SmoothAlphaTransition(m_hWnd, gAlpha, 1);
+ }
+ return FALSE;
+}
+
+LRESULT CLUI::OnSysCommand( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ switch (wParam)
+ {
+ case SC_MAXIMIZE:
+ return 0;
+
+ case SC_CLOSE:
+ PostMessage(m_hWnd, msg, SC_MINIMIZE, lParam);
+ return 0;
+ }
+
+ DefWindowProc(m_hWnd, msg, wParam, lParam);
+ if (db_get_b(NULL,"CList","OnDesktop",SETTING_ONDESKTOP_DEFAULT))
+ Sync( CLUIFrames_ActivateSubContainers, TRUE );
+ return FALSE;
+}
+
+LRESULT CLUI::OnKeyDown( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ if (wParam == VK_F5)
+ SendMessage(pcli->hwndContactTree,CLM_AUTOREBUILD,0,0);
+ return DefCluiWndProc( msg, wParam, lParam );
+}
+
+LRESULT CLUI::OnGetMinMaxInfo( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ DefWindowProc(m_hWnd,msg,wParam,lParam);
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = max(db_get_w(NULL,"CLUI","MinWidth",SETTING_MINWIDTH_DEFAULT),max(18,db_get_b(NULL,"CLUI","LeftClientMargin",SETTING_LEFTCLIENTMARIGN_DEFAULT)+db_get_b(NULL,"CLUI","RightClientMargin",SETTING_RIGHTCLIENTMARIGN_DEFAULT)+18));
+ if (nRequiredHeight == 0)
+ {
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = CLUIFramesGetMinHeight();
+ }
+ return FALSE;
+}
+
+LRESULT CLUI::OnMoving( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ CallWindowProc( DefWindowProc, m_hWnd, msg, wParam, lParam );
+ if ( FALSE ) //showcontents is turned on
+ {
+ Sync(CLUIFrames_OnMoving,m_hWnd,(RECT*)lParam);
+ }
+ return TRUE;
+}
+
+LRESULT CLUI::OnNewContactNotify( NMCLISTCONTROL * pnmc )
+{
+ ExtraImage_SetAllExtraIcons( pcli->hwndContactTree, pnmc->hItem );
+ return FALSE;
+}
+
+LRESULT CLUI::OnListRebuildNotify( NMCLISTCONTROL * pnmc )
+{
+ ExtraImage_SetAllExtraIcons( pcli->hwndContactTree, 0 );
+ return FALSE;
+}
+LRESULT CLUI::OnListSizeChangeNotify( NMCLISTCONTROL * pnmc )
+{
+
+ // TODO: Check and refactor possible problem of clist resized to full screen problem
+ static RECT rcWindow,rcTree,rcTree2,rcWorkArea,rcOld;
+ int maxHeight, minHeight,newHeight;
+ int winstyle;
+ if (mutex_bDisableAutoUpdate == 1)
+ return FALSE;
+ if (mutex_bDuringSizing)
+ rcWindow = rcSizingRect;
+ else
+ GetWindowRect(m_hWnd,&rcWindow);
+ if ( !g_CluiData.fAutoSize || pcli->hwndContactTree == 0 || CallService(MS_CLIST_DOCKINGISDOCKED,0,0))
+ return FALSE;
+
+ maxHeight = db_get_b(NULL,"CLUI","MaxSizeHeight",SETTING_MAXSIZEHEIGHT_DEFAULT);
+ minHeight = db_get_b(NULL,"CLUI","MinSizeHeight",SETTING_MINSIZEHEIGHT_DEFAULT);
+ rcOld = rcWindow;
+ GetWindowRect(pcli->hwndContactTree,&rcTree);
+
+ FRAMEWND* frm = FindFrameByItsHWND(pcli->hwndContactTree);
+ if (frm)
+ rcTree2 = frm->wndSize;
+ else
+ SetRect(&rcTree2,0,0,0,0);
+
+ winstyle = GetWindowLongPtr(pcli->hwndContactTree,GWL_STYLE);
+
+ SystemParametersInfo(SPI_GETWORKAREA,0,&rcWorkArea,FALSE);
+ if (MyMonitorFromWindow)
+ {
+ HMONITOR hMon = MyMonitorFromWindow(pcli->hwndContactTree, MONITOR_DEFAULTTONEAREST);
+ MONITORINFO mi;
+ mi.cbSize = sizeof(mi);
+ if (MyGetMonitorInfo(hMon, &mi))
+ rcWorkArea = mi.rcWork;
+ }
+
+
+ if (pnmc->pt.y>(rcWorkArea.bottom-rcWorkArea.top))
+ {
+ pnmc->pt.y = (rcWorkArea.bottom-rcWorkArea.top);
+
+ };
+ if ((pnmc->pt.y) == nLastRequiredHeight)
+ {
+ }
+ nLastRequiredHeight = pnmc->pt.y;
+ newHeight = max(CLUIFramesGetMinHeight(),max(pnmc->pt.y,3)+1+((winstyle&WS_BORDER)?2:0)+(rcWindow.bottom-rcWindow.top)-(rcTree.bottom-rcTree.top));
+ if (newHeight < (rcWorkArea.bottom-rcWorkArea.top)*minHeight/100)
+ newHeight = (rcWorkArea.bottom-rcWorkArea.top)*minHeight/100;
+
+ if (newHeight>(rcWorkArea.bottom-rcWorkArea.top)*maxHeight/100)
+ newHeight = (rcWorkArea.bottom-rcWorkArea.top)*maxHeight/100;
+
+ if (newHeight == (rcWindow.bottom-rcWindow.top)) return 0;
+
+ if (db_get_b(NULL,"CLUI","AutoSizeUpward",SETTING_AUTOSIZEUPWARD_DEFAULT)) {
+ rcWindow.top = rcWindow.bottom-newHeight;
+ if (rcWindow.top < rcWorkArea.top) rcWindow.top = rcWorkArea.top;
+ }
+ else {
+ rcWindow.bottom = rcWindow.top+newHeight;
+ if (rcWindow.bottom>rcWorkArea.bottom) rcWindow.bottom = rcWorkArea.bottom;
+ }
+ if (nRequiredHeight == 1)
+ return FALSE;
+ nRequiredHeight = 1;
+ if (mutex_bDuringSizing)
+ {
+ bNeedFixSizingRect = 1;
+ rcSizingRect.top = rcWindow.top;
+ rcSizingRect.bottom = rcWindow.bottom;
+ rcCorrectSizeRect = rcSizingRect;
+ }
+ else
+ {
+ bNeedFixSizingRect = 0;
+ }
+ if ( !mutex_bDuringSizing)
+ SetWindowPos(m_hWnd,0,rcWindow.left,rcWindow.top,rcWindow.right-rcWindow.left,rcWindow.bottom-rcWindow.top,SWP_NOZORDER|SWP_NOACTIVATE);
+ else
+ {
+ SetWindowPos(m_hWnd,0,rcWindow.left,rcWindow.top,rcWindow.right-rcWindow.left,rcWindow.bottom-rcWindow.top,SWP_NOZORDER|SWP_NOACTIVATE);
+ }
+ nRequiredHeight = 0;
+
+ return FALSE;
+}
+
+LRESULT CLUI::OnClickNotify( NMCLISTCONTROL * pnmc )
+{
+ DWORD hitFlags;
+ HANDLE hItem = (HANDLE)SendMessage(pcli->hwndContactTree,CLM_HITTEST,(WPARAM)&hitFlags,MAKELPARAM(pnmc->pt.x,pnmc->pt.y));
+
+ if (hitFlags&CLCHT_ONITEMEXTRA)
+ {
+ if ( !IsHContactGroup(hItem) && !IsHContactInfo(hItem))
+ {
+ pdisplayNameCacheEntry pdnce = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(pnmc->hItem);
+ if (pdnce == NULL) return 0;
+
+ int extra = ExtraImage_ColumnNumToExtraID(pnmc->iColumn);
+ NotifyEventHooks(g_CluiData.hEventExtraClick, (WPARAM)pnmc->hItem, extra);
+
+ if ( !ServiceExists("ExtraIcon/Register"))
+ {
+ int v,e,w;
+ v = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_PROTO);
+ e = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_EMAIL);
+ w = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_WEB);
+
+ if (pnmc->iColumn == v) {
+ CallService(MS_USERINFO_SHOWDIALOG,(WPARAM)pnmc->hItem,0);
+ };
+ if (pnmc->iColumn == e)
+ {
+ char *email = db_get_sa(pnmc->hItem,"UserInfo", "Mye-mail0");
+ if ( !email)
+ email = db_get_sa(pnmc->hItem, pdnce->m_cache_cszProto, "e-mail");
+ if (email) {
+ char buf[4096];
+ sprintf(buf,"mailto:%s",email);
+ mir_free(email);
+ ShellExecuteA(m_hWnd,"open",buf,NULL,NULL,SW_SHOW);
+ }
+ };
+ if (pnmc->iColumn == w) {
+ char *homepage = db_get_sa(pdnce->hContact,"UserInfo", "Homepage");
+ if ( !homepage)
+ homepage = db_get_sa(pdnce->hContact,pdnce->m_cache_cszProto, "Homepage");
+ if (homepage != NULL)
+ {
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM)homepage);
+ mir_free(homepage);
+ }
+ }
+ }
+ }
+ };
+ if (hItem && !(hitFlags&CLCHT_NOWHERE))
+ return DefCluiWndProc( WM_NOTIFY, 0, (LPARAM)pnmc );
+ if ((hitFlags&(CLCHT_NOWHERE|CLCHT_INLEFTMARGIN|CLCHT_BELOWITEMS)) == 0)
+ return DefCluiWndProc( WM_NOTIFY, 0, (LPARAM)pnmc );
+ if (db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT)) {
+ POINT pt;
+ int res;
+ pt = pnmc->pt;
+ ClientToScreen(pcli->hwndContactTree,&pt);
+ res = PostMessage(m_hWnd, WM_SYSCOMMAND, SC_MOVE|HTCAPTION,MAKELPARAM(pt.x,pt.y));
+ return res;
+ }
+ /*== == == == == == == == == = */
+ if (db_get_b(NULL,"CLUI","DragToScroll",SETTING_DRAGTOSCROLL_DEFAULT) && !db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT))
+ return ClcEnterDragToScroll(pcli->hwndContactTree,pnmc->pt.y);
+ /*== == == == == == == == == = */
+ return 0;
+}
+
+LRESULT CLUI::OnNotify( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ LPNMHDR pnmhdr = (LPNMHDR)lParam;
+ if ( pnmhdr->hwndFrom != pcli->hwndContactTree )
+ return DefCluiWndProc( msg, wParam, lParam );
+
+ switch ( pnmhdr->code)
+ {
+ case CLN_NEWCONTACT: return OnNewContactNotify((NMCLISTCONTROL *)pnmhdr );
+ case CLN_LISTREBUILT: return OnListRebuildNotify((NMCLISTCONTROL *)pnmhdr );
+ case CLN_LISTSIZECHANGE: return OnListSizeChangeNotify((NMCLISTCONTROL *)pnmhdr );
+ case NM_CLICK: return OnClickNotify((NMCLISTCONTROL *)pnmhdr );
+
+ }
+ return DefCluiWndProc( msg, wParam, lParam );
+}
+
+LRESULT CLUI::OnContextMenu( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ RECT rc;
+ POINT pt;
+
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ // x/y might be -1 if it was generated by a kb click
+ GetWindowRect(pcli->hwndContactTree,&rc);
+ if ( pt.x == -1 && pt.y == -1) {
+ // all this is done in screen-coords!
+ GetCursorPos(&pt);
+ // the mouse isnt near the window, so put it in the middle of the window
+ if ( !PtInRect(&rc,pt)) {
+ pt.x = rc.left + (rc.right - rc.left) / 2;
+ pt.y = rc.top + (rc.bottom - rc.top) / 2;
+ }
+ }
+ if (PtInRect( &rc ,pt ))
+ {
+ HMENU hMenu;
+ hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDGROUP,0,0);
+ TrackPopupMenu(hMenu,TPM_TOPALIGN|TPM_LEFTALIGN|TPM_LEFTBUTTON,pt.x,pt.y,0,m_hWnd,NULL);
+ DestroyTrayMenu(hMenu);
+ }
+ return FALSE;
+
+}
+LRESULT CLUI::OnMeasureItem( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ LPMEASUREITEMSTRUCT pmis = (LPMEASUREITEMSTRUCT)lParam;
+ switch ( pmis->itemData )
+ {
+ case MENU_MIRANDAMENU:
+ {
+ pmis->itemWidth = GetSystemMetrics( SM_CXSMICON ) * 4 / 3;
+ pmis->itemHeight = 0;
+ }
+ return TRUE;
+ case MENU_STATUSMENU:
+ {
+ HDC hdc;
+ SIZE textSize;
+ hdc = GetDC( m_hWnd );
+ GetTextExtentPoint32A( hdc, Translate("Status"), lstrlenA( Translate( "Status" )), &textSize );
+ pmis->itemWidth = textSize.cx;
+ pmis->itemHeight = 0;
+ ReleaseDC( m_hWnd, hdc );
+ }
+ return TRUE;
+ }
+ return CallService( MS_CLIST_MENUMEASUREITEM, wParam, lParam );
+}
+
+LRESULT CLUI::OnDrawItem( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ struct ClcData * dat = (struct ClcData*)GetWindowLongPtr(pcli->hwndContactTree,0);
+ LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
+ if ( !dat) return 0;
+
+ if (dis->CtlType == ODT_MENU) {
+ if (dis->itemData == MENU_MIRANDAMENU) {
+ if ( !g_CluiData.fLayered)
+ {
+ char buf[255];
+ short offset = 1 + ( dis->itemState&ODS_SELECTED ? 1 : 0 )
+ - ( dis->itemState&ODS_HOTLIGHT ? 1 : 0 );
+
+ HICON hIcon = LoadSkinnedIcon(SKINICON_OTHER_MAINMENU);
+
+ CLUI_DrawMenuBackGround(m_hWnd, dis->hDC, 1, dis->itemState);
+ mir_snprintf(buf,SIZEOF(buf),"Main,ID=MainMenu,Selected=%s,Hot=%s",(dis->itemState&ODS_SELECTED)?"True":"False",(dis->itemState&ODS_HOTLIGHT)?"True":"False");
+ SkinDrawGlyph(dis->hDC,&dis->rcItem,&dis->rcItem,buf);
+
+ int x = (dis->rcItem.right + dis->rcItem.left - GetSystemMetrics(SM_CXSMICON)) / 2 + offset;
+ int y = (dis->rcItem.bottom + dis->rcItem.top - GetSystemMetrics(SM_CYSMICON)) / 2 + offset;
+
+ DrawState( dis->hDC, NULL, NULL, (LPARAM)hIcon, 0, x, y , 0 , 0 ,
+ DST_ICON | ( dis->itemState & ODS_INACTIVE && (((FALSE))) ? DSS_DISABLED : DSS_NORMAL ));
+
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ nMirMenuState = dis->itemState;
+ } else {
+ nMirMenuState = dis->itemState;
+ pcli->pfnInvalidateRect(m_hWnd,NULL,0);
+ }
+ return TRUE;
+ }
+ else if (dis->itemData == MENU_STATUSMENU) {
+ if ( !g_CluiData.fLayered)
+ {
+ char buf[255] = {0};
+ RECT rc = dis->rcItem;
+ short dx = 1+(dis->itemState&ODS_SELECTED?1:0)-(dis->itemState&ODS_HOTLIGHT?1:0);
+ if (dx>1){
+ rc.left += dx;
+ rc.top += dx;
+ }else if (dx == 0){
+ rc.right -= 1;
+ rc.bottom -= 1;
+ }
+ CLUI_DrawMenuBackGround(m_hWnd, dis->hDC, 2, dis->itemState);
+ SetBkMode(dis->hDC,TRANSPARENT);
+ mir_snprintf(buf,SIZEOF(buf),"Main,ID=StatusMenu,Selected=%s,Hot=%s",(dis->itemState&ODS_SELECTED)?"True":"False",(dis->itemState&ODS_HOTLIGHT)?"True":"False");
+ SkinDrawGlyph(dis->hDC,&dis->rcItem,&dis->rcItem,buf);
+ SetTextColor(dis->hDC, (dis->itemState&ODS_SELECTED/*|dis->itemState&ODS_HOTLIGHT*/)?dat->MenuTextHiColor:dat->MenuTextColor);
+ DrawText(dis->hDC,TranslateT("Status"), lstrlen(TranslateT("Status")),&rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
+ nStatusMenuState = dis->itemState;
+ } else {
+ nStatusMenuState = dis->itemState;
+ pcli->pfnInvalidateRect(m_hWnd,NULL,0);
+ }
+ return TRUE;
+ } else if (dis->itemData == MENU_MINIMIZE && !g_CluiData.fLayered)
+ {
+ //TODO check if caption is visible
+ char buf[255] = {0};
+ short dx = 1+(dis->itemState&ODS_SELECTED?1:0)-(dis->itemState&ODS_HOTLIGHT?1:0);
+ HICON hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ CLUI_DrawMenuBackGround(m_hWnd, dis->hDC, 3, dis->itemState);
+ mir_snprintf(buf,SIZEOF(buf),"Main,ID=MainMenu,Selected=%s,Hot=%s",(dis->itemState&ODS_SELECTED)?"True":"False",(dis->itemState&ODS_HOTLIGHT)?"True":"False");
+ SkinDrawGlyph(dis->hDC,&dis->rcItem,&dis->rcItem,buf);
+ DrawState(dis->hDC,NULL,NULL,(LPARAM)hIcon,0,(dis->rcItem.right+dis->rcItem.left-GetSystemMetrics(SM_CXSMICON))/2+dx,(dis->rcItem.bottom+dis->rcItem.top-GetSystemMetrics(SM_CYSMICON))/2+dx,0,0,DST_ICON|(dis->itemState&ODS_INACTIVE && FALSE?DSS_DISABLED:DSS_NORMAL));
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ nMirMenuState = dis->itemState;
+ }
+
+ return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam);
+ }
+ return 0;
+}
+
+LRESULT CLUI::OnDestroy( UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ int state = db_get_b(NULL,"CList","State",SETTING_STATE_NORMAL);
+ BOOL wait = FALSE;
+
+ AniAva_UnloadModule();
+ TRACE("CLUI.c: WM_DESTROY\n");
+ g_CluiData.bSTATE = STATE_EXITING;
+ CLUI_DisconnectAll();
+ //fire the "Away Message" Event to wake the thread so it can die.
+ //fire the "Get Text Async" Event to wake the thread so it can die.
+ if (amWakeThread())
+ wait = TRUE;
+
+ if (gtaWakeThread())
+ wait = TRUE;
+
+ if (wait)
+ {
+ //need to give them a little time to exit.
+ Sleep(50);
+ }
+
+ TRACE("CLUI.c: WM_DESTROY - WaitThreadsCompletion \n");
+ while (CLUI_WaitThreadsCompletion(m_hWnd)); //stop all my threads
+ TRACE("CLUI.c: WM_DESTROY - WaitThreadsCompletion DONE\n");
+
+ for (int i=0; i < 64; i++)
+ if (CycleStartTick[i].szProto)
+ mir_free_and_nil(CycleStartTick[i].szProto);
+
+ if (state == SETTING_STATE_NORMAL)
+ CLUI_ShowWindowMod(m_hWnd,SW_HIDE);
+ UnLoadContactListModule();
+ ClcUnloadModule();
+
+ RemoveMenu(g_hMenuMain, 0, MF_BYPOSITION);
+ RemoveMenu(g_hMenuMain, 0, MF_BYPOSITION);
+ DestroyMenu(g_hMenuMain);
+
+ pcli->pfnTrayIconDestroy(m_hWnd);
+ mutex_bAnimationInProgress = 0;
+ CallService(MS_CLIST_FRAMES_REMOVEFRAME,(WPARAM)hFrameContactTree,(LPARAM)0);
+ TRACE("CLUI.c: WM_DESTROY - hFrameContactTree removed\n");
+ pcli->hwndContactTree = NULL;
+ pcli->hwndStatus = NULL;
+ {
+ if (g_CluiData.fAutoSize && !g_CluiData.fDocked)
+ {
+ RECT r;
+ GetWindowRect(pcli->hwndContactList,&r);
+ if (db_get_b(NULL,"CLUI","AutoSizeUpward",SETTING_AUTOSIZEUPWARD_DEFAULT))
+ r.top = r.bottom-CLUIFrames_GetTotalHeight();
+ else
+ r.bottom = r.top+CLUIFrames_GetTotalHeight();
+ db_set_dw(NULL,"CList","y",r.top);
+ db_set_dw(NULL,"CList","Height",r.bottom-r.top);
+ }
+ }
+ UnLoadCLUIFramesModule();
+ //ExtFrames_Uninit();
+ TRACE("CLUI.c: WM_DESTROY - UnLoadCLUIFramesModule DONE\n");
+ db_set_b(NULL,"CList","State",(BYTE)state);
+ ske_UnloadSkin(&g_SkinObjectList);
+
+ delete m_pCLUI;
+
+ pcli->hwndContactList = NULL;
+ pcli->hwndStatus = NULL;
+ PostQuitMessage(0);
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_cluiframes.cpp b/plugins/Clist_modern/src/modern_cluiframes.cpp
new file mode 100644
index 0000000000..4e6940e5e2
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_cluiframes.cpp
@@ -0,0 +1,4222 @@
+/*
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "hdr/modern_commonheaders.h"
+#include "m_api/m_skin_eng.h"
+#include "hdr/modern_cluiframes.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_sync.h"
+
+
+// ALL THIS MODULE FUNCTION SHOULD BE EXECUTED FROM MAIN THREAD
+
+#include "hdr/modern_static_cluiframes_service.h" // contain services initialization and proxiation
+
+
+static const int UNCOLLAPSED_FRAME_SIZE = 0;
+static const int DEFAULT_TITLEBAR_HEIGHT = 18;
+
+//GLOBALS
+FRAMEWND * g_pfwFrames = NULL;
+int g_nFramesCount = 0;
+int g_nTitleBarHeight = DEFAULT_TITLEBAR_HEIGHT;
+
+// STATIC
+
+enum {
+ frame_menu_lock = 1,
+ frame_menu_visible,
+ frame_menu_showtitlebar,
+ frame_menu_floating
+}; //legacy menu support
+
+enum { eUnknownId = -1 };
+
+static int _us_DoSetFrameFloat( WPARAM wParam,LPARAM lParam );
+static int CLUIFrameResizeFloatingFrame( int framepos );
+static HWND CreateSubContainerWindow( HWND parent,int x,int y,int width,int height );
+static BOOL CLUIFramesFitInSize();
+static int RemoveItemFromList(int pos, FRAMEWND **lpFrames, int *FrameItemCount );
+static int _us_DoSetFramePaintProc(WPARAM wParam, LPARAM lParam);
+
+
+
+static CRITICAL_SECTION _cluiFramesModuleCS = {0};
+static BOOL _cluiFramesModuleCSInitialized = FALSE;
+static BOOL _fCluiFramesModuleNotStarted = TRUE;
+static XPTHANDLE _hFrameTitleTheme = NULL;
+static int _nClientFrameId = eUnknownId; //for fast access to frame with alclient properties
+static int _iNextFrameId = 100;
+static HFONT _hTitleBarFont = NULL;
+
+// menus
+static HGENMENU _hmiVisible = (HGENMENU)-1;
+static HGENMENU _hmiTBVisible = (HGENMENU)-1;
+static HGENMENU _hmiLock = (HGENMENU)-1;
+static HGENMENU _hmiColl = (HGENMENU)-1;
+static HGENMENU _hmiFloating = (HGENMENU)-1;
+static HGENMENU _hmiAlignRoot = (HGENMENU)-1;
+static HGENMENU _hmiAlignTop = (HGENMENU)-1;
+static HGENMENU _hmiAlignClient = (HGENMENU)-1;
+static HGENMENU _hmiAlignBottom = (HGENMENU)-1;
+static HGENMENU _hmiPosRoot = (HGENMENU)-1;
+static HGENMENU _hmiPosUp = (HGENMENU)-1;
+static HGENMENU _hmiPosDown = (HGENMENU)-1;
+static HGENMENU _hmiBorder = (HGENMENU)-1;
+static HGENMENU _hmiRoot = (HGENMENU)-1;
+
+// others
+static int _nContactListHeight = 0;
+static DWORD _dwLastStoreTick = 0;
+
+HWND hWndExplorerToolBar;
+static int GapBetweenFrames = 1;
+
+BOOLEAN bMoveTogether;
+int recurs_prevent = 0;
+static BOOL PreventSizeCalling = FALSE;
+
+static HBITMAP hBmpBackground;
+static int backgroundBmpUse;
+static COLORREF bkColour;
+static COLORREF SelBkColour;
+static BOOL bkUseWinColours;
+BYTE AlignCOLLIconToLeft; //will hide frame icon
+COLORREF sttGetColor(char * module, char * color, COLORREF defColor);
+//for old multiwindow
+#define MPCF_CONTEXTFRAMEMENU 3
+POINT ptOld;
+short nLeft = 0;
+short nTop = 0;
+
+static int sortfunc(const void *a,const void *b)
+{
+ SortData *sd1,*sd2;
+ sd1 = (SortData *)a;
+ sd2 = (SortData *)b;
+ if (sd1->order > sd2->order){return(1);};
+ if (sd1->order < sd2->order){return(-1);};
+ return (0);
+};
+int CLUIFrames_OnMoving( HWND hwnd, RECT * r)
+{
+ int i;
+ g_CluiData.mutexPreventDockMoving = 0;
+ for (i=0;i < g_nFramesCount;i++) {
+
+ if ( !g_pfwFrames[i].floating && g_pfwFrames[i].OwnerWindow != NULL && g_pfwFrames[i].OwnerWindow != (HWND)-2)
+ {
+ int x;
+ int y;
+ int dx,dy;
+ FRAMEWND * Frame;
+ POINT pt = {0};
+ RECT wr;
+ Frame = &(g_pfwFrames[i]);
+
+ GetWindowRect(hwnd,&wr);
+ ClientToScreen(hwnd,&pt);
+ dx = (r->left-wr.left)+pt.x;
+ dy = (r->top-wr.top)+pt.y;
+ x = Frame->wndSize.left;
+ y = Frame->wndSize.top;
+ SetWindowPos(Frame->OwnerWindow,NULL,x+dx,y+dy,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSENDCHANGING|SWP_ASYNCWINDOWPOS|SWP_DEFERERASE|SWP_NOOWNERZORDER);
+ };
+
+ }
+ g_CluiData.mutexPreventDockMoving = 1;
+ AniAva_RedrawAllAvatars(FALSE);
+ return 0;
+}
+int SetAlpha(BYTE Alpha)
+{
+ int i;
+
+ for (i=0;i < g_nFramesCount;i++) {
+
+ if ( !g_pfwFrames[i].floating && g_pfwFrames[i].OwnerWindow != NULL && g_pfwFrames[i].OwnerWindow != (HWND)-2 && g_pfwFrames[i].visible && !g_pfwFrames[i].needhide )
+ {
+ HWND hwnd = g_pfwFrames[i].OwnerWindow;
+ if (g_proc_SetLayeredWindowAttributesNew)
+ {
+ long l;
+ l = GetWindowLongPtr(hwnd,GWL_EXSTYLE);
+ if ( !(l&WS_EX_LAYERED))
+ {
+ HWND parent = NULL;
+ if (g_CluiData.fOnDesktop)
+ {
+ HWND hProgMan = FindWindow(_T("Progman"),NULL);
+ if (IsWindow(hProgMan))
+ parent = hProgMan;
+ }
+
+ CLUI_ShowWindowMod(hwnd,SW_HIDE);
+ SetParent(hwnd,NULL);
+ SetWindowLongPtr(hwnd,GWL_EXSTYLE,l|WS_EX_LAYERED);
+ SetParent(hwnd,parent);
+ if (l&WS_VISIBLE) CLUI_ShowWindowMod(hwnd,SW_SHOW);
+ }
+ g_proc_SetLayeredWindowAttributesNew(hwnd, g_CluiData.dwKeyColor,Alpha, LWA_ALPHA|LWA_COLORKEY);
+ }
+ }
+ }
+ AniAva_RedrawAllAvatars(FALSE);
+ return 0;
+}
+
+
+int CLUIFrames_RepaintSubContainers()
+{
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ if ( !g_pfwFrames[i].floating && g_pfwFrames[i].OwnerWindow != (HWND)0 && g_pfwFrames[i].OwnerWindow != (HWND)-2 && g_pfwFrames[i].visible && !g_pfwFrames[i].needhide )
+ {
+ RedrawWindow(g_pfwFrames[i].hWnd,NULL,NULL,RDW_ALLCHILDREN|RDW_UPDATENOW|RDW_INVALIDATE|RDW_FRAME);
+ };
+ return 0;
+}
+
+int CLUIFrames_ActivateSubContainers( BOOL active)
+{
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ if (active && !g_pfwFrames[i].floating && g_pfwFrames[i].OwnerWindow != (HWND)0 && g_pfwFrames[i].OwnerWindow != (HWND)-2 && g_pfwFrames[i].visible && !g_pfwFrames[i].needhide )
+ {
+ HWND hwnd = g_pfwFrames[i].OwnerWindow;
+ hwnd = g_pfwFrames[i].hWnd;//OwnerWindow;
+ if (db_get_b(NULL,"CList","OnDesktop",SETTING_ONDESKTOP_DEFAULT))
+ {
+ SetWindowPos(g_pfwFrames[i].OwnerWindow,HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+ SetWindowPos(g_pfwFrames[i].OwnerWindow,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+ }
+ else SetWindowPos(g_pfwFrames[i].OwnerWindow, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOSIZE | SWP_NOMOVE);
+ };
+ return 0;
+}
+int CLUIFrames_SetParentForContainers( HWND parent )
+{
+ int i;
+ if (parent && parent != pcli->hwndContactList)
+ g_CluiData.fOnDesktop = 1;
+ else
+ g_CluiData.fOnDesktop = 0;
+ for (i=0;i < g_nFramesCount;i++) {
+ if ( !g_pfwFrames[i].floating && g_pfwFrames[i].OwnerWindow != (HWND)0 && g_pfwFrames[i].OwnerWindow != (HWND)-2 && g_pfwFrames[i].visible && !g_pfwFrames[i].needhide )
+ {
+ HWND hwnd = g_pfwFrames[i].OwnerWindow;
+ SetParent(hwnd,parent);
+ }
+ }
+ return 0;
+}
+
+int CLUIFrames_OnShowHide( HWND hwnd, int mode )
+{
+ int i;
+ int prevFrameCount;
+ for (i=0;i < g_nFramesCount;i++) {
+ if ( !g_pfwFrames[i].floating && g_pfwFrames[i].OwnerWindow != (HWND)0 && g_pfwFrames[i].OwnerWindow != (HWND)-2)
+ {
+ {
+ //Try to avoid crash on exit due to unlock.
+ HWND owner = g_pfwFrames[i].OwnerWindow;
+ HWND Frmhwnd = g_pfwFrames[i].hWnd;
+ BOOL visible = g_pfwFrames[i].visible;
+ BOOL needhide = g_pfwFrames[i].needhide;
+ needhide |= (!g_pfwFrames[i].collapsed || g_pfwFrames[i].height == 0 );
+ prevFrameCount = g_nFramesCount;
+ ShowWindow(owner,(mode == SW_HIDE || !visible || needhide)?SW_HIDE:mode);
+ ShowWindow(Frmhwnd,(mode == SW_HIDE || !visible || needhide)?SW_HIDE:mode);
+ }
+
+ if (mode != SW_HIDE)
+ {
+ SetWindowPos(g_pfwFrames[i].OwnerWindow,HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+ if (db_get_b(NULL,"CList","OnDesktop",SETTING_ONDESKTOP_DEFAULT))
+ {
+ SetWindowPos(g_pfwFrames[i].OwnerWindow,HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+ SetWindowPos(g_pfwFrames[i].OwnerWindow,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
+ }
+ else SetWindowPos(g_pfwFrames[i].OwnerWindow, HWND_NOTOPMOST, 0, 0, 0, 0,SWP_NOACTIVATE|SWP_NOSIZE | SWP_NOMOVE);
+ }
+ }
+ }
+ if (mode != SW_HIDE) SetForegroundWindow(pcli->hwndContactList);
+ AniAva_RedrawAllAvatars(TRUE);
+ return 0;
+}
+static int RemoveItemFromList(int pos,FRAMEWND **lpFrames,int *FrameItemCount)
+{
+ memmove(&((*lpFrames)[pos]),&((*lpFrames)[pos+1]),sizeof(FRAMEWND)*(*FrameItemCount-pos-1));
+ (*FrameItemCount)--;
+ (*lpFrames) = (FRAMEWND*)realloc((*lpFrames),sizeof(FRAMEWND)*(*FrameItemCount));
+ return 0;
+}
+
+static int id2pos(int id)
+{
+ int i;
+ if (_fCluiFramesModuleNotStarted) return -1;
+ for (i=0;i < g_nFramesCount;i++)
+ if (g_pfwFrames[i].id == id) return(i);
+ return(-1);
+};
+
+static int btoint(BOOLEAN b)
+{
+ if (b) return 1;
+ return 0;
+}
+
+
+static FRAMEWND* FindFrameByWnd( HWND hwnd )
+{
+ int i;
+
+ if ( hwnd == NULL ) return( NULL );
+
+ for (i=0;i < g_nFramesCount;i++)
+ if ((g_pfwFrames[i].floating) && (g_pfwFrames[i].ContainerWnd == hwnd))
+ return(&g_pfwFrames[i]);
+
+ return( NULL);
+}
+
+
+int QueueAllFramesUpdating(BYTE queue)
+{
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if ( !g_CluiData.fLayered)
+ {
+ if (queue)
+ InvalidateRect(g_pfwFrames[i].hWnd,NULL,FALSE);
+ else
+ ValidateRect(g_pfwFrames[i].hWnd,NULL);
+ }
+ if (g_pfwFrames[i].PaintCallbackProc)
+ {
+ g_pfwFrames[i].bQueued = queue;
+ if (g_pfwFrames[i].UpdateRgn)
+ {
+ DeleteObject(g_pfwFrames[i].UpdateRgn);
+ }
+ g_pfwFrames[i].UpdateRgn = 0;
+ }
+
+ }
+ return queue;
+
+}
+int FindFrameID(HWND FrameHwnd)
+{
+ FRAMEWND * frm = NULL;
+ if (FrameHwnd == NULL ) return 0;
+ frm = FindFrameByItsHWND(FrameHwnd);
+ if (frm)
+ return frm->id;
+ else return 0;
+}
+FRAMEWND * FindFrameByItsHWND(HWND FrameHwnd)
+{
+ int i;
+ if ( FrameHwnd == NULL ) return( NULL );
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if (g_pfwFrames[i].hWnd == FrameHwnd){return(&g_pfwFrames[i]);};
+ };
+ return NULL;
+}
+
+static void DockThumbs( FRAMEWND *pThumbLeft, FRAMEWND *pThumbRight, BOOL bMoveLeft )
+{
+ if (( pThumbRight->dockOpt.hwndLeft == NULL ) && ( pThumbLeft->dockOpt.hwndRight == NULL ))
+ {
+ pThumbRight->dockOpt.hwndLeft = pThumbLeft->ContainerWnd;
+ pThumbLeft->dockOpt.hwndRight = pThumbRight->ContainerWnd;
+ }
+}
+
+
+static void UndockThumbs( FRAMEWND *pThumb1, FRAMEWND *pThumb2 )
+{
+ if (( pThumb1 == NULL ) || ( pThumb2 == NULL ))
+ {
+ return;
+ }
+
+ if ( pThumb1->dockOpt.hwndRight == pThumb2->ContainerWnd )
+ {
+ pThumb1->dockOpt.hwndRight = NULL;
+ }
+
+ if ( pThumb1->dockOpt.hwndLeft == pThumb2->ContainerWnd )
+ {
+ pThumb1->dockOpt.hwndLeft = NULL;
+ }
+
+ if ( pThumb2->dockOpt.hwndRight == pThumb1->ContainerWnd )
+ {
+ pThumb2->dockOpt.hwndRight = NULL;
+ }
+
+ if ( pThumb2->dockOpt.hwndLeft == pThumb1->ContainerWnd )
+ {
+ pThumb2->dockOpt.hwndLeft = NULL;
+ }
+}
+static void PositionThumb( FRAMEWND *pThumb, short nX, short nY )
+{
+ FRAMEWND *pCurThumb = &g_pfwFrames[0];
+ FRAMEWND *pDockThumb = pThumb;
+ FRAMEWND fakeMainWindow;
+ FRAMEWND fakeTaskBarWindow;
+ RECT rc;
+ RECT rcThumb;
+ RECT rcOld;
+ SIZE sizeScreen;
+ int nNewX;
+ int nNewY;
+ int nOffs = 10;
+ int nWidth;
+ int nHeight;
+ POINT pt;
+ RECT rcLeft;
+ RECT rcTop;
+ RECT rcRight;
+ RECT rcBottom;
+ BOOL bDocked;
+ BOOL bDockedLeft;
+ BOOL bDockedRight;
+ BOOL bLeading;
+ int frmidx = 0;
+
+ if ( pThumb == NULL ) return;
+
+ sizeScreen.cx = GetSystemMetrics( SM_CXSCREEN );
+ sizeScreen.cy = GetSystemMetrics( SM_CYSCREEN );
+
+ // Get thumb dimnsions
+ GetWindowRect( pThumb->ContainerWnd, &rcThumb );
+ nWidth = rcThumb.right - rcThumb.left;
+ nHeight = rcThumb.bottom - rcThumb.top;
+
+ // Docking to the edges of the screen
+ nNewX = nX < nOffs ? 0 : nX;
+ nNewX = nNewX > ( sizeScreen.cx - nWidth - nOffs ) ? ( sizeScreen.cx - nWidth ) : nNewX;
+ nNewY = nY < nOffs ? 0 : nY;
+ nNewY = nNewY > ( sizeScreen.cy - nHeight - nOffs ) ? ( sizeScreen.cy - nHeight ) : nNewY;
+
+ bLeading = pThumb->dockOpt.hwndRight != NULL;
+
+ if ( bMoveTogether )
+ {
+ UndockThumbs( pThumb, FindFrameByWnd( pThumb->dockOpt.hwndLeft ));
+ GetWindowRect( pThumb->ContainerWnd, &rcOld );
+ }
+
+ memset(&fakeMainWindow,0,sizeof(fakeMainWindow));
+ fakeMainWindow.ContainerWnd = pcli->hwndContactList;
+ fakeMainWindow.floating = TRUE;
+
+ memset(&fakeTaskBarWindow,0,sizeof(fakeTaskBarWindow));
+ fakeTaskBarWindow.ContainerWnd = hWndExplorerToolBar;
+ fakeTaskBarWindow.floating = TRUE;
+
+
+ while( pCurThumb != NULL )
+ {
+ if (pCurThumb->floating) {
+
+ if ( pCurThumb != pThumb )
+ {
+ GetWindowRect( pThumb->ContainerWnd, &rcThumb );
+ OffsetRect( &rcThumb, nX - rcThumb.left, nY - rcThumb.top );
+
+ GetWindowRect( pCurThumb->ContainerWnd, &rc );
+
+ // These are rects we will dock into
+
+ rcLeft.left = rc.left - nOffs;
+ rcLeft.top = rc.top - nOffs;
+ rcLeft.right = rc.left + nOffs;
+ rcLeft.bottom = rc.bottom + nOffs;
+
+ rcTop.left = rc.left - nOffs;
+ rcTop.top = rc.top - nOffs;
+ rcTop.right = rc.right + nOffs;
+ rcTop.bottom = rc.top + nOffs;
+
+ rcRight.left = rc.right - nOffs;
+ rcRight.top = rc.top - nOffs;
+ rcRight.right = rc.right + nOffs;
+ rcRight.bottom = rc.bottom + nOffs;
+
+ rcBottom.left = rc.left - nOffs;
+ rcBottom.top = rc.bottom - nOffs;
+ rcBottom.right = rc.right + nOffs;
+ rcBottom.bottom = rc.bottom + nOffs;
+
+
+ bDockedLeft = FALSE;
+ bDockedRight = FALSE;
+
+ // Upper-left
+ pt.x = rcThumb.left;
+ pt.y = rcThumb.top;
+ bDocked = FALSE;
+
+ if ( PtInRect( &rcRight, pt ))
+ {
+ nNewX = rc.right;
+ bDocked = TRUE;
+ }
+
+ if ( PtInRect( &rcBottom, pt ))
+ {
+ nNewY = rc.bottom;
+
+ if ( PtInRect( &rcLeft, pt ))
+ {
+ nNewX = rc.left;
+ }
+ }
+
+ if ( PtInRect( &rcTop, pt ))
+ {
+ nNewY = rc.top;
+ bDockedLeft = bDocked;
+ }
+
+ // Upper-right
+ pt.x = rcThumb.right;
+ pt.y = rcThumb.top;
+ bDocked = FALSE;
+
+ if ( !bLeading && PtInRect( &rcLeft, pt ))
+ {
+ if ( !bDockedLeft )
+ {
+ nNewX = rc.left - nWidth;
+ bDocked = TRUE;
+ }
+ else if ( rc.right == rcThumb.left )
+ {
+ bDocked = TRUE;
+ }
+ }
+
+
+ if ( PtInRect( &rcBottom, pt ))
+ {
+ nNewY = rc.bottom;
+
+ if ( PtInRect( &rcRight, pt ))
+ {
+ nNewX = rc.right - nWidth;
+ }
+ }
+
+ if ( !bLeading && PtInRect( &rcTop, pt ))
+ {
+ nNewY = rc.top;
+ bDockedRight = bDocked;
+ }
+
+ if ( bMoveTogether )
+ {
+ if ( bDockedRight )
+ {
+ DockThumbs( pThumb, pCurThumb, TRUE );
+ }
+
+ if ( bDockedLeft )
+ {
+ DockThumbs( pCurThumb, pThumb, FALSE );
+ }
+ }
+
+ // Lower-left
+ pt.x = rcThumb.left;
+ pt.y = rcThumb.bottom;
+
+ if ( PtInRect( &rcRight, pt ))
+ {
+ nNewX = rc.right;
+ }
+
+ if ( PtInRect( &rcTop, pt ))
+ {
+ nNewY = rc.top - nHeight;
+
+ if ( PtInRect( &rcLeft, pt ))
+ {
+ nNewX = rc.left;
+ }
+ }
+
+
+ // Lower-right
+ pt.x = rcThumb.right;
+ pt.y = rcThumb.bottom;
+
+ if ( !bLeading && PtInRect( &rcLeft, pt ))
+ {
+ nNewX = rc.left - nWidth;
+ }
+
+ if ( !bLeading && PtInRect( &rcTop, pt ))
+ {
+ nNewY = rc.top - nHeight;
+
+ if ( PtInRect( &rcRight, pt ))
+ {
+ nNewX = rc.right - nWidth;
+ }
+ }
+ }
+
+ };
+ frmidx++;
+ if (pCurThumb->ContainerWnd == fakeTaskBarWindow.ContainerWnd){break;};
+ if (pCurThumb->ContainerWnd == fakeMainWindow.ContainerWnd){
+ pCurThumb = &fakeTaskBarWindow;continue;};
+ if (frmidx == g_nFramesCount){
+ pCurThumb = &fakeMainWindow;continue;
+ }
+
+ pCurThumb = &g_pfwFrames[frmidx];
+
+
+
+ }
+
+ // Adjust coords once again
+ nNewX = nNewX < nOffs ? 0 : nNewX;
+ nNewX = nNewX > ( sizeScreen.cx - nWidth - nOffs ) ? ( sizeScreen.cx - nWidth ) : nNewX;
+ nNewY = nNewY < nOffs ? 0 : nNewY;
+ nNewY = nNewY > ( sizeScreen.cy - nHeight - nOffs ) ? ( sizeScreen.cy - nHeight ) : nNewY;
+
+
+ SetWindowPos( pThumb->ContainerWnd,
+ HWND_TOPMOST,
+ nNewX,
+ nNewY,
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOZORDER|SWP_NOACTIVATE );
+
+
+ // OK, move all g_CluiData.fDocked thumbs
+ if ( bMoveTogether )
+ {
+ pDockThumb = FindFrameByWnd( pDockThumb->dockOpt.hwndRight );
+
+ PositionThumb( pDockThumb, (short)( nNewX + nWidth ), (short)nNewY );
+ }
+}
+
+
+
+static void GetBorderSize(HWND hwnd,RECT *rect)
+{
+ RECT wr,cr;
+ POINT pt1,pt2;
+ // RECT r = {0};
+ // *rect = r;
+ // return;
+ GetWindowRect(hwnd,&wr);
+ GetClientRect(hwnd,&cr);
+ pt1.y = cr.top;pt1.x = cr.left;
+ pt2.y = cr.bottom;pt2.x = cr.right;
+
+ ClientToScreen(hwnd,&pt1);
+ ClientToScreen(hwnd,&pt2);
+
+ cr.top = pt1.y;cr.left = pt1.x;
+ cr.bottom = pt2.y;cr.right = pt2.x;
+
+ rect->top = cr.top-wr.top;
+ rect->left = cr.left-wr.left;
+ rect->right = wr.right-cr.right;
+ rect->bottom = wr.bottom-cr.bottom;
+ //if (rect->top+rect->bottom>10){rect->top = rect->bottom = 2;};
+ //if (rect->left+rect->right>10){rect->top = rect->bottom = 2;};
+
+};
+
+static char __inline *AS(char *str,const char *setting,char *addstr)
+{
+ if (str != NULL) {
+ strcpy(str,setting);
+ strcat(str,addstr);
+ }
+ return str;
+}
+
+static int DBLoadFrameSettingsAtPos(int pos,int Frameid)
+{
+ char sadd[15];
+ char buf[255];
+ // char *oldtb;
+
+ _itoa(pos,sadd,10);
+
+ //DBWriteContactSettingString(0,CLUIFrameModule,strcat("Name",sadd),Frames[Frameid].name);
+ //bool
+ g_pfwFrames[Frameid].collapsed = db_get_b(0,CLUIFrameModule,AS(buf,"Collapse",sadd),g_pfwFrames[Frameid].collapsed);
+
+ g_pfwFrames[Frameid].Locked = db_get_b(0,CLUIFrameModule,AS(buf,"Locked",sadd),g_pfwFrames[Frameid].Locked);
+ g_pfwFrames[Frameid].visible = db_get_b(0,CLUIFrameModule,AS(buf,"Visible",sadd),g_pfwFrames[Frameid].visible);
+ g_pfwFrames[Frameid].TitleBar.ShowTitleBar = db_get_b(0,CLUIFrameModule,AS(buf,"TBVisile",sadd),g_pfwFrames[Frameid].TitleBar.ShowTitleBar);
+
+ g_pfwFrames[Frameid].height = db_get_w(0,CLUIFrameModule,AS(buf,"Height",sadd),g_pfwFrames[Frameid].height);
+ g_pfwFrames[Frameid].HeightWhenCollapsed = db_get_w(0,CLUIFrameModule,AS(buf,"HeightCollapsed",sadd),0);
+ g_pfwFrames[Frameid].align = db_get_w(0,CLUIFrameModule,AS(buf,"Align",sadd),g_pfwFrames[Frameid].align);
+
+ g_pfwFrames[Frameid].FloatingPos.x = DBGetContactSettingRangedWord(0,CLUIFrameModule,AS(buf,"FloatX",sadd),100,0,2048);
+ g_pfwFrames[Frameid].FloatingPos.y = DBGetContactSettingRangedWord(0,CLUIFrameModule,AS(buf,"FloatY",sadd),100,0,2048);
+ g_pfwFrames[Frameid].FloatingSize.x = DBGetContactSettingRangedWord(0,CLUIFrameModule,AS(buf,"FloatW",sadd),100,0,2048);
+ g_pfwFrames[Frameid].FloatingSize.y = DBGetContactSettingRangedWord(0,CLUIFrameModule,AS(buf,"FloatH",sadd),100,0,2048);
+
+ g_pfwFrames[Frameid].floating = db_get_b(0,CLUIFrameModule,AS(buf,"Floating",sadd),0);
+ g_pfwFrames[Frameid].order = db_get_w(0,CLUIFrameModule,AS(buf,"Order",sadd),0);
+
+ g_pfwFrames[Frameid].UseBorder = db_get_b(0,CLUIFrameModule,AS(buf,"UseBorder",sadd),g_pfwFrames[Frameid].UseBorder);
+
+ return 0;
+}
+
+static int DBStoreFrameSettingsAtPos(int pos,int Frameid)
+{
+ char sadd[16];
+ char buf[255];
+
+ _itoa(pos,sadd,10);
+
+ db_set_ws(0,CLUIFrameModule,AS(buf,"Name",sadd),g_pfwFrames[Frameid].Name);
+ //bool
+ db_set_b(0,CLUIFrameModule,AS(buf,"Collapse",sadd),(BYTE)btoint(g_pfwFrames[Frameid].collapsed));
+ db_set_b(0,CLUIFrameModule,AS(buf,"Locked",sadd),(BYTE)btoint(g_pfwFrames[Frameid].Locked));
+ db_set_b(0,CLUIFrameModule,AS(buf,"Visible",sadd),(BYTE)btoint(g_pfwFrames[Frameid].visible));
+ db_set_b(0,CLUIFrameModule,AS(buf,"TBVisile",sadd),(BYTE)btoint(g_pfwFrames[Frameid].TitleBar.ShowTitleBar));
+
+ db_set_w(0,CLUIFrameModule,AS(buf,"Height",sadd),(WORD)g_pfwFrames[Frameid].height);
+ db_set_w(0,CLUIFrameModule,AS(buf,"HeightCollapsed",sadd),(WORD)g_pfwFrames[Frameid].HeightWhenCollapsed);
+ db_set_w(0,CLUIFrameModule,AS(buf,"Align",sadd),(WORD)g_pfwFrames[Frameid].align);
+ //FloatingPos
+ db_set_w(0,CLUIFrameModule,AS(buf,"FloatX",sadd),(WORD)g_pfwFrames[Frameid].FloatingPos.x);
+ db_set_w(0,CLUIFrameModule,AS(buf,"FloatY",sadd),(WORD)g_pfwFrames[Frameid].FloatingPos.y);
+ db_set_w(0,CLUIFrameModule,AS(buf,"FloatW",sadd),(WORD)g_pfwFrames[Frameid].FloatingSize.x);
+ db_set_w(0,CLUIFrameModule,AS(buf,"FloatH",sadd),(WORD)g_pfwFrames[Frameid].FloatingSize.y);
+
+ db_set_b(0,CLUIFrameModule,AS(buf,"Floating",sadd),(BYTE)btoint(g_pfwFrames[Frameid].floating));
+ db_set_b(0,CLUIFrameModule,AS(buf,"UseBorder",sadd),(BYTE)btoint(g_pfwFrames[Frameid].UseBorder));
+ db_set_w(0,CLUIFrameModule,AS(buf,"Order",sadd),(WORD)g_pfwFrames[Frameid].order);
+ return 0;
+}
+
+static int LocateStorePosition(int Frameid,int maxstored)
+{
+
+ if (g_pfwFrames[Frameid].Name == NULL)
+ return -1;
+ char settingname[255];
+ for ( int i=0;i < maxstored;i++)
+ {
+
+ mir_snprintf(settingname,SIZEOF(settingname),"Name%d",i);
+ DBVARIANT dbv = {0};
+ if ( DBGetContactSettingTString( NULL, CLUIFrameModule, settingname, &dbv ))
+ continue;
+
+ if ( lstrcmpi( dbv.ptszVal, g_pfwFrames[Frameid].Name ) == 0 )
+ {
+ db_free( &dbv );
+ return i;
+ }
+ db_free( &dbv );
+ }
+ return -1;
+}
+
+static int CLUIFramesLoadFrameSettings(int Frameid)
+{
+ int storpos,maxstored;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if (Frameid < 0 || Frameid >= g_nFramesCount) return -1;
+
+ maxstored = db_get_w(0,CLUIFrameModule,"StoredFrames",-1);
+ if (maxstored == -1) return 0;
+
+ storpos = LocateStorePosition(Frameid,maxstored);
+ if (storpos == -1) return 0;
+
+ DBLoadFrameSettingsAtPos(storpos,Frameid);
+ return 0;
+}
+
+static int CLUIFramesStoreFrameSettings(int Frameid)
+{
+ int maxstored,storpos;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if (Frameid < 0 || Frameid >= g_nFramesCount) return -1;
+
+ maxstored = db_get_w(0,CLUIFrameModule,"StoredFrames",-1);
+ if (maxstored == -1) maxstored = 0;
+
+ storpos = LocateStorePosition(Frameid,maxstored);
+ if (storpos == -1) {storpos = maxstored; maxstored++;}
+
+ DBStoreFrameSettingsAtPos(storpos,Frameid);
+ db_set_w(0,CLUIFrameModule,"StoredFrames",(WORD)maxstored);
+
+ return 0;
+}
+
+static int CLUIFramesStoreAllFrames()
+{
+ int i;
+ if (_fCluiFramesModuleNotStarted) return -1;
+ for (i=0;i < g_nFramesCount;i++)
+ CLUIFramesStoreFrameSettings(i);
+ return 0;
+}
+
+static int CLUIFramesGetalClientFrame(void)
+{
+ int i;
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if ( _nClientFrameId != eUnknownId ) {
+ /* this value could become invalid if RemoveItemFromList was called,
+ * so we double-check */
+ if (_nClientFrameId < g_nFramesCount) {
+ if (g_pfwFrames[_nClientFrameId].align == alClient) {
+ return _nClientFrameId;
+ }
+ }
+ }
+
+ for (i=0;i < g_nFramesCount;i++)
+ if (g_pfwFrames[i].align == alClient) {
+ _nClientFrameId = i;
+ return i;
+ }
+ return -1;
+}
+
+static HMENU CLUIFramesCreateMenuForFrame(int frameid,int root,int popuppos,HGENMENU (*pfnAdd)(CLISTMENUITEM*))
+{
+ //TMO_MenuItem tmi;
+ HGENMENU menuid;
+ int framepos = id2pos(frameid);
+
+ if (_fCluiFramesModuleNotStarted)
+ return NULL;
+
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Visible");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_CHECKED;
+ mi.pszContactOwner = (char *)0;
+ mi.pszService = MS_CLIST_FRAMES_SHFRAME;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiVisible = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIVisible = menuid;
+
+ popuppos += 100000;
+
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Show title");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_CHECKED;
+ mi.pszService = MS_CLIST_FRAMES_SHFRAMETITLEBAR;
+ mi.pszContactOwner = (char *)0;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiTBVisible = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MITBVisible = menuid;
+
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Locked");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_CHECKED;
+ mi.pszService = MS_CLIST_FRAMES_ULFRAME;
+ mi.pszContactOwner = (char *)0;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiLock = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MILock = menuid;
+
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Expanded");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_CHECKED;
+ mi.pszService = MS_CLIST_FRAMES_UCOLLFRAME;
+ mi.pszContactOwner = (char *)0;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiColl = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIColl = menuid;
+
+ //floating
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Floating Mode");
+ mi.flags = CMIF_CHILDPOPUP;
+ mi.pszService = "Set_Floating";
+ mi.pszContactOwner = (char *)0;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiFloating = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIFloating = menuid;
+
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Border");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_CHECKED;
+ mi.pszService = MS_CLIST_FRAMES_SETUNBORDER;
+ mi.pszContactOwner = (char *)0;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiBorder = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIBorder = menuid;
+
+ popuppos += 100000;
+
+ {
+ //alignment root
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Align");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_ROOTPOPUP;
+ mi.pszService = "";
+ mi.pszContactOwner = (char *)0;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiAlignRoot = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIAlignRoot = menuid;
+
+ mi.flags = CMIF_CHILDPOPUP;
+ //align top
+ mi.pszPopupName = (char *)menuid;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Top");
+ mi.pszService = CLUIFRAMESSETALIGNALTOP;
+ mi.pszContactOwner = (char *)alTop;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiAlignTop = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIAlignTop = menuid;
+
+
+ //align client
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Client");
+ mi.pszService = CLUIFRAMESSETALIGNALCLIENT;
+ mi.pszContactOwner = (char *)alClient;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiAlignClient = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIAlignClient = menuid;
+
+ //align bottom
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Bottom");
+ mi.pszService = CLUIFRAMESSETALIGNALBOTTOM;
+ mi.pszContactOwner = (char *)alBottom;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiAlignBottom = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIAlignBottom = menuid;
+
+ }
+
+ { //position
+ //position root
+ mi.pszPopupName = (char *)root;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Position");
+ mi.flags = CMIF_CHILDPOPUP|CMIF_ROOTPOPUP;
+ mi.pszService = "";
+ mi.pszContactOwner = (char *)0;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiPosRoot = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIPosRoot = menuid;
+ //??????
+ mi.pszPopupName = (char *)menuid;
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Up");
+ mi.flags = CMIF_CHILDPOPUP;
+ mi.pszService = CLUIFRAMESMOVEUP;
+ mi.pszContactOwner = (char *)1;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiPosUp = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIPosUp = menuid;
+
+ mi.popupPosition = frameid;
+ mi.position = popuppos++;
+ mi.pszName = LPGEN("&Down");
+ mi.flags = CMIF_CHILDPOPUP;
+ mi.pszService = CLUIFRAMESMOVEDOWN;
+ mi.pszContactOwner = (char *)-1;
+ menuid = pfnAdd(&mi);
+ if (frameid == -1) _hmiPosDown = menuid;
+ else g_pfwFrames[framepos].MenuHandles.MIPosDown = menuid;
+
+ }
+
+ return 0;
+}
+
+static int ModifyMItem(WPARAM wParam,LPARAM lParam)
+{
+ if ((int) wParam == -1 ) return 0; // FIXME
+
+ return ModifyMenuItemProxy(wParam,lParam);
+};
+
+
+static int CLUIFramesModifyContextMenuForFrame(WPARAM wParam,LPARAM lParam)
+{
+ int pos;
+ CLISTMENUITEM mi;
+ /* HOOK */
+ if (MirandaExiting()) return 0;
+ if (_fCluiFramesModuleNotStarted) return -1;
+ pos = id2pos(wParam);
+ if (pos >= 0 && pos < g_nFramesCount) {
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS|CMIM_NAME|CMIF_CHILDPOPUP|CMIF_TCHAR;
+ if (g_pfwFrames[pos].visible) mi.flags |= CMIF_CHECKED;
+ mi.ptszName = g_pfwFrames[pos].TitleBar.tbname ? g_pfwFrames[pos].TitleBar.tbname : g_pfwFrames[pos].Name;
+ ModifyMItem((WPARAM)_hmiVisible,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].Locked) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)_hmiLock,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].TitleBar.ShowTitleBar) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)_hmiTBVisible,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].floating) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)_hmiFloating,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if ( g_CluiData.fLayered ) mi.flags |= CMIF_GRAYED;
+ else if ((g_pfwFrames[pos].UseBorder)) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)_hmiBorder,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].align&alTop) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)_hmiAlignTop,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].align&alClient) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)_hmiAlignClient,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].align&alBottom) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)_hmiAlignBottom,(LPARAM)&mi);
+
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].collapsed) mi.flags |= CMIF_CHECKED;
+ if ((!g_pfwFrames[pos].visible) || (g_pfwFrames[pos].Locked) || (pos == CLUIFramesGetalClientFrame())) mi.flags |= CMIF_GRAYED;
+ ModifyMItem((WPARAM)_hmiColl,(LPARAM)&mi);
+ }
+ return 0;
+}
+
+static int CLUIFramesModifyMainMenuItems(WPARAM wParam,LPARAM lParam)
+{
+ //hiword(wParam) = frameid,loword(wParam) = flag
+ int pos;
+ CLISTMENUITEM mi;
+ //TMO_MenuItem tmi;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+
+ pos = id2pos(wParam);
+
+ if (pos >= 0 && pos < g_nFramesCount) {
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS|CMIM_NAME|CMIF_CHILDPOPUP|CMIF_TCHAR;
+ if (g_pfwFrames[pos].visible) mi.flags |= CMIF_CHECKED;
+ mi.ptszName = g_pfwFrames[pos].TitleBar.tbname ? g_pfwFrames[pos].TitleBar.tbname : g_pfwFrames[pos].Name;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MIVisible,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].Locked) mi.flags |= CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MILock,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].TitleBar.ShowTitleBar) mi.flags |= CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MITBVisible,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].floating) mi.flags |= CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MIFloating,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+
+ if ( g_CluiData.fLayered ) mi.flags |= CMIF_GRAYED;
+ else if ((g_pfwFrames[pos].UseBorder)) mi.flags |= CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MIBorder,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP|((g_pfwFrames[pos].align&alClient)?CMIF_GRAYED:0);
+ if (g_pfwFrames[pos].align&alTop) mi.flags |= CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MIAlignTop,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].align&alClient) mi.flags |= CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MIAlignClient,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP|((g_pfwFrames[pos].align&alClient)?CMIF_GRAYED:0);
+ if (g_pfwFrames[pos].align&alBottom) mi.flags |= CMIF_CHECKED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MIAlignBottom,(LPARAM)&mi);
+
+ /*
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP|((Frames[pos].align&alClient)?CMIF_GRAYED:0);
+ if (Frames[pos].align&alTop) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)contMIAlignTop,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP|CMIF_GRAYED;
+ if (Frames[pos].align&alClient) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)contMIAlignClient,(LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP|((Frames[pos].align&alClient)?CMIF_GRAYED:0);
+ if (Frames[pos].align&alBottom) mi.flags |= CMIF_CHECKED;
+ ModifyMItem((WPARAM)contMIAlignBottom,(LPARAM)&mi);
+
+ */
+
+
+
+ mi.flags = CMIM_FLAGS|CMIF_CHILDPOPUP;
+ if (g_pfwFrames[pos].collapsed) mi.flags |= CMIF_CHECKED;
+ if ((!g_pfwFrames[pos].visible) || g_pfwFrames[pos].Locked || (pos == CLUIFramesGetalClientFrame())) mi.flags |= CMIF_GRAYED;
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_pfwFrames[pos].MenuHandles.MIColl,(LPARAM)&mi);
+ }
+
+ return 0;
+}
+
+
+static INT_PTR _us_DoGetFrameOptions(WPARAM wParam,LPARAM lParam)
+{
+ int pos;
+ INT_PTR retval;
+ BOOL bUnicodeText = (LOWORD(wParam) & FO_UNICODETEXT) != 0;
+ wParam = MAKEWPARAM((LOWORD(wParam)) & ~FO_UNICODETEXT, HIWORD(wParam));
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+
+ pos = id2pos(HIWORD(wParam));
+ if (pos < 0 || pos >= g_nFramesCount) {
+
+ return -1;
+ }
+
+ switch(LOWORD(wParam))
+ {
+ case FO_FLAGS:
+ retval = 0;
+ if (g_pfwFrames[pos].visible) retval |= F_VISIBLE;
+ if ( !g_pfwFrames[pos].collapsed) retval |= F_UNCOLLAPSED;
+ if (g_pfwFrames[pos].Locked) retval |= F_LOCKED;
+ if (g_pfwFrames[pos].TitleBar.ShowTitleBar) retval |= F_SHOWTB;
+ if (g_pfwFrames[pos].TitleBar.ShowTitleBarTip) retval |= F_SHOWTBTIP;
+ if ( !g_CluiData.fLayered)
+ {
+ if ( !(GetWindowLongPtr(g_pfwFrames[pos].hWnd,GWL_STYLE)&WS_BORDER)) retval |= F_NOBORDER;
+ }
+ else
+ if ( !g_pfwFrames[pos].UseBorder) retval |= F_NOBORDER;
+
+
+ break;
+
+ case FO_NAME:
+ if (bUnicodeText)
+ retval = (INT_PTR)g_pfwFrames[pos].Name;
+ else
+ retval = (INT_PTR)g_pfwFrames[pos].szName;
+ break;
+
+ case FO_TBNAME:
+ if (bUnicodeText)
+ retval = (INT_PTR)g_pfwFrames[pos].TitleBar.tbname;
+ else
+ retval = (INT_PTR)g_pfwFrames[pos].TitleBar.sztbname;
+ break;
+
+ case FO_TBTIPNAME:
+ if (bUnicodeText)
+ retval = (INT_PTR)g_pfwFrames[pos].TitleBar.tooltip;
+ else
+ retval = (INT_PTR)g_pfwFrames[pos].TitleBar.sztooltip;
+ break;
+
+ case FO_TBSTYLE:
+ retval = GetWindowLongPtr(g_pfwFrames[pos].TitleBar.hwnd,GWL_STYLE);
+ break;
+
+ case FO_TBEXSTYLE:
+ retval = GetWindowLongPtr(g_pfwFrames[pos].TitleBar.hwnd,GWL_EXSTYLE);
+ break;
+
+ case FO_ICON:
+ retval = (INT_PTR)g_pfwFrames[pos].TitleBar.hicon;
+ break;
+
+ case FO_HEIGHT:
+ retval = (INT_PTR)g_pfwFrames[pos].height;
+ break;
+
+ case FO_ALIGN:
+ retval = (INT_PTR)g_pfwFrames[pos].align;
+ break;
+ case FO_FLOATING:
+ retval = (INT_PTR)g_pfwFrames[pos].floating;
+ break;
+ default:
+ retval = -1;
+ break;
+ }
+
+ return retval;
+}
+
+static int UpdateTBToolTip(int framepos)
+{
+ {
+ TOOLINFO ti;
+
+ ZeroMemory(&ti,sizeof(ti));
+ ti.cbSize = sizeof(ti);
+ ti.lpszText = g_pfwFrames[framepos].TitleBar.tooltip;
+ ti.hinst = g_hInst;
+ ti.uFlags = TTF_IDISHWND|TTF_SUBCLASS ;
+ ti.uId = (UINT_PTR)g_pfwFrames[framepos].TitleBar.hwnd;
+
+ return(SendMessage(g_pfwFrames[framepos].TitleBar.hwndTip,TTM_UPDATETIPTEXT ,(WPARAM)0,(LPARAM)&ti));
+ }
+
+};
+//hiword(wParam) = frameid,loword(wParam) = flag
+static int _us_DoSetFrameOptions(WPARAM wParam,LPARAM lParam)
+{
+ int pos;
+ int retval; // value to be returned
+ BOOL bUnicodeText = (LOWORD(wParam) & FO_UNICODETEXT) != 0;
+ wParam = MAKEWPARAM((LOWORD(wParam))& ~FO_UNICODETEXT, HIWORD(wParam));
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+
+ pos = id2pos(HIWORD(wParam));
+ if (pos < 0 || pos >= g_nFramesCount) {
+
+ return -1;
+ }
+
+ switch(LOWORD(wParam))
+ {
+ case FO_FLAGS:{
+ int flag = lParam;
+ int style;
+
+ g_pfwFrames[pos].dwFlags = flag;
+ g_pfwFrames[pos].visible = FALSE;
+ if (flag&F_VISIBLE) g_pfwFrames[pos].visible = TRUE;
+
+ g_pfwFrames[pos].collapsed = TRUE;
+ if (flag&F_UNCOLLAPSED) g_pfwFrames[pos].collapsed = FALSE;
+
+ g_pfwFrames[pos].Locked = FALSE;
+ if (flag&F_LOCKED) g_pfwFrames[pos].Locked = TRUE;
+
+ g_pfwFrames[pos].UseBorder = TRUE;
+ if (flag&F_NOBORDER) g_pfwFrames[pos].UseBorder = FALSE;
+
+ g_pfwFrames[pos].TitleBar.ShowTitleBar = FALSE;
+ if (flag&F_SHOWTB) g_pfwFrames[pos].TitleBar.ShowTitleBar = TRUE;
+
+ g_pfwFrames[pos].TitleBar.ShowTitleBarTip = FALSE;
+ if (flag&F_SHOWTBTIP) g_pfwFrames[pos].TitleBar.ShowTitleBarTip = TRUE;
+
+ SendMessageA(g_pfwFrames[pos].TitleBar.hwndTip,TTM_ACTIVATE,(WPARAM)g_pfwFrames[pos].TitleBar.ShowTitleBarTip,0);
+
+ style = (int)GetWindowLongPtr(g_pfwFrames[pos].hWnd,GWL_STYLE);
+ style &= (~WS_BORDER);
+
+ if ( !(flag&F_NOBORDER ) && !g_CluiData.fLayered ) style |= WS_BORDER;
+
+ SetWindowLongPtr(g_pfwFrames[pos].hWnd,GWL_STYLE,(long)style);
+ SetWindowLongPtr(g_pfwFrames[pos].TitleBar.hwnd,GWL_STYLE,(long)style& ~(WS_VSCROLL | WS_HSCROLL));
+
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ SetWindowPos(g_pfwFrames[pos].TitleBar.hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED|SWP_NOACTIVATE);
+ return 0;
+ }
+
+ case FO_NAME:
+ if (lParam == (LPARAM)NULL)
+ return -1;
+
+ mir_free(g_pfwFrames[pos].Name);
+ mir_free(g_pfwFrames[pos].szName);
+ if (bUnicodeText) {
+ g_pfwFrames[pos].Name = mir_tstrdup((LPTSTR)lParam);
+ g_pfwFrames[pos].szName = mir_t2a((LPTSTR)lParam);
+ }
+ else {
+ g_pfwFrames[pos].szName = mir_strdup((char*)lParam);
+ g_pfwFrames[pos].Name = mir_a2t((char *)lParam);
+ }
+ return 0;
+
+ case FO_TBNAME:
+ if (lParam == (LPARAM)NULL) { return(-1);}
+
+ mir_free(g_pfwFrames[pos].TitleBar.tbname);
+ mir_free(g_pfwFrames[pos].TitleBar.sztbname);
+ if (bUnicodeText) {
+ g_pfwFrames[pos].TitleBar.tbname = mir_tstrdup((LPTSTR)lParam);
+ g_pfwFrames[pos].TitleBar.sztbname = mir_t2a((LPTSTR)lParam);
+ }
+ else {
+ g_pfwFrames[pos].TitleBar.sztbname = mir_strdup((char*)lParam);
+ g_pfwFrames[pos].TitleBar.tbname = mir_a2t((char*)lParam);
+ }
+
+ if (g_pfwFrames[pos].floating && (g_pfwFrames[pos].TitleBar.tbname != NULL))
+ SetWindowText(g_pfwFrames[pos].ContainerWnd,g_pfwFrames[pos].TitleBar.tbname);
+ return 0;
+
+ case FO_TBTIPNAME:
+ if (lParam == (LPARAM)NULL) { return(-1);}
+ if (g_pfwFrames[pos].TitleBar.tooltip != NULL) mir_free_and_nil(g_pfwFrames[pos].TitleBar.tooltip);
+ if (g_pfwFrames[pos].TitleBar.sztooltip != NULL) mir_free_and_nil(g_pfwFrames[pos].TitleBar.sztooltip);
+ if (bUnicodeText)
+ {
+ g_pfwFrames[pos].TitleBar.tooltip = mir_tstrdup((LPTSTR)lParam);
+ g_pfwFrames[pos].TitleBar.sztooltip = mir_t2a((LPTSTR)lParam);
+ }
+ else
+ {
+ g_pfwFrames[pos].TitleBar.sztooltip = mir_strdup((char*)lParam);
+ g_pfwFrames[pos].TitleBar.tooltip = mir_a2t((char*)lParam);
+ }
+ UpdateTBToolTip(pos);
+
+ return 0;
+
+ case FO_TBSTYLE:
+ SetWindowLongPtr(g_pfwFrames[pos].TitleBar.hwnd,GWL_STYLE,lParam& ~(WS_VSCROLL | WS_HSCROLL));
+
+ return 0;
+
+ case FO_TBEXSTYLE:
+ SetWindowLongPtr(g_pfwFrames[pos].TitleBar.hwnd,GWL_EXSTYLE,lParam);
+
+ return 0;
+
+ case FO_ICON:
+ g_pfwFrames[pos].TitleBar.hicon = (HICON)lParam;
+
+ return 0;
+
+ case FO_HEIGHT:
+ if (lParam < 0) { return -1;}
+
+ if (g_pfwFrames[pos].collapsed)
+ {
+ int oldHeight = g_pfwFrames[pos].height;
+ retval = g_pfwFrames[pos].height;
+ g_pfwFrames[pos].height = lParam;
+ if ( !CLUIFramesFitInSize()) g_pfwFrames[pos].height = retval;
+ retval = g_pfwFrames[pos].height;
+ if (g_pfwFrames[pos].height != oldHeight)
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ }
+ else
+ {
+ retval = g_pfwFrames[pos].HeightWhenCollapsed;
+ g_pfwFrames[pos].HeightWhenCollapsed = lParam;
+ if ( !CLUIFramesFitInSize()) g_pfwFrames[pos].HeightWhenCollapsed = retval;
+ retval = g_pfwFrames[pos].HeightWhenCollapsed;
+
+ }
+ return retval;
+
+ case FO_FLOATING:
+ if (lParam < 0) { return -1;}
+
+ {
+ int id = g_pfwFrames[pos].id;
+ g_pfwFrames[pos].floating = !(lParam);
+
+
+ CLUIFrames_SetFrameFloat(id,1);//lparam = 1 use stored width and height
+ return(wParam);
+ }
+
+ case FO_ALIGN:
+ if ( !(lParam&alTop || lParam&alBottom || lParam&alClient))
+ {
+ TRACE("Wrong align option \r\n");
+ return (-1);
+ };
+
+ if ((lParam&alClient) && (CLUIFramesGetalClientFrame() >= 0)) { //only one alClient frame possible
+ _nClientFrameId = eUnknownId;//recalc it
+
+ return -1;
+ }
+ g_pfwFrames[pos].align = lParam;
+
+
+ return(0);
+ }
+
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ return -1;
+}
+
+//wparam = lparam = 0
+static int _us_DoShowAllFrames(WPARAM wParam,LPARAM lParam)
+{
+ int i;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ for (i=0;i < g_nFramesCount;i++)
+ g_pfwFrames[i].visible = TRUE;
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ return 0;
+}
+
+//wparam = lparam = 0
+static int _us_DoShowTitles(WPARAM wParam,LPARAM lParam)
+{
+ int i;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ for (i=0;i < g_nFramesCount;i++)
+ g_pfwFrames[i].TitleBar.ShowTitleBar = TRUE;
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ return 0;
+}
+
+//wparam = lparam = 0
+static int _us_DoHideTitles(WPARAM wParam,LPARAM lParam)
+{
+ int i;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ for (i=0;i < g_nFramesCount;i++)
+ g_pfwFrames[i].TitleBar.ShowTitleBar = FALSE;
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ return 0;
+}
+
+//wparam = frameid
+static int _us_DoShowHideFrame(WPARAM wParam,LPARAM lParam)
+{
+ int pos;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if (wParam == 0) {
+ pos = lParam;
+ } else {
+ pos = id2pos(wParam);
+ }
+ if (pos >= 0 && (int)pos < g_nFramesCount)
+ {
+ g_pfwFrames[pos].visible = !g_pfwFrames[pos].visible;
+ if (g_pfwFrames[pos].OwnerWindow != (HWND)-2)
+ {
+ if (g_pfwFrames[pos].OwnerWindow)
+ CLUI_ShowWindowMod(g_pfwFrames[pos].OwnerWindow,(g_pfwFrames[pos].visible && g_pfwFrames[pos].collapsed && IsWindowVisible(pcli->hwndContactList))?SW_SHOW/*NOACTIVATE*/:SW_HIDE);
+ else if (g_pfwFrames[pos].visible)
+ {
+ g_pfwFrames[pos].OwnerWindow = CreateSubContainerWindow(pcli->hwndContactList,g_pfwFrames[pos].FloatingPos.x,g_pfwFrames[pos].FloatingPos.y,10,10);
+ SetParent(g_pfwFrames[pos].hWnd,g_pfwFrames[pos].OwnerWindow);
+ CLUI_ShowWindowMod(g_pfwFrames[pos].OwnerWindow,(g_pfwFrames[pos].visible && g_pfwFrames[pos].collapsed && IsWindowVisible(pcli->hwndContactList))?SW_SHOW/*NOACTIVATE*/:SW_HIDE);
+ }
+ }
+ if (g_pfwFrames[pos].floating){CLUIFrameResizeFloatingFrame(pos);};
+
+ if ( !g_pfwFrames[pos].floating) CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ }
+ return 0;
+}
+
+//wparam = frameid
+static int _us_DoShowHideFrameTitle(WPARAM wParam,LPARAM lParam)
+{
+ int pos;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if (wParam == 0) {
+ pos = lParam;
+ } else {
+ pos = id2pos(wParam);
+ }
+ if (pos >= 0 && (int)pos < g_nFramesCount)
+ g_pfwFrames[pos].TitleBar.ShowTitleBar = !g_pfwFrames[pos].TitleBar.ShowTitleBar;
+ //if (Frames[pos].height>
+
+
+
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+
+
+ return 0;
+}
+
+//wparam = frameid
+//lparam = -1 up ,1 down
+static int _us_DoMoveFrame(WPARAM wParam,LPARAM lParam)
+{
+ int pos,i,curpos,curalign,v,tmpval;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ pos = id2pos(wParam);
+ if (pos >= 0 && (int)pos < g_nFramesCount) {
+ SortData *sd;
+ curpos = g_pfwFrames[pos].order;
+ curalign = g_pfwFrames[pos].align;
+ v = 0;
+ sd = (SortData*)malloc(sizeof(SortData)*g_nFramesCount);
+ memset(sd,0,sizeof(SortData)*g_nFramesCount);
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if (g_pfwFrames[i].floating || (!g_pfwFrames[i].visible) || (g_pfwFrames[i].align != curalign)){continue;};
+
+ sd[v].order = g_pfwFrames[i].order;
+ sd[v].realpos = i;
+ v++;
+ };
+ if (v == 0){return(0);};
+ qsort(sd,v,sizeof(SortData),sortfunc);
+ for (i=0;i < v;i++)
+ g_pfwFrames[sd[i].realpos].order = i+1; //to be sure that order is incremental
+ for (i=0;i < v;i++)
+ {
+ if (sd[i].realpos == pos)
+ {
+ if (lParam == -1)
+ {
+ if (i >= v-1) break;
+ tmpval = g_pfwFrames[sd[i+1].realpos].order;
+ g_pfwFrames[sd[i+1].realpos].order = g_pfwFrames[pos].order;
+ g_pfwFrames[pos].order = tmpval;
+ break;
+ };
+ if (lParam == +1)
+ {
+ if (i < 1) break;
+ tmpval = g_pfwFrames[sd[i-1].realpos].order;
+ g_pfwFrames[sd[i-1].realpos].order = g_pfwFrames[pos].order;
+ g_pfwFrames[pos].order = tmpval;
+ break;
+ };
+
+
+ };
+ };
+
+ if (sd != NULL){free(sd);};
+ CLUIFramesStoreFrameSettings(pos);
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,0);
+
+ }
+
+ return(0);
+};
+
+
+
+static int _us_DoMoveFrameUp(WPARAM wParam,LPARAM lParam)
+{
+ return CLUIFrames_MoveFrame(wParam,(LPARAM)+1);
+}
+static int _us_DoMoveFrameDown(WPARAM wParam,LPARAM lParam)
+{
+ return CLUIFrames_MoveFrame(wParam,(LPARAM)-1);
+}
+//wparam = frameid
+//lparam = alignment
+static int _us_DoSetFrameAlign(WPARAM wParam,LPARAM lParam)
+{
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ CLUIFrames_SetFrameOptions(MAKEWPARAM(FO_ALIGN,wParam),lParam);
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,0);
+ return(0);
+}
+static int _us_DoAlignFrameTop(WPARAM wParam,LPARAM lParam)
+{
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ return CLUIFrames_SetFrameAlign(wParam,alTop);
+}
+static int _us_DoAlignFrameBottom(WPARAM wParam,LPARAM lParam)
+{
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ return CLUIFrames_SetFrameAlign(wParam,alBottom);
+}
+static int _us_DoAlignFrameClient(WPARAM wParam,LPARAM lParam)
+{
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ return CLUIFrames_SetFrameAlign(wParam,alClient);
+}
+
+
+//wparam = frameid
+static int _us_DoLockFrame(WPARAM wParam,LPARAM lParam)
+{
+ int pos;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if (wParam == 0) {
+ pos = lParam;
+ } else {
+ pos = id2pos(wParam);
+ }
+ if (pos >= 0 && (int)pos < g_nFramesCount) {
+ g_pfwFrames[pos].Locked = !g_pfwFrames[pos].Locked;
+ CLUIFramesStoreFrameSettings(pos);
+ }
+
+ return 0;
+}
+
+//wparam = frameid
+static int _us_DoSetFrameBorder(WPARAM wParam,LPARAM lParam)
+{
+ RECT rc;
+ int FrameId,oldflags;
+ HWND hw;
+ int flt;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if (wParam == 0) {
+ FrameId = lParam;
+ } else {
+ FrameId = id2pos(wParam);
+ }
+ if (FrameId == -1){return(-1);};
+ flt =
+ oldflags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,wParam),0);
+ if (oldflags&F_NOBORDER)
+ {
+ oldflags &= (~F_NOBORDER);
+ }
+ else
+ {
+ oldflags |= F_NOBORDER;
+ };
+ hw = g_pfwFrames[FrameId].hWnd;
+ GetWindowRect(hw,&rc);
+
+
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,wParam),oldflags);
+ {
+ SetWindowPos(hw,0,0,0,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE|SWP_DRAWFRAME);
+ };
+ return(0);
+};
+//wparam = frameid
+static int _us_DoCollapseFrame(WPARAM wParam,LPARAM lParam)
+{
+ int FrameId;
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ if (wParam == 0) {
+ FrameId = lParam;
+ } else {
+ FrameId = id2pos(wParam);
+ }
+ if (FrameId >= 0 && FrameId < g_nFramesCount)
+ {
+ int oldHeight;
+
+ // do not collapse/uncollapse client/locked/invisible frames
+ if (g_pfwFrames[FrameId].align == alClient && !(g_pfwFrames[FrameId].Locked || (!g_pfwFrames[FrameId].visible) || g_pfwFrames[FrameId].floating))
+ {
+ RECT rc;
+ if (CallService(MS_CLIST_DOCKINGISDOCKED,0,0)) {return 0;};
+ if ( !g_CluiData.fDocked && g_CluiData.fAutoSize) {return 0;};
+ GetWindowRect(pcli->hwndContactList,&rc);
+
+ if (g_pfwFrames[FrameId].collapsed == TRUE) {
+ rc.bottom -= rc.top;
+ rc.bottom -= g_pfwFrames[FrameId].height;
+ g_pfwFrames[FrameId].HeightWhenCollapsed = g_pfwFrames[FrameId].height;
+ g_pfwFrames[FrameId].collapsed = FALSE;
+ }
+ else
+ {
+ rc.bottom -= rc.top;
+ rc.bottom += g_pfwFrames[FrameId].HeightWhenCollapsed;
+ g_pfwFrames[FrameId].collapsed = TRUE;
+ }
+
+ SetWindowPos(pcli->hwndContactList,NULL,0,0,rc.right-rc.left,rc.bottom,SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE);
+
+ CLUIFramesStoreAllFrames();
+
+
+ return 0;
+
+ }
+ if (g_pfwFrames[FrameId].Locked || (!g_pfwFrames[FrameId].visible)) return 0;
+
+ oldHeight = g_pfwFrames[FrameId].height;
+
+ // if collapsed, uncollapse
+ if (g_pfwFrames[FrameId].collapsed == TRUE) {
+ g_pfwFrames[FrameId].HeightWhenCollapsed = g_pfwFrames[FrameId].height;
+ g_pfwFrames[FrameId].height = UNCOLLAPSED_FRAME_SIZE;
+ g_pfwFrames[FrameId].collapsed = FALSE;
+ }
+ // if uncollapsed, collapse
+ else {
+ g_pfwFrames[FrameId].height = g_pfwFrames[FrameId].HeightWhenCollapsed;
+ g_pfwFrames[FrameId].collapsed = TRUE;
+ }
+
+ if ( !g_pfwFrames[FrameId].floating)
+ {
+
+ if ( !CLUIFramesFitInSize()) {
+ //cant collapse,we can resize only for height < alclient frame height
+ int alfrm = CLUIFramesGetalClientFrame();
+
+ if (alfrm != -1) {
+ g_pfwFrames[FrameId].collapsed = FALSE;
+ if (g_pfwFrames[alfrm].height>2*UNCOLLAPSED_FRAME_SIZE) {
+ oldHeight = g_pfwFrames[alfrm].height-UNCOLLAPSED_FRAME_SIZE;
+ g_pfwFrames[FrameId].collapsed = TRUE;
+ }
+ }else
+ {
+ int i,sumheight = 0;
+ for (i=0;i < g_nFramesCount;i++) {
+ if ((g_pfwFrames[i].align != alClient) && (!g_pfwFrames[i].floating) && (g_pfwFrames[i].visible) && (!g_pfwFrames[i].needhide)) {
+ sumheight += (g_pfwFrames[i].height)+(g_nTitleBarHeight*btoint(g_pfwFrames[i].TitleBar.ShowTitleBar))+2;
+ return FALSE;
+ }
+ if (sumheight>_nContactListHeight-0-2)
+ {
+ g_pfwFrames[FrameId].height = (_nContactListHeight-0-2)-sumheight;
+ }
+
+ }
+ }
+
+ g_pfwFrames[FrameId].height = oldHeight;
+
+ if (g_pfwFrames[FrameId].collapsed == FALSE) {
+
+ if ( !g_pfwFrames[FrameId].floating)
+ {
+ }
+ else
+ {
+ //SetWindowPos(Frames[FrameId].hWnd,HWND_TOP,0,0,Frames[FrameId].wndSize.right-Frames[FrameId].wndSize.left,Frames[FrameId].height,SWP_SHOWWINDOW|SWP_NOMOVE);
+ SetWindowPos(g_pfwFrames[FrameId].ContainerWnd,HWND_TOP,0,0,g_pfwFrames[FrameId].wndSize.right-g_pfwFrames[FrameId].wndSize.left+6,g_pfwFrames[FrameId].height+DEFAULT_TITLEBAR_HEIGHT+4,SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOMOVE);
+ };
+
+
+ return -1;};//redraw not needed
+ }
+ };//floating test
+
+ //CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,0);
+ if ( !g_pfwFrames[FrameId].floating)
+ {
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,0);
+ }
+ else
+ {
+ //SetWindowPos(Frames[FrameId].hWnd,HWND_TOP,0,0,Frames[FrameId].wndSize.right-Frames[FrameId].wndSize.left,Frames[FrameId].height,SWP_SHOWWINDOW|SWP_NOMOVE);
+ RECT contwnd;
+ GetWindowRect(g_pfwFrames[FrameId].ContainerWnd,&contwnd);
+ contwnd.top = contwnd.bottom-contwnd.top;//height
+ contwnd.left = contwnd.right-contwnd.left;//width
+
+ contwnd.top -= (oldHeight-g_pfwFrames[FrameId].height);//newheight
+ SetWindowPos(g_pfwFrames[FrameId].ContainerWnd,HWND_TOP,0,0,contwnd.left,contwnd.top,SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOMOVE);
+ };
+ CLUIFramesStoreAllFrames();
+ return(0);
+ }
+ else
+ return -1;
+}
+
+static int CLUIFramesLoadMainMenu()
+{
+ if (_fCluiFramesModuleNotStarted)
+ return -1;
+
+ if (_hmiRoot != (HGENMENU)-1) {
+ CallService(MS_CLIST_REMOVEMAINMENUITEM,(WPARAM)_hmiRoot,0);
+ _hmiRoot = (HGENMENU)-1;
+ }
+
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof(mi);
+ // create root menu
+ mi.flags = CMIF_ICONFROMICOLIB | CMIF_ROOTHANDLE;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_MIRANDA);
+ mi.position = 3000090000;
+ mi.pszName = LPGEN("Frames");
+ _hmiRoot = Menu_AddMainMenuItem(&mi);
+ DestroyIcon_protect(mi.hIcon);
+ // create frames menu
+ int separator = 3000200000;
+ for (int i=0; i < g_nFramesCount; i++) {
+ mi.hIcon = g_pfwFrames[i].TitleBar.hicon;
+ mi.flags = CMIF_ROOTHANDLE | CMIF_TCHAR;
+ mi.position = separator;
+ mi.hParentMenu = _hmiRoot;
+ mi.ptszName = g_pfwFrames[i].TitleBar.tbname ? g_pfwFrames[i].TitleBar.tbname : g_pfwFrames[i].Name;
+ mi.pszService = 0;
+ g_pfwFrames[i].MenuHandles.MainMenuItem = Menu_AddMainMenuItem(&mi);
+ CLUIFramesCreateMenuForFrame(g_pfwFrames[i].id,(int)g_pfwFrames[i].MenuHandles.MainMenuItem,separator,Menu_AddMainMenuItem);
+ CLUIFramesModifyMainMenuItems(g_pfwFrames[i].id,0);
+ CallService(MS_CLIST_FRAMEMENUNOTIFY,(WPARAM)g_pfwFrames[i].id,(LPARAM)g_pfwFrames[i].MenuHandles.MainMenuItem);
+ separator++;
+ }
+
+ separator += 100000;
+
+ // create "show all frames" menu
+ mi.hIcon = NULL;
+ mi.flags = CMIF_ROOTHANDLE;
+ mi.position = separator++;
+ mi.hParentMenu = _hmiRoot;
+ mi.pszName = LPGEN("Show All Frames");
+ mi.pszService = MS_CLIST_FRAMES_SHOWALLFRAMES;
+ Menu_AddMainMenuItem(&mi);
+
+ // create "show all titlebars" menu
+ mi.position = separator++;
+ mi.pszName = LPGEN("Show All Titlebars");
+ mi.pszService = MS_CLIST_FRAMES_SHOWALLFRAMESTB;
+ Menu_AddMainMenuItem(&mi);
+
+ // create "hide all titlebars" menu
+ mi.position = separator++;
+ mi.pszName = LPGEN("Hide All Titlebars");
+ mi.pszService = MS_CLIST_FRAMES_HIDEALLFRAMESTB;
+ Menu_AddMainMenuItem(&mi);
+ return 0;
+}
+
+static HFONT CLUILoadTitleBarFont()
+{
+ char facename[] = "MS Shell Dlg";
+ HFONT hfont;
+ LOGFONTA logfont;
+ memset(&logfont,0,sizeof(logfont));
+ memmove(logfont.lfFaceName,facename,sizeof(facename));
+ logfont.lfWeight = FW_NORMAL;
+ logfont.lfHeight = -10;
+ logfont.lfCharSet = DEFAULT_CHARSET;
+ hfont = CreateFontIndirectA(&logfont);
+ return hfont;
+}
+
+
+//wparam = (CLISTFrame*)clfrm
+static int _us_DoAddFrame(WPARAM wParam,LPARAM lParam)
+{
+ int style,retval;
+ //char * CustomName = NULL;
+ CLISTFrame *clfrm = (CLISTFrame *)wParam;
+
+ if (pcli->hwndContactList == 0) return -1;
+ if (_fCluiFramesModuleNotStarted) return -1;
+ if (clfrm->cbSize != sizeof(CLISTFrame)) return -1;
+ if ( !(_hTitleBarFont)) _hTitleBarFont = CLUILoadTitleBarFont();
+
+ g_pfwFrames = (FRAMEWND*)realloc(g_pfwFrames,sizeof(FRAMEWND)*(g_nFramesCount+1));
+
+ memset(&g_pfwFrames[g_nFramesCount],0,sizeof(FRAMEWND));
+ g_pfwFrames[g_nFramesCount].id = _iNextFrameId++;
+ g_pfwFrames[g_nFramesCount].align = clfrm->align;
+ g_pfwFrames[g_nFramesCount].hWnd = clfrm->hWnd;
+ g_pfwFrames[g_nFramesCount].height = clfrm->height;
+ g_pfwFrames[g_nFramesCount].TitleBar.hicon = clfrm->hIcon;
+ //Frames[nFramescount].TitleBar.BackColour;
+ g_pfwFrames[g_nFramesCount].floating = FALSE;
+ if (clfrm->Flags&F_NO_SUBCONTAINER || !g_CluiData.fLayered)
+ g_pfwFrames[g_nFramesCount].OwnerWindow = (HWND)-2;
+ else g_pfwFrames[g_nFramesCount].OwnerWindow = 0;
+
+ //override tbbtip
+ //clfrm->Flags |= F_SHOWTBTIP;
+ //
+ if (db_get_b(0,CLUIFrameModule,"RemoveAllBorders",0) == 1)
+ {
+ clfrm->Flags |= F_NOBORDER;
+ };
+ g_pfwFrames[g_nFramesCount].dwFlags = clfrm->Flags;
+
+ if (clfrm->name == NULL || ((clfrm->Flags&F_UNICODE) ? lstrlenW(clfrm->wname) : lstrlenA(clfrm->name)) == 0) {
+ g_pfwFrames[g_nFramesCount].Name = (LPTSTR)mir_alloc(255 * sizeof(TCHAR));
+ GetClassName(g_pfwFrames[g_nFramesCount].hWnd,g_pfwFrames[g_nFramesCount].Name,255);
+ }
+ else
+ {
+ g_pfwFrames[g_nFramesCount].Name = (clfrm->Flags&F_UNICODE) ? mir_u2t(clfrm->wname) : mir_a2t(clfrm->name);
+ }
+ g_pfwFrames[g_nFramesCount].szName = mir_t2a(g_pfwFrames[g_nFramesCount].Name);
+ if (IsBadCodePtr((FARPROC)clfrm->TBname) || clfrm->TBname == NULL
+ || ((clfrm->Flags&F_UNICODE) ? lstrlenW(clfrm->TBwname) : lstrlenA(clfrm->TBname)) == 0)
+ g_pfwFrames[g_nFramesCount].TitleBar.tbname = mir_tstrdup(g_pfwFrames[g_nFramesCount].Name);
+ else
+ g_pfwFrames[g_nFramesCount].TitleBar.tbname = (clfrm->Flags&F_UNICODE) ? mir_u2t(clfrm->TBwname) : mir_a2t(clfrm->TBname);
+ g_pfwFrames[g_nFramesCount].TitleBar.sztbname = mir_t2a(g_pfwFrames[g_nFramesCount].TitleBar.tbname);
+ g_pfwFrames[g_nFramesCount].needhide = FALSE;
+ g_pfwFrames[g_nFramesCount].TitleBar.ShowTitleBar = (clfrm->Flags&F_SHOWTB?TRUE:FALSE);
+ g_pfwFrames[g_nFramesCount].TitleBar.ShowTitleBarTip = (clfrm->Flags&F_SHOWTBTIP?TRUE:FALSE);
+
+ g_pfwFrames[g_nFramesCount].collapsed = (clfrm->Flags&F_UNCOLLAPSED)?FALSE:TRUE;
+
+
+ g_pfwFrames[g_nFramesCount].Locked = clfrm->Flags&F_LOCKED?TRUE:FALSE;
+ g_pfwFrames[g_nFramesCount].visible = clfrm->Flags&F_VISIBLE?TRUE:FALSE;
+
+ g_pfwFrames[g_nFramesCount].UseBorder = ((clfrm->Flags&F_NOBORDER) || g_CluiData.fLayered)?FALSE:TRUE;
+
+ //Frames[nFramescount].OwnerWindow = 0;
+
+
+
+ g_pfwFrames[g_nFramesCount].TitleBar.hwnd
+ = CreateWindow(CLUIFrameTitleBarClassName,g_pfwFrames[g_nFramesCount].Name,
+ (db_get_b(0,CLUIFrameModule,"RemoveAllTitleBarBorders",1)?0:WS_BORDER)
+
+ |WS_CHILD|WS_CLIPCHILDREN|
+ (g_pfwFrames[g_nFramesCount].TitleBar.ShowTitleBar?WS_VISIBLE:0)|
+ WS_CLIPCHILDREN,
+ 0,0,0,0,pcli->hwndContactList,NULL,g_hInst,NULL);
+ SetWindowLongPtr(g_pfwFrames[g_nFramesCount].TitleBar.hwnd,GWLP_USERDATA,g_pfwFrames[g_nFramesCount].id);
+
+
+ g_pfwFrames[g_nFramesCount].TitleBar.hwndTip
+ = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL,
+ WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ pcli->hwndContactList, NULL, g_hInst,
+ NULL);
+
+ SetWindowPos(g_pfwFrames[g_nFramesCount].TitleBar.hwndTip, HWND_TOPMOST,0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ {
+ TOOLINFOA ti;
+ int res;
+
+ ZeroMemory(&ti,sizeof(ti));
+ ti.cbSize = sizeof(ti);
+ ti.lpszText = "";
+ ti.hinst = g_hInst;
+ ti.uFlags = TTF_IDISHWND|TTF_SUBCLASS ;
+ ti.uId = (UINT_PTR)g_pfwFrames[g_nFramesCount].TitleBar.hwnd;
+ res = SendMessageA(g_pfwFrames[g_nFramesCount].TitleBar.hwndTip,TTM_ADDTOOL,(WPARAM)0,(LPARAM)&ti);
+ }
+
+ SendMessageA(g_pfwFrames[g_nFramesCount].TitleBar.hwndTip,TTM_ACTIVATE,(WPARAM)g_pfwFrames[g_nFramesCount].TitleBar.ShowTitleBarTip,0);
+
+ g_pfwFrames[g_nFramesCount].oldstyles = GetWindowLongPtr(g_pfwFrames[g_nFramesCount].hWnd,GWL_STYLE);
+ g_pfwFrames[g_nFramesCount].TitleBar.oldstyles = GetWindowLongPtr(g_pfwFrames[g_nFramesCount].TitleBar.hwnd,GWL_STYLE);
+ //Frames[nFramescount].FloatingPos.x =
+
+ retval = g_pfwFrames[g_nFramesCount].id;
+ g_pfwFrames[g_nFramesCount].order = g_nFramesCount+1;
+ g_nFramesCount++;
+
+
+ CLUIFramesLoadFrameSettings(id2pos(retval));
+ if (g_pfwFrames[g_nFramesCount-1].collapsed == FALSE)
+ {
+ g_pfwFrames[g_nFramesCount-1].height = 0;
+ }
+
+ // create frame
+
+
+ // else Frames[nFramescount-1].height = Frames[nFramescount-1].HeightWhenCollapsed;
+
+ style = GetWindowLongPtr(g_pfwFrames[g_nFramesCount-1].hWnd,GWL_STYLE);
+ style &= (~WS_BORDER);
+ style |= (((g_pfwFrames[g_nFramesCount-1].UseBorder) && !g_CluiData.fLayered)?WS_BORDER:0);
+ SetWindowLongPtr(g_pfwFrames[g_nFramesCount-1].hWnd,GWL_STYLE,style);
+ SetWindowLongPtr(g_pfwFrames[g_nFramesCount-1].TitleBar.hwnd,GWL_STYLE,style& ~(WS_VSCROLL | WS_HSCROLL));
+ SetWindowLongPtr(g_pfwFrames[g_nFramesCount-1].TitleBar.hwnd,GWL_STYLE,GetWindowLongPtr(g_pfwFrames[g_nFramesCount-1].TitleBar.hwnd,GWL_STYLE)&~(WS_VSCROLL|WS_HSCROLL));
+
+ if (g_pfwFrames[g_nFramesCount-1].order == 0){g_pfwFrames[g_nFramesCount-1].order = g_nFramesCount;};
+
+
+ //need to enlarge parent
+ {
+ RECT mainRect;
+ int mainHeight, minHeight;
+ GetWindowRect(pcli->hwndContactList,&mainRect);
+ mainHeight = mainRect.bottom-mainRect.top;
+ minHeight = CLUIFrames_GetTotalHeight();
+ if (mainHeight < minHeight)
+ {
+ BOOL Upward = FALSE;
+ Upward = !g_CluiData.fDocked && g_CluiData.fAutoSize && db_get_b(NULL,"CLUI","AutoSizeUpward",SETTING_AUTOSIZEUPWARD_DEFAULT);
+
+ if (Upward)
+ mainRect.top = mainRect.bottom-minHeight;
+ else
+ mainRect.bottom = mainRect.top+minHeight;
+ SetWindowPos(pcli->hwndContactList,NULL,mainRect.left,mainRect.top,mainRect.right-mainRect.left, mainRect.bottom-mainRect.top, SWP_NOZORDER|SWP_NOREDRAW|SWP_NOACTIVATE|SWP_NOSENDCHANGING);
+ }
+ GetWindowRect(pcli->hwndContactList,&mainRect);
+ mainHeight = mainRect.bottom-mainRect.top;
+ //if (mainHeight < minHeight)
+ // DebugBreak();
+ }
+ _nClientFrameId = eUnknownId;//recalc it
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,0);
+
+ if (g_pfwFrames[g_nFramesCount-1].floating)
+ {
+
+ g_pfwFrames[g_nFramesCount-1].floating = FALSE;
+ //SetWindowPos(Frames[nFramescount-1].hw
+ CLUIFrames_SetFrameFloat(retval,1);//lparam = 1 use stored width and height
+ }
+ else
+ CLUIFrames_SetFrameFloat(retval,2);
+
+ /** Remove */
+ //_ExtFramesSrv_AddFrame( wParam, lParam);
+
+ return retval;
+}
+
+static int _us_DoRemoveFrame(WPARAM wParam,LPARAM lParam)
+{
+ int pos;
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ pos = id2pos(wParam);
+
+ if (pos < 0 || pos>g_nFramesCount){return(-1);};
+
+ mir_free_and_nil(g_pfwFrames[pos].Name);
+ mir_free_and_nil(g_pfwFrames[pos].szName);
+ mir_free_and_nil(g_pfwFrames[pos].TitleBar.tbname);
+ mir_free_and_nil(g_pfwFrames[pos].TitleBar.sztbname);
+ mir_free_and_nil(g_pfwFrames[pos].TitleBar.tooltip);
+ mir_free_and_nil(g_pfwFrames[pos].TitleBar.sztooltip);
+ DestroyWindow(g_pfwFrames[pos].hWnd);
+ g_pfwFrames[pos].hWnd = (HWND)-1;
+ DestroyWindow(g_pfwFrames[pos].TitleBar.hwnd);
+ if (g_pfwFrames[pos].TitleBar.hwndTip)
+ DestroyWindow(g_pfwFrames[pos].TitleBar.hwndTip);
+ g_pfwFrames[pos].TitleBar.hwnd = (HWND)-1;
+ if (g_pfwFrames[pos].ContainerWnd && g_pfwFrames[pos].ContainerWnd != (HWND)-1) DestroyWindow(g_pfwFrames[pos].ContainerWnd);
+ g_pfwFrames[pos].ContainerWnd = (HWND)-1;
+ if (g_pfwFrames[pos].TitleBar.hmenu) DestroyMenu(g_pfwFrames[pos].TitleBar.hmenu);
+ g_pfwFrames[pos].PaintCallbackProc = NULL;
+ if (g_pfwFrames[pos].UpdateRgn) DeleteObject(g_pfwFrames[pos].UpdateRgn);
+
+ if (g_pfwFrames[pos].OwnerWindow != (HWND)-1
+ && g_pfwFrames[pos].OwnerWindow != (HWND)-2
+ && g_pfwFrames[pos].OwnerWindow != (HWND)0)
+ DestroyWindow(g_pfwFrames[pos].OwnerWindow);
+
+ g_pfwFrames[pos].OwnerWindow = NULL;
+ RemoveItemFromList(pos,&g_pfwFrames,&g_nFramesCount);
+
+ CLUI__cliInvalidateRect(pcli->hwndContactList,NULL,TRUE);
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,0);
+ CLUI__cliInvalidateRect(pcli->hwndContactList,NULL,TRUE);
+
+ return(0);
+};
+
+
+static int CLUIFramesForceUpdateTB(const FRAMEWND *Frame)
+{
+ if (Frame->TitleBar.hwnd != 0) RedrawWindow(Frame->TitleBar.hwnd,NULL,NULL,RDW_ALLCHILDREN|RDW_UPDATENOW|RDW_ERASE|RDW_INVALIDATE|RDW_FRAME);
+ //UpdateWindow(Frame->TitleBar.hwnd);
+ return 0;
+}
+
+static int CLUIFramesForceUpdateFrame(const FRAMEWND *Frame)
+{
+ if (Frame->hWnd != 0)
+ {
+ RedrawWindow(Frame->hWnd,NULL,NULL,RDW_UPDATENOW|RDW_FRAME|RDW_ERASE|RDW_INVALIDATE);
+ UpdateWindow(Frame->hWnd);
+ };
+ if (Frame->floating)
+ {
+ if (Frame->ContainerWnd != 0) RedrawWindow(Frame->ContainerWnd,NULL,NULL,RDW_UPDATENOW|RDW_ALLCHILDREN|RDW_ERASE|RDW_INVALIDATE|RDW_FRAME);
+ //UpdateWindow(Frame->ContainerWnd);
+ };
+ return 0;
+}
+
+static int CLUIFrameMoveResize(const FRAMEWND *Frame)
+{
+ // we need to show or hide the frame?
+ if (Frame->visible && (!Frame->needhide)) {
+ if (Frame->OwnerWindow != (HWND)-2 && Frame->OwnerWindow)
+ {
+ // CLUI_ShowWindowMod(Frame->OwnerWindow,SW_SHOW);
+ }
+ CLUI_ShowWindowMod(Frame->hWnd,SW_SHOW/*NOACTIVATE*/);
+ CLUI_ShowWindowMod(Frame->TitleBar.hwnd,Frame->TitleBar.ShowTitleBar == TRUE?SW_SHOW/*NOACTIVATE*/:SW_HIDE);
+ }
+ else {
+ if (Frame->OwnerWindow && Frame->OwnerWindow != (HWND)(-1) && Frame->OwnerWindow != (HWND)(-2))
+ {
+ CLUI_ShowWindowMod(Frame->OwnerWindow,SW_HIDE);
+ }
+ CLUI_ShowWindowMod(Frame->hWnd,SW_HIDE);
+ CLUI_ShowWindowMod(Frame->TitleBar.hwnd,SW_HIDE);
+ return(0);
+ }
+
+ if (Frame->OwnerWindow && Frame->OwnerWindow != (HWND)-2 )
+ {
+ RECT pr;
+ POINT Off = {0};
+
+ ClientToScreen(pcli->hwndContactList,&Off);
+ GetWindowRect(pcli->hwndContactList,&pr);
+
+ if ( Frame->visible && (!Frame->collapsed || Frame->wndSize.bottom-Frame->wndSize.top == 0))
+ {
+ ShowWindowAsync( Frame->OwnerWindow, SW_HIDE );
+ ShowWindowAsync( Frame->hWnd, SW_HIDE );
+ }
+
+ {
+ SetWindowPos(Frame->OwnerWindow,NULL,Frame->wndSize.left+Off.x,Frame->wndSize.top+Off.y,
+ Frame->wndSize.right-Frame->wndSize.left,
+ Frame->wndSize.bottom-Frame->wndSize.top,SWP_NOZORDER|SWP_NOACTIVATE ); //- -= -=
+
+ SetWindowPos(Frame->hWnd,NULL,0,0,
+ Frame->wndSize.right-Frame->wndSize.left,
+ Frame->wndSize.bottom-Frame->wndSize.top,SWP_NOZORDER|SWP_NOACTIVATE);
+ }
+ // set titlebar position
+ if (Frame->TitleBar.ShowTitleBar) {
+ SetWindowPos(Frame->TitleBar.hwnd,NULL,Frame->wndSize.left,Frame->wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar,
+ Frame->wndSize.right-Frame->wndSize.left,
+ g_nTitleBarHeight,SWP_NOZORDER|SWP_NOACTIVATE );
+ }
+ if ( Frame->visible && IsWindowVisible( pcli->hwndContactList ) && Frame->collapsed && Frame->wndSize.bottom-Frame->wndSize.top != 0 )
+ {
+ ShowWindow( Frame->OwnerWindow, SW_SHOW );
+ ShowWindow( Frame->hWnd, SW_SHOW );
+ }
+
+ }
+ else
+ {
+ // set frame position
+ SetWindowPos(Frame->hWnd,NULL,Frame->wndSize.left,Frame->wndSize.top,
+ Frame->wndSize.right-Frame->wndSize.left,
+ Frame->wndSize.bottom-Frame->wndSize.top,SWP_NOZORDER|SWP_NOACTIVATE);
+ // set titlebar position
+ if (Frame->TitleBar.ShowTitleBar) {
+ SetWindowPos(Frame->TitleBar.hwnd,NULL,Frame->wndSize.left,Frame->wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar,
+ Frame->wndSize.right-Frame->wndSize.left,
+ g_nTitleBarHeight,SWP_NOZORDER|SWP_NOACTIVATE);
+
+ }
+ }
+ // Sleep(0);
+ return 0;
+}
+
+static BOOL CLUIFramesFitInSize(void)
+{
+ int i;
+ int sumheight = 0;
+ int tbh = 0; // title bar height
+ int clientfrm;
+ clientfrm = CLUIFramesGetalClientFrame();
+ if (clientfrm != -1)
+ tbh = g_nTitleBarHeight*btoint(g_pfwFrames[clientfrm].TitleBar.ShowTitleBar);
+
+ for (i=0;i < g_nFramesCount;i++) {
+ if ((g_pfwFrames[i].align != alClient) && (!g_pfwFrames[i].floating) && (g_pfwFrames[i].visible) && (!g_pfwFrames[i].needhide)) {
+ sumheight += (g_pfwFrames[i].height)+(g_nTitleBarHeight*btoint(g_pfwFrames[i].TitleBar.ShowTitleBar))+2/*+btoint(Frames[i].UseBorder)*2*/;
+ if (sumheight>_nContactListHeight-tbh-2)
+ {
+ if ( !g_CluiData.fDocked && g_CluiData.fAutoSize)
+ {
+ return TRUE; //Can be required to enlarge
+ }
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+int CLUIFrames_GetTotalHeight()
+{
+ int i;
+ int sumheight = 0;
+ RECT border;
+ if (pcli->hwndContactList == NULL) return 0;
+
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if ((g_pfwFrames[i].visible) && (!g_pfwFrames[i].needhide) && (!g_pfwFrames[i].floating) && (pcli->hwndContactTree) && (g_pfwFrames[i].hWnd != pcli->hwndContactTree))
+ sumheight += (g_pfwFrames[i].height)+(g_nTitleBarHeight*btoint(g_pfwFrames[i].TitleBar.ShowTitleBar));
+ };
+
+ GetBorderSize(pcli->hwndContactList,&border);
+
+ //GetWindowRect(pcli->hwndContactList,&winrect);
+ //GetClientRect(pcli->hwndContactList,&clirect);
+ // clirect.bottom -= clirect.top;
+ // clirect.bottom += border.top+border.bottom;
+ //allbord = (winrect.bottom-winrect.top)-(clirect.bottom-clirect.top);
+
+ //TODO minsize
+ sumheight += g_CluiData.TopClientMargin;
+ sumheight += g_CluiData.BottomClientMargin;
+ return max(db_get_w(NULL,"CLUI","MinHeight",SETTING_MINHEIGTH_DEFAULT),
+ (sumheight+border.top+border.bottom));
+}
+
+int CLUIFramesGetMinHeight()
+{
+ int i,tbh,clientfrm,sumheight = 0;
+ RECT border;
+ int allbord = 0;
+ if (pcli->hwndContactList == NULL) return 0;
+
+
+ // search for alClient frame and get the titlebar's height
+ tbh = 0;
+ clientfrm = CLUIFramesGetalClientFrame();
+ if (clientfrm != -1)
+ tbh = g_nTitleBarHeight*btoint(g_pfwFrames[clientfrm].TitleBar.ShowTitleBar);
+
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if ((g_pfwFrames[i].align != alClient) && (g_pfwFrames[i].visible) && (!g_pfwFrames[i].needhide) && (!g_pfwFrames[i].floating))
+ {
+ RECT wsize;
+
+ GetWindowRect(g_pfwFrames[i].hWnd,&wsize);
+ sumheight += (wsize.bottom-wsize.top)+(g_nTitleBarHeight*btoint(g_pfwFrames[i].TitleBar.ShowTitleBar));
+ }
+ };
+
+ GetBorderSize(pcli->hwndContactList,&border);
+
+ //GetWindowRect(pcli->hwndContactList,&winrect);
+ //GetClientRect(pcli->hwndContactList,&clirect);
+ // clirect.bottom -= clirect.top;
+ // clirect.bottom += border.top+border.bottom;
+ //allbord = (winrect.bottom-winrect.top)-(clirect.bottom-clirect.top);
+
+ //TODO minsize
+ sumheight += g_CluiData.TopClientMargin;
+ sumheight += g_CluiData.BottomClientMargin;
+ return max(db_get_w(NULL,"CLUI","MinHeight",SETTING_MINHEIGTH_DEFAULT),
+ (sumheight+border.top+border.bottom+allbord+tbh) );
+}
+
+
+
+
+static int CLUIFramesResizeFrames(const RECT newsize)
+{
+ int sumheight = 9999999,newheight;
+ int prevframe,prevframebottomline;
+ int tbh,curfrmtbh;
+ int drawitems;
+ int clientfrm;
+ int i,j;
+ int sepw = GapBetweenFrames;
+ int topBorder = newsize.top;
+ int minHeight = CLUIFrames_GetTotalHeight();
+ SortData *sdarray;
+
+
+ g_CluiData.nGapBetweenTitlebar = (int)db_get_dw(NULL,"CLUIFrames","GapBetweenTitleBar",SETTING_GAPTITLEBAR_DEFAULT);
+ GapBetweenFrames = db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT);
+ sepw = GapBetweenFrames;
+
+ if (g_nFramesCount < 1) return 0;
+ newheight = newsize.bottom-newsize.top;
+
+ // search for alClient frame and get the titlebar's height
+ tbh = 0;
+ clientfrm = CLUIFramesGetalClientFrame();
+ if (clientfrm != -1)
+ tbh = (g_nTitleBarHeight+g_CluiData.nGapBetweenTitlebar)*btoint(g_pfwFrames[clientfrm].TitleBar.ShowTitleBar);
+
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if ( !g_pfwFrames[i].floating)
+ {
+ g_pfwFrames[i].needhide = FALSE;
+ g_pfwFrames[i].wndSize.left = newsize.left;
+ g_pfwFrames[i].wndSize.right = newsize.right;
+
+ };
+ };
+ {
+ //sorting stuff
+ sdarray = (SortData*)malloc(sizeof(SortData)*g_nFramesCount);
+ if (sdarray == NULL){return(-1);};
+ for (i=0;i < g_nFramesCount;i++)
+ {sdarray[i].order = g_pfwFrames[i].order;
+ sdarray[i].realpos = i;
+ };
+ qsort(sdarray,g_nFramesCount,sizeof(SortData),sortfunc);
+
+ }
+
+ drawitems = g_nFramesCount;
+
+ while(sumheight>(newheight-tbh) && drawitems>0) {
+ sumheight = 0;
+ drawitems = 0;
+ for (i=0;i < g_nFramesCount;i++) {
+ if (((g_pfwFrames[i].align != alClient)) && (!g_pfwFrames[i].floating) && (g_pfwFrames[i].visible) && (!g_pfwFrames[i].needhide)) {
+ drawitems++;
+ curfrmtbh = (g_nTitleBarHeight+g_CluiData.nGapBetweenTitlebar)*btoint(g_pfwFrames[i].TitleBar.ShowTitleBar);
+ sumheight += (g_pfwFrames[i].height)+curfrmtbh+(i > 0 ? sepw : 0)+((g_pfwFrames[i].UseBorder && !g_CluiData.fLayered)?2:0);
+ if (sumheight>newheight-tbh) {
+ sumheight -= (g_pfwFrames[i].height)+curfrmtbh + (i > 0 ? sepw : 0);
+ g_pfwFrames[i].needhide = !g_CluiData.fDocked && g_CluiData.fAutoSize?FALSE:TRUE;
+ drawitems--;
+ break;
+ }
+ }
+ }
+ }
+
+ prevframe = -1;
+ prevframebottomline = topBorder;
+ for (j = 0;j < g_nFramesCount;j++) {
+ //move all alTop frames
+ i = sdarray[j].realpos;
+ if ((!g_pfwFrames[i].needhide) && (!g_pfwFrames[i].floating) && (g_pfwFrames[i].visible) && (g_pfwFrames[i].align == alTop)) {
+ curfrmtbh = (g_nTitleBarHeight+g_CluiData.nGapBetweenTitlebar)*btoint(g_pfwFrames[i].TitleBar.ShowTitleBar);
+ g_pfwFrames[i].wndSize.top = prevframebottomline+(i > 0 ? sepw : 0)+(curfrmtbh);
+ g_pfwFrames[i].wndSize.bottom = g_pfwFrames[i].height+g_pfwFrames[i].wndSize.top+((g_pfwFrames[i].UseBorder && !g_CluiData.fLayered)?2:0);
+ g_pfwFrames[i].prevvisframe = prevframe;
+ prevframe = i;
+ prevframebottomline = g_pfwFrames[i].wndSize.bottom;
+ if (prevframebottomline>newheight){
+ //prevframebottomline -= Frames[i].height+(curfrmtbh+1);
+ //Frames[i].needhide = TRUE;
+ }
+ }
+ }
+
+ if (sumheight < newheight) {
+ for (j = 0;j < g_nFramesCount;j++) {
+ //move alClient frame
+ i = sdarray[j].realpos;
+ if ((!g_pfwFrames[i].needhide) && (!g_pfwFrames[i].floating) && (g_pfwFrames[i].visible) && (g_pfwFrames[i].align == alClient)) {
+ int oldh;
+ g_pfwFrames[i].wndSize.top = prevframebottomline+(j > 0 ? sepw : 0)+(tbh);
+ g_pfwFrames[i].wndSize.bottom = g_pfwFrames[i].wndSize.top+newheight-sumheight-tbh-(j > 0 ? sepw : 0);
+
+ oldh = g_pfwFrames[i].height;
+ g_pfwFrames[i].height = g_pfwFrames[i].wndSize.bottom-g_pfwFrames[i].wndSize.top;
+ g_pfwFrames[i].prevvisframe = prevframe;
+ prevframe = i;
+ prevframebottomline = g_pfwFrames[i].wndSize.bottom;
+ if (prevframebottomline>newheight) {
+ //prevframebottomline -= Frames[i].height+(tbh+1);
+ //Frames[i].needhide = TRUE;
+ }
+ break;
+ }
+ }
+ }
+
+ //newheight
+ prevframebottomline = newheight+sepw+topBorder;
+ //prevframe = -1;
+ for (j = g_nFramesCount-1;j >= 0;j--) {
+ //move all alBottom frames
+ i = sdarray[j].realpos;
+ if ((g_pfwFrames[i].visible) && (!g_pfwFrames[i].floating) && (!g_pfwFrames[i].needhide) && (g_pfwFrames[i].align == alBottom)) {
+ curfrmtbh = (g_nTitleBarHeight+g_CluiData.nGapBetweenTitlebar)*btoint(g_pfwFrames[i].TitleBar.ShowTitleBar);
+
+ g_pfwFrames[i].wndSize.bottom = prevframebottomline-(j > 0 ? sepw : 0);
+ g_pfwFrames[i].wndSize.top = g_pfwFrames[i].wndSize.bottom-g_pfwFrames[i].height-((g_pfwFrames[i].UseBorder && !g_CluiData.fLayered)?2:0);
+ g_pfwFrames[i].prevvisframe = prevframe;
+ prevframe = i;
+ prevframebottomline = g_pfwFrames[i].wndSize.top/*-1*/-curfrmtbh;
+ if (prevframebottomline>newheight) {
+
+ }
+ }
+ }
+ for (i=0;i < g_nFramesCount;i++)
+ if (g_pfwFrames[i].TitleBar.ShowTitleBar)
+ SetRect(&g_pfwFrames[i].TitleBar.wndSize,g_pfwFrames[i].wndSize.left,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar,g_pfwFrames[i].wndSize.right,g_pfwFrames[i].wndSize.top-g_CluiData.nGapBetweenTitlebar);
+ if (sdarray != NULL){free(sdarray);sdarray = NULL;};
+
+
+
+ return 0;
+}
+
+static int SizeMoveNewSizes()
+{
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ {
+
+ if (g_pfwFrames[i].floating){
+ CLUIFrameResizeFloatingFrame(i);
+ }else
+ {
+ CLUIFrameMoveResize(&g_pfwFrames[i]);
+ };
+ }
+ return 0;
+}
+
+
+static int CLUIFramesResize(RECT newsize)
+{
+ CLUIFramesResizeFrames(newsize);
+ SizeMoveNewSizes();
+ return 0;
+}
+int CLUIFrames_ApplyNewSizes(int mode)
+{
+ int i;
+ g_CluiData.mutexPreventDockMoving = 0;
+ for (i=0;i < g_nFramesCount;i++) {
+ if ((mode == 1 && g_pfwFrames[i].OwnerWindow != (HWND)-2 && g_pfwFrames[i].OwnerWindow) ||
+ (mode == 2 && g_pfwFrames[i].OwnerWindow == (HWND)-2) ||
+ (mode == 3))
+ if (g_pfwFrames[i].floating){
+ CLUIFrameResizeFloatingFrame(i);
+ }else
+ {
+ CLUIFrameMoveResize(&g_pfwFrames[i]);
+ };
+ }
+ if (IsWindowVisible(pcli->hwndContactList))
+ {
+ ske_DrawNonFramedObjects(1,0);
+ CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,0,0);
+ }
+ g_CluiData.mutexPreventDockMoving = 1;
+ return 0;
+}
+
+static int _us_DoUpdateFrame(WPARAM wParam,LPARAM lParam)
+{
+ if (_fCluiFramesModuleNotStarted) return -1;
+ if (wParam == -1) { CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0); return 0;}
+ if (lParam&FU_FMPOS) CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,1);
+
+ int pos = id2pos( wParam );
+ if ( pos < 0 || pos >= g_nFramesCount ) { return -1; }
+ if ( lParam&FU_TBREDRAW ) CLUIFramesForceUpdateTB( &g_pfwFrames[pos] );
+ if ( lParam&FU_FMREDRAW ) CLUIFramesForceUpdateFrame( &g_pfwFrames[pos] );
+ return 0;
+}
+
+int CLUIFrames_OnClistResize_mod(WPARAM wParam,LPARAM mode)
+{
+ RECT nRect;
+ int tick;
+ GapBetweenFrames = db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT);
+ g_CluiData.nGapBetweenTitlebar = db_get_dw(NULL,"CLUIFrames","GapBetweenTitleBar",SETTING_GAPTITLEBAR_DEFAULT);
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ GetClientRect(pcli->hwndContactList,&nRect);
+
+ nRect.left += g_CluiData.LeftClientMargin;
+ nRect.right -= g_CluiData.RightClientMargin;
+ nRect.top += g_CluiData.TopClientMargin;
+ nRect.bottom -= g_CluiData.BottomClientMargin;
+ // g_CluiData.mutexPreventDockMoving = 0;
+ tick = GetTickCount();
+ CLUIFramesResize(nRect);
+ if (mode == 0) CLUIFrames_ApplyNewSizes(3);
+
+ tick = GetTickCount()-tick;
+
+ Sleep(0);
+
+ //dont save to database too many times
+ if (GetTickCount()-_dwLastStoreTick>1000){ CLUIFramesStoreAllFrames();_dwLastStoreTick = GetTickCount();};
+
+ return 0;
+}
+
+int SizeFramesByWindowRect(RECT *r, HDWP * PosBatch, int mode)
+{
+ RECT nRect;
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ g_CluiData.nGapBetweenTitlebar = (int)db_get_dw(NULL,"CLUIFrames","GapBetweenTitleBar",SETTING_GAPTITLEBAR_DEFAULT);
+ GapBetweenFrames = db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT);
+ nRect.left = 0;
+ nRect.top = 0;
+ nRect.right = r->right-r->left;
+ nRect.bottom = r->bottom-r->top;
+ nRect.left += g_CluiData.LeftClientMargin;
+ nRect.right -= g_CluiData.RightClientMargin;
+ nRect.top += g_CluiData.TopClientMargin;
+ nRect.bottom -= g_CluiData.BottomClientMargin;
+ CLUIFramesResizeFrames(nRect);
+ {
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ int dx;
+ int dy;
+ dx = 0;//rcNewWindowRect.left-rcOldWindowRect.left;
+ dy = 0;//_window_rect.top-rcOldWindowRect.top;
+ if ( !g_pfwFrames[i].floating)
+ {
+ if (g_pfwFrames[i].visible && !g_pfwFrames[i].needhide && !IsWindowVisible(g_pfwFrames[i].hWnd))
+ {
+ ShowWindow(g_pfwFrames[i].hWnd,SW_SHOW);
+ if (g_pfwFrames[i].TitleBar.ShowTitleBar) ShowWindow(g_pfwFrames[i].TitleBar.hwnd,SW_SHOW);
+ }
+ if (g_pfwFrames[i].OwnerWindow && (INT_PTR)(g_pfwFrames[i].OwnerWindow) != -2 )
+ {
+ if ( !(mode&2))
+ {
+ HWND hwnd;
+ hwnd = GetParent(g_pfwFrames[i].OwnerWindow);
+ *PosBatch = DeferWindowPos(*PosBatch,g_pfwFrames[i].OwnerWindow,NULL,g_pfwFrames[i].wndSize.left+r->left,g_pfwFrames[i].wndSize.top+r->top,
+ g_pfwFrames[i].wndSize.right-g_pfwFrames[i].wndSize.left, g_pfwFrames[i].wndSize.bottom-g_pfwFrames[i].wndSize.top,SWP_NOZORDER|SWP_NOACTIVATE);
+ SetWindowPos(g_pfwFrames[i].hWnd,NULL,0,0,
+ g_pfwFrames[i].wndSize.right-g_pfwFrames[i].wndSize.left, g_pfwFrames[i].wndSize.bottom-g_pfwFrames[i].wndSize.top,SWP_NOZORDER|SWP_NOACTIVATE/*|SWP_NOSENDCHANGING*/);
+ }
+ //Frame
+ if (g_pfwFrames[i].TitleBar.ShowTitleBar)
+ {
+ SetWindowPos(g_pfwFrames[i].TitleBar.hwnd,NULL,g_pfwFrames[i].wndSize.left+dx,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar+dy,
+ g_pfwFrames[i].wndSize.right-g_pfwFrames[i].wndSize.left,g_nTitleBarHeight,SWP_NOZORDER|SWP_NOACTIVATE );
+ SetRect(&g_pfwFrames[i].TitleBar.wndSize,g_pfwFrames[i].wndSize.left,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar,g_pfwFrames[i].wndSize.right,g_pfwFrames[i].wndSize.top-g_CluiData.nGapBetweenTitlebar);
+ UpdateWindow(g_pfwFrames[i].TitleBar.hwnd);
+ }
+ }
+ else
+ {
+ if (1)
+ {
+ int res = 0;
+ // set frame position
+ res = SetWindowPos(g_pfwFrames[i].hWnd,NULL,g_pfwFrames[i].wndSize.left+dx,g_pfwFrames[i].wndSize.top+dy,
+ g_pfwFrames[i].wndSize.right-g_pfwFrames[i].wndSize.left,
+ g_pfwFrames[i].wndSize.bottom-g_pfwFrames[i].wndSize.top,SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSENDCHANGING);
+ }
+ if (1)
+ {
+ // set titlebar position
+ if (g_pfwFrames[i].TitleBar.ShowTitleBar)
+ {
+ SetWindowPos(g_pfwFrames[i].TitleBar.hwnd,NULL,g_pfwFrames[i].wndSize.left+dx,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar+dy,
+ g_pfwFrames[i].wndSize.right-g_pfwFrames[i].wndSize.left,g_nTitleBarHeight,SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSENDCHANGING );
+ SetRect(&g_pfwFrames[i].TitleBar.wndSize,g_pfwFrames[i].wndSize.left,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar,g_pfwFrames[i].wndSize.right,g_pfwFrames[i].wndSize.top-g_CluiData.nGapBetweenTitlebar);
+
+ }
+ }
+ UpdateWindow(g_pfwFrames[i].hWnd);
+ if (g_pfwFrames[i].TitleBar.ShowTitleBar) UpdateWindow(g_pfwFrames[i].TitleBar.hwnd);
+ };
+ }
+
+ }
+ if (GetTickCount()-_dwLastStoreTick>1000)
+ {
+ CLUIFramesStoreAllFrames();
+ _dwLastStoreTick = GetTickCount();
+ };
+ }
+ return 0;
+}
+
+int CheckFramesPos(RECT *wr)
+{
+ //CALLED only FROM MainWindow procedure at CLUI.c
+ int i;
+ if (_fCluiFramesModuleNotStarted) return -1;
+ g_CluiData.nGapBetweenTitlebar = (int)db_get_dw(NULL,"CLUIFrames","GapBetweenTitleBar",SETTING_GAPTITLEBAR_DEFAULT);
+ GapBetweenFrames = db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT);
+
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ int dx;
+ int dy;
+ dx = 0;//rcNewWindowRect.left-rcOldWindowRect.left;
+ dy = 0;//_window_rect.top-rcOldWindowRect.top;
+ if ( !g_pfwFrames[i].floating && g_pfwFrames[i].visible)
+ {
+ if ( !(g_pfwFrames[i].OwnerWindow && (INT_PTR)(g_pfwFrames[i].OwnerWindow) != -2))
+ {
+ RECT r;
+ GetWindowRect(g_pfwFrames[i].hWnd,&r);
+ if (r.top-wr->top != g_pfwFrames[i].wndSize.top || r.left-wr->left != g_pfwFrames[i].wndSize.left)
+ SetWindowPos(g_pfwFrames[i].hWnd,NULL,g_pfwFrames[i].wndSize.left, g_pfwFrames[i].wndSize.top,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
+ }
+ if (g_pfwFrames[i].TitleBar.ShowTitleBar)
+ {
+ RECT r;
+ GetWindowRect(g_pfwFrames[i].TitleBar.hwnd,&r);
+ if (r.top-wr->top != g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar || r.left-wr->left != g_pfwFrames[i].wndSize.left)
+ {
+ SetWindowPos(g_pfwFrames[i].TitleBar.hwnd,NULL,g_pfwFrames[i].wndSize.left+dx,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar+dy,
+ g_pfwFrames[i].wndSize.right-g_pfwFrames[i].wndSize.left,g_nTitleBarHeight,SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE);
+ SetRect(&g_pfwFrames[i].TitleBar.wndSize,g_pfwFrames[i].wndSize.left,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar,g_pfwFrames[i].wndSize.right,g_pfwFrames[i].wndSize.top-g_CluiData.nGapBetweenTitlebar);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+int CLUIFramesOnClistResize(WPARAM wParam,LPARAM lParam)
+{
+ RECT nRect;
+ int tick;
+ GapBetweenFrames = db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT);
+ g_CluiData.nGapBetweenTitlebar = db_get_dw(NULL,"CLUIFrames","GapBetweenTitleBar",SETTING_GAPTITLEBAR_DEFAULT);
+
+ if (_fCluiFramesModuleNotStarted) return -1;
+
+ //need to enlarge parent
+ {
+ RECT mainRect;
+ int mainHeight, minHeight;
+ GetWindowRect(pcli->hwndContactList,&mainRect);
+ mainHeight = mainRect.bottom-mainRect.top;
+ minHeight = CLUIFrames_GetTotalHeight();
+ if (mainHeight < minHeight)
+ {
+ BOOL Upward = FALSE;
+ Upward = !g_CluiData.fDocked && g_CluiData.fAutoSize && db_get_b(NULL,"CLUI","AutoSizeUpward",SETTING_AUTOSIZEUPWARD_DEFAULT);
+
+ if (Upward)
+ mainRect.top = mainRect.bottom-minHeight;
+ else
+ mainRect.bottom = mainRect.top+minHeight;
+ SetWindowPos(pcli->hwndContactList,NULL,mainRect.left,mainRect.top,mainRect.right-mainRect.left, mainRect.bottom-mainRect.top, SWP_NOZORDER|SWP_NOREDRAW|SWP_NOACTIVATE|SWP_NOSENDCHANGING);
+ }
+ GetWindowRect(pcli->hwndContactList,&mainRect);
+ mainHeight = mainRect.bottom-mainRect.top;
+ }
+ GetClientRect(pcli->hwndContactList,&nRect);
+ //$$$ Fixed borders
+ if (lParam && lParam != 1 && lParam != 2)
+ {
+ RECT oldRect;
+ POINT pt;
+ RECT * newRect = (RECT *)lParam;
+ int dl,dt,dr,db;
+ GetWindowRect((HWND)wParam,&oldRect);
+ pt.x = nRect.left;
+ pt.y = nRect.top;
+ ClientToScreen(pcli->hwndContactList,&pt);
+ dl = pt.x-oldRect.left;
+ dt = pt.y-oldRect.top;
+ dr = (oldRect.right-oldRect.left)-(nRect.right-nRect.left)-dl;
+ db = (oldRect.bottom-oldRect.top)-(nRect.bottom-nRect.top)-dt;
+ nRect.left = newRect->left+dl;
+ nRect.top = newRect->top+dt;
+ nRect.bottom = newRect->bottom-db;
+ nRect.right = newRect->right-dr;
+ }
+
+
+ //if (DBGetContactSettingByte(NULL,"CLUI","ShowSBar",SETTING_SHOWSBAR_DEFAULT))GetWindowRect(pcli->hwndStatus,&rcStatus);
+ //else rcStatus.top = rcStatus.bottom = 0;
+ // nRect.top--;
+ /* $$$ rcStatus.top = rcStatus.bottom = 0;
+
+
+ nRect.bottom -= nRect.top;
+ nRect.bottom -= (rcStatus.bottom-rcStatus.top);
+ nRect.right -= nRect.left;
+ nRect.left = 0;
+ nRect.top = 0;
+ ContactListHeight = nRect.bottom; $$$*/
+
+ nRect.left += g_CluiData.LeftClientMargin;
+ nRect.right -= g_CluiData.RightClientMargin;
+ nRect.top += g_CluiData.TopClientMargin;
+ nRect.bottom -= g_CluiData.BottomClientMargin;
+
+ if (nRect.bottom < nRect.top)
+ nRect.bottom = nRect.top;
+ _nContactListHeight = nRect.bottom-nRect.top; //$$
+
+ tick = GetTickCount();
+
+
+ CLUIFramesResize(nRect);
+
+ CLUIFrames_ApplyNewSizes(2);
+ CLUIFrames_ApplyNewSizes(1);
+
+ //resizing = FALSE;
+
+ tick = GetTickCount()-tick;
+
+ if (pcli->hwndContactList != 0) CLUI__cliInvalidateRect(pcli->hwndContactList,NULL,TRUE);
+ if (pcli->hwndContactList != 0) UpdateWindow(pcli->hwndContactList);
+
+ if (lParam == 2) RedrawWindow(pcli->hwndContactList,NULL,NULL,RDW_UPDATENOW|RDW_ALLCHILDREN|RDW_ERASE|RDW_INVALIDATE);
+
+
+ Sleep(0);
+
+ //dont save to database too many times
+ if (GetTickCount()-_dwLastStoreTick>1000){ CLUIFramesStoreAllFrames();_dwLastStoreTick = GetTickCount();};
+
+ return 0;
+}
+
+int OnFrameTitleBarBackgroundChange(WPARAM wParam,LPARAM lParam)
+{
+ if (MirandaExiting()) return 0;
+ {
+ DBVARIANT dbv = {0};
+
+ AlignCOLLIconToLeft = db_get_b(NULL,"FrameTitleBar","AlignCOLLIconToLeft",CLCDEFAULT_COLLICONTOLEFT);
+
+ bkColour = sttGetColor("FrameTitleBar","BkColour",CLCDEFAULT_BKCOLOUR);
+ bkUseWinColours = db_get_b(NULL,"FrameTitleBar","UseWinColours",CLCDEFAULT_USEWINDOWSCOLOURS);
+ SelBkColour = sttGetColor("FrameTitleBar","TextColour",CLCDEFAULT_TEXTCOLOUR);
+ if (hBmpBackground) {DeleteObject(hBmpBackground); hBmpBackground = NULL;}
+ if (g_CluiData.fDisableSkinEngine)
+ {
+ if (db_get_b(NULL,"FrameTitleBar","UseBitmap",CLCDEFAULT_USEBITMAP)) {
+ if ( !DBGetContactSettingString(NULL,"FrameTitleBar","BkBitmap",&dbv)) {
+ hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ }
+ backgroundBmpUse = db_get_w(NULL,"FrameTitleBar","BkBmpUse",CLCDEFAULT_BKBMPUSE);
+ }
+ };
+
+ CLUI__cliInvalidateRect( pcli->hwndContactList, 0, 0 );
+
+ RedrawWindow(pcli->hwndContactList,NULL,NULL,RDW_UPDATENOW|RDW_ALLCHILDREN|RDW_ERASE|RDW_INVALIDATE);
+
+ return 0;
+}
+
+void DrawBackGround(HWND hwnd,HDC mhdc, HBITMAP hBmpBackground, COLORREF bkColour, DWORD backgroundBmpUse )
+{
+ HDC hdcMem,hdc;
+ RECT clRect,*rcPaint;
+
+ int yScroll = 0;
+ int y;
+ PAINTSTRUCT paintst = {0};
+ HBITMAP hBmpOsb,hOldBmp;
+ DWORD style = GetWindowLongPtr(hwnd,GWL_STYLE);
+ int grey = 0;
+ HFONT oFont;
+ HBRUSH hBrushAlternateGrey = NULL;
+
+ HFONT hFont;
+
+ //InvalidateRect(hwnd,0,FALSE);
+
+ hFont = (HFONT)SendMessage(hwnd,WM_GETFONT,0,0);
+
+ if (mhdc)
+ {
+ hdc = mhdc;
+ rcPaint = NULL;
+ }
+ else
+ {
+ hdc = BeginPaint(hwnd,&paintst);
+ rcPaint = &(paintst.rcPaint);
+ }
+
+ GetClientRect(hwnd,&clRect);
+ if (rcPaint == NULL) rcPaint = &clRect;
+ if (rcPaint->right-rcPaint->left == 0 || rcPaint->top-rcPaint->bottom == 0) rcPaint = &clRect;
+ y = -yScroll;
+ hdcMem = CreateCompatibleDC(hdc);
+ hBmpOsb = CreateBitmap(clRect.right,clRect.bottom,1,GetDeviceCaps(hdc,BITSPIXEL),NULL);
+ hOldBmp = (HBITMAP)SelectObject(hdcMem,hBmpOsb);
+ oFont = (HFONT)SelectObject(hdcMem,hFont);
+ SetBkMode(hdcMem,TRANSPARENT);
+ SetStretchBltMode(hdcMem,HALFTONE);
+ { HBRUSH hBrush;
+
+ hBrush = CreateSolidBrush(bkColour);
+ FillRect(hdcMem,rcPaint,hBrush);
+ DeleteObject(hBrush);
+ if (hBmpBackground) {
+ BITMAP bmp;
+ HDC hdcBmp;
+ int x,y;
+ int maxx,maxy;
+ int destw,desth;
+
+ GetObject(hBmpBackground,sizeof(bmp),&bmp);
+ hdcBmp = CreateCompatibleDC(hdcMem);
+ SelectObject(hdcBmp,hBmpBackground);
+ y = backgroundBmpUse&CLBF_SCROLL?-yScroll:0;
+ maxx = backgroundBmpUse&CLBF_TILEH?clRect.right:1;
+ maxy = backgroundBmpUse&CLBF_TILEV?maxy = rcPaint->bottom:y+1;
+ switch(backgroundBmpUse&CLBM_TYPE) {
+ case CLB_STRETCH:
+ if (backgroundBmpUse&CLBF_PROPORTIONAL) {
+ if (clRect.right*bmp.bmHeight < clRect.bottom*bmp.bmWidth) {
+ desth = clRect.bottom;
+ destw = desth*bmp.bmWidth/bmp.bmHeight;
+ }
+ else {
+ destw = clRect.right;
+ desth = destw*bmp.bmHeight/bmp.bmWidth;
+ }
+ }
+ else {
+ destw = clRect.right;
+ desth = clRect.bottom;
+ }
+ break;
+ case CLB_STRETCHH:
+ if (backgroundBmpUse&CLBF_PROPORTIONAL) {
+ destw = clRect.right;
+ desth = destw*bmp.bmHeight/bmp.bmWidth;
+ }
+ else {
+ destw = clRect.right;
+ desth = bmp.bmHeight;
+ }
+ break;
+ case CLB_STRETCHV:
+ if (backgroundBmpUse&CLBF_PROPORTIONAL) {
+ desth = clRect.bottom;
+ destw = desth*bmp.bmWidth/bmp.bmHeight;
+ }
+ else {
+ destw = bmp.bmWidth;
+ desth = clRect.bottom;
+ }
+ break;
+ default: //clb_topleft
+ destw = bmp.bmWidth;
+ desth = bmp.bmHeight;
+ break;
+ }
+ desth = clRect.bottom -clRect.top;
+ for (;y < maxy;y += desth) {
+ if (y < rcPaint->top-desth) continue;
+ for (x = 0;x < maxx;x += destw)
+ StretchBlt(hdcMem,x,y,destw,desth,hdcBmp,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
+ }
+ DeleteDC(hdcBmp);
+ }
+ }
+
+ {
+
+ BitBlt(hdc,rcPaint->left,rcPaint->top,rcPaint->right-rcPaint->left,rcPaint->bottom-rcPaint->top,hdcMem,rcPaint->left,rcPaint->top,SRCCOPY);
+
+ SelectObject(hdcMem,hOldBmp);
+ SelectObject(hdcMem,oFont);
+ DeleteObject(hBmpOsb);
+ DeleteDC(hdcMem);
+ paintst.fErase = FALSE;
+ //DeleteObject(hFont);
+ if ( !mhdc)
+ {
+ EndPaint(hwnd,&paintst);
+ }
+ }
+}
+
+
+int DrawTitleBar(HDC hdcMem2,RECT * rect,int Frameid)
+{
+ int pos;
+ BOOL bThemed = FALSE;
+ HDC hdcMem;
+ HFONT hoTTBFont;
+ RECT rc = *rect;
+ HBRUSH hBack,hoBrush;
+ HBITMAP b1 = NULL,b2 = NULL;
+ hdcMem = CreateCompatibleDC(hdcMem2);
+
+ SetBkMode(hdcMem,TRANSPARENT);
+ hoTTBFont = (HFONT)SelectObject(hdcMem,_hTitleBarFont);
+ ske_ResetTextEffect(hdcMem);
+ ske_ResetTextEffect(hdcMem2);
+ hBack = GetSysColorBrush(COLOR_3DFACE);
+ hoBrush = (HBRUSH)SelectObject(hdcMem,hBack);
+
+ pos = id2pos(Frameid);
+
+ if (pos >= 0 && pos < g_nFramesCount)
+ {
+ GetClientRect(g_pfwFrames[pos].TitleBar.hwnd,&rc);
+ if (g_pfwFrames[pos].floating)
+ {
+
+ rc.bottom = rc.top+g_nTitleBarHeight;
+ g_pfwFrames[pos].TitleBar.wndSize = rc;
+ }
+ else
+ {
+ g_pfwFrames[pos].TitleBar.wndSize = rc;
+ }
+ b1 = ske_CreateDIB32(rc.right-rc.left,rc.bottom-rc.top);
+ b2 = (HBITMAP)SelectObject(hdcMem,b1);
+ if ( g_pfwFrames[pos].floating && !g_CluiData.fDisableSkinEngine)
+ {
+ FillRect(hdcMem,&rc,hBack);
+ //SelectObject(hdcMem,hoBrush);
+ SkinDrawGlyph(hdcMem,&rc,&rc,"Main,ID=FrameCaption");
+ }
+ else
+ {
+ if (g_CluiData.fDisableSkinEngine)
+ {
+ if ( !hBmpBackground && bkUseWinColours && xpt_IsThemed(_hFrameTitleTheme))
+ {
+ int state = CS_ACTIVE;
+ // if (GetForegroundWindow() != pcli->hwndContactList) state = CS_INACTIVE;
+ xpt_DrawThemeBackground(_hFrameTitleTheme,hdcMem, WP_SMALLCAPTION, state, &rc,&rc);
+ bThemed = TRUE;
+ }
+ else
+ DrawBackGround(g_pfwFrames[pos].TitleBar.hwnd,hdcMem, hBmpBackground, bkColour, backgroundBmpUse);
+ }
+ else if ( !g_CluiData.fLayered)
+ {
+ ske_BltBackImage(g_pfwFrames[pos].TitleBar.hwnd,hdcMem,&rc);
+ }
+ else BitBlt(hdcMem,0,0,rc.right-rc.left,rc.bottom-rc.top,hdcMem2,rect->left,rect->top,SRCCOPY);
+ SkinDrawGlyph(hdcMem,&rc,&rc,"Main,ID=FrameCaption");
+ }
+ if (bThemed)
+ SetTextColor(hdcMem,GetSysColor(COLOR_CAPTIONTEXT ));
+ else
+ SetTextColor(hdcMem,SelBkColour);
+ {
+ RECT textrc = rc;
+ if ( !AlignCOLLIconToLeft)
+ {
+
+ if (g_pfwFrames[pos].TitleBar.hicon != NULL)
+ {
+ mod_DrawIconEx_helper(hdcMem,rc.left +2,rc.top+((g_nTitleBarHeight>>1)-(GetSystemMetrics(SM_CYSMICON)>>1)),g_pfwFrames[pos].TitleBar.hicon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL);
+ textrc.left += GetSystemMetrics(SM_CXSMICON)+4;
+ textrc.top += 2;
+ }
+ else
+ {
+ textrc.left += 2;
+ textrc.top += 2;
+ }
+
+ }
+ else
+ {
+ textrc.left += GetSystemMetrics(SM_CXSMICON)+2;
+ textrc.top += 2;
+ }
+ ske_TextOut(hdcMem,textrc.left,textrc.top,g_pfwFrames[pos].TitleBar.tbname,lstrlen(g_pfwFrames[pos].TitleBar.tbname));
+
+ }
+ if ( !AlignCOLLIconToLeft)
+ {
+ mod_DrawIconEx_helper(hdcMem,g_pfwFrames[pos].TitleBar.wndSize.right-GetSystemMetrics(SM_CXSMICON)-2,rc.top+((g_nTitleBarHeight>>1)-(GetSystemMetrics(SM_CXSMICON)>>1)),g_pfwFrames[pos].collapsed?LoadSkinnedIcon(SKINICON_OTHER_GROUPOPEN):LoadSkinnedIcon(SKINICON_OTHER_GROUPSHUT),GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL);
+ }
+ else
+ {
+ mod_DrawIconEx_helper(hdcMem,rc.left,rc.top+((g_nTitleBarHeight>>1)-(GetSystemMetrics(SM_CXSMICON)>>1)),g_pfwFrames[pos].collapsed?LoadSkinnedIcon(SKINICON_OTHER_GROUPOPEN):LoadSkinnedIcon(SKINICON_OTHER_GROUPSHUT),GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL);
+ }
+
+
+ }
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ if (g_pfwFrames[pos].floating || (!g_CluiData.fLayered))
+ {
+ HRGN rgn = CreateRectRgn(rect->left,rect->top,rect->right,rect->bottom);
+ SelectClipRgn(hdcMem2,rgn);
+ BitBlt(hdcMem2,rect->left,rect->top,rc.right-rc.left,rc.bottom-rc.top,hdcMem,0,0,SRCCOPY);
+ DeleteObject(rgn);
+ }
+ else
+ BitBlt(hdcMem2,rect->left,rect->top,rc.right-rc.left,rc.bottom-rc.top,hdcMem,0,0,SRCCOPY);
+ //MyAlphaBlend(hdcMem2,rect.left,rect.top,rc.right-rc.left,rc.bottom-rc.top,hdcMem,0,0,rc.right-rc.left,rc.bottom-rc.top,bf);
+ }
+
+ SelectObject(hdcMem,b2);
+ DeleteObject(b1);
+ SelectObject(hdcMem,hoTTBFont);
+ SelectObject(hdcMem,hoBrush);
+ mod_DeleteDC(hdcMem);
+ return 0;
+}
+static LRESULT CALLBACK CLUIFrameTitleBarProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static int s_nLastByPos = -1;
+ static int s_nOldFrameHeight = -1;
+ static int s_nCurDragBar = -1;
+
+ RECT rect;
+ int Frameid,Framemod,direction;
+ int xpos,ypos;
+
+ Frameid = (GetWindowLongPtr(hwnd,GWLP_USERDATA));
+ memset(&rect,0,sizeof(rect));
+
+
+ switch(msg)
+ {
+ case WM_CREATE:
+ if ( !_hFrameTitleTheme)
+ _hFrameTitleTheme = xpt_AddThemeHandle(hwnd,L"WINDOW");
+ SendMessage(hwnd,WM_SETFONT,(WPARAM)_hTitleBarFont,0);
+ return FALSE;
+ case WM_MEASUREITEM:
+ return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam);
+ case WM_DRAWITEM:
+ return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam);
+ case WM_USER+100:
+ return 1;
+ case WM_ENABLE:
+ if (hwnd != 0) CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ return 0;
+ case WM_ERASEBKGND:
+ {
+ return 1;
+ }
+ case WM_COMMAND:
+
+
+ if (ServiceExists(MO_CREATENEWMENUOBJECT))
+ {
+ //if ( CallService(MS_CLIST_MENUPROCESSCOMMAND,MAKEWPARAM(LOWORD(wParam),0),(LPARAM)Frameid)){break;};
+ if (ProcessCommandProxy(MAKEWPARAM(LOWORD(wParam),0),(LPARAM)Frameid)) break;
+ }else
+ {
+ if ( CallService(MS_CLIST_MENUPROCESSCOMMAND,MAKEWPARAM(LOWORD(wParam),MPCF_CONTEXTFRAMEMENU),(LPARAM)Frameid)){break;};
+
+ };
+
+
+ if (HIWORD(wParam) == 0) {//mouse events for self created menu
+ int framepos = id2pos(Frameid);
+ if (framepos == -1){break;};
+
+ switch(LOWORD(wParam))
+ {
+ case frame_menu_lock:
+ g_pfwFrames[framepos].Locked = !g_pfwFrames[framepos].Locked;
+ break;
+ case frame_menu_visible:
+ g_pfwFrames[framepos].visible = !g_pfwFrames[framepos].visible;
+ break;
+ case frame_menu_showtitlebar:
+ g_pfwFrames[framepos].TitleBar.ShowTitleBar = !g_pfwFrames[framepos].TitleBar.ShowTitleBar;
+ break;
+ case frame_menu_floating:
+ CLUIFrames_SetFrameFloat(Frameid,0);
+ break;
+ }
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ }
+
+ break;
+ case WM_RBUTTONDOWN:
+ {
+ HMENU hmenu;
+ POINT pt;
+ GetCursorPos(&pt);
+
+ if (ServiceExists(MS_CLIST_MENUBUILDFRAMECONTEXT))
+ {
+ hmenu = (HMENU)CallService(MS_CLIST_MENUBUILDFRAMECONTEXT,Frameid,0);
+ }
+ else
+ {//legacy menu support
+ int framepos = id2pos(Frameid);
+
+ if (framepos == -1){break;};
+ hmenu = CreatePopupMenu();
+ // Frames[Frameid].TitleBar.hmenu = hmenu;
+ AppendMenu(hmenu,MF_STRING|MF_DISABLED|MF_GRAYED,15,g_pfwFrames[framepos].Name);
+ AppendMenu(hmenu,MF_SEPARATOR,16,_T(""));
+
+ if (g_pfwFrames[framepos].Locked)
+ {AppendMenu(hmenu,MF_STRING|MF_CHECKED,frame_menu_lock,TranslateT("Lock Frame"));}
+ else{AppendMenu(hmenu,MF_STRING,frame_menu_lock,TranslateT("Lock Frame"));};
+
+ if (g_pfwFrames[framepos].visible)
+ {AppendMenu(hmenu,MF_STRING|MF_CHECKED,frame_menu_visible,TranslateT("Visible"));}
+ else{AppendMenu(hmenu,MF_STRING,frame_menu_visible,TranslateT("Visible"));};
+
+ if (g_pfwFrames[framepos].TitleBar.ShowTitleBar)
+ {AppendMenu(hmenu,MF_STRING|MF_CHECKED,frame_menu_showtitlebar,TranslateT("Show TitleBar"));}
+ else{AppendMenu(hmenu,MF_STRING,frame_menu_showtitlebar,TranslateT("Show TitleBar"));};
+
+ if (g_pfwFrames[framepos].floating)
+ {AppendMenu(hmenu,MF_STRING|MF_CHECKED,frame_menu_floating,TranslateT("Floating"));}
+ else{AppendMenu(hmenu,MF_STRING,frame_menu_floating,TranslateT("Floating"));};
+
+ //err = GetMenuItemCount(hmenu)
+
+ };
+
+ TrackPopupMenu(hmenu,TPM_LEFTALIGN,pt.x,pt.y,0,hwnd,0);
+ DestroyMenu(hmenu);
+ }
+ break;
+ case WM_LBUTTONDBLCLK:
+ {
+ Framemod = -1;
+ s_nLastByPos = -1;s_nOldFrameHeight = -1;ReleaseCapture();
+ CallService(MS_CLIST_FRAMES_UCOLLFRAME,Frameid,0);
+ s_nLastByPos = -1;s_nOldFrameHeight = -1;ReleaseCapture();
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ {
+ if (GetCapture() != hwnd){break;};
+ s_nCurDragBar = -1;s_nLastByPos = -1;s_nOldFrameHeight = -1;ReleaseCapture();
+ break;
+ };
+ case WM_LBUTTONDOWN:
+ {
+
+ int framepos = id2pos(Frameid);
+
+ if (framepos == -1){break;};
+ {
+ if (g_pfwFrames[framepos].floating)
+ {
+
+ POINT pt;
+ GetCursorPos(&pt);
+ g_pfwFrames[framepos].TitleBar.oldpos = pt;
+ };
+ };
+
+ //ScreenToClient(Frames[framepos].ContainerWnd,&Frames[framepos].TitleBar.oldpos);
+
+ if ((!(wParam&MK_CONTROL)) && g_pfwFrames[framepos].Locked && (!(g_pfwFrames[framepos].floating)))
+ {
+ if (db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT)) {
+ POINT pt;
+ int res;
+ //pt = nm->pt;
+ GetCursorPos(&pt);
+ res = SendMessage(GetParent(hwnd), WM_SYSCOMMAND, SC_MOVE|HTCAPTION,MAKELPARAM(pt.x,pt.y));
+ return res;
+ }
+ };
+
+ if (g_pfwFrames[framepos].floating)
+ {
+ RECT rc;
+ GetCursorPos(&ptOld);
+ //ClientToScreen(hwnd,&ptOld);
+ GetWindowRect( hwnd, &rc );
+
+ nLeft = (short)rc.left;
+ nTop = (short)rc.top;
+ };
+
+ SetCapture(hwnd);
+
+
+ break;
+ };
+ case WM_MOUSEMOVE:
+ {
+ POINT pt,pt2;
+ RECT wndr;
+ int pos;
+ //tbinfo
+ {
+ char TBcapt[255];
+
+
+ pos = id2pos(Frameid);
+
+ if (pos != -1)
+ {
+ int oldflags;
+
+
+ sprintf(TBcapt,"%s - h:%d, vis:%d, fl:%d, fl:(%d,%d,%d,%d),or: %d",
+ g_pfwFrames[pos].szName,g_pfwFrames[pos].height,g_pfwFrames[pos].visible,g_pfwFrames[pos].floating,
+ g_pfwFrames[pos].FloatingPos.x,g_pfwFrames[pos].FloatingPos.y,
+ g_pfwFrames[pos].FloatingSize.x,g_pfwFrames[pos].FloatingSize.y,
+ g_pfwFrames[pos].order
+ );
+
+ oldflags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,g_pfwFrames[pos].id),(LPARAM)0);
+ if ( !(oldflags&F_SHOWTBTIP))
+ {
+ oldflags |= F_SHOWTBTIP;
+ //CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,Frames[pos].id),(LPARAM)oldflags);
+ };
+ //CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_TBTIPNAME,Frames[pos].id),(LPARAM)TBcapt);
+ };
+
+
+
+ }
+ //
+ if ((wParam&MK_LBUTTON)/* && (wParam&MK_CONTROL)*/)
+ {
+ RECT rcMiranda;
+ RECT rcwnd,rcOverlap;
+ POINT newpt,ofspt,curpt,newpos;
+ //if (GetCapture() != hwnd){break;};
+ //curdragbar = -1;lbypos = -1;oldframeheight = -1;ReleaseCapture();
+
+ pos = id2pos(Frameid);
+ if (g_pfwFrames[pos].floating)
+ {
+
+ GetCursorPos(&curpt);
+ rcwnd.bottom = curpt.y+5;
+ rcwnd.top = curpt.y;
+ rcwnd.left = curpt.x;
+ rcwnd.right = curpt.x+5;
+
+ GetWindowRect(pcli->hwndContactList, &rcMiranda );
+ //GetWindowRect( Frames[pos].ContainerWnd, &rcwnd );
+ //IntersectRect( &rcOverlap, &rcwnd, &rcMiranda )
+ if (IsWindowVisible(pcli->hwndContactList) && IntersectRect( &rcOverlap, &rcwnd, &rcMiranda ))
+ {
+ int id = g_pfwFrames[pos].id;
+
+
+
+
+ ofspt.x = 0;ofspt.y = 0;
+ ClientToScreen(g_pfwFrames[pos].TitleBar.hwnd,&ofspt);
+ ofspt.x = curpt.x-ofspt.x;ofspt.y = curpt.y-ofspt.y;
+
+ CLUIFrames_SetFrameFloat(id,0);
+ newpt.x = 0;newpt.y = 0;
+ ClientToScreen(g_pfwFrames[pos].TitleBar.hwnd,&newpt);
+ SetCursorPos(newpt.x+ofspt.x,newpt.y+ofspt.y);
+ GetCursorPos(&curpt);
+
+ g_pfwFrames[pos].TitleBar.oldpos = curpt;
+
+ return(0);
+ };
+
+ }
+ else
+ {
+ int id = g_pfwFrames[pos].id;
+
+ GetCursorPos(&curpt);
+ rcwnd.bottom = curpt.y+5;
+ rcwnd.top = curpt.y;
+ rcwnd.left = curpt.x;
+ rcwnd.right = curpt.x+5;
+
+ GetWindowRect(pcli->hwndContactList, &rcMiranda );
+ //GetWindowRect( Frames[pos].ContainerWnd, &rcwnd );
+ //IntersectRect( &rcOverlap, &rcwnd, &rcMiranda )
+
+
+ if ( !IntersectRect( &rcOverlap, &rcwnd, &rcMiranda ))
+ {
+ GetCursorPos(&curpt);
+ GetWindowRect( g_pfwFrames[pos].hWnd, &rcwnd );
+ rcwnd.left = rcwnd.right-rcwnd.left;
+ rcwnd.top = rcwnd.bottom-rcwnd.top;
+ newpos.x = curpt.x;newpos.y = curpt.y;
+ if (curpt.x >= (rcMiranda.right-1)){newpos.x = curpt.x+5;};
+ if (curpt.x <= (rcMiranda.left+1)){newpos.x = curpt.x-(rcwnd.left)-5;};
+ if (curpt.y >= (rcMiranda.bottom-1)){newpos.y = curpt.y+5;};
+ if (curpt.y <= (rcMiranda.top+1)){newpos.y = curpt.y-(rcwnd.top)-5;};
+ ofspt.x = 0;ofspt.y = 0;
+ //ClientToScreen(Frames[pos].TitleBar.hwnd,&ofspt);
+ GetWindowRect(g_pfwFrames[pos].TitleBar.hwnd,&rcwnd);
+ ofspt.x = curpt.x-ofspt.x;ofspt.y = curpt.y-ofspt.y;
+
+ g_pfwFrames[pos].FloatingPos.x = newpos.x;
+ g_pfwFrames[pos].FloatingPos.y = newpos.y;
+ CLUIFrames_SetFrameFloat(id,0);
+ //SetWindowPos(Frames[pos].ContainerWnd,0,newpos.x,newpos.y,0,0,SWP_NOSIZE);
+
+
+ newpt.x = 0;newpt.y = 0;
+ ClientToScreen(g_pfwFrames[pos].TitleBar.hwnd,&newpt);
+
+ GetWindowRect( g_pfwFrames[pos].hWnd, &rcwnd );
+ SetCursorPos(newpt.x+(rcwnd.right-rcwnd.left)/2,newpt.y+(rcwnd.bottom-rcwnd.top)/2);
+ GetCursorPos(&curpt);
+
+ g_pfwFrames[pos].TitleBar.oldpos = curpt;
+
+
+ return(0);
+ };
+
+ };
+
+ //return(0);
+ };
+
+ if (wParam&MK_LBUTTON) {
+ int newh = -1,prevold;
+
+ if (GetCapture() != hwnd){break;};
+
+
+ pos = id2pos(Frameid);
+
+ if (g_pfwFrames[pos].floating)
+ {
+ GetCursorPos(&pt);
+ if ((g_pfwFrames[pos].TitleBar.oldpos.x != pt.x) || (g_pfwFrames[pos].TitleBar.oldpos.y != pt.y))
+ {
+
+ pt2 = pt;
+ ScreenToClient(hwnd,&pt2);
+ GetWindowRect(g_pfwFrames[pos].ContainerWnd,&wndr);
+ {
+ int dX,dY;
+ POINT ptNew;
+
+ ptNew.x = pt.x;
+ ptNew.y = pt.y;
+ //ClientToScreen( hwnd, &ptNew );
+
+ dX = ptNew.x - ptOld.x;
+ dY = ptNew.y - ptOld.y;
+
+ nLeft += (short)dX;
+ nTop += (short)dY;
+
+ if ( !(wParam&MK_CONTROL))
+ {
+ PositionThumb( &g_pfwFrames[pos], nLeft, nTop );
+ }else
+ {
+
+ SetWindowPos( g_pfwFrames[pos].ContainerWnd,
+ HWND_TOPMOST,
+ nLeft,
+ nTop,
+ 0,
+ 0,
+ SWP_NOSIZE |SWP_NOACTIVATE| SWP_NOZORDER );
+ };
+
+ ptOld = ptNew;
+
+
+
+ }
+
+ pt.x = nLeft;
+ pt.y = nTop;
+ g_pfwFrames[pos].TitleBar.oldpos = pt;
+ };
+
+ //break;
+ return(0);
+ };
+
+
+ if (g_pfwFrames[pos].prevvisframe != -1) {
+ GetCursorPos(&pt);
+
+ if ((g_pfwFrames[pos].TitleBar.oldpos.x == pt.x) && (g_pfwFrames[pos].TitleBar.oldpos.y == pt.y))
+ {break;};
+
+ ypos = rect.top+pt.y;xpos = rect.left+pt.x;
+ Framemod = -1;
+
+ if (g_pfwFrames[pos].align == alBottom) {
+ direction = -1;
+ Framemod = pos;
+ }
+ else {
+ direction = 1;
+ Framemod = g_pfwFrames[pos].prevvisframe;
+ }
+ if (g_pfwFrames[Framemod].Locked) {break;};
+ if (s_nCurDragBar != -1 && s_nCurDragBar != pos) {break;};
+
+ if (s_nLastByPos == -1) {
+ s_nCurDragBar = pos;
+ s_nLastByPos = ypos;
+ s_nOldFrameHeight = g_pfwFrames[Framemod].height;
+ SetCapture(hwnd);
+ {break;};
+ }
+ else
+ {
+ // if (GetCapture() != hwnd){break;};
+ };
+
+ newh = s_nOldFrameHeight+direction*(ypos-s_nLastByPos);
+ if (newh>0) {
+ prevold = g_pfwFrames[Framemod].height;
+ g_pfwFrames[Framemod].height = newh;
+ if ( !CLUIFramesFitInSize()) { g_pfwFrames[Framemod].height = prevold; return TRUE;}
+ g_pfwFrames[Framemod].height = newh;
+ if (newh>3) g_pfwFrames[Framemod].collapsed = TRUE;
+
+ }
+ g_pfwFrames[pos].TitleBar.oldpos = pt;
+ }
+
+ if (newh>0)
+ {
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ };
+ break;
+ }
+ s_nCurDragBar = -1;s_nLastByPos = -1;s_nOldFrameHeight = -1;ReleaseCapture();
+ }
+ break;
+ case WM_PRINT:
+ case WM_PRINTCLIENT:
+ {
+ //if (lParam&PRF_CLIENT)
+ {
+ GetClientRect(hwnd,&rect);
+ if ( !g_CluiData.fLayered)
+ {
+ ske_BltBackImage(hwnd,(HDC)wParam,&rect);
+ }
+ DrawTitleBar((HDC)wParam,&rect,Frameid);
+ }
+ break;
+ }
+ case WM_SIZE:
+ {
+ InvalidateRect(hwnd,NULL,FALSE);
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ case WM_PAINT:
+ {
+ HDC paintDC;
+ if (g_pfwFrames[id2pos(Frameid)].floating || (!g_CluiData.fLayered))
+ {
+ GetClientRect(hwnd,&rect);
+ paintDC = GetDC(hwnd);
+ DrawTitleBar(paintDC,&rect,Frameid);
+ ReleaseDC(hwnd,paintDC);
+ ValidateRect(hwnd,NULL);
+
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ default:return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return TRUE;
+}
+static int CLUIFrameResizeFloatingFrame(int framepos)
+{
+
+ int width,height;
+ RECT rect;
+
+ if ( !g_pfwFrames[framepos].floating){return(0);};
+ if (g_pfwFrames[framepos].ContainerWnd == 0){return(0);};
+ GetClientRect(g_pfwFrames[framepos].ContainerWnd,&rect);
+
+ width = rect.right-rect.left;
+ height = rect.bottom-rect.top;
+
+ g_pfwFrames[framepos].visible?CLUI_ShowWindowMod(g_pfwFrames[framepos].ContainerWnd,SW_SHOW/*NOACTIVATE*/):CLUI_ShowWindowMod(g_pfwFrames[framepos].ContainerWnd,SW_HIDE);
+
+
+
+ if (g_pfwFrames[framepos].TitleBar.ShowTitleBar)
+ {
+ CLUI_ShowWindowMod(g_pfwFrames[framepos].TitleBar.hwnd,SW_SHOW/*NOACTIVATE*/);
+ //if (Frames[framepos].Locked){return(0);};
+ g_pfwFrames[framepos].height = height-DEFAULT_TITLEBAR_HEIGHT;
+
+ SetWindowPos(g_pfwFrames[framepos].TitleBar.hwnd,HWND_TOP,0,0,width,DEFAULT_TITLEBAR_HEIGHT,SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_DRAWFRAME);
+ SetWindowPos(g_pfwFrames[framepos].hWnd,HWND_TOP,0,DEFAULT_TITLEBAR_HEIGHT,width,height-DEFAULT_TITLEBAR_HEIGHT,SWP_SHOWWINDOW);
+
+ }
+ else
+ {
+ //SetWindowPos(Frames[framepos].TitleBar.hwnd,HWND_TOP,0,0,width,DEFAULT_TITLEBAR_HEIGHT,SWP_SHOWWINDOW|SWP_NOMOVE);
+ //if (Frames[framepos].Locked){return(0);};
+ g_pfwFrames[framepos].height = height;
+ CLUI_ShowWindowMod(g_pfwFrames[framepos].TitleBar.hwnd,SW_HIDE);
+ SetWindowPos(g_pfwFrames[framepos].hWnd,HWND_TOP,0,0,width,height,SWP_SHOWWINDOW|SWP_NOACTIVATE);
+
+ };
+ // CLUIFramesForceUpdateFrame(&Frames[framepos]);
+ if (g_pfwFrames[framepos].ContainerWnd != 0) UpdateWindow(g_pfwFrames[framepos].ContainerWnd);
+ //GetClientRect(Frames[framepos].TitleBar.hwnd,&Frames[framepos].TitleBar.wndSize);
+ GetWindowRect(g_pfwFrames[framepos].hWnd,&g_pfwFrames[framepos].wndSize);
+ //Frames[framepos].height = Frames[framepos].wndSize.bottom-Frames[framepos].wndSize.top;
+ //GetClientRect(Frames[framepos].hWnd,&Frames[framepos].wndSize);
+ //Frames[framepos].height = Frames[framepos].wndSize.bottom-Frames[framepos].wndSize.top;
+ return(0);
+};
+
+static int CLUIFrameOnMainMenuBuild(WPARAM wParam,LPARAM lParam)
+{
+ if (MirandaExiting()) return 0;
+ CLUIFramesLoadMainMenu();
+
+ return 0;
+}
+
+static LRESULT CALLBACK CLUIFrameSubContainerProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+
+ RECT rect;
+ int Frameid;
+
+ Frameid = (GetWindowLongPtr(hwnd,GWLP_USERDATA));
+ memset(&rect,0,sizeof(rect));
+
+ /*
+ if ((msg == WM_MOVE) || (msg == WM_MOVING) || (msg == WM_NCLBUTTONDOWN) || (msg == WM_SYSCOMMAND) )
+ {
+ if (ServiceExists("Utils/SnapWindowProc"))
+ {
+ SnapWindowProc_t SnapInfo;
+ memset(&SnapInfo,0,sizeof(SnapInfo));
+
+ SnapInfo.hWnd = hwnd;
+ SnapInfo.wParam = wParam;
+ SnapInfo.lParam = lParam;
+ if (CallService("Utils/SnapWindowProc",(WPARAM)&SnapInfo,msg) != 0){return(TRUE);};
+ };
+ };
+ */
+ switch(msg) {
+ case WM_ACTIVATE:
+ {
+ if (g_bTransparentFlag)
+ {
+ BYTE alpha;
+ if ((wParam != WA_INACTIVE || ((HWND)lParam == hwnd) || GetParent((HWND)lParam) == hwnd))
+ {
+ HWND hw = lParam?GetParent((HWND)lParam):0;
+ alpha = db_get_b(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT);
+ if (hw) SetWindowPos(hw,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
+ CLUI_SmoothAlphaTransition(hwnd, alpha, 1);
+ }
+ }
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ case WM_NOTIFY:
+ case WM_PARENTNOTIFY:
+ case WM_SYSCOMMAND:
+ return SendMessage(pcli->hwndContactList,msg,wParam,lParam);
+
+ case WM_MOVE:
+ if (g_CluiData.fDocked) return 1;
+ break;
+
+ case WM_WINDOWPOSCHANGING:
+ {
+ if (g_CluiData.mutexPreventDockMoving)
+ {
+ WINDOWPOS *wp;
+ wp = (WINDOWPOS*)lParam;
+ wp->flags |= SWP_NOMOVE/*|SWP_NOSIZE*/;
+ wp->flags &= (wp->flags&~SWP_NOACTIVATE);
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ break;
+ }
+ case WM_WINDOWPOSCHANGED:
+ {
+ if (g_CluiData.fDocked && g_CluiData.mutexPreventDockMoving)
+ return 0;
+ }
+ break;
+ case WM_NCPAINT:
+ case WM_PAINT:
+ {
+ //ValidateRect(hwnd,NULL);
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ case WM_ERASEBKGND:
+ {
+ return 1;
+ }
+ };
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+};
+
+static HWND CreateSubContainerWindow(HWND parent,int x,int y,int width,int height)
+{
+ HWND hwnd;
+ hwnd = CreateWindowEx(g_proc_SetLayeredWindowAttributesNew ? WS_EX_LAYERED:0,CLUIFrameSubContainerClassName,_T("SubContainerWindow"),WS_POPUP|(!g_CluiData.fLayered ? WS_BORDER : 0),x,y,width,height,parent,0,g_hInst,0);
+ SetWindowLongPtr(hwnd,GWL_STYLE,GetWindowLongPtr(hwnd,GWL_STYLE)&~(WS_CAPTION|WS_BORDER));
+ if (g_CluiData.fOnDesktop)
+ {
+ HWND hProgMan = FindWindow(_T("Progman"),NULL);
+ if (IsWindow(hProgMan))
+ SetParent(hwnd,hProgMan);
+ }
+
+
+ return hwnd;
+};
+
+
+
+static LRESULT CALLBACK CLUIFrameContainerWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+
+ RECT rect;
+ int Frameid;
+
+ Frameid = (GetWindowLongPtr(hwnd,GWLP_USERDATA));
+ memset(&rect,0,sizeof(rect));
+ /*
+ if ((msg == WM_MOVE) || (msg == WM_MOVING) || (msg == WM_NCLBUTTONDOWN) || (msg == WM_SYSCOMMAND) )
+ {
+ if (ServiceExists("Utils/SnapWindowProc"))
+ {
+ SnapWindowProc_t SnapInfo;
+ memset(&SnapInfo,0,sizeof(SnapInfo));
+
+ SnapInfo.hWnd = hwnd;
+ SnapInfo.wParam = wParam;
+ SnapInfo.lParam = lParam;
+ if (CallService("Utils/SnapWindowProc",(WPARAM)&SnapInfo,msg) != 0){return(TRUE);};
+ };
+ };
+ */
+ switch(msg)
+ {
+
+ case WM_CREATE:
+ {
+ int framepos;
+
+ framepos = id2pos(Frameid);
+ //SetWindowPos(Frames[framepos].TitleBar.hwndTip, HWND_TOPMOST,0, 0, 0, 0,SWP_NOMOVE | SWP_NOSIZE );
+
+ return(0);
+ };
+ case WM_GETMINMAXINFO:
+ //DefWindowProc(hwnd,msg,wParam,lParam);
+ {
+ int framepos;
+ MINMAXINFO minmax;
+
+
+ framepos = id2pos(Frameid);
+ if (framepos < 0 || framepos >= g_nFramesCount){break;};
+ if ( !g_pfwFrames[framepos].minmaxenabled){break;};
+ if (g_pfwFrames[framepos].ContainerWnd == 0){break;};
+
+ if (g_pfwFrames[framepos].Locked)
+ {
+ RECT rct;
+
+ GetWindowRect(hwnd,&rct);
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = rct.right-rct.left;
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = rct.bottom-rct.top;
+ ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = rct.right-rct.left;
+ ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = rct.bottom-rct.top;
+ //
+ //return(0);
+ };
+
+
+ memset(&minmax,0,sizeof(minmax));
+ if (SendMessage(g_pfwFrames[framepos].hWnd,WM_GETMINMAXINFO,(WPARAM)0,(LPARAM)&minmax) == 0)
+ {
+ RECT border;
+ int tbh = g_nTitleBarHeight*btoint(g_pfwFrames[framepos].TitleBar.ShowTitleBar);
+ GetBorderSize(hwnd,&border);
+ if (minmax.ptMaxTrackSize.x != 0 && minmax.ptMaxTrackSize.y != 0){
+
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = minmax.ptMinTrackSize.x;
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = minmax.ptMinTrackSize.y;
+ ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = minmax.ptMaxTrackSize.x+border.left+border.right;
+ ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = minmax.ptMaxTrackSize.y+tbh+border.top+border.bottom;
+ };
+
+ }
+ else
+ {
+
+
+ return(DefWindowProc(hwnd, msg, wParam, lParam));
+ };
+
+
+
+ }
+ //return 0;
+
+ case WM_MOVE:
+ {
+ int framepos;
+ RECT rect;
+
+ framepos = id2pos(Frameid);
+
+ if (framepos < 0 || framepos >= g_nFramesCount){break;};
+ if (g_pfwFrames[framepos].ContainerWnd == 0){return(0);};
+
+ GetWindowRect(g_pfwFrames[framepos].ContainerWnd,&rect);
+ g_pfwFrames[framepos].FloatingPos.x = rect.left;
+ g_pfwFrames[framepos].FloatingPos.y = rect.top;
+ g_pfwFrames[framepos].FloatingSize.x = rect.right-rect.left;
+ g_pfwFrames[framepos].FloatingSize.y = rect.bottom-rect.top;
+
+ CLUIFramesStoreFrameSettings(framepos);
+
+ if ( g_pfwFrames[framepos].floating )
+ {
+ POINT curpt,ofspt, newpt, newpos;
+ RECT rcwnd, rcOverlap, rcMiranda;
+
+ GetCursorPos(&curpt);
+ rcwnd.bottom = curpt.y+5;
+ rcwnd.top = curpt.y;
+ rcwnd.left = curpt.x;
+ rcwnd.right = curpt.x+5;
+
+ GetWindowRect(pcli->hwndContactList, &rcMiranda );
+ //GetWindowRect( Frames[pos].ContainerWnd, &rcwnd );
+ //IntersectRect( &rcOverlap, &rcwnd, &rcMiranda )
+
+
+ if (IntersectRect( &rcOverlap, &rcwnd, &rcMiranda ))
+ {
+ GetCursorPos(&curpt);
+ GetWindowRect( g_pfwFrames[framepos].hWnd, &rcwnd );
+ rcwnd.left = rcwnd.right-rcwnd.left;
+ rcwnd.top = rcwnd.bottom-rcwnd.top;
+ newpos.x = curpt.x;newpos.y = curpt.y;
+ if (curpt.x >= (rcMiranda.right-1)){newpos.x = curpt.x+5;};
+ if (curpt.x <= (rcMiranda.left+1)){newpos.x = curpt.x-(rcwnd.left)-5;};
+ if (curpt.y >= (rcMiranda.bottom-1)){newpos.y = curpt.y+5;};
+ if (curpt.y <= (rcMiranda.top+1)){newpos.y = curpt.y-(rcwnd.top)-5;};
+ ofspt.x = 0;ofspt.y = 0;
+ //ClientToScreen(Frames[pos].TitleBar.hwnd,&ofspt);
+ GetWindowRect(g_pfwFrames[framepos].TitleBar.hwnd,&rcwnd);
+ ofspt.x = curpt.x-ofspt.x;ofspt.y = curpt.y-ofspt.y;
+
+ g_pfwFrames[framepos].FloatingPos.x = newpos.x;
+ g_pfwFrames[framepos].FloatingPos.y = newpos.y;
+ CLUIFrames_SetFrameFloat(Frameid,0);
+ //SetWindowPos(Frames[pos].ContainerWnd,0,newpos.x,newpos.y,0,0,SWP_NOSIZE);
+
+
+ newpt.x = 0;newpt.y = 0;
+ ClientToScreen(g_pfwFrames[framepos].TitleBar.hwnd,&newpt);
+
+ GetWindowRect( g_pfwFrames[framepos].hWnd, &rcwnd );
+ SetCursorPos(newpt.x+(rcwnd.right-rcwnd.left)/2,newpt.y+(rcwnd.bottom-rcwnd.top)/2);
+ GetCursorPos(&curpt);
+
+ g_pfwFrames[framepos].TitleBar.oldpos = curpt;
+
+
+ return(0);
+ };
+
+ };
+
+
+ return(0);
+ };
+
+ case WM_SIZE:
+ {
+ int framepos;
+ RECT rect;
+
+ CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
+
+ framepos = id2pos(Frameid);
+
+ if (framepos < 0 || framepos >= g_nFramesCount){break;};
+ if (g_pfwFrames[framepos].ContainerWnd == 0){return(0);};
+ CLUIFrameResizeFloatingFrame(framepos);
+
+ GetWindowRect(g_pfwFrames[framepos].ContainerWnd,&rect);
+ g_pfwFrames[framepos].FloatingPos.x = rect.left;
+ g_pfwFrames[framepos].FloatingPos.y = rect.top;
+ g_pfwFrames[framepos].FloatingSize.x = rect.right-rect.left;
+ g_pfwFrames[framepos].FloatingSize.y = rect.bottom-rect.top;
+
+ CLUIFramesStoreFrameSettings(framepos);
+
+
+ return(0);
+ };
+ case WM_LBUTTONDOWN:
+ {
+ if (db_get_b(NULL,"CLUI","ClientAreaDrag",SETTING_CLIENTDRAG_DEFAULT)) {
+ POINT pt;
+ GetCursorPos(&pt);
+ return SendMessage( hwnd, WM_SYSCOMMAND, SC_MOVE|HTCAPTION,MAKELPARAM(pt.x,pt.y));
+ }
+ break;
+ }
+ case WM_CLOSE:
+ {
+ DestroyWindow(hwnd);
+ break;
+ };
+
+ case WM_DESTROY:
+ {
+ //{ CLUIFramesStoreAllFrames();};
+ return(0);
+ };
+ /*
+ case WM_COMMAND:
+ case WM_NOTIFY:
+ return(SendMessage(pcli->hwndContactList,msg,wParam,lParam));
+ */
+
+
+ };
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+};
+static HWND CreateContainerWindow(HWND parent,int x,int y,int width,int height)
+{
+ return(CreateWindow(_T("FramesContainer"),_T("FramesContainer"),WS_POPUP|WS_THICKFRAME,x,y,width,height,parent,0,g_hInst,0));
+};
+
+
+static int _us_DoSetFrameFloat(WPARAM wParam,LPARAM lParam)
+{
+ HWND hwndtmp,hwndtooltiptmp;
+
+
+ int pos = id2pos( wParam );
+ if ( pos >= 0 && pos < g_nFramesCount )
+
+ if (g_pfwFrames[pos].floating || (lParam&2))
+ {
+ if (g_pfwFrames[pos].OwnerWindow != (HWND)-2 && g_pfwFrames[pos].visible)
+ {
+ if (g_pfwFrames[pos].OwnerWindow == 0) g_pfwFrames[pos].OwnerWindow = CreateSubContainerWindow(pcli->hwndContactList,g_pfwFrames[pos].FloatingPos.x,g_pfwFrames[pos].FloatingPos.y,10,10);
+ CLUI_ShowWindowMod(g_pfwFrames[pos].OwnerWindow,(g_pfwFrames[pos].visible && g_pfwFrames[pos].collapsed && IsWindowVisible(pcli->hwndContactList))?SW_SHOW/*NOACTIVATE*/:SW_HIDE);
+ SetParent(g_pfwFrames[pos].hWnd,g_pfwFrames[pos].OwnerWindow);
+ SetParent(g_pfwFrames[pos].TitleBar.hwnd,pcli->hwndContactList);
+ SetWindowLongPtr(g_pfwFrames[pos].OwnerWindow,GWLP_USERDATA,g_pfwFrames[pos].id);
+ g_pfwFrames[pos].floating = FALSE;
+ if ( !(lParam&2))
+ {
+ DestroyWindow(g_pfwFrames[pos].ContainerWnd);
+ g_pfwFrames[pos].ContainerWnd = 0;
+ }
+ }
+ else
+ {
+ SetParent(g_pfwFrames[pos].hWnd,pcli->hwndContactList);
+ SetParent(g_pfwFrames[pos].TitleBar.hwnd,pcli->hwndContactList);
+ g_pfwFrames[pos].floating = FALSE;
+ if (g_pfwFrames[pos].ContainerWnd) DestroyWindow(g_pfwFrames[pos].ContainerWnd);
+ g_pfwFrames[pos].ContainerWnd = 0;
+ }
+ }
+ else
+ {
+ RECT recttb,rectw,border;
+ int temp;
+ int neww,newh;
+ BOOLEAN locked;
+
+ g_pfwFrames[pos].oldstyles = GetWindowLongPtr(g_pfwFrames[pos].hWnd,GWL_STYLE);
+ g_pfwFrames[pos].TitleBar.oldstyles = GetWindowLongPtr(g_pfwFrames[pos].TitleBar.hwnd,GWL_STYLE);
+ locked = g_pfwFrames[pos].Locked;
+ g_pfwFrames[pos].Locked = FALSE;
+ g_pfwFrames[pos].minmaxenabled = FALSE;
+
+ GetWindowRect(g_pfwFrames[pos].hWnd,&rectw);
+ GetWindowRect(g_pfwFrames[pos].TitleBar.hwnd,&recttb);
+ if ( !g_pfwFrames[pos].TitleBar.ShowTitleBar){
+ recttb.top = recttb.bottom = recttb.left = recttb.right = 0;
+ };
+
+ g_pfwFrames[pos].ContainerWnd = CreateContainerWindow(pcli->hwndContactList,g_pfwFrames[pos].FloatingPos.x,g_pfwFrames[pos].FloatingPos.y,10,10);
+
+
+
+
+ SetParent(g_pfwFrames[pos].hWnd,g_pfwFrames[pos].ContainerWnd);
+ SetParent(g_pfwFrames[pos].TitleBar.hwnd,g_pfwFrames[pos].ContainerWnd);
+ if (g_pfwFrames[pos].OwnerWindow != (HWND)-2 && g_pfwFrames[pos].OwnerWindow != 0)
+ {
+ DestroyWindow(g_pfwFrames[pos].OwnerWindow);
+ g_pfwFrames[pos].OwnerWindow = 0;
+ }
+
+ GetBorderSize(g_pfwFrames[pos].ContainerWnd,&border);
+
+
+ SetWindowLongPtr(g_pfwFrames[pos].ContainerWnd,GWLP_USERDATA,g_pfwFrames[pos].id);
+ if ((lParam == 1))
+ {
+ //if ((Frames[pos].FloatingPos.x != 0) && (Frames[pos].FloatingPos.y != 0))
+ {
+ if (g_pfwFrames[pos].FloatingPos.x < 0){g_pfwFrames[pos].FloatingPos.x = 0;};
+ if (g_pfwFrames[pos].FloatingPos.y < 0){g_pfwFrames[pos].FloatingPos.y = 0;};
+
+ SetWindowPos(g_pfwFrames[pos].ContainerWnd,HWND_TOPMOST,g_pfwFrames[pos].FloatingPos.x,g_pfwFrames[pos].FloatingPos.y,g_pfwFrames[pos].FloatingSize.x,g_pfwFrames[pos].FloatingSize.y,SWP_HIDEWINDOW|SWP_NOACTIVATE);
+ }
+ }
+ else if (lParam == 0)
+ {
+ neww = rectw.right-rectw.left+border.left+border.right;
+ newh = (rectw.bottom-rectw.top)+(recttb.bottom-recttb.top)+border.top+border.bottom;
+ if (neww < 20){neww = 40;};
+ if (newh < 20){newh = 40;};
+ if (g_pfwFrames[pos].FloatingPos.x < 20){g_pfwFrames[pos].FloatingPos.x = 40;};
+ if (g_pfwFrames[pos].FloatingPos.y < 20){g_pfwFrames[pos].FloatingPos.y = 40;};
+
+ SetWindowPos(g_pfwFrames[pos].ContainerWnd,HWND_TOPMOST,g_pfwFrames[pos].FloatingPos.x,g_pfwFrames[pos].FloatingPos.y,neww,newh,SWP_HIDEWINDOW|SWP_NOACTIVATE);
+ };
+
+
+ SetWindowText(g_pfwFrames[pos].ContainerWnd,g_pfwFrames[pos].TitleBar.tbname);
+
+ temp = GetWindowLongPtr(g_pfwFrames[pos].ContainerWnd,GWL_EXSTYLE);
+ temp |= WS_EX_TOOLWINDOW|WS_EX_TOPMOST ;
+ SetWindowLongPtr(g_pfwFrames[pos].ContainerWnd,GWL_EXSTYLE,temp);
+
+ g_pfwFrames[pos].floating = TRUE;
+ g_pfwFrames[pos].Locked = locked;
+
+ }
+ CLUIFramesStoreFrameSettings(pos);
+ g_pfwFrames[pos].minmaxenabled = TRUE;
+ hwndtooltiptmp = g_pfwFrames[pos].TitleBar.hwndTip;
+
+ hwndtmp = g_pfwFrames[pos].ContainerWnd;
+
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,(LPARAM)0);
+ if (hwndtmp) SendMessage(hwndtmp,WM_SIZE,0,0);
+
+
+ SetWindowPos(hwndtooltiptmp, HWND_TOPMOST,0, 0, 0, 0,SWP_NOMOVE | SWP_NOSIZE|SWP_NOACTIVATE );
+
+ return 0;
+}
+
+
+int CLUIFrameOnModulesLoad(WPARAM wParam,LPARAM lParam)
+{
+ /* HOOK */
+ CLUIFramesLoadMainMenu();
+ CLUIFramesCreateMenuForFrame(-1,-1,000010000,Menu_AddContextFrameMenuItem);
+ return 0;
+}
+int CLUIFrameOnModulesUnload(WPARAM wParam,LPARAM lParam)
+{
+ //
+ //if (MirandaExiting()) return 0;
+ if ( !_hmiVisible) return 0;
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiVisible, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiTBVisible, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiLock, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiColl, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiFloating, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiAlignTop, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiAlignClient, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiAlignBottom, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiBorder, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiAlignRoot, 1 );
+
+
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiPosUp, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiPosDown, 1 );
+ CallService( MS_CLIST_REMOVECONTEXTFRAMEMENUITEM, ( LPARAM )_hmiPosRoot, 1 );
+
+
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiVisible, 1 );
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiTBVisible, 1 );
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiLock, 1 );
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiColl, 1 );
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiFloating, 1 );
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiBorder, 1 );
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiAlignRoot, 1 );
+ CallService( MO_REMOVEMENUITEM, ( LPARAM )_hmiPosRoot, 1 );
+
+ _hmiVisible = 0;
+ return 0;
+}
+
+int LoadCLUIFramesModule(void)
+{
+ WNDCLASS wndclass;
+ WNDCLASS cntclass;
+ WNDCLASS subconclass;
+ InitializeCriticalSection(&_cluiFramesModuleCS);
+ _cluiFramesModuleCSInitialized = TRUE;
+
+ wndclass.style = CS_DBLCLKS;//|CS_HREDRAW|CS_VREDRAW ;
+ wndclass.lpfnWndProc = CLUIFrameTitleBarProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = CLUIFrameTitleBarClassName;
+ RegisterClass(&wndclass);
+
+ subconclass.style = CS_DBLCLKS;//|CS_HREDRAW|CS_VREDRAW ;
+ subconclass.lpfnWndProc = CLUIFrameSubContainerProc;
+ subconclass.cbClsExtra = 0;
+ subconclass.cbWndExtra = 0;
+ subconclass.hInstance = g_hInst;
+ subconclass.hIcon = NULL;
+ subconclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ subconclass.hbrBackground = NULL;
+ subconclass.lpszMenuName = NULL;
+ subconclass.lpszClassName = CLUIFrameSubContainerClassName;
+ RegisterClass(&subconclass);
+
+ //container helper
+
+ cntclass.style = CS_DBLCLKS/*|CS_HREDRAW|CS_VREDRAW*/|( IsWinVerXPPlus() ? CS_DROPSHADOW : 0);
+ cntclass.lpfnWndProc = CLUIFrameContainerWndProc;
+ cntclass.cbClsExtra = 0;
+ cntclass.cbWndExtra = 0;
+ cntclass.hInstance = g_hInst;
+ cntclass.hIcon = NULL;
+ cntclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ cntclass.hbrBackground = NULL;
+ cntclass.lpszMenuName = NULL;
+ cntclass.lpszClassName = _T("FramesContainer");
+ RegisterClass(&cntclass);
+ //end container helper
+
+ GapBetweenFrames = db_get_dw(NULL,"CLUIFrames","GapBetweenFrames",SETTING_GAPFRAMES_DEFAULT);
+
+ g_nFramesCount = 0;
+
+ InitFramesMenus();
+
+ HookEvent(ME_SYSTEM_MODULESLOADED,CLUIFrameOnModulesLoad);
+ HookEvent(ME_CLIST_PREBUILDFRAMEMENU,CLUIFramesModifyContextMenuForFrame);
+ HookEvent(ME_CLIST_PREBUILDMAINMENU,CLUIFrameOnMainMenuBuild);
+ HookEvent(ME_SYSTEM_PRESHUTDOWN, CLUIFrameOnModulesUnload);
+
+ CreateCluiFramesServices();
+
+
+ hWndExplorerToolBar = FindWindowEx(0,0,_T("Shell_TrayWnd"),NULL);
+ OnFrameTitleBarBackgroundChange(0,0);
+ _fCluiFramesModuleNotStarted = FALSE;
+ return 0;
+}
+
+static INT_PTR UnloadMainMenu()
+{
+ CLUIFrameOnModulesUnload(0,0);
+ if (_hmiRoot != (HANDLE)-1)
+ {
+ CallService(MS_CLIST_REMOVEMAINMENUITEM,(WPARAM)_hmiRoot,0);
+ _hmiRoot = (HGENMENU)-1;
+ }
+
+ return (INT_PTR) _hmiRoot;
+}
+
+int UnLoadCLUIFramesModule(void)
+{
+ int i;
+
+ _fCluiFramesModuleNotStarted = TRUE;
+ if (hBmpBackground) {DeleteObject(hBmpBackground); hBmpBackground = NULL;}
+ CLUIFramesOnClistResize((WPARAM)pcli->hwndContactList,0);
+ CLUIFramesStoreAllFrames();
+
+
+ UnitFramesMenu();
+ UnloadMainMenu();
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if (g_pfwFrames[i].hWnd != pcli->hwndContactTree)
+ DestroyWindow(g_pfwFrames[i].hWnd);
+
+ g_pfwFrames[i].hWnd = (HWND)-1;
+ DestroyWindow(g_pfwFrames[i].TitleBar.hwnd);
+ g_pfwFrames[i].TitleBar.hwnd = (HWND)-1;
+ if (g_pfwFrames[i].ContainerWnd && g_pfwFrames[i].ContainerWnd != (HWND)(-2) && g_pfwFrames[i].ContainerWnd != (HWND)(-1)) DestroyWindow(g_pfwFrames[i].ContainerWnd);
+ g_pfwFrames[i].ContainerWnd = (HWND)-1;
+ if (g_pfwFrames[i].TitleBar.hmenu) DestroyMenu(g_pfwFrames[i].TitleBar.hmenu);
+ if (g_pfwFrames[i].OwnerWindow && g_pfwFrames[i].OwnerWindow != (HWND)(-2) && g_pfwFrames[i].OwnerWindow != (HWND)(-1))
+ DestroyWindow(g_pfwFrames[i].OwnerWindow );
+ g_pfwFrames[i].OwnerWindow = (HWND)-2;
+ if (g_pfwFrames[i].UpdateRgn) DeleteObject(g_pfwFrames[i].UpdateRgn);
+
+ mir_free_and_nil(g_pfwFrames[i].Name);
+ mir_free_and_nil(g_pfwFrames[i].szName);
+ mir_free_and_nil(g_pfwFrames[i].TitleBar.tbname);
+ mir_free_and_nil(g_pfwFrames[i].TitleBar.sztbname);
+ mir_free_and_nil(g_pfwFrames[i].TitleBar.tooltip);
+ mir_free_and_nil(g_pfwFrames[i].TitleBar.sztooltip);
+
+ }
+ if (g_pfwFrames) free(g_pfwFrames);
+ g_pfwFrames = NULL;
+ g_nFramesCount = 0;
+ UnregisterClass(CLUIFrameTitleBarClassName,g_hInst);
+ DeleteObject(_hTitleBarFont);
+
+ _cluiFramesModuleCSInitialized = FALSE;
+ DeleteCriticalSection(&_cluiFramesModuleCS);
+ return 0;
+}
+
+static int _us_DoSetFramePaintProc(WPARAM wParam, LPARAM lParam)
+{
+ if ( !wParam) return 0;
+ {
+ // LOOK REQUIRED OR SYNC CALL NEEDED
+ FRAMEWND *frm = FindFrameByItsHWND((HWND)wParam);
+ if ( !frm) return 0;
+ if (lParam)
+ frm->PaintCallbackProc = (tPaintCallbackProc)lParam;
+ else
+ frm->PaintCallbackProc = NULL;
+ return 1;
+ }
+}
+int CLUIFrames_SetLayeredMode( BOOL fLayeredMode, HWND hwnd )
+{
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ {
+ if (fLayeredMode)
+ {
+ if (g_pfwFrames[i].visible && GetParent(g_pfwFrames[i].hWnd) == pcli->hwndContactList && g_pfwFrames[i].PaintCallbackProc == NULL)
+ {
+ //create owner window
+ g_pfwFrames[i].OwnerWindow = CreateSubContainerWindow(pcli->hwndContactList,g_pfwFrames[i].FloatingPos.x,g_pfwFrames[i].FloatingPos.y,10,10);
+ SetParent(g_pfwFrames[i].hWnd,g_pfwFrames[i].OwnerWindow);
+ }
+ }
+ else
+ {
+ if (GetParent(g_pfwFrames[i].hWnd) == g_pfwFrames[i].OwnerWindow)
+ {
+ SetParent(g_pfwFrames[i].hWnd,hwnd);
+ if ((INT_PTR)g_pfwFrames[i].OwnerWindow>0)
+ {
+ DestroyWindow(g_pfwFrames[i].OwnerWindow);
+ g_pfwFrames[i].OwnerWindow = (HWND)-2;
+ }
+ }
+ }
+ }
+
+ CLUIFrames_UpdateFrame((WPARAM)-1,0); //update all frames
+ return 0;
+}
+
+int CLUIFrames_UpdateBorders()
+{
+ for ( int i=0; i < g_nFramesCount; i++ )
+ {
+ if ( !g_pfwFrames[i].floating )
+ {
+ DWORD style = (int)GetWindowLongPtr( g_pfwFrames[i].hWnd, GWL_STYLE ) & ( ~WS_BORDER );
+ if ( !g_CluiData.fLayered && g_pfwFrames[i].UseBorder ) style |= WS_BORDER;
+ SetWindowLongPtr( g_pfwFrames[i].hWnd, GWL_STYLE, style );
+ CLUIFramesModifyMainMenuItems( g_pfwFrames[i].id, 0 );
+ RedrawWindow( g_pfwFrames[i].hWnd, NULL, NULL, RDW_FRAME | RDW_INVALIDATE );
+ };
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_cluiservices.cpp b/plugins/Clist_modern/src/modern_cluiservices.cpp
new file mode 100644
index 0000000000..0b48b0ec47
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_cluiservices.cpp
@@ -0,0 +1,178 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "m_clui.h"
+#include "hdr/modern_commonprototypes.h"
+
+INT_PTR CListTray_GetGlobalStatus(WPARAM wparam,LPARAM lparam);
+
+int CLUIUnreadEmailCountChanged(WPARAM wParam,LPARAM lParam)
+{
+ CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE, 0 ,0);
+ return 0;
+}
+
+INT_PTR CLUIServices_ProtocolStatusChanged(WPARAM wParam,LPARAM lParam)
+{
+ CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,(WPARAM)pcli->hwndStatus,0);
+ if (lParam) cliTrayIconUpdateBase((char*)lParam);
+ return 0;
+}
+
+void cliCluiProtocolStatusChanged(int status,const char * proto)
+{
+ CLUIServices_ProtocolStatusChanged((WPARAM)status,(LPARAM)proto);
+}
+
+INT_PTR SortList(WPARAM wParam,LPARAM lParam)
+{
+ pcli->pfnClcBroadcast( WM_TIMER,TIMERID_DELAYEDRESORTCLC,0);
+ pcli->pfnClcBroadcast( INTM_SCROLLBARCHANGED,0,0);
+
+ return 0;
+}
+
+static INT_PTR MetaSupportCheck(WPARAM wParam,LPARAM lParam)
+{
+ return 1;
+}
+
+static INT_PTR GetHwnd(WPARAM wParam, LPARAM lParam)
+{
+ return (INT_PTR)pcli->hwndContactList;
+}
+
+static INT_PTR GetHwndTree(WPARAM wParam,LPARAM lParam)
+{
+ return (INT_PTR)pcli->hwndContactTree;
+}
+
+static INT_PTR GroupAdded(WPARAM wParam, LPARAM lParam)
+{
+ //CLC does this automatically unless it's a new group
+ if (lParam) {
+ HANDLE hItem;
+ TCHAR szFocusClass[64];
+ HWND hwndFocus = GetFocus();
+
+ GetClassName(hwndFocus, szFocusClass, SIZEOF(szFocusClass));
+ if ( !lstrcmp(szFocusClass, CLISTCONTROL_CLASS)) {
+ hItem = (HANDLE) SendMessage(hwndFocus, CLM_FINDGROUP, wParam, 0);
+ if (hItem)
+ SendMessage(hwndFocus, CLM_EDITLABEL, (WPARAM) hItem, 0);
+ }
+ }
+ return 0;
+}
+
+static INT_PTR ContactSetIcon(WPARAM wParam, LPARAM lParam)
+{
+ //unnecessary: CLC does this automatically
+ return 0;
+}
+
+static INT_PTR ContactDeleted(WPARAM wParam, LPARAM lParam)
+{
+ //unnecessary: CLC does this automatically
+ return 0;
+}
+
+static INT_PTR ContactAdded(WPARAM wParam, LPARAM lParam)
+{
+ //unnecessary: CLC does this automatically
+ return 0;
+}
+
+static INT_PTR ListBeginRebuild(WPARAM wParam, LPARAM lParam)
+{
+ //unnecessary: CLC does this automatically
+ return 0;
+}
+
+static INT_PTR ContactRenamed(WPARAM wParam, LPARAM lParam)
+{
+ //unnecessary: CLC does this automatically
+ return 0;
+}
+
+static INT_PTR ListEndRebuild(WPARAM wParam, LPARAM lParam)
+{
+ int rebuild = 0;
+ //CLC does this automatically, but we need to force it if hideoffline or hideempty has changed
+ if ((db_get_b(NULL, "CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT) == 0) != ((GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & CLS_HIDEOFFLINE) == 0)) {
+ if (db_get_b(NULL, "CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT))
+ SetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) | CLS_HIDEOFFLINE);
+ else
+ SetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & ~CLS_HIDEOFFLINE);
+ rebuild = 1;
+ }
+ if ((db_get_b(NULL, "CList", "HideEmptyGroups", SETTING_HIDEEMPTYGROUPS_DEFAULT) == 0) != ((GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & CLS_HIDEEMPTYGROUPS) == 0)) {
+ if (db_get_b(NULL, "CList", "HideEmptyGroups", SETTING_HIDEEMPTYGROUPS_DEFAULT))
+ SetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) | CLS_HIDEEMPTYGROUPS);
+ else
+ SetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & ~CLS_HIDEEMPTYGROUPS);
+ rebuild = 1;
+ }
+ if ((db_get_b(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT) == 0) != ((GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & CLS_USEGROUPS) == 0)) {
+ if (db_get_b(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT))
+ SetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) | CLS_USEGROUPS);
+ else
+ SetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE, GetWindowLongPtr(pcli->hwndContactTree, GWL_STYLE) & ~CLS_USEGROUPS);
+ rebuild = 1;
+ }
+ if (rebuild)
+ SendMessage(pcli->hwndContactTree, CLM_AUTOREBUILD, 0, 0);
+ return 0;
+}
+
+static int GetCaps(WPARAM wParam, LPARAM lParam)
+{
+ switch (wParam) {
+ case CLUICAPS_FLAGS1:
+ return CLUIF_HIDEEMPTYGROUPS | CLUIF_DISABLEGROUPS | CLUIF_HASONTOPOPTION | CLUIF_HASAUTOHIDEOPTION;
+ }
+ return 0;
+}
+
+
+
+int CLUIServices_LoadModule(void)
+{
+ CreateServiceFunction(MS_CLUI_METASUPPORT,MetaSupportCheck);
+ CreateServiceFunction(MS_CLUI_PROTOCOLSTATUSCHANGED,CLUIServices_ProtocolStatusChanged);
+ CreateServiceFunction(MS_CLUI_SORTLIST,SortList);
+ CreateServiceFunction(MS_CLIST_GETSTATUSMODE,CListTray_GetGlobalStatus);
+
+ CreateServiceFunction(MS_CLUI_GETHWND, GetHwnd);
+ CreateServiceFunction(MS_CLUI_GETHWNDTREE,GetHwndTree);
+ CreateServiceFunction(MS_CLUI_GROUPADDED, GroupAdded);
+ CreateServiceFunction(MS_CLUI_CONTACTSETICON, ContactSetIcon);
+ CreateServiceFunction(MS_CLUI_CONTACTADDED, ContactAdded);
+ CreateServiceFunction(MS_CLUI_CONTACTDELETED, ContactDeleted);
+ CreateServiceFunction(MS_CLUI_CONTACTRENAMED, ContactRenamed);
+ CreateServiceFunction(MS_CLUI_LISTBEGINREBUILD, ListBeginRebuild);
+ CreateServiceFunction(MS_CLUI_LISTENDREBUILD, ListEndRebuild);
+ return 0;
+}
+
diff --git a/plugins/Clist_modern/src/modern_commonheaders.cpp b/plugins/Clist_modern/src/modern_commonheaders.cpp
new file mode 100644
index 0000000000..45c2709d2b
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_commonheaders.cpp
@@ -0,0 +1,247 @@
+#define DB_USEHELPERFUNCTIONS
+#include "hdr/modern_commonheaders.h"
+
+BYTE gl_TrimText = 1;
+
+char * __cdecl strstri( char *a, const char *b)
+{
+ char * x, *y;
+ if ( !a || !b) return FALSE;
+ x = _strdup(a);
+ y = _strdup(b);
+ x = _strupr(x);
+ y = _strupr(y);
+ char * pos = strstr(x,y);
+ if ( pos )
+ {
+ char * retval = a + ( pos - x );
+ free(x);
+ free(y);
+ return retval;
+ }
+ free(x);
+ free(y);
+ return NULL;
+}
+int __cdecl mir_strcmpi(const char *a, const char *b)
+{
+ if (a == NULL && b == NULL) return 0;
+ if (a == NULL || b == NULL) return _stricmp(a?a:"",b?b:"");
+ return _stricmp(a,b);
+}
+
+int __cdecl mir_tstrcmpi(const TCHAR *a, const TCHAR *b)
+{
+ if (a == NULL && b == NULL) return 0;
+ if (a == NULL || b == NULL) return _tcsicmp(a?a:_T(""),b?b:_T(""));
+ return _tcsicmp(a,b);
+}
+BOOL __cdecl mir_bool_strcmpi(const char *a, const char *b)
+{
+ if (a == NULL && b == NULL) return 1;
+ if (a == NULL || b == NULL) return _stricmp(a?a:"",b?b:"") == 0;
+ return _stricmp(a,b) == 0;
+}
+
+BOOL __cdecl mir_bool_tstrcmpi(const TCHAR *a, const TCHAR *b)
+{
+ if (a == NULL && b == NULL) return 1;
+ if (a == NULL || b == NULL) return _tcsicmp(a?a:_T(""),b?b:_T("")) == 0;
+ return _tcsicmp(a,b) == 0;
+}
+
+#ifdef strlen
+#undef strcmp
+#undef strlen
+#endif
+
+int __cdecl mir_strcmp (const char *a, const char *b)
+{
+ if ( !(a && b)) return a != b;
+ return (strcmp(a,b));
+};
+
+int mir_strlen (const char *a)
+{
+ if (a == NULL) return 0;
+ return (int)(strlen(a));
+};
+
+#define strlen(a) mir_strlen(a)
+#define strcmp(a,b) mir_strcmp(a,b)
+
+/*
+__inline void *mir_calloc( size_t num, size_t size )
+{
+ void *p = mir_alloc(num*size);
+ if (p == NULL) return NULL;
+ memset(p,0,num*size);
+ return p;
+};
+*/
+wchar_t * mir_strdupW(const wchar_t * src)
+{
+ wchar_t * p;
+ if (src == NULL) return NULL;
+ p = (wchar_t *) mir_alloc((lstrlenW(src)+1)*sizeof(wchar_t));
+ if ( !p) return 0;
+ lstrcpyW(p, src);
+ return p;
+}
+
+//copy len symbols from string - do not check is it null terminated or len is more then actual
+char * strdupn(const char * src, int len)
+{
+ char * p;
+ if (src == NULL) return NULL;
+ p = (char*)malloc(len+1);
+ if ( !p) return 0;
+ memcpy(p,src,len);
+ p[len] = '\0';
+ return p;
+}
+
+DWORD exceptFunction(LPEXCEPTION_POINTERS EP)
+{
+ //printf("1 "); // printed first
+ char buf[4096];
+
+
+ mir_snprintf(buf, SIZEOF(buf), "\r\nExceptCode: %x\r\nExceptFlags: %x\r\nExceptAddress: %p\r\n",
+ EP->ExceptionRecord->ExceptionCode,
+ EP->ExceptionRecord->ExceptionFlags,
+ EP->ExceptionRecord->ExceptionAddress
+ );
+ TRACE(buf);
+ MessageBoxA(0,buf,"clist_mw Exception",0);
+
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+#ifdef _DEBUG
+#undef DeleteObject
+#endif
+
+void TRACE_ERROR()
+{
+ DWORD t = GetLastError();
+ LPVOID lpMsgBuf;
+ if ( !FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ t,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL ))
+ {
+ // Handle the error.
+ return ;
+ }
+#ifdef _DEBUG
+ MessageBox( NULL, (LPCTSTR)lpMsgBuf, _T("Error"), MB_OK | MB_ICONINFORMATION );
+ DebugBreak();
+#endif
+ LocalFree( lpMsgBuf );
+
+}
+
+BOOL DebugDeleteObject(HGDIOBJ a)
+{
+ BOOL res = DeleteObject(a);
+ if ( !res) TRACE_ERROR();
+ return res;
+}
+
+BOOL mod_DeleteDC(HDC hdc)
+{
+// ske_ResetTextEffect(hdc);
+ return DeleteDC(hdc);
+}
+#ifdef _DEBUG
+#define DeleteObject(a) DebugDeleteObject(a)
+#endif
+
+
+// load small icon (shared) it's not need to be destroyed
+
+HICON LoadSmallIconShared(HINSTANCE hInstance, LPCTSTR lpIconName)
+{
+ int cx = GetSystemMetrics(SM_CXSMICON);
+ return (HICON)LoadImage(hInstance,lpIconName, IMAGE_ICON,cx,cx, LR_DEFAULTCOLOR|LR_SHARED);
+}
+
+// load small icon (not shared) it IS NEED to be destroyed
+HICON LoadSmallIcon(HINSTANCE hInstance, LPCTSTR lpIconName)
+{
+ HICON hIcon = NULL; // icon handle
+ int index = -(int)lpIconName;
+ TCHAR filename[MAX_PATH] = {0};
+ GetModuleFileName(hInstance,filename,MAX_PATH);
+ ExtractIconEx(filename,index,NULL,&hIcon,1);
+ return hIcon;
+}
+
+// load small icon from hInstance
+HICON LoadIconEx(HINSTANCE hInstance, LPCTSTR lpIconName, BOOL bShared)
+{
+ HICON hResIcon = bShared?LoadSmallIcon(hInstance,lpIconName):LoadSmallIconShared(hInstance,lpIconName);
+ if ( !hResIcon) //Icon not found in hInstance lets try to load it from core
+ {
+ HINSTANCE hCoreInstance = GetModuleHandle(NULL);
+ if (hCoreInstance != hInstance)
+ hResIcon = bShared?LoadSmallIcon(hInstance,lpIconName):LoadSmallIconShared(hInstance,lpIconName);
+ }
+ return hResIcon;
+}
+
+BOOL DestroyIcon_protect(HICON icon)
+{
+ if (icon) return DestroyIcon(icon);
+ return FALSE;
+}
+
+void li_ListDestruct(SortedList *pList, ItemDestuctor pItemDestructor)
+{
+ int i=0;
+ if ( !pList) return;
+ for (i=0; i < pList->realCount; i++) pItemDestructor(pList->items[i]);
+ List_Destroy(pList);
+ mir_free(pList);
+}
+
+void li_RemoveDestruct(SortedList *pList, int index, ItemDestuctor pItemDestructor)
+{
+ if (index >= 0 && index < pList->realCount)
+ {
+ pItemDestructor(pList->items[index]);
+ List_Remove(pList, index);
+ }
+}
+
+void li_RemovePtrDestruct(SortedList *pList, void * ptr, ItemDestuctor pItemDestructor)
+{
+ if (List_RemovePtr(pList, ptr))
+ pItemDestructor(ptr);
+}
+
+void li_SortList(SortedList *pList, FSortFunc pSortFunct)
+{
+ FSortFunc pOldSort = pList->sortFunc;
+ int i;
+ if ( !pSortFunct) pSortFunct = pOldSort;
+ pList->sortFunc = NULL;
+ for (i=0; i < pList->realCount-1; i++)
+ if (pOldSort(pList->items[i],pList->items[i+1]) < 0)
+ {
+ void * temp = pList->items[i];
+ pList->items[i] = pList->items[i+1];
+ pList->items[i+1] = temp;
+ i--;
+ if (i>0) i--;
+ }
+ pList->sortFunc = pOldSort;
+}
diff --git a/plugins/Clist_modern/src/modern_contact.cpp b/plugins/Clist_modern/src/modern_contact.cpp
new file mode 100644
index 0000000000..7b1ba95544
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_contact.cpp
@@ -0,0 +1,219 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "hdr/modern_commonprototypes.h"
+
+struct
+{
+ int m_cache_nStatus,order;
+} statusModeOrder[] = {
+ {ID_STATUS_OFFLINE,500},
+ {ID_STATUS_ONLINE,10},
+ {ID_STATUS_AWAY,200},
+ {ID_STATUS_DND,110},
+ {ID_STATUS_NA,450},
+ {ID_STATUS_OCCUPIED,100},
+ {ID_STATUS_FREECHAT,0},
+ {ID_STATUS_INVISIBLE,20},
+ {ID_STATUS_ONTHEPHONE,150},
+ {ID_STATUS_OUTTOLUNCH,425}};
+
+static int GetContactStatus(HANDLE hContact)
+{
+ return (GetContactCachedStatus(hContact));
+}
+
+
+void cli_ChangeContactIcon(HANDLE hContact,int iIcon,int add)
+{
+ corecli.pfnChangeContactIcon((HANDLE) hContact,(int) iIcon,(int) add);
+}
+
+static int GetStatusModeOrdering(int statusMode)
+{
+ int i;
+ for (i=0;i < SIZEOF(statusModeOrder);i++)
+ if (statusModeOrder[i].m_cache_nStatus == statusMode) return statusModeOrder[i].order;
+ return 1000;
+}
+
+
+DWORD CompareContacts2_getLMTime(HANDLE hContact)
+{
+ HANDLE hDbEvent;
+ DBEVENTINFO dbei = {0};
+
+ hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDLAST, (WPARAM)hContact, 0);
+ while(hDbEvent) {
+ dbei.cbSize = sizeof(dbei);
+ dbei.pBlob = 0;
+ dbei.cbBlob = 0;
+ CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei);
+ if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT))
+ return dbei.timestamp;
+ hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDPREV, (WPARAM)hDbEvent, 0);
+ }
+ return 0;
+}
+
+#define SAFESTRING(a) a?a:""
+#define SAFETSTRING(a) a?a:_T("")
+
+int GetProtoIndex(char * szName)
+{
+ PROTOACCOUNT **accs = NULL;
+ int accCount = 0;
+ int i;
+ if ( !szName) return -1;
+ ProtoEnumAccounts( &accCount, &accs );
+ for (i=0; i < accCount; i++)
+ if ( !mir_strcmpi(szName,accs[i]->szModuleName))
+ return accs[i]->iOrder;
+ return -1;
+}
+
+int CompareContacts2(const struct ClcContact *contact1,const struct ClcContact *contact2, int by)
+{
+
+ HANDLE a;
+ HANDLE b;
+ TCHAR *namea, *nameb;
+ int statusa,statusb;
+ char *szProto1,*szProto2;
+
+ if ((INT_PTR)contact1 < 100 || (INT_PTR)contact2 < 100) return 0;
+
+ a = contact1->hContact;
+ b = contact2->hContact;
+
+ namea = (TCHAR *)contact1->szText;
+ statusa = GetContactCachedStatus(contact1->hContact);
+ szProto1 = contact1->proto;
+
+ nameb = (TCHAR *)contact2->szText;
+ statusb = GetContactCachedStatus(contact2->hContact);
+ szProto2 = contact2->proto;
+
+
+ if (by == SORTBY_STATUS)
+ { //status
+ int ordera,orderb;
+ ordera = GetStatusModeOrdering(statusa);
+ orderb = GetStatusModeOrdering(statusb);
+ if (ordera != orderb) return ordera-orderb;
+ else return 0;
+ }
+
+
+ if (g_CluiData.fSortNoOfflineBottom == 0 && (statusa == ID_STATUS_OFFLINE) != (statusb == ID_STATUS_OFFLINE)) { //one is offline: offline goes below online
+ return 2*(statusa == ID_STATUS_OFFLINE)-1;
+ }
+
+ if (by == SORTBY_NAME)
+ { //name
+ return mir_tstrcmpi(namea,nameb);
+ }
+ if (by == SORTBY_NAME_LOCALE)
+ { //name
+ static int LocaleId = -1;
+ if (LocaleId == -1) LocaleId = CallService(MS_LANGPACK_GETLOCALE,0,0);
+ return (CompareString(LocaleId,NORM_IGNORECASE,SAFETSTRING(namea),-1,SAFETSTRING(nameb),-1))-2;
+ }
+ else if (by == SORTBY_LASTMSG)
+ { //last message
+ DWORD ta = CompareContacts2_getLMTime(a);
+ DWORD tb = CompareContacts2_getLMTime(b);
+ return tb-ta;
+ }
+ else if (by == SORTBY_PROTO)
+ {
+ int rc = GetProtoIndex(szProto1)-GetProtoIndex(szProto2);
+
+ if (rc != 0 && (szProto1 != NULL && szProto2 != NULL)) return rc;
+ }
+ else if (by == SORTBY_RATE)
+ return contact2->bContactRate-contact1->bContactRate;
+ // else :o)
+ return 0;
+}
+
+int cliCompareContacts(const struct ClcContact *contact1,const struct ClcContact *contact2)
+{
+ int i, r;
+ for (i=0; i < SIZEOF(g_CluiData.bSortByOrder); i++)
+ {
+ r = CompareContacts2(contact1, contact2, g_CluiData.bSortByOrder[i]);
+ if (r != 0)
+ return r;
+ }
+ return 0;
+}
+
+#undef SAFESTRING
+
+INT_PTR ContactChangeGroup(WPARAM wParam,LPARAM lParam)
+{
+ CallService(MS_CLUI_CONTACTDELETED,wParam,0);
+ if ((HANDLE)lParam == NULL)
+ db_unset((HANDLE)wParam,"CList","Group");
+ else
+ db_set_ws((HANDLE)wParam,"CList","Group",pcli->pfnGetGroupName(lParam, NULL));
+ CallService(MS_CLUI_CONTACTADDED,wParam,ExtIconFromStatusMode((HANDLE)wParam,(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,wParam,0),GetContactStatus((HANDLE)wParam)));
+ return 0;
+}
+
+INT_PTR ToggleHideOffline(WPARAM wParam,LPARAM lParam)
+{
+ return pcli->pfnSetHideOffline((WPARAM)-1,0);
+}
+
+INT_PTR ToggleGroups(WPARAM wParam,LPARAM lParam)
+{
+
+ db_set_b(NULL, "CList", "UseGroups",
+ (BYTE) !db_get_b(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT));
+ pcli->pfnLoadContactTree();
+ return 0;
+}
+
+INT_PTR SetUseGroups(WPARAM wParam, LPARAM lParam)
+{
+ int newVal = !(GetWindowLongPtr(pcli->hwndContactTree,GWL_STYLE)&CLS_USEGROUPS);
+ if ( wParam != -1 )
+ {
+ if ( !newVal == wParam ) return 0;
+ newVal = wParam;
+ }
+ db_set_b(NULL,"CList","UseGroups",(BYTE)newVal);
+ SendMessage(pcli->hwndContactTree,CLM_SETUSEGROUPS,newVal,0);
+ return 0;
+}
+
+INT_PTR ToggleSounds(WPARAM wParam,LPARAM lParam)
+{
+ db_set_b(NULL, "Skin", "UseSound",
+ (BYTE) !db_get_b(NULL, "Skin", "UseSound", SETTING_ENABLESOUNDS_DEFAULT ));
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_docking.cpp b/plugins/Clist_modern/src/modern_docking.cpp
new file mode 100644
index 0000000000..e05de26096
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_docking.cpp
@@ -0,0 +1,372 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_clist.h"
+#include "m_api/m_skin_eng.h"
+#include "m_api/m_skinbutton.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_sync.h"
+
+#define WM_DOCKCALLBACK (WM_USER+121)
+#define WM_CREATEDOCKED (WM_USER+122)
+#define EDGESENSITIVITY 3
+
+#define DOCKED_NONE 0
+#define DOCKED_LEFT 1
+#define DOCKED_RIGHT 2
+
+BOOL LockSubframeMoving = 0;
+static int TempDock = 0;
+static int dock_drag_dx = 0;
+static int dock_drag_dy = 0;
+
+static void Docking_GetMonitorRectFromPoint(POINT pt,RECT *rc)
+{
+ HMODULE hUserInstance = GetModuleHandle(_T("user32"));
+
+ if ( MyMonitorFromPoint )
+ {
+ MONITORINFO monitorInfo;
+ HMONITOR hMonitor = MyMonitorFromPoint(pt,MONITOR_DEFAULTTONEAREST); // always returns a valid value
+ monitorInfo.cbSize = sizeof(MONITORINFO);
+
+ if ( MyGetMonitorInfo(hMonitor,&monitorInfo))
+ {
+ CopyMemory(rc,&monitorInfo.rcMonitor,sizeof(RECT));
+ return;
+ }
+ }
+
+ // "generic" win95/NT support, also serves as failsafe
+ rc->left = 0;
+ rc->top = 0;
+ rc->bottom = GetSystemMetrics(SM_CYSCREEN);
+ rc->right = GetSystemMetrics(SM_CXSCREEN);
+}
+
+void Docking_GetMonitorRectFromWindow(HWND hWnd,RECT *rc)
+{
+ POINT ptWindow;
+ GetWindowRect(hWnd,rc);
+ ptWindow.x = rc->left;
+ ptWindow.y = rc->top;
+ Docking_GetMonitorRectFromPoint(ptWindow,rc);
+}
+
+static void Docking_AdjustPosition(HWND hwnd,RECT *rcDisplay,RECT *rc)
+{
+ APPBARDATA abd;
+
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = hwnd;
+ abd.uEdge = g_CluiData.fDocked == DOCKED_LEFT?ABE_LEFT:ABE_RIGHT;
+ abd.rc = *rc;
+ abd.rc.top = rcDisplay->top;
+ abd.rc.bottom = rcDisplay->bottom;
+ if (g_CluiData.fDocked == DOCKED_LEFT) {
+ abd.rc.right = rcDisplay->left+abd.rc.right-abd.rc.left;
+ abd.rc.left = rcDisplay->left;
+ }
+ else {
+ abd.rc.left = rcDisplay->right-(abd.rc.right-abd.rc.left);
+ abd.rc.right = rcDisplay->right;
+
+ }
+ SHAppBarMessage(ABM_SETPOS,&abd);
+ *rc = abd.rc;
+}
+
+int Docking_IsDocked(WPARAM wParam,LPARAM lParam)
+{
+ return g_CluiData.fDocked;
+}
+
+int Docking_ProcessWindowMessage(WPARAM wParam,LPARAM lParam)
+{
+ APPBARDATA abd;
+ static int draggingTitle;
+ MSG *msg = (MSG*)wParam;
+
+ if (msg->message == WM_DESTROY)
+ db_set_b(NULL,"CList","Docked",(BYTE)g_CluiData.fDocked);
+
+ if ( !g_CluiData.fDocked && msg->message != WM_CREATE && msg->message != WM_MOVING && msg->message != WM_CREATEDOCKED && msg->message != WM_MOVE && msg->message != WM_SIZE) return 0;
+ switch(msg->message) {
+ case WM_CREATE:
+ //if (GetSystemMetrics(SM_CMONITORS)>1) return 0;
+ if (db_get_b(NULL,"CList","Docked",0) && db_get_b(NULL,"CLUI","DockToSides",SETTING_DOCKTOSIDES_DEFAULT))
+ {
+ PostMessage(msg->hwnd,WM_CREATEDOCKED,0,0);
+ }
+ draggingTitle = 0;
+ return 0;
+
+ case WM_CREATEDOCKED:
+ //we need to post a message just after creation to let main message function do some work
+ g_CluiData.fDocked = (BOOL)db_get_b(NULL,"CList","Docked",0);
+ if (IsWindowVisible(msg->hwnd) && !IsIconic(msg->hwnd)) {
+ RECT rc, rcMonitor;
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ abd.lParam = 0;
+ abd.uCallbackMessage = WM_DOCKCALLBACK;
+ SHAppBarMessage(ABM_NEW,&abd);
+ GetWindowRect(msg->hwnd,&rc);
+ Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
+ Docking_AdjustPosition(msg->hwnd,&rcMonitor,&rc);
+ MoveWindow(msg->hwnd,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,TRUE);
+ g_CluiData.mutexPreventDockMoving = 0;
+ Sync(CLUIFrames_OnMoving,msg->hwnd,&rc);
+ g_CluiData.mutexPreventDockMoving = 1;
+ ModernSkinButton_ReposButtons( msg->hwnd, SBRF_DO_NOT_DRAW, NULL );
+ }
+ break;
+ case WM_CAPTURECHANGED:
+ ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_NOT_DRAW,NULL);
+ return 0;
+ case WM_ACTIVATE:
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ SHAppBarMessage(ABM_ACTIVATE,&abd);
+ return 0;
+ case WM_SIZE:
+ ModernSkinButton_ReposButtons( msg->hwnd, SBRF_DO_REDRAW_ALL, NULL );
+ return 0;
+
+ case WM_WINDOWPOSCHANGED:
+ {
+ if (g_CluiData.fDocked) ModernSkinButton_ReposButtons( msg->hwnd,SBRF_DO_NOT_DRAW, NULL );
+ return 0;
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ SHAppBarMessage(ABM_WINDOWPOSCHANGED,&abd);
+ ModernSkinButton_ReposButtons( msg->hwnd, SBRF_DO_NOT_DRAW, NULL );
+ return 0;
+ }
+ case WM_MOVING:
+ {
+ RECT rcMonitor;
+ RECT rcWindow;
+ RECT *rc;
+ int dx = 0;
+ POINT ptCursor;
+ if (g_CluiData.fDocked) return 0;
+ // stop early
+ BOOL bControlled = (BOOL)(GetAsyncKeyState(VK_CONTROL)&0x8000);
+
+ // GetMessagePos() is no good, position is always unsigned
+ GetCursorPos(&ptCursor);
+ GetWindowRect(msg->hwnd,&rcWindow);
+ dock_drag_dx = rcWindow.left-ptCursor.x;
+ dock_drag_dy = rcWindow.top-ptCursor.y;
+ Docking_GetMonitorRectFromPoint(ptCursor,&rcMonitor);
+
+ if (((ptCursor.x < rcMonitor.left+EDGESENSITIVITY)
+ || (ptCursor.x >= rcMonitor.right-EDGESENSITIVITY))
+ && db_get_b(NULL,"CLUI","DockToSides",SETTING_DOCKTOSIDES_DEFAULT))
+ {
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ abd.lParam = 0;
+ abd.uCallbackMessage = WM_DOCKCALLBACK;
+ SHAppBarMessage(ABM_NEW,&abd);
+ if (ptCursor.x < rcMonitor.left+EDGESENSITIVITY) g_CluiData.fDocked = DOCKED_LEFT;
+ else g_CluiData.fDocked = DOCKED_RIGHT;
+ // TempDock = 1;
+ GetWindowRect(msg->hwnd,(LPRECT)msg->lParam);
+ rc = (RECT*)msg->lParam;
+ if (g_CluiData.fDocked == DOCKED_RIGHT)
+ dx = (rc->right>rcMonitor.right)?rc->right-rcMonitor.right:0;
+ else
+ dx = (rc->left < rcMonitor.left)?rc->left-rcMonitor.left:0;
+ OffsetRect(rc,-dx,0);
+ Docking_AdjustPosition(msg->hwnd,(LPRECT)&rcMonitor,(LPRECT)msg->lParam);
+ SendMessage(msg->hwnd,WM_SIZE,0,0);
+ g_CluiData.mutexPreventDockMoving = 0;
+ Sync(CLUIFrames_OnMoving,msg->hwnd,(LPRECT)msg->lParam);
+ g_CluiData.mutexPreventDockMoving = 1;
+ mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
+ db_set_b(NULL,"CList","Docked",(BYTE)g_CluiData.fDocked);
+ ModernSkinButton_ReposButtons( msg->hwnd, SBRF_DO_NOT_DRAW, NULL );
+ return TRUE;
+ }
+ return 0;
+ }
+ case WM_EXITSIZEMOVE:
+ {
+ RECT rcMonitor;
+ RECT rcWindow;
+ if (TempDock) TempDock = 0;
+ GetWindowRect(msg->hwnd,&rcWindow);
+ Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
+ Docking_AdjustPosition(msg->hwnd,&rcMonitor,&rcWindow);
+ *((LRESULT*)lParam) = TRUE;
+ g_CluiData.mutexPreventDockMoving = 0;
+ SetWindowPos(msg->hwnd,0,rcWindow.left,rcWindow.top,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOSENDCHANGING);
+ Sync(CLUIFrames_OnMoving,msg->hwnd,&rcWindow);
+ ModernSkinButton_ReposButtons( msg->hwnd, SBRF_DO_NOT_DRAW, NULL );// -= -= -=
+ g_CluiData.mutexPreventDockMoving = 1;
+ return 1;
+ }
+
+ case WM_MOVE:
+ {
+
+ if (g_CluiData.fDocked && 0) {
+ RECT rc, rcMonitor;
+ Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
+ GetWindowRect(msg->hwnd,&rc);
+ Docking_AdjustPosition(msg->hwnd,&rcMonitor,&rc);
+ MoveWindow(msg->hwnd,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,TRUE);
+ Sync(CLUIFrames_OnMoving,msg->hwnd,&rc);
+ ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_NOT_DRAW, NULL);// -= -= -=
+
+ return 1;
+ }
+ ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_ALT_DRAW, NULL);
+ return 0;
+ }
+ case WM_SIZING:
+ {
+
+ /*RECT rcMonitor;
+ Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
+ Docking_AdjustPosition(msg->hwnd,&rcMonitor,(LPRECT)msg->lParam);
+ *((LRESULT*)lParam) = TRUE;
+ */
+ RECT rc;
+ if (g_CluiData.fDocked) ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_NOT_DRAW,NULL);
+ return FALSE;
+ rc = *(RECT*)(msg->lParam);
+ g_CluiData.mutexPreventDockMoving = 0;
+ Sync(CLUIFrames_OnMoving,msg->hwnd,&rc);
+ // -= -= -=
+ return TRUE;
+ }
+ case WM_SHOWWINDOW:
+ {
+ if (msg->lParam) return 0;
+ BOOL toBeDocked = (BOOL) db_get_b(NULL,"CLUI","DockToSides",SETTING_DOCKTOSIDES_DEFAULT);
+ if ((msg->wParam && g_CluiData.fDocked < 0) || (!msg->wParam && g_CluiData.fDocked>0)) g_CluiData.fDocked = -g_CluiData.fDocked;
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ if (msg->wParam) {
+ RECT rc, rcMonitor;
+ Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
+ abd.lParam = 0;
+ abd.uCallbackMessage = WM_DOCKCALLBACK;
+ SHAppBarMessage(ABM_NEW,&abd);
+ GetWindowRect(msg->hwnd,&rc);
+ Docking_AdjustPosition(msg->hwnd,&rcMonitor,&rc);
+ MoveWindow(msg->hwnd,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,FALSE);
+ Sync(CLUIFrames_OnMoving,msg->hwnd,&rc);
+ ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_NOT_DRAW,NULL);// -= -= -=
+ }
+ else {
+ SHAppBarMessage(ABM_REMOVE,&abd);
+ }
+ }
+ return 0;
+ case WM_NCHITTEST:
+ { LONG result;
+ result = DefWindowProc(msg->hwnd,WM_NCHITTEST,msg->wParam,msg->lParam);
+ if (result == HTSIZE || result == HTTOP || result == HTTOPLEFT || result == HTTOPRIGHT ||
+ result == HTBOTTOM || result == HTBOTTOMRIGHT || result == HTBOTTOMLEFT) {*((LRESULT*)lParam) = HTCLIENT; return TRUE;}
+ if (g_CluiData.fDocked == DOCKED_LEFT && result == HTLEFT) {*((LRESULT*)lParam) = HTCLIENT; return TRUE;}
+ if (g_CluiData.fDocked == DOCKED_RIGHT && result == HTRIGHT) {*((LRESULT*)lParam) = HTCLIENT; return TRUE;}
+
+
+ return 0;
+ }
+ case WM_SYSCOMMAND:
+ if ((msg->wParam&0xFFF0) != SC_MOVE) return 0;
+ SetActiveWindow(msg->hwnd);
+ SetCapture(msg->hwnd);
+ draggingTitle = 1;
+ *((LRESULT*)lParam) = 0;
+ return TRUE;
+ case WM_MOUSEMOVE:
+
+ if ( !draggingTitle) return 0;
+ { RECT rc;
+ POINT pt;
+ GetClientRect(msg->hwnd,&rc);
+ if (((g_CluiData.fDocked == DOCKED_LEFT || g_CluiData.fDocked == -DOCKED_LEFT) && (short)LOWORD(msg->lParam)>rc.right) ||
+ ((g_CluiData.fDocked == DOCKED_RIGHT || g_CluiData.fDocked == -DOCKED_RIGHT) && (short)LOWORD(msg->lParam) < 0)) {
+ ReleaseCapture();
+ draggingTitle = 0;
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ SHAppBarMessage(ABM_REMOVE,&abd);
+ g_CluiData.fDocked = 0;
+ GetCursorPos(&pt);
+ PostMessage(msg->hwnd,WM_NCLBUTTONDOWN,HTCAPTION,MAKELPARAM(pt.x,pt.y));
+ SetWindowPos(msg->hwnd,0,pt.x-rc.right/2,pt.y-GetSystemMetrics(SM_CYFRAME)-GetSystemMetrics(SM_CYSMCAPTION)/2,db_get_dw(NULL,"CList","Width",0),db_get_dw(NULL,"CList","Height",0),SWP_NOZORDER);
+ db_set_b(NULL,"CList","Docked",(BYTE)g_CluiData.fDocked);
+ // ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_NOT_DRAW, NULL);
+ }
+ return 1;
+ }
+ case WM_LBUTTONUP:
+ if (draggingTitle) {
+ ReleaseCapture();
+ draggingTitle = 0;
+ }
+ return 0;
+ case WM_DOCKCALLBACK:
+ switch(msg->wParam) {
+ case ABN_WINDOWARRANGE:
+ CLUI_ShowWindowMod(msg->hwnd,msg->lParam?SW_HIDE:SW_SHOW);
+ {
+
+ RECT rc, rcMonitor;
+ Docking_GetMonitorRectFromWindow(msg->hwnd,&rcMonitor);
+ GetWindowRect(msg->hwnd,&rc);
+ Docking_AdjustPosition(msg->hwnd,&rcMonitor,&rc);
+ Sync(CLUIFrames_OnMoving,msg->hwnd,&rc); // -= -= -=
+ ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_NOT_DRAW, NULL);
+
+ g_CluiData.mutexPreventDockMoving = 1;
+ }
+ break;
+ }
+ return TRUE;
+ case WM_DESTROY:
+ if (g_CluiData.fDocked>0) {
+ ZeroMemory(&abd,sizeof(abd));
+ abd.cbSize = sizeof(abd);
+ abd.hWnd = msg->hwnd;
+ SHAppBarMessage(ABM_REMOVE,&abd);
+ ModernSkinButton_ReposButtons(msg->hwnd, SBRF_DO_NOT_DRAW, NULL);
+ }
+ return 0;
+ }
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_extraimage.cpp b/plugins/Clist_modern/src/modern_extraimage.cpp
new file mode 100644
index 0000000000..3a306081fe
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_extraimage.cpp
@@ -0,0 +1,509 @@
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_commonprototypes.h"
+
+
+
+#define ExtraImageIconsIndexCount 6
+
+bool visar[EXTRACOLUMNCOUNT];
+int ExtraImageIconsIndex[ExtraImageIconsIndexCount];
+int EnabledColumnCount = 0;
+BOOL g_mutex_bSetAllExtraIconsCycle = 0;
+
+static HIMAGELIST hExtraImageList = NULL;
+static HIMAGELIST hWideExtraImageList = NULL;
+
+void ExtraImage_SetAllExtraIcons(HWND hwndList,HANDLE hContact);
+
+void ClearExtraIcons();
+
+bool ImageCreated = FALSE;
+BYTE ExtraOrder[] =
+{
+ 1, // EXTRA_ICON_EMAIL
+ 2, // EXTRA_ICON_PROTO
+ 3, // EXTRA_ICON_SMS
+ 4, // EXTRA_ICON_ADV1
+ 5, // EXTRA_ICON_ADV2
+ 6, // EXTRA_ICON_WEB
+ 7, // EXTRA_ICON_CLIENT
+ 0, // EXTRA_ICON_VISMODE
+ 8, // EXTRA_ICON_ADV3
+ 9, // EXTRA_ICON_ADV4
+};
+
+BOOL HasExtraIconsService()
+{
+ return ServiceExists("ExtraIcon/Register");
+}
+
+bool isColumnVisible(int extra)
+{
+ if (HasExtraIconsService())
+ return true;
+
+ int i=0;
+ for (i=0; i < sizeof(ExtraOrder)/sizeof(ExtraOrder[0]); i++)
+ if (ExtraOrder[i] == extra)
+ {
+ switch(i+1)
+ {
+ case EXTRA_ICON_EMAIL: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_EMAIL",SETTING_EXTRA_ICON_EMAIL_DEFAULT) != 0;
+ case EXTRA_ICON_PROTO: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_PROTO",SETTING_EXTRA_ICON_PROTO_DEFAULT) != 0;
+ case EXTRA_ICON_SMS: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_SMS",SETTING_EXTRA_ICON_SMS_DEFAULT) != 0;
+ case EXTRA_ICON_ADV1: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_ADV1",SETTING_EXTRA_ICON_ADV1_DEFAULT) != 0;
+ case EXTRA_ICON_ADV2: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_ADV2",SETTING_EXTRA_ICON_ADV2_DEFAULT) != 0;
+ case EXTRA_ICON_WEB: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_WEB",SETTING_EXTRA_ICON_WEB_DEFAULT) != 0;
+ case EXTRA_ICON_CLIENT: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_CLIENT",SETTING_EXTRA_ICON_CLIENT_DEFAULT) != 0;
+ case EXTRA_ICON_VISMODE: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_VISMODE",SETTING_EXTRA_ICON_VISMODE_DEFAULT) != 0;
+ case EXTRA_ICON_ADV3: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_ADV3",SETTING_EXTRA_ICON_ADV3_DEFAULT) != 0;
+ case EXTRA_ICON_ADV4: return db_get_b(NULL,CLUIFrameModule,"EXTRA_ICON_ADV4",SETTING_EXTRA_ICON_ADV4_DEFAULT) != 0;
+ }
+ break;
+ }
+ return(FALSE);
+}
+
+void GetVisColumns()
+{
+ visar[0] = isColumnVisible(0);
+ visar[1] = isColumnVisible(1);
+ visar[2] = isColumnVisible(2);
+ visar[3] = isColumnVisible(3);
+ visar[4] = isColumnVisible(4);
+ visar[5] = isColumnVisible(5);
+ visar[6] = isColumnVisible(6);
+ visar[7] = isColumnVisible(7);
+ visar[8] = isColumnVisible(8);
+ visar[9] = isColumnVisible(9);
+};
+
+__inline int bti(bool b)
+{
+ return(b?1:0);
+};
+int colsum(int from,int to)
+{
+ int i,sum;
+ if (from < 0 || from >= EXTRACOLUMNCOUNT){return(-1);};
+ if (to < 0 || to >= EXTRACOLUMNCOUNT){return(-1);};
+ if (to < from){return(-1);};
+
+ sum = 0;
+ for (i = from;i <= to;i++)
+ {
+ sum += bti(visar[i]);
+ };
+ return(sum);
+};
+
+
+
+
+int ExtraImage_ExtraIDToColumnNum(int extra)
+{
+ if (HasExtraIconsService())
+ {
+ if (extra < 1 || extra > EXTRACOLUMNCOUNT)
+ return -1;
+ else
+ return extra-1;
+ }
+
+ int ord = ExtraOrder[extra-1];
+ if ( !visar[ord]) return -1;
+ return (colsum(0,ord)-1);
+};
+
+int ExtraImage_ColumnNumToExtraID(int column)
+{
+ if (HasExtraIconsService())
+ return column+1;
+
+ for (int i=0; i < EXTRA_ICON_COUNT; i++)
+ if (ExtraImage_ExtraIDToColumnNum(i) == column)
+ return i;
+
+ return -1;
+}
+
+INT_PTR SetIconForExtraColumn(WPARAM wParam,LPARAM lParam)
+{
+ pIconExtraColumn piec;
+ int icol;
+ HANDLE hItem;
+
+ if (pcli->hwndContactTree == 0){return(-1);};
+ if (wParam == 0 || lParam == 0){return(-1);};
+ piec = (pIconExtraColumn)lParam;
+
+ if (piec->cbSize != sizeof(IconExtraColumn)){return(-1);};
+ icol = ExtraImage_ExtraIDToColumnNum(piec->ColumnType);
+ if (icol == -1){return(-1);};
+ hItem = (HANDLE)SendMessage(pcli->hwndContactTree,CLM_FINDCONTACT,(WPARAM)wParam,0);
+ if (hItem == 0){return(-1);};
+
+ SendMessage(pcli->hwndContactTree,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(icol,piec->hImage));
+ return(0);
+}
+
+//wparam = hIcon
+//return hImage on success,-1 on failure
+INT_PTR AddIconToExtraImageList(WPARAM wParam,LPARAM lParam)
+{
+ if (hExtraImageList == 0 || wParam == 0)
+ return -1;
+
+ int res = ((int)ImageList_AddIcon(hExtraImageList,(HICON)wParam));
+ return (res > 254) ? -1 : res;
+}
+
+void SetNewExtraColumnCount()
+{
+ LoadPositionsFromDB(ExtraOrder);
+ GetVisColumns();
+
+ int newcount = colsum(0,EXTRACOLUMNCOUNT-1);
+ db_set_b(NULL,CLUIFrameModule,"EnabledColumnCount",(BYTE)newcount);
+ EnabledColumnCount = newcount;
+ SendMessage(pcli->hwndContactTree,CLM_SETEXTRACOLUMNS,EnabledColumnCount,0);
+}
+
+void ExtraImage_ReloadExtraIcons()
+{
+ int count,i;
+ PROTOACCOUNT **accs;
+ HICON hicon;
+ BOOL needFree;
+
+ SendMessage(pcli->hwndContactTree,CLM_SETEXTRACOLUMNSSPACE,db_get_b(NULL,"CLUI","ExtraColumnSpace",18),0);
+ SendMessage(pcli->hwndContactTree,CLM_SETEXTRAIMAGELIST,0,(LPARAM)NULL);
+ if (hExtraImageList){ImageList_Destroy(hExtraImageList);};
+ if (hWideExtraImageList){ImageList_Destroy(hWideExtraImageList);};
+
+ hExtraImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_COLOR32|ILC_MASK,1,256);
+ hWideExtraImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_COLOR32|ILC_MASK,1,256);
+
+ if ( !HasExtraIconsService()) {
+ //loading icons
+ HICON hIcon = LoadSkinnedIcon(SKINICON_OTHER_SENDEMAIL);
+ ExtraImageIconsIndex[0] = ImageList_AddIcon(hExtraImageList, hIcon);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ hIcon = LoadSkinnedIcon(SKINICON_OTHER_SMS);
+ ExtraImageIconsIndex[1] = ImageList_AddIcon(hExtraImageList, hIcon);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ hIcon = LoadSkinnedIcon(SKINICON_EVENT_URL);
+ ExtraImageIconsIndex[2] = ImageList_AddIcon(hExtraImageList, hIcon);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+
+ //calc only needed protocols
+ //adding protocol icons
+ ProtoEnumAccounts( &count, &accs );
+ for (i=0;i < count;i++) {
+ if ( !IsAccountEnabled(accs[i]) || CallProtoService(accs[i]->szModuleName, PS_GETCAPS,PFLAGNUM_2, 0 ) == 0)
+ continue;
+
+ hIcon = LoadSkinnedProtoIcon(accs[i]->szModuleName,ID_STATUS_ONLINE);
+ ImageList_AddIcon(hExtraImageList, hIcon);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ }
+
+ hicon = CLUI_LoadIconFromExternalFile("clisticons.dll",5,TRUE,TRUE,"AlwaysVis","Contact List",Translate("Always Visible"),-IDI_ALWAYSVIS,&needFree);
+ if ( !hicon) {hicon = LoadSmallIcon(g_hInst, MAKEINTRESOURCE(IDI_ALWAYSVIS));needFree = TRUE;}
+ ExtraImageIconsIndex[3] = ImageList_AddIcon(hExtraImageList,hicon );
+ if (needFree) DestroyIcon_protect(hicon);
+
+ hicon = CLUI_LoadIconFromExternalFile("clisticons.dll",6,TRUE,TRUE,"NeverVis","Contact List",Translate("Never Visible"),-IDI_NEVERVIS,&needFree);
+ if ( !hicon) {hicon = LoadSmallIcon(g_hInst, MAKEINTRESOURCE(IDI_NEVERVIS));needFree = TRUE;}
+ ExtraImageIconsIndex[4] = ImageList_AddIcon(hExtraImageList,hicon );
+ if (needFree) DestroyIcon_protect(hicon);
+
+ hicon = CLUI_LoadIconFromExternalFile("clisticons.dll",7,TRUE,TRUE,"ChatActivity","Contact List",Translate("Chat Activity"),-IDI_CHAT,&needFree);
+ if ( !hicon) {hicon = LoadSmallIcon(g_hInst, MAKEINTRESOURCE(IDI_CHAT));needFree = TRUE;}
+ ExtraImageIconsIndex[5] = ImageList_AddIcon(hExtraImageList,hicon );
+ if (needFree) DestroyIcon_protect(hicon);
+ }
+
+ SendMessage(pcli->hwndContactTree,CLM_SETEXTRAIMAGELIST,(WPARAM)hWideExtraImageList,(LPARAM)hExtraImageList);
+ //ExtraImage_SetAllExtraIcons(hImgList);
+ SetNewExtraColumnCount();
+ NotifyEventHooks(g_CluiData.hEventExtraImageListRebuilding,0,0);
+ ImageCreated = TRUE;
+}
+
+void ReAssignExtraIcons()
+{
+ ClearExtraIcons();
+ SetNewExtraColumnCount();
+ ExtraImage_SetAllExtraIcons(pcli->hwndContactTree,0);
+ SendMessage(pcli->hwndContactTree,CLM_AUTOREBUILD,0,0);
+}
+
+void ClearExtraIcons()
+{
+ SetNewExtraColumnCount();
+
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ do {
+ HANDLE hItem = (HANDLE)SendMessage(pcli->hwndContactTree,CLM_FINDCONTACT,(WPARAM)hContact,0);
+ if (hItem == 0)
+ continue;
+
+ for (int i=0;i < EnabledColumnCount;i++)
+ SendMessage(pcli->hwndContactTree,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(i,0xFF));
+ }
+ while(hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0));
+};
+
+void ExtraImage_SetAllExtraIcons(HWND hwndList,HANDLE hContact)
+{
+ HANDLE hItem;
+ int locApparentMode = 0;
+ char * locApparentModeProto = NULL;
+ bool hcontgiven = FALSE;
+ char *szProto;
+ char *(ImgIndex[64]);
+ int maxpr,count,i;
+ PROTOACCOUNT **accs;
+ pdisplayNameCacheEntry pdnce;
+ int em,pr,sms,a1,a2,w1,c1;
+ int tick = 0;
+ g_mutex_bSetAllExtraIconsCycle = 1;
+ hcontgiven = (hContact != 0);
+
+ if (pcli->hwndContactTree == 0){return;};
+ tick = GetTickCount();
+ if (ImageCreated == FALSE) ExtraImage_ReloadExtraIcons();
+
+ SetNewExtraColumnCount();
+
+ BOOL hasExtraIconsService = HasExtraIconsService();
+ if ( !hasExtraIconsService)
+ {
+ em = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_EMAIL);
+ pr = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_PROTO);
+ sms = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_SMS);
+ a1 = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_ADV1);
+ a2 = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_ADV2);
+ w1 = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_WEB);
+ c1 = ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_CLIENT);
+
+ memset( ImgIndex, 0, sizeof( ImgIndex ));
+ ProtoEnumAccounts( &count, &accs );
+ maxpr = 0;
+ //calc only needed protocols
+ for (i=0;i < count;i++) {
+ if ( !IsAccountEnabled( accs[i] ) || CallProtoService(accs[i]->szModuleName,PS_GETCAPS,PFLAGNUM_2,0) == 0) continue;
+ ImgIndex[maxpr] = accs[i]->szModuleName;
+ maxpr++;
+ }
+ }
+
+ if (hContact == NULL)
+ {
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ }
+
+ do {
+
+ szProto = NULL;
+ hItem = hContact;
+ if (hItem == 0){continue;};
+ pdnce = (pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hItem);
+ if (pdnce == NULL) {continue;};
+
+ // szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0);
+ szProto = pdnce->m_cache_cszProto;
+
+ if ( !hasExtraIconsService)
+ {
+ {
+ bool showweb;
+ showweb = FALSE;
+ if (ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_WEB) != -1)
+ {
+
+ if (szProto != NULL)
+ {
+ char *homepage;
+ homepage = db_get_sa(pdnce->hContact,"UserInfo", "Homepage");
+ if ( !homepage)
+ homepage = db_get_sa(pdnce->hContact,pdnce->m_cache_cszProto, "Homepage");
+ if (homepage != NULL)
+ {
+ showweb = TRUE;
+ mir_free(homepage);
+ }
+ }
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_WEB),(showweb)?2:0xFF));
+ }
+ }
+ {
+ DBVARIANT dbv = {0};
+ bool showemail;
+ showemail = TRUE;
+ if (ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_EMAIL) != -1)
+ {
+
+ if (szProto == NULL || DBGetContactSettingString(hContact, szProto, "e-mail",&dbv))
+ {
+ db_free(&dbv);
+ if (DBGetContactSettingString(hContact, "UserInfo", "Mye-mail0", &dbv))
+ showemail = FALSE;
+ }
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_EMAIL),(showemail)?0:0xFF));
+ db_free(&dbv);
+ }
+ }
+
+ {
+ DBVARIANT dbv = {0};
+ bool showsms;
+ showsms = TRUE;
+ if (ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_SMS) != -1)
+ {
+ if (szProto == NULL || DBGetContactSettingString(hContact, szProto, "Cellular",&dbv))
+ {
+ db_free(&dbv);
+ if (DBGetContactSettingString(hContact, "UserInfo", "MyPhone0", &dbv))
+ showsms = FALSE;
+ }
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_SMS),(showsms)?1:0xFF));
+ db_free(&dbv);
+ }
+ }
+
+ if (ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_PROTO) != -1)
+ {
+ for (i=0;i < maxpr;i++)
+ {
+ if ( !mir_strcmp(ImgIndex[i],szProto))
+ {
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_PROTO),i+3));
+ break;
+ };
+ };
+ };
+ if (ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_VISMODE) != -1)
+ {
+ BYTE iconIndex = 0xFF;
+ if (szProto != NULL)
+ {
+ if ( !db_get_b(hContact, szProto, "ChatRoom", 0))
+ {
+ if (pdnce->ApparentMode == ID_STATUS_OFFLINE)
+ iconIndex = ExtraImageIconsIndex[4];
+ else if (pdnce->ApparentMode == ID_STATUS_ONLINE)
+ {
+ if (szProto != locApparentModeProto)
+ {
+ locApparentModeProto = szProto;
+ locApparentMode = CallProtoService(locApparentModeProto,PS_GETSTATUS,0,0);
+ }
+ if (locApparentMode == ID_STATUS_INVISIBLE || db_get_b(NULL,"CList","AlwaysShowAlwaysVisIcon",SETTING_ALWAYSVISICON_DEFAULT) == 1)
+ iconIndex = ExtraImageIconsIndex[3]; }
+ }
+ else
+ {
+ if (pdnce->ApparentMode == ID_STATUS_OFFLINE)
+ iconIndex = ExtraImageIconsIndex[5];
+ else iconIndex = 255;
+ }
+ }
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(ExtraImage_ExtraIDToColumnNum(EXTRA_ICON_VISMODE),iconIndex));
+ }
+ }
+ NotifyEventHooks(g_CluiData.hEventExtraImageApplying,(WPARAM)hContact,0);
+ if (hcontgiven) break;
+ Sleep(0);
+ } while(hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0));
+
+ tick = GetTickCount()-tick;
+ g_mutex_bSetAllExtraIconsCycle = 0;
+ CLUI__cliInvalidateRect(hwndList,NULL,FALSE);
+ Sleep(0);
+}
+
+HWND SetToolTip(HWND hwnd, TCHAR * tip);
+
+HWND tipHWND = NULL;
+
+static int ehhShowExtraInfoTip(WPARAM wParam, LPARAM lParam)
+{
+ CLCEXTRAINFOTIP * eit = (CLCEXTRAINFOTIP *)lParam;
+ //tipHWND = SetToolTip(eit->hwnd,_T("TEST"));
+ //SendMessage(tipHWND,TTM_ACTIVATE,1,0);
+ //SendMessage(tipHWND,TTM_POPUP,0,0);
+ return 1;
+
+}
+
+int ehhHideExtraInfoTip(WPARAM wParam, LPARAM lParam)
+{
+
+ //SendMessage(tipHWND,TTM_ACTIVATE,0,0);
+ return 0;
+
+}
+
+INT_PTR WideSetIconForExtraColumn(WPARAM wParam,LPARAM lParam)
+{
+ pIconExtraColumn piec;
+ int icol;
+ HANDLE hItem;
+
+ if (pcli->hwndContactTree == 0){return(-1);};
+ if (wParam == 0 || lParam == 0){return(-1);};
+ piec = (pIconExtraColumn)lParam;
+
+ if (piec->cbSize != sizeof(IconExtraColumn)){return(-1);};
+ icol = ExtraImage_ExtraIDToColumnNum(piec->ColumnType);
+ if (icol == -1){return(-1);};
+
+ hItem = (HANDLE)SendMessage(pcli->hwndContactTree,CLM_FINDCONTACT,(WPARAM)wParam,0);
+ if (hItem == 0){return(-1);};
+ if (piec->hImage == (HANDLE)0xFF) piec->hImage = (HANDLE)0xFFFF;
+
+ SendMessage(pcli->hwndContactTree,CLM_SETWIDEEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(icol,piec->hImage));
+ return(0);
+};
+
+//wparam = hIcon
+//return hImage on success,-1 on failure
+INT_PTR WideAddIconToExtraImageList(WPARAM wParam,LPARAM lParam)
+{
+ int res = -1;
+ if (hWideExtraImageList == 0 || wParam == 0){return(-1);};
+ res = ((int)ImageList_AddIcon(hWideExtraImageList,(HICON)wParam));
+ if (res == 0xFF) res = ((int)ImageList_AddIcon(hWideExtraImageList,(HICON)wParam));
+ if (res>0xFFFE) return -1;
+ return res;
+};
+static int ehhExtraImage_UnloadModule(WPARAM wParam,LPARAM lParam)
+{
+ if (hExtraImageList) { ImageList_Destroy(hExtraImageList); };
+ if (hWideExtraImageList) { ImageList_Destroy(hWideExtraImageList); };
+ return 0;
+
+}
+void ExtraImage_LoadModule()
+{
+ CreateServiceFunction(MS_CLIST_EXTRA_SET_ICON,WideSetIconForExtraColumn);
+ CreateServiceFunction(MS_CLIST_EXTRA_ADD_ICON,WideAddIconToExtraImageList);
+
+ //CreateServiceFunction(MS_CLIST_EXTRA2_SET_ICON,WideSetIconForExtraColumn);
+ //CreateServiceFunction(MS_CLIST_EXTRA2_ADD_ICON,WideAddIconToExtraImageList);
+
+
+
+ //HookEvent(ME_SKIN2_ICONSCHANGED,OnIconLibIconChanged);
+
+ HookEvent(ME_CLC_SHOWEXTRAINFOTIP, ehhShowExtraInfoTip );
+ HookEvent(ME_CLC_HIDEINFOTIP, ehhHideExtraInfoTip );
+ HookEvent(ME_SYSTEM_SHUTDOWN, ehhExtraImage_UnloadModule );
+};
+
+
+
+
+
diff --git a/plugins/Clist_modern/src/modern_framesmenu.cpp b/plugins/Clist_modern/src/modern_framesmenu.cpp
new file mode 100644
index 0000000000..950bf122bb
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_framesmenu.cpp
@@ -0,0 +1,214 @@
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_commonprototypes.h"
+
+// == == == == == == == == == == == == == Frames
+HANDLE hFrameMenuObject;
+
+//contactmenu exec param(ownerdata)
+//also used in checkservice
+typedef struct{
+ char *szServiceName;
+ int Frameid;
+ INT_PTR param1;
+}
+ FrameMenuExecParam,*lpFrameMenuExecParam;
+
+void FreeAndNil( void **p )
+{
+ if ( p == NULL )
+ return;
+
+ if ( *p != NULL ) {
+ mir_free( *p );
+ *p = NULL;
+} }
+
+static INT_PTR AddContextFrameMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ TMO_MenuItem tmi;
+ CLISTMENUITEM *mi = (CLISTMENUITEM*)lParam;
+ if ( !pcli->pfnConvertMenu(mi, &tmi))
+ return NULL;
+
+ tmi.root = (mi->flags & CMIF_ROOTHANDLE) ? mi->hParentMenu : NULL;
+
+ lpFrameMenuExecParam fmep = (lpFrameMenuExecParam)mir_alloc(sizeof(FrameMenuExecParam));
+ if (fmep == NULL)
+ return 0;
+
+ memset(fmep, 0, sizeof(FrameMenuExecParam));
+ fmep->szServiceName = mir_strdup(mi->pszService);
+ fmep->Frameid = mi->popupPosition;
+ fmep->param1 = (INT_PTR)mi->pszContactOwner;
+ tmi.ownerdata = fmep;
+
+ return CallService(MO_ADDNEWMENUITEM,(WPARAM)hFrameMenuObject,(LPARAM)&tmi);
+}
+
+static INT_PTR RemoveContextFrameMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ lpFrameMenuExecParam fmep = (lpFrameMenuExecParam)CallService(MO_MENUITEMGETOWNERDATA,wParam,lParam);
+ if (fmep != NULL){
+ if (fmep->szServiceName != NULL)
+ mir_free(fmep->szServiceName);
+ mir_free(fmep);
+ }
+
+ if (lParam != 1)
+ CallService(MO_REMOVEMENUITEM,wParam,0);
+
+ return 0;
+}
+
+//called with:
+//wparam - ownerdata
+//lparam - lparam from winproc
+INT_PTR FrameMenuExecService(WPARAM wParam,LPARAM lParam) {
+ lpFrameMenuExecParam fmep = (lpFrameMenuExecParam)wParam;
+ if (fmep == NULL){return(-1);};
+ CallService(fmep->szServiceName,lParam,fmep->param1);
+
+ return(0);
+};
+
+//true - ok,false ignore
+INT_PTR FrameMenuCheckService(WPARAM wParam,LPARAM lParam) {
+
+ PCheckProcParam pcpp = (PCheckProcParam)wParam;
+ lpFrameMenuExecParam fmep;
+ TMO_MenuItem mi;
+
+ if (pcpp == NULL){return(FALSE);};
+ if (CallService(MO_GETMENUITEM,(WPARAM)pcpp->MenuItemHandle,(LPARAM)&mi) == 0)
+ {
+ fmep = (lpFrameMenuExecParam)mi.ownerdata;
+ if (fmep != NULL)
+ {
+ //pcpp->wParam - frameid
+ if (((WPARAM)fmep->Frameid == pcpp->wParam) || fmep->Frameid == -1) return(TRUE);
+ };
+
+ };
+ return(FALSE);
+};
+
+static INT_PTR ContextFrameMenuNotify(WPARAM wParam,LPARAM lParam)
+{
+ NotifyEventHooks(g_CluiData.hEventPreBuildFrameMenu,wParam,lParam);
+ return(0);
+};
+
+static INT_PTR BuildContextFrameMenu(WPARAM wParam,LPARAM lParam)
+{
+ ListParam param = { 0 };
+ param.MenuObjectHandle = hFrameMenuObject;
+ param.wParam = wParam;
+ param.lParam = lParam;
+
+ HMENU hMenu = CreatePopupMenu();
+ //NotifyEventHooks(hPreBuildFrameMenuEvent,wParam,-1);
+ ContextFrameMenuNotify(wParam,-1);
+ CallService(MO_BUILDMENU,(WPARAM)hMenu,(LPARAM)&param);
+ return (INT_PTR)hMenu;
+}
+
+// == == == == == == == == == == == == == Frames end
+bool InternalGenMenuModule = FALSE;
+
+int MeasureItemProxy(WPARAM wParam,LPARAM lParam) {
+
+ int val;
+ if (InternalGenMenuModule)
+ {
+
+ val = CallService(MS_INT_MENUMEASUREITEM,wParam,lParam);
+ if (val) return(val);
+ };
+ return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam);
+
+
+};
+
+
+int DrawItemProxy(WPARAM wParam,LPARAM lParam) {
+ if (InternalGenMenuModule)
+ {
+ int val;
+ val = CallService(MS_INT_MENUDRAWITEM,wParam,lParam);
+ if (val) return(val);
+ }
+ return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam);
+
+};
+
+
+
+int ProcessCommandProxy(WPARAM wParam,LPARAM lParam) {
+ if (InternalGenMenuModule)
+ {
+ int val;
+ val = CallService(MS_INT_MENUPROCESSCOMMAND,wParam,lParam);
+ if (val) return(val);
+ };
+
+ return CallService(MS_CLIST_MENUPROCESSCOMMAND,wParam,lParam);
+
+};
+
+int ModifyMenuItemProxy(WPARAM wParam,LPARAM lParam) {
+ if (InternalGenMenuModule)
+ {
+ int val;
+ val = CallService(MS_INT_MODIFYMENUITEM,wParam,lParam);
+ if (val) return(val);
+ };
+
+ return CallService(MS_CLIST_MODIFYMENUITEM,wParam,lParam);
+
+};
+
+
+int InitFramesMenus(void)
+{
+ TMenuParam tmp;
+
+ if ( !ServiceExists(MO_REMOVEMENUOBJECT))
+ {
+
+ InitCustomMenus();
+ InternalGenMenuModule = TRUE;
+ };
+
+ if (ServiceExists(MO_REMOVEMENUOBJECT))
+ {
+ CreateServiceFunction("FrameMenuExecService",FrameMenuExecService);
+ CreateServiceFunction("FrameMenuCheckService",FrameMenuCheckService);
+
+ CreateServiceFunction(MS_CLIST_REMOVECONTEXTFRAMEMENUITEM,RemoveContextFrameMenuItem);
+ CreateServiceFunction("CList/AddContextFrameMenuItem",AddContextFrameMenuItem);
+ CreateServiceFunction(MS_CLIST_MENUBUILDFRAMECONTEXT,BuildContextFrameMenu);
+ CreateServiceFunction(MS_CLIST_FRAMEMENUNOTIFY,ContextFrameMenuNotify);
+
+
+ //frame menu object
+ memset(&tmp,0,sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ tmp.CheckService = "FrameMenuCheckService";
+ tmp.ExecService = "FrameMenuExecService";
+ tmp.name = "FrameMenu";
+ hFrameMenuObject = (HANDLE)CallService(MO_CREATENEWMENUOBJECT,0,(LPARAM)&tmp);
+ }
+ return 0;
+}
+int UnitFramesMenu()
+{
+
+ /*
+ if (ServiceExists(MO_REMOVEMENUOBJECT))
+ {
+ CallService(MO_REMOVEMENUOBJECT,hFrameMenuObject,0);
+ if (InternalGenMenuModule){UnitGenMenu();};
+ };
+ */
+ return(0);
+};
diff --git a/plugins/Clist_modern/src/modern_gdiplus.cpp b/plugins/Clist_modern/src/modern_gdiplus.cpp
new file mode 100644
index 0000000000..f07e294dbd
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_gdiplus.cpp
@@ -0,0 +1,308 @@
+/*
+ * test for gdi+
+ */
+
+
+#include "hdr/modern_commonheaders.h"
+
+#undef Translate //otherwise will conflict with gdi plus Translate
+#include <gdiplus.h>
+
+#include "hdr/modern_global_structure.h"
+
+BYTE saved_alpha;
+ULONG_PTR g_gdiplusToken;
+int mir_strlen(const char *a);
+HBITMAP ske_CreateDIB32(int cx, int cy);
+void InitGdiPlus(void)
+{
+ Gdiplus::GdiplusStartupInput gdiplusStartupInput;
+ g_CluiData.fGDIPlusFail = false;
+ __try {
+ if (g_gdiplusToken == 0)
+ Gdiplus::GdiplusStartup(&g_gdiplusToken, &gdiplusStartupInput, NULL);
+ }
+ __except ( EXCEPTION_EXECUTE_HANDLER ) {
+ g_CluiData.fGDIPlusFail = true;
+ }
+}
+
+void ShutdownGdiPlus(void)
+{
+ Gdiplus::GdiplusStartupInput gdiplusStartupInput;
+ __try {
+ if (g_gdiplusToken)
+ Gdiplus::GdiplusShutdown(g_gdiplusToken);
+ }
+ __except ( EXCEPTION_EXECUTE_HANDLER ) {
+ g_CluiData.fGDIPlusFail = true;
+ }
+ g_gdiplusToken = 0;
+}
+
+
+
+
+using namespace Gdiplus;
+
+static ColorMatrix ClrMatrix = {
+ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.5f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
+};
+
+
+
+int g_hottrack;
+
+DWORD argb_from_cola(COLORREF col, BYTE alpha)
+{
+ return((BYTE) (alpha) << 24 | col);
+}
+HBITMAP GDIPlus_LoadGlyphImage(char *szFileName)
+{
+ WCHAR *string;
+ string = (WCHAR*)malloc(sizeof(WCHAR)*(mir_strlen(szFileName)+2));
+ MultiByteToWideChar(CP_ACP, 0, szFileName, -1, string, (mir_strlen(szFileName)+2)*sizeof(WCHAR));
+ // Create a Bitmap object from a JPEG file.
+ Bitmap bitmap(string,0);
+ free(string);
+ // Clone a portion of the bitmap.
+ Bitmap* clone = bitmap.Clone(0, 0, bitmap.GetWidth(), bitmap.GetHeight(), PixelFormat32bppPARGB);
+ HBITMAP hbmp = NULL;
+ if (clone)
+ {
+ clone->GetHBITMAP(Color(0,0,0),&hbmp);
+ delete clone;
+ }
+ return hbmp;
+}
+void TextOutWithGDIp(HDC hDestDC, int x, int y, LPCTSTR lpString, int nCount)
+{
+// Graphics s(hDestDC);
+// HBITMAP hs;
+// hs = (HBITMAP)GetCurrentObject(hDestDC,OBJ_BITMAP);
+// Bitmap sb(hs,NULL);
+// Bitmap *b = (sb.Clone(x,y,150,30,PixelFormat32bppARGB));
+// Graphics g(b);//(100,100,PixelFormat32bppPARGB);
+// //g.DrawImage(sb);
+// // s.SetCompositingMode(CompositingModeSourceCopy);
+// // g.SetCompositingMode(CompositingModeSourceCopy);
+// g.DrawImage(&sb,0,0,x,y,100,30,UnitPixel);
+// //s.SetCompositingMode(CompositingModeSourceCopy);
+// //g.SetCompositingMode(CompositingModeSourceCopy);
+// // Create a string.
+//
+// WCHAR *string;
+// string = (WCHAR*)malloc(sizeof(WCHAR)*(nCount+2));
+// MultiByteToWideChar(CP_ACP, 0, lpString, -1, string, (nCount+2)*sizeof(WCHAR));
+// Font myFont(hDestDC);
+//
+// PointF origin((float)0, (float)0);
+// PointF origin2((float)x, (float)y);
+// g.SetTextRenderingHint(TextRenderingHintSystemDefault);
+// g.SetSmoothingMode(SmoothingModeAntiAlias);
+// COLORREF ref = GetTextColor(hDestDC);
+// SolidBrush blackBrush(Color(255, GetRValue(ref),GetGValue(ref),GetBValue(ref)));
+// g.SetInterpolationMode(InterpolationModeHighQualityBicubic);
+// g.DrawString(string,nCount,&myFont,origin, &blackBrush);
+// //g.SetCompositingMode(CompositingModeSourceCopy);
+// //s.SetCompositingMode(CompositingModeSourceCopy);
+// free(string);
+// //HDC temp = g.GetHDC();
+// //BitBlt(hDestDC,x,y,100,100,temp,0,0,SRCCOPY);
+// //g.ReleaseHDC(temp);
+// s.DrawImage(b,origin2);
+//
+}
+
+void DrawAvatarImageWithGDIp(HDC hDestDC,int x, int y, DWORD width, DWORD height, HBITMAP hbmp, int x1, int y1, DWORD width1, DWORD height1,DWORD flag,BYTE alpha)
+{
+ BITMAP bmp;
+ Bitmap *bm;
+ BYTE * bmbits = NULL;
+ GetObject(hbmp,sizeof(BITMAP),&bmp);
+ Graphics g(hDestDC);
+ if (bmp.bmBitsPixel == 32 && (flag&AVS_PREMULTIPLIED))
+ {
+ bmbits = (BYTE*)bmp.bmBits;
+ if ( !bmbits)
+ {
+ bmbits = (BYTE*)malloc(bmp.bmHeight*bmp.bmWidthBytes);
+ GetBitmapBits(hbmp,bmp.bmHeight*bmp.bmWidthBytes,bmbits);
+ }
+ bm = new Bitmap(bmp.bmWidth,bmp.bmHeight,bmp.bmWidthBytes,PixelFormat32bppPARGB,bmbits);
+ bm->RotateFlip(RotateNoneFlipY);
+ if ( !bmp.bmBits)
+ {
+ bm->RotateFlip(RotateNoneFlipY);
+ free(bmbits);
+ }
+ }
+ else
+ bm = new Bitmap(hbmp,NULL);
+
+ ImageAttributes attr;
+ ColorMatrix ClrMatrix =
+ {
+ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, ((float)alpha)/255, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ attr.SetColorMatrix(&ClrMatrix, ColorMatrixFlagsDefault,ColorAdjustTypeBitmap);
+ g.SetInterpolationMode(InterpolationModeHighQualityBicubic);
+ RectF rect((float)x,(float)y,(float)width,(float)height);
+ g.DrawImage(bm, rect, (float)x1, (float)y1, (float)width1, (float)height1 , UnitPixel, &attr, NULL, NULL);
+ delete bm;
+}
+BOOL GDIPlus_AlphaBlend(HDC hdcDest,int nXOriginDest,int nYOriginDest,int nWidthDest,int nHeightDest,HDC hdcSrc,int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc, BLENDFUNCTION * bf)
+{
+ Graphics g(hdcDest);
+ BITMAP bmp;
+ HBITMAP hbmp = (HBITMAP)GetCurrentObject(hdcSrc,OBJ_BITMAP);
+ GetObject(hbmp,sizeof(BITMAP),&bmp);
+ Bitmap *bm = new Bitmap(hbmp,NULL);
+ if (bmp.bmBitsPixel == 32 && bf->AlphaFormat)
+ {
+ bm = new Bitmap(bmp.bmWidth,bmp.bmHeight,bmp.bmWidthBytes,PixelFormat32bppPARGB,(BYTE*)bmp.bmBits);
+ bm->RotateFlip(RotateNoneFlipY);
+ }
+ else
+ bm = new Bitmap(hbmp,NULL);
+ ImageAttributes attr;
+ ColorMatrix ClrMatrix =
+ {
+ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, ((float)bf->SourceConstantAlpha)/255, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ attr.SetColorMatrix(&ClrMatrix, ColorMatrixFlagsDefault,ColorAdjustTypeBitmap);
+
+ if (bf->BlendFlags&128 && nWidthDest < nWidthSrc && nHeightDest < nHeightSrc)
+ {
+ g.SetInterpolationMode(InterpolationModeHighQualityBicubic);
+ g.SetPixelOffsetMode(PixelOffsetModeHalf);
+ attr.SetGamma((REAL)0.8,ColorAdjustTypeBitmap);
+ }
+ else
+ {
+ g.SetInterpolationMode(InterpolationModeLowQuality);
+ //g.SetPixelOffsetMode(PixelOffsetModeHalf);
+ }
+
+ RectF rect((float)nXOriginDest,(float)nYOriginDest,(float)nWidthDest,(float)nHeightDest);
+ g.DrawImage(bm, rect, (float)nXOriginSrc, (float)nYOriginSrc, (float)nWidthSrc, (float)nHeightSrc , UnitPixel, &attr, NULL, NULL);
+ delete bm;
+ return TRUE;
+}
+COLORREF __inline _revcolref(COLORREF colref)
+{
+ return RGB(GetBValue(colref), GetGValue(colref), GetRValue(colref));
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+// GDIPlus_IsAnimatedGIF and GDIPlus_ExtractAnimatedGIF
+// based on routine from http://www.codeproject.com/vcpp/gdiplus/imageexgdi.asp
+//
+
+BOOL GDIPlus_IsAnimatedGif (TCHAR * szName)
+{
+ int nFrameCount = 0;
+ Image image(szName);
+ UINT count = 0;
+
+ count = image.GetFrameDimensionsCount();
+ GUID* pDimensionIDs = new GUID[count];
+
+ // Get the list of frame dimensions from the Image object.
+ image.GetFrameDimensionsList(pDimensionIDs, count);
+
+ // Get the number of frames in the first dimension.
+ nFrameCount = image.GetFrameCount(&pDimensionIDs[0]);
+
+ delete[] pDimensionIDs;
+
+ return (BOOL) (nFrameCount > 1);
+}
+
+void GDIPlus_ExtractAnimatedGIF (TCHAR * szName, int width, int height, HBITMAP * pBitmap, int ** pframesDelay, int * pframesCount, SIZE * pSizeAvatar)
+{
+ int nFrameCount = 0;
+ Bitmap image(szName);
+ PropertyItem * pPropertyItem;
+
+ UINT count = 0;
+
+ count = image.GetFrameDimensionsCount();
+ GUID* pDimensionIDs = new GUID[count];
+
+ // Get the list of frame dimensions from the Image object.
+ image.GetFrameDimensionsList(pDimensionIDs, count);
+
+ // Get the number of frames in the first dimension.
+ nFrameCount = image.GetFrameCount(&pDimensionIDs[0]);
+
+ // Assume that the image has a property item of type PropertyItemEquipMake.
+ // Get the size of that property item.
+ int nSize = image.GetPropertyItemSize(PropertyTagFrameDelay);
+
+ // Allocate a buffer to receive the property item.
+ pPropertyItem = (PropertyItem*) malloc(nSize);
+
+ image.GetPropertyItem(PropertyTagFrameDelay, nSize, pPropertyItem);
+
+ int clipWidth;
+ int clipHeight;
+ int imWidth = image.GetWidth();
+ int imHeight = image.GetHeight();
+ float xscale = (float)width/imWidth;
+ float yscale = (float)height/imHeight;
+ xscale = min(xscale,yscale);
+ clipWidth = (int)(xscale*imWidth+.5);
+ clipHeight = (int)(xscale*imHeight+.5);
+
+ HBITMAP hBitmap = ske_CreateDIB32(clipWidth*nFrameCount, height);
+ HDC hdc = CreateCompatibleDC(NULL);
+ HBITMAP oldBmp = (HBITMAP)SelectObject(hdc,hBitmap);
+ Graphics graphics(hdc);
+ ImageAttributes attr;
+
+ graphics.SetInterpolationMode( InterpolationModeHighQualityBicubic );
+ graphics.SetPixelOffsetMode( PixelOffsetModeHalf );
+ int * delays = (int*)malloc(nFrameCount*sizeof(int));
+ memset(delays,0,nFrameCount*sizeof(int));
+
+ GUID pageGuid = FrameDimensionTime;
+ /*
+ The GDIPlus strange behavior: without next 2 lines it will draw first frame anti aliased, but next - not
+ */
+ if ( nFrameCount > 1 )
+ image.SelectActiveFrame(&pageGuid, 1 );
+
+ for (int i=0; i < nFrameCount; i++)
+ {
+ image.SelectActiveFrame( &pageGuid, i );
+ graphics.DrawImage( &image, Rect(i*clipWidth, 0,clipWidth,clipHeight ), 0, 0, imWidth, imHeight , UnitPixel, &attr);
+ long lPause = ((long*) pPropertyItem->value)[i] * 10;
+ delays[i] = (int)lPause;
+ }
+ SelectObject(hdc,oldBmp);
+ DeleteDC(hdc);
+ free(pPropertyItem);
+ delete[] pDimensionIDs;
+ if (pBitmap && pframesDelay && pframesCount && pSizeAvatar)
+ {
+ *pBitmap = hBitmap;
+ *pframesDelay = delays;
+ *pframesCount = nFrameCount;
+ pSizeAvatar->cx = clipWidth;
+ pSizeAvatar->cy = clipHeight;
+ }
+ GdiFlush();
+} \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_gettextasync.cpp b/plugins/Clist_modern/src/modern_gettextasync.cpp
new file mode 100644
index 0000000000..0e01838ae4
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_gettextasync.cpp
@@ -0,0 +1,205 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+/*
+* Author Artem Shpynov aka FYR
+* Copyright 2000-2008 Artem Shpynov
+*/
+
+//////////////////////////////////////////////////////////////////////////
+// Module to async parsing of texts
+
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_gettextasync.h"
+#include "newpluginapi.h"
+#include "hdr/modern_sync.h"
+
+int CLUI_SyncSetPDNCE(WPARAM wParam, LPARAM lParam);
+int CLUI_SyncGetShortData(WPARAM wParam, LPARAM lParam);
+
+#define gtalock EnterCriticalSection(&gtaCS)
+#define gtaunlock LeaveCriticalSection( &gtaCS )
+
+typedef struct _GetTextAsyncItem {
+ HANDLE hContact;
+ struct ClcData *dat;
+ struct _GetTextAsyncItem *Next;
+} GTACHAINITEM;
+
+static GTACHAINITEM * gtaFirstItem = NULL;
+static GTACHAINITEM * gtaLastItem = NULL;
+static CRITICAL_SECTION gtaCS;
+static HANDLE hgtaWakeupEvent = NULL;
+
+
+static BOOL gtaGetItem(GTACHAINITEM * mpChain)
+{
+ gtalock;
+ if ( !gtaFirstItem)
+ {
+ gtaunlock;
+ return FALSE;
+ }
+ else if (mpChain)
+ {
+ GTACHAINITEM * ch;
+ ch = gtaFirstItem;
+ *mpChain = *ch;
+ gtaFirstItem = (GTACHAINITEM *)ch->Next;
+ if ( !gtaFirstItem) gtaLastItem = NULL;
+ free(ch);
+ gtaunlock;
+ return TRUE;
+ }
+ gtaunlock;
+ return FALSE;
+}
+
+static int gtaThreadProc(void * lpParam)
+{
+ BOOL exit = FALSE;
+ HWND hwnd = pcli->hwndContactList;
+ struct SHORTDATA data = {0};
+ struct SHORTDATA * dat;
+
+ while (!MirandaExiting())
+ {
+ Sync(CLUI_SyncGetShortData,(WPARAM)pcli->hwndContactTree,(LPARAM)&data);
+ do
+ {
+ if ( !MirandaExiting())
+ SleepEx(0,TRUE); //1000 contacts per second
+ if (MirandaExiting())
+ {
+ g_dwGetTextAsyncThreadID = 0;
+ return 0;
+ }
+ else
+ {
+ GTACHAINITEM mpChain = {0};
+ struct SHORTDATA dat2 = {0};
+ if ( !gtaGetItem(&mpChain)) break;
+ if (mpChain.dat == NULL || (!IsBadReadPtr(mpChain.dat,sizeof(mpChain.dat)) && mpChain.dat->hWnd == data.hWnd)) dat = &data;
+ else
+ {
+ Sync(CLUI_SyncGetShortData,(WPARAM)mpChain.dat->hWnd,(LPARAM)&dat2);
+ dat = &dat2;
+ }
+ if ( !MirandaExiting())
+ {
+ displayNameCacheEntry cacheEntry;
+ memset( &cacheEntry, 0, sizeof(cacheEntry));
+ cacheEntry.hContact = mpChain.hContact;
+ if ( !Sync(CLUI_SyncGetPDNCE, (WPARAM) 0,(LPARAM)&cacheEntry))
+ {
+ if ( !MirandaExiting())
+ Cache_GetSecondLineText(dat, &cacheEntry);
+ if ( !MirandaExiting())
+ Cache_GetThirdLineText(dat, &cacheEntry);
+ if ( !MirandaExiting())
+ Sync(CLUI_SyncSetPDNCE, (WPARAM) CCI_LINES,(LPARAM)&cacheEntry);
+ CListSettings_FreeCacheItemData(&cacheEntry);
+ }
+ }
+ else
+ {
+ g_dwGetTextAsyncThreadID = 0;
+ return 0;
+ }
+ KillTimer(dat->hWnd,TIMERID_INVALIDATE_FULL);
+ CLUI_SafeSetTimer(dat->hWnd,TIMERID_INVALIDATE_FULL,500,NULL);
+ }
+ }
+ while (!exit);
+
+ WaitForSingleObjectEx(hgtaWakeupEvent, INFINITE, FALSE );
+ ResetEvent(hgtaWakeupEvent);
+ }
+ g_dwGetTextAsyncThreadID = 0;
+ return 1;
+}
+
+BOOL gtaWakeThread()
+{
+ if (hgtaWakeupEvent && g_dwGetTextAsyncThreadID)
+ {
+ SetEvent(hgtaWakeupEvent);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int gtaAddRequest(struct ClcData *dat,struct ClcContact *contact,HANDLE hContact)
+{
+ if (MirandaExiting()) return 0;
+ gtalock;
+ {
+ GTACHAINITEM * mpChain = (GTACHAINITEM *)malloc(sizeof(GTACHAINITEM));
+ mpChain->hContact = hContact;
+ mpChain->dat = dat;
+ mpChain->Next = NULL;
+ if (gtaLastItem)
+ {
+ gtaLastItem->Next = (GTACHAINITEM *)mpChain;
+ gtaLastItem = mpChain;
+ }
+ else
+ {
+ gtaFirstItem = mpChain;
+ gtaLastItem = mpChain;
+ SetEvent(hgtaWakeupEvent);
+ }
+ }
+ gtaunlock;
+ return FALSE;
+}
+void gtaRenewText(HANDLE hContact)
+{
+ gtaAddRequest(NULL,NULL, hContact);
+}
+int gtaOnModulesUnload(WPARAM wParam,LPARAM lParam)
+{
+ SetEvent(hgtaWakeupEvent);
+ return 0;
+}
+void InitCacheAsync()
+{
+ InitializeCriticalSection(&gtaCS);
+ hgtaWakeupEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
+ g_dwGetTextAsyncThreadID = (DWORD)mir_forkthread((pThreadFunc)gtaThreadProc,0);
+ HookEvent(ME_SYSTEM_PRESHUTDOWN, gtaOnModulesUnload);
+}
+
+void UninitCacheAsync()
+{
+ GTACHAINITEM mpChain;
+ SetEvent(hgtaWakeupEvent);
+ CloseHandle(hgtaWakeupEvent);
+ gtalock;
+ while(gtaGetItem(&mpChain));
+ gtaunlock;
+ DeleteCriticalSection(&gtaCS);
+}
diff --git a/plugins/Clist_modern/src/modern_global.cpp b/plugins/Clist_modern/src/modern_global.cpp
new file mode 100644
index 0000000000..269abb136e
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_global.cpp
@@ -0,0 +1,35 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+
+listed in contributors.txt.
+
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "hdr/modern_commonheaders.h"
+
+//////////////////////////////////////////////////////////////////////////
+// Global variables
+
+//int hClcProtoCount = 0;
+//ClcProtoStatus *clcProto = NULL;
+HIMAGELIST g_himlCListClc = NULL;
+HICON g_hListeningToIcon = NULL;
+char* g_szMetaModuleName = 0;
diff --git a/plugins/Clist_modern/src/modern_groupmenu.cpp b/plugins/Clist_modern/src/modern_groupmenu.cpp
new file mode 100644
index 0000000000..33c93a10a6
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_groupmenu.cpp
@@ -0,0 +1,754 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "hdr/modern_clc.h"
+
+//////////////////////////////Group MENU/////////////////////////
+HANDLE hGroupMenuObject;
+
+HANDLE hGroupMainMenuItemProxy;
+HANDLE hHideShowMainMenuItem;
+HANDLE hGroupStatusMenuItemProxy;
+
+HANDLE hHideOfflineUsersMenuItem;
+HANDLE hHideOfflineUsersOutHereMenuItem;
+HANDLE hHideEmptyGroupsMenuItem;
+HANDLE hDisableGroupsMenuItem;
+HANDLE hNewGroupMenuItem;
+HANDLE hNewSubGroupMenuItem;
+
+int NewGroupIconidx;
+
+void InitSubGroupMenus(void);
+
+//Groupmenu exec param(ownerdata)
+typedef struct{
+char *szServiceName;
+int Param1,Param2;
+}GroupMenuExecParam,*lpGroupMenuExecParam;
+
+/*
+wparam = handle to the menu item returned by MS_CLIST_ADDCONTACTMENUITEM
+return 0 on success.
+*/
+static INT_PTR RemoveGroupMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ CallService(MO_REMOVEMENUITEM,wParam,0);
+ return 0;
+}
+
+
+INT_PTR BuildGroupMenu(WPARAM wParam,LPARAM lParam)
+{
+ ListParam param = { 0 };
+ param.MenuObjectHandle = hGroupMenuObject;
+
+ //hMenu = hMainMenu;
+ HMENU hMenu = CreatePopupMenu();
+ //hMenu = wParam;
+ int tick = GetTickCount();
+
+ NotifyEventHooks(g_CluiData.hEventPreBuildGroupMenu,0,0);
+
+ CallService(MO_BUILDMENU,(WPARAM)hMenu,(LPARAM)&param);
+ //DrawMenuBar((HWND)CallService("CLUI/GetHwnd",0,0));
+ tick = GetTickCount()-tick;
+ return (INT_PTR)hMenu;
+}
+
+static INT_PTR AddGroupMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ TMO_MenuItem tmi;
+ CLISTMENUITEM *mi = (CLISTMENUITEM*)lParam;
+ if ( !pcli->pfnConvertMenu(mi, &tmi))
+ return NULL;
+
+ lpGroupMenuExecParam mmep = (lpGroupMenuExecParam)mir_calloc(sizeof(GroupMenuExecParam));
+ if (mmep == NULL)
+ return 0;
+
+ //we need just one parametr.
+ mmep->szServiceName = mir_strdup(mi->pszService);
+ mmep->Param1 = mi->popupPosition;
+ lpGroupMenuParam gmp = (lpGroupMenuParam)wParam;
+ if (gmp != NULL) {
+ mmep->Param1 = gmp->wParam;
+ mmep->Param2 = gmp->lParam;
+ }
+ tmi.ownerdata = mmep;
+
+ char buf[1024];
+ sprintf(buf,"%s/%s",mi->pszService,mi->pszName);
+
+ OptParam op;
+ op.Handle = (HANDLE)CallService(MO_ADDNEWMENUITEM,(WPARAM)hGroupMenuObject,(LPARAM)&tmi);
+ op.Setting = OPT_MENUITEMSETUNIQNAME;
+ op.Value = (INT_PTR)buf;
+ CallService(MO_SETOPTIONSMENUITEM,(WPARAM)0,(LPARAM)&op);
+ return (INT_PTR)op.Handle;
+}
+
+int GroupMenuCheckService(WPARAM wParam,LPARAM lParam) {
+//not used
+ return(0);
+};
+
+INT_PTR GroupMenuonAddService(WPARAM wParam,LPARAM lParam) {
+
+ MENUITEMINFO *mii = (MENUITEMINFO* )wParam;
+ if (mii == NULL) return 0;
+
+ if (hHideShowMainMenuItem == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_STATE;
+ mii->fState |= MFS_DEFAULT;
+
+ }
+ if (hGroupMainMenuItemProxy == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0);
+ }
+
+ if (hGroupStatusMenuItemProxy == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ }
+
+ return(TRUE);
+};
+
+
+//called with:
+//wparam - ownerdata
+//lparam - lparam from winproc
+INT_PTR GroupMenuExecService(WPARAM wParam,LPARAM lParam) {
+ if (wParam != 0)
+ {
+ lpGroupMenuExecParam mmep = (lpGroupMenuExecParam)wParam;
+ if ( !mir_strcmp(mmep->szServiceName,"Help/AboutCommand"))
+ {
+ //bug in help.c,it used wparam as parent window handle without reason.
+ mmep->Param1 = 0;
+ CallService(mmep->szServiceName,mmep->Param1,lParam);
+ }else
+ {
+ CallService(mmep->szServiceName,mmep->Param1,mmep->Param2);
+ }
+
+ };
+ return(1);
+};
+INT_PTR FreeOwnerDataGroupMenu (WPARAM wParam,LPARAM lParam)
+{
+
+ lpGroupMenuExecParam mmep;
+ mmep = (lpGroupMenuExecParam)lParam;
+ if (mmep != NULL){
+ FreeAndNil((void **)&mmep->szServiceName);
+ FreeAndNil((void **)&mmep);
+ }
+
+return(0);
+};
+
+INT_PTR HideGroupsHelper(WPARAM wParam,LPARAM lParam)
+{
+ int newVal = !(GetWindowLongPtr(pcli->hwndContactTree,GWL_STYLE)&CLS_HIDEEMPTYGROUPS);
+ db_set_b(NULL,"CList","HideEmptyGroups",(BYTE)newVal);
+ SendMessage(pcli->hwndContactTree,CLM_SETHIDEEMPTYGROUPS,newVal,0);
+ return 0;
+}
+
+INT_PTR UseGroupsHelper(WPARAM wParam,LPARAM lParam)
+{
+ int newVal = !(GetWindowLongPtr(pcli->hwndContactTree,GWL_STYLE)&CLS_USEGROUPS);
+ db_set_b(NULL,"CList","UseGroups",(BYTE)newVal);
+ SendMessage(pcli->hwndContactTree,CLM_SETUSEGROUPS,newVal,0);
+ return 0;
+}
+
+INT_PTR HideOfflineRootHelper(WPARAM wParam,LPARAM lParam)
+{
+SendMessage(
+ (HWND)CallService(MS_CLUI_GETHWNDTREE,0,0),
+ CLM_SETHIDEOFFLINEROOT,
+ !SendMessage((HWND)CallService(MS_CLUI_GETHWNDTREE,0,0),CLM_GETHIDEOFFLINEROOT,0,0),
+ 0);
+ return 0;
+};
+
+INT_PTR CreateGroupHelper(WPARAM wParam,LPARAM lParam)
+{
+ SendMessage((HWND)CallService(MS_CLUI_GETHWNDTREE,0,0), CLM_SETHIDEEMPTYGROUPS, 0, 0);
+ SendMessage((HWND)CallService(MS_CLUI_GETHWNDTREE,0,0), CLM_SETUSEGROUPS, 1, 0);
+ CallService(MS_CLIST_GROUPCREATE, 0, 0);
+
+ return 0;
+};
+
+static int OnBuildGroupMenu(WPARAM wParam,LPARAM lParam)
+{
+ CLISTMENUITEM mi;
+ if (MirandaExiting()) return 0;
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | (db_get_b(NULL,"CList","HideOffline",SETTING_HIDEOFFLINE_DEFAULT)?CMIF_CHECKED:0);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideOfflineUsersMenuItem, (LPARAM)&mi);
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | (SendMessage(pcli->hwndContactTree,CLM_GETHIDEOFFLINEROOT,0,0)?CMIF_CHECKED:0);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideOfflineUsersOutHereMenuItem, (LPARAM)&mi);
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | (GetWindowLongPtr(pcli->hwndContactTree,GWL_STYLE)&CLS_HIDEEMPTYGROUPS?CMIF_CHECKED:0);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideEmptyGroupsMenuItem, (LPARAM)&mi);
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | (GetWindowLongPtr(pcli->hwndContactTree,GWL_STYLE)&CLS_USEGROUPS?0:CMIF_CHECKED);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hDisableGroupsMenuItem, (LPARAM)&mi);
+
+ return 0;
+};
+
+int static OnIconLibIconChanged(WPARAM wParam,LPARAM lParam)
+{
+ HICON hicon;
+ CLISTMENUITEM clmi = {0};
+ BOOL needFree;
+ if (MirandaExiting()) return 0;
+ hicon = CLUI_LoadIconFromExternalFile("clisticons.dll",2,TRUE,FALSE,"NewGroup","Contact List","New Group",-IDI_NEWGROUP2,&needFree);
+ NewGroupIconidx = ImageList_ReplaceIcon(hCListImages,NewGroupIconidx,hicon);
+ if (needFree) DestroyIcon_protect(hicon);
+ clmi.cbSize = sizeof(clmi);
+ clmi.flags = CMIM_ICON;
+ clmi.hIcon = ske_ImageList_GetIcon(hCListImages,NewGroupIconidx,0);
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hNewSubGroupMenuItem,(LPARAM)&clmi);
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)hNewGroupMenuItem,(LPARAM)&clmi);
+ //
+
+
+ return 0;
+};
+
+void GroupMenus_Init(void)
+{
+ TMenuParam tmp;
+ OptParam op;
+ HICON hicon;
+ BOOL needFree;
+ hicon = CLUI_LoadIconFromExternalFile("clisticons.dll",2,TRUE,TRUE,"NewGroup","Contact List","New Group",-IDI_NEWGROUP2,&needFree);
+ NewGroupIconidx = hicon?ImageList_AddIcon(hCListImages,hicon ):-1;
+ if (needFree) DestroyIcon_protect(hicon);
+ CreateServiceFunction("CLISTMENUSGroup/ExecService",GroupMenuExecService);
+ CreateServiceFunction("CLISTMENUSGroup/FreeOwnerDataGroupMenu",FreeOwnerDataGroupMenu);
+ CreateServiceFunction("CLISTMENUSGroup/GroupMenuonAddService",GroupMenuonAddService);
+ CreateServiceFunction("CLISTMENUSGroup/HideGroupsHelper",HideGroupsHelper);
+ CreateServiceFunction("CLISTMENUSGroup/UseGroupsHelper",UseGroupsHelper);
+ CreateServiceFunction("CLISTMENUSGroup/HideOfflineRootHelper",HideOfflineRootHelper);
+ CreateServiceFunction("CLISTMENUSGroup/CreateGroupHelper",CreateGroupHelper);
+
+ CreateServiceFunction("CList/AddGroupMenuItem",AddGroupMenuItem);
+ CreateServiceFunction(MS_CLIST_REMOVEGROUPMENUITEM,RemoveGroupMenuItem);
+ CreateServiceFunction(MS_CLIST_MENUBUILDGROUP,BuildGroupMenu);
+
+ HookEvent(ME_CLIST_PREBUILDGROUPMENU,OnBuildGroupMenu);
+
+ InitSubGroupMenus();
+
+ //Group menu
+ memset(&tmp,0,sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ tmp.CheckService = NULL;
+ tmp.ExecService = "CLISTMENUSGroup/ExecService";
+ tmp.name = LPGEN("GroupMenu");
+ hGroupMenuObject = (HANDLE)CallService(MO_CREATENEWMENUOBJECT,(WPARAM)0,(LPARAM)&tmp);
+
+
+ op.Handle = hGroupMenuObject;
+ op.Setting = OPT_USERDEFINEDITEMS;
+ op.Value = TRUE;
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ op.Handle = hGroupMenuObject;
+ op.Setting = OPT_MENUOBJECT_SET_FREE_SERVICE;
+ op.Value = (INT_PTR)"CLISTMENUSGroup/FreeOwnerDataGroupMenu";
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ op.Handle = hGroupMenuObject;
+ op.Setting = OPT_MENUOBJECT_SET_ONADD_SERVICE;
+ op.Value = (INT_PTR)"CLISTMENUSGroup/GroupMenuonAddService";
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ {
+ //add exit command to menu
+ CLISTMENUITEM mi;
+ GroupMenuParam gmp;
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 1900000;
+ mi.pszService = "CloseAction";
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_EXIT);
+ mi.pszName = LPGEN("E&xit");
+ mi.flags = CMIF_ICONFROMICOLIB;
+ AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 500;
+ mi.pszService = MS_CLIST_SHOWHIDE;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_SHOWHIDE);
+ mi.pszName = LPGEN("&Hide/Show");
+ mi.flags = CMIF_ICONFROMICOLIB;
+ hHideShowMainMenuItem = (HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 200000;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_FINDUSER);
+ mi.pszService = "FindAdd/FindAddCommand";
+ mi.pszName = LPGEN("&Find/Add Contacts...");
+ AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 300000;
+ mi.pszService = "";
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_MAINMENU); // eternity #004
+ mi.pszName = LPGEN("&Main Menu");
+ mi.flags = CMIF_ICONFROMICOLIB; // eternity #004
+ hGroupMainMenuItemProxy = (HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon); // eternity #004
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 300100;
+ mi.pszService = "";
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_STATUS); // eternity #004
+ mi.pszName = LPGEN("&Status");
+ mi.flags = CMIF_ICONFROMICOLIB; // eternity #004
+ hGroupStatusMenuItemProxy = (HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon); // eternity #004
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 400000;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_OPTIONS);
+ mi.pszService = "Options/OptionsCommand";
+ mi.pszName = LPGEN("&Options...");
+ AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 500000;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_MIRANDA);
+ mi.pszService = "Help/AboutCommand";
+ mi.pszName = LPGEN("&About");
+ AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100000;
+ mi.hIcon = ske_ImageList_GetIcon(hCListImages,NewGroupIconidx,0);
+ mi.pszService = "CLISTMENUSGroup/CreateGroupHelper";
+ mi.pszName = LPGEN("&New Group");
+ hNewGroupMenuItem = (HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100001;
+ mi.hIcon = NULL;
+ mi.pszService = MS_CLIST_SETHIDEOFFLINE;
+ mi.pszName = LPGEN("&Hide Offline Users");
+ gmp.lParam = 0;gmp.wParam = -1;
+ hHideOfflineUsersMenuItem = (HANDLE)AddGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100002;
+ mi.hIcon = NULL;
+ mi.pszService = "CLISTMENUSGroup/HideOfflineRootHelper";
+ mi.pszName = LPGEN("Hide &Offline Users out here");
+ hHideOfflineUsersOutHereMenuItem = (HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100003;
+ mi.hIcon = NULL;
+ mi.pszService = "CLISTMENUSGroup/HideGroupsHelper";
+ mi.pszName = LPGEN("Hide &Empty Groups");
+ hHideEmptyGroupsMenuItem = (HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+
+
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 100004;
+ mi.hIcon = NULL;
+ mi.pszService = "CLISTMENUSGroup/UseGroupsHelper";
+ mi.pszName = LPGEN("Disable &Groups");
+ hDisableGroupsMenuItem = (HANDLE)AddGroupMenuItem((WPARAM)0,(LPARAM)&mi);
+
+
+ HookEvent(ME_SKIN2_ICONSCHANGED,OnIconLibIconChanged);
+
+ //MS_CLIST_GROUPCREATE
+
+ };
+}
+
+//////////////////////////////END Group MENU/////////////////////////
+
+
+
+
+//////////////////////////////SubGroup MENU/////////////////////////
+HANDLE hSubGroupMenuObject;
+
+HANDLE hSubGroupMainMenuItemProxy;
+HANDLE hSubGroupStatusMenuItemProxy;
+HANDLE hHideOfflineUsersHereMenuItem;
+HANDLE hShowOfflineUsersHereMenuItem;
+
+//SubGroupmenu exec param(ownerdata)
+typedef struct{
+char *szServiceName;
+int Param1,Param2;
+}SubGroupMenuExecParam,*lpSubGroupMenuExecParam;
+
+/*
+wparam = handle to the menu item returned by MS_CLIST_ADDCONTACTMENUITEM
+return 0 on success.
+*/
+static INT_PTR RemoveSubGroupMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ CallService(MO_REMOVEMENUITEM,wParam,0);
+ return 0;
+}
+
+
+static int OnBuildSubGroupMenu(WPARAM wParam,LPARAM lParam)
+{
+ CLISTMENUITEM mi;
+ BOOL gray1 = FALSE;
+ BOOL gray2 = FALSE;
+ BOOL showOfflineinGroup = FALSE;
+
+
+ struct ClcGroup *group = (struct ClcGroup *)wParam;
+ if (wParam == 0) return 0;
+
+ if (MirandaExiting()) return 0;
+ //contact->group
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+
+ showOfflineinGroup = CLCItems_IsShowOfflineGroup(group);
+ gray1 = (showOfflineinGroup != FALSE);
+ gray2 = (group->hideOffline != FALSE);
+
+ if (gray1 && gray2) gray1 = FALSE; //should not be cause CLCItems_IsShowOfflineGroup return false if group->hideOffline
+
+ mi.flags = CMIM_FLAGS | ((group->hideOffline && !gray1)?CMIF_CHECKED:0)| (gray1?CMIF_GRAYED:0);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hHideOfflineUsersHereMenuItem, (LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS | ((showOfflineinGroup && !gray2) ? CMIF_CHECKED:0)| (gray2?CMIF_GRAYED:0);
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hShowOfflineUsersHereMenuItem, (LPARAM)&mi);
+
+ return 0;
+};
+INT_PTR BuildSubGroupMenu(WPARAM wParam,LPARAM lParam)
+{
+ ListParam param = { 0 };
+ param.MenuObjectHandle = hSubGroupMenuObject;
+ param.wParam = wParam;
+ param.lParam = lParam;
+
+ //hMenu = hMainMenu;
+ HMENU hMenu = CreatePopupMenu();
+ //hMenu = wParam;
+ int tick = GetTickCount();
+
+ NotifyEventHooks(g_CluiData.hEventPreBuildSubGroupMenu,wParam,0);
+
+ CallService(MO_BUILDMENU,(WPARAM)hMenu,(LPARAM)&param);
+ //DrawMenuBar((HWND)CallService("CLUI/GetHwnd",0,0));
+ tick = GetTickCount()-tick;
+ return (INT_PTR)hMenu;
+}
+
+HMENU cliBuildGroupPopupMenu(struct ClcGroup *group)
+{
+ //HWND wnd = GetForegroundWindow();
+ return (HMENU)CallService(MS_CLIST_MENUBUILDSUBGROUP,(WPARAM)group,0);
+}
+static INT_PTR AddSubGroupMenuItem(WPARAM wParam,LPARAM lParam)
+{
+ TMO_MenuItem tmi;
+ CLISTMENUITEM *mi = (CLISTMENUITEM*)lParam;
+ if ( !pcli->pfnConvertMenu(mi, &tmi))
+ return NULL;
+
+ lpSubGroupMenuExecParam mmep = (lpSubGroupMenuExecParam)mir_calloc(sizeof(SubGroupMenuExecParam));
+ if ( mmep == NULL)
+ return 0;
+
+ //we need just one parametr.
+ mmep->szServiceName = mir_strdup(mi->pszService);
+ mmep->Param1 = mi->popupPosition;
+ lpGroupMenuParam gmp = (lpGroupMenuParam)wParam;
+ if (gmp != NULL) {
+ mmep->Param1 = gmp->wParam;
+ mmep->Param2 = gmp->lParam;
+ }
+ tmi.ownerdata = mmep;
+
+ char buf[1024];
+ sprintf(buf,"%s/%s",mi->pszService,mi->pszName);
+
+ OptParam op;
+ op.Handle = (HANDLE)CallService(MO_ADDNEWMENUITEM,(WPARAM)hSubGroupMenuObject,(LPARAM)&tmi);
+ op.Setting = OPT_MENUITEMSETUNIQNAME;
+ op.Value = (INT_PTR)buf;
+ CallService(MO_SETOPTIONSMENUITEM,(WPARAM)0,(LPARAM)&op);
+ return (INT_PTR)op.Handle;
+}
+
+INT_PTR SubGroupMenuCheckService(WPARAM wParam,LPARAM lParam) {
+//not used
+ //TODO ADD
+ lpSubGroupMenuExecParam mmep;
+ TCheckProcParam * CParam = (TCheckProcParam*)wParam;
+ if (CParam)
+ {
+
+ mmep = (lpSubGroupMenuExecParam)(CParam->MenuItemOwnerData);
+ if (mmep)
+ {
+ mmep->Param2 = CParam->lParam;
+ }
+
+ }
+ return(1);
+};
+
+INT_PTR SubGroupMenuonAddService(WPARAM wParam,LPARAM lParam) {
+
+ MENUITEMINFO *mii = (MENUITEMINFO* )wParam;
+
+ if (mii == NULL) return 0;
+
+/*
+ if (hHideShowMainMenuItem == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_STATE;
+ mii->fState |= MFS_DEFAULT;
+
+ }
+ if (hSubGroupMainMenuItemProxy == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0);
+ }
+
+ if (hSubGroupStatusMenuItemProxy == (HANDLE)lParam)
+ {
+ mii->fMask |= MIIM_SUBMENU;
+ //mi.fType = MFT_STRING;
+ mii->hSubMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ }
+*/
+ return(TRUE);
+};
+
+
+//called with:
+//wparam - ownerdata
+//lparam - lparam from winproc
+INT_PTR SubGroupMenuExecService(WPARAM wParam,LPARAM lParam) {
+ if (wParam != 0)
+ {
+ lpSubGroupMenuExecParam mmep = (lpSubGroupMenuExecParam)wParam;
+ if ( !mir_strcmp(mmep->szServiceName,"Help/AboutCommand"))
+ {
+ //bug in help.c,it used wparam as parent window handle without reason.
+ mmep->Param1 = 0;
+ CallService(mmep->szServiceName,mmep->Param1,lParam);
+ }else
+ {
+ CallService(mmep->szServiceName,mmep->Param1,lParam);
+ }
+
+ };
+ return(1);
+};
+INT_PTR FreeOwnerDataSubGroupMenu (WPARAM wParam,LPARAM lParam)
+{
+
+ lpSubGroupMenuExecParam mmep;
+ mmep = (lpSubGroupMenuExecParam)lParam;
+ if (mmep != NULL){
+ FreeAndNil((void **)&mmep->szServiceName);
+ FreeAndNil((void **)&mmep);
+ }
+
+return(0);
+};
+
+//wparam menu handle to pass to clc.c
+//lparam WM_COMMAND HWND
+INT_PTR GroupMenuExecProxy(WPARAM wParam,LPARAM lParam)
+{
+ SendMessage(lParam?(HWND)lParam:(HWND)pcli->hwndContactTree,WM_COMMAND,wParam,0);
+ return 0;
+};
+
+void InitSubGroupMenus(void)
+{
+ TMenuParam tmp;
+ OptParam op;
+
+ CreateServiceFunction("CLISTMENUSSubGroup/ExecService",SubGroupMenuExecService);
+ CreateServiceFunction("CLISTMENUSSubGroup/FreeOwnerDataSubGroupMenu",FreeOwnerDataSubGroupMenu);
+ CreateServiceFunction("CLISTMENUSSubGroup/SubGroupMenuonAddService",SubGroupMenuonAddService);
+ CreateServiceFunction("CLISTMENUSSubGroup/SubGroupMenuCheckService",SubGroupMenuCheckService);
+ CreateServiceFunction("CLISTMENUSSubGroup/GroupMenuExecProxy",GroupMenuExecProxy);
+
+ //CreateServiceFunction("CLISTMENUSSubGroup/HideSubGroupsHelper",HideSubGroupsHelper);
+ //CreateServiceFunction("CLISTMENUSSubGroup/UseSubGroupsHelper",UseSubGroupsHelper);
+ //CreateServiceFunction("CLISTMENUSSubGroup/HideOfflineRootHelper",HideOfflineRootHelper);
+
+ CreateServiceFunction("CList/AddSubGroupMenuItem",AddSubGroupMenuItem);
+ CreateServiceFunction(MS_CLIST_REMOVESUBGROUPMENUITEM,RemoveSubGroupMenuItem);
+ CreateServiceFunction(MS_CLIST_MENUBUILDSUBGROUP,BuildSubGroupMenu);
+
+ HookEvent(ME_CLIST_PREBUILDSUBGROUPMENU,OnBuildSubGroupMenu);
+
+ //SubGroup menu
+ memset(&tmp,0,sizeof(tmp));
+ tmp.cbSize = sizeof(tmp);
+ tmp.CheckService = NULL;
+ tmp.ExecService = "CLISTMENUSSubGroup/ExecService";
+ tmp.name = LPGEN("SubGroupMenu");
+ hSubGroupMenuObject = (HANDLE)CallService(MO_CREATENEWMENUOBJECT,(WPARAM)0,(LPARAM)&tmp);
+
+ op.Handle = hSubGroupMenuObject;
+ op.Setting = OPT_USERDEFINEDITEMS;
+ op.Value = TRUE;
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ op.Handle = hSubGroupMenuObject;
+ op.Setting = OPT_MENUOBJECT_SET_FREE_SERVICE;
+ op.Value = (INT_PTR)"CLISTMENUSSubGroup/FreeOwnerDataSubGroupMenu";
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ op.Handle = hSubGroupMenuObject;
+ op.Setting = OPT_MENUOBJECT_SET_ONADD_SERVICE;
+ op.Value = (INT_PTR)"CLISTMENUSSubGroup/SubGroupMenuonAddService";
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ op.Handle = hSubGroupMenuObject;
+ op.Setting = OPT_MENUOBJECT_SET_CHECK_SERVICE;
+ op.Value = (INT_PTR)"CLISTMENUSSubGroup/SubGroupMenuCheckService";
+ CallService(MO_SETOPTIONSMENUOBJECT,(WPARAM)0,(LPARAM)&op);
+
+ //add exit command to menu
+ CLISTMENUITEM mi;
+ GroupMenuParam gmp;
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 1000;
+ mi.hIcon = ske_ImageList_GetIcon(hCListImages,NewGroupIconidx,0);
+ mi.pszService = "CLISTMENUSSubGroup/GroupMenuExecProxy";
+ mi.pszName = LPGEN("&New SubGroup");
+ gmp.lParam = 0;gmp.wParam = POPUP_NEWSUBGROUP;
+ hNewSubGroupMenuItem = (HANDLE)AddSubGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 1001;
+ mi.hIcon = NULL;
+ mi.pszService = "CLISTMENUSSubGroup/GroupMenuExecProxy";
+ mi.pszName = LPGEN("&Hide Offline Users in here");
+ gmp.lParam = 0;
+ gmp.wParam = POPUP_GROUPHIDEOFFLINE;
+ hHideOfflineUsersHereMenuItem = (HANDLE)AddSubGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 1002;
+ mi.hIcon = NULL;
+ mi.pszService = "CLISTMENUSSubGroup/GroupMenuExecProxy";
+ mi.pszName = LPGEN("&Show Offline Users in here");
+ gmp.lParam = 0;
+ gmp.wParam = POPUP_GROUPSHOWOFFLINE;
+ hShowOfflineUsersHereMenuItem = (HANDLE)AddSubGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 900001;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_RENAME);
+ mi.pszService = "CLISTMENUSSubGroup/GroupMenuExecProxy";
+ mi.pszName = LPGEN("&Rename Group");
+ gmp.lParam = 0;gmp.wParam = POPUP_RENAMEGROUP;
+ AddSubGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+
+ memset(&mi,0,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.position = 900002;
+ mi.flags = CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_DELETE);
+ mi.pszService = "CLISTMENUSSubGroup/GroupMenuExecProxy";
+ mi.pszName = LPGEN("&Delete Group");
+ gmp.lParam = 0;gmp.wParam = POPUP_DELETEGROUP;
+ AddSubGroupMenuItem((WPARAM)&gmp,(LPARAM)&mi);
+ DestroyIcon_protect(mi.hIcon);
+}
+
+//////////////////////////////END SubGroup MENU/////////////////////////
diff --git a/plugins/Clist_modern/src/modern_image_array.cpp b/plugins/Clist_modern/src/modern_image_array.cpp
new file mode 100644
index 0000000000..21a87c18d7
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_image_array.cpp
@@ -0,0 +1,705 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Created by Pescuma
+
+*/
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_image_array.h"
+#include "hdr/modern_commonprototypes.h"
+
+// To use this code in other places, replace the body of this func by the body of ske_CreateDIB32
+static HBITMAP ImageArray_CreateBitmapPoint(int cx, int cy, void ** pt)
+{
+ return ske_CreateDIB32Point(cx, cy, pt);
+}
+
+
+// Initialize data
+static BOOL ImageArray_Alloc(LP_IMAGE_ARRAY_DATA iad, int size)
+{
+ int size_grow = size;
+
+ if (size_grow > iad->nodes_allocated_size)
+ {
+ size_grow += iad->grow_step - (size_grow % iad->grow_step);
+
+ if (iad->nodes != NULL)
+ {
+ IMAGE_ARRAY_DATA_NODE *tmp = (IMAGE_ARRAY_DATA_NODE *) realloc((void *)iad->nodes,
+ sizeof(IMAGE_ARRAY_DATA_NODE) * size_grow);
+
+ if (tmp == NULL)
+ {
+ TRACE("Out of memory: realloc returned NULL (ImageArray_Alloc)");
+ ImageArray_Free(iad, FALSE);
+ return FALSE;
+ }
+
+ iad->nodes = tmp;
+ memset( &iad->nodes[iad->nodes_allocated_size], 0, (size_grow - iad->nodes_allocated_size) * sizeof(IMAGE_ARRAY_DATA_NODE));
+ }
+ else
+ {
+ iad->nodes = (IMAGE_ARRAY_DATA_NODE *) malloc(sizeof(IMAGE_ARRAY_DATA_NODE) * size_grow);
+
+ if (iad->nodes == NULL)
+ {
+ TRACE("Out of memory: alloc returned NULL (ImageArray_Alloc)");
+
+ ImageArray_Free(iad, FALSE);
+
+ return FALSE;
+ }
+
+ ZeroMemory(iad->nodes, sizeof(IMAGE_ARRAY_DATA_NODE) * size_grow);
+ }
+
+ iad->nodes_allocated_size = size_grow;
+ }
+ else if (size < iad->nodes_allocated_size)
+ {
+ // Give some more space to try to avoid a free
+ if ((iad->nodes_allocated_size - size) / iad->grow_step >= 2 )
+ {
+ IMAGE_ARRAY_DATA_NODE *tmp;
+
+ size_grow += iad->grow_step - (size_grow % iad->grow_step);
+
+ tmp = (IMAGE_ARRAY_DATA_NODE *) realloc((void *)iad->nodes, sizeof(IMAGE_ARRAY_DATA_NODE) * size_grow);
+
+ if (tmp == NULL)
+ {
+ TRACE("Out of memory: realloc returned NULL when reducing size! (ImageArray_Alloc)");
+
+ ImageArray_Free(iad, FALSE);
+
+ return FALSE;
+ }
+
+ iad->nodes = tmp;
+ }
+ }
+
+ iad->nodes_size = size;
+
+ return TRUE;
+}
+
+
+// Initialize data
+void ImageArray_Initialize(LP_IMAGE_ARRAY_DATA iad, BOOL width_based, int grow_step)
+{
+ iad->width_based = width_based;
+ iad->grow_step = grow_step;
+ if (iad->grow_step <= 0)
+ {
+ iad->grow_step = 1;
+ }
+ iad->hdc = CreateCompatibleDC(NULL);
+ iad->img = NULL;
+
+ iad->width = 0;
+ iad->height = 0;
+
+ InitializeCriticalSection(&iad->cs);
+
+ iad->nodes = NULL;
+ iad->nodes_allocated_size = 0;
+ iad->nodes_size = 0;
+}
+
+
+// Free data
+// If keep_bitmap is TRUE, doesn't delete de bitmap and return its handle. Else, return NULL
+HBITMAP ImageArray_Free(LP_IMAGE_ARRAY_DATA iad, BOOL keep_bitmap)
+{
+ mod_DeleteDC(iad->hdc);
+
+ if (iad->img != NULL && !keep_bitmap)
+ {
+ DeleteObject(iad->img);
+ iad->img = NULL;
+ iad->width = 0;
+ iad->height = 0;
+ }
+
+ if (iad->nodes != NULL)
+ {
+ free(iad->nodes);
+ iad->nodes = NULL;
+ iad->nodes_allocated_size = 0;
+ iad->nodes_size = 0;
+ }
+
+ DeleteCriticalSection(&iad->cs);
+
+ return iad->img;
+}
+
+// Free data but keep config
+void ImageArray_Clear(LP_IMAGE_ARRAY_DATA iad)
+{
+ HDC tmpdc = CreateCompatibleDC(iad->hdc);
+ if (iad->hdc) mod_DeleteDC(iad->hdc);
+ iad->hdc = tmpdc;
+
+ if (iad->img != NULL)
+ {
+ DeleteObject(iad->img);
+ iad->img = NULL;
+ iad->width = 0;
+ iad->height = 0;
+ }
+
+ if (iad->nodes != NULL)
+ {
+ free(iad->nodes);
+ iad->nodes = NULL;
+ iad->nodes_allocated_size = 0;
+ iad->nodes_size = 0;
+ }
+}
+
+
+// Add image to the list (return the index of the image or -1 on error)
+// If pos == -1, add to the end of the list
+int ImageArray_AddImage(LP_IMAGE_ARRAY_DATA iad, HBITMAP hBmp, int pos)
+{
+ BITMAP bm;
+ int new_width, new_height;
+ HBITMAP hNewBmp, old_bmp;
+ HDC hdc_old;
+ BOOL last_one;
+
+ int i;
+
+ if (hBmp == NULL)
+ return -1;
+
+ EnterCriticalSection(&iad->cs);
+
+ if (pos < 0)
+ pos = iad->nodes_size;
+
+ // Add to end?
+ if (pos >= iad->nodes_size)
+ {
+ pos = iad->nodes_size;
+ last_one = TRUE;
+ }
+ else
+ {
+ last_one = FALSE;
+ }
+
+ // Get bounds
+ if ( !GetObject(hBmp,sizeof(BITMAP),&bm))
+ {
+ LeaveCriticalSection(&iad->cs);
+ return -1;
+ }
+
+ if (iad->width_based)
+ {
+ new_width = max(bm.bmWidth, iad->width);
+ new_height = iad->height + bm.bmHeight;
+ }
+ else
+ {
+ new_width = bm.bmWidth + iad->width;
+ new_height = max(iad->height, bm.bmHeight);
+ }
+
+ // Alloc image
+ hNewBmp = ImageArray_CreateBitmapPoint(new_width, new_height,&(iad->lpBits));
+ if (hNewBmp == NULL)
+ {
+ LeaveCriticalSection(&iad->cs);
+ return -1;
+ }
+
+ // Alloc array
+ if ( !ImageArray_Alloc(iad, iad->nodes_size + 1))
+ {
+ DeleteObject(hNewBmp);
+ LeaveCriticalSection(&iad->cs);
+ return -1;
+ }
+
+ // Move image...
+
+ // Set some draw states
+ SelectObject(iad->hdc, hNewBmp);
+ hdc_old = CreateCompatibleDC(iad->hdc);
+ old_bmp = (HBITMAP)GetCurrentObject(hdc_old, OBJ_BITMAP);
+
+ SetBkMode(iad->hdc,TRANSPARENT);
+ {
+ POINT org;
+ GetBrushOrgEx(iad->hdc, &org);
+ SetStretchBltMode(iad->hdc, HALFTONE);
+ SetBrushOrgEx(iad->hdc, org.x, org.y, NULL);
+ }
+
+ {
+ int x = 0, y = 0, w = 0, h = 0;
+
+ // 1- old data
+ if (pos > 0)
+ {
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ w = iad->width;
+ h = 0;
+ for (i=0; i < pos; i++)
+ {
+ h += iad->nodes[i].height;
+ }
+ }
+ else
+ {
+ h = iad->height;
+ w = 0;
+ for (i=0; i < pos; i++)
+ {
+ w += iad->nodes[i].width;
+ }
+ }
+ BitBlt(iad->hdc, 0, 0, w, h, hdc_old, 0, 0, SRCCOPY);
+ }
+
+ // 2- new image
+ if (iad->width_based)
+ {
+ x = 0;
+ y = h;
+ }
+ else
+ {
+ x = w;
+ y = 0;
+ }
+ SelectObject(hdc_old, hBmp);
+ BitBlt(iad->hdc, x, y, bm.bmWidth, bm.bmHeight, hdc_old, 0, 0, SRCCOPY);
+
+ // 3- old data
+ if ( !last_one)
+ {
+ int ox, oy;
+
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ ox = 0;
+ oy = y;
+
+ x = 0;
+ y += bm.bmHeight;
+
+ w = iad->width;
+ h = iad->height - h;
+ }
+ else
+ {
+ ox = x;
+ oy = 0;
+
+ x += bm.bmWidth;
+ y = 0;
+
+ w = iad->width - w;
+ h = iad->height;
+ }
+ BitBlt(iad->hdc, x, y, w, h, hdc_old, ox, oy, SRCCOPY);
+ }
+ }
+
+ // restore things
+ SelectObject(hdc_old,old_bmp);
+ mod_DeleteDC(hdc_old);
+ if (iad->img != NULL) DeleteObject(iad->img);
+ iad->img = hNewBmp;
+
+ // Move array
+ if ( !last_one && iad->nodes_size > 1)
+ {
+ memmove(&iad->nodes[pos+1], &iad->nodes[pos], (iad->nodes_size - pos) * sizeof(IMAGE_ARRAY_DATA_NODE));
+ }
+ iad->nodes[pos].width = bm.bmWidth;
+ iad->nodes[pos].height = bm.bmHeight;
+
+ iad->width = new_width;
+ iad->height = new_height;
+
+ // Finished it!
+ LeaveCriticalSection(&iad->cs);
+
+ return pos;
+}
+
+
+
+// Change an image in the list (return TRUE on success)
+BOOL ImageArray_ChangeImage(LP_IMAGE_ARRAY_DATA iad, HBITMAP hBmp, int pos)
+{
+ BITMAP bm;
+ int new_width, new_height;
+ HBITMAP hNewBmp;
+ HDC hdc_old;
+ int i;
+
+ if (hBmp == NULL)
+ return FALSE;
+
+ if (pos < 0)
+ return FALSE;
+
+ if (pos >= iad->nodes_size)
+ return FALSE;
+
+ EnterCriticalSection(&iad->cs);
+
+ // Get bounds
+ if ( !GetObject(hBmp,sizeof(BITMAP),&bm))
+ {
+ LeaveCriticalSection(&iad->cs);
+ return FALSE;
+ }
+
+ if (iad->width_based)
+ {
+ new_width = max(bm.bmWidth, iad->width);
+ new_height = iad->height + bm.bmHeight - iad->nodes[pos].height;
+ }
+ else
+ {
+ new_width = bm.bmWidth + iad->width - iad->nodes[pos].width;
+ new_height = max(iad->height, bm.bmHeight);
+ }
+
+ // Alloc image
+ hNewBmp = ImageArray_CreateBitmapPoint(new_width, new_height,&(iad->lpBits));
+ if (hNewBmp == NULL)
+ {
+ LeaveCriticalSection(&iad->cs);
+ return FALSE;
+ }
+
+ // Move image...
+
+ // Set some draw states
+ SelectObject(iad->hdc, hNewBmp);
+ hdc_old = CreateCompatibleDC(iad->hdc);
+
+ SetBkMode(iad->hdc, TRANSPARENT);
+ {
+ POINT org;
+ GetBrushOrgEx(iad->hdc, &org);
+ SetStretchBltMode(iad->hdc, HALFTONE);
+ SetBrushOrgEx(iad->hdc, org.x, org.y, NULL);
+ }
+
+ {
+ int x = 0, y = 0, w = 0, h = 0;
+
+ // 1- old data
+ if (pos > 0)
+ {
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ w = iad->width;
+ h = 0;
+ for (i=0; i < pos; i++)
+ {
+ h += iad->nodes[i].height;
+ }
+ }
+ else
+ {
+ h = iad->height;
+ w = 0;
+ for (i=0; i < pos; i++)
+ {
+ w += iad->nodes[i].width;
+ }
+ }
+ BitBlt(iad->hdc, 0, 0, w, h, hdc_old, 0, 0, SRCCOPY);
+ }
+
+ // 2- new image
+ if (iad->width_based)
+ {
+ x = 0;
+ y = h;
+ }
+ else
+ {
+ x = w;
+ y = 0;
+ }
+ SelectObject(hdc_old, hBmp);
+ BitBlt(iad->hdc, x, y, bm.bmWidth, bm.bmHeight, hdc_old, 0, 0, SRCCOPY);
+
+ // 3- old data
+ if (pos < iad->nodes_size - 1)
+ {
+ int ox, oy;
+
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ ox = 0;
+ oy = y + iad->nodes[pos].height;
+
+ x = 0;
+ y += bm.bmHeight;
+
+ w = iad->width;
+ h = iad->height - h - iad->nodes[pos].height;
+ }
+ else
+ {
+ ox = x + iad->nodes[pos].width;
+ oy = 0;
+
+ x += bm.bmWidth;
+ y = 0;
+
+ w = iad->width - w - iad->nodes[pos].width;
+ h = iad->height;
+ }
+ BitBlt(iad->hdc, x, y, w, h, hdc_old, ox, oy, SRCCOPY);
+ }
+ }
+
+ // restore things
+ mod_DeleteDC(hdc_old);
+ if (iad->img != NULL) DeleteObject(iad->img);
+ iad->img = hNewBmp;
+
+ // Move array
+ iad->nodes[pos].width = bm.bmWidth;
+ iad->nodes[pos].height = bm.bmHeight;
+
+ iad->width = new_width;
+ iad->height = new_height;
+
+ // Finished it!
+ LeaveCriticalSection(&iad->cs);
+
+ return pos;
+}
+
+
+// Remove an image
+BOOL ImageArray_RemoveImage(LP_IMAGE_ARRAY_DATA iad, int pos)
+{
+ int new_width, new_height;
+ HBITMAP hNewBmp;
+ HDC hdc_old;
+ int i;
+
+ if (pos < 0)
+ return FALSE;
+
+ if (pos >= iad->nodes_size)
+ return FALSE;
+
+ EnterCriticalSection(&iad->cs);
+
+ // Get bounds
+ if (iad->width_based)
+ {
+ new_width = iad->width;
+ new_height = iad->height - iad->nodes[pos].height;
+ }
+ else
+ {
+ new_width = iad->width - iad->nodes[pos].width;
+ new_height = iad->height;
+ }
+
+ // Alloc image
+ hNewBmp = ImageArray_CreateBitmapPoint(new_width, new_height,&(iad->lpBits));
+ if (hNewBmp == NULL)
+ {
+ LeaveCriticalSection(&iad->cs);
+ return FALSE;
+ }
+
+ // Move image...
+
+ // Set some draw states
+ SelectObject(iad->hdc, hNewBmp);
+ hdc_old = CreateCompatibleDC(iad->hdc);
+
+ SetBkMode(iad->hdc, TRANSPARENT);
+ {
+ POINT org;
+ GetBrushOrgEx(iad->hdc, &org);
+ SetStretchBltMode(iad->hdc, HALFTONE);
+ SetBrushOrgEx(iad->hdc, org.x, org.y, NULL);
+ }
+
+ {
+ int x = 0, y = 0, w = 0, h = 0;
+
+ if (pos > 0)
+ {
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ w = iad->width;
+ h = 0;
+ for (i=0; i < pos; i++)
+ {
+ h += iad->nodes[i].height;
+ }
+ }
+ else
+ {
+ h = iad->height;
+ w = 0;
+ for (i=0; i < pos; i++)
+ {
+ w += iad->nodes[i].width;
+ }
+ }
+ BitBlt(iad->hdc, 0, 0, w, h, hdc_old, 0, 0, SRCCOPY);
+ }
+
+ if (pos < iad->nodes_size - 1)
+ {
+ int ox, oy;
+
+ SelectObject(hdc_old, iad->img);
+
+ if (iad->width_based)
+ {
+ ox = 0;
+ oy = h + iad->nodes[pos].height;
+
+ x = 0;
+ y = h;
+
+ w = iad->width;
+ h = iad->height - h - iad->nodes[pos].height;
+ }
+ else
+ {
+ ox = w + iad->nodes[pos].width;
+ oy = 0;
+
+ x = w;
+ y = 0;
+
+ w = iad->width - w - iad->nodes[pos].width;
+ h = iad->height;
+ }
+ BitBlt(iad->hdc, x, y, w, h, hdc_old, ox, oy, SRCCOPY);
+ }
+ }
+
+ // restore things
+ mod_DeleteDC(hdc_old);
+ if (iad->img != NULL) DeleteObject(iad->img);
+ iad->img = hNewBmp;
+
+ // Move array
+ if (pos < iad->nodes_size - 1)
+ {
+ memmove(&iad->nodes[pos], &iad->nodes[pos + 1], (iad->nodes_size - pos - 1) * sizeof(IMAGE_ARRAY_DATA_NODE));
+ }
+
+ iad->nodes_size--;
+
+ iad->width = new_width;
+ iad->height = new_height;
+
+ // Free array
+ ImageArray_Alloc(iad, iad->nodes_size);
+
+ // Finished it!
+ LeaveCriticalSection(&iad->cs);
+
+ return pos;
+}
+
+
+
+BOOL ImageArray_DrawImage(LP_IMAGE_ARRAY_DATA iad, int pos, HDC hdcDest, int nXDest, int nYDest, BYTE Alpha)
+{
+ if (hdcDest == NULL || pos < 0 || pos >= iad->nodes_size)
+ return FALSE;
+
+ EnterCriticalSection(&iad->cs);
+ {
+ int w, h, i;
+
+ if (iad->width_based)
+ {
+ w = 0;
+ h = 0;
+ for (i=0; i < pos; i++)
+ {
+ h += iad->nodes[i].height;
+ }
+ }
+ else
+ {
+ h = 0;
+ w = 0;
+ for (i=0; i < pos; i++)
+ {
+ w += iad->nodes[i].width;
+ }
+ }
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, Alpha, AC_SRC_ALPHA };
+ /*ske_*/AlphaBlend(hdcDest, nXDest, nYDest, iad->nodes[pos].width, iad->nodes[pos].height, iad->hdc, w, h, iad->nodes[pos].width, iad->nodes[pos].height,bf);
+ }
+ }
+
+
+ LeaveCriticalSection(&iad->cs);
+ return FALSE;
+}
+
+BOOL ImageArray_GetImageSize(LP_IMAGE_ARRAY_DATA iad, int pos, SIZE * lpSize)
+{
+ EnterCriticalSection(&iad->cs);
+ if (lpSize)
+ {
+ lpSize->cx = iad->nodes[pos].width;
+ lpSize->cy = iad->nodes[pos].height;
+ }
+ LeaveCriticalSection(&iad->cs);
+ return TRUE;
+} \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_keyboard.cpp b/plugins/Clist_modern/src/modern_keyboard.cpp
new file mode 100644
index 0000000000..56f9ed6d2e
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_keyboard.cpp
@@ -0,0 +1,67 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include <m_hotkeys.h>
+
+int InitSkinHotKeys(void);
+
+INT_PTR hkCloseMiranda(WPARAM wParam,LPARAM lParam)
+{
+ CallService("CloseAction", 0, 0);
+ return 0;
+}
+
+INT_PTR hkRestoreStatus(WPARAM wParam,LPARAM lParam)
+{
+ int nStatus = db_get_w(NULL, "CList", "Status", ID_STATUS_OFFLINE);
+ CallService(MS_CLIST_SETSTATUSMODE, nStatus, 0);
+
+ return 0;
+}
+
+int InitSkinHotKeys(void)
+{
+ CreateServiceFunction("CLIST/HK/CloseMiranda",hkCloseMiranda);
+ CreateServiceFunction("CLIST/HK/RestoreStatus",hkRestoreStatus);
+
+ HOTKEYDESC shk = {0};
+ shk.cbSize = sizeof(shk);
+
+ shk.pszDescription = LPGEN("Close Miranda");
+ shk.pszName = "CloseMiranda";
+ shk.pszSection = LPGEN("Main");
+ shk.pszService = "CLIST/HK/CloseMiranda";
+ Hotkey_Register(&shk);
+
+ shk.pszDescription = LPGEN("Restore last status");
+ shk.pszName = "RestoreLastStatus";
+ shk.pszSection = LPGEN("Status");
+ shk.pszService = "CLIST/HK/RestoreStatus";
+ Hotkey_Register(&shk);
+
+ return 0;
+}
+
+void UninitSkinHotKeys(void)
+{
+}
diff --git a/plugins/Clist_modern/src/modern_log.cpp b/plugins/Clist_modern/src/modern_log.cpp
new file mode 100644
index 0000000000..af2b9c9a68
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_log.cpp
@@ -0,0 +1,46 @@
+#include "hdr/modern_commonheaders.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+
+void Log(const char *file,int line,const char *fmt,...)
+{
+
+
+ va_list vararg;
+ const char *file_tmp;
+ char str[1024];
+ char buf[1024];
+
+ file_tmp = strrchr(file, '\\');
+ if (file_tmp == NULL)
+ file_tmp = file;
+ else
+ file_tmp++;
+
+ va_start(vararg,fmt);
+ mir_vsnprintf(str,SIZEOF(str),fmt,vararg);
+ va_end(vararg);
+ {
+ char * tmp = str;
+ while(*tmp != '\0')
+ {
+ if (*tmp == '\n') *tmp = ' ';
+ tmp++;
+ }
+ }
+ mir_snprintf(buf,SIZEOF(buf),"clist_modern:[%u - %u]: %s \t\t(%s Ln %d)\n",GetCurrentThreadId(),GetTickCount(),str,file_tmp,line);
+#ifdef _FILELOG_
+ {
+ FILE *fp;
+ fp = fopen(_FILELOG_,"at");
+ fprintf(fp,buf);
+ fclose(fp);
+ }
+#else
+ OutputDebugStringA(buf);
+#endif
+}
+
diff --git a/plugins/Clist_modern/src/modern_newrowopts.cpp b/plugins/Clist_modern/src/modern_newrowopts.cpp
new file mode 100644
index 0000000000..b44ea0dbe3
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_newrowopts.cpp
@@ -0,0 +1,198 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2003 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/************************************************************************/
+/* Author Artem Shpynov (shpynov@nm.ru) */
+/************************************************************************/
+
+/************************************************************************/
+/********* New row design options file handle ********/
+/************************************************************************/
+
+
+#include "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "m_clc.h"
+
+#define EMPTY_PLACE 255
+#define COLUMNS_PLACE 254
+#define ROWS_PLACE 253
+
+typedef struct _NodeList
+{
+ BYTE bType;
+ int pData;
+ DWORD AllocatedChilds;
+ struct _NodeList * childNodes;
+ struct _NodeList * itemParent;
+} NodeList;
+
+NodeList * RootNode = NULL;
+
+NodeList * AddNode(NodeList * Parent)
+{
+ NodeList * res;
+ if ( !Parent)
+ {
+ res = (NodeList *)mir_alloc(sizeof(NodeList));
+ memset(res,0,sizeof(NodeList));
+ return res;
+ }
+ Parent->childNodes = (NodeList*) mir_realloc(Parent->childNodes,sizeof(NodeList)*(Parent->AllocatedChilds+1));
+ memset(&(Parent->childNodes[Parent->AllocatedChilds]),0,sizeof(NodeList));
+ Parent->childNodes[Parent->AllocatedChilds].itemParent = Parent;
+ Parent->AllocatedChilds++;
+ return &(Parent->childNodes[Parent->AllocatedChilds-1]);
+}
+
+
+BOOL RemoveChildNode(NodeList * FromList, DWORD index)
+{
+ if ( !FromList) return FALSE;
+ if (FromList->AllocatedChilds <= index) return FALSE;
+ NodeList *work = &(FromList->childNodes[index]);
+ for (size_t i=0; i < work->AllocatedChilds; i++)
+ if (work->childNodes[i].AllocatedChilds)
+ RemoveChildNode(work->childNodes, (DWORD)i);
+
+ if (work->AllocatedChilds) {
+ mir_free_and_nil(work->childNodes);
+ work->AllocatedChilds = 0;
+ }
+ memmove(FromList->childNodes+index,FromList->childNodes+index+1,sizeof(NodeList)*(FromList->AllocatedChilds-index-1));
+ FromList->AllocatedChilds--;
+ return TRUE;
+}
+
+BOOL RemoveNode(NodeList * FromList)
+{
+ if ( !FromList) return FALSE;
+ if (FromList->itemParent)
+ {
+ DWORD k;
+ for (k = 0;k < FromList->itemParent->AllocatedChilds;k++)
+ if (&(FromList->itemParent->childNodes[k]) == FromList)
+ {
+ BOOL res = RemoveChildNode(FromList->itemParent,k);
+ return res;
+ }
+ }
+ do
+ {
+ RemoveChildNode(FromList,0);
+ }
+ while (FromList->AllocatedChilds>0);
+ mir_free_and_nil(FromList->childNodes);
+ mir_free_and_nil(FromList);
+ return TRUE;
+}
+int ident = 0;
+void PrintIdent()
+{
+ int k;
+ for (k = 0;k < ident;k++)
+ TRACE("-");
+}
+
+void TraceTreeLevel(NodeList * node)
+{
+ DWORD i;
+ if ( !node) return;
+ PrintIdent();
+ {
+ char buf[255];
+ mir_snprintf(buf,SIZEOF(buf),"%d\n",node->pData);
+ TRACE(buf);
+ }
+ ident += 5;
+ for (i=0; i < node->AllocatedChilds;i++)
+ {
+
+ if (node->childNodes[i].AllocatedChilds>0)
+ TraceTreeLevel(&(node->childNodes[i]));
+ else
+ {
+ PrintIdent();
+ {
+ char buf[255];
+ mir_snprintf(buf,SIZEOF(buf),"%d\n",node->childNodes[i].pData);
+ TRACE(buf);
+ }
+ }
+ }
+ ident -= 5;
+}
+
+BOOL CALLBACK DlgProcItemNewRowOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ NodeList * res1,*res2, *res3;
+ int i=0;
+ RootNode = AddNode(NULL);
+ RootNode->pData = i++;
+ res1 = AddNode(RootNode);
+ res1->pData = i++;
+ res1 = AddNode(RootNode);
+ res1->pData = i++;
+ res2 = AddNode(res1);
+ res2->pData = i++;
+ res2 = AddNode(res1);
+ res2->pData = i++;
+ res3 = AddNode(res2);
+ res3->pData = i++;
+ res3 = AddNode(res1);
+ res3->pData = i++;
+ res3 = AddNode(RootNode);
+ res3->pData = i++;
+ TRACE("*********** Nodes DUMP 1 ***********\n");
+ TraceTreeLevel(RootNode);
+ if (RemoveNode(res1)) res1 = 0;
+ TRACE("*********** Nodes DUMP 2 ***********\n");
+ TraceTreeLevel(RootNode);
+ //CheckDlgButton(hwndDlg, IDC_HIDE_ICON_ON_AVATAR, DBGetContactSettingByte(NULL,"CList","IconHideOnAvatar",SETTING_HIDEICONONAVATAR_DEFAULT) == 1 ? BST_CHECKED : BST_UNCHECKED );
+ MessageBox(hwndDlg,_T("Init NewRow Dialog"),_T("Notify"),MB_OK);
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->idFrom)
+ {
+ case 0:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ return 0;
+};
diff --git a/plugins/Clist_modern/src/modern_popup.cpp b/plugins/Clist_modern/src/modern_popup.cpp
new file mode 100644
index 0000000000..9da27e5ff9
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_popup.cpp
@@ -0,0 +1,131 @@
+/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_popup.h"
+
+
+BOOL EnablePopups = FALSE;
+
+static LRESULT CALLBACK DumbPopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+
+// Show an error popup
+void ShowErrPopup(const char *title, const char *description)
+{
+ ShowPopup(title == NULL ? "Modern Contact List Error" : title, description, POPUP_TYPE_ERROR);
+}
+
+
+// Show an trace popup
+void ShowTracePopup(const char *text)
+{
+#ifdef _DEBUG
+ static int num = 0;
+ char tmp[1024];
+
+ mir_snprintf(tmp, SIZEOF(tmp), "CM TRACE %d: %s", num, text);
+ TRACE(tmp);
+ TRACE("\n");
+ num++;
+
+ ShowPopup(tmp, "", POPUP_TYPE_NORMAL);
+#endif
+}
+
+
+// Show an popup
+void ShowPopup(const char *title, const char *description, int type)
+{
+ POPUPDATAEX ppd;
+ int ret;
+
+ if ( !ServiceExists(MS_POPUP_ADDPOPUPEX) || !EnablePopups)
+ {
+ return;
+ }
+
+ // Make popup
+ ZeroMemory(&ppd, sizeof(ppd));
+ ppd.lchContact = 0;
+ ppd.lchIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+
+ strncpy(ppd.lpzContactName, title == NULL ? "Modern Contact List" : title, SIZEOF(ppd.lpzContactName)-1);
+ ppd.lpzContactName[SIZEOF(ppd.lpzContactName)-1] = '\0';
+
+ if (description != NULL)
+ {
+ strncpy(ppd.lpzText, description, SIZEOF(ppd.lpzText)-1);
+ ppd.lpzText[SIZEOF(ppd.lpzText)-1] = '\0';
+ }
+
+ if (type == POPUP_TYPE_NORMAL || type == POPUP_TYPE_TEST)
+ {
+ ppd.colorBack = 0;
+ ppd.colorText = 0;
+ }
+ else // if (type == POPUP_TYPE_ERROR)
+ {
+ ppd.colorBack = -1;
+ ppd.colorText = RGB(255,255,255);
+ }
+
+ ppd.PluginWindowProc = DumbPopupDlgProc;
+
+ if (type == POPUP_TYPE_NORMAL || type == POPUP_TYPE_TEST)
+ {
+ ppd.iSeconds = 0;
+ }
+ else // if (type == POPUP_TYPE_ERROR)
+ {
+ ppd.iSeconds = 0;
+ }
+
+ // Now that every field has been filled, we want to see the popup.
+ ret = CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd,0);
+
+ ret++;
+}
+
+
+
+// Handle to popup events
+static LRESULT CALLBACK DumbPopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch(message) {
+ case WM_COMMAND:
+ {
+ PUDeletePopUp(hWnd);
+ return TRUE;
+ }
+
+ case WM_CONTEXTMENU:
+ {
+ PUDeletePopUp(hWnd);
+ return TRUE;
+ }
+
+ case UM_FREEPLUGINDATA:
+ {
+ return TRUE;
+ }
+ }
+
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
diff --git a/plugins/Clist_modern/src/modern_row.cpp b/plugins/Clist_modern/src/modern_row.cpp
new file mode 100644
index 0000000000..d2799d2b9a
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_row.cpp
@@ -0,0 +1,789 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Created by Anton Senko aka ZORG , tweaked by Artem Shpynov aka FYR
+
+*/
+
+#include "hdr/modern_commonheaders.h"
+
+/*
+#include "m_stdhdr.h"
+
+#include <windows.h>
+#include <commctrl.h>
+#include <stdio.h>
+#include <time.h>
+#include <stddef.h>
+#include <process.h>
+#include <io.h>
+#include <string.h>
+#include <direct.h>
+#include "resource.h"
+#include "hdr/modern_commonheaders.h"
+*/
+#include "hdr/modern_row.h"
+
+//Futher declaration
+void rowCalculateMinSize(ROWCELL* cell);
+void rowEqualize(ROWCELL* cell);
+void rowResetEmptyRects(ROWCELL* cell);
+void rowDeleteTree(ROWCELL* cell);
+////////
+
+
+
+//extern ROWCELL * gl_RowRoot; // Óêàçàòåëü íà êîðíåâîé òýã < contact> â øàáëîíå
+//ROWOBJECTS RowTA; // Ñòðóêòóðà, ÷åðåç êîòîðóþ îñóùåñòâëÿåòñÿ äîñòóï ê ýëåìåíòàì êîíòàêòà.
+// Ôîðìèðóåòñÿ ïðè âûïîëíåíèè ôó-è RowParce. Íåÿâíûé ïàðàìåòð ôóè rowParserGetParam
+
+
+// Ôîðìèðóåòñÿ ïðè âûïîëíåíèè ôó-è RowParce. Íåÿâíûé ïàðàìåòð ôóè rowParserGetParam
+
+char *tmplbuf; // Áóôåð äëÿ õðàíåíèÿ øàáëîíà â òåêñòîâîì âèäå
+
+ROWCELL *cppInitModernRow(ROWCELL ** tabAccess)
+{
+ int fsize;
+ int seq = 0;
+ ROWCELL * RowRoot = NULL;
+ FILE * hFile;
+ int i=0;
+ if ( !db_get_b(NULL,"ModernData","UseAdvancedRowLayout",SETTING_ROW_ADVANCEDLAYOUT_DEFAULT)) return NULL;
+ tmplbuf = NULL;
+ if (db_get_b(NULL,"ModernData","UseAdvancedRowLayout",SETTING_ROW_ADVANCEDLAYOUT_DEFAULT) == 1)
+ tmplbuf = db_get_sa(NULL,"ModernData","RowTemplate");
+ if (tmplbuf) {
+ rowParse(RowRoot, RowRoot, tmplbuf, i, seq,tabAccess);
+ mir_free(tmplbuf);
+ return RowRoot;
+ }
+ if (hFile = fopen("template.txt", "rb"))
+ {
+ fsize = _filelength(_fileno(hFile));
+ tmplbuf = (char*)malloc(fsize+1);
+ ZeroMemory(tmplbuf, fsize+1);
+
+ for (i=0; i < fsize; i++) tmplbuf[i] = getc(hFile);
+ tmplbuf[i] = 0;
+ i=0;
+ rowParse(RowRoot, RowRoot, tmplbuf, i, seq,tabAccess);
+ db_set_s(NULL,"ModernData","RowTemplate",tmplbuf);
+ free(tmplbuf);
+ fclose(hFile);
+ return RowRoot;
+ }
+ return NULL;
+
+}
+
+void cppDeleteTree(ROWCELL * RowRoot)
+{
+ ROWCELL *rc = RowRoot;
+ rowDeleteTree(rc);
+}
+
+int cppCalculateRowHeight(ROWCELL *RowRoot)
+{
+ RowRoot->h = 0;
+ RowRoot->w = 0;
+ rowResetEmptyRects(RowRoot);
+ rowCalculateMinSize(RowRoot);
+ rowEqualize(RowRoot);
+ if (RowRoot) return RowRoot->r.bottom;
+ return 0;
+}
+void cppCalculateRowItemsPos(ROWCELL *RowRoot, int width)
+{
+ rowSizeWithReposition(RowRoot, width);
+}
+
+// rowAddCell
+// Âûäåëÿåò íåîáõîäèìîå êîë-âî äèí. ïàìÿòè äëÿ ñòðóêòóðû ROWCELL
+// è ñâÿçûâàåò åå ñ äåðåâîì îïèñàíèÿ êîíòàêòà
+// link - ïîëå child èëè next, ðîäèòåëüñêîé ñòðóêòóðû ROWCELL
+// cont - òèï êîíòåéíåðà: ñòðîêà, ñòîëáåö èëè êîðíåâîé óçåë
+//
+//
+const ROWCELL * rowAddCell(ROWCELL* &link, int cont)
+{
+ link = (ROWCELL*)malloc(sizeof(ROWCELL));
+ ZeroMemory(link, sizeof(ROWCELL));
+ link->cont = cont;
+ return link;
+}
+
+// rowDeleteTree
+// Îñâîáîæäàåò ïàìÿòü çàíÿòóþ äåðåâîì îïèñàíèÿ êîíòàêòà
+// cell - àäðåñ êîðíåâîãî óçëà äåðåâà îïèñàíèÿ êîíòàêòà
+//
+//
+void rowDeleteTree(ROWCELL* cell)
+{
+ if ( !cell) return;
+ if (cell->child)
+ rowDeleteTree((ROWCELL*)(cell->child));
+ if (cell->next)
+ rowDeleteTree((ROWCELL*)(cell->next));
+ free(cell);
+ cell = NULL;
+ return;
+}
+
+// rowParserGetNextWord
+// Âûáèðàåò èç ïîòîêà äàííûõ (ñåé÷àñ ôàéëîâîãî) î÷åðåäíîå ñëîâî.
+// Ñëîâîì ñ÷èòàåòñÿ ïîñëåäîâàòåëüíîñòü ñèìâîëîâ, îãðàíè÷åííàÿ çíàêàìè: SP, < , >, ;, TAB, CR, LF
+// ñèìâîëû îò ; è äî êîíöà ñòðîêè ñ÷èòàþòñÿ êîììåíòàðèåì.
+// NOTE: Äàííàÿ ðåàëèçàöèÿ íå ñîâñåì ïîäõîäèò äëÿ âêëþ÷åíèÿ åå â ModernCL,
+// à ïî ñåìó, òóò íàäî áóäåò ïåðåäåëûâàòü
+// tbuf - óêàçàòåëü íà áóôåð ñîäåðæàùèé òåêñò øàáëîíà
+// hbuf - óêàçàòåëü áóôåðà
+//
+//
+char * rowParserGetNextWord(char *tbuf, int &hbuf)
+{
+ static char buf[256];
+ char ch;
+
+ int j = -1;
+
+ ZeroMemory(buf, 256);
+
+ while(tbuf[hbuf] != 0)
+ {
+ ch = tbuf[hbuf];
+
+ // Remark found
+ if (ch == ';')
+ {
+ if (j >= 0) return buf;
+
+ while (tbuf[hbuf] != 10 && tbuf[hbuf] != 13) hbuf++;
+ }
+
+ // Tag-bracers found
+ if ( !(ch == '>' && j < 0)) //not single '>' found
+ {
+ if ((ch == '<' || ch == '>') && j >= 0)
+ {
+ if (ch == '>')
+ {
+ if (buf[0] == '/' || buf[0] == '<') buf[++j] = ch;
+ hbuf++;
+ }
+ return buf;
+ }
+
+ if (ch == ' ' || ch == 9 || ch == 10 || ch == 13 || ch == ';' || ch == '>')
+ {
+ if (ch == '>')
+ {
+ buf[++j] = ch;
+ hbuf++;
+ }
+
+ if (j >= 0) return buf; // Word is selected
+ }
+ else
+ buf[++j] = ch;
+ }
+ hbuf++;
+ }
+ return NULL;
+}
+
+// rowParserGetParam
+// èùåò è èíòåðïðåòèðóåò ñëîâà â øàáëîíå, çàêëþ÷åííûå ìåæäó òýãàìè
+// cell - óêàçàòåëü íà òåêóùèé èíòåðïðåòèðóåìûé êîíòåéíåð øàáëîíà
+// tbuf - óêàçàòåëü íà áóôåð ñîäåðæàùèé òåêñò øàáëîíà
+// hbuf - óêàçàòåëü áóôåðà
+//
+//
+void rowParserGetParam(ROWCELL* &cell, char *tbuf, int &hbuf)
+{
+ char * word = rowParserGetNextWord(tbuf, hbuf);
+ int param = 0;
+
+ if ( !_strnicmp(word, "avatar", strlen(word))) param = TC_AVATAR;
+ else if ( !_strnicmp(word, "text1", strlen(word))) param = TC_TEXT1;
+ else if ( !_strnicmp(word, "text2", strlen(word))) param = TC_TEXT2;
+ else if ( !_strnicmp(word, "text3", strlen(word))) param = TC_TEXT3;
+ else if ( !_strnicmp(word, "status", strlen(word))) param = TC_STATUS;
+ else if ( !_strnicmp(word, "extra", strlen(word))) param = TC_EXTRA;
+ else if ( !_strnicmp(word, "extra1", strlen(word))) param = TC_EXTRA1;
+ else if ( !_strnicmp(word, "extra2", strlen(word))) param = TC_EXTRA2;
+ else if ( !_strnicmp(word, "extra3", strlen(word))) param = TC_EXTRA3;
+ else if ( !_strnicmp(word, "extra4", strlen(word))) param = TC_EXTRA4;
+ else if ( !_strnicmp(word, "extra5", strlen(word))) param = TC_EXTRA5;
+ else if ( !_strnicmp(word, "extra6", strlen(word))) param = TC_EXTRA6;
+ else if ( !_strnicmp(word, "extra7", strlen(word))) param = TC_EXTRA7;
+ else if ( !_strnicmp(word, "extra8", strlen(word))) param = TC_EXTRA8;
+ else if ( !_strnicmp(word, "extra9", strlen(word))) param = TC_EXTRA9;
+ else if ( !_strnicmp(word, "time", strlen(word))) param = TC_TIME;
+ else if ( !_strnicmp(word, "space", strlen(word))) param = TC_SPACE;
+ else if ( !_strnicmp(word, "fspace", strlen(word))) param = TC_FIXED;
+
+ else if ( !_strnicmp(word, "left", strlen(word))) param = TC_LEFT;
+ else if ( !_strnicmp(word, "top", strlen(word))) param = TC_TOP;
+ else if ( !_strnicmp(word, "vcenter", strlen(word))) param = TC_VCENTER;
+ else if ( !_strnicmp(word, "hcenter", strlen(word))) param = TC_HCENTER;
+ else if ( !_strnicmp(word, "right", strlen(word))) param = TC_RIGHT;
+ else if ( !_strnicmp(word, "bottom", strlen(word))) param = TC_BOTTOM;
+
+ else if ( !_strnicmp(word, "layer", strlen(word))) cell->layer = TRUE;
+
+ else if ( !_strnicmp(word, "width", strlen(word))) param = TC_WIDTH;
+ else if ( !_strnicmp(word, "height", strlen(word))) param = TC_HEIGHT;
+
+ else
+ {
+ hbuf -= (int)strlen(word);
+ return;
+ }
+
+ if (param>TC_TEXT3 && param != TC_SPACE) cell->hasfixed = 1;
+
+ switch (param)
+ {
+ case TC_TEXT1:
+ case TC_TEXT2:
+ case TC_TEXT3:
+ case TC_SPACE:
+ cell->sizing = 1;
+ case TC_STATUS:
+ case TC_AVATAR:
+ case TC_EXTRA:
+ case TC_EXTRA1:
+ case TC_EXTRA2:
+ case TC_EXTRA3:
+ case TC_EXTRA4:
+ case TC_EXTRA5:
+ case TC_EXTRA6:
+ case TC_EXTRA7:
+ case TC_EXTRA8:
+ case TC_EXTRA9:
+ case TC_TIME:
+ case TC_FIXED:
+
+ cell->type = param;
+ break;
+
+ case TC_HCENTER:
+ case TC_RIGHT:
+ cell->halign = param;
+ break;
+
+ case TC_VCENTER:
+ case TC_BOTTOM:
+ cell->valign = param;
+ break;
+
+ case TC_WIDTH:
+ word = rowParserGetNextWord(tbuf, hbuf);
+ param = atoi(word);
+ cell->w = param;
+ break;
+
+ case TC_HEIGHT:
+ word = rowParserGetNextWord(tbuf, hbuf);
+ param = atoi(word);
+ cell->h = param;
+ }
+
+ rowParserGetParam(cell, tbuf, hbuf);
+ return;
+}
+// rowParse
+// Èùåò â øàáëîíå òåãè < contact>, < tr> è < tc>, è äîáàâëÿåò ñîîòâåòñòâóþùèå óçëû
+// â äåðåâî îïèñàíèÿ êîíòàêòà
+// cell - ïîëå child èëè next ðîäèòåëüñêîãî êîíòåéíåðà
+// parent - óêàçàòåëü íà ðîäèòåëüñêèé êîíòåéíåð
+// tbuf - óêàçàòåëü íà áóôåð ñîäåðæàùèé òåêñò øàáëîíà
+// hbuf - óêàçàòåëü áóôåðà
+// sequence - íóæíî çàäàâàòü 0, ýòî î÷åðåäíîñòü íàõîæäåíèÿ
+//
+BOOL rowParse(ROWCELL* &cell, ROWCELL* parent, char *tbuf, int &hbuf, int &sequence, ROWCELL** RowTabAccess )
+{
+ char * word;
+ word = rowParserGetNextWord(tbuf, hbuf);
+ int cont;
+
+ if (!_strnicmp(word, "<tr", strlen(word)) || !_strnicmp(word, "<tr>", strlen(word))) cont = TC_ROW;
+ else if ( !_strnicmp(word, "<tc", strlen(word)) || !_strnicmp(word, "<tc>", strlen(word))) cont = TC_COL;
+ else if ( !_strnicmp(word, "/>", strlen(word)) ||
+ !_strnicmp(word, "</tr>", strlen(word)) ||
+ !_strnicmp(word, "</tc>", strlen(word))) return TRUE;
+ else return FALSE;
+
+ rowAddCell(cell, cont);
+ rowParserGetParam(cell, tbuf, hbuf);
+ if (cell->type != 0 && cell->type != TC_SPACE && cell->type != TC_FIXED)
+ RowTabAccess[sequence++] = cell;
+
+ if ( !rowParse(cell->child, cell, tbuf, hbuf, sequence,RowTabAccess))
+ return FALSE;
+
+ if ( !parent)
+ {
+ RowTabAccess[sequence] = NULL;
+ return TRUE;
+ }
+
+ if ( !rowParse(cell->next, parent, tbuf, hbuf, sequence,RowTabAccess))
+ return FALSE;
+
+ parent->sizing |= cell->sizing;
+ parent->hasfixed |= cell->hasfixed;
+ return TRUE;
+}
+
+void rowResetEmptyRects(ROWCELL* cell)
+{
+ if ( !cell) return;
+ if (cell->type == 0)
+ {
+ SetRect(&(cell->r),0,0,0,0);
+ cell->full_width = 0;
+ cell->fixed_width = 0;
+ }
+ rowResetEmptyRects(cell->child);
+ rowResetEmptyRects(cell->next);
+}
+
+// rowCalculateMinSize
+// Âû÷èñëåíèå ìèíèìàëüíûõ ðàçìåðîâ êàæäîãî êîíòåéíåðà äåðåâà îïèñàíèÿ êîíòàêòà
+// Ýòà ôó-ÿ ÂÑÅÃÄÀ! äîëæíà âûçûâàòüñÿ íåïîñðåäñòâåííî ïåðåä rowPositioning
+// cell - óêàçàòåëü íà êîðíåâîé óçåë äåðåâà îïèñàíèÿ êîíòàêòà
+// NOTE: Ïåðåä âûçûâîì rowCalculateMinSize íåîáõîäèìî çàïîëíèòü ïîëÿ w è h ñòðóêòóðû RowTA, äëÿ êàæäîãî ýëåìåíòà
+//
+void rowCalculateMinSize(ROWCELL* cell)
+{
+ ROWCELL* curchild = NULL;
+ int w = 0,h = 0;
+ int wl = 0, hl = 0;
+ int fullWidth = 0;
+ if ( !cell) return;
+
+ cell->r.left = 0;
+ cell->r.top = 0;
+
+ if (cell->type < TC_TEXT1 || cell->type > TC_TEXT3 && cell->type != TC_SPACE)
+ cell->r.right = cell->w;
+ else
+ cell->r.right = 0;
+
+ cell->r.bottom = cell->h;
+
+ rowCalculateMinSize(cell->child);
+ rowCalculateMinSize(cell->next);
+
+ if ( !(curchild = cell->child)) return;
+
+ if (cell->cont == TC_ROW)
+ {
+ do
+ {
+ h = max(h, curchild->r.bottom);
+
+ if (curchild->layer)
+ {
+ //w = max(w, curchild->r.right);
+ wl += curchild->r.right;
+ fullWidth = max(fullWidth,max(curchild->full_width,curchild->w));
+ }
+ else
+ {
+ w += curchild->r.right;
+ fullWidth += max(curchild->full_width,curchild->w);
+ }
+ }
+ while (curchild = curchild->next);
+ }
+
+ if (cell->cont == TC_COL)
+ {
+ while (curchild)
+ {
+ w = max(w, curchild->r.right);
+ fullWidth = max(fullWidth,max(curchild->full_width,curchild->w));
+
+ if (curchild->layer)
+ {
+ hl = curchild->r.bottom;
+ // h = max(h, curchild->r.bottom);
+ }
+ else
+ h += curchild->r.bottom;
+
+ curchild = curchild->next;
+ }
+ }
+
+ cell->r.right = max(max(w, cell->r.right),wl);
+ cell->r.bottom = max(max(h, cell->r.bottom),hl);
+ cell->full_width = max(fullWidth,cell->full_width);
+ cell->fixed_width = max(cell->fixed_width,cell->r.right);
+ return;
+}
+
+// void rowEqualise(ROWCELL* cell)
+//
+// Óðàâíèâàåò âûñîòû äåòåé âíóòðè ñòðîê, è øèðèíû äåòåé âíóòðè ñòîáöîâ
+// cell - óêàçàòåëü íà êîðíåâîé óçåë äåðåâà îïèñàíèÿ êîíòàêòà
+//
+void rowEqualize(ROWCELL* cell)
+{
+ ROWCELL* curchild = NULL;
+ if ( !cell) return;
+ rowEqualize(cell->child);
+ rowEqualize(cell->next);
+
+ if ( !(curchild = cell->child)) return;
+
+ if (cell->cont == TC_ROW)
+ {
+ do
+ {
+ if (curchild->layer) continue;
+ curchild->r.bottom = cell->r.bottom;
+ }
+ while (curchild = curchild->next);
+ }
+
+ if (cell->cont == TC_COL)
+ {
+ do
+ {
+ if (curchild->layer) continue;
+ curchild->r.right = cell->r.right;
+ }
+ while (curchild = curchild->next);
+ }
+
+
+ //rowEqualize(cell->child);
+ //rowEqualize(cell->next);
+}
+
+// void rowPlacing(pttCell cell, pttCell parent)
+//
+// Ïîçèöèîíèðóåò ýëåìåíò ñòðîêè êîíòàêòà â åãî êîíòåéíåðå
+// cell - óêàçàòåëü íà ïëàâàþùèé êîíòåéíåð
+//
+void rowPlacing(pROWCELL cell)
+{
+ if (cell->type == 0) return;
+
+ switch(cell->type)
+ {
+ case TC_TEXT1:
+ case TC_TEXT2:
+ case TC_TEXT3:
+ case TC_SPACE:
+ cell->r.right += cell->r.left;
+ break;
+ default:
+ {
+ switch(cell->halign)
+ {
+ case TC_LEFT:
+ break;
+ case TC_HCENTER:
+ cell->r.left += (cell->r.right - cell->w)/2;
+ break;
+ case TC_RIGHT:
+ cell->r.left += cell->r.right - cell->w;
+ }
+ cell->r.right = cell->r.left + cell->w;
+ }
+ }
+
+ switch(cell->valign)
+ {
+ case TC_TOP:
+ break;
+ case TC_VCENTER:
+ cell->r.top += (cell->r.bottom - cell->h)/2;
+ break;
+ case TC_BOTTOM:
+ cell->r.top += cell->r.bottom - cell->h;
+ }
+ cell->r.bottom = cell->r.top + cell->h;
+}
+
+// void ttTLProc(pROWCELL cell, pROWCELL parent)
+//
+// Ïîçèöèîíèðóåò ïëàâàþùèé êîíòåéíåð, âíóòðè ðîäèòåëüñêîãî
+// cell - óêàçàòåëü íà ïëàâàþùèé êîíòåéíåð
+// parent - óêàçàòåëü íà ðîäèòåëüñêèé êîíòåéíåð
+//
+void rowLayerProc(pROWCELL cell, pROWCELL parent)
+{
+ if (cell->sizing)
+ {
+ cell->r.left = parent->r.left;
+ //cell->r.right += cell->r.left;
+ }
+ else
+ {
+ switch(cell->halign)
+ {
+ case TC_LEFT:
+ cell->r.left = parent->r.left;
+ break;
+ case TC_HCENTER:
+ cell->r.left = parent->r.left + (parent->r.right - cell->r.right)/2;
+ break;
+ case TC_RIGHT:
+ cell->r.left = parent->r.left + parent->r.right - cell->r.right;
+ }
+ }
+
+ switch(cell->valign)
+ {
+ case TC_TOP:
+ cell->r.top = parent->r.top;
+ break;
+ case TC_VCENTER:
+ cell->r.top = parent->r.top + (parent->r.bottom - cell->r.bottom)/2;
+ break;
+ case TC_BOTTOM:
+ cell->r.top = parent->r.top + parent->r.bottom - cell->r.bottom;
+ break;
+ }
+}
+
+// void rowPositioning(pROWCELL cell, int &dist)
+//
+// Âû÷èñëÿåò ïðÿìîóãîëüíèêè ýëåìåíòîâ êîíòàêòà, ó÷èòûâàÿ âûðàâíèâàíèå â êîíòåéíåðå
+// cell - óêàçàòåëü íà êîðíåâîé óçåë äåðåâà îïèñàíèÿ êîíòàêòà
+// dist - íîâàÿ øèðèíà êîíòàêòà
+//
+void rowPositioning(pROWCELL cell, int &dist)
+{
+ ROWCELL* curchild = NULL;
+
+ int x = cell->r.left;
+ int y = cell->r.top;
+
+ int h = cell->r.bottom;
+ int w = dist;
+
+ int r = 0;
+ int size = 0;
+ int cw = 0;
+ int fixedsized = 0;
+ int autosized = 0;
+ int dummy = 0;
+
+ // Êîðððåêòèðîâêà íàçíà÷àåìîé øèðèíû dist
+ if (w < cell->r.right && (cell->type < TC_TEXT1 || cell->type > TC_TEXT3 && cell->type != TC_SPACE) || !cell->sizing)
+ dist = w = cell->r.right;
+
+ cell->r.right = dist;
+ dummy = dist;
+ if ( !(curchild = cell->child))
+ {
+ rowPlacing(cell);
+ return;
+ }
+
+ // Ïîçèöèîíèðîâàíèå êîíòåéíåðîâ â ñòðîêå
+ if (cell->cont == TC_ROW)
+ {
+ fixedsized = cell->fixed_width;
+ while (curchild)
+ {
+ // Êîíòåéíåðû layer íå äîëæíû âëèÿòü íà ïîçèöèîíèðîâàíèå êîíòåéíåðîâ tc
+ if (curchild->layer)
+ {
+ curchild = curchild->next;
+ continue;
+ }
+
+ cw += curchild->r.right;
+
+ if (curchild->sizing)
+ {
+ autosized += max(curchild->w,curchild->full_width);
+ r++;
+ }
+ else
+ size += curchild->r.right;
+
+ curchild = curchild->next;
+ }
+
+ w -= size;
+ fixedsized -= size;
+
+ if (r == 0)
+ {
+ switch(cell->halign)
+ {
+ case TC_HCENTER:
+ x += (dist - cw)/2;// - 1;
+ break;
+ case TC_RIGHT:
+ x += dist - cw;
+ break;
+ }
+ }
+
+
+ curchild = cell->child;
+
+ size = 0;
+ while(curchild)
+ {
+ if (curchild->layer)
+ {
+ //int dummy = 0;
+ rowLayerProc(curchild, cell);
+ rowPositioning(curchild, dummy);
+ }
+ else
+ {
+ curchild->r.top = cell->r.top;
+ curchild->r.left = x;
+
+
+ w -= size;
+ if (curchild->sizing)
+ {
+ if ((0&!curchild->fitwidth) || r>1) //ïîêà îòêëþ÷åíî -ïðîáëåìû ñ âûðàâíèâàíèåì
+ {
+ if (curchild->hasfixed)
+ fixedsized -= curchild->fixed_width;
+ switch (cell->halign)
+ {
+ case TC_RIGHT:
+ size = (w-fixedsized)-(autosized-max(curchild->full_width,curchild->w));
+ break;
+ case TC_LEFT:
+ size = min(w-fixedsized,max(curchild->full_width,curchild->w));
+ break;
+ case TC_HCENTER:
+ if (autosized) {size = max(curchild->full_width,curchild->w)*w/autosized; break;}
+ default:
+ size = w / r;
+ }
+ autosized -= (max(curchild->full_width,curchild->w));
+ if (autosized < 0) autosized = 0;
+ if (size < 0) size = 0;
+ }
+ else size = w;
+ /* ïîêà îòêëþ÷åíî èáî ïàðàìåòð âëèÿåò íà âûðàâíèâàíèå âêëþ÷àåòñÿ ïî ëåâîìó êðàþ
+ if (0 && !curchild->fitwidth)
+ if (size>max(curchild->full_width,curchild->w))
+ size = max(curchild->full_width,curchild->w);
+ */
+ r--;
+ }
+ else
+ size = curchild->r.right;
+
+ rowPositioning(curchild, size);
+ x += size;
+
+ if ( !curchild->sizing)
+ size = 0;
+ }
+
+ curchild = curchild->next;
+ }
+ }
+
+ // Ïîçèöèîíèðîâàíèå êîíòåéíåðîâ â ñòîëáöå
+ if (cell->cont == TC_COL)
+ {
+ while (curchild)
+ {
+ // Êîíòåéíåðû layer íå äîëæíû âëèÿòü íà ïîçèöèîíèðîâàíèå êîíòåéíåðîâ tr
+ if (curchild->layer)
+ {
+ curchild = curchild->next;
+ continue;
+ }
+
+ size += curchild->r.bottom;
+ curchild = curchild->next;
+ }
+
+ if (h > size)
+ {
+ switch(cell->valign)
+ {
+ case TC_VCENTER:
+ y += (h - size) / 2;
+ break;
+ case TC_BOTTOM:
+ y += (h - size);
+ break;
+ }
+ }
+
+ curchild = cell->child;
+ while(curchild)
+ {
+ if (curchild->layer)
+ {
+ rowLayerProc(curchild, cell);
+ rowPositioning(curchild, dummy);
+ }
+ else
+ {
+ curchild->r.top = y;
+ y += curchild->r.bottom;
+
+ curchild->r.left = cell->r.left;
+ curchild->r.right = dist;
+
+ rowPositioning(curchild, size);
+
+ }
+
+ curchild = curchild->next;
+ }
+ }
+
+ rowPlacing(cell);
+
+}
+
+// void rowSizeWithReposition(ROWCELL* &root, int width)
+//
+// Ïðîèçâîäèò ïðîñ÷åò è ïîçèöèîíèðîâàíèå ýëåìåíòîâ êîòàêòà
+// Ïåðåä âûçîâîì íåîáõîäèìî çàïîëíèòü ñòðóêòóðó RowTA
+//
+void rowSizeWithReposition(ROWCELL* &root, int width)
+{
+ root->h = 0;
+ root->w = 0;
+ rowCalculateMinSize(root);
+ rowEqualize(root);
+ rowPositioning(root, width);
+ root->h = root->r.bottom;
+ root->w = root->r.right;
+}
+
+#undef _CPPCODE
diff --git a/plugins/Clist_modern/src/modern_rowheight_funcs.cpp b/plugins/Clist_modern/src/modern_rowheight_funcs.cpp
new file mode 100644
index 0000000000..238962baa2
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_rowheight_funcs.cpp
@@ -0,0 +1,796 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Created by Pescuma, modified by Artem Shpynov
+
+*/
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_rowheight_funcs.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_row.h"
+#include "hdr/modern_clcpaint.h"
+
+int g_mutex_nCalcRowHeightLock = 0;
+int mod_CalcRowHeight_worker(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item);
+void RowHeights_CalcRowHeights_Worker(struct ClcData *dat, HWND hwnd);
+int RowHeights_GetRowHeight_worker(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item);
+
+/*
+*
+*/
+
+ROWCELL * gl_RowTabAccess[TC_ELEMENTSCOUNT+1] = {0}; // Ìàññèâ, ÷åðåç êîòîðûé îñóùåñòâëÿåòñÿ äîñòóï ê ýëåìåíòàì êîíòàêòà.
+ROWCELL * gl_RowRoot;
+
+void FreeRowCell ()
+{
+ if (gl_RowRoot)
+ cppDeleteTree(gl_RowRoot);
+}
+
+void RowHeight_InitModernRow()
+{
+ gl_RowRoot = cppInitModernRow(gl_RowTabAccess);
+ return;
+}
+
+SIZE GetAvatarSize(int imageWidth, int imageHeight, int maxWidth, int maxHeight)
+{
+ float scalefactor = 0;
+ SIZE sz = {0};
+ if (imageWidth == 0 || imageHeight == 0) return sz;
+ if (maxWidth == 0) maxWidth = maxHeight;
+ scalefactor = min((float)maxWidth/imageWidth,(float)maxHeight/imageHeight);
+ sz.cx = (LONG)(imageWidth*scalefactor);
+ sz.cy = (LONG)(imageHeight*scalefactor);
+ return sz;
+}
+
+int RowHeight_CalcRowHeight(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item)
+{
+ int res;
+ if (MirandaExiting()) return 0;
+ g_mutex_nCalcRowHeightLock++;
+ res = mod_CalcRowHeight_worker(dat,hwnd,contact,item);
+ g_mutex_nCalcRowHeightLock--;
+ return res;
+}
+int mod_CalcRowHeight_worker(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item)
+{
+ BYTE i=0;
+ int res = 0;
+ int height = 0;
+ displayNameCacheEntry * pdnce;
+ BOOL hasAvatar = FALSE;
+ DWORD style;
+ style = GetWindowLongPtr(hwnd,GWL_STYLE);
+ pdnce = (displayNameCacheEntry*)pcli->pfnGetCacheEntry(contact->hContact);
+ if ( !RowHeights_Alloc(dat, item + 1))
+ return -1;
+ if ( !pcli->hwndContactTree) return 0;
+ //if ( !gl_RowRoot) RowHeight_InitModernRow();
+ if (dat->hWnd != pcli->hwndContactTree || !gl_RowRoot || contact->type == CLCIT_GROUP)
+ {
+ int tmp = 0;
+ tmp = dat->fontModernInfo[g_clcPainter.GetBasicFontID(contact)].fontHeight;
+ if (dat->text_replace_smileys && dat->first_line_draw_smileys && !dat->text_resize_smileys)
+ tmp = max(tmp, contact->ssText.iMaxSmileyHeight);
+ if (contact->type == CLCIT_GROUP)
+ {
+ char * szCounts = pcli->pfnGetGroupCountsText(dat, contact);
+ // Has the count?
+ if (szCounts && szCounts[0])
+ tmp = max(tmp,dat->fontModernInfo[contact->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS].fontHeight);
+ }
+ tmp = max(tmp, ICON_HEIGHT);
+ tmp = max(tmp,dat->row_min_heigh);
+ tmp += dat->row_border*2;
+ if (contact->type == CLCIT_GROUP &&
+ contact->group->parent->groupId == 0 &&
+ contact->group->parent->cl.items[0] != contact)
+ tmp += dat->row_before_group_space;
+ if (item != -1) dat->row_heights[item] = tmp;
+ return tmp;
+ }
+ hasAvatar = (dat->use_avatar_service && contact->avatar_data != NULL) || (!dat->use_avatar_service && contact->avatar_pos != AVATAR_POS_DONT_HAVE);
+ while (gl_RowTabAccess[i] != NULL)
+ {
+ if (gl_RowTabAccess[i]->type != TC_SPACE)
+ {
+ gl_RowTabAccess[i]->h = 0;
+ gl_RowTabAccess[i]->w = 0;
+ SetRect(&(gl_RowTabAccess[i]->r),0,0,0,0);
+ switch (gl_RowTabAccess[i]->type)
+ {
+ case TC_TEXT1:
+ {
+ int tmp = 0;
+ tmp = dat->fontModernInfo[g_clcPainter.GetBasicFontID(contact)].fontHeight;
+ if (dat->text_replace_smileys && dat->first_line_draw_smileys && !dat->text_resize_smileys)
+ tmp = max(tmp, contact->ssText.iMaxSmileyHeight);
+ if (item == -1)
+ {
+ //calculate text width here
+ SIZE size = {0};
+ RECT dummyRect = {0,0,1024,tmp};
+ HDC hdc = CreateCompatibleDC(NULL);
+ g_clcPainter.ChangeToFont(hdc,dat,g_clcPainter.GetBasicFontID(contact),NULL);
+ g_clcPainter.GetTextSize(&size,hdc,dummyRect,contact->szText,contact->ssText.plText,0, dat->text_resize_smileys ? 0 : contact->ssText.iMaxSmileyHeight);
+ if (contact->type == CLCIT_GROUP)
+ {
+ char * szCounts = pcli->pfnGetGroupCountsText(dat, contact);
+ if (szCounts && strlen(szCounts)>0)
+ {
+ RECT count_rc = {0};
+ // calc width and height
+ g_clcPainter.ChangeToFont(hdc,dat,contact->group->expanded?FONTID_OPENGROUPCOUNTS:FONTID_CLOSEDGROUPCOUNTS,NULL);
+ ske_DrawText(hdc,_T(" "),1,&count_rc,DT_CALCRECT | DT_NOPREFIX);
+ size.cx += count_rc.right-count_rc.left;
+ count_rc.right = 0;
+ count_rc.left = 0;
+ ske_DrawTextA(hdc,szCounts,lstrlenA(szCounts),&count_rc,DT_CALCRECT);
+ size.cx += count_rc.right-count_rc.left;
+ tmp = max(tmp,count_rc.bottom-count_rc.top);
+ }
+ }
+ gl_RowTabAccess[i]->w = size.cx;
+ SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
+ ske_ResetTextEffect(hdc);
+ mod_DeleteDC(hdc);
+ }
+ gl_RowTabAccess[i]->h = tmp;
+
+ break;
+ }
+ case TC_TEXT2:
+ {
+ int tmp = 0;
+ HANDLE hContact = pdnce->hContact;
+ if (dat->second_line_show && pdnce->szSecondLineText && pdnce->szSecondLineText[0] )
+ {
+ tmp = dat->fontModernInfo[FONTID_SECONDLINE].fontHeight;
+ if (dat->text_replace_smileys && dat->second_line_draw_smileys && !dat->text_resize_smileys)
+ tmp = max(tmp, pdnce->ssSecondLine.iMaxSmileyHeight);
+ if (item == -1)
+ {
+ //calculate text width here
+
+ SIZE size = {0};
+ RECT dummyRect = {0,0,1024,tmp};
+ HDC hdc = CreateCompatibleDC(NULL);
+ g_clcPainter.ChangeToFont(hdc,dat,FONTID_SECONDLINE,NULL);
+ g_clcPainter.GetTextSize(&size,hdc,dummyRect,pdnce->szSecondLineText,pdnce->ssSecondLine.plText,0, dat->text_resize_smileys ? 0 : pdnce->ssSecondLine.iMaxSmileyHeight);
+ gl_RowTabAccess[i]->w = size.cx;
+ SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
+ ske_ResetTextEffect(hdc);
+ mod_DeleteDC(hdc);
+ }
+ }
+ gl_RowTabAccess[i]->h = tmp;
+ break;
+ }
+ case TC_TEXT3:
+ {
+ int tmp = 0;
+ HANDLE hContact = pdnce->hContact;
+ if (dat->third_line_show && pdnce->szThirdLineText && pdnce->szThirdLineText[0])
+ {
+ tmp = dat->fontModernInfo[FONTID_THIRDLINE].fontHeight;
+ if (dat->text_replace_smileys && dat->third_line_draw_smileys && !dat->text_resize_smileys)
+ tmp = max(tmp, pdnce->ssThirdLine.iMaxSmileyHeight);
+ if (item == -1)
+ {
+ //calculate text width here
+ SIZE size = {0};
+ RECT dummyRect = {0,0,1024,tmp};
+ HDC hdc = CreateCompatibleDC(NULL);
+ g_clcPainter.ChangeToFont(hdc,dat,FONTID_THIRDLINE,NULL);
+ g_clcPainter.GetTextSize(&size,hdc,dummyRect,pdnce->szThirdLineText,pdnce->ssThirdLine.plText,0, dat->text_resize_smileys ? 0 : pdnce->ssThirdLine.iMaxSmileyHeight);
+ gl_RowTabAccess[i]->w = size.cx;
+ SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
+ ske_ResetTextEffect(hdc);
+ mod_DeleteDC(hdc);
+ }
+ }
+ gl_RowTabAccess[i]->h = tmp;
+ break;
+ }
+ case TC_STATUS:
+ {
+ if (
+ (contact->type == CLCIT_GROUP && !dat->row_hide_group_icon) ||
+ ( contact->type == CLCIT_CONTACT && contact->iImage != -1 &&
+ !(dat->icon_hide_on_avatar && dat->avatars_show && (hasAvatar || (!hasAvatar && dat->icon_draw_on_avatar_space && contact->iImage != -1)) && !contact->image_is_special))
+ )
+ {
+ gl_RowTabAccess[i]->h = ICON_HEIGHT;
+ gl_RowTabAccess[i]->w = ICON_HEIGHT;
+ }
+ break;
+ }
+ case TC_AVATAR:
+ {
+ if (dat->avatars_show &&
+ contact->type == CLCIT_CONTACT &&
+ (hasAvatar || (dat->icon_hide_on_avatar && dat->icon_draw_on_avatar_space && contact->iImage != -1) )
+ )
+ {
+ SIZE sz = {0};
+ int iW = 0, iH = 0;
+ if (dat->use_avatar_service)
+ {
+ if (contact->avatar_data)
+ {
+ iH = contact->avatar_data->bmHeight;
+ iW = contact->avatar_data->bmWidth;
+ }
+ }
+ else if (dat->avatar_cache.nodes)
+ {
+ iW = dat->avatar_cache.nodes[contact->avatar_pos].width;
+ iH = dat->avatar_cache.nodes[contact->avatar_pos].height;
+ }
+ sz = GetAvatarSize(iW,iH,dat->avatars_maxwidth_size,dat->avatars_maxheight_size);
+ if ((sz.cx == 0 || sz.cy == 0) && dat->icon_hide_on_avatar && dat->icon_draw_on_avatar_space && contact->iImage != -1)
+ { sz.cx = ICON_HEIGHT; sz.cy = ICON_HEIGHT; }
+
+ gl_RowTabAccess[i]->h = sz.cy;
+ gl_RowTabAccess[i]->w = sz.cx;
+ }
+
+ break;
+ }
+ case TC_EXTRA:
+ {
+ // Draw extra icons
+
+ if (contact->type == CLCIT_CONTACT &&
+ (!contact->isSubcontact || db_get_b(NULL,"CLC","MetaHideExtra",SETTING_METAHIDEEXTRA_DEFAULT) == 0 && dat->extraColumnsCount > 0))
+ {
+ BOOL hasExtra = FALSE;
+ int k;
+ int width = 0;
+ for (k = 0; k < dat->extraColumnsCount; k++)
+ if (contact->iExtraImage[k] != 0xFF || contact->iWideExtraImage[k] != 0xFFFF || !dat->MetaIgnoreEmptyExtra)
+ {
+ hasExtra = TRUE;
+ if (item != -1) break;
+ width += (width>0)?dat->extraColumnSpacing:(dat->extraColumnSpacing-2);
+ }
+ if (hasExtra)
+ {
+ gl_RowTabAccess[i]->h = ICON_HEIGHT;
+ gl_RowTabAccess[i]->w = width;
+ }
+ }
+ break;
+ }
+ case TC_EXTRA1:
+ case TC_EXTRA2:
+ case TC_EXTRA3:
+ case TC_EXTRA4:
+ case TC_EXTRA5:
+ case TC_EXTRA6:
+ case TC_EXTRA7:
+ case TC_EXTRA8:
+ case TC_EXTRA9:
+ {
+ if (contact->type == CLCIT_CONTACT &&
+ (!contact->isSubcontact || db_get_b(NULL,"CLC","MetaHideExtra",SETTING_METAHIDEEXTRA_DEFAULT) == 0 && dat->extraColumnsCount > 0))
+ {
+ int eNum = gl_RowTabAccess[i]->type-TC_EXTRA1;
+ if (eNum < dat->extraColumnsCount)
+ if (contact->iExtraImage[eNum] != 255 || contact->iWideExtraImage[eNum] != 0xFFFF || !dat->MetaIgnoreEmptyExtra)
+ {
+ gl_RowTabAccess[i]->h = ICON_HEIGHT;
+ gl_RowTabAccess[i]->w = ICON_HEIGHT;
+ }
+ }
+ break;
+ }
+ case TC_TIME:
+ {
+ if (contact->type == CLCIT_CONTACT && dat->contact_time_show && pdnce->hTimeZone)
+ {
+ gl_RowTabAccess[i]->h = dat->fontModernInfo[FONTID_CONTACT_TIME].fontHeight;
+ if (item == -1)
+ {
+ TCHAR szResult[80];
+
+ if ( !tmi.printDateTime(pdnce->hTimeZone, _T("t"), szResult, SIZEOF(szResult), 0))
+ {
+ SIZE text_size = {0};
+ RECT rc = {0};
+ // Select font
+ HDC hdc = CreateCompatibleDC(NULL);
+ g_clcPainter.ChangeToFont(hdc,dat,FONTID_CONTACT_TIME,NULL);
+
+ // Get text size
+ text_size.cy = ske_DrawText(hdc, szResult, lstrlen(szResult), &rc, DT_CALCRECT | DT_NOPREFIX | DT_SINGLELINE);
+ SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
+ ske_ResetTextEffect(hdc);
+ mod_DeleteDC(hdc);
+ text_size.cx = rc.right - rc.left;
+ gl_RowTabAccess[i]->w = text_size.cx;
+
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ i++;
+ }
+
+ height = cppCalculateRowHeight(gl_RowRoot);
+ height += dat->row_border*2;
+ height = max(height,dat->row_min_heigh);
+ if (item != -1) dat->row_heights[item] = height;
+ return height;
+}
+
+
+
+
+/*
+*
+*/
+
+
+
+
+BOOL RowHeights_Initialize(struct ClcData *dat)
+{
+ dat->max_row_height = 0;
+ dat->row_heights_size = 0;
+ dat->row_heights_allocated = 0;
+ dat->row_heights = NULL;
+
+ return TRUE;
+}
+
+void RowHeights_Free(struct ClcData *dat)
+{
+ if (dat->row_heights != NULL)
+ {
+ free(dat->row_heights);
+ dat->row_heights = NULL;
+ }
+
+ dat->row_heights_allocated = 0;
+ dat->row_heights_size = 0;
+}
+
+void RowHeights_Clear(struct ClcData *dat)
+{
+ dat->row_heights_size = 0;
+}
+
+
+BOOL RowHeights_Alloc(struct ClcData *dat, int size)
+{
+ if (size > dat->row_heights_size)
+ {
+ if (size > dat->row_heights_allocated)
+ {
+ int size_grow = size;
+
+ size_grow += 100 - (size_grow % 100);
+
+ if (dat->row_heights != NULL)
+ {
+ int *tmp = (int *) realloc((void *)dat->row_heights, sizeof(int) * size_grow);
+
+ if (tmp == NULL)
+ {
+ TRACE("Out of memory: realloc returned NULL (RowHeights_Alloc)");
+ RowHeights_Free(dat);
+ return FALSE;
+ }
+
+ dat->row_heights = tmp;
+ memset(dat->row_heights+(dat->row_heights_allocated),0,sizeof(int) * (size_grow-dat->row_heights_allocated));
+ }
+ else
+ {
+ dat->row_heights = (int *) malloc(sizeof(int) * size_grow);
+
+ if (dat->row_heights == NULL)
+ {
+ TRACE("Out of memory: alloc returned NULL (RowHeights_Alloc)");
+ RowHeights_Free(dat);
+ return FALSE;
+ }
+ memset(dat->row_heights,0,sizeof(int) * size_grow);
+ }
+
+ dat->row_heights_allocated = size_grow;
+ }
+
+ dat->row_heights_size = size;
+ }
+
+ return TRUE;
+}
+
+
+// Calc and store max row height
+int RowHeights_GetMaxRowHeight(struct ClcData *dat, HWND hwnd)
+{
+ int max_height = 0, i, tmp;
+ DWORD style = GetWindowLongPtr(hwnd,GWL_STYLE);
+
+ if ( !dat->text_ignore_size_for_row_height)
+ {
+ int contact_fonts[] = {FONTID_CONTACTS, FONTID_INVIS, FONTID_OFFLINE, FONTID_NOTONLIST, FONTID_OFFINVIS,
+ FONTID_AWAY,FONTID_DND, FONTID_NA, FONTID_OCCUPIED, FONTID_CHAT, FONTID_INVISIBLE,
+ FONTID_PHONE, FONTID_LUNCH};
+ int other_fonts[] = {FONTID_OPENGROUPS, FONTID_OPENGROUPCOUNTS,FONTID_CLOSEDGROUPS, FONTID_CLOSEDGROUPCOUNTS, FONTID_DIVIDERS, FONTID_CONTACT_TIME};
+
+ // Get contact font size
+ tmp = 0;
+ for (i=0 ; i < MAX_REGS(contact_fonts) ; i++)
+ {
+ if (tmp < dat->fontModernInfo[contact_fonts[i]].fontHeight)
+ tmp = dat->fontModernInfo[contact_fonts[i]].fontHeight;
+ }
+ if (dat->text_replace_smileys && dat->first_line_draw_smileys && !dat->text_resize_smileys)
+ {
+ tmp = max(tmp, dat->text_smiley_height);
+ }
+ max_height += tmp;
+
+ if (dat->second_line_show)
+ {
+ tmp = dat->fontModernInfo[FONTID_SECONDLINE].fontHeight;
+ if (dat->text_replace_smileys && dat->second_line_draw_smileys && !dat->text_resize_smileys)
+ {
+ tmp = max(tmp, dat->text_smiley_height);
+ }
+ max_height += dat->second_line_top_space + tmp;
+ }
+
+ if (dat->third_line_show)
+ {
+ tmp = dat->fontModernInfo[FONTID_THIRDLINE].fontHeight;
+ if (dat->text_replace_smileys && dat->third_line_draw_smileys && !dat->text_resize_smileys)
+ {
+ tmp = max(tmp, dat->text_smiley_height);
+ }
+ max_height += dat->third_line_top_space + tmp;
+ }
+
+ // Get other font sizes
+ for (i=0 ; i < MAX_REGS(other_fonts) ; i++)
+ {
+ if (max_height < dat->fontModernInfo[other_fonts[i]].fontHeight)
+ max_height = dat->fontModernInfo[other_fonts[i]].fontHeight;
+ }
+ }
+
+ // Avatar size
+ if (dat->avatars_show && !dat->avatars_ignore_size_for_row_height)
+ {
+ max_height = max(max_height, dat->avatars_maxheight_size);
+ }
+
+ // Checkbox size
+ if (style&CLS_CHECKBOXES || style&CLS_GROUPCHECKBOXES)
+ {
+ max_height = max(max_height, dat->checkboxSize);
+ }
+
+ // Icon size
+ if ( !dat->icon_ignore_size_for_row_height)
+ {
+ max_height = max(max_height, ICON_HEIGHT);
+ }
+
+ max_height += 2 * dat->row_border;
+
+ // Min size
+ max_height = max(max_height, dat->row_min_heigh);
+
+ dat->max_row_height = max_height;
+
+ return max_height;
+}
+
+
+// Calc and store row height for all items in the list
+void RowHeights_CalcRowHeights(struct ClcData *dat, HWND hwnd)
+{
+ if (MirandaExiting()) return;
+ g_mutex_nCalcRowHeightLock++;
+ RowHeights_CalcRowHeights_Worker(dat, hwnd);
+ g_mutex_nCalcRowHeightLock--;
+}
+
+void RowHeights_CalcRowHeights_Worker(struct ClcData *dat, HWND hwnd)
+{
+ int indent, subident, subindex, line_num;
+ struct ClcContact *Drawing;
+ struct ClcGroup *group;
+
+ if (MirandaExiting()) return;
+
+ // Draw lines
+ group = &dat->list;
+ group->scanIndex = 0;
+ indent = 0;
+ subindex = -1;
+ line_num = -1;
+
+ RowHeights_Clear(dat);
+
+ while(TRUE)
+ {
+ if (subindex == -1)
+ {
+ if (group->scanIndex == group->cl.count)
+ {
+ group = group->parent;
+ indent--;
+ if (group == NULL) break; // Finished list
+ group->scanIndex++;
+ continue;
+ }
+
+ // Get item to draw
+ Drawing = group->cl.items[group->scanIndex];
+ subident = 0;
+ }
+ else
+ {
+ // Get item to draw
+ Drawing = &(group->cl.items[group->scanIndex]->subcontacts[subindex]);
+ subident = dat->subIndent;
+ }
+
+ line_num++;
+
+ // Calc row height
+ if ( !gl_RowRoot) RowHeights_GetRowHeight(dat, hwnd, Drawing, line_num);
+ else RowHeight_CalcRowHeight(dat, hwnd, Drawing, line_num);
+
+ //increment by subcontacts
+ if (group->cl.items[group->scanIndex]->subcontacts != NULL && group->cl.items[group->scanIndex]->type != CLCIT_GROUP)
+ {
+ if (group->cl.items[group->scanIndex]->SubExpanded && dat->expandMeta)
+ {
+ if (subindex < group->cl.items[group->scanIndex]->SubAllocated-1)
+ {
+ subindex++;
+ }
+ else
+ {
+ subindex = -1;
+ }
+ }
+ }
+
+ if (subindex == -1)
+ {
+ if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP && group->cl.items[group->scanIndex]->group->expanded)
+ {
+ group = group->cl.items[group->scanIndex]->group;
+ indent++;
+ group->scanIndex = 0;
+ subindex = -1;
+ continue;
+ }
+ group->scanIndex++;
+ }
+ }
+
+}
+
+
+// Calc and store row height
+int RowHeights_GetRowHeight(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item)
+{
+ int res;
+ if (MirandaExiting()) return 0;
+ g_mutex_nCalcRowHeightLock++;
+ res = RowHeights_GetRowHeight_worker(dat, hwnd, contact, item);
+ g_mutex_nCalcRowHeightLock--;
+ return res;
+}
+
+int RowHeights_GetRowHeight_worker(struct ClcData *dat, HWND hwnd, struct ClcContact *contact, int item)
+{
+ int height = 0;
+ if (MirandaExiting()) return 0;
+ if (gl_RowRoot)
+ return RowHeight_CalcRowHeight(dat, hwnd, contact, item);
+ else
+ {
+ displayNameCacheEntry *pdnce = (displayNameCacheEntry *)pcli->pfnGetCacheEntry(contact->hContact);
+ DWORD style = GetWindowLongPtr(hwnd,GWL_STYLE);
+ //TODO replace futher code with new rowheight definition
+ int tmp;
+ BOOL selected = ((item == dat->selection) && (dat->hwndRenameEdit != NULL || dat->showSelAlways || dat->exStyle&CLS_EX_SHOWSELALWAYS || g_clcPainter.IsForegroundWindow(hwnd)) && contact->type != CLCIT_DIVIDER);
+ BOOL hottrack = ((item == dat->iHotTrack) && (dat->hwndRenameEdit != NULL || dat->showSelAlways || dat->exStyle&CLS_EX_SHOWSELALWAYS || g_clcPainter.IsForegroundWindow(hwnd)) && contact->type != CLCIT_DIVIDER);
+ BOOL minimalistic = (g_clcPainter.CheckMiniMode(dat,selected,hottrack));
+ if ( !RowHeights_Alloc(dat, item + 1))
+ return -1;
+
+ if (dat->row_variable_height)
+ {
+ if ( !dat->text_ignore_size_for_row_height)
+ {
+ HANDLE hContact = pdnce->hContact;
+ tmp = dat->fontModernInfo[g_clcPainter.GetBasicFontID(contact)].fontHeight;
+ if (dat->text_replace_smileys && dat->first_line_draw_smileys && !dat->text_resize_smileys)
+ {
+ tmp = max(tmp, contact->ssText.iMaxSmileyHeight);
+ }
+ height += tmp;
+
+ if ( !minimalistic && dat->second_line_show && pdnce->szSecondLineText && pdnce->szSecondLineText[0])
+ {
+ tmp = dat->fontModernInfo[FONTID_SECONDLINE].fontHeight;
+ if (dat->text_replace_smileys && dat->second_line_draw_smileys && !dat->text_resize_smileys)
+ {
+ tmp = max(tmp, pdnce->ssSecondLine.iMaxSmileyHeight);
+ }
+ height += dat->second_line_top_space + tmp;
+ }
+
+ if ( !minimalistic && dat->third_line_show && pdnce->szThirdLineText && pdnce->szThirdLineText[0])
+ {
+ tmp = dat->fontModernInfo[FONTID_THIRDLINE].fontHeight;
+ if (dat->text_replace_smileys && dat->third_line_draw_smileys && !dat->text_resize_smileys)
+ {
+ tmp = max(tmp, pdnce->ssThirdLine.iMaxSmileyHeight);
+ }
+ height += dat->third_line_top_space + tmp;
+ }
+ }
+
+ // Avatar size
+ if (dat->avatars_show && !dat->avatars_ignore_size_for_row_height &&
+ contact->type == CLCIT_CONTACT &&
+ (
+ (dat->use_avatar_service && contact->avatar_data != NULL) ||
+ (!dat->use_avatar_service && contact->avatar_pos != AVATAR_POS_DONT_HAVE)
+ ) && !minimalistic )
+ {
+ height = max(height, dat->avatars_maxheight_size);
+ }
+
+ // Checkbox size
+ if ((style&CLS_CHECKBOXES && contact->type == CLCIT_CONTACT) ||
+ (style&CLS_GROUPCHECKBOXES && contact->type == CLCIT_GROUP) ||
+ (contact->type == CLCIT_INFO && contact->flags&CLCIIF_CHECKBOX))
+ {
+ height = max(height, dat->checkboxSize);
+ }
+
+ // Icon size
+ if ( !dat->icon_ignore_size_for_row_height)
+ {
+ if (contact->type == CLCIT_GROUP
+ || (contact->type == CLCIT_CONTACT && contact->iImage != -1
+ && !(dat->icon_hide_on_avatar && dat->avatars_show
+ && ((dat->use_avatar_service && contact->avatar_data != NULL) ||
+ (!dat->use_avatar_service && contact->avatar_pos != AVATAR_POS_DONT_HAVE)
+ )
+ && !contact->image_is_special)))
+ {
+ height = max(height, ICON_HEIGHT);
+ }
+ }
+
+ height += 2 * dat->row_border;
+
+ // Min size
+ height = max(height, dat->row_min_heigh);
+ }
+ else
+ {
+ height = dat->max_row_height;
+ }
+
+ dat->row_heights[item] = height;
+
+ return height;
+ }
+}
+
+
+// Calc item top Y (using stored data)
+int cliGetRowTopY(struct ClcData *dat, int item)
+{
+ int i;
+ int y = 0;
+ if (item >= dat->row_heights_size)
+ return cliGetRowBottomY(dat,item-1);
+
+ for (i=0 ; i < item ; i++)
+ {
+ y += dat->row_heights[i];
+ }
+
+ return y;
+}
+
+
+// Calc item bottom Y (using stored data)
+int cliGetRowBottomY(struct ClcData *dat, int item)
+{
+ int i;
+ int y = 0;
+
+ if (item >= dat->row_heights_size)
+ return -1;
+
+ for (i=0 ; i <= item ; i++)
+ {
+ y += dat->row_heights[i];
+ }
+
+ return y;
+}
+
+
+// Calc total height of rows (using stored data)
+int cliGetRowTotalHeight(struct ClcData *dat)
+{
+ int i;
+ int y = 0;
+
+ for (i=0 ; i < dat->row_heights_size ; i++)
+ {
+ y += dat->row_heights[i];
+ }
+
+ return y;
+}
+
+// Return the line that pos_y is at or -1 (using stored data)
+int cliRowHitTest(struct ClcData *dat, int pos_y)
+{
+ int i;
+ int y = 0;
+
+ if (pos_y < 0)
+ return -1;
+
+ for (i=0 ; i < dat->row_heights_size ; i++)
+ {
+ y += dat->row_heights[i];
+
+ if (pos_y < y)
+ return i;
+ }
+
+ return -1;
+}
+
+int cliGetRowHeight(struct ClcData *dat, int item)
+{
+ if ( item >= dat->row_heights_size || item < 0 )
+ return dat->max_row_height;
+ return dat->row_heights[ item ];
+}
diff --git a/plugins/Clist_modern/src/modern_rowtemplateopt.cpp b/plugins/Clist_modern/src/modern_rowtemplateopt.cpp
new file mode 100644
index 0000000000..cc64f3a522
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_rowtemplateopt.cpp
@@ -0,0 +1,704 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "m_clc.h"
+#include "io.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_row.h"
+
+
+
+
+
+
+void RefreshTree(HWND hwndDlg,HTREEITEM hti);
+static char* rowOptTmplStr;
+static ROWCELL* rowOptTmplRoot;
+static ROWCELL* rowOptTA[100];
+ TCHAR *types[] = {_T("none"), _T("text1"), _T("text2"), _T("text3"), _T("status"),
+ _T("avatar"), _T("extra"), _T("extra1"), _T("extra2"), _T("extra3"),
+ _T("extra4"), _T("extra5"), _T("extra6"), _T("extra7"), _T("extra8"),
+ _T("extra9"), _T("time"), _T("space"), _T("fspace")};
+RECT da = {205,58,440,130}; // Draw area
+// Add by ZorG
+
+//char * rowOptBuildTmpl(HTREEITEM node, HWND htree)
+//{
+//}
+void rowOptBuildTA(pROWCELL cell, pROWCELL* TA, int* i)
+{
+ if ( !cell) return;
+ TA[(*i)++] = cell;
+ rowOptBuildTA(cell->child,TA, i);
+ rowOptBuildTA(cell->next, TA, i);
+}
+
+void rowOptShowSettings(HWND hwnd)
+{
+ TVITEM tvi;
+ pROWCELL cell;
+ HTREEITEM node = TreeView_GetSelection(GetDlgItem(hwnd, IDC_ROWTREE));
+ int param;
+
+ tvi.hItem = node;
+ tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+
+ TreeView_GetItem(GetDlgItem(hwnd, IDC_ROWTREE), &tvi);
+ cell = (pROWCELL)tvi.lParam;
+
+ if ( !tvi.hItem)
+ {
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTTYPE) ,0);
+ EnableWindow(GetDlgItem(hwnd,IDC_VALIGN),0);
+ EnableWindow(GetDlgItem(hwnd,IDC_HALIGN) ,0);
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTWIDTH) ,0);
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTHEIGHT),0);
+ EnableWindow(GetDlgItem(hwnd,IDC_SPINCONTWIDTH) ,0);
+ EnableWindow(GetDlgItem(hwnd,IDC_SPINCONTHEIGHT),0);
+ SendDlgItemMessage(hwnd,IDC_SPINCONTWIDTH, UDM_SETPOS,0,0);
+ SendDlgItemMessage(hwnd,IDC_SPINCONTHEIGHT,UDM_SETPOS,0,0);
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTLAYER),0);
+ return;
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTTYPE) ,1);
+ EnableWindow(GetDlgItem(hwnd,IDC_VALIGN),1);
+ EnableWindow(GetDlgItem(hwnd,IDC_HALIGN) ,1);
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTLAYER),1);
+
+ if (cell->type != TC_SPACE && cell->type != TC_FIXED)
+ {
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTWIDTH) ,0);
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTHEIGHT),0);
+ EnableWindow(GetDlgItem(hwnd,IDC_SPINCONTWIDTH) ,0);
+ EnableWindow(GetDlgItem(hwnd,IDC_SPINCONTHEIGHT),0);
+ SendDlgItemMessage(hwnd,IDC_SPINCONTWIDTH, UDM_SETPOS,0,0);
+ SendDlgItemMessage(hwnd,IDC_SPINCONTHEIGHT,UDM_SETPOS,0,0);
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTWIDTH) ,1);
+ EnableWindow(GetDlgItem(hwnd,IDC_CONTHEIGHT),1);
+ EnableWindow(GetDlgItem(hwnd,IDC_SPINCONTWIDTH) ,1);
+ EnableWindow(GetDlgItem(hwnd,IDC_SPINCONTHEIGHT),1);
+ SendDlgItemMessage(hwnd,IDC_SPINCONTWIDTH, UDM_SETPOS,0,MAKELONG(cell->w,0));
+ SendDlgItemMessage(hwnd,IDC_SPINCONTHEIGHT,UDM_SETPOS,0,MAKELONG(cell->h,0));
+ }
+
+ }
+
+ SendDlgItemMessage(hwnd, IDC_CONTTYPE, CB_SETCURSEL, cell->type, 0);
+
+ switch (cell->valign)
+ {
+ case TC_VCENTER:
+ param = 1;
+ break;
+ case TC_BOTTOM:
+ param = 2;
+ break;
+ default:
+ param = 0;
+ }
+ SendDlgItemMessage(hwnd, IDC_VALIGN, CB_SETCURSEL, param, 0);
+
+ switch (cell->halign)
+ {
+ case TC_HCENTER:
+ param = 1;
+ break;
+ case TC_RIGHT:
+ param = 2;
+ break;
+ default:
+ param = 0;
+ }
+ SendDlgItemMessage(hwnd, IDC_HALIGN, CB_SETCURSEL, param, 0);
+
+ CheckDlgButton(hwnd,IDC_CONTLAYER,cell->layer?BST_CHECKED:BST_UNCHECKED);
+
+ return;
+
+}
+
+void rowOptGenerateTreeView(pROWCELL cell, HTREEITEM node, HWND hwnd)
+{
+ TVINSERTSTRUCT tvis;
+ HTREEITEM pnode;
+
+ if ( !cell) return;
+
+ tvis.hParent = node;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ tvis.item.stateMask = TVIS_STATEIMAGEMASK;
+ tvis.item.lParam = (LPARAM)cell;
+
+ switch (cell->cont)
+ {
+ case TC_ROW:
+ tvis.item.pszText = _T("Line");
+ break;
+ case TC_COL:
+ tvis.item.pszText = _T("Column");
+ }
+
+ tvis.item.iImage = cell->child?1:2;
+ tvis.item.iSelectedImage = cell->child?0:2;
+
+ pnode = TreeView_InsertItem(hwnd,&tvis);
+
+ rowOptGenerateTreeView(cell->child, pnode, hwnd);
+ rowOptGenerateTreeView(cell->next, node, hwnd);
+}
+
+int rowOptFillRowTree(HWND hwnd)
+{
+ int i=0;
+ TreeView_DeleteAllItems(hwnd);
+ rowOptGenerateTreeView(rowOptTmplRoot, NULL, hwnd);
+ TreeView_Expand(hwnd, TreeView_GetRoot(hwnd), TVM_EXPAND);
+
+ return 0;
+}
+
+void rowOptAddContainer(HWND htree, HTREEITEM hti)
+{
+ TVINSERTSTRUCT tvis;
+ TVITEM tviparent;
+ ROWCELL *cell = NULL;
+
+ if ( !hti)
+ {
+ if (TreeView_GetRoot(htree)) return;
+ else
+ {
+ rowAddCell(rowOptTmplRoot, TC_ROW);
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = TVI_ROOT;
+ tvis.item.pszText = _T("Line");
+ tvis.item.lParam = (LPARAM)rowOptTmplRoot;
+ cell = rowOptTmplRoot;
+ }
+ }
+ else
+ {
+ // Get parent item
+ tviparent.hItem = hti;
+ tviparent.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ TreeView_GetItem(htree, &tviparent);
+ cell = (pROWCELL)tviparent.lParam;
+
+ if (cell->cont == TC_ROW)
+ tvis.item.pszText = _T("Column");
+ else
+ tvis.item.pszText = _T("Line");
+
+ if (cell->child)
+ {
+ cell = cell->child;
+
+ while (cell->next)
+ cell = cell->next;
+
+ rowAddCell(cell->next, ((ROWCELL*)tviparent.lParam)->cont == TC_ROW?TC_COL:TC_ROW);
+ cell = cell->next;
+ }
+ else
+ {
+ rowAddCell(cell->child, ((ROWCELL*)tviparent.lParam)->cont == TC_ROW?TC_COL:TC_ROW);
+ cell = cell->child;
+ }
+
+ tvis.hInsertAfter = TVI_LAST;
+ }
+
+ tvis.item.lParam = (LPARAM)cell;
+ tvis.hParent = hti;
+
+ tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ tvis.item.stateMask = TVIS_STATEIMAGEMASK;
+ tvis.item.iImage = 2;
+ tvis.item.iSelectedImage = 2;
+
+ TreeView_InsertItem(htree,&tvis);
+
+ TreeView_Expand(htree, hti, TVM_EXPAND);
+
+ // Change icon at parent item
+ tviparent.iImage = 1;
+ tviparent.iSelectedImage = 0;
+ TreeView_SetItem(htree, &tviparent);
+
+ {
+ int i=0;
+ ZeroMemory( rowOptTA, sizeof( rowOptTA ));
+ rowOptBuildTA(rowOptTmplRoot, (pROWCELL*)&rowOptTA, &i);
+ }
+
+}
+
+void rowOptDelContainer(HWND htree, HTREEITEM hti)
+{
+ HTREEITEM prev = TreeView_GetPrevSibling(htree, hti);
+ HTREEITEM prnt = TreeView_GetParent(htree, hti);
+ TVITEM tvi, tvpi;
+
+ if ( !hti) return;
+
+ // Get current tree item
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ TreeView_GetItem(htree, &tvi);
+
+ tvpi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+
+ if (prev)
+ {
+ tvpi.hItem = prev;
+ TreeView_GetItem(htree, &tvpi);
+ ((pROWCELL)tvpi.lParam)->next = ((pROWCELL)tvi.lParam)->next;
+ }
+ else
+ {
+ if (prnt)
+ {
+ tvpi.hItem = prnt;
+ TreeView_GetItem(htree, &tvpi);
+ ((pROWCELL)tvpi.lParam)->child = ((pROWCELL)tvi.lParam)->next;
+ prev = prnt;
+ }
+ else
+ {
+
+ tvpi.lParam = (LPARAM)NULL;
+ rowOptTmplRoot = (pROWCELL)tvpi.lParam;
+ }
+
+ }
+
+ ((pROWCELL)tvi.lParam)->next = NULL;
+ rowDeleteTree((pROWCELL)tvi.lParam);
+
+ {
+ int i=0;
+ ZeroMemory( rowOptTA, sizeof( rowOptTA ));
+ rowOptBuildTA((pROWCELL)tvpi.lParam, (pROWCELL*)&rowOptTA, &i );
+ }
+
+ TreeView_DeleteItem(htree, hti);
+
+
+ // Change icon at parent item
+ if ( !prnt || (prnt != prev)) return;
+
+ if ( TreeView_GetChild(htree, prnt))
+ {
+ tvpi.iImage = 1;
+ tvpi.iSelectedImage = 0;
+ }
+ else
+ {
+ tvpi.iImage = 2;
+ tvpi.iSelectedImage = 2;
+ }
+ TreeView_SetItem(htree, &tvpi);
+
+}
+
+void RefreshTree(HWND hwndDlg,HTREEITEM hti)
+{
+ HWND htree = GetDlgItem(hwndDlg, IDC_ROWTREE);
+ pROWCELL cell;
+ TVITEM tvi = {0};
+ if (hti == NULL) hti = TreeView_GetRoot(htree);
+ while (hti)
+ {
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE;//|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT;
+ TreeView_GetItem(htree, &tvi);
+ cell = (pROWCELL)tvi.lParam;
+ if (cell)
+ {
+ TCHAR buf[200] = {0};
+ if ( !cell->child)
+ {
+ if (cell->type == 0)
+ mir_sntprintf(buf, SIZEOF(buf), TranslateT("Empty %s cell"), cell->cont == TC_COL?TranslateT("column"):TranslateT("line"));
+ else
+ mir_sntprintf(buf, SIZEOF(buf), TranslateT("%s"), TranslateTS(types[cell->type]));
+ }
+ else
+ {
+ if (cell->type == 0)
+ mir_sntprintf(buf, SIZEOF(buf), TranslateT("%s"), cell->cont != TC_COL?TranslateT("columns"):TranslateT("lines"));
+ else
+ mir_sntprintf(buf, SIZEOF(buf), TranslateT("%s, contain %s"), TranslateTS(types[cell->type]),cell->cont != TC_COL?TranslateT("columns"):TranslateT("lines"));
+ }
+ if (cell->layer) _tcsncat(buf,TranslateT(" layered"),SIZEOF(buf));
+ tvi.mask = TVIF_HANDLE|TVIF_TEXT;
+ tvi.pszText = buf;
+ TreeView_SetItem(htree,&tvi);
+ }
+ {
+ HTREEITEM child_hti = TreeView_GetChild(htree,hti);
+ if (child_hti) RefreshTree(hwndDlg,child_hti);
+ }
+ hti = TreeView_GetNextSibling(htree,hti);
+ }
+
+ RedrawWindow(hwndDlg,NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_UPDATENOW|RDW_ALLCHILDREN);
+}
+
+INT_PTR CALLBACK DlgTmplEditorOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ int hbuf = 0, seq = 0;
+ HWND htree = GetDlgItem(hwndDlg,IDC_ROWTREE);
+
+ TranslateDialogDefault(hwndDlg);
+ rowOptTmplStr = db_get_sa(NULL, "ModernData", "RowTemplate");
+ if ( !rowOptTmplStr) rowOptTmplStr = mir_strdup("<TR />");
+ {
+ //HIMAGELIST himlTreeIcons;
+ //himlTreeIcons = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),ILC_COLOR32|ILC_MASK,3,2);
+ //ImageList_AddIcon(himlTreeIcons,LoadSmallIconShared(g_hInst,MAKEINTRESOURCE(IDI_ROWCONT1)));
+ //ImageList_AddIcon(himlTreeIcons,LoadSmallIconShared(g_hInst,MAKEINTRESOURCE(IDI_ROWCONT2)));
+ //ImageList_AddIcon(himlTreeIcons,LoadSmallIconShared(g_hInst,MAKEINTRESOURCE(IDI_ROWCONT3)));
+ //TreeView_SetImageList(htree,himlTreeIcons,TVSIL_NORMAL);
+ }
+
+ SendDlgItemMessage(hwndDlg,IDC_SPINCONTWIDTH, UDM_SETRANGE,0,MAKELONG(999,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPINCONTHEIGHT,UDM_SETRANGE,0,MAKELONG(999,0));
+
+ {
+ int i, item;
+
+ for (i=0; i < SIZEOF(types); i++)
+ {
+ item = SendDlgItemMessage(hwndDlg,IDC_CONTTYPE,CB_ADDSTRING,0,(LPARAM)TranslateTS(types[i]));
+ SendDlgItemMessage(hwndDlg,IDC_CONTTYPE,CB_SETITEMDATA,item,(LPARAM)0);
+ }
+ SendDlgItemMessage(hwndDlg,IDC_CONTTYPE,CB_SETCURSEL,0,0);
+ }
+
+ {
+ int i, item;
+ TCHAR *alignment[] = {_T("left"), _T("hCenter"), _T("right")};
+ for (i=0; i < SIZEOF(alignment); i++)
+ {
+ item = SendDlgItemMessage(hwndDlg,IDC_HALIGN,CB_ADDSTRING,0,(LPARAM)TranslateTS(alignment[i]));
+ SendDlgItemMessage(hwndDlg,IDC_HALIGN,CB_SETITEMDATA,item,(LPARAM)0);
+ }
+ SendDlgItemMessage(hwndDlg,IDC_HALIGN,CB_SETCURSEL,0,0);
+
+ }
+
+ {
+ int i, item;
+ TCHAR *alignment[] = {_T("top"), _T("vCenter"), _T("bottom")};
+ for (i=0; i < SIZEOF(alignment); i++)
+ {
+ item = SendDlgItemMessage(hwndDlg,IDC_VALIGN,CB_ADDSTRING,0,(LPARAM)TranslateTS(alignment[i]));
+ SendDlgItemMessage(hwndDlg,IDC_VALIGN,CB_SETITEMDATA,item,(LPARAM)0);
+ }
+ SendDlgItemMessage(hwndDlg,IDC_VALIGN,CB_SETCURSEL,0,0);
+ }
+
+ rowDeleteTree(rowOptTmplRoot);
+ rowOptTmplRoot = NULL;
+ rowParse(rowOptTmplRoot, rowOptTmplRoot, rowOptTmplStr, hbuf, seq, rowOptTA);
+ seq = 0;
+ ZeroMemory( rowOptTA, sizeof( rowOptTA ));
+ rowOptBuildTA(rowOptTmplRoot, (pROWCELL*)&rowOptTA, &seq);
+
+ rowOptFillRowTree(htree);
+ RefreshTree(hwndDlg,NULL);
+ TreeView_SelectItem(GetDlgItem(hwndDlg, IDC_ROWTREE), TreeView_GetRoot(GetDlgItem(hwndDlg, IDC_ROWTREE)));
+ rowOptShowSettings(hwndDlg);
+
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ HWND htree = GetDlgItem(hwndDlg, IDC_ROWTREE);
+ pROWCELL cell;
+ TVITEM tvi = {0};
+ HTREEITEM hti = TreeView_GetSelection(htree);
+
+
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ TreeView_GetItem(htree, &tvi);
+ cell = (pROWCELL)tvi.lParam;
+
+ switch (LOWORD(wParam))
+ {
+ case IDC_CONTTYPE:
+ if (HIWORD(wParam) == CBN_SELENDOK)
+ {
+ TVITEM tv = {0};
+ int index = SendMessage(GetDlgItem(hwndDlg,IDC_CONTTYPE),CB_GETCURSEL, 0, 0);
+ cell->type = index;
+ RefreshTree(hwndDlg,NULL);
+ }
+
+ case IDC_VALIGN:
+ if (HIWORD(wParam) == CBN_SELENDOK)
+ {
+ switch (SendMessage(GetDlgItem(hwndDlg,IDC_VALIGN),CB_GETCURSEL, 0, 0))
+ {
+ case 0:
+ cell->valign = TC_TOP;
+ break;
+ case 1:
+ cell->valign = TC_VCENTER;
+ break;
+ case 2:
+ cell->valign = TC_BOTTOM;
+ break;
+ }
+ RefreshTree(hwndDlg,NULL);
+ }
+
+ case IDC_HALIGN:
+ if (HIWORD(wParam) == CBN_SELENDOK)
+ {
+ switch (SendMessage(GetDlgItem(hwndDlg,IDC_HALIGN),CB_GETCURSEL, 0, 0))
+ {
+ case 0:
+ cell->halign = TC_LEFT;
+ break;
+ case 1:
+ cell->halign = TC_HCENTER;
+ break;
+ case 2:
+ cell->halign = TC_RIGHT;
+ break;
+ }
+ RefreshTree(hwndDlg,NULL);
+ }
+
+
+ }
+
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ if (lParam == (LPARAM)GetDlgItem(hwndDlg,IDC_ADDCONTAINER))
+ // Adding new container
+ {
+ rowOptAddContainer(htree, hti);
+ }
+ else if (lParam == (LPARAM)GetDlgItem(hwndDlg,IDC_DELCONTAINER))
+ // Deleting container
+ {
+ rowOptDelContainer(htree, hti);
+ }
+ else if (lParam == (LPARAM)GetDlgItem(hwndDlg,IDC_CONTUP))
+ // Moving container to up
+ {
+ RedrawWindow(htree,&da,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_UPDATENOW|RDW_ALLCHILDREN);
+ }
+ else if (lParam == (LPARAM)GetDlgItem(hwndDlg,IDC_CONTDOWN))
+ // Moving container to down
+ {
+ }
+ RefreshTree(hwndDlg,NULL);
+ RedrawWindow(GetParent(hwndDlg),NULL,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_UPDATENOW|RDW_ALLCHILDREN);
+ }
+
+
+ //SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ return TRUE;
+ }
+
+ case WM_NOTIFY:
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+
+ case IDC_ROWTREE:
+ if (((LPNMHDR)lParam)->code == NM_SETCURSOR )
+ rowOptShowSettings(hwndDlg);
+ if (((LPNMHDR)lParam)->code == NM_CLICK )
+ RedrawWindow(hwndDlg,&da,NULL,RDW_INVALIDATE|RDW_ERASE|RDW_UPDATENOW);
+ break;
+
+ case 0: // Apply or Ok button is pressed
+ return FALSE; // Temporary
+ break;
+ }
+ return TRUE;
+
+ case WM_PAINT:
+ {
+ int i=0;
+
+ // Drawning row template at properties page
+ PAINTSTRUCT ps;
+ HDC hdc;
+ TVITEM curItem;
+
+ if ( !rowOptTmplRoot) return FALSE;
+ hdc = BeginPaint(hwndDlg, &ps);
+
+ curItem.hItem = TreeView_GetSelection(GetDlgItem(hwndDlg, IDC_ROWTREE));
+ curItem.mask = TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
+ TreeView_GetItem(GetDlgItem(hwndDlg, IDC_ROWTREE), &curItem);
+
+ while(rowOptTA[i])
+ {
+ switch(rowOptTA[i]->type)
+ {
+ case TC_AVATAR:
+ rowOptTA[i]->w = 25;
+ rowOptTA[i]->h = 30;
+ break;
+
+ case TC_STATUS:
+ case TC_EXTRA1:
+ case TC_EXTRA2:
+ case TC_EXTRA3:
+ case TC_EXTRA4:
+ case TC_EXTRA5:
+ case TC_EXTRA6:
+ case TC_EXTRA7:
+ case TC_EXTRA8:
+ case TC_EXTRA9:
+ rowOptTA[i]->w = 16;
+ rowOptTA[i]->h = 16;
+ break;
+
+ case TC_EXTRA:
+ rowOptTA[i]->w = 112;
+ rowOptTA[i]->h = 16;
+ break;
+
+ case TC_TEXT1:
+ case TC_TEXT2:
+ case TC_TEXT3:
+ rowOptTA[i]->w = 200;
+ rowOptTA[i]->h = 16;
+ break;
+
+ case TC_TIME:
+ rowOptTA[i]->w = 30;
+ rowOptTA[i]->h = 10;
+ default:
+ {
+ rowOptTA[i]->w = 0;
+ rowOptTA[i]->h = 0;
+ }
+
+ }
+
+
+ i++;
+ }
+
+ rowSizeWithReposition(rowOptTmplRoot, da.right-da.left);
+
+
+
+ i = -1;
+ while (rowOptTA[++i])
+ {
+
+ switch(rowOptTA[i]->type)
+ {
+ case TC_SPACE:
+ case TC_FIXED:
+ case 0:
+ //if (rowOptTA[i] != (pROWCELL)curItem.lParam)
+ continue;
+ }
+ Rectangle(hdc,
+ rowOptTA[i]->r.left + da.left,
+ rowOptTA[i]->r.top + da.top,
+ rowOptTA[i]->r.right + da.left,
+ rowOptTA[i]->r.bottom + da.top);
+ }
+
+ EndPaint(hwndDlg, &ps);
+ return FALSE;
+ }
+
+ }
+ return FALSE;
+}
+
+
+
+
+/*
+BOOL CALLBACK DlgTmplEditorOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+
+{
+ switch (msg)
+ {
+ case WM_DESTROY:
+ {
+ break;
+ }
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ break;
+ }
+ case WM_COMMAND:
+ {
+ //LOWORD(wParam) == IDC_control
+ //HIWORD(wParam) == Message
+ //SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->idFrom)
+ {
+// case IDC_control:
+// {
+// break;
+// }
+ case 0:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ break;
+ } //case PSN_APPLY
+ } //switch code
+ } //case 0:
+ } //switch from
+ } //case: WM_NOTIFY
+ } // switch msg
+ return FALSE;
+}
+*/ \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_skinbutton.cpp b/plugins/Clist_modern/src/modern_skinbutton.cpp
new file mode 100644
index 0000000000..8bae142748
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_skinbutton.cpp
@@ -0,0 +1,815 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*
+This file contains code related to new modern free positioned skinned buttons
+*/
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_skinengine.h"
+#include "hdr/modern_clcpaint.h"
+#include "m_api/m_skinbutton.h"
+
+
+
+
+
+#define MODERNSKINBUTTONCLASS "MirandaModernSkinButtonClass"
+BOOL ModernSkinButtonModuleIsLoaded = FALSE;
+static HANDLE hookSystemShutdown_ModernSkinButton = NULL;
+static LRESULT CALLBACK ModernSkinButtonWndProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+int ModernSkinButtonUnloadModule(WPARAM wParam, LPARAM lParam);
+int SkinSelector_DeleteMask(MODERNMASK * mm);
+HWND SetToolTip(HWND hwnd, TCHAR * tip);
+
+typedef struct _ModernSkinButtonCtrl
+{
+ HWND hwnd;
+ BYTE down; // button state
+ BYTE focus; // has focus (1 or 0)
+ BYTE hover;
+ BYTE IsSwitcher;
+ BOOL fCallOnPress;
+ char * ID;
+ char * CommandService;
+ char * StateService;
+ char * HandleService;
+ char * ValueDBSection;
+ char * ValueTypeDef;
+ int Left, Top, Bottom, Right;
+ HMENU hMenu;
+ TCHAR * Hint;
+
+} ModernSkinButtonCtrl;
+typedef struct _HandleServiceParams
+{
+ HWND hwnd;
+ DWORD msg;
+ WPARAM wParam;
+ LPARAM lParam;
+ BOOL handled;
+} HandleServiceParams;
+
+static CRITICAL_SECTION csTips;
+static HWND hwndToolTips = NULL;
+
+int ModernSkinButtonLoadModule()
+{
+ WNDCLASSEX wc;
+ ZeroMemory(&wc, sizeof(wc));
+ wc.cbSize = sizeof(wc);
+ wc.lpszClassName = _T(MODERNSKINBUTTONCLASS);
+ wc.lpfnWndProc = ModernSkinButtonWndProc;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.cbWndExtra = sizeof(ModernSkinButtonCtrl*);
+ wc.hbrBackground = 0;
+ wc.style = CS_GLOBALCLASS;
+ RegisterClassEx(&wc);
+ InitializeCriticalSection(&csTips);
+ hookSystemShutdown_ModernSkinButton = HookEvent(ME_SYSTEM_SHUTDOWN, ModernSkinButtonUnloadModule);
+ ModernSkinButtonModuleIsLoaded = TRUE;
+ return 0;
+}
+
+int ModernSkinButtonUnloadModule(WPARAM wParam, LPARAM lParam)
+{
+ DeleteCriticalSection(&csTips);
+ return 0;
+}
+
+static int ModernSkinButtonPaintWorker(HWND hwnd, HDC whdc)
+{
+ HDC hdc;
+ HBITMAP bmp,oldbmp;
+ RECT rc;
+ HDC sdc = NULL;
+ ModernSkinButtonCtrl* bct = (ModernSkinButtonCtrl *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ if ( !bct) return 0;
+ if ( !IsWindowVisible(hwnd)) return 0;
+ if ( !whdc && !g_CluiData.fLayered) InvalidateRect(hwnd,NULL,FALSE);
+
+ if (whdc && g_CluiData.fLayered) hdc = whdc;
+ else
+ {
+ //sdc = GetWindowDC(GetParent(hwnd));
+ hdc = CreateCompatibleDC(NULL);
+ }
+ GetClientRect(hwnd,&rc);
+ bmp = ske_CreateDIB32(rc.right,rc.bottom);
+ oldbmp = (HBITMAP)SelectObject(hdc,bmp);
+ if ( !g_CluiData.fLayered)
+ ske_BltBackImage(bct->hwnd,hdc,NULL);
+ {
+ MODERNMASK Request = {0};
+ // int res;
+ //HBRUSH br = CreateSolidBrush(RGB(255,255,255));
+ char * Value = NULL;
+ DWORD val = 0;
+ {
+ if (bct->ValueDBSection && bct->ValueTypeDef)
+ {
+ char * key;
+ char * section;
+ DWORD defval = 0;
+ char buf[20];
+ key = mir_strdup(bct->ValueDBSection);
+ section = key;
+ if (bct->ValueTypeDef[0] != 's')
+ defval = (DWORD)atol(bct->ValueTypeDef+1);
+ do
+ {
+ if (key[0] == '/') {key[0] = '\0'; key++; break;}
+ key++;
+ } while (key[0] != '\0');
+ switch (bct->ValueTypeDef[0])
+ {
+ case 's':
+ {
+ Value = db_get_sa(NULL,section,key);
+ if ( !Value)
+ Value = mir_strdup(bct->ValueTypeDef+1);
+ break;
+ }
+ case 'd':
+ defval = db_get_dw(NULL,section,key,defval);
+ Value = mir_strdup(_ltoa(defval,buf,SIZEOF(buf)));
+ break;
+ case 'w':
+ defval = db_get_w(NULL,section,key,defval);
+ Value = mir_strdup(_ltoa(defval,buf,SIZEOF(buf)));
+ break;
+ case 'b':
+ defval = db_get_b(NULL,section,key,defval);
+ Value = mir_strdup(_ltoa(defval,buf,SIZEOF(buf)));
+ break;
+ }
+ mir_free(section);
+ }
+
+ }
+ g_clcPainter.AddParam(&Request,mod_CalcHash("Module"),"MButton",0);
+ g_clcPainter.AddParam(&Request,mod_CalcHash("ID"),bct->ID,0);
+ g_clcPainter.AddParam(&Request,mod_CalcHash("Down"),bct->down?"1":"0",0);
+ g_clcPainter.AddParam(&Request,mod_CalcHash("Focused"),bct->focus?"1":"0",0);
+ g_clcPainter.AddParam(&Request,mod_CalcHash("Hovered"),bct->hover?"1":"0",0);
+ if (Value) {
+ g_clcPainter.AddParam(&Request,mod_CalcHash("Value"),Value,0);
+ mir_free(Value);
+ }
+ SkinDrawGlyphMask(hdc,&rc,&rc,&Request);
+ SkinSelector_DeleteMask(&Request);
+ // DeleteObject(br);
+ }
+
+ if ( !whdc && g_CluiData.fLayered)
+ {
+ RECT r;
+ SetRect(&r,bct->Left,bct->Top,bct->Right,bct->Bottom);
+ ske_DrawImageAt(hdc,&r);
+ //CallingService to immeadeately update window with new image.
+ }
+ if (whdc && !g_CluiData.fLayered)
+ {
+ RECT r = {0};
+ GetClientRect(bct->hwnd,&r);
+ BitBlt(whdc,0,0,r.right,r.bottom,hdc,0,0,SRCCOPY);
+ }
+ SelectObject(hdc,oldbmp);
+ DeleteObject(bmp);
+ if ( !whdc || !g_CluiData.fLayered)
+ {
+ SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
+ mod_DeleteDC(hdc);
+ }
+ // if (sdc)
+ // ReleaseDC(GetParent(hwnd),sdc);
+ return 0;
+}
+
+static int ModernSkinButtonToggleDBValue(char * ValueDBSection,char *ValueTypeDef)
+{
+ if (ValueDBSection && ValueTypeDef)
+ {
+ char * key;
+ char * section;
+ char * val;
+ char * val2;
+ char * Value;
+ long l1,l2,curval;
+ DWORD defval = 0;
+ // char buf[20];
+ key = mir_strdup(ValueDBSection);
+ section = key;
+ do
+ {
+ if (key[0] == '/') {key[0] = '\0'; key++; break;}
+ key++;
+ } while (key[0] != '\0');
+
+ val = mir_strdup(ValueTypeDef+1);
+ val2 = val;
+ do
+ {
+ if (val2[0] == '/') {val2[0] = '\0'; val2++; break;}
+ val2++;
+ } while (val2[0] != '\0');
+
+ if (ValueTypeDef[0] != 's')
+ {
+ l1 = (DWORD)atol(val);
+ l2 = (DWORD)atol(val2);
+ }
+
+ switch (ValueTypeDef[0]) {
+ case 's':
+ Value = db_get_sa(NULL,section,key);
+ if ( !Value || (Value && mir_bool_strcmpi(Value,val2)))
+ Value = mir_strdup(val);
+ else
+ Value = mir_strdup(val2);
+ db_set_s(NULL,section,key,Value);
+ mir_free(Value);
+ break;
+
+ case 'd':
+ curval = db_get_dw(NULL,section,key,l2);
+ curval = (curval == l2)?l1:l2;
+ db_set_dw(NULL,section,key,(DWORD)curval);
+ break;
+
+ case 'w':
+ curval = db_get_w(NULL,section,key,l2);
+ curval = (curval == l2)?l1:l2;
+ db_set_w(NULL,section,key,(WORD)curval);
+ break;
+
+ case 'b':
+ curval = db_get_b(NULL,section,key,l2);
+ curval = (curval == l2)?l1:l2;
+ db_set_b(NULL,section,key,(BYTE)curval);
+ break;
+ }
+ mir_free(section);
+ mir_free(val);
+ }
+ return 0;
+}
+
+static char *_skipblank(char * str) //str will be modified;
+{
+ char * endstr = str+strlen(str);
+ while ((*str == ' ' || *str == '\t') && *str != '\0') str++;
+ while ((*endstr == ' ' || *endstr == '\t') && *endstr != '\0' && endstr < str) endstr--;
+ if (*endstr != '\0')
+ {
+ endstr++;
+ *endstr = '\0';
+ }
+ return str;
+}
+
+static int _CallServiceStrParams(IN char * toParce, OUT int *Return)
+{
+ char * pszService;
+ char * param1 = NULL;
+ char * param2 = NULL;
+ int paramCount = 0;
+ int result = 0;
+ pszService = mir_strdup(toParce);
+ param2 = strrchr(pszService, '%');
+ if (param2)
+ {
+ paramCount++;
+ *param2 = '\0'; param2++;
+ _skipblank(param2);
+ if (strlen(param2) == 0) param2 = NULL;
+ }
+ param1 = strrchr(pszService, '%');
+ if (param1)
+ {
+ paramCount++;
+ *param1 = '\0'; param1++;
+ _skipblank(param1);
+ if (strlen(param1) == 0) param1 = NULL;
+ }
+ if ( !pszService) return 0;
+ if (strlen(pszService) == 0) {
+ mir_free(pszService);
+ return 0;
+ }
+ if (param1 && *param1 == '\"')
+ {
+ param1++;
+ *(param1+strlen(param1)) = '\0';
+ }
+ else if (param1)
+ {
+ param1 = (char*)atoi(param1);
+ }
+ if (param2 && *param2 == '\"')
+ {
+ param2++;
+ *(param2+strlen(param2)) = '\0';
+ }
+ else if (param2)
+ param2 = (char*)atoi(param2);
+
+ if (paramCount == 1)
+ {
+ param1 = param2;
+ param2 = NULL;
+ }
+ if ( !ServiceExists(pszService))
+ {
+ result = 0;
+ }
+ else
+ {
+ int ret = 0;
+ result = 1;
+ ret = CallService(pszService, (WPARAM)param1, (WPARAM)param2);
+ if (Return) *Return = ret;
+ }
+ mir_free(pszService);
+ return result;
+}
+
+
+static LRESULT CALLBACK ModernSkinButtonWndProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ ModernSkinButtonCtrl* bct = (msg != WM_NCCREATE)?(ModernSkinButtonCtrl *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA):0;
+ if (bct && bct->HandleService && IsBadStringPtrA(bct->HandleService,255))
+ bct->HandleService = NULL;
+
+ if (bct)
+ if (bct->HandleService)
+ if (ServiceExists(bct->HandleService))
+ {
+ int t;
+ HandleServiceParams MSG = {0};
+ MSG.hwnd = hwndDlg;
+ MSG.msg = msg;
+ MSG.wParam = wParam;
+ MSG.lParam = lParam;
+ t = CallService(bct->HandleService,(WPARAM)&MSG,0);
+ if (MSG.handled) return t;
+ }
+ switch(msg)
+ {
+ case WM_NCCREATE:
+ {
+ SetWindowLongPtr(hwndDlg, GWL_STYLE, GetWindowLongPtr(hwndDlg, GWL_STYLE)|BS_OWNERDRAW);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ if (((CREATESTRUCT *)lParam)->lpszName) SetWindowText(hwndDlg, ((CREATESTRUCT *)lParam)->lpszName);
+ return TRUE;
+ }
+ case WM_DESTROY:
+ {
+ if (bct) {
+ EnterCriticalSection(&csTips);
+ if (hwndToolTips) {
+ TOOLINFO ti;
+ ZeroMemory(&ti, sizeof(ti));
+ ti.cbSize = sizeof(ti);
+ ti.uFlags = TTF_IDISHWND;
+ ti.hwnd = bct->hwnd;
+ ti.uId = (UINT_PTR)bct->hwnd;
+ if (SendMessage(hwndToolTips, TTM_GETTOOLINFO, 0, (LPARAM)&ti)) {
+ SendMessage(hwndToolTips, TTM_DELTOOL, 0, (LPARAM)&ti);
+ }
+ if (SendMessage(hwndToolTips, TTM_GETTOOLCOUNT, 0, (LPARAM)&ti) == 0) {
+ DestroyWindow(hwndToolTips);
+ hwndToolTips = NULL;
+ }
+ }
+ LeaveCriticalSection(&csTips);
+ mir_free(bct->ID);
+ mir_free(bct->CommandService);
+ mir_free(bct->StateService);
+ mir_free(bct->HandleService);
+ mir_free(bct->Hint);
+ mir_free(bct->ValueDBSection);
+ mir_free(bct->ValueTypeDef);
+ mir_free(bct);
+ }
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ break; // DONT! fall thru
+ }
+ case WM_SETCURSOR:
+ {
+ HCURSOR hCurs1;
+ hCurs1 = LoadCursor(NULL, IDC_ARROW);
+ if (hCurs1) SetCursor(hCurs1);
+ if (bct) SetToolTip(hwndDlg, bct->Hint);
+ return 1;
+ }
+ case WM_PRINT:
+ {
+ if (IsWindowVisible(hwndDlg))
+ ModernSkinButtonPaintWorker(hwndDlg,(HDC)wParam);
+ break;
+ }
+ case WM_PAINT:
+ {
+ if (IsWindowVisible(hwndDlg) && !g_CluiData.fLayered)
+ {
+ PAINTSTRUCT ps = {0};
+ BeginPaint(hwndDlg,&ps);
+ ModernSkinButtonPaintWorker(hwndDlg,(HDC)ps.hdc);
+ EndPaint(hwndDlg,&ps);
+ }
+ return DefWindowProc(hwndDlg, msg, wParam, lParam);
+ }
+ case WM_CAPTURECHANGED:
+ {
+ bct->hover = 0;
+ bct->down = 0;
+ ModernSkinButtonPaintWorker(bct->hwnd,0);
+ // KillTimer(bct->hwnd,1234);
+ break;
+ }
+ //case WM_TIMER:
+ // {
+ // POINT t;
+ // GetCursorPos(&t);
+ // if (bct->hover && WindowFromPoint(t) != bct->hwnd)
+ // {
+ // KillTimer(bct->hwnd,1234);
+ // bct->hover = 0;
+ // ReleaseCapture();
+ // PaintWorker(bct->hwnd,0);
+ // }
+ // return 0;
+ // }
+ case WM_MOUSEMOVE:
+ {
+ if ( !bct->hover)
+ {
+ SetCapture(bct->hwnd);
+ bct->hover = 1;
+ //KillTimer(bct->hwnd,1234);
+ //CLUI_SafeSetTimer(bct->hwnd,1234,100,NULL);
+ ModernSkinButtonPaintWorker(bct->hwnd,0);
+ return 0;
+ }
+ else
+ {
+ POINT t;
+ t.x = LOWORD(lParam);
+ t.y = HIWORD(lParam);
+ ClientToScreen(bct->hwnd,&t);
+ if (WindowFromPoint(t) != bct->hwnd)
+ ReleaseCapture();
+ return 0;
+ }
+
+
+ }
+ case WM_LBUTTONDOWN:
+ {
+ //KillTimer(bct->hwnd,1234);
+ //CLUI_SafeSetTimer(bct->hwnd,1234,100,NULL);
+ bct->down = 1;
+ SetForegroundWindow(GetParent(bct->hwnd));
+ ModernSkinButtonPaintWorker(bct->hwnd,0);
+ if (bct && bct->CommandService && IsBadStringPtrA(bct->CommandService,255))
+ bct->CommandService = NULL;
+ if (bct->fCallOnPress)
+ {
+ if (bct->CommandService)
+ {
+
+ if ( !_CallServiceStrParams(bct->CommandService, NULL) && (bct->ValueDBSection && bct->ValueTypeDef))
+ ModernSkinButtonToggleDBValue(bct->ValueDBSection,bct->ValueTypeDef);
+ }
+ bct->down = 0;
+
+ ModernSkinButtonPaintWorker(bct->hwnd,0);
+ }
+
+ return 0;
+ }
+ case WM_LBUTTONUP:
+ if (bct->down)
+ {
+ //KillTimer(bct->hwnd,1234);
+ //CLUI_SafeSetTimer(bct->hwnd,1234,100,NULL);
+ ReleaseCapture();
+ bct->hover = 0;
+ bct->down = 0;
+ ModernSkinButtonPaintWorker(bct->hwnd,0);
+ if (bct && bct->CommandService && IsBadStringPtrA(bct->CommandService,255))
+ bct->CommandService = NULL;
+ if (bct->CommandService)
+ if (_CallServiceStrParams(bct->CommandService, NULL))
+ {}
+ else if (bct->ValueDBSection && bct->ValueTypeDef)
+ ModernSkinButtonToggleDBValue(bct->ValueDBSection,bct->ValueTypeDef);
+ }
+
+
+ }
+ return DefWindowProc(hwndDlg, msg, wParam, lParam);
+}
+
+
+HWND SetToolTip(HWND hwnd, TCHAR * tip)
+{
+ TOOLINFO ti;
+ if ( !tip) return 0;
+ EnterCriticalSection(&csTips);
+ if ( !hwndToolTips) {
+ // hwndToolTips = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, _T(""), WS_POPUP, 0, 0, 0, 0, NULL, NULL, GetModuleHandle(NULL), NULL);
+
+ hwndToolTips = CreateWindowEx(0, TOOLTIPS_CLASS, NULL,
+ WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ hwnd, NULL, GetModuleHandle(NULL),
+ NULL);
+
+ SetWindowPos(hwndToolTips, HWND_TOPMOST,0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ }
+
+ ZeroMemory(&ti, sizeof(ti));
+ ti.cbSize = sizeof(ti);
+ ti.uFlags = TTF_IDISHWND;
+ ti.hwnd = hwnd;
+ ti.uId = (UINT_PTR)hwnd;
+ if (SendMessage(hwndToolTips, TTM_GETTOOLINFO, 0, (LPARAM)&ti)) {
+ SendMessage(hwndToolTips, TTM_DELTOOL, 0, (LPARAM)&ti);
+ }
+ ti.uFlags = TTF_IDISHWND|TTF_SUBCLASS;
+ ti.uId = (UINT_PTR)hwnd;
+ ti.lpszText = (TCHAR*)tip;
+ SendMessage(hwndToolTips,TTM_ADDTOOL,0,(LPARAM)&ti);
+
+ LeaveCriticalSection(&csTips);
+ return hwndToolTips;
+}
+
+
+
+typedef struct _MButton
+{
+ HWND hwnd;
+ BYTE ConstrainPositionFrom; //(BBRRTTLL) L = 0 - from left, L = 1 from right, L = 2 from center
+ int OrL,OrR,OrT,OrB;
+ int minW,minH;
+ ModernSkinButtonCtrl * bct;
+
+} MButton;
+MButton * Buttons = NULL;
+DWORD ButtonsCount = 0;
+
+#define _center_h( rc ) (((rc)->right + (rc)->left ) >> 1)
+#define _center_v( rc ) (((rc)->bottom + (rc)->top ) >> 1)
+
+int ModernSkinButton_AddButton(HWND parent,
+ char * ID,
+ char * CommandService,
+ char * StateDefService,
+ char * HandeService,
+ int Left,
+ int Top,
+ int Right,
+ int Bottom,
+ DWORD sbFlags,
+ TCHAR * Hint,
+ char * DBkey,
+ char * TypeDef,
+ int MinWidth, int MinHeight)
+{
+ // if ( !parent) return 0;
+ if ( !ModernSkinButtonModuleIsLoaded) return 0;
+ if ( !Buttons)
+ Buttons = (MButton*)mir_alloc(sizeof(MButton));
+ else
+ Buttons = (MButton*)mir_realloc(Buttons,sizeof(MButton)*(ButtonsCount+1));
+ {
+ //HWND hwnd;
+ RECT rc = {0};
+ ModernSkinButtonCtrl* bct;
+ int l,r,b,t;
+ if (parent) GetClientRect(parent,&rc);
+ l = ( sbFlags & SBF_ALIGN_TL_RIGHT ) ? ( rc.right + Left ) :
+ ( sbFlags & SBF_ALIGN_TL_HCENTER ) ? ( _center_h( &rc ) + Left ) :
+ ( rc.left + Left );
+
+ t = ( sbFlags & SBF_ALIGN_TL_BOTTOM ) ? ( rc.bottom + Top ) :
+ ( sbFlags & SBF_ALIGN_TL_VCENTER ) ? ( _center_v( &rc ) + Top ) :
+ ( rc.top+Top );
+
+ r = ( sbFlags & SBF_ALIGN_BR_RIGHT ) ? ( rc.right + Right ) :
+ ( sbFlags & SBF_ALIGN_BR_HCENTER ) ? ( _center_h( &rc) + Right ) :
+ ( rc.left + Right );
+
+ b = ( sbFlags & SBF_ALIGN_BR_BOTTOM ) ? ( rc.bottom + Bottom ) :
+ ( sbFlags & SBF_ALIGN_BR_VCENTER ) ? ( _center_v( &rc ) + Bottom ) :
+ ( rc.top + Bottom );
+ bct = (ModernSkinButtonCtrl *)mir_alloc(sizeof(ModernSkinButtonCtrl));
+ memset(bct,0,sizeof(ModernSkinButtonCtrl));
+ bct->Left = l;
+ bct->Right = r;
+ bct->Top = t;
+ bct->Bottom = b;
+ bct->fCallOnPress = ( sbFlags & SBF_CALL_ON_PRESS ) != 0;
+ bct->HandleService = mir_strdup(HandeService);
+ bct->CommandService = mir_strdup(CommandService);
+ bct->StateService = mir_strdup(StateDefService);
+ if (DBkey && &DBkey != '\0') bct->ValueDBSection = mir_strdup(DBkey); else bct->ValueDBSection = NULL;
+ if (TypeDef && &TypeDef != '\0') bct->ValueTypeDef = mir_strdup(TypeDef); else bct->ValueTypeDef = mir_strdup("sDefault");
+ bct->ID=mir_strdup(ID);
+ bct->Hint = mir_tstrdup(Hint);
+ Buttons[ButtonsCount].bct = bct;
+ Buttons[ButtonsCount].hwnd = NULL;
+ Buttons[ButtonsCount].OrL = Left;
+ Buttons[ButtonsCount].OrT = Top;
+ Buttons[ButtonsCount].OrR = Right;
+ Buttons[ButtonsCount].OrB = Bottom;
+ Buttons[ButtonsCount].ConstrainPositionFrom = (BYTE)sbFlags;
+ Buttons[ButtonsCount].minH = MinHeight;
+ Buttons[ButtonsCount].minW = MinWidth;
+ ButtonsCount++;
+ // CLUI_ShowWindowMod(hwnd,SW_SHOW);
+ }
+ return 0;
+}
+
+
+
+static int ModernSkinButtonErase(int l,int t,int r, int b)
+{
+ DWORD i;
+ if ( !ModernSkinButtonModuleIsLoaded) return 0;
+ if ( !g_CluiData.fLayered) return 0;
+ if ( !g_pCachedWindow) return 0;
+ if ( !g_pCachedWindow->hImageDC || !g_pCachedWindow->hBackDC) return 0;
+ if ( !(l || r || t || b))
+ {
+ for (i=0; i < ButtonsCount; i++)
+ {
+ if (pcli->hwndContactList && Buttons[i].hwnd != NULL)
+ {
+ //TODO: Erase button
+ BitBlt(g_pCachedWindow->hImageDC,Buttons[i].bct->Left,Buttons[i].bct->Top,Buttons[i].bct->Right-Buttons[i].bct->Left,Buttons[i].bct->Bottom-Buttons[i].bct->Top,
+ g_pCachedWindow->hBackDC,Buttons[i].bct->Left,Buttons[i].bct->Top,SRCCOPY);
+ }
+ }
+ }
+ else
+ {
+ BitBlt(g_pCachedWindow->hImageDC,l,t,r-l,b-t, g_pCachedWindow->hBackDC,l,t,SRCCOPY);
+ }
+ return 0;
+}
+
+static HWND ModernSkinButtonCreateWindow(ModernSkinButtonCtrl * bct, HWND parent)
+{
+ HWND hwnd;
+
+ if (bct == NULL) return FALSE;
+ {
+ TCHAR *UnicodeID;
+ UnicodeID = mir_a2u(bct->ID);
+ hwnd = CreateWindow(_T(MODERNSKINBUTTONCLASS),UnicodeID,WS_VISIBLE|WS_CHILD,bct->Left,bct->Top,bct->Right-bct->Left,bct->Bottom-bct->Top,parent,NULL,g_hInst,NULL);
+ mir_free(UnicodeID);
+ }
+
+ bct->hwnd = hwnd;
+ bct->focus = 0;
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)bct);
+ return hwnd;
+}
+
+int ModernSkinButtonRedrawAll(HDC hdc)
+{
+ DWORD i;
+ if ( !ModernSkinButtonModuleIsLoaded) return 0;
+ g_mutex_bLockUpdating++;
+ for (i=0; i < ButtonsCount; i++)
+ {
+ if (pcli->hwndContactList && Buttons[i].hwnd == NULL)
+ Buttons[i].hwnd = ModernSkinButtonCreateWindow(Buttons[i].bct,pcli->hwndContactList);
+ ModernSkinButtonPaintWorker(Buttons[i].hwnd,0);
+ }
+ g_mutex_bLockUpdating--;
+ return 0;
+}
+
+int ModernSkinButtonDeleteAll()
+{
+ if ( !ModernSkinButtonModuleIsLoaded)
+ return 0;
+
+ for (size_t i=0; i < ButtonsCount; i++)
+ if (Buttons[i].hwnd)
+ DestroyWindow(Buttons[i].hwnd);
+
+ mir_free_and_nil(Buttons);
+ ButtonsCount = 0;
+ return 0;
+}
+
+int ModernSkinButton_ReposButtons(HWND parent, BYTE draw, RECT * r)
+{
+ DWORD i;
+ RECT rc;
+ RECT clr;
+ RECT rd;
+ BOOL altDraw = FALSE;
+ static SIZE oldWndSize = {0};
+ if ( !ModernSkinButtonModuleIsLoaded) return 0;
+ GetWindowRect(parent,&rd);
+ GetClientRect(parent,&clr);
+ if ( !r)
+ GetWindowRect(parent,&rc);
+ else
+ rc = *r;
+ if (g_CluiData.fLayered && ( draw & SBRF_DO_ALT_DRAW ))
+ {
+ int sx,sy;
+ sx = rd.right-rd.left;
+ sy = rd.bottom-rd.top;
+ if (sx != oldWndSize.cx || sy != oldWndSize.cy)
+ altDraw = TRUE;//EraseButtons();
+ oldWndSize.cx = sx;
+ oldWndSize.cy = sy;
+ }
+
+ OffsetRect(&rc,-rc.left,-rc.top);
+ rc.right = rc.left+(clr.right-clr.left);
+ rc.bottom = rc.top+(clr.bottom-clr.top);
+ for (i=0; i < ButtonsCount; i++)
+ {
+ int l,r,b,t;
+ RECT oldRect = {0};
+ int sbFlags = Buttons[i].ConstrainPositionFrom;
+ if (parent && Buttons[i].hwnd == NULL)
+ {
+ Buttons[i].hwnd = ModernSkinButtonCreateWindow(Buttons[i].bct,parent);
+ altDraw = FALSE;
+ }
+
+ l = ( sbFlags & SBF_ALIGN_TL_RIGHT ) ? ( rc.right + Buttons[i].OrL ) :
+ ( sbFlags & SBF_ALIGN_TL_HCENTER ) ? ( _center_h( &rc ) + Buttons[i].OrL ) :
+ ( rc.left + Buttons[i].OrL );
+
+ t = ( sbFlags & SBF_ALIGN_TL_BOTTOM ) ? ( rc.bottom + Buttons[i].OrT ) :
+ ( sbFlags & SBF_ALIGN_TL_VCENTER ) ? ( _center_v( &rc ) + Buttons[i].OrT ) :
+ ( rc.top + Buttons[i].OrT );
+
+ r = ( sbFlags & SBF_ALIGN_BR_RIGHT ) ? ( rc.right + Buttons[i].OrR ) :
+ ( sbFlags & SBF_ALIGN_BR_HCENTER ) ? ( _center_h( &rc) + Buttons[i].OrR ) :
+ ( rc.left + Buttons[i].OrR );
+
+ b = ( sbFlags & SBF_ALIGN_BR_BOTTOM ) ? ( rc.bottom + Buttons[i].OrB ) :
+ ( sbFlags & SBF_ALIGN_BR_VCENTER ) ? ( _center_v( &rc ) + Buttons[i].OrB ) :
+ ( rc.top + Buttons[i].OrB );
+
+ SetWindowPos(Buttons[i].hwnd,HWND_TOP,l,t,r-l,b-t,0);
+ if ( (rc.right-rc.left < Buttons[i].minW /* && Buttons[i].minW != 0*/)
+ || (rc.bottom-rc.top < Buttons[i].minH /* && Buttons[i].minH != 0*/))
+ CLUI_ShowWindowMod(Buttons[i].hwnd,SW_HIDE);
+ else
+ CLUI_ShowWindowMod(Buttons[i].hwnd,SW_SHOW);
+ if ((1 || altDraw) &&
+ (Buttons[i].bct->Left != l ||
+ Buttons[i].bct->Top != t ||
+ Buttons[i].bct->Right != r ||
+ Buttons[i].bct->Bottom != b))
+ {
+ //Need to erase in old location
+ ModernSkinButtonErase(Buttons[i].bct->Left,Buttons[i].bct->Top,Buttons[i].bct->Right,Buttons[i].bct->Bottom);
+ }
+
+ Buttons[i].bct->Left = l;
+ Buttons[i].bct->Top = t;
+ Buttons[i].bct->Right = r;
+ Buttons[i].bct->Bottom = b;
+
+
+ }
+ if ( draw & SBRF_DO_REDRAW_ALL ) ModernSkinButtonRedrawAll(0);
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_skineditor.cpp b/plugins/Clist_modern/src/modern_skineditor.cpp
new file mode 100644
index 0000000000..36763ef5d5
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_skineditor.cpp
@@ -0,0 +1,841 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "m_clc.h"
+#include "io.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_sync.h"
+
+typedef struct _OPT_OBJECT_DATA
+{
+ char * szName;
+ char * szPath;
+ char * szValue;
+ char * szTempValue;
+} OPT_OBJECT_DATA;
+
+static char *gl_Mask = NULL;
+HWND gl_Dlg = NULL;
+int gl_controlID = 0;
+int EnableGroup(HWND hwndDlg, HWND first, BOOL bEnable);
+int ShowGroup(HWND hwndDlg, HWND first, BOOL bEnable);
+BOOL glOtherSkinWasLoaded = FALSE;
+BYTE glSkinWasModified = 0; //1- but not applied, 2-stored to DB
+HTREEITEM FindChild(HWND hTree, HTREEITEM Parent, char * Caption)
+{
+ HTREEITEM res = NULL, tmp = NULL;
+ if (Parent)
+ tmp = TreeView_GetChild(hTree,Parent);
+ else
+ tmp = TreeView_GetRoot(hTree);
+ while (tmp)
+ {
+ TVITEMA tvi;
+ char buf[255];
+ tvi.hItem = tmp;
+ tvi.mask = TVIF_TEXT|TVIF_HANDLE;
+ tvi.pszText = (LPSTR)&buf;
+ tvi.cchTextMax = 254;
+ TreeView_GetItemA(hTree,&tvi);
+ if (mir_bool_strcmpi(Caption,tvi.pszText))
+ return tmp;
+ tmp = TreeView_GetNextSibling(hTree,tmp);
+ }
+ return tmp;
+}
+
+int TreeAddObject(HWND hwndDlg, int ID, OPT_OBJECT_DATA * data)
+{
+ HTREEITEM rootItem = NULL;
+ HTREEITEM cItem = NULL;
+ char * path;
+ char * ptr;
+ char * ptrE;
+ char buf[255];
+ BOOL ext = FALSE;
+ path = data->szPath?mir_strdup(data->szPath):(data->szName[1] == '$')?mir_strdup((data->szName)+2):NULL;
+ if ( !path) {
+ mir_snprintf(buf,SIZEOF(buf),"$(other)/%s",(data->szName)+1);
+ path = mir_strdup(buf);
+ }
+
+ ptr = path;
+ ptrE = path;
+ do
+ {
+
+ while (*ptrE != '/' && *ptrE != '\0') ptrE++;
+ if (*ptrE == '/')
+ {
+ *ptrE = '\0';
+ ptrE++;
+ // find item if not - create;
+ {
+ cItem = FindChild(GetDlgItem(hwndDlg,ID),rootItem,ptr);
+ if ( !cItem) // not found - create node
+ {
+ TVINSERTSTRUCTA tvis;
+ tvis.hParent = rootItem;
+ tvis.hInsertAfter = TVI_SORT;
+ tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_PARAM;
+ tvis.item.pszText = ptr;
+ tvis.item.lParam = (LPARAM)NULL;
+ cItem = TreeView_InsertItemA(GetDlgItem(hwndDlg,ID),&tvis);
+
+ }
+ rootItem = cItem;
+ }
+ ptr = ptrE;
+ }
+ else ext = TRUE;
+ }while (!ext);
+
+ //Insert item node
+ {
+ TVINSERTSTRUCTA tvis;
+ tvis.hParent = rootItem;
+ tvis.hInsertAfter = TVI_SORT;
+ tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_PARAM;
+ tvis.item.pszText = ptr;
+ tvis.item.lParam = (LPARAM)data;
+ TreeView_InsertItemA(GetDlgItem(hwndDlg,ID),&tvis);
+ }
+ mir_free(path);
+ return 0;
+}
+
+int enumDB_SkinObjectsForEditorProc(const char *szSetting,LPARAM lParam)
+{
+ if (wildcmp((char *)szSetting,gl_Mask,0) || wildcmp((char *)szSetting,"$*",0))
+ {
+ char * value;
+ char *desc;
+ char *descKey;
+ descKey = mir_strdup(szSetting);
+ descKey[0] = '%';
+ value = db_get_sa(NULL,SKIN,szSetting);
+ desc = db_get_sa(NULL,SKIN,descKey);
+ if (wildcmp(value,"?lyph*",0))
+ {
+ OPT_OBJECT_DATA * a = (OPT_OBJECT_DATA*)mir_alloc(sizeof(OPT_OBJECT_DATA));
+ a->szPath = desc;
+ a->szName = mir_strdup(szSetting);
+ a->szValue = value;
+ a->szTempValue = NULL;
+ TreeAddObject(gl_Dlg,gl_controlID,a);
+ }
+ else {
+ mir_free(value);
+ mir_free(desc);
+ }
+ mir_free(descKey);
+ }
+ return 0;
+}
+
+int FillObjectTree(HWND hwndDlg, int ObjectTreeID, char * wildmask)
+{
+ DBCONTACTENUMSETTINGS dbces;
+ gl_Dlg = hwndDlg;
+ gl_controlID = ObjectTreeID;
+ gl_Mask = wildmask;
+ dbces.pfnEnumProc = enumDB_SkinObjectsForEditorProc;
+ dbces.szModule = SKIN;
+ dbces.ofsSettings = 0;
+ CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces);
+ return 0;
+}
+TCHAR *TYPES[] = {_T("- Empty - (do not draw this object)"),_T("Solid fill object"),_T("Image (draw image)"),_T("Fragment (draw portion of image)")};
+TCHAR *FITMODES[] = {_T("Stretch Both directions"),_T("Stretch Vertical, Tile Horizontal"),_T("Tile Vertical, Stretch Horizontal"),_T("Tile Both directions")};
+
+void SetAppropriateGroups(HWND hwndDlg, int Type)
+//str contains default values
+{
+ switch (Type)
+ {
+ case -1:
+ {
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_1),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_COLOUR),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_ALPHA),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_2),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_3),FALSE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_S_SIZE),FALSE);
+ }
+ break;
+ case 0:
+ {
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_1),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_COLOUR),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_ALPHA),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_2),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_3),FALSE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_S_SIZE),FALSE);
+ }
+ break;
+ case 1:
+ {
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_1),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_COLOUR),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_ALPHA),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_2),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_3),FALSE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_S_SIZE),FALSE);
+ //Set Color and alpha
+ }
+ break;
+ case 2:
+ {
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_1),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_COLOUR),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_ALPHA),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_2),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_3),FALSE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_S_SIZE),TRUE);
+ //Set alpha, image, margins etc.
+ }
+ break;
+ case 3:
+ {
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_1),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_COLOUR),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_ALPHA),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_2),TRUE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_3),TRUE);
+ ShowWindow(GetDlgItem(hwndDlg,IDC_S_SIZE),TRUE);
+ //Set alpha, image, margins etc.
+ }
+ break;
+ }
+}
+
+void SetControls(HWND hwndDlg, char * str)
+{
+ char buf[250];
+ int Type=0;
+ if ( !str)
+ {
+ SetAppropriateGroups(hwndDlg,-1);
+ return;
+ }
+ GetParamN(str,buf,SIZEOF(buf),1,',',TRUE);
+ if (mir_bool_strcmpi(buf,"Solid")) Type=1;
+ else if (mir_bool_strcmpi(buf,"Image")) Type=2;
+ else if (mir_bool_strcmpi(buf,"Fragment")) Type=3;
+ SendDlgItemMessage(hwndDlg,IDC_TYPE,CB_SETCURSEL,(WPARAM)Type,(LPARAM)0);
+ SetAppropriateGroups(hwndDlg,Type);
+ switch (Type)
+ {
+ case 1:
+ {
+ int r,g,b,a;
+ r = g = b = 200;
+ a = 255;
+ r = atoi(GetParamN(str,buf,SIZEOF(buf),2,',',TRUE));
+ g = atoi(GetParamN(str,buf,SIZEOF(buf),3,',',TRUE));
+ b = atoi(GetParamN(str,buf,SIZEOF(buf),4,',',TRUE));
+ a = atoi(GetParamN(str,buf,SIZEOF(buf),5,',',TRUE));
+ SendDlgItemMessage(hwndDlg,IDC_COLOR,CPM_SETCOLOUR,(WPARAM)0,(LPARAM)RGB(r,g,b));
+ SendDlgItemMessage(hwndDlg,IDC_COLOR,CPM_SETDEFAULTCOLOUR,(WPARAM)0,(LPARAM)RGB(r,g,b));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_SETPOS,0,MAKELONG(a,0));
+ }
+ break;
+ case 2:
+ {
+ int a;
+ int l,t,r,b;
+ int fitmode = 0;
+ l = t = r = b = 0;
+ a = 255;
+
+ l = atoi(GetParamN(str,buf,SIZEOF(buf),4,',',TRUE));
+ t = atoi(GetParamN(str,buf,SIZEOF(buf),5,',',TRUE));
+ r = atoi(GetParamN(str,buf,SIZEOF(buf),6,',',TRUE));
+ b = atoi(GetParamN(str,buf,SIZEOF(buf),7,',',TRUE));
+ a = atoi(GetParamN(str,buf,SIZEOF(buf),8,',',TRUE));
+
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_SETPOS,0,MAKELONG(a,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_LEFT,UDM_SETPOS,0,MAKELONG(l,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_TOP,UDM_SETPOS,0,MAKELONG(t,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_RIGHT,UDM_SETPOS,0,MAKELONG(r,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_BOTTOM,UDM_SETPOS,0,MAKELONG(b,0));
+
+ GetParamN(str,buf,SIZEOF(buf),2,',',TRUE);
+ SendDlgItemMessageA(hwndDlg,IDC_FILE,WM_SETTEXT,0,(LPARAM)buf);
+
+ GetParamN(str,buf,SIZEOF(buf),3,',',TRUE);
+ if (mir_bool_strcmpi(buf,"TileBoth")) fitmode = FM_TILE_BOTH;
+ else if (mir_bool_strcmpi(buf,"TileVert")) fitmode = FM_TILE_VERT;
+ else if (mir_bool_strcmpi(buf,"TileHorz")) fitmode = FM_TILE_HORZ;
+ else fitmode = 0;
+ SendDlgItemMessage(hwndDlg,IDC_FIT,CB_SETCURSEL,(WPARAM)fitmode,(LPARAM)0);
+ }
+
+ break;
+ case 3:
+ {
+ int a;
+ int l,t,r,b;
+ int x,y,w,h;
+ int fitmode = 0;
+ l = t = r = b = 0;
+ x = y = w = h = 0;
+ a = 255;
+
+ x = atoi(GetParamN(str,buf,SIZEOF(buf),3,',',TRUE));
+ y = atoi(GetParamN(str,buf,SIZEOF(buf),4,',',TRUE));
+ w = atoi(GetParamN(str,buf,SIZEOF(buf),5,',',TRUE));
+ h = atoi(GetParamN(str,buf,SIZEOF(buf),6,',',TRUE));
+
+ l = atoi(GetParamN(str,buf,SIZEOF(buf),8,',',TRUE));
+ t = atoi(GetParamN(str,buf,SIZEOF(buf),9,',',TRUE));
+ r = atoi(GetParamN(str,buf,SIZEOF(buf),10,',',TRUE));
+ b = atoi(GetParamN(str,buf,SIZEOF(buf),11,',',TRUE));
+ a = atoi(GetParamN(str,buf,SIZEOF(buf),12,',',TRUE));
+
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_SETPOS,0,MAKELONG(a,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_LEFT,UDM_SETPOS,0,MAKELONG(l,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_TOP,UDM_SETPOS,0,MAKELONG(t,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_RIGHT,UDM_SETPOS,0,MAKELONG(r,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_BOTTOM,UDM_SETPOS,0,MAKELONG(b,0));
+
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_POSLEFT,UDM_SETPOS,0,MAKELONG(x,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_POSTOP,UDM_SETPOS,0,MAKELONG(y,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_WIDTH,UDM_SETPOS,0,MAKELONG(w,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_HEIGHT,UDM_SETPOS,0,MAKELONG(h,0));
+
+ GetParamN(str,buf,SIZEOF(buf),2,',',TRUE);
+ SendDlgItemMessageA(hwndDlg,IDC_FILE,WM_SETTEXT,0,(LPARAM)buf);
+
+ GetParamN(str,buf,SIZEOF(buf),7,',',TRUE);
+ if (mir_bool_strcmpi(buf,"TileBoth")) fitmode = FM_TILE_BOTH;
+ else if (mir_bool_strcmpi(buf,"TileVert")) fitmode = FM_TILE_VERT;
+ else if (mir_bool_strcmpi(buf,"TileHorz")) fitmode = FM_TILE_HORZ;
+ else fitmode = 0;
+ SendDlgItemMessage(hwndDlg,IDC_FIT,CB_SETCURSEL,(WPARAM)fitmode,(LPARAM)0);
+ }
+
+ break;
+ }
+}
+
+
+
+int GetShortFileName(char * FullFile)
+{
+ char buf[MAX_PATH] = {0};
+ char * f = strrchr(FullFile,'\\');
+ char * file = f?mir_strdup(f+1):0;
+ if ( !file) return 0;
+ ske_GetFullFilename(buf,file,0,TRUE);
+ if (mir_bool_strcmpi(buf,FullFile))
+ {
+ _snprintf(FullFile,MAX_PATH,"%s",file);
+ mir_free(file);
+ return 1; //skin folder relative
+ }
+
+ CallService(MS_UTILS_PATHTORELATIVE,(WPARAM)FullFile,(LPARAM)buf);
+ if (buf[0] != '\\' && buf[1] != ':')
+ _snprintf(FullFile,MAX_PATH,"\\%s",buf);
+ else
+ _snprintf(FullFile,MAX_PATH,"%s",buf);
+
+ mir_free(file);
+ return 2; //mirand folder relative
+}
+
+char * MadeString(HWND hwndDlg)
+{
+ char buf[MAX_PATH*2] = {0};
+ int i = SendDlgItemMessage(hwndDlg,IDC_TYPE,CB_GETCURSEL,(WPARAM)0,(LPARAM)0);
+ switch (i)
+ {
+ case 0:
+ mir_snprintf(buf,SIZEOF(buf),"Glyph,Skip");
+ break;
+ case 1:
+ {
+ BYTE a;
+ DWORD col;
+ a = (BYTE)SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_GETPOS,0,0);
+ col = (DWORD)SendDlgItemMessage(hwndDlg,IDC_COLOR,CPM_GETCOLOUR,(WPARAM)0,(LPARAM)0);
+ mir_snprintf(buf,SIZEOF(buf),"Glyph,Solid,%d,%d,%d,%d",GetRValue(col),GetGValue(col),GetBValue(col),a);
+ }
+ break;
+ case 2:
+ {
+ BYTE a;
+ WORD l,t,b,r;
+ char buf_name[MAX_PATH] = {0};
+ int i=0;
+ a = (BYTE)SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_GETPOS,0,0);
+ l = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_LEFT,UDM_GETPOS,0,0);
+ t = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_TOP,UDM_GETPOS,0,0);
+ r = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_RIGHT,UDM_GETPOS,0,0);
+ b = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_BOTTOM,UDM_GETPOS,0,0);
+ SendDlgItemMessageA(hwndDlg,IDC_FILE,WM_GETTEXT,(WPARAM)MAX_PATH,(LPARAM)buf_name);
+ i = SendDlgItemMessage(hwndDlg,IDC_FIT,CB_GETCURSEL,0,0);
+ mir_snprintf(buf,SIZEOF(buf),"Glyph,Image,%s,%s,%d,%d,%d,%d,%d",buf_name,
+ //fitmode
+ (i == FM_TILE_BOTH)?"TileBoth":
+ (i == FM_TILE_VERT)?"TileVert":
+ (i == FM_TILE_HORZ)?"TileHorz":"StretchBoth",
+ l,t,r,b,a);
+ }
+ break;
+ case 3:
+ {
+ BYTE a;
+ WORD l,t,b,r;
+ WORD x,y,w,h;
+ char buf_name[MAX_PATH] = {0};
+ int i=0;
+ a = (BYTE)SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_GETPOS,0,0);
+ l = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_LEFT,UDM_GETPOS,0,0);
+ t = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_TOP,UDM_GETPOS,0,0);
+ r = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_RIGHT,UDM_GETPOS,0,0);
+ b = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_BOTTOM,UDM_GETPOS,0,0);
+
+ x = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_POSLEFT,UDM_GETPOS,0,0);
+ y = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_POSTOP,UDM_GETPOS,0,0);
+
+ w = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_WIDTH,UDM_GETPOS,0,0);
+ h = (WORD)SendDlgItemMessage(hwndDlg,IDC_SPIN_HEIGHT,UDM_GETPOS,0,0);
+
+ SendDlgItemMessageA(hwndDlg,IDC_FILE,WM_GETTEXT,(WPARAM)MAX_PATH,(LPARAM)buf_name);
+ i = SendDlgItemMessage(hwndDlg,IDC_FIT,CB_GETCURSEL,0,0);
+ mir_snprintf(buf,SIZEOF(buf),"Glyph,Fragment,%s,%d,%d,%d,%d,%s,%d,%d,%d,%d,%d",buf_name,x,y,w,h,
+ //fitmode
+ (i == FM_TILE_BOTH)?"TileBoth":
+ (i == FM_TILE_VERT)?"TileVert":
+ (i == FM_TILE_HORZ)?"TileHorz":"StretchBoth",
+ l,t,r,b,a);
+ }
+ break;
+ }
+ if (buf[0] != '\0') return mir_strdup(buf);
+ return 0;
+}
+void UpdateInfo(HWND hwndDlg)
+{
+ char *b = MadeString(hwndDlg);
+ if ( !b)
+ {
+ SendDlgItemMessageA(hwndDlg,IDC_EDIT1,WM_SETTEXT,0,(LPARAM)"");
+ return;
+ }
+ SendDlgItemMessageA(hwndDlg,IDC_EDIT1,WM_SETTEXT,0,(LPARAM)b);
+ {
+ OPT_OBJECT_DATA *sd = NULL;
+ HTREEITEM hti = TreeView_GetSelection(GetDlgItem(hwndDlg,IDC_OBJECT_TREE));
+ if (hti)
+ {
+ TVITEMA tvi = {0};
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ TreeView_GetItem(GetDlgItem(hwndDlg,IDC_OBJECT_TREE),&tvi);
+ sd = (OPT_OBJECT_DATA*)(tvi.lParam);
+ if (sd)
+ {
+ mir_free(sd->szValue);
+ sd->szValue = mir_strdup(b);
+ }
+ }
+ }
+ mir_free(b);
+ glSkinWasModified = 1;
+}
+
+void StoreTreeNode(HWND hTree, HTREEITEM node, char * section)
+{
+ HTREEITEM tmp;
+ tmp = node;
+ while (tmp)
+ {
+ HTREEITEM tmp2 = NULL;
+ TVITEMA tvi;
+ char buf[255];
+ tvi.hItem = tmp;
+ tvi.mask = TVIF_TEXT|TVIF_HANDLE;
+ tvi.pszText = (LPSTR)&buf;
+ tvi.cchTextMax = 254;
+ TreeView_GetItemA(hTree,&tvi);
+ if (tvi.lParam)
+ {
+ OPT_OBJECT_DATA * dat = (OPT_OBJECT_DATA*)(tvi.lParam);
+ if (dat->szName && dat->szValue)
+ db_set_s(NULL,section,dat->szName,dat->szValue);
+ }
+ tmp2 = TreeView_GetChild(hTree,tmp);
+ if (tmp2) StoreTreeNode(hTree,tmp2,section);
+ tmp = TreeView_GetNextSibling(hTree,tmp);
+ }
+ return;
+}
+
+void StoreTreeToDB(HWND hTree, char * section)
+{
+ HTREEITEM tmp = NULL;
+ tmp = TreeView_GetRoot(hTree);
+ StoreTreeNode(hTree,tmp,section);
+ db_set_b(NULL,section,"Modified",1);
+ glSkinWasModified = 2;
+}
+static BOOL fileChanged = FALSE;
+static char * object_clipboard = NULL;
+int GetFileSizes(HWND hwndDlg)
+{
+ char buf[MAX_PATH];
+ SIZE sz = {0};
+ SendDlgItemMessageA(hwndDlg,IDC_FILE,WM_GETTEXT,(WPARAM)MAX_PATH,(LPARAM)buf);
+ ske_GetFullFilename(buf,buf,0,TRUE);
+ {
+ HBITMAP hbmp = ske_LoadGlyphImage(buf);
+ if (hbmp)
+ {
+ BITMAP bm = {0};
+ GetObject(hbmp,sizeof(BITMAP),&bm);
+ sz.cx = bm.bmWidth;
+ sz.cy = bm.bmHeight;
+ ske_UnloadGlyphImage(hbmp);
+ }
+ }
+ _snprintf(buf, MAX_PATH, "%s %d x %d %s",Translate("Image size is"),sz.cx, sz.cy, Translate("pixels"));
+ SendDlgItemMessageA(hwndDlg,IDC_S_SIZE,WM_SETTEXT,0,(LPARAM)buf);
+ return 0;
+}
+
+INT_PTR CALLBACK DlgSkinEditorOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_WINDOWPOSCHANGED:
+ {
+ WINDOWPOS * wp = (WINDOWPOS *)lParam;
+ if (lParam && wp->flags&SWP_SHOWWINDOW)
+ {
+ if (glOtherSkinWasLoaded)
+ {
+ TreeView_DeleteAllItems(GetDlgItem(hwndDlg,IDC_OBJECT_TREE));
+ FillObjectTree(hwndDlg,IDC_OBJECT_TREE,"$$*");
+ glSkinWasModified = 0;
+ glOtherSkinWasLoaded = FALSE;
+ }
+ }
+ break;
+ }
+
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ FillObjectTree(hwndDlg,IDC_OBJECT_TREE,"$$*");
+ { //Fill types combo
+ int i=0;
+ for (i=0; i < SIZEOF(TYPES); i++)
+ SendDlgItemMessage(hwndDlg,IDC_TYPE,CB_ADDSTRING,0,(LPARAM)TranslateTS(TYPES[i]));
+ }
+ { //Fill fit combo
+ int i=0;
+ for (i=0; i < SIZEOF(FITMODES); i++)
+ SendDlgItemMessage(hwndDlg,IDC_FIT,CB_ADDSTRING,0,(LPARAM)TranslateTS(FITMODES[i]));
+ }
+ //SPIN Ranges
+ {
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_SETRANGE,0,MAKELONG(255,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_ALPHA,UDM_SETPOS,0,MAKELONG(255,0));
+
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_TOP,UDM_SETRANGE,0,MAKELONG(900,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_LEFT,UDM_SETRANGE,0,MAKELONG(900,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_BOTTOM,UDM_SETRANGE,0,MAKELONG(900,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_RIGHT,UDM_SETRANGE,0,MAKELONG(900,0));
+
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_POSLEFT,UDM_SETRANGE,0,MAKELONG(1000,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_POSTOP,UDM_SETRANGE,0,MAKELONG(1000,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_WIDTH,UDM_SETRANGE,0,MAKELONG(1000,0));
+ SendDlgItemMessage(hwndDlg,IDC_SPIN_HEIGHT,UDM_SETRANGE,0,MAKELONG(1000,0));
+ }
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_1),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_COLOUR),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_ST_ALPHA),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_2),FALSE);
+ EnableGroup(hwndDlg,GetDlgItem(hwndDlg,IDC_GROUP_3),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PASTE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_COPY),FALSE);
+ glSkinWasModified = 0;
+ glOtherSkinWasLoaded = FALSE;
+ break;
+
+ case WM_COMMAND:
+ {
+ if (LOWORD(wParam) == IDC_TYPE)
+ {
+ if (HIWORD(wParam) == CBN_SELCHANGE)
+ {
+ int i = SendDlgItemMessage(hwndDlg,IDC_TYPE,CB_GETCURSEL,(WPARAM)0,(LPARAM)0);
+ //if (IsWindowEnabled(GetDlgItem(hwndDlg,IDC_TYPE)))
+ SetAppropriateGroups(hwndDlg,i);
+ if (GetFocus() == GetDlgItem(hwndDlg,IDC_TYPE))
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ UpdateInfo(hwndDlg);
+ break;
+ }
+ }
+ else if (LOWORD(wParam) == IDC_COPY)
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ mir_free_and_nil(object_clipboard);
+
+ OPT_OBJECT_DATA *sd = NULL;
+ HTREEITEM hti = TreeView_GetSelection(GetDlgItem(hwndDlg,IDC_OBJECT_TREE));
+ if (hti != 0)
+ {
+ TVITEM tvi = {0};
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ TreeView_GetItem(GetDlgItem(hwndDlg,IDC_OBJECT_TREE),&tvi);
+ sd = (OPT_OBJECT_DATA*)(tvi.lParam);
+ }
+ if (sd && sd->szValue)
+ object_clipboard = mir_strdup(sd->szValue);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PASTE),object_clipboard != NULL);
+ return 0;
+ }
+ }
+ else if (LOWORD(wParam) == IDC_PASTE)
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ if (object_clipboard)
+ SetControls(hwndDlg, object_clipboard);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ UpdateInfo(hwndDlg);
+ return 0;
+ }
+ }
+ else if (LOWORD(wParam) == IDC_COLOR)
+ {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ UpdateInfo(hwndDlg);
+ }
+ else if (LOWORD(wParam) == IDC_BROWSE)
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ {
+ char str[MAX_PATH] = {0};
+ OPENFILENAMEA ofn = {0};
+ char filter[512] = {0};
+ int res = 0;
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = hwndDlg;
+ ofn.hInstance = NULL;
+ ofn.lpstrFilter = "Images (*.png,*.jpg,*.bmp,*.gif,*.tga)\0*.png;*.jpg;*.jpeg;*.bmp;*.gif;*.tga\0All files (*.*)\0*.*\0\0";
+ ofn.Flags = (OFN_FILEMUSTEXIST | OFN_HIDEREADONLY);
+ SendDlgItemMessageA(hwndDlg,IDC_FILE,WM_GETTEXT,(WPARAM)SIZEOF(str),(LPARAM)str);
+ if (str[0] == '\0' || strchr(str,'%'))
+ {
+ ofn.Flags |= OFN_NOVALIDATE;
+ str[0] = '\0';
+ }
+ else
+ {
+ ske_GetFullFilename(str,str,(char*)0,TRUE);
+ }
+ ofn.lpstrFile = str;
+
+ ofn.nMaxFile = SIZEOF(str);
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.lpstrDefExt = "*.*";
+ res = GetOpenFileNameA(&ofn);
+ if (res) {
+ GetShortFileName(ofn.lpstrFile);
+ SendDlgItemMessageA(hwndDlg,IDC_FILE,WM_SETTEXT,(WPARAM)0,(LPARAM)ofn.lpstrFile);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ UpdateInfo(hwndDlg);
+ }
+ }
+ }
+ }
+ else if (LOWORD(wParam) == IDC_FILE)
+ {
+ if (HIWORD(wParam) == EN_CHANGE)
+ {
+ fileChanged = TRUE;
+ if ((HWND)lParam != GetFocus())
+ {
+ GetFileSizes(hwndDlg);
+ fileChanged = FALSE;
+ }
+ }
+ else if (HIWORD(wParam) == EN_KILLFOCUS)
+ {
+ if (fileChanged)
+ {
+ GetFileSizes(hwndDlg);
+ fileChanged = FALSE;
+ }
+ }
+ }
+ else if ((
+ (LOWORD(wParam) == IDC_E_TOP
+ || LOWORD(wParam) == IDC_E_BOTTOM
+ || LOWORD(wParam) == IDC_E_LEFT
+ || LOWORD(wParam) == IDC_E_RIGHT
+ || LOWORD(wParam) == IDC_E_X
+ || LOWORD(wParam) == IDC_E_Y
+ || LOWORD(wParam) == IDC_E_W
+ || LOWORD(wParam) == IDC_E_H
+ || LOWORD(wParam) == IDC_EDIT_ALPHA
+ )
+ && HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()))
+ {
+ return 0;
+ }
+ else if (LOWORD(wParam) != IDC_EDIT1)
+ {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ UpdateInfo(hwndDlg);
+ }
+ //check (LOWORD(wParam))
+ //SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case IDC_OBJECT_TREE:
+ {
+ //Save existed object
+ //Change to new object
+ NMTREEVIEWA * nmtv = (NMTREEVIEWA *) lParam;
+ if ( !nmtv) return 0;
+ if (nmtv->hdr.code == TVN_SELCHANGEDA || nmtv->hdr.code == TVN_SELCHANGEDW)
+ {
+ if (nmtv->itemOld.lParam)
+ {
+ OPT_OBJECT_DATA * dataOld = (OPT_OBJECT_DATA*)nmtv->itemOld.lParam;
+ if (dataOld->szValue) {
+ mir_free(dataOld->szValue);
+ dataOld->szValue = MadeString(hwndDlg);
+ }
+ }
+ if (nmtv->itemNew.lParam)
+ {
+ OPT_OBJECT_DATA * data = (OPT_OBJECT_DATA*)nmtv->itemNew.lParam;
+ char buf[255];
+
+ mir_snprintf(buf,SIZEOF(buf),"%s = %s",data->szName, data->szValue);
+ SendDlgItemMessageA(hwndDlg,IDC_EDIT1,WM_SETTEXT,0,(LPARAM)buf);
+ SetControls(hwndDlg,data->szValue);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_COPY),TRUE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PASTE),object_clipboard != NULL);
+ }
+ else
+ {
+ SendDlgItemMessageA(hwndDlg,IDC_EDIT1,WM_SETTEXT,0,(LPARAM)"");
+ SetControls(hwndDlg,NULL);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_COPY),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_PASTE),FALSE);
+ }
+
+ }
+ else if (nmtv->hdr.code == TVN_DELETEITEMA)
+ {
+ OPT_OBJECT_DATA * dataOld = (OPT_OBJECT_DATA*)nmtv->itemOld.lParam;
+ if (dataOld) {
+ mir_free_and_nil(dataOld->szName);
+ mir_free_and_nil(dataOld->szPath);
+ mir_free_and_nil(dataOld->szTempValue);
+ mir_free_and_nil(dataOld->szValue);
+ }
+ }
+ return 0;
+ }
+
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ if ( !glOtherSkinWasLoaded) //store only if skin is same
+ {
+ StoreTreeToDB(GetDlgItem(hwndDlg,IDC_OBJECT_TREE),SKIN);
+ //ReloadSkin
+ ske_LoadSkinFromDB();
+ pcli->pfnClcBroadcast( INTM_RELOADOPTIONS,0,0);
+ Sync(CLUIFrames_OnClistResize_mod,0,0);
+ ske_RedrawCompleteWindow();
+ Sync(CLUIFrames_OnClistResize_mod, (WPARAM)0, (LPARAM)0);
+ {
+ HWND hwnd = pcli->hwndContactList;
+ RECT rc = {0};
+ GetWindowRect(hwnd, &rc);
+ Sync(CLUIFrames_OnMoving,hwnd,&rc);
+ }
+ return TRUE;
+ }
+ else
+ return TRUE;
+ }
+ break;
+ }
+
+ case WM_DESTROY:
+ mir_free(object_clipboard);
+ break;
+
+ }
+ return FALSE;
+}
+
+int EnableGroup(HWND hwndDlg, HWND first, BOOL bEnable)
+{
+ HWND hwnd = first;
+ BOOL exit = FALSE;
+ if ( !hwnd) return 0;
+ do
+ {
+ EnableWindow(hwnd,bEnable);
+ hwnd = GetWindow(hwnd,GW_HWNDNEXT);
+ if ( !hwnd || GetWindowLongPtr(hwnd,GWL_STYLE)&WS_GROUP) exit = TRUE;
+ }
+ while (!exit);
+ return 0;
+}
+
+int ShowGroup(HWND hwndDlg, HWND first, BOOL bEnable)
+{
+ HWND hwnd = first;
+ BOOL exit = FALSE;
+ if ( !hwnd) return 0;
+ do
+ {
+ ShowWindow(hwnd,bEnable?SW_SHOW:SW_HIDE);
+ hwnd = GetWindow(hwnd,GW_HWNDNEXT);
+ if ( !hwnd || GetWindowLongPtr(hwnd,GWL_STYLE)&WS_GROUP) exit = TRUE;
+ }
+ while (!exit);
+ return 0;
+}
+
diff --git a/plugins/Clist_modern/src/modern_skinengine.cpp b/plugins/Clist_modern/src/modern_skinengine.cpp
new file mode 100644
index 0000000000..11c8391c4d
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_skinengine.cpp
@@ -0,0 +1,4650 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+//Include
+#include "hdr/modern_commonheaders.h"
+#include <m_png.h>
+#include "m_api/m_skin_eng.h"
+#include "hdr/modern_skinselector.h"
+#include "hdr/modern_cluiframes.h"
+
+#define _EFFECTENUM_FULL_H
+#include "hdr/modern_effectenum.h"
+#undef _EFFECTENUM_FULL_H
+
+#include "hdr/modern_skinengine.h"
+#include "hdr/modern_commonprototypes.h"
+#include <shlwapi.h>
+#include "hdr/modern_sync.h"
+//Implementation
+
+/* Global variables */
+
+SKINOBJECTSLIST g_SkinObjectList = {0};
+CURRWNDIMAGEDATA * g_pCachedWindow = NULL;
+
+BOOL (WINAPI *g_proc_UpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD);
+
+BOOL g_flag_bPostWasCanceled = FALSE;
+BOOL g_flag_bFullRepaint = FALSE;
+BOOL g_mutex_bLockUpdating = FALSE;
+
+SortedList * gl_plGlyphTexts = NULL;
+SortedList * gl_plSkinFonts = NULL;
+
+/* Private module variables */
+
+static HANDLE hSkinLoadedEvent;
+
+static GLYPHIMAGE * pLoadedImages = NULL;
+static DWORD dwLoadedImagesCount = 0;
+static DWORD dwLoadedImagesAlocated = 0;
+
+static BOOL flag_bUpdateQueued = FALSE;
+static BOOL flag_bJustDrawNonFramedObjects = FALSE;
+static BOOL mutex_bLockUpdate = FALSE;
+
+static SortedList * pEffectStack = NULL;
+static SKINOBJECTSLIST * pCurrentSkin = NULL;
+static char ** pszSettingName = NULL;
+static int nArrayLen = 0;
+static char * iniCurrentSection = NULL;
+static char * szFileName = NULL;
+
+static BYTE pbGammaWeight[256] = {0};
+static BYTE pbGammaWeightAdv[256] = {0};
+static BOOL bGammaWeightFilled = FALSE;
+
+static CRITICAL_SECTION cs_SkinChanging = {0};
+
+
+/* Private module procedures */
+static BOOL ske_GetMaskBit(BYTE *line, int x);
+static INT_PTR ske_Service_AlphaTextOut(WPARAM wParam,LPARAM lParam);
+static INT_PTR ske_Service_DrawIconEx(WPARAM wParam,LPARAM lParam);
+
+static int ske_AlphaTextOut (HDC hDC, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format, DWORD ARGBcolor);
+static void ske_AddParseTextGlyphObject(char * szGlyphTextID,char * szDefineString,SKINOBJECTSLIST *Skin);
+static void ske_AddParseSkinFont(char * szFontID,char * szDefineString,SKINOBJECTSLIST *Skin);
+static int ske_DeleteAllSettingInSection(char * SectionName);
+static int ske_GetSkinFromDB(char * szSection, SKINOBJECTSLIST * Skin);
+static LPSKINOBJECTDESCRIPTOR ske_FindObject(const char * szName, BYTE objType,SKINOBJECTSLIST* Skin);
+static HBITMAP ske_LoadGlyphImageByDecoders(char * szFileName);
+static int ske_LoadSkinFromResource(BOOL bOnlyObjects);
+static void ske_PreMultiplyChanells(HBITMAP hbmp,BYTE Mult);
+static int ske_ValidateSingleFrameImage(FRAMEWND * Frame, BOOL SkipBkgBlitting);
+static INT_PTR ske_Service_UpdateFrameImage(WPARAM wParam, LPARAM lParam);
+static INT_PTR ske_Service_InvalidateFrameImage(WPARAM wParam, LPARAM lParam);
+static INT_PTR ske_Service_DrawTextWithEffect( WPARAM wParam, LPARAM lParam );
+
+//Decoders
+static HMODULE hImageDecoderModule;
+
+typedef DWORD (__stdcall *pfnImgNewDecoder)(void ** ppDecoder);
+static pfnImgNewDecoder ImgNewDecoder;
+
+typedef DWORD (__stdcall *pfnImgDeleteDecoder)(void * pDecoder);
+static pfnImgDeleteDecoder ImgDeleteDecoder;
+
+typedef DWORD (__stdcall *pfnImgNewDIBFromFile)(LPVOID /*in*/pDecoder, LPCSTR /*in*/pFileName, LPVOID /*out*/*pImg);
+static pfnImgNewDIBFromFile ImgNewDIBFromFile;
+
+typedef DWORD (__stdcall *pfnImgDeleteDIBSection)(LPVOID /*in*/pImg);
+static pfnImgDeleteDIBSection ImgDeleteDIBSection;
+
+typedef DWORD (__stdcall *pfnImgGetHandle)(LPVOID /*in*/pImg, HBITMAP /*out*/*pBitmap, LPVOID /*out*/*ppDIBBits);
+static pfnImgGetHandle ImgGetHandle;
+
+static MODERNEFFECT meCurrentEffect = {-1,{0},0,0};
+
+
+//////////////////////////////////////////////////////////////////////////
+// Ini file parser
+//////////////////////////////////////////////////////////////////////////
+IniParser::IniParser( TCHAR * tcsFileName, BYTE flags ) : _Flags( flags )
+{
+ _DoInit();
+ if ( !tcsFileName ) return;
+
+ if ( tcsFileName[0] == _T('%'))
+ {
+ //TODO: Add parser of resource filename here
+ _LoadResourceIni( g_hInst, MAKEINTRESOURCEA(IDR_MSF_DEFAULT_SKIN), "MSF");
+ return;
+ }
+
+ _hFile = _tfopen( tcsFileName, _T("r"));
+
+ if ( _hFile != NULL )
+ {
+ _eType = IT_FILE;
+ _isValid = true;
+ }
+}
+
+IniParser::IniParser( HINSTANCE hInst, const char * resourceName, const char * resourceType, BYTE flags ) : _Flags( flags )
+{
+ _DoInit();
+ _LoadResourceIni( hInst, resourceName, resourceType );
+}
+
+IniParser::~IniParser()
+{
+ mir_free( _szSection );
+ if ( _hFile ) fclose( _hFile );
+ if ( _hGlobalRes ) {
+ UnlockResource( _hGlobalRes );
+ FreeResource(_hGlobalRes);
+ }
+
+ _szSection = NULL;
+ _hGlobalRes = NULL;
+ _hFile = NULL;
+ _isValid = false;
+ _eType = IT_UNKNOWN;
+}
+
+HRESULT IniParser::Parse( ParserCallback_t pLineCallBackProc, LPARAM SecCheck )
+{
+ if ( _isValid && pLineCallBackProc )
+ {
+ _pLineCallBackProc = pLineCallBackProc;
+ _SecCheck = SecCheck;
+ switch ( _eType )
+ {
+ case IT_FILE:
+ return _DoParseFile();
+ case IT_RESOURCE:
+ return _DoParseResource();
+ }
+ }
+ return E_FAIL;
+}
+
+
+HRESULT IniParser::WriteStrToDb( const char * szSection, const char * szName, const char * szValue, IniParser * This )
+{
+ if ( This->_SecCheck)
+ {
+ //TODO check security here
+ if ( wildcmp( szSection,"Skin_Description_Section",1 )) return S_OK;
+ }
+ if (( This->_Flags == IniParser::FLAG_ONLY_OBJECTS ) && !wildcmp( szSection, DEFAULTSKINSECTION,1 ))
+ return S_OK; // skip not objects
+
+
+// if ( strlen(szValue)>0 && szValue[strlen(szValue)-1] == '\n' )
+// szValue[strlen(szValue)-1] = '\0'; //kill linefeed at the end
+
+ switch(szValue[0])
+ {
+ case 'b':
+ {
+ BYTE P;
+ P = (BYTE)atoi(szValue+1);
+ db_set_b(NULL,szSection,szName,P);
+ }
+ break;
+ case 'w':
+ {
+ WORD P;
+ P = (WORD)atoi(szValue+1);
+ db_set_w(NULL,szSection,szName,P);
+ }
+ break;
+ case 'd':
+ {
+ DWORD P;
+ P = (DWORD)atoi(szValue+1);
+ db_set_dw(NULL,szSection,szName,P);
+ }
+ break;
+ case 's':
+ db_set_s(NULL,szSection,szName,szValue+1);
+ break;
+ case 'f':
+ if (szFileName)
+ {
+ char fn[MAX_PATH] = {0};
+ char bb[MAX_PATH*2] = {0};
+ int pp, i;
+ pp = -1;
+ CallService(MS_UTILS_PATHTORELATIVE, (WPARAM)szFileName, (LPARAM)fn);
+ {
+ for (i = strlen(fn); i >= 0; i--) if (fn[i] == '.') break;
+ if (i>0) fn[i] = '\0';
+ }
+ _snprintf(bb,SIZEOF(bb),"%s\\%s",fn,szValue+1);
+ db_set_s(NULL,szSection,szName,bb);
+ }
+ break;
+ }
+ return S_OK;
+}
+int IniParser::GetSkinFolder( IN const TCHAR * szFileName, OUT TCHAR * pszFolderName )
+{
+ TCHAR *pszPos;
+ TCHAR *szBuff;
+
+ szBuff = mir_tstrdup( szFileName );
+ pszPos = szBuff + _tcslen( szBuff );
+ while ( pszPos > szBuff && *pszPos != _T('.')) { pszPos--; }
+ *pszPos = _T('\0');
+ _tcscpy( pszFolderName, szBuff );
+
+ TCHAR custom_folder[MAX_PATH];
+ TCHAR cus[MAX_PATH];
+ TCHAR *b3;
+ _tcscpy( custom_folder, pszFolderName );
+ b3 = custom_folder + _tcslen( custom_folder );
+ while ( b3 > custom_folder && *b3 != _T('\\')) { b3--; }
+ *b3 = _T('\0');
+
+ GetPrivateProfileString(_T("Skin_Description_Section"),_T("SkinFolder"),_T(""),cus,SIZEOF(custom_folder),szFileName);
+ if ( cus && _tcslen(cus)>0)
+ _sntprintf(pszFolderName,MAX_PATH,_T("%s\\%s"),custom_folder,cus);
+
+ mir_free(szBuff);
+ CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)pszFolderName, (LPARAM)pszFolderName);
+ return 0;
+}
+
+void IniParser::_DoInit()
+{
+ _isValid = false;
+ _eType = IT_UNKNOWN;
+ _szSection = NULL;
+ _hFile = NULL;
+ _hGlobalRes = NULL;
+ _dwSizeOfRes = 0;
+ _pPosition = NULL;
+ _pLineCallBackProc = NULL;
+ _SecCheck = 0;
+
+}
+
+void IniParser::_LoadResourceIni( HINSTANCE hInst, const char * resourceName, const char * resourceType )
+{
+
+ if ( _eType != IT_UNKNOWN ) return;
+
+ HRSRC hRSrc = FindResourceA( hInst, resourceName, resourceType );
+ if ( !hRSrc ) return;
+
+ _hGlobalRes = LoadResource( hInst, hRSrc );
+ if ( !_hGlobalRes ) return;
+
+ _dwSizeOfRes = SizeofResource( hInst, hRSrc );
+ _pPosition = (char*) LockResource( _hGlobalRes );
+
+ _isValid = true;
+ _eType = IT_RESOURCE;
+
+}
+
+
+
+HRESULT IniParser::_DoParseFile()
+{
+ char szLine[MAX_LINE_LEN];
+ _nLine = 0;
+ while ( fgets( szLine, SIZEOF(szLine), _hFile ) != NULL )
+ {
+ size_t len = 0;
+ char * pLine = (char*)_RemoveTailings( szLine, len );
+ if ( len > 0 )
+ {
+ pLine[len] = '\0';
+ if ( !_DoParseLine( pLine )) return E_FAIL;
+ }
+ else
+ _nLine++;
+ };
+
+ return S_OK;
+}
+
+HRESULT IniParser::_DoParseResource()
+{
+ _nLine = 0;
+ char szLine[MAX_LINE_LEN];
+ char * pos = ( char* ) _pPosition;
+
+ while ( pos < _pPosition + _dwSizeOfRes )
+ {
+ int i=0;
+ while ( pos < _pPosition + _dwSizeOfRes && *pos != '\n' && *pos != '\0' && i < MAX_LINE_LEN - 1 )
+ {
+ if ((*pos) != '\r' )
+ szLine[ i++ ] = *pos;
+ pos++;
+ }
+ szLine[ i ] = '\0';
+ pos++;
+
+ size_t len = 0;
+ char * pLine = (char*) _RemoveTailings( szLine, len );
+ if ( len > 0 )
+ {
+ pLine[len] = '\0';
+ if ( !_DoParseLine( pLine )) return E_FAIL;
+ }
+ else
+ _nLine++;
+ }
+ return S_OK;
+}
+
+const char * IniParser::_RemoveTailings( const char * szLine, size_t& len )
+{
+ const char * pStart = szLine;
+ while( *pStart == ' ' || *pStart == '\t' ) pStart++; //skip spaces at begin
+ const char * pEnd = pStart + strlen( pStart );
+ while( pEnd > pStart && ( *pEnd == ' ' || *pEnd == '\t' || *pEnd == '\n' || *pEnd == '\r' )) pEnd--;
+
+ len = pEnd - pStart;
+ return pStart;
+}
+
+BOOL IniParser::_DoParseLine( char * szLine )
+{
+ _nLine++;
+ DWORD len = strlen( szLine );
+
+ if ( len == 0 ) return TRUE;
+
+ switch( szLine[0] )
+ {
+ case ';':
+ return TRUE; // start of comment is found
+ case '[':
+ {
+ //New section start here
+ mir_free( _szSection );
+ _szSection = NULL;
+
+ char *tbuf = szLine + 1; // skip [
+
+ char *ebuf = tbuf;
+
+ while ( *ebuf != ']' && *ebuf != '\0' ) ebuf++;
+ if ( *ebuf == '\0' )
+ return FALSE; // no close bracket
+
+ DWORD sectionLen = ebuf - tbuf;
+ _szSection = (char*) mir_alloc( sectionLen + 1 );
+ strncpy( _szSection, tbuf, sectionLen );
+ _szSection[sectionLen] = '\0';
+ }
+ return TRUE;
+
+ default:
+ if ( !_szSection )
+ return TRUE; //param found out of section
+
+ char *keyName = szLine;
+ char *keyValue = szLine;
+
+ DWORD eqPlace = 0;
+ DWORD len2 = strlen(keyName);
+
+ while ( eqPlace < len2 && keyName[ eqPlace ] != '=' )
+ eqPlace++; //find '='
+
+ if (eqPlace == 0 || eqPlace == len2)
+ return TRUE; // = not found or no key name //say false
+
+ keyName[eqPlace] = '\0';
+
+ keyValue = keyName + eqPlace + 1;
+
+ //remove tail spaces in Name
+ {
+ DWORD len3 = strlen(keyName);
+ int j = len3-1;
+ while (j>0 && (keyName[j] == ' ' || keyName[j] == '\t')) j--;
+ if (j >= 0) keyName[j+1] = '\0';
+ }
+ //remove start spaces in Value
+ {
+ DWORD len3 = strlen(keyValue);
+ DWORD j = 0;
+ while (j < len3 && (keyValue[j] == ' ' || keyValue[j] == '\t')) j++;
+ if (j < len3) keyValue += j;
+ }
+ //remove tail spaces in Value
+ {
+ DWORD len3 = strlen(keyValue);
+ int j = len3-1;
+ while (j>0 && (keyValue[j] == ' ' || keyValue[j] == '\t' || keyValue[j] == '\n')) j--;
+ if (j >= 0) keyValue[j+1] = '\0';
+ }
+ _pLineCallBackProc( _szSection, keyName, keyValue, this );
+ }
+ return TRUE;
+}
+//////////////////////////////////////////////////////////////////////////
+// End of IniParser
+//////////////////////////////////////////////////////////////////////////
+
+HRESULT SkinEngineLoadModule()
+{
+ ModernSkinButtonLoadModule();
+ InitializeCriticalSection(&cs_SkinChanging);
+ MainModernMaskList = (LISTMODERNMASK*)mir_calloc(sizeof(LISTMODERNMASK));
+ //init variables
+ g_SkinObjectList.dwObjLPAlocated = 0;
+ g_SkinObjectList.dwObjLPReserved = 0;
+ g_SkinObjectList.pObjects = NULL;
+ // Initialize GDI+
+ InitGdiPlus();
+ AniAva_InitModule();
+ //load decoder
+ hImageDecoderModule = NULL;
+ if (g_CluiData.fGDIPlusFail)
+ {
+ hImageDecoderModule = LoadLibrary(_T("ImgDecoder.dll"));
+ if (hImageDecoderModule == NULL)
+ {
+ char tDllPath[ MAX_PATH ];
+ GetModuleFileNameA( g_hInst, tDllPath, sizeof( tDllPath ));
+ {
+ char* p = strrchr( tDllPath, '\\' );
+ if ( p != NULL )
+ strcpy( p+1, "ImgDecoder.dll" );
+ else
+ {
+ strcpy( tDllPath, "ImgDecoder.dll" );
+ }
+ }
+
+ hImageDecoderModule = LoadLibraryA(tDllPath);
+ }
+ if (hImageDecoderModule != NULL)
+ {
+ ImgNewDecoder = (pfnImgNewDecoder )GetProcAddress( hImageDecoderModule, "ImgNewDecoder");
+ ImgDeleteDecoder = (pfnImgDeleteDecoder )GetProcAddress( hImageDecoderModule, "ImgDeleteDecoder");
+ ImgNewDIBFromFile = (pfnImgNewDIBFromFile)GetProcAddress( hImageDecoderModule, "ImgNewDIBFromFile");
+ ImgDeleteDIBSection = (pfnImgDeleteDIBSection)GetProcAddress( hImageDecoderModule, "ImgDeleteDIBSection");
+ ImgGetHandle = (pfnImgGetHandle)GetProcAddress( hImageDecoderModule, "ImgGetHandle");
+ }
+ }
+ //create services
+ CreateServiceFunction(MS_SKIN_DRAWGLYPH,ske_Service_DrawGlyph);
+ CreateServiceFunction(MS_SKINENG_UPTATEFRAMEIMAGE,ske_Service_UpdateFrameImage);
+ CreateServiceFunction(MS_SKINENG_INVALIDATEFRAMEIMAGE,ske_Service_InvalidateFrameImage);
+ CreateServiceFunction(MS_SKINENG_ALPHATEXTOUT,ske_Service_AlphaTextOut);
+ CreateServiceFunction(MS_SKINENG_DRAWICONEXFIX,ske_Service_DrawIconEx);
+
+ CreateServiceFunction(MS_DRAW_TEXT_WITH_EFFECT,ske_Service_DrawTextWithEffect);
+
+ //create event handle
+ hSkinLoadedEvent = HookEvent(ME_SKIN_SERVICESCREATED,CLUI_OnSkinLoad);
+ NotifyEventHooks(g_CluiData.hEventSkinServicesCreated,0,0);
+ return S_OK;
+}
+
+int SkinEngineUnloadModule()
+{
+ //unload services
+ ModernSkinButtonUnloadModule(0,0);
+ ske_UnloadSkin(&g_SkinObjectList);
+
+ mir_free_and_nil(g_SkinObjectList.pObjects);
+ mir_free_and_nil(g_SkinObjectList.pMaskList);
+ mir_free_and_nil(MainModernMaskList);
+
+ if (pEffectStack)
+ {
+ for (int i=0; i < pEffectStack->realCount; i++)
+ if (pEffectStack->items[i]) {
+ EFFECTSSTACKITEM * effect = (EFFECTSSTACKITEM*)(pEffectStack->items[i]);
+ mir_free(effect);
+ }
+ List_Destroy(pEffectStack);
+ mir_free_and_nil(pEffectStack);
+ }
+ if (g_pCachedWindow) {
+ SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackOld);
+ SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageOld);
+ DeleteObject(g_pCachedWindow->hBackDIB);
+ DeleteObject(g_pCachedWindow->hImageDIB);
+ mod_DeleteDC(g_pCachedWindow->hBackDC);
+ mod_DeleteDC(g_pCachedWindow->hImageDC);
+ ReleaseDC(NULL,g_pCachedWindow->hScreenDC);
+ mir_free_and_nil(g_pCachedWindow);
+ }
+ DeleteCriticalSection(&cs_SkinChanging);
+ GdiFlush();
+ DestroyHookableEvent(g_CluiData.hEventSkinServicesCreated);
+ if (hImageDecoderModule) FreeLibrary(hImageDecoderModule);
+ AniAva_UnloadModule();
+ ShutdownGdiPlus();
+ //free variables
+ return 1;
+}
+
+BOOL ske_AlphaBlend(HDC hdcDest,int nXOriginDest,int nYOriginDest,int nWidthDest,int nHeightDest,HDC hdcSrc,int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc,BLENDFUNCTION blendFunction)
+{
+ if (g_CluiData.fDisableSkinEngine && !(!g_CluiData.fGDIPlusFail && blendFunction.BlendFlags&128))
+ {
+ if (nWidthDest != nWidthSrc || nHeightDest != nHeightSrc)
+ return StretchBlt(hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest,hdcSrc,nXOriginSrc,nYOriginSrc,nWidthSrc,nHeightSrc, SRCCOPY);
+ else
+ return BitBlt(hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest,hdcSrc,nXOriginSrc,nYOriginSrc, SRCCOPY);
+ }
+
+ if ( !g_CluiData.fGDIPlusFail && blendFunction.BlendFlags&128 ) //Use gdi+ engine
+ {
+ return GDIPlus_AlphaBlend( hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest,
+ hdcSrc,nXOriginSrc,nYOriginSrc,nWidthSrc,nHeightSrc,
+ &blendFunction);
+ }
+ blendFunction.BlendFlags &= ~128;
+ return AlphaBlend(hdcDest,nXOriginDest,nYOriginDest,nWidthDest,nHeightDest,hdcSrc,nXOriginSrc,nYOriginSrc,nWidthSrc,nHeightSrc,blendFunction);
+}
+
+static int ske_LockSkin()
+{
+ EnterCriticalSection(&cs_SkinChanging);
+ return 0;
+}
+
+static int ske_UnlockSkin()
+{
+ LeaveCriticalSection(&cs_SkinChanging);
+ return 0;
+}
+
+typedef struct _tagDCBuffer
+{
+ HDC hdcOwnedBy;
+ int nUsageID;
+ int width;
+ int height;
+ void* pImage;
+ HDC hDC;
+ HBITMAP oldBitmap;
+ HBITMAP hBitmap;
+ DWORD dwDestroyAfterTime;
+}DCBUFFER;
+CRITICAL_SECTION BufferListCS = {0};
+
+SortedList * BufferList = NULL;
+enum
+{
+ BUFFER_DRAWICON = 0,
+ BUFFER_DRAWIMAGE
+};
+
+int SortBufferList(void* it1, void * it2)
+{
+ DCBUFFER * buf1 = (DCBUFFER *)it1;
+ DCBUFFER * buf2 = (DCBUFFER *)it2;
+ if (buf1->hdcOwnedBy != buf2->hdcOwnedBy) return (int)(buf1->hdcOwnedBy < buf2->hdcOwnedBy);
+ else if (buf1->nUsageID != buf2->nUsageID) return (int) (buf1->nUsageID < buf2->nUsageID);
+ else return (int) (buf1->hDC < buf2->hDC);
+}
+
+HDC ske_RequestBufferDC(HDC hdcOwner, int dcID, int width, int height, BOOL fClear)
+{
+ DCBUFFER buf;
+ DCBUFFER * pBuf;
+ if (BufferList == NULL)
+ {
+ BufferList = List_Create(0,2);
+ BufferList->sortFunc = SortBufferList;
+ InitializeCriticalSection(&BufferListCS);
+ }
+ EnterCriticalSection(&BufferListCS);
+ //Try to find DC in buffer list
+ buf.hdcOwnedBy = hdcOwner;
+ buf.nUsageID = dcID;
+ buf.hDC = NULL;
+ pBuf = (DCBUFFER*)List_Find(BufferList,(void*)&buf);
+ if ( !pBuf)
+ {
+ //if not found - allocate it
+ pBuf = (DCBUFFER *)mir_alloc(sizeof(DCBUFFER));
+ *pBuf = buf;
+ pBuf->width = width;
+ pBuf->height = height;
+ pBuf->hBitmap = ske_CreateDIB32Point(width,height,&(pBuf->pImage));
+ pBuf->hDC = CreateCompatibleDC(hdcOwner);
+ pBuf->oldBitmap = (HBITMAP)SelectObject(pBuf->hDC,pBuf->hBitmap);
+ pBuf->dwDestroyAfterTime = 0;
+ List_InsertPtr(BufferList,pBuf);
+ }
+ else
+ {
+ if (pBuf->width != width || pBuf->height != height)
+ {
+ //resize
+ SelectObject(pBuf->hDC,pBuf->oldBitmap);
+ DeleteObject(pBuf->hBitmap);
+ pBuf->width = width;
+ pBuf->height = height;
+ pBuf->hBitmap = ske_CreateDIB32Point(width,height,&(pBuf->pImage));
+ pBuf->oldBitmap = (HBITMAP)SelectObject(pBuf->hDC,pBuf->hBitmap);
+ } else if (fClear)
+ memset(pBuf->pImage,0,width*height*sizeof(DWORD));
+ }
+ pBuf->dwDestroyAfterTime = 0;
+ LeaveCriticalSection(&BufferListCS);
+ return pBuf->hDC;
+}
+
+int ske_ReleaseBufferDC(HDC hDC, int keepTime)
+{
+ DWORD dwCurrentTime = GetTickCount();
+ DCBUFFER * pBuf = NULL;
+ //Try to find DC in buffer list - set flag to be release after time;
+ int i=0;
+ EnterCriticalSection(&BufferListCS);
+ for (i=0; i < BufferList->realCount; i++)
+ {
+ pBuf = (DCBUFFER *)BufferList->items[i];
+ if (pBuf)
+ {
+ if (hDC != NULL && pBuf->hDC == hDC)
+ {
+ pBuf->dwDestroyAfterTime = dwCurrentTime+keepTime;
+ break;
+ }
+ else
+ {
+ if ((pBuf->dwDestroyAfterTime && pBuf->dwDestroyAfterTime < dwCurrentTime) || keepTime == -1)
+ {
+ SelectObject(pBuf->hDC,pBuf->oldBitmap);
+ DeleteObject(pBuf->hBitmap);
+ DeleteDC(pBuf->hDC);
+ mir_free(pBuf);
+ List_Remove(BufferList,i);
+ i--;
+ }
+ }
+ }
+ }
+ LeaveCriticalSection(&BufferListCS);
+ return 0;
+}
+
+BOOL ske_SetRgnOpaque(HDC memdc,HRGN hrgn, BOOL force)
+{
+ RGNDATA * rdata;
+ DWORD rgnsz;
+ DWORD d;
+ RECT * rect;
+ if (g_CluiData.fDisableSkinEngine && !force) return TRUE;
+ rgnsz = GetRegionData(hrgn,0,NULL);
+ rdata = (RGNDATA *) mir_alloc(rgnsz);
+ GetRegionData(hrgn,rgnsz,rdata);
+ rect = (RECT *)rdata->Buffer;
+ for (d = 0; d < rdata->rdh.nCount; d++)
+ {
+ ske_SetRectOpaque(memdc,&rect[d], force);
+ }
+ mir_free(rdata);
+ return TRUE;
+}
+
+
+BOOL ske_SetRectOpaque(HDC memdc,RECT *fr, BOOL force)
+{
+ int f = 0;
+ BYTE * bits;
+ BITMAP bmp;
+ HBITMAP hbmp;
+
+ if ( g_CluiData.fDisableSkinEngine && !force )
+ return TRUE;
+
+ hbmp = (HBITMAP)GetCurrentObject( memdc,OBJ_BITMAP );
+ GetObject( hbmp, sizeof(bmp), &bmp );
+
+ if ( bmp.bmPlanes != 1 )
+ return FALSE;
+
+ if ( !bmp.bmBits)
+ {
+ f = 1;
+ bits = (BYTE*)malloc(bmp.bmWidthBytes*bmp.bmHeight);
+ GetBitmapBits(hbmp,bmp.bmWidthBytes*bmp.bmHeight,bits);
+ }
+ else
+ bits = (BYTE*)bmp.bmBits;
+
+ int sx = ( fr->left > 0 ) ? fr->left : 0;
+ int sy = ( fr->top > 0 ) ? fr->top : 0;
+ int ex = ( fr->right < bmp.bmWidth ) ? fr->right : bmp.bmWidth;
+ int ey = ( fr->bottom < bmp.bmHeight) ? fr->bottom : bmp.bmHeight;
+
+ int width = ex-sx;
+
+ BYTE* pLine = ((BYTE*)bits) + (bmp.bmHeight-sy-1)*bmp.bmWidthBytes + (sx << 2) + 3;
+ for ( int y = 0; y < (ey - sy); y++ )
+ {
+ BYTE * pColumn = pLine;
+ for ( int x = 0; x < width; x++ )
+ {
+ *pColumn = 255;
+ pColumn += 4;
+ }
+ pLine -= bmp.bmWidthBytes;
+ }
+ if (f)
+ {
+ SetBitmapBits(hbmp,bmp.bmWidthBytes*bmp.bmHeight,bits);
+ free(bits);
+ }
+ // DeleteObject(hbmp);
+ return 1;
+}
+
+static BOOL ske_SkinFillRectByGlyph(HDC hDest, HDC hSource, RECT * rFill, RECT * rGlyph, RECT * rClip, BYTE mode, BYTE drawMode, int depth)
+{
+ int destw = 0, desth = 0;
+ int xstart = 0, xmax = 0;
+ int ystart = 0, ymax = 0;
+ BLENDFUNCTION bfa = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+
+ //initializations
+ if (mode == FM_STRETCH)
+ {
+ HDC mem2dc;
+ HBITMAP mem2bmp, oldbmp;
+ RECT wr;
+ IntersectRect(&wr,rClip,rFill);
+ if ((wr.bottom-wr.top)*(wr.right-wr.left) == 0) return 0;
+ if (drawMode != 2)
+ {
+ mem2dc = CreateCompatibleDC(hDest);
+ mem2bmp = ske_CreateDIB32(wr.right-wr.left,wr.bottom-wr.top);
+ oldbmp = (HBITMAP)SelectObject(mem2dc,mem2bmp);
+
+ }
+
+ if (drawMode == 0 || drawMode == 2)
+ {
+ if (drawMode == 0)
+ {
+ ske_AlphaBlend(mem2dc,rFill->left-wr.left,rFill->top-wr.top,rFill->right-rFill->left,rFill->bottom-rFill->top,
+ hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,rGlyph->bottom-rGlyph->top,bf);
+ ske_AlphaBlend(hDest,wr.left,wr.top,wr.right-wr.left, wr.bottom -wr.top,mem2dc,0,0,wr.right-wr.left, wr.bottom -wr.top,bf);
+ }
+ else
+ {
+ ske_AlphaBlend(hDest,rFill->left,rFill->top,rFill->right-rFill->left,rFill->bottom-rFill->top,
+ hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,rGlyph->bottom-rGlyph->top,bf);
+
+ }
+ }
+ else
+ {
+ // BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, 0 };
+ ske_AlphaBlend(mem2dc,rFill->left-wr.left,rFill->top-wr.top,rFill->right-rFill->left,rFill->bottom-rFill->top,
+ hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,rGlyph->bottom-rGlyph->top,bf);
+ ske_AlphaBlend(hDest,wr.left,wr.top,wr.right-wr.left, wr.bottom -wr.top,mem2dc,0,0,wr.right-wr.left, wr.bottom -wr.top,bf);
+ }
+ if (drawMode != 2)
+ {
+ SelectObject(mem2dc,oldbmp);
+ DeleteObject(mem2bmp);
+ mod_DeleteDC(mem2dc);
+ }
+ return 1;
+ }
+ else if (mode == FM_TILE_VERT && (rGlyph->bottom-rGlyph->top>0) && (rGlyph->right-rGlyph->left>0))
+ {
+ HDC mem2dc;
+ HBITMAP mem2bmp,oldbmp;
+ RECT wr;
+ IntersectRect(&wr,rClip,rFill);
+ if ((wr.bottom-wr.top)*(wr.right-wr.left) == 0) return 0;
+ mem2dc = CreateCompatibleDC(hDest);
+ //SetStretchBltMode(mem2dc, HALFTONE);
+ mem2bmp = ske_CreateDIB32(wr.right-wr.left, rGlyph->bottom-rGlyph->top);
+ oldbmp = (HBITMAP)SelectObject(mem2dc,mem2bmp);
+ if ( !oldbmp)
+ return 0;
+
+ /// draw here
+ {
+ int y = 0, sy = 0, maxy = 0;
+ int w = rFill->right-rFill->left;
+ int h = rGlyph->bottom-rGlyph->top;
+ if (h>0 && (wr.bottom-wr.top)*(wr.right-wr.left) != 0)
+ {
+ w = wr.right-wr.left;
+ {
+ // BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, 0 };
+ ske_AlphaBlend(mem2dc,-(wr.left-rFill->left),0,rFill->right-rFill->left,h,hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,h,bf);
+ //StretchBlt(mem2dc,-(wr.left-rFill->left),0,rFill->right-rFill->left,h,hSource,rGlyph->left,rGlyph->top,rGlyph->right-rGlyph->left,h,SRCCOPY);
+ }
+ if (drawMode == 0 || drawMode == 2)
+ {
+ if (drawMode == 0 )
+ {
+
+ int dy;
+ dy = (wr.top-rFill->top)%h;
+ if (dy >= 0)
+ {
+ int ht;
+ y = wr.top;
+ ht = (y+h-dy <= wr.bottom)?(h-dy):(wr.bottom-wr.top);
+ BitBlt(hDest,wr.left,y,w,ht,mem2dc,0,dy,SRCCOPY);
+ }
+
+ y = wr.top+h-dy;
+ while (y < wr.bottom-h){
+ BitBlt(hDest,wr.left,y,w,h,mem2dc,0,0,SRCCOPY);
+ y += h;
+ }
+ if (y <= wr.bottom)
+ BitBlt(hDest,wr.left,y,w,wr.bottom-y, mem2dc,0,0,SRCCOPY);
+
+ }
+ else
+ {
+ y = wr.top;
+ while (y < wr.bottom-h)
+ {
+ // BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, 0 };
+ ske_AlphaBlend(hDest,wr.left,y,w,h, mem2dc,0,0,w,h,bf);
+ y += h;
+ }
+ if (y <= wr.bottom)
+ {
+ // BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, 0 };
+ ske_AlphaBlend(hDest,wr.left,y,w,wr.bottom-y, mem2dc,0,0,w,wr.bottom-y,bf);
+ }
+ }
+
+ }
+ else
+ {
+ int dy;
+
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+
+ dy = (wr.top-rFill->top)%h;
+
+ if (dy >= 0)
+ {
+ int ht;
+ y = wr.top;
+ ht = (y+h-dy <= wr.bottom)?(h-dy):(wr.bottom-wr.top);
+ ske_AlphaBlend(hDest,wr.left,y,w,ht,mem2dc,0,dy,w,ht,bf);
+ }
+
+ y = wr.top+h-dy;
+ while (y < wr.bottom-h)
+ {
+ ske_AlphaBlend(hDest,wr.left,y,w,h,mem2dc,0,0,w,h,bf);
+ y += h;
+ }
+ if (y <= wr.bottom)
+ ske_AlphaBlend(hDest,wr.left,y,w,wr.bottom-y, mem2dc,0,0,w,wr.bottom-y,bf);
+ }
+ }
+ }
+ SelectObject(mem2dc,oldbmp);
+ DeleteObject(mem2bmp);
+ mod_DeleteDC(mem2dc);
+ }
+ else if (mode == FM_TILE_HORZ && (rGlyph->right-rGlyph->left>0) && (rGlyph->bottom-rGlyph->top>0) && (rFill->bottom-rFill->top)>0 && (rFill->right-rFill->left)>0)
+ {
+ HDC mem2dc;
+ RECT wr;
+ HBITMAP mem2bmp,oldbmp;
+ int w = rGlyph->right-rGlyph->left;
+ int h = rFill->bottom-rFill->top;
+ IntersectRect(&wr,rClip,rFill);
+ if ((wr.bottom-wr.top)*(wr.right-wr.left) == 0) return 0;
+ h = wr.bottom-wr.top;
+ mem2dc = CreateCompatibleDC(hDest);
+
+ mem2bmp = ske_CreateDIB32(w,h);
+ oldbmp = (HBITMAP)SelectObject(mem2dc,mem2bmp);
+
+ if ( !oldbmp)
+ return 0;
+ /// draw here
+ {
+ int x = 0, sy = 0, maxy = 0;
+ {
+ //SetStretchBltMode(mem2dc, HALFTONE);
+ //StretchBlt(mem2dc,0,0,w,h,hSource,rGlyph->left+(wr.left-rFill->left),rGlyph->top,w,h,SRCCOPY);
+
+ // BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, 0 };
+ ske_AlphaBlend(mem2dc,0,-(wr.top-rFill->top),w,rFill->bottom-rFill->top,hSource,rGlyph->left,rGlyph->top,w,rGlyph->bottom-rGlyph->top,bf);
+ if (drawMode == 0 || drawMode == 2)
+ {
+ if (drawMode == 0)
+ {
+
+ int dx;
+ dx = (wr.left-rFill->left)%w;
+ if (dx >= 0)
+ {
+ int wt;
+ x = wr.left;
+ wt = (x+w-dx <= wr.right)?(w-dx):(wr.right-wr.left);
+ BitBlt(hDest,x,wr.top,wt,h,mem2dc,dx,0,SRCCOPY);
+ }
+ x = wr.left+w-dx;
+ while (x < wr.right-w){
+ BitBlt(hDest,x,wr.top,w,h,mem2dc,0,0,SRCCOPY);
+ x += w;
+ }
+ if (x <= wr.right)
+ BitBlt(hDest,x,wr.top,wr.right-x,h, mem2dc,0,0,SRCCOPY);
+ }
+ else
+ {
+ int dx;
+ dx = (wr.left-rFill->left)%w;
+ x = wr.left-dx;
+ while (x < wr.right-w){
+ ske_AlphaBlend(hDest,x,wr.top,w,h,mem2dc,0,0,w,h,bf);
+ x += w;
+ }
+ if (x <= wr.right)
+ ske_AlphaBlend(hDest,x,wr.top,wr.right-x,h, mem2dc,0,0,wr.right-x,h,bf);
+ }
+
+ }
+ else
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ int dx;
+ dx = (wr.left-rFill->left)%w;
+ if (dx >= 0)
+ {
+ int wt;
+ x = wr.left;
+ wt = (x+w-dx <= wr.right)?(w-dx):(wr.right-wr.left);
+ ske_AlphaBlend(hDest,x,wr.top,wt,h,mem2dc,dx,0,wt,h,bf);
+ }
+ x = wr.left+w-dx;
+ while (x < wr.right-w){
+ ske_AlphaBlend(hDest,x,wr.top,w,h,mem2dc,0,0,w,h,bf);
+ x += w;
+ }
+ if (x <= wr.right)
+ ske_AlphaBlend(hDest,x,wr.top,wr.right-x,h, mem2dc,0,0,wr.right-x,h,bf);
+
+ }
+ }
+ }
+ SelectObject(mem2dc,oldbmp);
+ DeleteObject(mem2bmp);
+ mod_DeleteDC(mem2dc);
+ }
+ else if (mode == FM_TILE_BOTH && (rGlyph->right-rGlyph->left>0) && (rGlyph->bottom-rGlyph->top>0))
+ {
+ HDC mem2dc;
+ int w = rGlyph->right-rGlyph->left;
+ int x = 0, sy = 0, maxy = 0;
+ int h = rFill->bottom-rFill->top;
+ HBITMAP mem2bmp,oldbmp;
+ RECT wr;
+ IntersectRect(&wr,rClip,rFill);
+ if ((wr.bottom-wr.top)*(wr.right-wr.left) == 0) return 0;
+ mem2dc = CreateCompatibleDC(hDest);
+ mem2bmp = ske_CreateDIB32(w,wr.bottom-wr.top);
+ h = wr.bottom-wr.top;
+ oldbmp = (HBITMAP)SelectObject(mem2dc,mem2bmp);
+#ifdef _DEBUG
+ if ( !oldbmp)
+ (NULL,"Tile bitmap not selected","ERROR", MB_OK);
+#endif
+ /// draw here
+ {
+
+ //fill temp bitmap
+ {
+ int y;
+ int dy;
+ dy = (wr.top-rFill->top)%(rGlyph->bottom-rGlyph->top);
+ y = -dy;
+ while (y < wr.bottom-wr.top)
+ {
+
+ ske_AlphaBlend(mem2dc,0,y,w,rGlyph->bottom-rGlyph->top, hSource,rGlyph->left,rGlyph->top,w,rGlyph->bottom-rGlyph->top,bf);
+ y += rGlyph->bottom-rGlyph->top;
+ }
+
+ //--
+ //end temp bitmap
+ if (drawMode == 0 || drawMode == 2)
+ {
+ if (drawMode == 0)
+ {
+
+ int dx;
+ dx = (wr.left-rFill->left)%w;
+ if (dx >= 0)
+ {
+ int wt;
+ x = wr.left;
+ wt = (x+w-dx <= wr.right)?(w-dx):(wr.right-wr.left);
+ BitBlt(hDest,x,wr.top,wt,h,mem2dc,dx,0,SRCCOPY);
+ }
+ x = wr.left+w-dx;
+ while (x < wr.right-w){
+ BitBlt(hDest,x,wr.top,w,h,mem2dc,0,0,SRCCOPY);
+ x += w;
+ }
+ if (x <= wr.right)
+ BitBlt(hDest,x,wr.top,wr.right-x,h, mem2dc,0,0,SRCCOPY);
+ }
+ else
+ {
+ int dx;
+ dx = (wr.left-rFill->left)%w;
+ x = wr.left-dx;
+ while (x < wr.right-w){
+ ske_AlphaBlend(hDest,x,wr.top,w,h,mem2dc,0,0,w,h,bf);
+ x += w;
+ }
+ if (x <= wr.right)
+ ske_AlphaBlend(hDest,x,wr.top,wr.right-x,h, mem2dc,0,0,wr.right-x,h,bf);
+ }
+
+ }
+ else
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+
+ int dx;
+ dx = (wr.left-rFill->left)%w;
+ if (dx >= 0)
+ {
+ int wt;
+ x = wr.left;
+ wt = (x+w-dx <= wr.right)?(w-dx):(wr.right-wr.left);
+ ske_AlphaBlend(hDest,x,wr.top,wt,h,mem2dc,dx,0,wt,h,bf);
+ }
+ x = wr.left+w-dx;
+ while (x < wr.right-w){
+ ske_AlphaBlend(hDest,x,wr.top,w,h,mem2dc,0,0,w,h,bf);
+ x += w;
+ }
+ if (x <= wr.right)
+ ske_AlphaBlend(hDest,x,wr.top,wr.right-x,h, mem2dc,0,0,wr.right-x,h,bf);
+
+ }
+ }
+
+ }
+ SelectObject(mem2dc,oldbmp);
+ DeleteObject(mem2bmp);
+ mod_DeleteDC(mem2dc);
+ }
+ return 1;
+
+}
+
+HBITMAP ske_CreateDIB32(int cx, int cy)
+{
+ return ske_CreateDIB32Point(cx,cy,NULL);
+}
+
+HBITMAP ske_CreateDIB32Point(int cx, int cy, void ** bits)
+{
+ BITMAPINFO RGB32BitsBITMAPINFO;
+ UINT * ptPixels;
+ HBITMAP DirectBitmap;
+
+ if ( cx < 0 || cy < 0 ) {
+#ifdef _DEBUG
+ DebugBreak();
+#endif
+ return NULL;
+ }
+
+ ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO));
+ RGB32BitsBITMAPINFO.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ RGB32BitsBITMAPINFO.bmiHeader.biWidth = cx;//bm.bmWidth;
+ RGB32BitsBITMAPINFO.bmiHeader.biHeight = cy;//bm.bmHeight;
+ RGB32BitsBITMAPINFO.bmiHeader.biPlanes = 1;
+ RGB32BitsBITMAPINFO.bmiHeader.biBitCount = 32;
+ // pointer used for direct Bitmap pixels access
+
+
+ DirectBitmap = CreateDIBSection(NULL,
+ (BITMAPINFO *)&RGB32BitsBITMAPINFO,
+ DIB_RGB_COLORS,
+ (void **)&ptPixels,
+ NULL, 0);
+ if ((DirectBitmap == NULL || ptPixels == NULL) && cx != 0 && cy != 0)
+ {
+#ifdef _DEBUG
+ MessageBoxA(NULL,"Object not allocated. Check GDI object count","ERROR",MB_OK|MB_ICONERROR);
+ DebugBreak();
+#endif
+ ;
+ }
+ else memset(ptPixels,0,cx*cy*4);
+ if (bits != NULL) *bits = ptPixels;
+ return DirectBitmap;
+}
+
+HRGN ske_CreateOpaqueRgn(BYTE Level, bool Opaque)
+{
+ if ( !g_pCachedWindow)
+ return NULL;
+
+ RGBQUAD * buf = (RGBQUAD *) g_pCachedWindow->hImageDIBByte;
+
+ int x,y;
+ unsigned int cRect = 64;
+ PRGNDATA pRgnData = (PRGNDATA)malloc(sizeof(RGNDATAHEADER) + (cRect)*sizeof(RECT));
+ memset(pRgnData, 0, sizeof(RGNDATAHEADER));
+ pRgnData->rdh.dwSize = sizeof(RGNDATAHEADER);
+ pRgnData->rdh.iType = RDH_RECTANGLES;
+
+ for (y = 0; y < g_pCachedWindow->Height; ++y)
+ {
+ bool inside = false;
+ bool lastin = false;
+ unsigned int entry = 0;
+
+ for (x = 0; x < g_pCachedWindow->Width; ++x)
+ {
+ inside = Opaque ? (buf->rgbReserved > Level) : (buf->rgbReserved < Level);
+ ++buf;
+
+ if (inside != lastin)
+ {
+ if (inside)
+ {
+ lastin = true;
+ entry = x;
+ } else {
+ if (pRgnData->rdh.nCount == cRect)
+ {
+ cRect = cRect + 64;
+ pRgnData = (PRGNDATA)realloc(pRgnData, sizeof(RGNDATAHEADER) + (cRect)*sizeof(RECT));
+ }
+ SetRect(((LPRECT)pRgnData->Buffer) + pRgnData->rdh.nCount, entry, g_pCachedWindow->Height - y, x, g_pCachedWindow->Height - y + 1);
+
+ pRgnData->rdh.nCount++;
+ lastin = false;
+ }
+ }
+ }
+
+ if (lastin)
+ {
+ if (pRgnData->rdh.nCount == cRect)
+ {
+ cRect = cRect + 64;
+ pRgnData = (PRGNDATA)realloc(pRgnData, sizeof(RGNDATAHEADER) + (cRect)*sizeof(RECT));
+ }
+ SetRect(((LPRECT)pRgnData->Buffer) + pRgnData->rdh.nCount, entry, g_pCachedWindow->Height - y, x, g_pCachedWindow->Height - y + 1);
+
+ pRgnData->rdh.nCount++;
+ }
+ }
+ HRGN hRgn = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount*sizeof(RECT), (LPRGNDATA)pRgnData);
+ free(pRgnData);
+
+ return hRgn;
+}
+
+static int ske_DrawSkinObject(SKINDRAWREQUEST * preq, GLYPHOBJECT * pobj)
+{
+ HDC memdc = NULL, glyphdc = NULL;
+ int k = 0;
+ //BITMAP bmp = {0};
+ HBITMAP membmp = 0,oldbmp = 0,oldglyph = 0;
+ BYTE Is32Bit = 0;
+ RECT PRect;
+ POINT mode2offset = {0};
+ int depth = 0;
+ int mode = 0; //0-FastDraw, 1-DirectAlphaDraw, 2-BufferedAlphaDraw
+
+ if ( !(preq && pobj)) return -1;
+ if ((!pobj->hGlyph || pobj->hGlyph == (HBITMAP)-1) && ((pobj->Style&7) == ST_IMAGE || (pobj->Style&7) == ST_FRAGMENT || (pobj->Style&7) == ST_SOLARIZE)) return 0;
+ // Determine painting mode
+ depth = GetDeviceCaps(preq->hDC,BITSPIXEL);
+ depth = depth < 16?16:depth;
+ Is32Bit = pobj->bmBitsPixel == 32;
+ if ((!Is32Bit && pobj->dwAlpha == 255) && pobj->Style != ST_BRUSH) mode = 0;
+ else if (pobj->dwAlpha == 255 && pobj->Style != ST_BRUSH) mode = 1;
+ else mode = 2;
+ // End painting mode
+
+ //force mode
+
+ if (preq->rcClipRect.bottom-preq->rcClipRect.top*preq->rcClipRect.right-preq->rcClipRect.left == 0)
+ preq->rcClipRect = preq->rcDestRect;
+ IntersectRect(&PRect,&preq->rcDestRect,&preq->rcClipRect);
+ if (IsRectEmpty(&PRect))
+ {
+ return 0;
+ }
+ if (mode == 2)
+ {
+ memdc = CreateCompatibleDC(preq->hDC);
+ membmp = ske_CreateDIB32(PRect.right-PRect.left,PRect.bottom-PRect.top);
+ oldbmp = (HBITMAP)SelectObject(memdc,membmp);
+ if (oldbmp == NULL)
+ {
+ if (mode == 2)
+ {
+ SelectObject(memdc,oldbmp);
+ mod_DeleteDC(memdc);
+ DeleteObject(membmp);
+ }
+ return 0;
+ }
+ }
+
+ if (mode != 2) memdc = preq->hDC;
+ {
+ if (pobj->hGlyph && pobj->hGlyph != (HBITMAP)-1)
+ {
+ glyphdc = CreateCompatibleDC(preq->hDC);
+ if ( !oldglyph)
+ oldglyph = (HBITMAP)SelectObject(glyphdc,pobj->hGlyph);
+ else
+ SelectObject(glyphdc,pobj->hGlyph);
+ }
+ // Drawing
+ {
+ RECT rFill, rGlyph, rClip;
+ if ((pobj->Style&7) == ST_BRUSH)
+ {
+ HBRUSH br = CreateSolidBrush(pobj->dwColor);
+ RECT fr;
+ if (mode == 2)
+ {
+ SetRect(&fr,0,0,PRect.right-PRect.left,PRect.bottom-PRect.top);
+ FillRect(memdc,&fr,br);
+ ske_SetRectOpaque(memdc,&fr);
+ // FillRectAlpha(memdc,&fr,pobj->dwColor|0xFF000000);
+ }
+ else
+ {
+ fr = PRect;
+ // SetRect(&fr,0,0,PRect.right-PRect.left,PRect.bottom-PRect.top);
+ FillRect(preq->hDC,&fr,br);
+ }
+ DeleteObject(br);
+ k = -1;
+ }
+ else
+ {
+ if (mode == 2)
+ {
+ mode2offset.x = PRect.left;
+ mode2offset.y = PRect.top;
+ OffsetRect(&PRect,-mode2offset.x,-mode2offset.y);
+ }
+ rClip = (preq->rcClipRect);
+
+ {
+ int lft = 0;
+ int top = 0;
+ int rgh = pobj->bmWidth;
+ int btm = pobj->bmHeight;
+ if ((pobj->Style&7) == ST_FRAGMENT)
+ {
+ lft = pobj->clipArea.x;
+ top = pobj->clipArea.y;
+ rgh = min(rgh,lft+pobj->szclipArea.cx);
+ btm = min(btm,top+pobj->szclipArea.cy);
+ }
+
+ // Draw center...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.top+pobj->dwTop;
+ rFill.bottom = preq->rcDestRect.bottom-pobj->dwBottom;
+ rFill.left = preq->rcDestRect.left+pobj->dwLeft;
+ rFill.right = preq->rcDestRect.right-pobj->dwRight;
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+ rGlyph.top = top+pobj->dwTop;
+ rGlyph.left = lft+pobj->dwLeft;
+ rGlyph.right = rgh-pobj->dwRight;
+ rGlyph.bottom = btm-pobj->dwBottom;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode,mode,depth);
+ }
+
+ // Draw top side...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.top;
+ rFill.bottom = preq->rcDestRect.top+pobj->dwTop;
+ rFill.left = preq->rcDestRect.left+pobj->dwLeft;
+ rFill.right = preq->rcDestRect.right-pobj->dwRight;
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+ rGlyph.top = top+0;
+ rGlyph.left = lft+pobj->dwLeft;
+ rGlyph.right = rgh-pobj->dwRight;
+ rGlyph.bottom = top+pobj->dwTop;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_HORZ,mode,depth);
+ }
+ // Draw bottom side...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.bottom-pobj->dwBottom;
+ rFill.bottom = preq->rcDestRect.bottom;
+ rFill.left = preq->rcDestRect.left+pobj->dwLeft;
+ rFill.right = preq->rcDestRect.right-pobj->dwRight;
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+
+ rGlyph.top = btm-pobj->dwBottom;
+ rGlyph.left = lft+pobj->dwLeft;
+ rGlyph.right = rgh-pobj->dwRight;
+ rGlyph.bottom = btm;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_HORZ,mode,depth);
+ }
+ // Draw left side...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.top+pobj->dwTop;
+ rFill.bottom = preq->rcDestRect.bottom-pobj->dwBottom;
+ rFill.left = preq->rcDestRect.left;
+ rFill.right = preq->rcDestRect.left+pobj->dwLeft;
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+
+ rGlyph.top = top+pobj->dwTop;
+ rGlyph.left = lft;
+ rGlyph.right = lft+pobj->dwLeft;
+ rGlyph.bottom = btm-pobj->dwBottom;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_VERT,mode,depth);
+ }
+
+ // Draw right side...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.top+pobj->dwTop;
+ rFill.bottom = preq->rcDestRect.bottom-pobj->dwBottom;
+ rFill.left = preq->rcDestRect.right-pobj->dwRight;
+ rFill.right = preq->rcDestRect.right;
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+
+ rGlyph.top = top+pobj->dwTop;
+ rGlyph.left = rgh-pobj->dwRight;
+ rGlyph.right = rgh;
+ rGlyph.bottom = btm-pobj->dwBottom;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,pobj->FitMode&FM_TILE_VERT,mode,depth);
+ }
+
+
+ // Draw Top-Left corner...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.top;
+ rFill.bottom = preq->rcDestRect.top+pobj->dwTop;
+ rFill.left = preq->rcDestRect.left;
+ rFill.right = preq->rcDestRect.left+pobj->dwLeft;
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+
+ rGlyph.top = top;
+ rGlyph.left = lft;
+ rGlyph.right = lft+pobj->dwLeft;
+ rGlyph.bottom = top+pobj->dwTop;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth);
+ }
+ // Draw Top-Right corner...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.top;
+ rFill.bottom = preq->rcDestRect.top+pobj->dwTop;
+ rFill.left = preq->rcDestRect.right-pobj->dwRight;
+ rFill.right = preq->rcDestRect.right;
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+
+ rGlyph.top = top;
+ rGlyph.left = rgh-pobj->dwRight;
+ rGlyph.right = rgh;
+ rGlyph.bottom = top+pobj->dwTop;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth);
+ }
+
+ // Draw Bottom-Left corner...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.bottom-pobj->dwBottom;
+ rFill.bottom = preq->rcDestRect.bottom;
+ rFill.left = preq->rcDestRect.left;
+ rFill.right = preq->rcDestRect.left+pobj->dwLeft;
+
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+
+ rGlyph.left = lft;
+ rGlyph.right = lft+pobj->dwLeft;
+ rGlyph.top = btm-pobj->dwBottom;
+ rGlyph.bottom = btm;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth);
+ }
+ // Draw Bottom-Right corner...
+ if (1)
+ {
+ rFill.top = preq->rcDestRect.bottom-pobj->dwBottom;
+ rFill.bottom = preq->rcDestRect.bottom;
+ rFill.left = preq->rcDestRect.right-pobj->dwRight;
+ rFill.right = preq->rcDestRect.right;
+
+
+ if (mode == 2)
+ OffsetRect(&rFill,-mode2offset.x,-mode2offset.y);
+
+ rGlyph.left = rgh-pobj->dwRight;
+ rGlyph.right = rgh;
+ rGlyph.top = btm-pobj->dwBottom;
+ rGlyph.bottom = btm;
+
+ k += ske_SkinFillRectByGlyph(memdc,glyphdc,&rFill,&rGlyph,&PRect,0,mode,depth);
+ }
+ }
+
+ }
+
+ if ((k>0 || k == -1) && mode == 2)
+ {
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, /*(bm.bmBitsPixel == 32)?255:*/pobj->dwAlpha, (pobj->bmBitsPixel == 32 && pobj->Style != ST_BRUSH)?AC_SRC_ALPHA:0};
+ if (mode == 2)
+ OffsetRect(&PRect,mode2offset.x,mode2offset.y);
+ ske_AlphaBlend( preq->hDC,PRect.left,PRect.top,PRect.right-PRect.left,PRect.bottom-PRect.top,
+ memdc,0,0,PRect.right-PRect.left,PRect.bottom-PRect.top,bf);
+ }
+ }
+ }
+ //free GDI resources
+ //--++--
+
+ //free GDI resources
+ {
+
+ if (oldglyph) SelectObject(glyphdc,oldglyph);
+ if (glyphdc) mod_DeleteDC(glyphdc);
+ }
+ if (mode == 2)
+ {
+ SelectObject(memdc,oldbmp);
+ mod_DeleteDC(memdc);
+ DeleteObject(membmp);
+ }
+
+ }
+ if (pobj->plTextList && pobj->plTextList->realCount>0)
+ {
+ int i;
+ HFONT hOldFont;
+ for (i=0; i < pobj->plTextList->realCount; i++)
+ {
+ GLYPHTEXT * gt = (GLYPHTEXT *)pobj->plTextList->items[i];
+ if ( !gt->hFont)
+ {
+ if (gl_plSkinFonts && gl_plSkinFonts->realCount>0)
+ {
+ int j = 0;
+ for (j = 0; j < gl_plSkinFonts->realCount; j++)
+ {
+ SKINFONT * sf;
+ sf = (SKINFONT*)gl_plSkinFonts->items[j];
+ if (sf->szFontID && !strcmp(sf->szFontID,gt->szFontID))
+ {
+ gt->hFont = sf->hFont;
+ break;
+ }
+ }
+ }
+ if ( !gt->hFont) gt->hFont = (HFONT)-1;
+ }
+ if (gt->hFont != (HFONT)-1)
+ {
+ RECT rc = {0};
+ hOldFont = (HFONT)SelectObject(preq->hDC,gt->hFont);
+
+
+
+ if (gt->RelativeFlags&2) rc.left = preq->rcDestRect.right+gt->iLeft;
+ else if (gt->RelativeFlags&1) rc.left = ((preq->rcDestRect.right-preq->rcDestRect.left)>>1)+gt->iLeft;
+ else rc.left = preq->rcDestRect.left+gt->iLeft;
+
+ if (gt->RelativeFlags&8) rc.top = preq->rcDestRect.bottom+gt->iTop;
+ else if (gt->RelativeFlags&4) rc.top = ((preq->rcDestRect.bottom-preq->rcDestRect.top)>>1)+gt->iTop;
+ else rc.top = preq->rcDestRect.top+gt->iTop;
+
+ if (gt->RelativeFlags&32) rc.right = preq->rcDestRect.right+gt->iRight;
+ else if (gt->RelativeFlags&16) rc.right = ((preq->rcDestRect.right-preq->rcDestRect.left)>>1)+gt->iRight;
+ else rc.right = preq->rcDestRect.left+gt->iRight;
+
+ if (gt->RelativeFlags&128) rc.bottom = preq->rcDestRect.bottom+gt->iBottom;
+ else if (gt->RelativeFlags&64) rc.bottom = ((preq->rcDestRect.bottom-preq->rcDestRect.top)>>1)+gt->iBottom;
+ else rc.bottom = preq->rcDestRect.top+gt->iBottom;
+
+ ske_AlphaTextOut(preq->hDC, gt->stText, -1, &rc,gt->dwFlags, gt->dwColor);
+ SelectObject(preq->hDC,hOldFont);
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+
+int ske_AddDescriptorToSkinObjectList (LPSKINOBJECTDESCRIPTOR lpDescr, SKINOBJECTSLIST* Skin)
+{
+ SKINOBJECTSLIST *sk;
+ if (Skin) sk = Skin; else sk = &g_SkinObjectList;
+ if ( !sk) return 0;
+ if (mir_bool_strcmpi(lpDescr->szObjectID,"_HEADER_")) return 0;
+ {//check if new object allready presents.
+ DWORD i=0;
+ for (i=0; i < sk->dwObjLPAlocated;i++)
+ if ( !mir_strcmp(sk->pObjects[i].szObjectID,lpDescr->szObjectID)) return 0;
+ }
+ if (sk->dwObjLPAlocated+1>sk->dwObjLPReserved)
+ { // Realocated list to add space for new object
+
+ sk->pObjects = (SKINOBJECTDESCRIPTOR*)mir_realloc(sk->pObjects,sizeof(SKINOBJECTDESCRIPTOR)*(sk->dwObjLPReserved+1)/*alloc step*/);
+ sk->dwObjLPReserved++;
+ }
+ { //filling new objects field
+ sk->pObjects[sk->dwObjLPAlocated].bType = lpDescr->bType;
+ sk->pObjects[sk->dwObjLPAlocated].Data = NULL;
+ sk->pObjects[sk->dwObjLPAlocated].szObjectID = mir_strdup(lpDescr->szObjectID);
+ // sk->Objects[sk->dwObjLPAlocated].szObjectName = mir_strdup(lpDescr->szObjectName);
+ if (lpDescr->Data != NULL)
+ { //Copy defaults values
+ switch (lpDescr->bType)
+ {
+ case OT_GLYPHOBJECT:
+ {
+ GLYPHOBJECT * obdat;
+ GLYPHOBJECT * gl = (GLYPHOBJECT*)lpDescr->Data;
+ sk->pObjects[sk->dwObjLPAlocated].Data = mir_alloc(sizeof(GLYPHOBJECT));
+ obdat = (GLYPHOBJECT*)sk->pObjects[sk->dwObjLPAlocated].Data;
+ memmove(obdat,gl,sizeof(GLYPHOBJECT));
+ if (gl->szFileName != NULL)
+ {
+ obdat->szFileName = mir_strdup(gl->szFileName);
+ mir_free_and_nil(gl->szFileName);
+ }
+ else obdat->szFileName = NULL;
+
+ obdat->hGlyph = NULL;
+ break;
+ }
+ }
+
+ }
+ }
+ sk->dwObjLPAlocated++;
+ return 1;
+}
+
+static LPSKINOBJECTDESCRIPTOR ske_FindObject(const char * szName, BYTE objType, SKINOBJECTSLIST* Skin)
+{
+ // DWORD i;
+ SKINOBJECTSLIST* sk;
+ sk = (Skin == NULL)?(&g_SkinObjectList):Skin;
+ return skin_FindObjectByRequest((char *)szName,sk->pMaskList);
+}
+
+static LPSKINOBJECTDESCRIPTOR ske_FindObjectByMask(MODERNMASK * pModernMask, BYTE objType, SKINOBJECTSLIST* Skin)
+{
+ // DWORD i;
+ SKINOBJECTSLIST* sk;
+ sk = (Skin == NULL)?(&g_SkinObjectList):Skin;
+ if ( !sk->pMaskList) return NULL;
+ return skin_FindObjectByMask(pModernMask,sk->pMaskList);
+}
+
+LPSKINOBJECTDESCRIPTOR ske_FindObjectByName(const char * szName, BYTE objType, SKINOBJECTSLIST* Skin)
+{
+ DWORD i;
+ SKINOBJECTSLIST* sk;
+ sk = (Skin == NULL)?(&g_SkinObjectList):Skin;
+ for (i=0; i < sk->dwObjLPAlocated; i++)
+ {
+ if (sk->pObjects[i].bType == objType || objType == OT_ANY)
+ {
+ if ( !mir_strcmp(sk->pObjects[i].szObjectID,szName))
+ return &(sk->pObjects[i]);
+ }
+ }
+ return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Paint glyph
+// wParam - LPSKINDRAWREQUEST
+// lParam - possible direct pointer to modern mask
+//////////////////////////////////////////////////////////////////////////
+
+INT_PTR ske_Service_DrawGlyph(WPARAM wParam,LPARAM lParam)
+{
+ LPSKINDRAWREQUEST preq;
+ LPSKINOBJECTDESCRIPTOR pgl;
+ LPGLYPHOBJECT gl;
+ if ( !wParam) return -1;
+ ske_LockSkin();
+ __try
+ {
+ preq = (LPSKINDRAWREQUEST)wParam;
+ if (lParam)
+ pgl = ske_FindObjectByMask((MODERNMASK*)lParam, OT_GLYPHOBJECT,NULL);
+ else
+ pgl = ske_FindObject(preq->szObjectID, OT_GLYPHOBJECT,NULL);
+ if (pgl == NULL) return -1;
+ if (pgl->Data == NULL) return -1;
+ gl = (LPGLYPHOBJECT)pgl->Data;
+ if ((gl->Style&7) == ST_SKIP) return ST_SKIP;
+ if (gl->hGlyph == NULL && gl->hGlyph != (HBITMAP)-1 &&
+ ( (gl->Style&7) == ST_IMAGE
+ || (gl->Style&7) == ST_FRAGMENT
+ || (gl->Style&7) == ST_SOLARIZE ))
+ if (gl->szFileName)
+ {
+ gl->hGlyph = ske_LoadGlyphImage(gl->szFileName);
+ if (gl->hGlyph)
+ {
+ BITMAP bmp = {0};
+ GetObject(gl->hGlyph,sizeof(BITMAP),&bmp);
+ gl->bmBitsPixel = (BYTE)bmp.bmBitsPixel;
+ gl->bmHeight = bmp.bmHeight;
+ gl->bmWidth = bmp.bmWidth;
+ }
+ else
+ gl->hGlyph = (HBITMAP)-1; //invalid
+ }
+ return ske_DrawSkinObject(preq,gl);
+ }
+ __finally
+ {
+ ske_UnlockSkin();
+ }
+ return -1;
+}
+
+
+void ske_PreMultiplyChanells(HBITMAP hbmp,BYTE Mult)
+{
+ BITMAP bmp;
+ BOOL flag = FALSE;
+ BYTE * pBitmapBits;
+ DWORD Len;
+ int bh,bw,y,x;
+
+ GetObject(hbmp, sizeof(BITMAP), (LPSTR)&bmp);
+ bh = bmp.bmHeight;
+ bw = bmp.bmWidth;
+ Len = bh*bw*4;
+ flag = (bmp.bmBits == NULL);
+ if (flag)
+ {
+ pBitmapBits = (LPBYTE)malloc(Len);
+ GetBitmapBits(hbmp,Len,pBitmapBits);
+ }
+ else
+ pBitmapBits = (BYTE*)bmp.bmBits;
+ for (y = 0; y < bh; ++y)
+ {
+ BYTE *pPixel = pBitmapBits + bw * 4 * y;
+
+ for (x = 0; x < bw ; ++x)
+ {
+ if (Mult)
+ {
+ pPixel[0] = pPixel[0]*pPixel[3]/255;
+ pPixel[1] = pPixel[1]*pPixel[3]/255;
+ pPixel[2] = pPixel[2]*pPixel[3]/255;
+ }
+ else
+ {
+ pPixel[3] = 255;
+ }
+ pPixel += 4;
+ }
+ }
+ if (flag)
+ {
+ Len = SetBitmapBits(hbmp,Len,pBitmapBits);
+ free (pBitmapBits);
+ }
+ return;
+}
+
+int ske_GetFullFilename(char * buf, char *file, char * skinfolder,BOOL madeAbsolute)
+{
+ char b2[MAX_PATH] = {0};
+ char *SkinPlace = db_get_sa(NULL,SKIN,"SkinFolder");
+ if ( !SkinPlace) SkinPlace = mir_strdup("\\Skin\\default");
+ if (file[0] != '\\' && file[1] != ':')
+ _snprintf(b2, MAX_PATH,"%s\\%s",(skinfolder == NULL)?SkinPlace:((INT_PTR)skinfolder != -1)?skinfolder:"",file);
+ else
+ _snprintf(b2, MAX_PATH,"%s",file);
+ if (madeAbsolute)
+ if (b2[0] == '\\' && b2[1] != '\\')
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)(b2+1), (LPARAM)buf);
+ else
+ CallService(MS_UTILS_PATHTOABSOLUTE, (WPARAM)(b2), (LPARAM)buf);
+ else
+ memcpy(buf,b2,MAX_PATH);
+
+ mir_free(SkinPlace);
+ return 0;
+}
+
+
+static HBITMAP ske_skinLoadGlyphImage(char * szFileName)
+{
+ if ( !g_CluiData.fGDIPlusFail && !wildcmpi(szFileName,"*.tga"))
+ return GDIPlus_LoadGlyphImage(szFileName);
+ else
+ return ske_LoadGlyphImageByDecoders(szFileName);
+}
+
+/*
+This function is required to load TGA to dib buffer myself
+Major part of routines is from http://tfcduke.developpez.com/tutoriel/format/tga/fichiers/tga.c
+*/
+
+static BOOL ske_ReadTGAImageData(void * From, DWORD fromSize, BYTE * destBuf, DWORD bufSize, BOOL RLE)
+{
+ BYTE * pos = destBuf;
+ BYTE * from = fromSize?(BYTE*)From:NULL;
+ FILE * fp = !fromSize?(FILE*)From:NULL;
+ DWORD destCount = 0;
+ DWORD fromCount = 0;
+ if ( !RLE)
+ {
+ while (((from && fromCount < fromSize) || (fp && fromCount < bufSize))
+ && (destCount < bufSize))
+ {
+ BYTE r = from?from[fromCount++]:(BYTE)fgetc(fp);
+ BYTE g = from?from[fromCount++]:(BYTE)fgetc(fp);
+ BYTE b = from?from[fromCount++]:(BYTE)fgetc(fp);
+ BYTE a = from?from[fromCount++]:(BYTE)fgetc(fp);
+ pos[destCount++] = r;
+ pos[destCount++] = g;
+ pos[destCount++] = b;
+ pos[destCount++] = a;
+
+ if (destCount>bufSize) break;
+ if (from) if (fromCount < fromSize) break;
+ }
+ }
+ else
+ {
+ BYTE rgba[4];
+ BYTE packet_header;
+ BYTE *ptr = pos;
+ BYTE size;
+ int i;
+ while (ptr < pos + bufSize)
+ {
+ /* read first byte */
+ packet_header = from?from[fromCount]:(BYTE)fgetc(fp);
+ if (from) from++;
+ size = 1 + (packet_header & 0x7f);
+ if (packet_header & 0x80)
+ {
+ /* run-length packet */
+ if (from)
+ {
+ *((DWORD*)rgba) = *((DWORD*)(from+fromCount));
+ fromCount += 4;
+ }
+ else fread (rgba, sizeof (BYTE), 4, fp);
+ for (i=0; i < size; ++i, ptr += 4)
+ {
+ ptr[2] = rgba[2];
+ ptr[1] = rgba[1];
+ ptr[0] = rgba[0];
+ ptr[3] = rgba[3];
+ }
+ }
+ else
+ { /* not run-length packet */
+ for (i=0; i < size; ++i, ptr += 4)
+ {
+ ptr[0] = from? from[fromCount++]:(BYTE)fgetc (fp);
+ ptr[1] = from? from[fromCount++]:(BYTE)fgetc (fp);
+ ptr[2] = from? from[fromCount++]:(BYTE)fgetc (fp);
+ ptr[3] = from? from[fromCount++]:(BYTE)fgetc (fp);
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+static HBITMAP ske_LoadGlyphImage_TGA(char * szFilename)
+{
+ BYTE *colormap = NULL;
+ int cx = 0,cy = 0;
+ BOOL err = FALSE;
+ tga_header_t header;
+ if ( !szFilename) return NULL;
+ if ( !wildcmpi(szFilename,"*\\*%.tga"))
+ {
+ //Loading TGA image from file
+ FILE *fp;
+ fp = fopen (szFilename, "rb");
+ if ( !fp)
+ {
+ TRACEVAR("error: couldn't open \"%s\"!\n", szFilename);
+ return NULL;
+ }
+ /* read header */
+ fread (&header, sizeof (tga_header_t), 1, fp);
+ if ( (header.pixel_depth != 32)
+ || ((header.image_type != 10) && (header.image_type != 2))
+ )
+ {
+ fclose(fp);
+ return NULL;
+ }
+
+ /*memory allocation */
+ colormap = (BYTE*)malloc(header.width*header.height*4);
+ cx = header.width;
+ cy = header.height;
+ fseek (fp, header.id_lenght, SEEK_CUR);
+ fseek (fp, header.cm_length, SEEK_CUR);
+ err = !ske_ReadTGAImageData((void*)fp, 0, colormap, header.width*header.height*4,header.image_type == 10);
+ fclose(fp);
+ }
+
+
+ else
+ {
+ /* reading from resources IDR_TGA_DEFAULT_SKIN */
+ DWORD size = 0;
+ BYTE * mem;
+ HGLOBAL hRes;
+ HRSRC hRSrc = FindResourceA(g_hInst,MAKEINTRESOURCEA(IDR_TGA_DEFAULT_SKIN),"TGA");
+ if ( !hRSrc) return NULL;
+ hRes = LoadResource(g_hInst,hRSrc);
+ if ( !hRes) return NULL;
+ size = SizeofResource(g_hInst,hRSrc);
+ mem = (BYTE*) LockResource(hRes);
+ if (size>sizeof(header))
+ {
+ tga_header_t * header = (tga_header_t *)mem;
+ if (header->pixel_depth == 32 && (header->image_type == 2 || header->image_type == 10))
+ {
+ colormap = (BYTE*)malloc(header->width*header->height*4);
+ cx = header->width;
+ cy = header->height;
+ ske_ReadTGAImageData((void*)(mem+sizeof(tga_header_t)+header->id_lenght+header->cm_length), size-(sizeof(tga_header_t)+header->id_lenght+header->cm_length), colormap, cx*cy*4,header->image_type == 10);
+ }
+ }
+ FreeResource(hRes);
+ }
+ if (colormap) //create dib section
+ {
+ BYTE * pt;
+ HBITMAP hbmp = ske_CreateDIB32Point(cx,cy,(void**)&pt);
+ if (hbmp) memcpy(pt,colormap,cx*cy*4);
+ free(colormap);
+ return hbmp;
+ }
+ return NULL;
+}
+
+
+//this function is required to load PNG to dib buffer myself
+HBITMAP ske_LoadGlyphImage_Png2Dib(char * szFilename)
+{
+
+ {
+ HANDLE hFile, hMap = NULL;
+ BYTE* ppMap = NULL;
+ long cbFileSize = 0;
+ BITMAPINFOHEADER* pDib;
+ BYTE* pDibBits;
+
+ if ( !ServiceExists( MS_PNG2DIB )) {
+ MessageBox( NULL, TranslateT( "You need an image services plugin to process PNG images." ), TranslateT( "Error" ), MB_OK );
+ return (HBITMAP)NULL;
+ }
+
+ if (( hFile = CreateFileA( szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL )) != INVALID_HANDLE_VALUE )
+ if (( hMap = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL )) != NULL )
+ if (( ppMap = ( BYTE* )MapViewOfFile( hMap, FILE_MAP_READ, 0, 0, 0 )) != NULL )
+ cbFileSize = GetFileSize( hFile, NULL );
+
+ if ( cbFileSize != 0 ) {
+ PNG2DIB param;
+ param.pSource = ppMap;
+ param.cbSourceSize = cbFileSize;
+ param.pResult = &pDib;
+ if ( CallService( MS_PNG2DIB, 0, ( LPARAM )&param ))
+ pDibBits = ( BYTE* )( pDib+1 );
+ else
+ cbFileSize = 0;
+ }
+
+ if ( ppMap != NULL ) UnmapViewOfFile( ppMap );
+ if ( hMap != NULL ) CloseHandle( hMap );
+ if ( hFile != NULL ) CloseHandle( hFile );
+
+ if ( cbFileSize == 0 )
+ return (HBITMAP)NULL;
+
+ {
+ BITMAPINFO* bi = ( BITMAPINFO* )pDib;
+ BYTE *pt = (BYTE*)bi;
+ pt += bi->bmiHeader.biSize;
+ if (bi->bmiHeader.biBitCount != 32)
+ {
+ HDC sDC = GetDC( NULL );
+ HBITMAP hBitmap = CreateDIBitmap( sDC, pDib, CBM_INIT, pDibBits, bi, DIB_PAL_COLORS );
+ SelectObject( sDC, hBitmap );
+ DeleteDC( sDC );
+ GlobalFree( pDib );
+ return hBitmap;
+ }
+ else
+ {
+ BYTE * ptPixels = pt;
+ HBITMAP hBitmap = CreateDIBSection(NULL,bi, DIB_RGB_COLORS, (void **)&ptPixels, NULL, 0);
+ memcpy(ptPixels,pt,bi->bmiHeader.biSizeImage);
+ GlobalFree( pDib );
+ return hBitmap;
+ }
+ }
+ }
+}
+
+static HBITMAP ske_LoadGlyphImageByDecoders(char * szFileName)
+{
+ // Loading image from file by imgdecoder...
+ HBITMAP hBitmap = NULL;
+ char ext[5];
+ BYTE f = 0;
+ LPBYTE pBitmapBits;
+ LPVOID pImg = NULL;
+ LPVOID m_pImgDecoder;
+
+ BITMAP bmpInfo;
+ {
+ int l;
+ l = mir_strlen(szFileName);
+ memmove(ext,szFileName +(l-4),5);
+ }
+ if ( !strchr(szFileName,'%') && !PathFileExistsA(szFileName)) return NULL;
+ if (mir_bool_strcmpi(ext,".tga"))
+ {
+ hBitmap = ske_LoadGlyphImage_TGA(szFileName);
+ f = 1;
+ }
+ else if (ServiceExists("Image/Png2Dib") && mir_bool_strcmpi(ext,".png"))
+ {
+ hBitmap = ske_LoadGlyphImage_Png2Dib(szFileName);
+ GetObject(hBitmap, sizeof(BITMAP), &bmpInfo);
+ f = (bmpInfo.bmBits != NULL);
+ // hBitmap = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)szFileName);
+ // f = 1;
+
+ }
+ else if (hImageDecoderModule == NULL || !mir_bool_strcmpi(ext,".png"))
+ hBitmap = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)szFileName);
+ else
+ {
+ f = 1;
+ ImgNewDecoder(&m_pImgDecoder);
+ if ( !ImgNewDIBFromFile(m_pImgDecoder, szFileName, &pImg))
+ {
+ ImgGetHandle(pImg, &hBitmap, (LPVOID *)&pBitmapBits);
+ ImgDeleteDecoder(m_pImgDecoder);
+ }
+ }
+ if (hBitmap)
+ {
+
+ GetObject(hBitmap, sizeof(BITMAP), &bmpInfo);
+ if (bmpInfo.bmBitsPixel == 32)
+ ske_PreMultiplyChanells(hBitmap,f);
+ else
+ {
+ HDC dc24,dc32;
+ HBITMAP hBitmap32,obmp24,obmp32;
+ dc32 = CreateCompatibleDC(NULL);
+ dc24 = CreateCompatibleDC(NULL);
+ hBitmap32 = ske_CreateDIB32(bmpInfo.bmWidth,bmpInfo.bmHeight);
+ obmp24 = (HBITMAP)SelectObject(dc24,hBitmap);
+ obmp32 = (HBITMAP)SelectObject(dc32,hBitmap32);
+ BitBlt(dc32,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,dc24,0,0,SRCCOPY);
+ SelectObject(dc24,obmp24);
+ SelectObject(dc32,obmp32);
+ mod_DeleteDC(dc24);
+ mod_DeleteDC(dc32);
+ DeleteObject(hBitmap);
+ hBitmap = hBitmap32;
+ ske_PreMultiplyChanells(hBitmap,0);
+ }
+
+ }
+ return hBitmap;
+}
+
+HBITMAP ske_LoadGlyphImage(char * szFileName)
+{
+ // try to find image in loaded
+ DWORD i;
+ HBITMAP hbmp;
+ char szFile [MAX_PATH] = {0};
+ ske_GetFullFilename(szFile,szFileName,g_SkinObjectList.szSkinPlace,TRUE);
+ ske_LockSkin();
+ if (pLoadedImages)
+ {
+ for (i=0; i < dwLoadedImagesCount; i++)
+ {
+ if (mir_bool_strcmpi(pLoadedImages[i].szFileName,szFile))
+ {
+ pLoadedImages[i].dwLoadedTimes++;
+ ske_UnlockSkin();
+ return pLoadedImages[i].hGlyph;
+ }
+ }
+ }
+ // load new image
+ hbmp = ske_skinLoadGlyphImage(szFile);
+ if (hbmp == NULL)
+ {
+ ske_UnlockSkin();
+ return NULL;
+ }
+ // add to loaded list
+ if (dwLoadedImagesCount+1>dwLoadedImagesAlocated)
+ {
+ pLoadedImages = (GLYPHIMAGE*)mir_realloc(pLoadedImages,sizeof(GLYPHIMAGE)*(dwLoadedImagesCount+1));
+ if (pLoadedImages) dwLoadedImagesAlocated++;
+ else
+ {
+ ske_UnlockSkin();
+ return NULL;
+ }
+ }
+ pLoadedImages[dwLoadedImagesCount].dwLoadedTimes = 1;
+ pLoadedImages[dwLoadedImagesCount].hGlyph = hbmp;
+ pLoadedImages[dwLoadedImagesCount].szFileName = mir_strdup(szFile);
+ dwLoadedImagesCount++;
+ ske_UnlockSkin();
+ return hbmp;
+}
+
+int ske_UnloadGlyphImage(HBITMAP hbmp)
+{
+ DWORD i;
+ for (i=0; i < dwLoadedImagesCount; i++)
+ {
+ if (hbmp == pLoadedImages[i].hGlyph)
+ {
+ pLoadedImages[i].dwLoadedTimes--;
+ if (pLoadedImages[i].dwLoadedTimes == 0)
+ {
+ LPGLYPHIMAGE gl = &(pLoadedImages[i]);
+ mir_free_and_nil(gl->szFileName);
+ memmove(&(pLoadedImages[i]),&(pLoadedImages[i+1]),sizeof(GLYPHIMAGE)*(dwLoadedImagesCount-i-1));
+ dwLoadedImagesCount--;
+ DeleteObject(hbmp);
+ if (pLoadedImages && dwLoadedImagesCount == 0)
+ {
+ dwLoadedImagesAlocated = 0;
+ mir_free_and_nil(pLoadedImages);
+ }
+ }
+ return 0;
+ }
+
+ }
+ DeleteObject(hbmp);
+ return 0;
+}
+
+int ske_UnloadSkin(SKINOBJECTSLIST * Skin)
+{
+ DWORD i;
+ ske_LockSkin();
+ ClearMaskList(Skin->pMaskList);
+
+ //clear font list
+ if (gl_plSkinFonts && gl_plSkinFonts->realCount > 0) {
+ for (int i=0; i < gl_plSkinFonts->realCount; i++) {
+ SKINFONT * sf = (SKINFONT *)gl_plSkinFonts->items[i];
+ if (sf) {
+ mir_free(sf->szFontID);
+ DeleteObject(sf->hFont);
+ mir_free(sf);
+ }
+ }
+ List_Destroy(gl_plSkinFonts);
+ mir_free_and_nil(gl_plSkinFonts);
+ }
+
+ mir_free_and_nil(Skin->szSkinPlace);
+ if (Skin->pTextList) List_Destroy(Skin->pTextList);
+ mir_free_and_nil(Skin->pTextList);
+ ModernSkinButtonDeleteAll();
+ if (Skin->dwObjLPAlocated == 0) { ske_UnlockSkin(); return 0;}
+ for (i=0; i < Skin->dwObjLPAlocated; i++)
+ {
+ switch(Skin->pObjects[i].bType)
+ {
+ case OT_GLYPHOBJECT:
+ {
+ GLYPHOBJECT * dt;
+ dt = (GLYPHOBJECT*)Skin->pObjects[i].Data;
+ if (dt->hGlyph && dt->hGlyph != (HBITMAP)-1)
+ ske_UnloadGlyphImage(dt->hGlyph);
+ dt->hGlyph = NULL;
+ mir_free_and_nil(dt->szFileName);
+ {// delete texts
+ int i;
+ if (dt->plTextList && dt->plTextList->realCount>0)
+ {
+ for (i=0; i < dt->plTextList->realCount; i++)
+ {
+ GLYPHTEXT * gt = (GLYPHTEXT *)dt->plTextList->items[i];
+ if (gt) {
+ mir_free(gt->stText);
+ mir_free(gt->stValueText);
+ mir_free(gt->szFontID);
+ mir_free(gt->szGlyphTextID);
+ mir_free(gt);
+ }
+ }
+ List_Destroy(dt->plTextList);
+ mir_free(dt->plTextList);
+ }
+ }
+ mir_free(dt);
+ }
+ break;
+ }
+ mir_free_and_nil(Skin->pObjects[i].szObjectID);
+
+ }
+ mir_free_and_nil(Skin->pObjects);
+ Skin->pTextList = NULL;
+ Skin->dwObjLPAlocated = 0;
+ Skin->dwObjLPReserved = 0;
+ ske_UnlockSkin();
+ return 0;
+}
+
+static void RegisterMaskByParce(const char * szSetting, char * szValue, SKINOBJECTSLIST * pSkin)
+{
+ int i;
+ DWORD ID=atoi(szSetting+1);
+ for (i=0; i < mir_strlen(szValue); i++) if (szValue[i] == ':') break;
+ if (i < mir_strlen(szValue))
+ {
+ char * Obj, *Mask;
+ int res;
+ Mask = szValue+i+1;
+ Obj = (char*)mir_alloc(i+1);
+ strncpy(Obj,szValue,i);
+ Obj[i] = '\0';
+ res = AddStrModernMaskToList(ID,Mask,Obj,pSkin->pMaskList,pSkin);
+ mir_free(Obj);
+ }
+}
+
+static int ske_ProcessLoadindString(const char * szSetting, char *szValue)
+{
+ if ( !pCurrentSkin) return 0;
+ if (szSetting[0] == '$')
+ RegisterObjectByParce((char *)szSetting, szValue);
+ else if (szSetting[0] == '#')
+ RegisterButtonByParce((char *)szSetting,szValue);
+ else if (szSetting[0] == '@')
+ RegisterMaskByParce((char *)szSetting, szValue, pCurrentSkin); ///
+ else if (szSetting[0] == 't')
+ ske_AddParseTextGlyphObject((char*)szSetting,szValue,pCurrentSkin);
+ else if (szSetting[0] == 'f')
+ ske_AddParseSkinFont((char*)szSetting,szValue,pCurrentSkin);
+ else return 0;
+ return 1;
+}
+static int ske_enumdb_SkinObjectsProc (const char *szSetting,LPARAM lParam)
+{
+ char *value;
+ value = db_get_sa(NULL,SKIN,szSetting);
+ ske_ProcessLoadindString(szSetting,value);
+ mir_free_and_nil(value);
+
+ return 0;
+}
+
+static int ske_SortTextGlyphObjectFunc(void * first, void * second)
+{
+ return strcmp(((GLYPHTEXT*)(((int*)first)[0]))->szGlyphTextID,((GLYPHTEXT*)(((int*)second)[0]))->szGlyphTextID);
+}
+
+static void ske_LinkSkinObjects(SKINOBJECTSLIST * pObjectList)
+{
+ DWORD i;
+ // LINK Mask with objects
+ for (i=0; i < pObjectList->pMaskList->dwMaskCnt; i++)
+ {
+ MODERNMASK *mm = &(pObjectList->pMaskList->pl_Masks[i]);
+ void * pObject = (void*) ske_FindObjectByName(mm->szObjectName, OT_ANY, (SKINOBJECTSLIST*) pObjectList);
+ mir_free_and_nil(mm->szObjectName);
+ mm->bObjectFound = TRUE;
+ mm->pObject = pObject;
+ }
+
+ if (pObjectList->pTextList)
+ {
+ int i;
+ // LINK Text with objects
+ for (i=0; i < pObjectList->pTextList->realCount; i++)
+ {
+ GLYPHTEXT * glText;
+ GLYPHOBJECT *globj = NULL;
+ SKINOBJECTDESCRIPTOR * lpobj;
+ glText = (GLYPHTEXT *)pObjectList->pTextList->items[i];
+ lpobj = ske_FindObjectByName(glText->szObjectName,OT_GLYPHOBJECT, pObjectList);
+ mir_free_and_nil(glText->szObjectName);
+ if (lpobj)
+ globj = (GLYPHOBJECT*)lpobj->Data;
+ if (globj)
+ {
+ if ( !globj->plTextList)
+ {
+ globj->plTextList = List_Create(0,1);
+ globj->plTextList->sortFunc = ske_SortTextGlyphObjectFunc;
+ }
+ List_Insert(globj->plTextList,(void*)glText,globj->plTextList->realCount);
+ qsort(globj->plTextList->items,globj->plTextList->realCount,sizeof(void*),(int(*)(const void*, const void*))globj->plTextList->sortFunc);
+ pObjectList->pTextList->items[i] = NULL;
+ }
+ else
+ {
+ GLYPHTEXT *gt = glText;
+ if (gt) {
+ mir_free(gt->stText);
+ mir_free(gt->stValueText);
+ mir_free(gt->szFontID);
+ mir_free(gt->szGlyphTextID);
+ mir_free(gt);
+ }
+ }
+ }
+ List_Destroy(pObjectList->pTextList);
+ mir_free_and_nil(pObjectList->pTextList);
+ }
+}
+// Getting skin objects and masks from DB
+static int ske_GetSkinFromDB(char * szSection, SKINOBJECTSLIST * Skin)
+{
+ if (Skin == NULL) return 0;
+ ske_UnloadSkin(Skin);
+ g_CluiData.fDisableSkinEngine = db_get_b(NULL,"ModernData","DisableEngine", SETTING_DISABLESKIN_DEFAULT);
+ //window borders
+ if (g_CluiData.fDisableSkinEngine) {
+ g_CluiData.LeftClientMargin = 0;
+ g_CluiData.RightClientMargin = 0;
+ g_CluiData.TopClientMargin = 0;
+ g_CluiData.BottomClientMargin = 0;
+ } else {
+ //window borders
+ g_CluiData.LeftClientMargin = (int)db_get_b(NULL,"CLUI","LeftClientMargin",SETTING_LEFTCLIENTMARIGN_DEFAULT);
+ g_CluiData.RightClientMargin = (int)db_get_b(NULL,"CLUI","RightClientMargin",SETTING_RIGHTCLIENTMARIGN_DEFAULT);
+ g_CluiData.TopClientMargin = (int)db_get_b(NULL,"CLUI","TopClientMargin",SETTING_TOPCLIENTMARIGN_DEFAULT);
+ g_CluiData.BottomClientMargin = (int)db_get_b(NULL,"CLUI","BottomClientMargin",SETTING_BOTTOMCLIENTMARIGN_DEFAULT);
+ }
+
+ if (g_CluiData.fDisableSkinEngine) return 0;
+
+ Skin->pMaskList = (LISTMODERNMASK*)mir_alloc(sizeof(LISTMODERNMASK));
+ memset(Skin->pMaskList,0,sizeof(LISTMODERNMASK));
+ Skin->szSkinPlace = db_get_sa(NULL,SKIN,"SkinFolder");
+ if ( !Skin->szSkinPlace || (strchr(Skin->szSkinPlace, '%') && !db_get_b(NULL,SKIN,"Modified",0)))
+ {
+ BOOL bOnlyObjects = FALSE;
+ if (Skin->szSkinPlace && strchr(Skin->szSkinPlace, '%'))
+ bOnlyObjects = TRUE;
+ mir_free(Skin->szSkinPlace);
+ Skin->szSkinPlace = mir_strdup("%Default%");
+ ske_LoadSkinFromResource( bOnlyObjects );
+ }
+ //Load objects
+ {
+ DBCONTACTENUMSETTINGS dbces;
+ pCurrentSkin = Skin;
+ dbces.pfnEnumProc = ske_enumdb_SkinObjectsProc;
+ dbces.szModule = SKIN;
+ dbces.ofsSettings = 0;
+ CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces);
+
+ SortMaskList(pCurrentSkin->pMaskList);
+ ske_LinkSkinObjects(pCurrentSkin);
+ }
+ //Load Masks
+ return 0;
+}
+
+//surrogate to be called from outside
+void ske_LoadSkinFromDB(void)
+{
+ ske_GetSkinFromDB(SKIN,&g_SkinObjectList);
+ g_CluiData.dwKeyColor = db_get_dw(NULL,"ModernSettings","KeyColor",(DWORD)SETTING_KEYCOLOR_DEFAULT);
+}
+
+//
+
+static int ske_LoadSkinFromResource(BOOL bOnlyObjects)
+{
+
+ IniParser parser(g_hInst, MAKEINTRESOURCEA(IDR_MSF_DEFAULT_SKIN), "MSF", bOnlyObjects ? IniParser::FLAG_ONLY_OBJECTS : IniParser::FLAG_WITH_SETTINGS );
+ if ( !parser.CheckOK()) return 0;
+
+ ske_DeleteAllSettingInSection("ModernSkin");
+ db_set_s(NULL,SKIN,"SkinFolder","%Default%");
+ db_set_s(NULL,SKIN,"SkinFile","%Default%");
+ parser.Parse( IniParser::WriteStrToDb, 0 );
+ return 0;
+}
+
+//Load data from ini file
+int ske_LoadSkinFromIniFile(TCHAR * szFileName, BOOL bOnlyObjects)
+{
+ TCHAR skinFolder[MAX_PATH] = {0};
+ TCHAR skinFile[MAX_PATH] = {0};
+ if (_tcschr(szFileName,_T('%')))
+ return ske_LoadSkinFromResource( bOnlyObjects );
+
+ IniParser parser( szFileName, bOnlyObjects ? IniParser::FLAG_ONLY_OBJECTS : IniParser::FLAG_WITH_SETTINGS );
+ if ( !parser.CheckOK()) return 0;
+
+ ske_DeleteAllSettingInSection("ModernSkin");
+ IniParser::GetSkinFolder(szFileName,skinFolder);
+ CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)szFileName, (LPARAM)skinFile);
+
+ db_set_ws(NULL,SKIN,"SkinFolder", skinFolder);
+ db_set_ws(NULL,SKIN,"SkinFile", skinFile);
+
+ parser.Parse( IniParser::WriteStrToDb, 1 );
+
+ return 0;
+}
+
+
+static int ske_enumdb_SkinSectionDeletionProc (const char *szSetting,LPARAM lParam)
+{
+
+ if (szSetting == NULL){return(0);};
+ nArrayLen++;
+ pszSettingName = (char **)realloc(pszSettingName,nArrayLen*sizeof(char *));
+ pszSettingName[nArrayLen-1] = _strdup(szSetting);
+ return(0);
+};
+static int ske_DeleteAllSettingInSection(char * SectionName)
+{
+ DBCONTACTENUMSETTINGS dbces;
+ nArrayLen = 0;
+ pszSettingName = NULL;
+ dbces.pfnEnumProc = ske_enumdb_SkinSectionDeletionProc;
+ dbces.szModule = SectionName;
+ dbces.ofsSettings = 0;
+
+ CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces);
+
+ //delete all settings
+ if (nArrayLen == 0){return(0);};
+ {
+ int i;
+ for (i=0;i < nArrayLen;i++)
+ {
+ db_unset(0,SectionName,pszSettingName[i]);
+ free(pszSettingName[i]);
+ };
+ free(pszSettingName);
+ pszSettingName = NULL;
+ nArrayLen = 0;
+ };
+ return(0);
+};
+
+
+BOOL ske_TextOutA(HDC hdc, int x, int y, char * lpString, int nCount)
+{
+ TCHAR *buf = (TCHAR *)mir_alloc((2+nCount)*sizeof(TCHAR));
+ BOOL res;
+ MultiByteToWideChar(CallService( MS_LANGPACK_GETCODEPAGE, 0, 0 ), 0, lpString, -1, buf, (2+nCount)*sizeof(TCHAR));
+ res = ske_TextOut(hdc,x,y,buf,nCount);
+ mir_free(buf);
+ return res;
+}
+
+BOOL ske_TextOut(HDC hdc, int x, int y, LPCTSTR lpString, int nCount)
+{
+ int ta;
+ SIZE sz;
+ RECT rc = {0};
+ if ( !g_CluiData.fGDIPlusFail && 0) ///text via gdi+
+ {
+ TextOutWithGDIp(hdc,x,y,lpString,nCount);
+ return 0;
+ }
+ else
+
+ {
+ // return TextOut(hdc, x,y,lpString,nCount);
+ GetTextExtentPoint32(hdc,lpString,nCount,&sz);
+ ta = GetTextAlign(hdc);
+ SetRect(&rc,x,y,x+sz.cx,y+sz.cy);
+ ske_DrawText(hdc,lpString,nCount,&rc,DT_NOCLIP|DT_SINGLELINE|DT_LEFT);
+ }
+ return 1;
+}
+
+static INT_PTR ske_Service_AlphaTextOut(WPARAM wParam,LPARAM lParam)
+{
+ if ( !wParam) return 0;
+ {
+ AlphaTextOutParams ap = *(AlphaTextOutParams*)wParam;
+ return ske_AlphaTextOut(ap.hDC,ap.lpString,ap.nCount,ap.lpRect,ap.format,ap.ARGBcolor);
+ }
+}
+
+static __inline void ske_SetMatrix( sbyte * matrix,
+ sbyte a, sbyte b, sbyte c,
+ sbyte d, sbyte e, sbyte f,
+ sbyte g, sbyte h, sbyte i)
+{
+ matrix[0] = a; matrix[1] = b; matrix[2] = c;
+ matrix[3] = d; matrix[4] = e; matrix[5] = f;
+ matrix[6] = g; matrix[7] = h; matrix[8] = i;
+}
+
+static void ske_SetTextEffect(BYTE EffectID, DWORD FirstColor, DWORD SecondColor)
+{
+ if (EffectID>MAXPREDEFINEDEFFECTS) return;
+ if (EffectID == -1) meCurrentEffect.EffectID = -1;
+ else
+ {
+ meCurrentEffect.EffectID = EffectID;
+ meCurrentEffect.EffectMatrix = ModernEffectsEnum[EffectID];
+ meCurrentEffect.EffectColor1 = FirstColor;
+ meCurrentEffect.EffectColor2 = SecondColor;
+ }
+}
+
+BOOL ske_ResetTextEffect(HDC hdc)
+{
+ int i;
+ if ( !pEffectStack || !pEffectStack->realCount) return TRUE;
+ for (i=0; i < pEffectStack->realCount; i++)
+ if (pEffectStack->items[i] && ((EFFECTSSTACKITEM*)(pEffectStack->items[i]))->hdc == hdc)
+ {
+ EFFECTSSTACKITEM * effect = (EFFECTSSTACKITEM*)(pEffectStack->items[i]);
+ mir_free(effect);
+ List_Remove(pEffectStack,i);
+ return TRUE;
+ }
+ return FALSE;
+};
+
+BOOL ske_SelectTextEffect(HDC hdc, BYTE EffectID, DWORD FirstColor, DWORD SecondColor)
+{
+ if (EffectID>MAXPREDEFINEDEFFECTS) return 0;
+ if (EffectID == -1) return ske_ResetTextEffect(hdc);
+ if ( !pEffectStack)
+ {
+ pEffectStack = List_Create(0,1);
+ }
+ {
+ int i;
+ for (i=0; i < pEffectStack->realCount; i++)
+ if (pEffectStack->items[i] && ((EFFECTSSTACKITEM*)(pEffectStack->items[i]))->hdc == hdc)
+ {
+ EFFECTSSTACKITEM * effect = (EFFECTSSTACKITEM*)(pEffectStack->items[i]);
+ effect->EffectID = EffectID;
+ effect->FirstColor = FirstColor;
+ effect->SecondColor = SecondColor;
+ return TRUE;
+ }
+ }
+ {
+ EFFECTSSTACKITEM * effect = (EFFECTSSTACKITEM *) mir_alloc(sizeof(EFFECTSSTACKITEM));
+ effect->hdc = hdc;
+ effect->EffectID = EffectID;
+ effect->FirstColor = FirstColor;
+ effect->SecondColor = SecondColor;
+ List_Insert(pEffectStack, effect, 0);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static BOOL ske_GetTextEffect(HDC hdc, MODERNEFFECT * modernEffect)
+{
+ int i=0;
+ if ( !pEffectStack || !pEffectStack->realCount) return FALSE;
+ if ( !modernEffect) return FALSE;
+ for (i=0; i < pEffectStack->realCount; i++)
+ if (pEffectStack->items[i] && ((EFFECTSSTACKITEM*)(pEffectStack->items[i]))->hdc == hdc)
+ {
+ EFFECTSSTACKITEM * effect = (EFFECTSSTACKITEM*)(pEffectStack->items[i]);
+ modernEffect->EffectID = effect->EffectID;
+ modernEffect->EffectColor1 = effect->FirstColor;
+ modernEffect->EffectColor2 = effect->SecondColor;
+ modernEffect->EffectMatrix = ModernEffectsEnum[effect->EffectID];
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static BOOL ske_DrawTextEffect(BYTE* destPt,BYTE* maskPt, DWORD width, DWORD height, MODERNEFFECT *effect)
+{
+ sbyte *buf;
+ sbyte *outbuf;
+ sbyte *bufline, *buflineTop, *buflineMid;
+ int sign = 0;
+ BYTE *maskline,*destline;
+ BYTE al,rl,gl,bl,ad,rd,gd,bd;
+ int k = 0;
+ DWORD x,y;
+ sbyte *matrix;
+ BYTE mcTopStart;
+ BYTE mcBottomEnd;
+ BYTE mcLeftStart;
+ BYTE mcRightEnd;
+ BYTE effectCount;
+ int minX = width;
+ int maxX = 0;
+ int minY = height;
+ int maxY = 0;
+ if (effect->EffectID == 0xFF) return FALSE;
+ if ( !width || ! height) return FALSE;
+ if ( !destPt) return FALSE;
+ buf = (sbyte*)malloc(width*height*sizeof(BYTE));
+ {
+ matrix = effect->EffectMatrix.matrix;
+ mcTopStart = 2-effect->EffectMatrix.topEffect;
+ mcBottomEnd = 3+effect->EffectMatrix.bottomEffect;
+ mcLeftStart = 2-effect->EffectMatrix.leftEffect;
+ mcRightEnd = 3+effect->EffectMatrix.rightEffect;
+ effectCount = effect->EffectMatrix.cycleCount;
+ }
+ al = 255-((BYTE)(effect->EffectColor1>>24));
+ rl = GetRValue(effect->EffectColor1);
+ gl = GetGValue(effect->EffectColor1);
+ bl = GetBValue(effect->EffectColor1);
+ rd = GetRValue(effect->EffectColor2);
+ gd = GetGValue(effect->EffectColor2);
+ bd = GetBValue(effect->EffectColor2);
+ ad = 255-((BYTE)(effect->EffectColor2>>24));
+ rd = GetRValue(effect->EffectColor2);
+ gd = GetGValue(effect->EffectColor2);
+ bd = GetBValue(effect->EffectColor2);
+
+ //Fill buffer by mid values of image
+ for (y = 0; y < height; y++)
+ {
+ bufline = buf+y*width;
+ maskline = maskPt+((y*width) << 2);
+ for (x = 0; x < width; x++)
+ {
+ BYTE a = (sbyte)(DWORD)((maskline[0]+maskline[2]+maskline[1]+maskline[1])>>4);
+ *bufline = a;
+ if (a != 0)
+ {
+ minX = min((int)x,minX);
+ minY = min((int)y,minY);
+ maxX = max((int)x,maxX);
+ maxY = max((int)y,maxY);
+ }
+ bufline++;
+ maskline += 4;
+ }
+ }
+ //Here perform effect on buffer and place results to outbuf
+ for (k = 0; k < (effectCount&0x7F); k++)
+ {
+ minX = max( 0, minX + mcLeftStart - 2 );
+ minY = max( 0, minY + mcTopStart - 2 );
+ maxX = min((int)width, maxX + mcRightEnd - 1 );
+ maxY = min((int)height, maxY + mcBottomEnd - 1 );
+
+ outbuf = (sbyte*)malloc(width*height*sizeof(sbyte));
+ memset(outbuf,0,width*height*sizeof(sbyte));
+ for (y = (DWORD)minY; y < (DWORD)maxY; y++)
+ {
+ int val;
+ bufline = outbuf+y*width+minX;
+ buflineMid = buf+y*width+minX;
+ for (x = (DWORD)minX; x < (DWORD)maxX; x++)
+ {
+ int matrixHor,matrixVer;
+ val = 0;
+ for (matrixVer = mcTopStart; matrixVer < mcBottomEnd; matrixVer++)
+ {
+ int buflineStep = width*(matrixVer-2);
+ int as = y+matrixVer-2;
+ sbyte * buflineTopS = NULL;
+ if (as >= 0 && (DWORD)as < height) buflineTopS = buflineMid+buflineStep;
+
+ for (matrixHor = mcLeftStart; matrixHor < mcRightEnd;matrixHor++)
+ {
+ int a = as;
+ buflineTop = buflineTopS;
+ a = x+matrixHor-2;
+ if (buflineTop && a >= 0 && (DWORD)a < width) buflineTop += matrixHor-2;
+ else buflineTop = NULL;
+ if (buflineTop)
+ val += ((*buflineTop)*matrix[matrixVer*5+matrixHor]);
+ }
+ }
+ val = (val+1)>>5;
+ *bufline = (sbyte)((val>127)?127:(val < -125)?-125:val);
+ bufline++;
+ buflineMid++;
+ }
+ }
+ free(buf);
+ buf = outbuf;
+ }
+ {
+ BYTE r1,b1,g1,a1;
+ b1 = bl; r1 = rl; g1 = gl; a1 = al; sign = 1;
+ //perform out to dest
+ for (y = 0; y < height; y++)
+ {
+ bufline = buf+y*width;
+ destline = destPt+((y*width) << 2);
+ for (x = 0; x < width; x++)
+ {
+ sbyte val = *bufline;
+ BYTE absVal = ((val < 0)?-val:val);
+
+ if (val != 0)
+ {
+ if (val>0 && sign < 0)
+ { b1 = bl; r1 = rl; g1 = gl; a1 = al; sign = 1;}
+ else if (val < 0 && sign>0)
+ { b1 = bd; r1 = rd; g1 = gd; a1 = ad; sign = -1;}
+
+ absVal = absVal*a1/255;
+
+ destline[0] = ((destline[0]*(128-absVal))+absVal*b1)>>7;
+ destline[1] = ((destline[1]*(128-absVal))+absVal*g1)>>7;
+ destline[2] = ((destline[2]*(128-absVal))+absVal*r1)>>7;
+ destline[3] += ((255-destline[3])*(a1*absVal))/32640;
+ }
+ bufline++;
+ destline += 4;
+ }
+ }
+ free(buf);
+ }
+ return FALSE;
+}
+
+static int ske_AlphaTextOut (HDC hDC, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format, DWORD ARGBcolor)
+{
+ if ( !( lpString && lpRect ))
+ {
+ DebugBreak();
+ return 0;
+ }
+
+ // Step first fill fast calc correction tables:
+ static bool _tables_empty = true;
+ static BYTE gammaTbl[256]; // Gamma correction table
+ static WORD blueMulTbl[256]; // blue coefficient multiplication table
+ static WORD greenMulTbl[256]; // green coefficient multiplication table
+ static WORD redMulTbl[256]; // red coefficient multiplication table
+ if ( _tables_empty )
+ {
+ // fill tables
+ double gammaCfPw = 1000 / (double)DBGetContactSettingRangedWord(NULL,"ModernData","AlphaTextOutGamma", 700, 1, 5000 );
+ BYTE blueCf = db_get_b(NULL,"ModernData","AlphaTextOutBlueCorrection", 28 );
+ BYTE redCf = db_get_b(NULL,"ModernData","AlphaTextOutRed Correction", 77 );
+ BYTE greenCf = db_get_b(NULL,"ModernData","AlphaTextOutGreen Correction", 151 );
+
+ for ( int i=0; i < 256; i++ )
+ {
+ gammaTbl[i] = (BYTE)( 255 * pow((double)i / 255, gammaCfPw ));
+ blueMulTbl[i] = i * blueCf;
+ redMulTbl[i] = i * redCf;
+ greenMulTbl[i] = i * greenCf;
+ }
+ }
+
+ // Calc len of input string
+ if ( nCount == -1 ) nCount = lstrlen( lpString );
+
+ // retrieve destination bitmap bits
+ HBITMAP hDestBitmap = (HBITMAP) GetCurrentObject( hDC, OBJ_BITMAP );
+ BITMAP bmpDest;
+ GetObject( hDestBitmap, sizeof(BITMAP), &bmpDest );
+
+ BOOL destHasNotDIB = FALSE;
+ BYTE * pDestBits = NULL;
+ if ( bmpDest.bmBits == NULL )
+ {
+ destHasNotDIB = TRUE;
+ pDestBits = (BYTE*) malloc ( bmpDest.bmHeight * bmpDest.bmWidthBytes );
+ GetBitmapBits( hDestBitmap, bmpDest.bmHeight*bmpDest.bmWidthBytes, pDestBits );
+ }
+ else
+ pDestBits = (BYTE*)bmpDest.bmBits;
+
+ BOOL isDest16bit = ( bmpDest.bmBitsPixel ) != 32;
+
+
+ // Creating offscreen buffer
+ HDC hOffscreenDC = CreateCompatibleDC( hDC );
+
+ // Font to be used to draw text
+ HFONT hFont = (HFONT)GetCurrentObject( hDC, OBJ_FONT);
+ HFONT hOldOffscreenFont = (HFONT)SelectObject( hOffscreenDC, hFont );
+
+ // Calculating text geometric size
+ RECT workRect = *lpRect;
+ int workRectWidth = workRect.right - workRect.left;
+ int workRectHeight = workRect.bottom - workRect.top;
+
+ if ( workRectWidth <= 0 || workRectHeight <= 0 )
+ return 0;
+
+ SIZE textSize;
+ GetTextExtentPoint32( hOffscreenDC, lpString, nCount, &textSize );
+
+ LPCTSTR lpWorkString = lpString;
+ BOOL bNeedFreeWorkString = FALSE;
+
+ // if we need to cut the text with ellipsis
+ if (( format&DT_END_ELLIPSIS ) && textSize.cx > workRectWidth )
+ {
+ // Calc geometric width of ellipsis
+ SIZE szEllipsis;
+ GetTextExtentPoint32A(hOffscreenDC,"...",3,&szEllipsis);
+ szEllipsis.cx++; // CORRECTION: some width correction
+
+ // Calc count of visible chars
+ int visibleCharCount = nCount;
+ if ( workRectWidth > szEllipsis.cx)
+ {
+ GetTextExtentExPoint( hOffscreenDC, lpString, nCount,
+ workRectWidth - szEllipsis.cx,
+ &visibleCharCount, NULL, &textSize );
+ }
+ else
+ {
+ GetTextExtentExPoint( hOffscreenDC, lpString, nCount,
+ 0, &visibleCharCount, NULL, &textSize);
+ }
+
+ // replace end of string by elipsis
+ bNeedFreeWorkString = TRUE;
+ lpWorkString = (TCHAR*) malloc(( visibleCharCount + 4) * sizeof(TCHAR));
+
+ memcpy((void*) lpWorkString, lpString, visibleCharCount * sizeof(TCHAR));
+ memcpy((void*) ( lpWorkString + visibleCharCount ), _T("..."), 4 * sizeof(TCHAR)); // 3 + 1
+
+ nCount = visibleCharCount + 3;
+ }
+
+ // Calc sizes and offsets
+
+ textSize.cx += 2; // CORRECTION: for italic
+
+ int drx = 0; // x-axis offset of draw point
+
+ if ( workRectWidth > textSize.cx )
+ {
+ if ( format & ( DT_RIGHT | DT_RTLREADING ))
+ {
+ drx = workRectWidth - textSize.cx;
+ }
+ else if ( format & DT_CENTER )
+ {
+ drx = ( workRectWidth - textSize.cx ) >> 1;
+ }
+ }
+ else
+ {
+ textSize.cx = workRectWidth;
+ }
+
+ int dry = 0; // y-axis offset of draw point
+
+ if ( workRectHeight > textSize.cy )
+ {
+ if ( format & DT_BOTTOM )
+ {
+ dry = workRectHeight - textSize.cy;
+ }
+ else if ( format & DT_VCENTER )
+ {
+ dry = ( workRectHeight - textSize.cy ) >> 1;
+ }
+ }
+ else
+ {
+ textSize.cy = workRectHeight;
+ }
+
+ textSize.cx += 4; // CORRECTION: for effects ???
+ textSize.cy += 4; // CORRECTION: for effects ???
+
+ if ( textSize.cx > 0 && textSize.cy > 0 ) // Ok we need to paint
+ {
+ // probably here are mess ofscreen and temp buff dc
+
+ //Create bitmap image for offscreen
+ BYTE * bits = NULL;
+ HBITMAP hbmp = ske_CreateDIB32Point( textSize.cx, textSize.cy, (void**)&bits );
+ if ( bits != NULL )
+ {
+ HBITMAP holdbmp = (HBITMAP)SelectObject( hOffscreenDC, hbmp );
+
+ //Create buffer bitmap image for temp text
+ BYTE * bufbits = NULL;
+ HBITMAP bufbmp = ske_CreateDIB32Point( textSize.cx, textSize.cy, (void**)&bufbits );
+ if ( bufbits != NULL )
+ {
+ HDC bufDC = CreateCompatibleDC( hDC );
+ HBITMAP bufoldbmp = (HBITMAP)SelectObject( bufDC, bufbmp );
+ HFONT hOldBufFont = (HFONT)SelectObject( bufDC, hFont );
+ SetBkColor( bufDC, RGB( 0, 0, 0 ));
+ SetTextColor( bufDC,RGB(255,255,255));
+
+ // Copy from destination to temp buffer
+ BitBlt( hOffscreenDC, 0, 0, textSize.cx, textSize.cy, hDC, workRect.left + drx - 2, workRect.top + dry - 2, SRCCOPY );
+
+ //Draw text on offscreen bitmap
+ TextOut( bufDC, 2, 2, lpWorkString, nCount);
+
+ MODERNEFFECT effect;
+ if (ske_GetTextEffect( hDC, &effect ))
+ ske_DrawTextEffect( bits, bufbits, textSize.cx, textSize.cy, &effect );
+
+ //RenderText
+ RECT drawRect;
+ drawRect.left = 0; drawRect.top = 0;
+ drawRect.right = textSize.cx;
+ drawRect.bottom = textSize.cy;
+
+ DWORD x,y;
+ DWORD width = textSize.cx;
+ DWORD heigh = textSize.cy;
+
+ BYTE * pDestScanLine;
+ BYTE * pBufScanLine;
+ BYTE * pix;
+ BYTE * bufpix;
+
+ BYTE al = 255 - ((BYTE)( ARGBcolor >> 24 ));
+ BYTE r = GetRValue( ARGBcolor );
+ BYTE g = GetGValue( ARGBcolor );
+ BYTE b = GetBValue( ARGBcolor );
+
+ for ( y = 2; y < heigh - 2; y++ )
+ {
+ int lineBytes = y * (width << 2);
+
+ pDestScanLine = bits + lineBytes;
+ pBufScanLine = bufbits + lineBytes;
+
+ for ( x = 2; x < width - 2; x++)
+ {
+ pix = pDestScanLine + ( x << 2 );
+ bufpix = pBufScanLine + ( x << 2 );
+
+ // Monochromatic
+ BYTE bx = gammaTbl[ bufpix[0] ];
+ BYTE gx = gammaTbl[ bufpix[1] ];
+ BYTE rx = gammaTbl[ bufpix[2] ];
+
+ if ( al != 255 )
+ {
+ bx *= al/255;
+ gx *= al/255;
+ rx *= al/255;
+ }
+ BYTE ax = (BYTE)(( (DWORD)rx*77 + (DWORD)gx * 151 + (DWORD)bx *28 + 128 ) / 256 );
+
+ if (ax)
+ {
+ //Normalize components to gray
+ BYTE axx = 255 - (( r + g + b ) >> 2 ) ; // Coefficient of grayance, more white font - more gray edges
+ WORD atx = ax * (255 - axx);
+ bx = ( atx + bx * axx )/255;
+ gx = ( atx + gx * axx )/255;
+ rx = ( atx + rx * axx )/255;
+
+ short rrx, grx, brx;
+ brx = (short)((b-pix[0])*bx/255);
+ grx = (short)((g-pix[1])*gx/255);
+ rrx = (short)((r-pix[2])*rx/255);
+
+ pix[0] += brx;
+ pix[1] += grx;
+ pix[2] += rrx;
+ pix[3] = (BYTE)(ax+(BYTE)(255-ax)*pix[3]/255);
+ }
+ }
+ }
+
+ //Blit to destination
+ BitBlt( hDC, workRect.left + drx - 2, workRect.top + dry - 2, textSize.cx, textSize.cy, hOffscreenDC, 0, 0, SRCCOPY );
+
+ //free resources
+ SelectObject(bufDC,bufoldbmp);
+ DeleteObject(bufbmp);
+ SelectObject(bufDC, hOldBufFont );
+ mod_DeleteDC(bufDC);
+ }
+ SelectObject(hOffscreenDC,holdbmp);
+ DeleteObject(hbmp);
+ }
+ }
+
+ // Final cleanup
+ SelectObject( hOffscreenDC, hOldOffscreenFont );
+ DeleteDC( hOffscreenDC );
+
+ if ( destHasNotDIB )
+ free( pDestBits );
+
+ if ( bNeedFreeWorkString )
+ free((void*)lpWorkString );
+
+ return 0;
+}
+
+static int ske_DrawTextWithEffectWorker( HDC hdc, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format, MODERNFONTEFFECT * effect )
+{
+ if (format&DT_CALCRECT) return DrawText(hdc,lpString,nCount,lpRect,format);
+
+ if (format&DT_RTLREADING) SetTextAlign(hdc,TA_RTLREADING);
+ DWORD color = GetTextColor(hdc);
+
+ RECT r = *lpRect;
+ OffsetRect(&r,1,1);
+ DWORD form = format;
+ if ( effect && effect->effectIndex )
+ ske_SelectTextEffect( hdc, effect->effectIndex - 1, effect->baseColour, effect->secondaryColour );
+
+ int res = ske_AlphaTextOut(hdc, lpString, nCount, lpRect, form, color );
+
+ if ( effect && effect->effectIndex )
+ ske_ResetTextEffect( hdc );
+
+ return res;
+}
+
+INT_PTR ske_Service_DrawTextWithEffect( WPARAM wParam, LPARAM lParam )
+{
+ DrawTextWithEffectParam * p = ( DrawTextWithEffectParam * ) wParam;
+ if ( p->cbSize != sizeof(DrawTextWithEffectParam))
+ return FALSE;
+ return ske_DrawTextWithEffectWorker( p->hdc, p->lpchText, p->cchText, p->lprc, p->dwDTFormat, p->pEffect );
+}
+
+BOOL ske_DrawTextA(HDC hdc, char * lpString, int nCount, RECT * lpRect, UINT format)
+{
+ TCHAR *buf = mir_a2u(lpString);
+ BOOL res;
+ res = ske_DrawText(hdc,buf,nCount,lpRect,format);
+ mir_free(buf);
+ return res;
+}
+
+
+BOOL ske_DrawText(HDC hdc, LPCTSTR lpString, int nCount, RECT * lpRect, UINT format)
+{
+ DWORD form = 0, color = 0;
+ RECT r = *lpRect;
+ OffsetRect(&r,1,1);
+ if (format&DT_RTLREADING) SetTextAlign(hdc,TA_RTLREADING);
+ if (format&DT_CALCRECT) return DrawText(hdc,lpString,nCount,lpRect,format);
+ if (format&DT_FORCENATIVERENDER || g_CluiData.fDisableSkinEngine)
+ return DrawText(hdc,lpString,nCount,lpRect,format&~DT_FORCENATIVERENDER);
+ form = format;
+ color = GetTextColor(hdc);
+ if ( !g_CluiData.fGDIPlusFail && 0) ///text via gdi+
+ {
+ TextOutWithGDIp(hdc,lpRect->left,lpRect->top,lpString,nCount);
+ return 0;
+ }
+ return ske_AlphaTextOut(hdc,lpString,nCount,lpRect,form,color);
+}
+
+HICON ske_ImageList_GetIcon(HIMAGELIST himl, int i, UINT fStyle)
+{
+ IMAGEINFO imi = {0};
+ BITMAP bm = {0};
+ if ( IsWinVerXPPlus() && i != -1 )
+ {
+ ImageList_GetImageInfo(himl,i,&imi);
+ GetObject(imi.hbmImage,sizeof(bm),&bm);
+ if (bm.bmBitsPixel == 32) //stupid bug of Microsoft
+ // Icons bitmaps are not premultiplied
+ // So Imagelist_AddIcon - premultiply alpha
+ // But incorrect - it is possible that alpha will
+ // be less than color and
+ // ImageList_GetIcon will return overflowed colors
+ // TODO: Direct draw Icon from imagelist without
+ // extracting of icon
+ {
+ BYTE * bits = NULL;
+ bits = (BYTE*)bm.bmBits;
+ if ( !bits)
+ {
+ bits = (BYTE*)malloc(bm.bmWidthBytes*bm.bmHeight);
+ GetBitmapBits(imi.hbmImage,bm.bmWidthBytes*bm.bmHeight,bits);
+ }
+ {
+ int iy;
+ BYTE *bcbits;
+ int wb = ((imi.rcImage.right-imi.rcImage.left)*bm.bmBitsPixel>>3);
+ bcbits = bits+(bm.bmHeight-imi.rcImage.bottom)*bm.bmWidthBytes+(imi.rcImage.left*bm.bmBitsPixel>>3);
+ for (iy = 0; iy < imi.rcImage.bottom-imi.rcImage.top; iy++)
+ {
+ int x;
+ // Dummy microsoft fix - alpha can be less than r,g or b
+ // Looks like color channels in icons should be non-premultiplied with alpha
+ // But AddIcon store it premultiplied (incorrectly cause can be Alpha == 7F, but R,G or B == 80
+ // So i check that alpha is 0x7F and set it to 0x80
+ DWORD *c = ((DWORD*)bcbits);
+ for (x = 0;x < imi.rcImage.right-imi.rcImage.left; x++)
+ {
+ DWORD val = *c;
+ BYTE a = (BYTE)((val)>>24);
+ if (a != 0)
+ {
+ BYTE r = (BYTE)((val&0xFF0000)>>16);
+ BYTE g = (BYTE)((val&0xFF00)>>8);
+ BYTE b = (BYTE)(val&0xFF);
+ if (a < r || a < g || a < b)
+ {
+ a = max(max(r,g),b);
+ val = a << 24|r << 16|g << 8|b;
+ *c = val;
+ }
+ }
+ c++;
+ }
+ bcbits += bm.bmWidthBytes;
+ }
+ }
+ if ( !bm.bmBits)
+ {
+ SetBitmapBits(imi.hbmImage,bm.bmWidthBytes*bm.bmHeight,bits);
+ free(bits);
+ }
+ }
+ }
+ return ImageList_GetIcon(himl,i,ILD_NORMAL);
+}
+
+////////////////////////////////////////////////////////////////////////////
+// This creates new dib image from Imagelist icon ready to alphablend it
+
+HBITMAP ske_ExtractDIBFromImagelistIcon( HIMAGELIST himl,int index, int * outWidth, int * outHeight)
+{
+ return NULL;
+}
+
+BOOL ske_ImageList_DrawEx( HIMAGELIST himl,int i,HDC hdcDst,int x,int y,int dx,int dy,COLORREF rgbBk,COLORREF rgbFg,UINT fStyle)
+{
+ //the routine to directly draw icon from image list without creating icon from there - should be some faster
+
+ if (i < 0) return FALSE;
+
+ if (g_CluiData.fDisableSkinEngine)
+ return ImageList_DrawEx( himl, i, hdcDst, x, y, dx, dy, rgbBk, rgbFg, fStyle);
+
+ BYTE alpha;
+ if (fStyle&ILD_BLEND25) alpha = 64;
+ else if (fStyle&ILD_BLEND50) alpha = 128;
+ else alpha = 255;
+
+ HICON hIcon = ske_ImageList_GetIcon(himl,i,ILD_NORMAL);
+ if (hIcon)
+ {
+ ske_DrawIconEx(hdcDst,x,y,hIcon,dx?dx:GetSystemMetrics(SM_CXSMICON),dy?dy:GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL|(alpha << 24));
+ DestroyIcon(hIcon);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static INT_PTR ske_Service_DrawIconEx(WPARAM wParam,LPARAM lParam)
+{
+ DrawIconFixParam *p = (DrawIconFixParam*)wParam;
+ if ( !p) return 0;
+ return ske_DrawIconEx(p->hdc,p->xLeft,p->yTop,p->hIcon,p->cxWidth,p->cyWidth,p->istepIfAniCur,p->hbrFlickerFreeDraw,p->diFlags);
+}
+
+
+BOOL ske_DrawIconEx(HDC hdcDst,int xLeft,int yTop,HICON hIcon,int cxWidth,int cyWidth, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags)
+{
+
+ ICONINFO ici;
+ BYTE alpha = (BYTE)((diFlags&0xFF000000)>>24);
+
+
+ HDC imDC;
+ HBITMAP oldBmp, imBmp,tBmp;
+ BITMAP imbt,immaskbt;
+ BYTE * imbits;
+ BYTE * imimagbits;
+ BYTE * immaskbits;
+ DWORD cx,cy,icy;
+ BYTE *t1, *t2, *t3;
+
+ BOOL NoDIBImage = FALSE;
+ //lockimagelist
+ BYTE hasmask = FALSE;
+ BYTE no32bit = FALSE;
+ BYTE noMirrorMask = FALSE;
+ BYTE hasalpha = FALSE;
+ alpha = alpha?alpha:255;
+
+ if ( g_CluiData.fDisableSkinEngine && !(diFlags&0x80))
+ return DrawIconEx(hdcDst,xLeft,yTop,hIcon,cxWidth,cyWidth,istepIfAniCur,hbrFlickerFreeDraw,diFlags&0xFFFF7F);
+
+ if ( !GetIconInfo(hIcon,&ici)) return 0;
+
+ GetObject(ici.hbmColor,sizeof(BITMAP),&imbt);
+ if (imbt.bmWidth*imbt.bmHeight == 0)
+ {
+ DeleteObject(ici.hbmColor);
+ DeleteObject(ici.hbmMask);
+ return 0;
+ }
+ GetObject(ici.hbmMask,sizeof(BITMAP),&immaskbt);
+ cy = imbt.bmHeight;
+
+ if (imbt.bmBitsPixel != 32)
+ {
+ HDC tempDC1;
+ HBITMAP otBmp;
+ no32bit = TRUE;
+ tempDC1 = CreateCompatibleDC(hdcDst);
+ tBmp = ske_CreateDIB32(imbt.bmWidth,imbt.bmHeight);
+ if (tBmp)
+ {
+ GetObject(tBmp,sizeof(BITMAP),&imbt);
+ otBmp = (HBITMAP)SelectObject(tempDC1,tBmp);
+ DrawIconEx(tempDC1,0,0,hIcon,imbt.bmWidth,imbt.bmHeight,istepIfAniCur,hbrFlickerFreeDraw,DI_IMAGE);
+ noMirrorMask = TRUE;
+
+ }
+ SelectObject(tempDC1,otBmp);
+ mod_DeleteDC(tempDC1);
+ }
+ /*
+ if (imbt.bmBitsPixel != 32)
+ {
+ HDC tempDC1;
+ HBITMAP otBmp;
+ no32bit = TRUE;
+ tempDC1 = ske_RequestBufferDC(hdcDst,BUFFER_DRAWICON,imbt.bmWidth,imbt.bmHeight);
+ if (tempDC1)
+ {
+ DrawIconEx(tempDC1,0,0,hIcon,imbt.bmWidth,imbt.bmHeight,istepIfAniCur,hbrFlickerFreeDraw,DI_IMAGE);
+ noMirrorMask = TRUE;
+ ske_ReleaseBufferDC(tempDC1,2000); //keep buffer for 2 seconds
+ }
+ }
+ */
+ if (imbt.bmBits == NULL)
+ {
+ NoDIBImage = TRUE;
+ imimagbits = (BYTE*)malloc(cy*imbt.bmWidthBytes);
+ GetBitmapBits(ici.hbmColor,cy*imbt.bmWidthBytes,(void*)imimagbits);
+ }
+ else imimagbits = (BYTE*)imbt.bmBits;
+
+
+ if (immaskbt.bmBits == NULL)
+ {
+ immaskbits = (BYTE*)malloc(cy*immaskbt.bmWidthBytes);
+ GetBitmapBits(ici.hbmMask,cy*immaskbt.bmWidthBytes,(void*)immaskbits);
+ }
+ else
+ immaskbits = (BYTE*)immaskbt.bmBits;
+ icy = imbt.bmHeight;
+ cx = imbt.bmWidth;
+ imDC = CreateCompatibleDC(hdcDst);
+ imBmp = ske_CreateDIB32Point(cx,icy,(void**)&imbits);
+ oldBmp = (HBITMAP)SelectObject(imDC,imBmp);
+ if (imbits != NULL && imimagbits != NULL && immaskbits != NULL)
+ {
+ int x; int y;
+ int bottom,right,top,h;
+ int mwb,mwb2;
+ mwb = immaskbt.bmWidthBytes;
+ mwb2 = imbt.bmWidthBytes;
+ bottom = icy;
+ right = cx;
+ top = 0;
+ h = icy;
+ for (y = top;(y < bottom) && !hasmask; y++)
+ {
+ t1 = immaskbits+y*mwb;
+ for (x = 0; (x < mwb) && !hasmask; x++)
+ hasmask |= (*(t1+x) != 0);
+ }
+
+ for (y = top;(y < bottom) && !hasalpha; y++)
+ {
+ t1 = imimagbits+(cy-y-1)*mwb2;
+ for (x = 0; (x < right) && !hasalpha; x++)
+ hasalpha |= (*(t1+(x << 2)+3) != 0);
+ }
+
+ for (y = 0; y < (int)icy; y++)
+ {
+ t1 = imimagbits+(h-y-1-top)*mwb2;
+ t2 = imbits+(!no32bit?y:(icy-y-1))*mwb2;
+ t3 = immaskbits+(noMirrorMask?y:(h-y-1-top))*mwb;
+ for (x = 0; x < right; x++)
+ {
+ DWORD * src, *dest;
+ BYTE mask = 0;
+ BYTE a = 0;
+ src = (DWORD*)(t1+(x << 2));
+ dest = (DWORD*)(t2+(x << 2));
+ if (hasalpha && !hasmask)
+ a = ((BYTE*)src)[3];
+ else
+ {
+ mask = ((1 << (7-x%8))&(*(t3+(x>>3)))) != 0;
+ if (mask)// && !hasalpha)
+ {
+ if ( !hasalpha)
+ { *dest = 0; continue; }
+ else
+ {
+ if (((BYTE*)src)[3]>0 )
+ a = ((BYTE*)src)[3];
+ else
+ a = 0;
+ }
+ }
+ else if (hasalpha || hasmask)
+ a = (((BYTE*)src)[3]>0?((BYTE*)src)[3]:255);
+ else if ( !hasalpha && !hasmask)
+ a = 255;
+ else { *dest = 0; continue; }
+ }
+ if (a>0)
+ {
+ ((BYTE*)dest)[3] = a;
+ ((BYTE*)dest)[0] = ((BYTE*)src)[0]*a/255;
+ ((BYTE*)dest)[1] = ((BYTE*)src)[1]*a/255;
+ ((BYTE*)dest)[2] = ((BYTE*)src)[2]*a/255;
+ }
+ else
+ *dest = 0;
+ }
+ }
+ }
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, diFlags&128, alpha, AC_SRC_ALPHA };
+ ske_AlphaBlend(hdcDst,xLeft,yTop,cxWidth, cyWidth, imDC,0,0, cx,icy,bf);
+ }
+ if (immaskbt.bmBits == NULL) free(immaskbits);
+ if (imbt.bmBits == NULL) free(imimagbits);
+ SelectObject(imDC,oldBmp);
+ DeleteObject(imBmp);
+ if (no32bit)DeleteObject(tBmp);
+ DeleteObject(ici.hbmColor);
+ DeleteObject(ici.hbmMask);
+ SelectObject(imDC,GetStockObject(DEFAULT_GUI_FONT));
+ mod_DeleteDC(imDC);
+ return 1;// DrawIconExS(hdc,xLeft,yTop,hIcon,cxWidth,cyWidth,istepIfAniCur,hbrFlickerFreeDraw,diFlags);
+}
+
+
+
+int ske_PrepeareImageButDontUpdateIt(RECT * r)
+{
+ if (g_CluiData.fLayered)
+ {
+ mutex_bLockUpdate = 1;
+ ske_DrawNonFramedObjects(TRUE,r);
+ ske_ValidateFrameImageProc(r);
+ mutex_bLockUpdate = 0;
+ return 0;
+ }
+ else
+ {
+ return ske_ReCreateBackImage(FALSE,r);
+ }
+ return 0;
+}
+
+int ske_RedrawCompleteWindow()
+{
+ if (g_CluiData.fLayered)
+ {
+ ske_DrawNonFramedObjects(TRUE,0);
+ CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,0,0);
+ }
+ else
+ {
+ RedrawWindow(pcli->hwndContactList,NULL,NULL,RDW_ALLCHILDREN|RDW_ERASE|RDW_INVALIDATE|RDW_FRAME);
+ }
+ return 0;
+}
+// Request to repaint frame or change/drop callback data
+// wParam = hWnd of called frame
+// lParam = pointer to sPaintRequest (or NULL to redraw all)
+// return 2 - already queued, data updated, 1-have been queued, 0 - failure
+
+static INT_PTR ske_Service_UpdateFrameImage(WPARAM wParam, LPARAM lParam) // Immideately recall paint routines for frame and refresh image
+{
+ if ( MirandaLoading()) return 0;
+
+ RECT wnd;
+ FRAMEWND *frm;
+ BOOL NoCancelPost = 0;
+ BOOL IsAnyQueued = 0;
+ if ( !g_CluiData.mutexOnEdgeSizing)
+ GetWindowRect(pcli->hwndContactList,&wnd);
+ else
+ wnd = g_rcEdgeSizingRect;
+ if ( !g_CluiData.fLayered)
+ {
+ RedrawWindow((HWND)wParam,NULL,NULL,RDW_UPDATENOW|RDW_ERASE|RDW_INVALIDATE|RDW_FRAME);
+ return 0;
+ }
+ if (g_pCachedWindow == NULL) ske_ValidateFrameImageProc(&wnd);
+ else if (g_pCachedWindow->Width != wnd.right-wnd.left || g_pCachedWindow->Height != wnd.bottom-wnd.top) ske_ValidateFrameImageProc(&wnd);
+ else if (wParam == 0) ske_ValidateFrameImageProc(&wnd);
+ else // all Ok Update Single Frame
+ {
+ // TO BE LOCKED OR PROXIED
+ frm = FindFrameByItsHWND((HWND)wParam);
+ if ( !frm) ske_ValidateFrameImageProc(&wnd);
+ // Validate frame, update window image and remove it from queue
+ else
+ {
+ if (frm->UpdateRgn)
+ {
+ DeleteObject(frm->UpdateRgn);
+ frm->UpdateRgn = 0;
+ }
+ ske_ValidateSingleFrameImage(frm,0);
+ ske_UpdateWindowImage();
+ NoCancelPost = 1;
+ //-- Remove frame from queue
+ if (flag_bUpdateQueued)
+ {
+ int i;
+ frm->bQueued = 0;
+ for (i=0;i < g_nFramesCount;i++)
+ if (IsAnyQueued |= g_pfwFrames[i].bQueued) break;
+ }
+ }
+ }
+ if ((!NoCancelPost || !IsAnyQueued) && flag_bUpdateQueued) // no any queued updating cancel post or need to cancel post
+ {
+ flag_bUpdateQueued = 0;
+ g_flag_bPostWasCanceled = 1;
+ }
+ return 1;
+}
+static INT_PTR ske_Service_InvalidateFrameImage(WPARAM wParam, LPARAM lParam) // Post request for updating
+{
+ if ( MirandaLoading()) return 0;
+ if (wParam)
+ {
+ FRAMEWND *frm = FindFrameByItsHWND((HWND)wParam);
+ sPaintRequest * pr = (sPaintRequest*)lParam;
+ if ( !g_CluiData.fLayered || (frm && frm->floating)) return InvalidateRect((HWND)wParam,pr?(RECT*)&(pr->rcUpdate):NULL,FALSE);
+ if (frm)
+ {
+ if (frm->PaintCallbackProc != NULL)
+ {
+ frm->PaintData = (sPaintRequest *)pr;
+ frm->bQueued = 1;
+ if (pr)
+ {
+ HRGN r2;
+ if ( !IsRectEmpty(&pr->rcUpdate))
+ {
+ RECT rcClient;
+ RECT rcUpdate;
+ GetClientRect(frm->hWnd,&rcClient);
+ IntersectRect( &rcUpdate, &rcClient, &pr->rcUpdate );
+ if ( IsRectEmpty( &rcUpdate ))
+ return 0;
+ r2 = CreateRectRgn( rcUpdate.left, rcUpdate.top, rcUpdate.right, rcUpdate.bottom );
+ }
+ else
+ {
+ RECT r;
+ GetClientRect(frm->hWnd,&r);
+ r2 = CreateRectRgn(r.left,r.top,r.right,r.bottom);
+ }
+ if ( !frm->UpdateRgn)
+ {
+ frm->UpdateRgn = CreateRectRgn(0,0,1,1);
+ CombineRgn(frm->UpdateRgn,r2,0,RGN_COPY);
+ }
+ else CombineRgn(frm->UpdateRgn,frm->UpdateRgn,r2,RGN_OR);
+ DeleteObject(r2);
+ }
+
+ }
+ }
+ else
+ {
+ Sync( QueueAllFramesUpdating, (BYTE)1 );
+ }
+ }
+ else
+ Sync( QueueAllFramesUpdating , (BYTE)1 );
+ if ( !flag_bUpdateQueued || g_flag_bPostWasCanceled)
+ if (PostMessage(pcli->hwndContactList,UM_UPDATE,0,0))
+ {
+ flag_bUpdateQueued = 1;
+ g_flag_bPostWasCanceled = 0;
+ }
+ return 1;
+}
+
+
+static int ske_ValidateSingleFrameImage(FRAMEWND * Frame, BOOL SkipBkgBlitting) // Calling frame paint proc
+{
+ if ( !g_pCachedWindow) { TRACE("ske_ValidateSingleFrameImage calling without cached\n"); return 0;}
+ if (Frame->hWnd == (HWND)-1 && !Frame->PaintCallbackProc) { TRACE("ske_ValidateSingleFrameImage calling without FrameProc\n"); return 0;}
+ { // if ok update image
+ HDC hdc;
+ HBITMAP o,n;
+ RECT rcPaint,wnd;
+ RECT ru = {0};
+ int w,h,x,y;
+ int w1,h1,x1,y1;
+
+ CLUI_SizingGetWindowRect(pcli->hwndContactList,&wnd);
+ rcPaint = Frame->wndSize;
+ {
+ int dx,dy,bx,by;
+ if (g_CluiData.mutexOnEdgeSizing)
+ {
+ dx = rcPaint.left-wnd.left;
+ dy = rcPaint.top-wnd.top;
+ bx = rcPaint.right-wnd.right;
+ by = rcPaint.bottom-wnd.bottom;
+ wnd = g_rcEdgeSizingRect;
+ rcPaint.left = wnd.left+dx;
+ rcPaint.top = wnd.top+dy;
+ rcPaint.right = wnd.right+bx;
+ rcPaint.bottom = wnd.bottom+by;
+ }
+ }
+ //OffsetRect(&rcPaint,-wnd.left,-wnd.top);
+ w = rcPaint.right-rcPaint.left;
+ h = rcPaint.bottom-rcPaint.top;
+ if (w <= 0 || h <= 0)
+ {
+ TRACE("Frame size smaller than 0\n");
+ return 0;
+ }
+ x = rcPaint.left;
+ y = rcPaint.top;
+ hdc = CreateCompatibleDC(g_pCachedWindow->hImageDC);
+ n = ske_CreateDIB32(w,h);
+ o = (HBITMAP)SelectObject(hdc,n);
+ {
+ if (Frame->UpdateRgn && !SkipBkgBlitting)
+ {
+ GetRgnBox(Frame->UpdateRgn,&ru);
+ {
+ RECT rc;
+ GetClientRect(Frame->hWnd,&rc);
+ if (ru.top < 0) ru.top = 0;
+ if (ru.left < 0) ru.left = 0;
+ if (ru.right>rc.right) ru.right = rc.right;
+ if (ru.bottom>rc.bottom) ru.bottom = rc.bottom;
+ }
+ if ( !IsRectEmpty(&ru))
+ {
+ x1 = ru.left;
+ y1 = ru.top;
+ w1 = ru.right-ru.left;
+ h1 = ru.bottom-ru.top;
+ }
+ else
+ {x1 = 0; y1 = 0; w1 = w; h1 = h;}
+ // copy image at hdc
+ if (SkipBkgBlitting) //image already at foreground
+ {
+ BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hImageDC,x+x1,y+y1,SRCCOPY);
+ }
+ else
+ {
+ BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hBackDC,x+x1,y+y1,SRCCOPY);
+ }
+ Frame->PaintCallbackProc(Frame->hWnd,hdc,&ru,Frame->UpdateRgn, Frame->dwFlags,Frame->PaintData);
+ }
+ else
+ {
+ HRGN rgnUpdate;
+ RECT r;
+ GetClientRect(Frame->hWnd,&r);
+ rgnUpdate = CreateRectRgn(r.left,r.top,r.right,r.bottom);
+ ru = r;
+ if ( !IsRectEmpty(&ru))
+ {
+ x1 = ru.left;
+ y1 = ru.top;
+ w1 = ru.right-ru.left;
+ h1 = ru.bottom-ru.top;
+ }
+ else
+ {x1 = 0; y1 = 0; w1 = w; h1 = h;}
+ // copy image at hdc
+ if (SkipBkgBlitting) //image already at foreground
+ {
+ BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hImageDC,x+x1,y+y1,SRCCOPY);
+ }
+ else
+ {
+ BitBlt(hdc,x1,y1,w1,h1,g_pCachedWindow->hBackDC,x+x1,y+y1,SRCCOPY);
+ }
+ Frame->PaintCallbackProc(Frame->hWnd,hdc,&r,rgnUpdate, Frame->dwFlags,Frame->PaintData);
+ ru = r;
+ DeleteObject(rgnUpdate);
+ }
+ DeleteObject(Frame->UpdateRgn);
+ Frame->UpdateRgn = 0;
+ }
+ if ( !IsRectEmpty(&ru))
+ {
+ x1 = ru.left;
+ y1 = ru.top;
+ w1 = ru.right-ru.left;
+ h1 = ru.bottom-ru.top;
+ }
+ else
+ {x1 = 0; y1 = 0; w1 = w; h1 = h;}
+ /* if ( !SkipBkgBlitting)
+ {
+ BitBlt(g_pCachedWindow->hImageDC,x+x1,y+y1,w1,h1,g_pCachedWindow->hBackDC,x+x1,y+y1,SRCCOPY);
+ }
+
+ */
+ {
+ //BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ BitBlt(g_pCachedWindow->hImageDC,x+x1,y+y1,w1,h1,hdc,x1,y1,SRCCOPY);
+ //BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ //MyAlphaBlend(g_pCachedWindow->hImageDC,x+x1,y+y1,w1,h1,hdc,x1,y1,w1,h1,bf);
+ }
+
+ if ( fnGetScrollBarInfo && (GetWindowLongPtr(Frame->hWnd,GWL_STYLE) & WS_VSCROLL))
+ {
+ //Draw vertical scroll bar
+ //
+ RECT rThumb;
+ RECT rUpBtn;
+ RECT rDnBtn;
+ RECT rLine;
+ int dx,dy;
+ SCROLLBARINFO si = {0};
+ si.cbSize = sizeof(SCROLLBARINFO);
+ fnGetScrollBarInfo(Frame->hWnd,OBJID_VSCROLL,&si);
+ rLine = (si.rcScrollBar);
+ rUpBtn = rLine;
+ rDnBtn = rLine;
+ rThumb = rLine;
+
+ rUpBtn.bottom = rUpBtn.top+si.dxyLineButton;
+ rDnBtn.top = rDnBtn.bottom-si.dxyLineButton;
+ rThumb.top = rLine.top+si.xyThumbTop;
+ rThumb.bottom = rLine.top+si.xyThumbBottom;
+ {
+ dx = Frame->wndSize.right-rLine.right;
+ dy = -rLine.top+Frame->wndSize.top;
+ }
+ OffsetRect(&rLine,dx,dy);
+ OffsetRect(&rUpBtn,dx,dy);
+ OffsetRect(&rDnBtn,dx,dy);
+ OffsetRect(&rThumb,dx,dy);
+ BitBlt(g_pCachedWindow->hImageDC,rLine.left,rLine.top,rLine.right-rLine.left,rLine.bottom-rLine.top,g_pCachedWindow->hBackDC,rLine.left,rLine.top,SRCCOPY);
+ {
+ char req[255];
+ _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=Back",Frame->szName);
+ SkinDrawGlyph(g_pCachedWindow->hImageDC,&rLine,&rLine,req);
+ _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=Thumb",Frame->szName);
+ SkinDrawGlyph(g_pCachedWindow->hImageDC,&rThumb,&rThumb,req);
+ _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=UpLineButton",Frame->szName);
+ SkinDrawGlyph(g_pCachedWindow->hImageDC,&rUpBtn,&rUpBtn,req);
+ _snprintf(req,sizeof(req),"Main,ID=ScrollBar,Frame=%s,Part=DownLineButton",Frame->szName);
+ SkinDrawGlyph(g_pCachedWindow->hImageDC,&rDnBtn,&rDnBtn,req);
+ }
+ }
+
+ SelectObject(hdc,o);
+ DeleteObject(n);
+ mod_DeleteDC(hdc);
+ }
+ return 1;
+}
+
+int ske_BltBackImage (HWND destHWND, HDC destDC, RECT * BltClientRect)
+{
+ POINT ptMainWnd = {0};
+ POINT ptChildWnd = {0};
+ RECT from = {0};
+ RECT w = {0};
+ if (g_CluiData.fDisableSkinEngine)
+ {
+ FillRect(destDC,BltClientRect,GetSysColorBrush(COLOR_3DFACE));
+ return 0;
+ }
+ ske_ReCreateBackImage(FALSE,NULL);
+ if (BltClientRect) w = *BltClientRect;
+ else GetClientRect(destHWND,&w);
+ ptChildWnd.x = w.left;
+ ptChildWnd.y = w.top;
+ ClientToScreen(destHWND,&ptChildWnd);
+ ClientToScreen(pcli->hwndContactList,&ptMainWnd);
+ //TODO if main not relative to client area
+ return BitBlt(destDC,w.left,w.top,(w.right-w.left),(w.bottom-w.top),g_pCachedWindow->hBackDC,(ptChildWnd.x-ptMainWnd.x),(ptChildWnd.y-ptMainWnd.y),SRCCOPY);
+
+}
+int ske_ReCreateBackImage(BOOL Erase,RECT *w)
+{
+ HBITMAP hb2;
+ RECT wnd = {0};
+ BOOL IsNewCache = 0;
+ if (g_CluiData.fDisableSkinEngine) return 0;
+ GetClientRect(pcli->hwndContactList,&wnd);
+ if (w) wnd = *w;
+ //-- Check cached.
+ if (g_pCachedWindow == NULL)
+ {
+ //-- Create New Cache
+ {
+ g_pCachedWindow = (CURRWNDIMAGEDATA*)mir_calloc(sizeof(CURRWNDIMAGEDATA));
+ g_pCachedWindow->hScreenDC = GetDC(NULL);
+ g_pCachedWindow->hBackDC = CreateCompatibleDC(g_pCachedWindow->hScreenDC);
+ g_pCachedWindow->hImageDC = CreateCompatibleDC(g_pCachedWindow->hScreenDC);
+ g_pCachedWindow->Width = wnd.right-wnd.left;
+ g_pCachedWindow->Height = wnd.bottom-wnd.top;
+ if (g_pCachedWindow->Width != 0 && g_pCachedWindow->Height != 0)
+ {
+ g_pCachedWindow->hImageDIB = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte));
+ g_pCachedWindow->hBackDIB = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte));
+ g_pCachedWindow->hImageOld = (HBITMAP)SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageDIB);
+ g_pCachedWindow->hBackOld = (HBITMAP)SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackDIB);
+ }
+ }
+ IsNewCache = 1;
+ }
+ if (g_pCachedWindow->Width != wnd.right-wnd.left || g_pCachedWindow->Height != wnd.bottom-wnd.top)
+ {
+ HBITMAP hb1 = NULL,hb2 = NULL;
+ g_pCachedWindow->Width = wnd.right-wnd.left;
+ g_pCachedWindow->Height = wnd.bottom-wnd.top;
+ if (g_pCachedWindow->Width != 0 && g_pCachedWindow->Height != 0)
+ {
+ hb1 = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte));
+ hb2 = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte));
+ SelectObject(g_pCachedWindow->hImageDC,hb1);
+ SelectObject(g_pCachedWindow->hBackDC,hb2);
+ }
+ else
+ {
+ SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageOld);
+ SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackOld);
+ }
+ if (g_pCachedWindow->hImageDIB) DeleteObject(g_pCachedWindow->hImageDIB);
+ if (g_pCachedWindow->hBackDIB) DeleteObject(g_pCachedWindow->hBackDIB);
+ g_pCachedWindow->hImageDIB = hb1;
+ g_pCachedWindow->hBackDIB = hb2;
+ IsNewCache = 1;
+ }
+ if ((Erase || IsNewCache ) && (g_pCachedWindow->Width != 0 && g_pCachedWindow->Height != 0))
+ {
+
+ hb2 = ske_CreateDIB32(g_pCachedWindow->Width,g_pCachedWindow->Height);
+ SelectObject(g_pCachedWindow->hBackDC,hb2);
+ DeleteObject(g_pCachedWindow->hBackDIB);
+ g_pCachedWindow->hBackDIB = hb2;
+ FillRect(g_pCachedWindow->hBackDC,&wnd,GetSysColorBrush(COLOR_BTNFACE));
+ SkinDrawGlyph(g_pCachedWindow->hBackDC,&wnd,&wnd,"Main,ID=Background,Opt=Non-Layered");
+ ske_SetRectOpaque(g_pCachedWindow->hBackDC,&wnd);
+ }
+ return 1;
+}
+int ske_DrawNonFramedObjects(BOOL Erase,RECT *r)
+{
+ RECT w,wnd;
+ if (r) w = *r;
+ else CLUI_SizingGetWindowRect(pcli->hwndContactList,&w);
+ if ( !g_CluiData.fLayered) return ske_ReCreateBackImage(FALSE,0);
+ if (g_pCachedWindow == NULL)
+ return ske_ValidateFrameImageProc(&w);
+
+ wnd = w;
+ OffsetRect(&w, -w.left, -w.top);
+ if (Erase)
+ {
+ HBITMAP hb2;
+ hb2 = ske_CreateDIB32(g_pCachedWindow->Width,g_pCachedWindow->Height);
+ SelectObject(g_pCachedWindow->hBackDC,hb2);
+ DeleteObject(g_pCachedWindow->hBackDIB);
+ g_pCachedWindow->hBackDIB = hb2;
+ }
+
+ SkinDrawGlyph(g_pCachedWindow->hBackDC,&w,&w,"Main,ID=Background");
+ //--Draw frames captions
+ {
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ if (g_pfwFrames[i].TitleBar.ShowTitleBar && g_pfwFrames[i].visible && !g_pfwFrames[i].floating)
+ {
+ RECT rc;
+ SetRect(&rc,g_pfwFrames[i].wndSize.left,g_pfwFrames[i].wndSize.top-g_nTitleBarHeight-g_CluiData.nGapBetweenTitlebar,g_pfwFrames[i].wndSize.right,g_pfwFrames[i].wndSize.top-g_CluiData.nGapBetweenTitlebar);
+ //GetWindowRect(Frames[i].TitleBar.hwnd,&rc);
+ //OffsetRect(&rc,-wnd.left,-wnd.top);
+ Sync( DrawTitleBar, g_pCachedWindow->hBackDC, &rc, g_pfwFrames[i].id );
+ }
+ }
+ g_mutex_bLockUpdating = 1;
+
+ flag_bJustDrawNonFramedObjects = 1;
+ return 0;
+}
+int ske_ValidateFrameImageProc(RECT * r) // Calling queued frame paint procs and refresh image
+{
+ RECT wnd = {0};
+ BOOL IsNewCache = 0;
+ BOOL IsForceAllPainting = 0;
+ if (r) wnd = *r;
+ else GetWindowRect(pcli->hwndContactList,&wnd);
+ if (wnd.right-wnd.left == 0 || wnd.bottom-wnd.top == 0) return 0;
+ g_mutex_bLockUpdating = 1;
+ //-- Check cached.
+ if (g_pCachedWindow == NULL)
+ {
+ //-- Create New Cache
+ {
+ g_pCachedWindow = (CURRWNDIMAGEDATA*)mir_calloc(sizeof(CURRWNDIMAGEDATA));
+ g_pCachedWindow->hScreenDC = GetDC(NULL);
+ g_pCachedWindow->hBackDC = CreateCompatibleDC(g_pCachedWindow->hScreenDC);
+ g_pCachedWindow->hImageDC = CreateCompatibleDC(g_pCachedWindow->hScreenDC);
+ g_pCachedWindow->Width = wnd.right-wnd.left;
+ g_pCachedWindow->Height = wnd.bottom-wnd.top;
+ g_pCachedWindow->hImageDIB = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte));
+ g_pCachedWindow->hBackDIB = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte));
+ g_pCachedWindow->hImageOld = (HBITMAP)SelectObject(g_pCachedWindow->hImageDC,g_pCachedWindow->hImageDIB);
+ g_pCachedWindow->hBackOld = (HBITMAP)SelectObject(g_pCachedWindow->hBackDC,g_pCachedWindow->hBackDIB);
+ }
+ IsNewCache = 1;
+ }
+ if (g_pCachedWindow->Width != wnd.right-wnd.left || g_pCachedWindow->Height != wnd.bottom-wnd.top)
+ {
+ HBITMAP hb1,hb2;
+ g_pCachedWindow->Width = wnd.right-wnd.left;
+ g_pCachedWindow->Height = wnd.bottom-wnd.top;
+ hb1 = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hImageDIBByte));
+ hb2 = ske_CreateDIB32Point(g_pCachedWindow->Width,g_pCachedWindow->Height,(void**)&(g_pCachedWindow->hBackDIBByte));
+ SelectObject(g_pCachedWindow->hImageDC,hb1);
+ SelectObject(g_pCachedWindow->hBackDC,hb2);
+ DeleteObject(g_pCachedWindow->hImageDIB);
+ DeleteObject(g_pCachedWindow->hBackDIB);
+ g_pCachedWindow->hImageDIB = hb1;
+ g_pCachedWindow->hBackDIB = hb2;
+ IsNewCache = 1;
+ }
+ if (IsNewCache)
+ {
+ ske_DrawNonFramedObjects(0,&wnd);
+ IsForceAllPainting = 1;
+ }
+ if (flag_bJustDrawNonFramedObjects)
+ {
+ IsForceAllPainting = 1;
+ flag_bJustDrawNonFramedObjects = 0;
+ }
+ if (IsForceAllPainting)
+ {
+ BitBlt(g_pCachedWindow->hImageDC,0,0,g_pCachedWindow->Width,g_pCachedWindow->Height,g_pCachedWindow->hBackDC,0,0,SRCCOPY);
+ Sync( QueueAllFramesUpdating, (BYTE)1 );
+ }
+ //-- Validating frames
+ {
+ int i;
+ for (i=0;i < g_nFramesCount;i++)
+ if (g_pfwFrames[i].PaintCallbackProc && g_pfwFrames[i].visible && !g_pfwFrames[i].floating )
+ if (g_pfwFrames[i].bQueued || IsForceAllPainting)
+ ske_ValidateSingleFrameImage(&g_pfwFrames[i],IsForceAllPainting);
+ }
+ g_mutex_bLockUpdating = 1;
+ ModernSkinButtonRedrawAll(0);
+ g_mutex_bLockUpdating = 0;
+ if ( !mutex_bLockUpdate) ske_UpdateWindowImageRect(&wnd);
+ //-- Clear queue
+ {
+ Sync( QueueAllFramesUpdating, (BYTE)0 );
+ flag_bUpdateQueued = 0;
+ g_flag_bPostWasCanceled = 0;
+ }
+ return 1;
+}
+
+int ske_UpdateWindowImage()
+{
+ if (MirandaExiting())
+ return 0;
+ if (g_CluiData.fLayered)
+ {
+ RECT r;
+ GetWindowRect(pcli->hwndContactList,&r);
+ return ske_UpdateWindowImageRect(&r);
+ }
+ else
+ ske_ReCreateBackImage(FALSE,0);
+ ske_ApplyTransluency();
+ return 0;
+}
+
+
+int ske_UpdateWindowImageRect(RECT * r) // Update window with current image and
+{
+ //if not validity -> ValidateImageProc
+ //else Update using current alpha
+ RECT wnd = *r;
+
+ if ( !g_CluiData.fLayered) return ske_ReCreateBackImage(FALSE,0);
+ if (g_pCachedWindow == NULL) return ske_ValidateFrameImageProc(&wnd);
+ if (g_pCachedWindow->Width != wnd.right-wnd.left || g_pCachedWindow->Height != wnd.bottom-wnd.top) return ske_ValidateFrameImageProc(&wnd);
+ if (g_flag_bFullRepaint)
+ {
+ g_flag_bFullRepaint = 0;
+ return ske_ValidateFrameImageProc(&wnd);
+ }
+ ske_JustUpdateWindowImageRect(&wnd);
+ return 0;
+}
+
+void ske_ApplyTransluency()
+{
+ int IsTransparancy;
+ HWND hwnd = pcli->hwndContactList;
+ BOOL layered = (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED)?TRUE:FALSE;
+
+ IsTransparancy = g_CluiData.fSmoothAnimation || g_bTransparentFlag;
+ if ( !g_bTransparentFlag && !g_CluiData.fSmoothAnimation && g_CluiData.bCurrentAlpha != 0)
+ g_CluiData.bCurrentAlpha = 255;
+ if ( !g_CluiData.fLayered && (/*(g_CluiData.bCurrentAlpha == 255) || */(g_proc_SetLayeredWindowAttributesNew && IsTransparancy)))
+ {
+ if ( !layered) SetWindowLongPtr(hwnd, GWL_EXSTYLE, GetWindowLongPtr(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
+ if (g_proc_SetLayeredWindowAttributesNew) g_proc_SetLayeredWindowAttributesNew(hwnd, RGB(0,0,0), (BYTE)g_CluiData.bCurrentAlpha, LWA_ALPHA);
+ }
+
+ AniAva_RedrawAllAvatars(FALSE);
+ return;
+}
+
+int ske_JustUpdateWindowImage()
+{
+ RECT r;
+ if ( !g_CluiData.fLayered)
+ {
+ ske_ApplyTransluency();
+ return 0;
+ }
+ GetWindowRect(pcli->hwndContactList,&r);
+ return ske_JustUpdateWindowImageRect(&r);
+}
+int ske_JustUpdateWindowImageRect(RECT * rty)
+//Update window image
+{
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0,g_CluiData.bCurrentAlpha, AC_SRC_ALPHA };
+ POINT dest = {0}, src = {0};
+ int res;
+ RECT wnd = *rty;
+
+ RECT rect;
+ SIZE sz = {0};
+
+ if ( !g_CluiData.fLayered)
+ {
+ ske_ApplyTransluency();
+ return 0;
+ }
+ if ( !pcli->hwndContactList) return 0;
+ rect = wnd;
+ dest.x = rect.left;
+ dest.y = rect.top;
+ sz.cx = rect.right-rect.left;
+ sz.cy = rect.bottom-rect.top;
+ if (g_proc_UpdateLayeredWindow && g_CluiData.fLayered)
+ {
+ if ( !(GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE)&WS_EX_LAYERED))
+ SetWindowLongPtr(pcli->hwndContactList,GWL_EXSTYLE, GetWindowLongPtr(pcli->hwndContactList, GWL_EXSTYLE) |WS_EX_LAYERED);
+ Sync( SetAlpha, g_CluiData.bCurrentAlpha );
+
+ res = g_proc_UpdateLayeredWindow(pcli->hwndContactList,g_pCachedWindow->hScreenDC,&dest,&sz,g_pCachedWindow->hImageDC,&src,RGB(1,1,1),&bf,ULW_ALPHA);
+ g_CluiData.fAeroGlass = false;
+ CLUI_UpdateAeroGlass();
+ }
+ else InvalidateRect(pcli->hwndContactList,NULL,TRUE);
+ return 0;
+}
+
+int ske_DrawImageAt(HDC hdc, RECT *rc)
+{
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ BitBlt(g_pCachedWindow->hImageDC,rc->left,rc->top,rc->right-rc->left,rc->bottom-rc->top,g_pCachedWindow->hBackDC,rc->left,rc->top,SRCCOPY);
+ ske_AlphaBlend(g_pCachedWindow->hImageDC,rc->left,rc->top,rc->right-rc->left,rc->bottom-rc->top,hdc,0,0,rc->right-rc->left,rc->bottom-rc->top,bf);
+ if ( !g_mutex_bLockUpdating)
+ ske_UpdateWindowImage();
+ return 0;
+}
+
+HBITMAP ske_GetCurrentWindowImage()
+{
+ return g_pCachedWindow->hImageDIB;
+}
+
+/*
+* Glyph text routine
+*/
+
+static DWORD ske_HexToARGB(char * Hex)
+{
+ char buf[10] = {0};
+ char buf2[11] = {0};
+ char * st;
+ BYTE alpha;
+ DWORD AARRGGBB = 0;
+ _snprintf(buf,10,"%s\n",Hex);
+ if (buf[1] == 'x' || buf[1] == 'X')
+ _snprintf(buf2,11,"0x%s\n",buf+2);
+ else
+ _snprintf(buf2,11,"0x%s\n",buf);
+ buf2[10] = '\0';
+ AARRGGBB = strtoul(buf2,&st,16);
+ alpha = (BYTE)((AARRGGBB&0xFF000000)>>24);
+ alpha = 255-((alpha == 0)?255:alpha);
+ AARRGGBB = (alpha << 24)+((AARRGGBB&0x00FF0000)>>16)+((AARRGGBB&0x000000FF) << 16)+(AARRGGBB&0x0000FF00);
+ return AARRGGBB;
+}
+
+static TCHAR *ske_ReAppend(TCHAR *lfirst, TCHAR * lsecond, int len)
+{
+ int l1 = lfirst?lstrlen(lfirst):0;
+ int l2 = (len?len:(lstrlen(lsecond)+1));
+ TCHAR *buf = (TCHAR *)mir_alloc((l1+l2+1)*sizeof(TCHAR));
+ if (lfirst) memmove(buf,lfirst,l1*sizeof(TCHAR));
+ memmove(buf+l1,lsecond,l2*sizeof(TCHAR));
+ mir_free(lfirst);
+ if (len) buf[l1+l2] = _T('\0');
+ return buf;
+}
+
+TCHAR* ske_ReplaceVar(TCHAR *var)
+{
+ if ( !var) return mir_tstrdup(_T(""));
+ if ( !lstrcmpi(var,_T("Profile")))
+ {
+ char buf[MAX_PATH] = {0};
+ CallService(MS_DB_GETPROFILENAME,(WPARAM)MAX_PATH,(LPARAM)buf);
+ {
+ int i = strlen(buf);
+ while (buf[i] != '.' && i>0) i--;
+ buf[i] = '\0';
+ }
+ mir_free(var);
+ return mir_a2u(buf);
+ }
+
+ mir_free(var);
+ return mir_tstrdup(_T(""));
+}
+TCHAR *ske_ParseText(TCHAR *stzText)
+{
+ int len = lstrlen(stzText);
+ TCHAR *result = NULL;
+ int stpos = 0;
+ int curpos = 0;
+
+ while(curpos < len)
+ {
+ //1 find first %
+ while(curpos < len && stzText[curpos] != (TCHAR)'%') curpos++;
+ if (curpos < len) //% found
+ {
+ if (curpos-stpos>0)
+ result = ske_ReAppend(result,stzText+stpos,curpos-stpos);
+ stpos = curpos+1;
+ curpos++;
+ //3 find second %
+ while(curpos < len && stzText[curpos] != (TCHAR)'%') curpos++;
+ if (curpos < len)
+ {
+ if (curpos-stpos>0)
+ {
+ TCHAR *var = (TCHAR *)mir_alloc((curpos-stpos+1)*sizeof(TCHAR));
+ memmove(var,stzText+stpos,(curpos-stpos)*sizeof(TCHAR));
+ var[curpos-stpos] = (TCHAR)'\0';
+ var = ske_ReplaceVar(var);
+ result = ske_ReAppend(result,var,0);
+ mir_free(var);
+ }
+ else result = ske_ReAppend(result,_T("%"),0);
+
+ curpos++;
+ stpos = curpos;
+ }
+ else
+ {
+ // if (curpos-stpos>0)
+ // result = ske_ReAppend(result,stzText+stpos,curpos-stpos);
+ break;
+ }
+ }
+ else
+ {
+ if (curpos-stpos>0)
+ result = ske_ReAppend(result,stzText+stpos,curpos-stpos);
+ break;
+ }
+ }
+ return result;
+}
+/*
+* Parse text object string, find glyph object and add text to it.
+* szGlyphTextID and Define string is:
+* t[szGlyphTextID] = s[HostObjectID],[Left],[Top],[Right],[Bottom],[LTRBHV],[FontID],[Color1],[reservedforColor2],[Text]
+*/
+static void OLDske_AddParseTextGlyphObject(char * szGlyphTextID,char * szDefineString,SKINOBJECTSLIST *Skin)
+{
+
+ GLYPHOBJECT *globj = NULL;
+ {
+ char buf[255] = {0};
+ GetParamN(szDefineString,buf,sizeof(buf),0,',',TRUE);
+ if (strlen(buf))
+ {
+ SKINOBJECTDESCRIPTOR * lpobj;
+ lpobj = ske_FindObjectByName(buf,OT_GLYPHOBJECT,Skin);
+ if (lpobj)
+ globj = (GLYPHOBJECT*)lpobj->Data;
+ }
+ if (globj)
+ {
+ GLYPHTEXT * glText;
+
+ if ( !globj->plTextList)
+ {
+ globj->plTextList = List_Create(0,1);
+ globj->plTextList->sortFunc = ske_SortTextGlyphObjectFunc;
+ }
+ glText = (GLYPHTEXT*)mir_calloc(sizeof(GLYPHTEXT));
+ glText->szGlyphTextID = mir_strdup(szGlyphTextID);
+ glText->szObjectName = mir_strdup(buf);
+ glText->iLeft = atoi(GetParamN(szDefineString,buf,sizeof(buf),1,',',TRUE));
+ glText->iTop = atoi(GetParamN(szDefineString,buf,sizeof(buf),2,',',TRUE));
+ glText->iRight = atoi(GetParamN(szDefineString,buf,sizeof(buf),3,',',TRUE));
+ glText->iBottom = atoi(GetParamN(szDefineString,buf,sizeof(buf),4,',',TRUE));
+ {
+ memset(buf,0,6);
+ GetParamN(szDefineString,buf,sizeof(buf),5,',',TRUE);
+ buf[0] &= 95; buf[1] &= 95; buf[2] &= 95; buf[3] &= 95; buf[4] &= 95; buf[5] &= 95; //to uppercase: &01011111 (0-95)
+ glText->RelativeFlags =
+ (buf[0] == 'C'?1:((buf[0] == 'R')?2:0)) //[BC][RC][BC][RC] --- Left relative
+ |(buf[1] == 'C'?4:((buf[1] == 'B')?8:0)) // | | |--------- Top relative
+ |(buf[2] == 'C'?16:((buf[2] == 'R')?32:0)) // | |--------------Right relative
+ |(buf[3] == 'C'?64:((buf[3] == 'B')?128:0)); // |------------------Bottom relative
+ glText->dwFlags = (buf[4] == 'C'?DT_CENTER:((buf[4] == 'R')?DT_RIGHT:DT_LEFT))
+ |(buf[5] == 'C'?DT_VCENTER:((buf[5] == 'B')?DT_BOTTOM:DT_TOP));
+ }
+ glText->szFontID = mir_strdup(GetParamN(szDefineString,buf,sizeof(buf),6,',',TRUE));
+
+ glText->dwColor = ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),7,',',TRUE));
+ glText->dwShadow = ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),8,',',TRUE));
+ glText->stValueText = mir_a2u(GetParamN(szDefineString,buf,sizeof(buf),9,',',TRUE));
+ glText->stText = ske_ParseText(glText->stValueText);
+ List_Insert(globj->plTextList,(void*)glText,globj->plTextList->realCount);
+ qsort(globj->plTextList->items,globj->plTextList->realCount,sizeof(void*),(int(*)(const void*, const void*))globj->plTextList->sortFunc);
+ }
+ }
+}
+
+
+static void ske_AddParseTextGlyphObject(char * szGlyphTextID,char * szDefineString,SKINOBJECTSLIST *Skin)
+{
+ char buf[255] = {0};
+ GetParamN(szDefineString,buf,sizeof(buf),0,',',TRUE);
+ if (strlen(buf))
+ {
+ GLYPHTEXT * glText;
+ glText = (GLYPHTEXT*)mir_calloc(sizeof(GLYPHTEXT));
+ glText->szGlyphTextID = mir_strdup(szGlyphTextID);
+ glText->szObjectName = mir_strdup(buf);
+ glText->iLeft = atoi(GetParamN(szDefineString,buf,sizeof(buf),1,',',TRUE));
+ glText->iTop = atoi(GetParamN(szDefineString,buf,sizeof(buf),2,',',TRUE));
+ glText->iRight = atoi(GetParamN(szDefineString,buf,sizeof(buf),3,',',TRUE));
+ glText->iBottom = atoi(GetParamN(szDefineString,buf,sizeof(buf),4,',',TRUE));
+ {
+ memset(buf,0,6);
+ GetParamN(szDefineString,buf,sizeof(buf),5,',',TRUE);
+ buf[0] &= 95; buf[1] &= 95; buf[2] &= 95; buf[3] &= 95; buf[4] &= 95; buf[5] &= 95; //to uppercase: &01011111 (0-95)
+ glText->RelativeFlags =
+ (buf[0] == 'C'?1:((buf[0] == 'R')?2:0)) //[BC][RC][BC][RC] --- Left relative
+ |(buf[1] == 'C'?4:((buf[1] == 'B')?8:0)) // | | |--------- Top relative
+ |(buf[2] == 'C'?16:((buf[2] == 'R')?32:0)) // | |--------------Right relative
+ |(buf[3] == 'C'?64:((buf[3] == 'B')?128:0)); // |------------------Bottom relative
+ glText->dwFlags = (buf[4] == 'C'?DT_CENTER:((buf[4] == 'R')?DT_RIGHT:DT_LEFT))
+ |(buf[5] == 'C'?DT_VCENTER:((buf[5] == 'B')?DT_BOTTOM:DT_TOP));
+ }
+ glText->szFontID = mir_strdup(GetParamN(szDefineString,buf,sizeof(buf),6,',',TRUE));
+
+ glText->dwColor = ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),7,',',TRUE));
+ glText->dwShadow = ske_HexToARGB(GetParamN(szDefineString,buf,sizeof(buf),8,',',TRUE));
+ glText->stValueText = mir_a2u(GetParamN(szDefineString,buf,sizeof(buf),9,',',TRUE));
+ glText->stText = ske_ParseText(glText->stValueText);
+
+ if ( !Skin->pTextList)
+ Skin->pTextList = List_Create(0,1);
+ List_InsertPtr(Skin->pTextList,glText);
+ }
+}
+
+
+/*
+* Parse font definition string.
+* szGlyphTextID and Define string is:
+* f[szFontID] = s[FontTypefaceName],[size],[BIU]
+*/
+static void ske_AddParseSkinFont(char * szFontID,char * szDefineString,SKINOBJECTSLIST *Skin)
+{
+ //SortedList * gl_plSkinFonts = NULL;
+ SKINFONT * sf = NULL;
+ sf = (SKINFONT*)mir_calloc(sizeof(SKINFONT));
+ if (sf)
+ {
+ {
+ char buf[255];
+ int fntSize = 0;
+ BOOL fntBold = FALSE, fntItalic = FALSE, fntUnderline = FALSE;
+ LOGFONTA logfont = {0};
+ logfont.lfCharSet = DEFAULT_CHARSET;
+ logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
+ logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ logfont.lfQuality = DEFAULT_QUALITY;
+ logfont.lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
+
+ strncpy(logfont.lfFaceName,GetParamN(szDefineString,buf,sizeof(buf),0,',',TRUE),32);
+ logfont.lfHeight = atoi(GetParamN(szDefineString,buf,sizeof(buf),1,',',TRUE));
+ if (logfont.lfHeight < 0)
+ {
+ HDC hdc = CreateCompatibleDC(NULL);
+ logfont.lfHeight = (long)-MulDiv(logfont.lfHeight, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+ mod_DeleteDC(hdc);
+ }
+ logfont.lfHeight = -logfont.lfHeight;
+ GetParamN(szDefineString,buf,sizeof(buf),2,',',TRUE);
+ buf[0] &= 95; buf[1] &= 95; buf[2] &= 95;
+ logfont.lfWeight = (buf[0] == 'B')?FW_BOLD:FW_NORMAL;
+ logfont.lfItalic = (buf[1] == 'I')?1:0;
+ logfont.lfUnderline = (buf[2] == 'U')?1:0;
+
+ sf->hFont = CreateFontIndirectA(&logfont);
+ if (sf->hFont)
+ {
+ sf->szFontID = mir_strdup(szFontID);
+ if ( !gl_plSkinFonts)
+ gl_plSkinFonts = List_Create(0,1);
+ if (gl_plSkinFonts)
+ {
+ List_Insert(gl_plSkinFonts,(void*)sf,gl_plSkinFonts->realCount);
+ }
+ }
+
+ }
+ }
+
+}
+
+/*
+HICON ske_CreateJoinedIcon_Old(HICON hBottom, HICON hTop,BYTE alpha)
+{
+HDC tempDC;
+HICON res = NULL;
+HBITMAP oImage,nImage;
+HBITMAP nMask;
+ICONINFO iNew = {0};
+ICONINFO iciBottom = {0};
+ICONINFO iciTop = {0};
+BITMAP bmp = {0};
+SIZE sz = {0};
+{
+if ( !GetIconInfo(hBottom,&iciBottom)) return NULL;
+GetObject(iciBottom.hbmColor,sizeof(BITMAP),&bmp);
+sz.cx = bmp.bmWidth; sz.cy = bmp.bmHeight;
+if (iciBottom.hbmColor) DeleteObject(iciBottom.hbmColor);
+if (iciBottom.hbmMask) DeleteObject(iciBottom.hbmMask);
+}
+if (sz.cx == 0 || sz.cy == 0) return NULL;
+tempDC = CreateCompatibleDC(NULL);
+nImage = ske_CreateDIB32(sz.cx,sz.cy);
+oImage = SelectObject(tempDC,nImage);
+ske_DrawIconEx(tempDC,0,0,hBottom,sz.cx,sz.cy,0,NULL,DI_NORMAL);
+ske_DrawIconEx(tempDC,0,0,hTop,sz.cx,sz.cy,0,NULL,DI_NORMAL|(alpha << 24));
+SelectObject(tempDC,oImage);
+DeleteDC(tempDC);
+{
+BYTE * p = malloc(sz.cx*sz.cy/8+10);
+nMask = CreateBitmap(sz.cx,sz.cy,1,1,(void*)p);
+iNew.fIcon = TRUE;
+iNew.hbmColor = nImage;
+iNew.hbmMask = nMask;
+res = CreateIconIndirect(&iNew);
+if ( !res)
+TRACE_ERROR();
+DeleteObject(nImage);
+DeleteObject(nMask);
+free(p);
+}
+return res;
+}
+*/
+
+
+/*
+* ske_CheckHasAlfaChannel - checks if image has at least one BYTE in alpha chennel
+* that is not a 0. (is image real 32 bit or just 24 bit)
+*/
+static BOOL ske_CheckHasAlfaChannel(BYTE * from, int widthByte, int height)
+{
+ int i=0,j = 0;
+ DWORD * pt = (DWORD*)from;
+ while (j < height)
+ {
+ BYTE * add = (BYTE*)pt+widthByte;
+ while (pt < (DWORD*)add)
+ {
+ if ((*pt&0xFF000000) != 0) return TRUE;
+ pt++;
+ }
+ pt = (DWORD*)(from+widthByte*j);
+ j++;
+ }
+ return FALSE;
+}
+
+/*
+* ske_CheckIconHasMask - checks if mask image has at least one that is not a 0.
+* Not sure is ir required or not
+*/
+static BOOL ske_CheckIconHasMask(BYTE * from)
+{
+ int i=0;
+ for (i=0; i < 16*16/8; i++)
+ {
+ if (from[i] != 0) return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+* ske_GetMaskBit - return value of apropriate mask bit in line at x position
+*/
+static BOOL ske_GetMaskBit(BYTE *line, int x)
+{
+ return ((*(line+(x>>3)))&(0x01 << (7-(x&0x07)))) != 0;
+}
+/*
+* ske_Blend - alpha ske_Blend ARGB values of 2 pixels. X1 - underlaying,
+* X2 - overlaying points.
+*/
+
+static DWORD ske_Blend(DWORD X1,DWORD X2, BYTE alpha)
+{
+ BYTE a1 = (BYTE)(X1>>24);
+ BYTE a2 = (BYTE)(((X2>>24)*alpha)>>8);
+ BYTE r1 = (BYTE)(X1>>16);
+ BYTE r2 = (BYTE)(X2>>16);
+ BYTE g1 = (BYTE)(X1>>8);
+ BYTE g2 = (BYTE)(X2>>8);
+ BYTE b1 = (BYTE)(X1);
+ BYTE b2 = (BYTE)(X2);
+
+ BYTE a_1 = ~a1;
+ BYTE a_2 = ~a2;
+ WORD am = (WORD)a1*a_2;
+
+ /* it is possible to use >>8 instead of /255 but it is require additional
+ * checking of alphavalues
+ */
+ WORD ar = a1+(((WORD)a_1*a2)/255);
+ // if a2 more than 0 than result should be more
+ // or equal (if a1 == 0) to a2, else in combination
+ // with mask we can get here black points
+
+ ar = (a2>ar)?a2:ar;
+
+ if (ar == 0) return 0;
+
+ //else
+ {
+ WORD arm = ar*255;
+ WORD rr = (((WORD)r1*am+(WORD)r2*a2*255))/arm;
+ WORD gr = (((WORD)g1*am+(WORD)g2*a2*255))/arm;
+ WORD br = (((WORD)b1*am+(WORD)b2*a2*255))/arm;
+ return (ar << 24)|(rr << 16)|(gr << 8)|br;
+ }
+
+}
+/*
+* CreateJoinedIcon - creates new icon by drawing hTop over hBottom.
+*/
+HICON ske_CreateJoinedIcon(HICON hBottom, HICON hTop, BYTE alpha)
+{
+ HDC tempDC;
+ HICON res = NULL;
+ HBITMAP oImage,nImage;
+ HBITMAP nMask;
+ BITMAP bmp = {0};
+ BYTE *ptPixels;
+ ICONINFO iNew = {0};
+ ICONINFO iciBottom = {0};
+ ICONINFO iciTop = {0};
+
+ BITMAP bmp_top = {0};
+ BITMAP bmp_top_mask = {0};
+
+ BITMAP bmp_bottom = {0};
+ BITMAP bmp_bottom_mask = {0};
+
+ tempDC = CreateCompatibleDC(NULL);
+ nImage = ske_CreateDIB32Point(16,16,(void**)&ptPixels);
+ oImage = (HBITMAP)SelectObject(tempDC,nImage);
+
+ GetIconInfo(hBottom,&iciBottom);
+ GetObject(iciBottom.hbmColor,sizeof(BITMAP),&bmp_bottom);
+ GetObject(iciBottom.hbmMask,sizeof(BITMAP),&bmp_bottom_mask);
+
+ GetIconInfo(hTop,&iciTop);
+ GetObject(iciTop.hbmColor,sizeof(BITMAP),&bmp_top);
+ GetObject(iciTop.hbmMask,sizeof(BITMAP),&bmp_top_mask);
+
+ if (bmp_bottom.bmBitsPixel == 32 && bmp_top.bmBitsPixel == 32 && IsWinVerXPPlus())
+ {
+ BYTE * BottomBuffer, * TopBuffer, * BottomMaskBuffer, * TopMaskBuffer;
+ BYTE * bb, * tb, * bmb, * tmb;
+ BYTE * db = ptPixels;
+ int vstep_d = 16*4;
+ int vstep_b = bmp_bottom.bmWidthBytes;
+ int vstep_t = bmp_top.bmWidthBytes;
+ int vstep_bm = bmp_bottom_mask.bmWidthBytes;
+ int vstep_tm = bmp_top_mask.bmWidthBytes;
+ alpha = alpha?alpha:255;
+ if (bmp_bottom.bmBits) bb = BottomBuffer = (BYTE*)bmp_bottom.bmBits;
+ else
+ {
+ BottomBuffer = (BYTE*)malloc(bmp_bottom.bmHeight*bmp_bottom.bmWidthBytes);
+ GetBitmapBits(iciBottom.hbmColor,bmp_bottom.bmHeight*bmp_bottom.bmWidthBytes,BottomBuffer);
+ bb = BottomBuffer+vstep_b*(bmp_bottom.bmHeight-1);
+ vstep_b = -vstep_b;
+ }
+ if (bmp_top.bmBits) tb = TopBuffer = (BYTE*)bmp_top.bmBits;
+ else
+ {
+ TopBuffer = (BYTE*)malloc(bmp_top.bmHeight*bmp_top.bmWidthBytes);
+ GetBitmapBits(iciTop.hbmColor,bmp_top.bmHeight*bmp_top.bmWidthBytes,TopBuffer);
+ tb = TopBuffer+vstep_t*(bmp_top.bmHeight-1);
+ vstep_t = -vstep_t;
+ }
+ if (bmp_bottom_mask.bmBits)
+ {
+ BottomMaskBuffer = (BYTE*)bmp_bottom_mask.bmBits;
+ bmb = BottomMaskBuffer;
+ }
+ else
+ {
+ BottomMaskBuffer = (BYTE*)malloc(bmp_bottom_mask.bmHeight*bmp_bottom_mask.bmWidthBytes);
+ GetBitmapBits(iciBottom.hbmMask,bmp_bottom_mask.bmHeight*bmp_bottom_mask.bmWidthBytes,BottomMaskBuffer);
+ bmb = BottomMaskBuffer+vstep_bm*(bmp_bottom_mask.bmHeight-1);
+ vstep_bm = -vstep_bm;
+
+ }
+ if (bmp_top_mask.bmBits)
+ {
+ TopMaskBuffer = (BYTE*)bmp_top_mask.bmBits;
+ tmb = TopMaskBuffer;
+
+ }
+ else
+ {
+ TopMaskBuffer = (BYTE*)malloc(bmp_top_mask.bmHeight*bmp_top_mask.bmWidthBytes);
+ GetBitmapBits(iciTop.hbmMask,bmp_top_mask.bmHeight*bmp_top_mask.bmWidthBytes,TopMaskBuffer);
+ tmb = TopMaskBuffer+vstep_tm*(bmp_top_mask.bmHeight-1);
+ vstep_tm = -vstep_tm;
+ }
+ {
+ int x = 0; int y = 0;
+ BOOL topHasAlpha = ske_CheckHasAlfaChannel(TopBuffer,bmp_top.bmWidthBytes,bmp_top.bmHeight);
+ BOOL bottomHasAlpha = ske_CheckHasAlfaChannel(BottomBuffer,bmp_bottom.bmWidthBytes,bmp_bottom.bmHeight);
+ BOOL topHasMask = ske_CheckIconHasMask(TopMaskBuffer);
+ BOOL bottomHasMask = ske_CheckIconHasMask(BottomMaskBuffer);
+ for (y = 0; y < 16; y++)
+ {
+ for (x = 0; x < 16; x++)
+ {
+ BOOL mask_b = ske_GetMaskBit(bmb,x);
+ BOOL mask_t = ske_GetMaskBit(tmb,x);
+ DWORD bottom_d = ((DWORD*)bb)[x];
+ DWORD top_d = ((DWORD*)tb)[x];
+ if (topHasMask)
+ {
+ if (mask_t == 1 && !topHasAlpha ) top_d &= 0xFFFFFF;
+ else if ( !topHasAlpha) top_d |= 0xFF000000;
+ }
+ if (bottomHasMask)
+ {
+ if (mask_b == 1 && !bottomHasAlpha) bottom_d &= 0xFFFFFF;
+ else if ( !bottomHasAlpha) bottom_d |= 0xFF000000;
+ }
+ ((DWORD*)db)[x] = ske_Blend(bottom_d,top_d,alpha);
+ }
+ bb += vstep_b;
+ tb += vstep_t;
+ bmb += vstep_bm;
+ tmb += vstep_tm;
+ db += vstep_d;
+ }
+ }
+ if ( !bmp_bottom.bmBits) free(BottomBuffer);
+ if ( !bmp_top.bmBits) free(TopBuffer);
+ if ( !bmp_bottom_mask.bmBits) free(BottomMaskBuffer);
+ if ( !bmp_top_mask.bmBits) free(TopMaskBuffer);
+ }
+ else
+ {
+ ske_DrawIconEx(tempDC,0,0,hBottom,16,16,0,NULL,DI_NORMAL);
+ ske_DrawIconEx(tempDC,0,0,hTop,16,16,0,NULL,DI_NORMAL|(alpha << 24));
+ }
+ DeleteObject(iciBottom.hbmColor);
+ DeleteObject(iciTop.hbmColor);
+ DeleteObject(iciBottom.hbmMask);
+ DeleteObject(iciTop.hbmMask);
+
+ SelectObject(tempDC,oImage);
+ DeleteDC(tempDC);
+ {
+ //BYTE *p = malloc(32);
+ //memset(p,0,32);
+ BYTE p[32] = {0};
+ nMask = CreateBitmap(16,16,1,1,(void*)&p);
+ {
+ HDC tempDC2 = CreateCompatibleDC(NULL);
+ HDC tempDC3 = CreateCompatibleDC(NULL);
+ HBITMAP hbm = CreateCompatibleBitmap(tempDC3,16,16);
+ HBITMAP obmp = (HBITMAP)SelectObject(tempDC2,nMask);
+ HBITMAP obmp2 = (HBITMAP)SelectObject(tempDC3,hbm);
+ DrawIconEx(tempDC2,0,0,hBottom,16,16,0,NULL,DI_MASK);
+ DrawIconEx(tempDC3,0,0,hTop,16,16,0,NULL,DI_MASK);
+ BitBlt(tempDC2,0,0,16,16,tempDC3,0,0,SRCAND);
+ SelectObject(tempDC2,obmp);
+ SelectObject(tempDC3,obmp2);
+ DeleteObject(hbm);
+ DeleteDC(tempDC2);
+ DeleteDC(tempDC3);
+ }
+ iNew.fIcon = TRUE;
+ iNew.hbmColor = nImage;
+ iNew.hbmMask = nMask;
+ res = CreateIconIndirect(&iNew);
+ DeleteObject(nImage);
+ DeleteObject(nMask);
+ }
+ return res;
+}
+
+#define NEWJOINEDSTR( destination, first, separator, last) \
+ destination = (char*)alloca(strlen(first)+strlen(separator)+strlen(last)+1); \
+ if (destination) { \
+ *destination = '\0'; \
+ strcat(destination,first); \
+ strcat(destination,separator); \
+ strcat(destination,last); \
+ }
+
+#define SKINSETSECTION "SkinnedSettings"
+
+BOOL SkinDBGetContactSetting(HANDLE hContact, const char* szSection, const char*szKey, DBVARIANT * retdbv, BOOL * bSkined )
+{
+ if ( !hContact) { //only for not contact settings
+ char * szSkinKey;
+ NEWJOINEDSTR(szSkinKey,szSection,"@",szKey);
+ if ( !db_get(hContact, SKINSETSECTION, szSkinKey, retdbv)) {
+ if (bSkined) *bSkined = TRUE;
+ return FALSE;
+ } }
+ // not skinned
+ if (bSkined) bSkined = FALSE;
+ return db_get(hContact, szSection, szKey, retdbv);
+}
+
+BYTE SkinDBGetContactSettingByte(HANDLE hContact, const char* szSection, const char*szKey, BYTE bDefault)
+{
+ DBVARIANT dbv = {0};
+ BOOL bSkined = FALSE;
+ if ( !SkinDBGetContactSetting(hContact, szSection, szKey, &dbv, &bSkined)) {
+ if (dbv.type == DBVT_BYTE)
+ {
+ BYTE retVal = dbv.bVal;
+ db_free(&dbv);
+ return retVal;
+ } else {
+ db_free(&dbv);
+ if ( !bSkined) return db_get_b(hContact, szSection, szKey, bDefault);
+ }
+ }
+ return bDefault;
+}
+
+WORD SkinDBGetContactSettingWord(HANDLE hContact, const char* szSection, const char*szKey, WORD wDefault)
+{
+ BOOL bSkined = FALSE;
+ DBVARIANT dbv = {0};
+ if ( !SkinDBGetContactSetting(hContact, szSection, szKey, &dbv, &bSkined)) {
+ if (dbv.type == DBVT_WORD) {
+ WORD retVal = dbv.wVal;
+ db_free(&dbv);
+ return retVal;
+ } else {
+ db_free(&dbv);
+ if ( !bSkined) return db_get_w(hContact, szSection, szKey, wDefault);
+ }
+ }
+ return wDefault;
+}
+
+DWORD SkinDBGetContactSettingDword(HANDLE hContact, const char* szSection, const char*szKey, DWORD dwDefault)
+{
+ DBVARIANT dbv = {0};
+ BOOL bSkined = FALSE;
+ if ( !SkinDBGetContactSetting(hContact, szSection, szKey, &dbv, &bSkined)) {
+ if (dbv.type == DBVT_DWORD) {
+ DWORD retVal = dbv.dVal;
+ db_free(&dbv);
+ return retVal;
+ } else {
+ db_free(&dbv);
+ if ( !bSkined) return db_get_dw(hContact, szSection, szKey, dwDefault);
+ }
+ }
+ return dwDefault;
+}
diff --git a/plugins/Clist_modern/src/modern_skinned_profile.cpp b/plugins/Clist_modern/src/modern_skinned_profile.cpp
new file mode 100644
index 0000000000..d31fe7d18f
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_skinned_profile.cpp
@@ -0,0 +1,115 @@
+
+
+#include "hdr/modern_commonheaders.h"
+
+#ifdef _DEBUG // REMOVE ME, as soon as ghazan will implement msvcprt.lib msvcrt.lib analogs to vc6tovc7.lib
+#include "hdr/modern_skinned_profile.h"
+
+
+//need to be linked in: atls.lib msvcprt.lib msvcrt.lib
+
+CSkinnedProfile CSkinnedProfile::_me;
+
+
+CSkinnedProfile::CSkinnedProfile()
+{
+ Init();
+}
+
+CSkinnedProfile::~CSkinnedProfile()
+{
+
+}
+
+HRESULT CSkinnedProfile::Init()
+{
+ CAutoCriticalSection Lock( SkinProfile()->_Lock, true );
+ SkinnedProfile.clear();
+ return S_OK;
+}
+
+HRESULT CSkinnedProfile::Clear()
+{
+ CAutoCriticalSection Lock( SkinProfile()->_Lock, true );
+ SkinnedProfile.clear();
+ return S_OK;
+}
+
+
+ValueVariant* CSkinnedProfile::_GetValue( const char * szSection, const char * szKey )
+{
+ KeyList_t::iterator k_it = SkinnedProfile.find( szSection );
+ if ( k_it == SkinnedProfile.end() )
+ return NULL; // Not skinned
+
+ ValueList_t::iterator v_it = k_it->second.find( szKey );
+ if ( v_it == k_it->second.end() )
+ return NULL; // Not skinned
+
+ return &( v_it->second );
+};
+
+BYTE CSkinnedProfile::SpiGetSkinByte( HANDLE hContact, const char * szSection, const char * szKey, const BYTE defValue )
+{
+ if ( hContact )
+ return ModernGetSettingByte( hContact, szSection, szKey, defValue ); //per-contact settings are not skinnablr at all
+
+ CAutoCriticalSection Lock( SkinProfile()->_Lock, true );
+
+ ValueVariant* value = SkinProfile()->_GetValue( szSection, szKey );
+
+ if ( value == NULL ) // not skinned => return DB
+ return ModernGetSettingWord( hContact, szSection, szKey, defValue );
+
+ else if ( !value->IsEmpty() )
+ return value->GetByte();
+
+ return defValue; // skinned but empty => return default value
+}
+
+WORD CSkinnedProfile::SpiGetSkinWord( HANDLE hContact, const char * szSection, const char * szKey, const WORD defValue )
+{
+ if ( hContact )
+ return ModernGetSettingWord( hContact, szSection, szKey, defValue ); //per-contact settings are not skinnablr at all
+
+ CAutoCriticalSection Lock( SkinProfile()->_Lock, true );
+
+ ValueVariant* value = SkinProfile()->_GetValue( szSection, szKey );
+
+ if ( value == NULL ) // not skinned => return DB
+ return ModernGetSettingWord( hContact, szSection, szKey, defValue );
+
+ else if ( !value->IsEmpty() )
+ return value->GetWord();
+
+ return defValue; // skinned but empty => return default value
+}
+
+DWORD CSkinnedProfile::SpiGetSkinDword( HANDLE hContact, const char * szSection, const char * szKey, const DWORD defValue )
+{
+ if ( hContact )
+ return ModernGetSettingDword( hContact, szSection, szKey, defValue ); //per-contact settings are not skinnablr at all
+
+ CAutoCriticalSection Lock( SkinProfile()->_Lock, true );
+
+ ValueVariant* value = SkinProfile()->_GetValue( szSection, szKey );
+
+ if ( value == NULL ) // not skinned => return DB
+ return ModernGetSettingDword( hContact, szSection, szKey, defValue );
+
+ else if ( !value->IsEmpty() )
+ return value->GetDword();
+
+ return defValue; // skinned but empty => return default value
+}
+
+BOOL CSkinnedProfile::SpiCheckSkinned( HANDLE hContact, const char * szSection, const char * szKey )
+{
+ if ( hContact )
+ return FALSE;
+
+ CAutoCriticalSection Lock( SkinProfile()->_Lock, true );
+
+ return ( SkinProfile()->_GetValue( szSection, szKey ) == NULL );
+}
+#endif // _DEBUG // REMOVE ME, as soon as ghazan will implement msvcprt.lib msvcrt.lib analogs to vc6tovc7.lib \ No newline at end of file
diff --git a/plugins/Clist_modern/src/modern_skinopt.cpp b/plugins/Clist_modern/src/modern_skinopt.cpp
new file mode 100644
index 0000000000..1ffb72804c
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_skinopt.cpp
@@ -0,0 +1,771 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or ( at your option ) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clui.h"
+#include "hdr/modern_clist.h"
+#include "m_clc.h"
+#include "io.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_sync.h"
+#include <m_utils.h>
+#include <m_database.h>
+#include <m_modernopt.h>
+
+/*******************************/
+// Main skin selection routine //
+/*******************************/
+#define MAX_NAME 100
+typedef struct _SkinListData
+{
+ TCHAR Name[MAX_NAME];
+ TCHAR File[MAX_PATH];
+} SkinListData;
+
+HBITMAP hPreviewBitmap = NULL;
+HTREEITEM AddItemToTree( HWND hTree, TCHAR * folder, TCHAR * itemName, void * data );
+HTREEITEM AddSkinToListFullName( HWND hwndDlg, TCHAR * fullName );
+HTREEITEM AddSkinToList( HWND hwndDlg, TCHAR * path, TCHAR* file );
+HTREEITEM FillAvailableSkinList( HWND hwndDlg );
+
+INT_PTR CALLBACK DlgSkinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+int SkinOptInit( WPARAM wParam, LPARAM lParam )
+{
+ OPTIONSDIALOGPAGE odp;
+ if ( !g_CluiData.fDisableSkinEngine )
+ {
+ //Tabbed settings
+ ZeroMemory( &odp, sizeof( odp ));
+ odp.cbSize = sizeof( odp );
+ odp.position = -200000000;
+ odp.hInstance = g_hInst;
+ odp.pfnDlgProc = DlgSkinOpts;
+ odp.pszTemplate = MAKEINTRESOURCEA( IDD_OPT_SKIN );
+ odp.pszGroup = LPGEN( "Skins" );
+ odp.pszTitle = LPGEN( "Contact List" );
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.pszTab = LPGEN( "Load/Save" );
+ Options_AddPage(wParam, &odp);
+
+ if ( db_get_b( NULL, "ModernData", "EnableSkinEditor", SETTING_ENABLESKINEDITOR_DEFAULT )) {
+ odp.flags |= ODPF_EXPERTONLY;
+ odp.pfnDlgProc = DlgSkinEditorOpts;
+ odp.pszTemplate = MAKEINTRESOURCEA( IDD_OPT_SKINEDITOR );
+ odp.pszTab = LPGEN( "Object Editor" );
+ Options_AddPage(wParam, &odp);
+ }
+ }
+ return 0;
+}
+
+int ModernSkinOptInit( WPARAM wParam, LPARAM lParam )
+{
+ MODERNOPTOBJECT obj = {0};
+ obj.cbSize = sizeof(obj);
+ obj.dwFlags = MODEROPT_FLG_TCHAR;
+ obj.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ obj.hInstance = g_hInst;
+ obj.iSection = MODERNOPT_PAGE_SKINS;
+ obj.iType = MODERNOPT_TYPE_SELECTORPAGE;
+ obj.lptzSubsection = _T("Contact List");
+ obj.lpzThemeExtension = ".msf";
+ obj.lpzThemeModuleName = "ModernSkinSel";
+ CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj);
+ return 0;
+}
+INT_PTR CALLBACK DlgSkinOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch ( msg )
+ {
+ case WM_DESTROY:
+ {
+ if ( hPreviewBitmap ) ske_UnloadGlyphImage( hPreviewBitmap );
+ break;
+ }
+
+ case WM_INITDIALOG:
+ {
+ HTREEITEM it;
+ TranslateDialogDefault( hwndDlg );
+ it = FillAvailableSkinList( hwndDlg );
+ HWND wnd = GetDlgItem( hwndDlg, IDC_TREE1 );
+ TreeView_SelectItem( wnd, it );
+ }
+ return 0;
+ case WM_COMMAND:
+ {
+ int isLoad = 0;
+ switch ( LOWORD( wParam ))
+ {
+ case IDC_COLOUR_MENUNORMAL:
+ case IDC_COLOUR_MENUSELECTED:
+ case IDC_COLOUR_FRAMES:
+ case IDC_COLOUR_STATUSBAR:
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+
+ case IDC_BUTTON_INFO:
+ {
+ TCHAR Author[255];
+ TCHAR URL[MAX_PATH];
+ TCHAR Contact[255];
+ TCHAR Description[400];
+ TCHAR text[2000];
+ SkinListData *sd = NULL;
+ HTREEITEM hti = TreeView_GetSelection( GetDlgItem( hwndDlg, IDC_TREE1 ));
+ if ( hti == 0 ) return 0;
+ {
+ TVITEM tvi = {0};
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ TreeView_GetItem( GetDlgItem( hwndDlg, IDC_TREE1 ), &tvi );
+ sd = ( SkinListData* )( tvi.lParam );
+ }
+ if ( !sd ) return 0;
+ if ( sd->File && !_tcschr( sd->File, _T('%')))
+ {
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Author" ), TranslateT( "( unknown )" ), Author, SIZEOF( Author ), sd->File );
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "URL" ), _T( "" ), URL, SIZEOF( URL ), sd->File );
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Contact" ), _T( "" ), Contact, SIZEOF( Contact ), sd->File );
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Description" ), _T( "" ), Description, SIZEOF( Description ), sd->File );
+ _sntprintf( text, SIZEOF( text ), TranslateT( "%s\n\n%s\n\nAuthor(s):\t %s\nContact:\t %s\nWeb:\t %s\n\nFile:\t %s" ),
+ sd->Name, Description, Author, Contact, URL, sd->File );
+ }
+ else
+ {
+ _sntprintf( text, SIZEOF( text ), TranslateT( "%s\n\n%s\n\nAuthor(s): %s\nContact:\t %s\nWeb:\t %s\n\nFile:\t %s" ),
+ TranslateT( "reVista for Modern v0.5" ),
+ TranslateT( "This is second default Modern Contact list skin in Vista Aero style" ),
+ TranslateT( "Angeli-Ka (graphics), FYR (template)" ),
+ _T( "JID: fyr@jabber.ru" ),
+ _T("fyr.mirandaim.ru"),
+ TranslateT( "Inside library" ));
+ }
+ MessageBox( hwndDlg, text, TranslateT( "Skin Information" ), MB_OK|MB_ICONINFORMATION );
+ }
+ break;
+ case IDC_BUTTON_APPLY_SKIN:
+ if ( HIWORD( wParam ) == BN_CLICKED )
+ {
+ SkinListData *sd = NULL;
+ HTREEITEM hti = TreeView_GetSelection( GetDlgItem( hwndDlg, IDC_TREE1 ));
+ if ( hti == 0 ) return 0;
+ {
+ TVITEM tvi = {0};
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ TreeView_GetItem( GetDlgItem( hwndDlg, IDC_TREE1 ), &tvi );
+ sd = ( SkinListData* )( tvi.lParam );
+ }
+ if ( !sd ) return 0;
+ if ( glSkinWasModified>0 )
+ {
+ int res = 0;
+ if ( glSkinWasModified == 1 )
+ res = MessageBox( hwndDlg, TranslateT( "Skin editor contains not stored changes.\n\nAll changes will be lost.\n\n Continue to load new skin?" ), TranslateT( "Warning!" ), MB_OKCANCEL|MB_ICONWARNING|MB_DEFBUTTON2|MB_TOPMOST );
+ else
+ res = MessageBox( hwndDlg, TranslateT( "Current skin was not saved to file.\n\nAll changes will be lost.\n\n Continue to load new skin?" ), TranslateT( "Warning!" ), MB_OKCANCEL|MB_ICONWARNING|MB_DEFBUTTON2|MB_TOPMOST );
+ if ( res != IDOK ) return 0;
+ }
+ ske_LoadSkinFromIniFile( sd->File, FALSE );
+ ske_LoadSkinFromDB( );
+ glOtherSkinWasLoaded = TRUE;
+ pcli->pfnClcBroadcast( INTM_RELOADOPTIONS, 0, 0 );
+ Sync( CLUIFrames_OnClistResize_mod, 0, 0 );
+ ske_RedrawCompleteWindow( );
+ Sync( CLUIFrames_OnClistResize_mod, 0, 0 );
+ {
+ HWND hwnd = pcli->hwndContactList;
+ RECT rc = {0};
+ GetWindowRect( hwnd, &rc );
+ Sync( CLUIFrames_OnMoving, hwnd, &rc );
+ }
+ if ( g_hCLUIOptionsWnd )
+ {
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_LEFTMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "LeftClientMargin", SETTING_LEFTCLIENTMARIGN_DEFAULT ));
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_RIGHTMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "RightClientMargin", SETTING_RIGHTCLIENTMARIGN_DEFAULT ));
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_TOPMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "TopClientMargin", SETTING_TOPCLIENTMARIGN_DEFAULT ));
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_BOTTOMMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "BottomClientMargin", SETTING_BOTTOMCLIENTMARIGN_DEFAULT ));
+ }
+ }
+ break;
+ case IDC_BUTTON_LOAD:
+ isLoad = 1;
+ if ( HIWORD( wParam ) == BN_CLICKED )
+ {
+ {
+ TCHAR str[MAX_PATH] = {0};
+ OPENFILENAME ofn = {0};
+ TCHAR filter[512] = {0};
+ int res = 0;
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = hwndDlg;
+ ofn.hInstance = NULL;
+
+ mir_sntprintf(filter, SIZEOF(filter), _T("%s (*.msf)%c*.MSF%c%c"), TranslateT("Miranda skin file"), 0, 0, 0);
+ ofn.lpstrFilter = filter;
+ ofn.lpstrFile = str;
+ ofn.Flags = isLoad?( OFN_FILEMUSTEXIST | OFN_HIDEREADONLY ) : ( OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY ) | OFN_DONTADDTORECENT;
+ ofn.nMaxFile = sizeof( str );
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.lpstrDefExt = _T( "msf" );
+
+ {
+ DWORD tick = GetTickCount( );
+ res = GetOpenFileName( &ofn );
+ if ( !res )
+ if ( GetTickCount( )-tick < 100 )
+ {
+ res = GetOpenFileName( &ofn );
+ if ( !res ) break;
+ }
+ else break;
+ }
+ if ( res )
+ {
+ HTREEITEM it = AddSkinToListFullName( hwndDlg, ofn.lpstrFile );
+ TreeView_SelectItem( GetDlgItem( hwndDlg, IDC_TREE1 ), it );
+ //SendDlgItemMessage( hwndDlg, IDC_SKINS_LIST, LB_SETCURSEL, it, 0 );
+ //SendMessage( hwndDlg, WM_COMMAND, MAKEWPARAM( IDC_SKINS_LIST, LBN_SELCHANGE ), 0 );
+ }
+ }
+ }
+ }
+ break;
+ }
+ case WM_DRAWITEM:
+ if ( wParam == IDC_PREVIEW )
+ {
+ //TODO:Draw hPreviewBitmap here
+ HDC memDC, imgDC;
+ HBITMAP hbmp, holdbmp, imgOldbmp;
+ int mWidth, mHeight;
+ RECT workRect = {0};
+ HBRUSH hbr = CreateSolidBrush( GetSysColor( COLOR_3DFACE ));
+ DRAWITEMSTRUCT *dis = ( DRAWITEMSTRUCT * )lParam;
+ mWidth = dis->rcItem.right-dis->rcItem.left;
+ mHeight = dis->rcItem.bottom-dis->rcItem.top;
+ memDC = CreateCompatibleDC( dis->hDC );
+ hbmp = ske_CreateDIB32( mWidth, mHeight );
+ holdbmp = ( HBITMAP )SelectObject( memDC, hbmp );
+ workRect = dis->rcItem;
+ OffsetRect( &workRect, -workRect.left, -workRect.top );
+ FillRect( memDC, &workRect, hbr );
+ DeleteObject( hbr );
+ if ( hPreviewBitmap )
+ {
+ //variables
+ BITMAP bmp = {0};
+ POINT imgPos = {0};
+ int wWidth, wHeight;
+ int dWidth, dHeight;
+ float xScale = 1, yScale = 1;
+ //GetSize
+ GetObject( hPreviewBitmap, sizeof( BITMAP ), &bmp );
+ wWidth = workRect.right-workRect.left;
+ wHeight = workRect.bottom-workRect.top;
+ if ( wWidth < bmp.bmWidth ) xScale = ( float )wWidth/bmp.bmWidth;
+ if ( wHeight < bmp.bmHeight ) yScale = ( float )wHeight/bmp.bmHeight;
+ xScale = min( xScale, yScale );
+ yScale = xScale;
+ dWidth = ( int )( xScale*bmp.bmWidth );
+ dHeight = ( int )( yScale*bmp.bmHeight );
+ //CalcPosition
+ imgPos.x = workRect.left+(( wWidth-dWidth )>>1 );
+ imgPos.y = workRect.top+(( wHeight-dHeight )>>1 );
+ //DrawImage
+ if ( !g_CluiData.fGDIPlusFail ) //Use gdi+ engine
+ {
+ DrawAvatarImageWithGDIp( memDC, imgPos.x, imgPos.y, dWidth, dHeight, hPreviewBitmap, 0, 0, bmp.bmWidth, bmp.bmHeight, 8, 255 );
+ }
+ else
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ imgDC = CreateCompatibleDC( dis->hDC );
+ imgOldbmp = ( HBITMAP )SelectObject( imgDC, hPreviewBitmap );
+ ske_AlphaBlend( memDC, imgPos.x, imgPos.y, dWidth, dHeight, imgDC, 0, 0, bmp.bmWidth, bmp.bmHeight, bf );
+ SelectObject( imgDC, imgOldbmp );
+ mod_DeleteDC( imgDC );
+ }
+ }
+ BitBlt( dis->hDC, dis->rcItem.left, dis->rcItem.top, mWidth, mHeight, memDC, 0, 0, SRCCOPY );
+ SelectObject( memDC, holdbmp );
+ DeleteObject( hbmp );
+ mod_DeleteDC( memDC );
+ }
+ break;
+
+ case WM_NOTIFY:
+ switch (( ( LPNMHDR )lParam )->idFrom )
+ {
+ case IDC_TREE1:
+ {
+ NMTREEVIEW * nmtv = ( NMTREEVIEW * ) lParam;
+ if ( !nmtv ) return 0;
+ if ( nmtv->hdr.code == TVN_SELCHANGEDA
+ || nmtv->hdr.code == TVN_SELCHANGEDW )
+ {
+ SkinListData * sd = NULL;
+ if ( hPreviewBitmap )
+ {
+ ske_UnloadGlyphImage( hPreviewBitmap );
+ hPreviewBitmap = NULL;
+ }
+ if ( nmtv->itemNew.lParam )
+ {
+ sd = ( SkinListData* )nmtv->itemNew.lParam;
+ {
+ TCHAR buf[MAX_PATH];
+ CallService( MS_UTILS_PATHTORELATIVET, ( WPARAM )sd->File, ( LPARAM )buf );
+ SendDlgItemMessage( hwndDlg, IDC_EDIT_SKIN_FILENAME, WM_SETTEXT, 0, ( LPARAM )buf );
+ }
+ {
+ TCHAR prfn[MAX_PATH] = {0};
+ TCHAR imfn[MAX_PATH] = {0};
+ TCHAR skinfolder[MAX_PATH] = {0};
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Preview" ), _T( "" ), imfn, SIZEOF( imfn ), sd->File );
+ IniParser::GetSkinFolder( sd->File, skinfolder );
+ _sntprintf( prfn, SIZEOF( prfn ), _T("%s\\%s"), skinfolder, imfn );
+ CallService( MS_UTILS_PATHTOABSOLUTET, ( WPARAM )prfn, ( LPARAM ) imfn );
+ char * imfn_ch = mir_t2a( imfn );
+ hPreviewBitmap = ske_LoadGlyphImage( imfn_ch );
+ mir_free( imfn_ch );
+ }
+ EnableWindow( GetDlgItem( hwndDlg, IDC_BUTTON_APPLY_SKIN ), TRUE );
+ EnableWindow( GetDlgItem( hwndDlg, IDC_BUTTON_INFO ), TRUE );
+ if ( hPreviewBitmap )
+ InvalidateRect( GetDlgItem( hwndDlg, IDC_PREVIEW ), NULL, TRUE );
+ else //prepare text
+ {
+ TCHAR Author[255];
+ TCHAR URL[MAX_PATH];
+ TCHAR Contact[255];
+ TCHAR Description[400];
+ TCHAR text[2000];
+ SkinListData* sd = NULL;
+ HTREEITEM hti = TreeView_GetSelection( GetDlgItem( hwndDlg, IDC_TREE1 ));
+ if ( hti == 0 ) return 0;
+ {
+ TVITEM tvi = {0};
+ tvi.hItem = hti;
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ TreeView_GetItem( GetDlgItem( hwndDlg, IDC_TREE1 ), &tvi );
+ sd = ( SkinListData* )( tvi.lParam );
+ }
+ if ( !sd ) return 0;
+
+ if ( sd->File && !_tcschr( sd->File, _T('%')))
+ {
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Author" ), TranslateT( "( unknown )" ), Author, SIZEOF( Author ), sd->File );
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "URL" ), _T( "" ), URL, SIZEOF( URL ), sd->File );
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Contact" ), _T( "" ), Contact, SIZEOF( Contact ), sd->File );
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Description" ), _T( "" ), Description, SIZEOF( Description ), sd->File );
+ _sntprintf( text, SIZEOF( text ), TranslateT( "Preview is not available\n\n%s\n----------------------\n\n%s\n\nAUTHOR(S):\n%s\n\nCONTACT:\n%s\n\nHOMEPAGE:\n%s" ),
+ sd->Name, Description, Author, Contact, URL );
+ }
+ else
+ {
+ _sntprintf( text, SIZEOF( text ), TranslateT( "%s\n\n%s\n\nAUTHORS:\n%s\n\nCONTACT:\n%s\n\nWEB:\n%s\n\n\n" ),
+ TranslateT( "reVista for Modern v0.5" ),
+ TranslateT( "This is second default Modern Contact list skin in Vista Aero style" ),
+ TranslateT( "graphics by Angeli-Ka\ntemplate by FYR" ),
+ _T("JID: fyr@jabber.ru"),
+ _T("fyr.mirandaim.ru"));
+ }
+ ShowWindow( GetDlgItem( hwndDlg, IDC_PREVIEW ), SW_HIDE );
+ ShowWindow( GetDlgItem( hwndDlg, IDC_STATIC_INFO ), SW_SHOW );
+ SendDlgItemMessage( hwndDlg, IDC_STATIC_INFO, WM_SETTEXT, 0, ( LPARAM )text );
+ }
+ }
+ else
+ {
+ //no selected
+ SendDlgItemMessage( hwndDlg, IDC_EDIT_SKIN_FILENAME, WM_SETTEXT, 0, ( LPARAM )TranslateT( "Select skin from list" ));
+ EnableWindow( GetDlgItem( hwndDlg, IDC_BUTTON_APPLY_SKIN ), FALSE );
+ EnableWindow( GetDlgItem( hwndDlg, IDC_BUTTON_INFO ), FALSE );
+ SendDlgItemMessage( hwndDlg, IDC_STATIC_INFO, WM_SETTEXT, 0, ( LPARAM )TranslateT( "Please select skin to apply" ));
+ ShowWindow( GetDlgItem( hwndDlg, IDC_PREVIEW ), SW_HIDE );
+ }
+ ShowWindow( GetDlgItem( hwndDlg, IDC_PREVIEW ), hPreviewBitmap?SW_SHOW:SW_HIDE );
+ return 0;
+ }
+ else if ( nmtv->hdr.code == TVN_DELETEITEMA || nmtv->hdr.code == TVN_DELETEITEMW )
+ {
+ mir_free_and_nil( nmtv->itemOld.lParam );
+ return 0;
+ }
+ break;
+ }
+ case 0:
+ switch (( ( LPNMHDR )lParam )->code )
+ {
+ case PSN_APPLY:
+ {
+ {
+ DWORD tick = GetTickCount( );
+ pcli->pfnClcBroadcast( INTM_RELOADOPTIONS, 0, 0 );
+ NotifyEventHooks( g_CluiData.hEventBkgrChanged, 0, 0 );
+ pcli->pfnClcBroadcast( INTM_INVALIDATE, 0, 0 );
+ RedrawWindow( GetParent( pcli->hwndContactTree ), NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_ALLCHILDREN );
+ }
+ return 0;
+ }
+ break;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+int SearchSkinFiles( HWND hwndDlg, TCHAR * Folder )
+{
+ struct _tfinddata_t fd = {0};
+ TCHAR mask[MAX_PATH];
+ long hFile;
+ _sntprintf( mask, SIZEOF( mask ), _T("%s\\*.msf"), Folder );
+ //fd.attrib = _A_SUBDIR;
+ hFile = _tfindfirst( mask, &fd );
+ if ( hFile != -1 )
+ {
+ do {
+ AddSkinToList( hwndDlg, Folder, fd.name );
+ }while ( !_tfindnext( hFile, &fd ));
+ _findclose( hFile );
+ }
+ _sntprintf( mask, SIZEOF( mask ), _T("%s\\*"), Folder );
+ hFile = _tfindfirst( mask, &fd );
+ {
+ do {
+ if ( fd.attrib&_A_SUBDIR && !( _tcsicmp( fd.name, _T(".")) == 0 || _tcsicmp( fd.name, _T("..")) == 0 ))
+ {//Next level of subfolders
+ TCHAR path[MAX_PATH];
+ _sntprintf( path, SIZEOF( path ), _T("%s\\%s"), Folder, fd.name );
+ SearchSkinFiles( hwndDlg, path );
+ }
+ }while ( !_tfindnext( hFile, &fd ));
+ _findclose( hFile );
+ }
+ return 0;
+}
+HTREEITEM FillAvailableSkinList( HWND hwndDlg )
+{
+ struct _finddata_t fd = {0};
+ //long hFile;
+ HTREEITEM res = (HTREEITEM)-1;
+ TCHAR path[MAX_PATH];//, mask[MAX_PATH];
+ int attrib;
+ TCHAR *SkinsFolder = DBGetStringT( NULL, "ModernData", "SkinsFolder" );
+ if ( !SkinsFolder ) SkinsFolder = mir_tstrdup( _T("Skins"));
+
+ CallService( MS_UTILS_PATHTOABSOLUTET, ( WPARAM )SkinsFolder, ( LPARAM )path );
+ mir_free_and_nil( SkinsFolder );
+
+ AddSkinToList( hwndDlg, TranslateT( "Default Skin" ), _T("%Default Skin%"));
+ attrib = GetFileAttributes( path );
+ if ( attrib != INVALID_FILE_ATTRIBUTES && ( attrib & FILE_ATTRIBUTE_DIRECTORY ))
+ SearchSkinFiles( hwndDlg, path );
+ {
+ TCHAR * skinfile;
+ TCHAR skinfull[MAX_PATH];
+ skinfile = DBGetStringT( NULL, SKIN, "SkinFile" );
+ if ( skinfile )
+ {
+ CallService( MS_UTILS_PATHTOABSOLUTET, ( WPARAM )skinfile, ( LPARAM )skinfull );
+ res = AddSkinToListFullName( hwndDlg, skinfull );
+
+ mir_free( skinfile );
+ }
+ }
+ return res;
+}
+HTREEITEM AddSkinToListFullName( HWND hwndDlg, TCHAR * fullName )
+{
+ TCHAR path[MAX_PATH] = {0};
+ TCHAR file[MAX_PATH] = {0};
+ TCHAR *buf;
+ _tcsncpy( path, fullName, SIZEOF( path ));
+ buf = path + _tcslen( path );
+ while ( buf > path )
+ {
+ if ( *buf == _T( '\\' ))
+ {
+ *buf = _T( '\0' );
+ break;
+ }
+ buf--;
+ }
+ buf++;
+ _tcsncpy( file, buf, SIZEOF( file ));
+ return AddSkinToList( hwndDlg, path, file );
+}
+
+
+HTREEITEM AddSkinToList( HWND hwndDlg, TCHAR * path, TCHAR* file )
+{
+ {
+ TCHAR buf[MAX_PATH];
+ _sntprintf( buf, SIZEOF( buf ), _T("%s\\%s"), path, file );
+
+ }
+ {
+ TCHAR fullName[MAX_PATH] = {0};
+ TCHAR defskinname[MAX_PATH] = {0};
+ SkinListData * sd = NULL;
+ sd = ( SkinListData * )mir_alloc( sizeof( SkinListData ));
+ if ( !sd ) return 0;
+ _sntprintf( fullName, SIZEOF( fullName ), _T("%s\\%s"), path, file );
+ memmove( defskinname, file, (_tcslen( file )-4) * sizeof(TCHAR));
+ defskinname[_tcslen( file )+1] = _T('\0');
+ if ( !file || _tcschr( file, _T('%')))
+ {
+ //sd->File = "%Default Skin%";
+ _sntprintf( sd->File, MAX_PATH, _T("%%Default Skin%%"));
+ _sntprintf( sd->Name, 100, TranslateT( "%Default Skin%" ));
+ return AddItemToTree( GetDlgItem( hwndDlg, IDC_TREE1 ), TranslateT( "Default Skin" ), sd->Name, sd );
+ }
+ else
+ {
+ GetPrivateProfileString( _T("Skin_Description_Section"), _T("Name"), defskinname, sd->Name, SIZEOF( sd->Name ), fullName );
+ _tcscpy( sd->File, fullName );
+ }
+ return AddItemToTree( GetDlgItem( hwndDlg, IDC_TREE1 ), fullName, sd->Name, sd );
+ }
+ return (HTREEITEM)-1;
+}
+
+
+
+HTREEITEM FindChild( HWND hTree, HTREEITEM Parent, TCHAR * Caption, void * data )
+{
+ HTREEITEM res = NULL, tmp = NULL;
+ if ( Parent )
+ tmp = TreeView_GetChild( hTree, Parent );
+ else
+ tmp = TreeView_GetRoot( hTree );
+ while ( tmp )
+ {
+ TVITEM tvi;
+ TCHAR buf[255];
+ tvi.hItem = tmp;
+ tvi.mask = TVIF_TEXT|TVIF_HANDLE;
+ tvi.pszText = (LPTSTR)&buf;
+ tvi.cchTextMax = 254;
+ TreeView_GetItem( hTree, &tvi );
+ if ( _tcsicmp( Caption, tvi.pszText ) == 0 )
+ {
+ if ( data )
+ {
+ SkinListData * sd = NULL;
+ TVITEM tvi = {0};
+ tvi.hItem = tmp;
+ tvi.mask = TVIF_HANDLE|TVIF_PARAM;
+ TreeView_GetItem( hTree, &tvi );
+ sd = ( SkinListData* )( tvi.lParam );
+ if ( sd )
+ if ( !_tcsicmp( sd->File, (( SkinListData* )data )->File ))
+ return tmp;
+ }
+ else
+ return tmp;
+ }
+ tmp = TreeView_GetNextSibling( hTree, tmp );
+ }
+ return tmp;
+}
+
+
+HTREEITEM AddItemToTree( HWND hTree, TCHAR * folder, TCHAR * itemName, void * data )
+{
+ HTREEITEM rootItem = NULL;
+ HTREEITEM cItem = NULL;
+ TCHAR path[MAX_PATH];//, mask[MAX_PATH];
+ TCHAR * ptr;
+ TCHAR * ptrE;
+ BOOL ext = FALSE;
+ CallService( MS_UTILS_PATHTORELATIVET, ( WPARAM )folder, ( LPARAM )path );
+ ptrE = path;
+ while ( *ptrE != _T('\\') && *ptrE != _T('\0') && *ptrE != _T(':')) ptrE++;
+ if ( *ptrE == _T('\\'))
+ {
+ *ptrE = _T('\0');
+ ptrE++;
+ }
+ else ptrE = path;
+ ptr = ptrE;
+ do
+ {
+
+ while ( *ptrE != _T('\\') && *ptrE != _T('\0')) ptrE++;
+ if ( *ptrE == _T('\\'))
+ {
+ *ptrE = _T('\0');
+ ptrE++;
+ // find item if not - create;
+ {
+ cItem = FindChild( hTree, rootItem, ptr, NULL );
+ if ( !cItem ) // not found - create node
+ {
+ TVINSERTSTRUCT tvis;
+ tvis.hParent = rootItem;
+ tvis.hInsertAfter = TVI_ROOT;
+ tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_PARAM;
+ tvis.item.pszText = ptr;
+ {
+ tvis.item.lParam = ( LPARAM )NULL;
+ }
+ cItem = TreeView_InsertItem( hTree, &tvis );
+
+ }
+ rootItem = cItem;
+ }
+ ptr = ptrE;
+ }
+ else ext = TRUE;
+ }while ( !ext );
+ //Insert item node
+ cItem = FindChild( hTree, rootItem, itemName, data );
+ if ( !cItem )
+ {
+ TVINSERTSTRUCT tvis;
+ tvis.hParent = rootItem;
+ tvis.hInsertAfter = TVI_SORT;
+ tvis.item.mask = TVIF_PARAM|TVIF_TEXT|TVIF_PARAM;
+ tvis.item.pszText = itemName;
+ tvis.item.lParam = ( LPARAM )data;
+ return TreeView_InsertItem( hTree, &tvis );
+ }
+ else
+ {
+ mir_free( data ); //need to free otherwise memory leak
+ return cItem;
+ }
+ return 0;
+}
+
+INT_PTR SvcActiveSkin(WPARAM wParam, LPARAM lParam)
+{
+ TCHAR *skinfile;
+ TCHAR skinfull[MAX_PATH];
+ skinfile = DBGetStringT( NULL, SKIN, "SkinFile" );
+ if ( skinfile ) {
+ CallService( MS_UTILS_PATHTOABSOLUTET, ( WPARAM )skinfile, ( LPARAM )skinfull );
+ mir_free(skinfile);
+ return (INT_PTR)mir_tstrdup(skinfull);
+ }
+
+ return NULL;
+}
+
+INT_PTR SvcApplySkin(WPARAM wParam, LPARAM lParam)
+{
+ ske_LoadSkinFromIniFile((TCHAR *)lParam, FALSE );
+ ske_LoadSkinFromDB( );
+ glOtherSkinWasLoaded = TRUE;
+ pcli->pfnClcBroadcast( INTM_RELOADOPTIONS, 0, 0 );
+ Sync( CLUIFrames_OnClistResize_mod, 0, 0 );
+ ske_RedrawCompleteWindow( );
+ Sync( CLUIFrames_OnClistResize_mod, 0, 0 );
+ {
+ HWND hwnd = pcli->hwndContactList;
+ RECT rc = {0};
+ GetWindowRect( hwnd, &rc );
+ Sync( CLUIFrames_OnMoving, hwnd, &rc );
+ }
+ if ( g_hCLUIOptionsWnd )
+ {
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_LEFTMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "LeftClientMargin", SETTING_LEFTCLIENTMARIGN_DEFAULT ));
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_RIGHTMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "RightClientMargin", SETTING_RIGHTCLIENTMARIGN_DEFAULT ));
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_TOPMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "TopClientMargin", SETTING_TOPCLIENTMARIGN_DEFAULT ));
+ SendDlgItemMessage( g_hCLUIOptionsWnd, IDC_BOTTOMMARGINSPIN, UDM_SETPOS, 0, db_get_b( NULL, "CLUI", "BottomClientMargin", SETTING_BOTTOMCLIENTMARIGN_DEFAULT ));
+ }
+ return 0;
+}
+
+INT_PTR SvcPreviewSkin(WPARAM wParam, LPARAM lParam)
+{
+ DRAWITEMSTRUCT *dis = ( DRAWITEMSTRUCT * )wParam;
+
+ HDC imgDC;
+ HBITMAP imgOldbmp;
+ int mWidth, mHeight;
+ RECT workRect = {0};
+ mWidth = dis->rcItem.right-dis->rcItem.left;
+ mHeight = dis->rcItem.bottom-dis->rcItem.top;
+ workRect = dis->rcItem;
+ OffsetRect( &workRect, -workRect.left, -workRect.top );
+
+ if (lParam)
+ {
+ TCHAR prfn[MAX_PATH] = {0};
+ TCHAR imfn[MAX_PATH] = {0};
+ TCHAR skinfolder[MAX_PATH] = {0};
+ GetPrivateProfileString( _T( "Skin_Description_Section" ), _T( "Preview" ), _T( "" ), imfn, SIZEOF( imfn ), (LPCTSTR)lParam );
+ IniParser::GetSkinFolder((LPCTSTR)lParam, skinfolder );
+ _sntprintf( prfn, SIZEOF( prfn ), _T("%s\\%s"), skinfolder, imfn );
+ CallService( MS_UTILS_PATHTOABSOLUTET, ( WPARAM )prfn, ( LPARAM ) imfn );
+ char * imfn_ch = mir_t2a( imfn );
+ hPreviewBitmap = ske_LoadGlyphImage( imfn_ch );
+ mir_free( imfn_ch );
+
+ if ( hPreviewBitmap )
+ {
+ //variables
+ BITMAP bmp = {0};
+ POINT imgPos = {0};
+ int wWidth, wHeight;
+ int dWidth, dHeight;
+ float xScale = 1, yScale = 1;
+ //GetSize
+ GetObject( hPreviewBitmap, sizeof( BITMAP ), &bmp );
+ wWidth = workRect.right-workRect.left;
+ wHeight = workRect.bottom-workRect.top;
+ if ( wWidth < bmp.bmWidth ) xScale = ( float )wWidth/bmp.bmWidth;
+ if ( wHeight < bmp.bmHeight ) yScale = ( float )wHeight/bmp.bmHeight;
+ xScale = min( xScale, yScale );
+ yScale = xScale;
+ dWidth = ( int )( xScale*bmp.bmWidth );
+ dHeight = ( int )( yScale*bmp.bmHeight );
+ //CalcPosition
+ imgPos.x = workRect.left+(( wWidth-dWidth )>>1 );
+ imgPos.y = workRect.top+(( wHeight-dHeight )>>1 );
+ //DrawImage
+ if ( !g_CluiData.fGDIPlusFail ) //Use gdi+ engine
+ {
+ DrawAvatarImageWithGDIp( dis->hDC, imgPos.x, imgPos.y, dWidth, dHeight, hPreviewBitmap, 0, 0, bmp.bmWidth, bmp.bmHeight, 8, 255 );
+ }
+ else
+ {
+ BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
+ imgDC = CreateCompatibleDC( dis->hDC );
+ imgOldbmp = ( HBITMAP )SelectObject( imgDC, hPreviewBitmap );
+ ske_AlphaBlend( dis->hDC, imgPos.x, imgPos.y, dWidth, dHeight, imgDC, 0, 0, bmp.bmWidth, bmp.bmHeight, bf );
+ SelectObject( imgDC, imgOldbmp );
+ mod_DeleteDC( imgDC );
+ }
+ ske_UnloadGlyphImage(hPreviewBitmap);
+ }
+ }
+
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_skinselector.cpp b/plugins/Clist_modern/src/modern_skinselector.cpp
new file mode 100644
index 0000000000..2500bc3ac6
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_skinselector.cpp
@@ -0,0 +1,792 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+///// structures and services to manage modern skin objects (mask mechanism)
+
+//#include "windows.h"
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_skinselector.h"
+#include "hdr/modern_skinengine.h"
+#include "m_api/m_skin_eng.h"
+#include "m_api/m_skinbutton.h"
+#include "hdr/modern_commonprototypes.h"
+LISTMODERNMASK * MainModernMaskList = NULL;
+
+
+/// IMPLEMENTATIONS
+char * ModernMaskToString(MODERNMASK * mm, char * buf, UINT bufsize)
+{
+ int i=0;
+ for (i=0; i < (int)mm->dwParamCnt;i++)
+ {
+ if (mm->pl_Params[i].bMaskParamFlag)
+ {
+ if (i>0) _snprintf(buf,bufsize,"%s%%",buf);
+ if (mm->pl_Params[i].bMaskParamFlag &MPF_DIFF)
+ _snprintf(buf,bufsize,"%s = %s",mm->pl_Params[i].szName,mm->pl_Params[i].szValue);
+ else
+ _snprintf(buf,bufsize,"%s^%s",mm->pl_Params[i].szName,mm->pl_Params[i].szValue);
+ }
+ else break;
+ }
+ return buf;
+}
+int SkinSelector_DeleteMask(MODERNMASK * mm)
+{
+ int i;
+ if ( !mm->pl_Params) return 0;
+ for (i=0;i < (int)mm->dwParamCnt;i++)
+ {
+ if (mm->pl_Params[i].szName) free(mm->pl_Params[i].szName);
+ if (mm->pl_Params[i].szValue) free(mm->pl_Params[i].szValue);
+ }
+ free(mm->pl_Params);
+ return 1;
+}
+
+#define _qtoupper(_c) (((_c) >= 'a' && (_c) <= 'z')?((_c)-('a'+'A')):(_c))
+BOOL wildcmpi(TCHAR* name, TCHAR* mask)
+{
+ TCHAR* last = '\0';
+ for (;; mask++, name++)
+ {
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break;
+ if (*name == '\0') return ((BOOL)!*mask);
+ }
+ if (*mask != '*') return FALSE;
+ for (;; mask++, name++)
+ {
+ while(*mask == '*')
+ {
+ last = mask++;
+ if (*mask == '\0') return ((BOOL)!*mask); /* true */
+ }
+ if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last;
+ }
+}
+
+BOOL wildcmpi(char * name, char * mask)
+{
+ char * last = '\0';
+ for (;; mask++, name++)
+ {
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) break;
+ if (*name == '\0') return ((BOOL)!*mask);
+ }
+ if (*mask != '*') return FALSE;
+ for (;; mask++, name++)
+ {
+ while(*mask == '*')
+ {
+ last = mask++;
+ if (*mask == '\0') return ((BOOL)!*mask); /* true */
+ }
+ if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
+ if (*mask != '?' && _qtoupper(*mask) != _qtoupper(*name)) name -= (size_t)(mask - last) - 1, mask = last;
+ }
+}
+
+BOOL __inline wildcmp(const char * name, const char * mask, BYTE option)
+{
+ const char * last = '\0';
+ for (;; mask++, name++)
+ {
+ if (*mask != '?' && *mask != *name) break;
+ if (*name == '\0') return ((BOOL)!*mask);
+ }
+ if (*mask != '*') return FALSE;
+ for (;; mask++, name++)
+ {
+ while(*mask == '*')
+ {
+ last = mask++;
+ if (*mask == '\0') return ((BOOL)!*mask); /* true */
+ }
+ if (*name == '\0') return ((BOOL)!*mask); /* *mask == EOS */
+ if (*mask != '?' && *mask != *name) name -= (size_t)(mask - last) - 1, mask = last;
+ }
+}
+
+BOOL MatchMask(char * name, char * mask)
+{
+ if ( !mask || !name) return mask == name;
+ if (*mask != '|') return wildcmpi(name,mask);
+ {
+ int s = 1,e = 1;
+ char * temp;
+ while (mask[e] != '\0')
+ {
+ s = e;
+ while(mask[e] != '\0' && mask[e] != '|') e++;
+ temp = (char*)malloc(e-s+1);
+ memcpy(temp,mask+s,e-s);
+ temp[e-s] = '\0';
+ if (wildcmpi(name,temp))
+ {
+ free(temp);
+ return TRUE;
+ }
+ free(temp);
+ if (mask[e] != '\0') e++;
+ else return FALSE;
+ }
+ return FALSE;
+ }
+ return FALSE;
+}
+#if __GNUC__
+#define NOINLINEASM
+#endif
+
+DWORD mod_CalcHash(const char *szStr)
+{
+#if defined _M_IX86 && !defined _NUMEGA_BC_FINALCHECK && !defined NOINLINEASM
+ __asm { //this breaks if szStr is empty
+ xor edx,edx
+ xor eax,eax
+ mov esi,szStr
+ mov al,[esi]
+ xor cl,cl
+lph_top: //only 4 of 9 instructions in here don't use AL, so optimal pipe use is impossible
+ xor edx,eax
+ inc esi
+ xor eax,eax
+ and cl,31
+ mov al,[esi]
+ add cl,5
+ test al,al
+ rol eax,cl //rol is u-pipe only, but pairable
+ //rol doesn't touch z-flag
+ jnz lph_top //5 clock tick loop. not bad.
+
+ xor eax,edx
+ }
+#else
+ DWORD hash = 0;
+ int i;
+ int shift = 0;
+ for (i=0;szStr[i];i++) {
+ hash ^= szStr[i] << shift;
+ if (shift>24) hash ^= (szStr[i]>>(32-shift))&0x7F;
+ shift = (shift+5)&0x1F;
+ }
+ return hash;
+#endif
+}
+
+/*
+DWORD mod_CalcHash(const char * a)
+{
+ DWORD Val = 0;
+ BYTE N;
+ DWORD k = mir_strlen(a);
+ if (k < 23) N = (BYTE)k; else N = 23;
+ while (N>0)
+ {
+ Val = Val << 1;
+ Val ^= ((DWORD)*a++)-31;
+ N--;
+ }
+ return Val;
+}
+*/
+int AddModernMaskToList(MODERNMASK * mm, LISTMODERNMASK * mmTemplateList)
+{
+ if ( !mmTemplateList || !mm) return -1;
+ mmTemplateList->pl_Masks = (MODERNMASK *)mir_realloc(mmTemplateList->pl_Masks,sizeof(MODERNMASK)*(mmTemplateList->dwMaskCnt+1));
+ memmove(&(mmTemplateList->pl_Masks[mmTemplateList->dwMaskCnt]),mm,sizeof(MODERNMASK));
+ mmTemplateList->dwMaskCnt++;
+ return mmTemplateList->dwMaskCnt-1;
+}
+
+int ClearMaskList(LISTMODERNMASK * mmTemplateList)
+{
+ int i;
+ if ( !mmTemplateList) return -1;
+ if ( !mmTemplateList->pl_Masks) return -1;
+ for (i=0; i < (int)mmTemplateList->dwMaskCnt; i++)
+ SkinSelector_DeleteMask(&(mmTemplateList->pl_Masks[i]));
+ mir_free_and_nil(mmTemplateList->pl_Masks);
+ mmTemplateList->dwMaskCnt = 0;
+ return 0;
+}
+int DeleteMaskByItID(DWORD mID,LISTMODERNMASK * mmTemplateList)
+{
+ if ( !mmTemplateList) return -1;
+ if (mID < 0 || mID >= mmTemplateList->dwMaskCnt) return -1;
+ if (mmTemplateList->dwMaskCnt == 1)
+ {
+ SkinSelector_DeleteMask(&(mmTemplateList->pl_Masks[0]));
+ mir_free_and_nil(mmTemplateList->pl_Masks);
+ mmTemplateList->pl_Masks = NULL;
+ mmTemplateList->dwMaskCnt;
+ }
+ else
+ {
+ MODERNMASK * newAlocation;
+ DWORD i;
+ SkinSelector_DeleteMask(&(mmTemplateList->pl_Masks[mID]));
+ newAlocation = (MODERNMASK *)mir_alloc(sizeof(MODERNMASK)*mmTemplateList->dwMaskCnt-1);
+ memmove(newAlocation,mmTemplateList->pl_Masks,sizeof(MODERNMASK)*(mID+1));
+ for (i = mID; i < mmTemplateList->dwMaskCnt-1; i++)
+ {
+ newAlocation[i] = mmTemplateList->pl_Masks[i+1];
+ newAlocation[i].dwMaskId = i;
+ }
+ mir_free_and_nil(mmTemplateList->pl_Masks);
+ mmTemplateList->pl_Masks = newAlocation;
+ mmTemplateList->dwMaskCnt--;
+ }
+ return mmTemplateList->dwMaskCnt;
+}
+
+
+int ExchangeMasksByID(DWORD mID1, DWORD mID2, LISTMODERNMASK * mmTemplateList)
+{
+ if ( !mmTemplateList) return 0;
+ if (mID1 < 0 || mID1 >= mmTemplateList->dwMaskCnt) return 0;
+ if (mID2 < 0 || mID2 >= mmTemplateList->dwMaskCnt) return 0;
+ if (mID1 == mID2) return 0;
+ {
+ MODERNMASK mm;
+ mm = mmTemplateList->pl_Masks[mID1];
+ mmTemplateList->pl_Masks[mID1] = mmTemplateList->pl_Masks[mID2];
+ mmTemplateList->pl_Masks[mID2] = mm;
+ }
+ return 1;
+}
+int SortMaskList(LISTMODERNMASK * mmList)
+{
+ DWORD pos = 1;
+ if (mmList->dwMaskCnt < 2) return 0;
+ do {
+ if (mmList->pl_Masks[pos].dwMaskId < mmList->pl_Masks[pos-1].dwMaskId)
+ {
+ ExchangeMasksByID(pos, pos-1, mmList);
+ pos--;
+ if (pos < 1)
+ pos = 1;
+ }
+ else
+ pos++;
+ } while(pos < mmList->dwMaskCnt);
+
+ return 1;
+}
+
+enum
+{
+ EXCEPTION_EQUAL,
+ EXCEPTION_NOT_EQUAL = 1,
+ EXCEPTION_WILD = 2,
+};
+static BOOL _GetParamValue( char * szText, unsigned int& start, unsigned int length, char* &param, unsigned int& paramlen, char* &value, unsigned int& valuelen, int& except )
+{
+ char * curChar = szText + start;
+ char * lastChar = szText + length;
+
+ enum { STATE_PARAM, STATE_VALUE };
+ int state = STATE_PARAM;
+ if ( start >= length ) return FALSE;
+
+ paramlen = 0;
+ valuelen = 0;
+ value = NULL;
+ param = NULL;
+
+ except = EXCEPTION_EQUAL;
+ param = curChar;
+
+
+ BOOL exitLoop = false;
+ while ( !exitLoop )
+ {
+ switch ( *curChar )
+ {
+
+ case '^':
+ if ( state == STATE_VALUE ) break;
+ except |= EXCEPTION_NOT_EQUAL;
+ exitLoop = TRUE;
+ //fall trough
+ case '=':
+ if ( state == STATE_VALUE ) break;
+ //search value end
+ paramlen = curChar - param;
+ exitLoop = TRUE;
+ break;
+
+ case ',':
+ default:
+ if ( *curChar != ',' && curChar < lastChar ) break;
+ if ( state == STATE_PARAM )
+ {
+ // no parameter name only value
+ value = param;
+ param = NULL;
+ paramlen = 0;
+ state = STATE_VALUE;
+ }
+ exitLoop = TRUE;
+ break;
+ case '*': case '?':
+ if (state == STATE_PARAM ) break;
+ except |= EXCEPTION_WILD;
+ break;
+ }
+ if ( exitLoop)
+ {
+ if (state == STATE_PARAM )
+ {
+ paramlen = curChar - param;
+ state = STATE_VALUE;
+ curChar++; //skip Sign
+ value = curChar;
+ exitLoop = FALSE;
+ }
+ else if ( state == STATE_VALUE )
+ {
+ valuelen = curChar - value;
+ }
+ }
+ else
+ {
+ curChar++;
+ }
+ }
+
+
+ start = curChar - szText + 1;
+ // skip spaces
+ if ( value && valuelen )
+ {
+ while ( *value == ' ' || *value == '\t' )
+ {
+ value++;
+ valuelen--;
+ }
+ while ( *( value + valuelen - 1) == ' ' || *( value + valuelen -1 ) == '\t' )
+ valuelen--;
+ }
+
+ if ( param && paramlen )
+ {
+ while (*param == ' ' || *param == '\t' )
+ {
+ param++;
+ paramlen--;
+ }
+ while (*(param+paramlen-1) == ' ' || *(param+paramlen-1) == '\t' )
+ paramlen--;
+ }
+
+ return ( value || param );
+}
+
+int ParseToModernMask(MODERNMASK * mm, char * szText)
+{
+ if ( !mm || !szText) return -1;
+
+ unsigned int textLen = mir_strlen(szText);
+ BYTE curParam = 0;
+
+ MASKPARAM param = {0};
+
+ unsigned int startPos = 0;
+ char * pszParam;
+ char * pszValue;
+ unsigned int paramlen;
+ unsigned int valuelen;
+ int except;
+
+ while ( _GetParamValue( szText, startPos, textLen, pszParam, paramlen, pszValue, valuelen, except))
+ {
+ if ( except & EXCEPTION_NOT_EQUAL )
+ param.bMaskParamFlag = MPF_NOT_EQUAL;
+ else
+ param.bMaskParamFlag = MPF_EQUAL;
+
+ //Get param name
+ if ( pszParam && paramlen )
+ {
+ param.szName = strdupn( pszParam, paramlen);
+ param.dwId = mod_CalcHash( param.szName );
+ }
+ else //ParamName = 'Module'
+ {
+ param.szName = _strdup( "Module");
+ param.dwId = mod_CalcHash( param.szName );
+ }
+
+
+ param.szValue = strdupn( pszValue, valuelen );
+
+ if ( !(except & EXCEPTION_WILD))
+ {
+ param.dwValueHash = mod_CalcHash( param.szValue );
+ param.bMaskParamFlag |= MPF_HASHED;
+ }
+ if (curParam >= mm->dwParamCnt)
+ {
+ mm->pl_Params = (MASKPARAM*)realloc(mm->pl_Params,(mm->dwParamCnt+1)*sizeof(MASKPARAM));
+ mm->dwParamCnt++;
+ }
+ memmove(&(mm->pl_Params[curParam]),&param,sizeof(MASKPARAM));
+ curParam++;
+ memset(&param,0,sizeof(MASKPARAM));
+ }
+ return 0;
+};
+
+BOOL CompareModernMask(MODERNMASK * mmValue,MODERNMASK * mmTemplate)
+{
+ //TODO
+ BOOL res = TRUE;
+ BOOL exit = FALSE;
+ BYTE pVal = 0, pTemp = 0;
+ while (pTemp < mmTemplate->dwParamCnt && pVal < mmValue->dwParamCnt && !exit)
+ {
+ // find pTemp parameter in mValue
+ DWORD vh, ph;
+ BOOL finded = 0;
+ MASKPARAM p = mmTemplate->pl_Params[pTemp];
+ ph = p.dwId;
+ vh = p.dwValueHash;
+ pVal = 0;
+ if ( p.bMaskParamFlag& MPF_HASHED ) //compare by hash
+ while (pVal < mmValue->dwParamCnt && mmValue->pl_Params[pVal].bMaskParamFlag != 0)
+ {
+ if (mmValue->pl_Params[pVal].dwId == ph)
+ {
+ if (mmValue->pl_Params[pVal].dwValueHash == vh){finded = 1; break;}
+ else {finded = 0; break;}
+ }
+ pVal++;
+ }
+ else
+ while (mmValue->pl_Params[pVal].bMaskParamFlag != 0)
+ {
+ if (mmValue->pl_Params[pVal].dwId == ph)
+ {
+ if (wildcmp(mmValue->pl_Params[pVal].szValue,p.szValue,0)){finded = 1; break;}
+ else {finded = 0; break;}
+ }
+ pVal++;
+ }
+ if ( !((finded && !(p.bMaskParamFlag&MPF_DIFF)) || (!finded && (p.bMaskParamFlag&MPF_DIFF))))
+ {res = FALSE; break;}
+ pTemp++;
+ }
+ return res;
+};
+
+BOOL CompareStrWithModernMask(char * szValue,MODERNMASK * mmTemplate)
+{
+ MODERNMASK mmValue = {0};
+ int res;
+ if ( !ParseToModernMask(&mmValue, szValue))
+ {
+ res = CompareModernMask(&mmValue,mmTemplate);
+ SkinSelector_DeleteMask(&mmValue);
+ return res;
+ }
+ else return 0;
+};
+
+//AddingMask
+int AddStrModernMaskToList(DWORD maskID, char * szStr, char * objectName, LISTMODERNMASK * mmTemplateList, void * pObjectList)
+{
+ if ( !szStr || !mmTemplateList) return -1;
+
+ MODERNMASK mm = {0};
+ if (ParseToModernMask(&mm,szStr)) return -1;
+
+ mm.bObjectFound = FALSE;
+ mm.szObjectName = mir_strdup(objectName);
+ //mm.pObject = (void*) ske_FindObjectByName(objectName, OT_ANY, (SKINOBJECTSLIST*) pObjectList);
+ mm.dwMaskId = maskID;
+ return AddModernMaskToList(&mm,mmTemplateList);
+}
+
+//Searching
+MODERNMASK * FindMaskByStr(char * szValue,LISTMODERNMASK * mmTemplateList)
+{
+ //TODO
+ return NULL;
+}
+
+SKINOBJECTDESCRIPTOR * skin_FindObjectByMask (MODERNMASK * mm,LISTMODERNMASK * mmTemplateList)
+{
+ SKINOBJECTDESCRIPTOR * res = NULL;
+ DWORD i=0;
+ while (i < mmTemplateList->dwMaskCnt)
+ {
+ if (CompareModernMask(mm,&(mmTemplateList->pl_Masks[i])))
+ {
+ res = (SKINOBJECTDESCRIPTOR*) mmTemplateList->pl_Masks[i].pObject;
+ return res;
+ }
+ i++;
+ }
+ return res;
+}
+
+SKINOBJECTDESCRIPTOR * skin_FindObjectByRequest(char * szValue,LISTMODERNMASK * mmTemplateList)
+{
+ MODERNMASK mm = {0};
+ SKINOBJECTDESCRIPTOR * res = NULL;
+ if ( !mmTemplateList)
+ if (g_SkinObjectList.pMaskList)
+ mmTemplateList = g_SkinObjectList.pMaskList;
+ else
+ return NULL;
+
+ if ( !mmTemplateList) return NULL;
+ ParseToModernMask(&mm,szValue);
+ res = skin_FindObjectByMask(&mm,mmTemplateList);
+ SkinSelector_DeleteMask(&mm);
+ return res;
+}
+
+TCHAR * GetParamNT(char * string, TCHAR * buf, int buflen, BYTE paramN, char Delim, BOOL SkipSpaces)
+{
+ char *ansibuf = (char*)mir_alloc(buflen/sizeof(TCHAR));
+ GetParamN(string, ansibuf, buflen/sizeof(TCHAR), paramN, Delim, SkipSpaces);
+ MultiByteToWideChar(CP_UTF8,0,ansibuf,-1,buf,buflen);
+ mir_free(ansibuf);
+ return buf;
+}
+
+char * GetParamN(char * string, char * buf, int buflen, BYTE paramN, char Delim, BOOL SkipSpaces)
+{
+ int i=0;
+ DWORD start = 0;
+ DWORD end = 0;
+ DWORD CurentCount = 0;
+ DWORD len;
+ while (i < mir_strlen(string))
+ {
+ if (string[i] == Delim)
+ {
+ if (CurentCount == paramN) break;
+ start = i+1;
+ CurentCount++;
+ }
+ i++;
+ }
+ if (CurentCount == paramN)
+ {
+ if (SkipSpaces)
+ { //remove spaces
+ while (string[start] == ' ' && (int)start < mir_strlen(string))
+ start++;
+ while (i>1 && string[i-1] == ' ' && i>(int)start)
+ i--;
+ }
+ len = ((int)(i-start) < buflen)?i-start:buflen;
+ strncpy(buf,string+start,len);
+ buf[len] = '\0';
+ }
+ else buf[0] = '\0';
+ return buf;
+}
+
+//Parse DB string and add buttons
+int RegisterButtonByParce(char * ObjectName, char * Params)
+{
+ char buf [255];
+ int res;
+ GetParamN(Params,buf, SIZEOF(buf),0,',',0);
+ // if (boolstrcmpi("Push",buf)
+ { //Push type
+ char buf2[20] = {0};
+ char pServiceName[255] = {0};
+ char pStatusServiceName[255] = {0};
+ int Left, Top,Right,Bottom;
+ int MinWidth, MinHeight;
+ char TL[9] = {0};
+ TCHAR Hint[250] = {0};
+ char Section[250] = {0};
+ char Type[250] = {0};
+
+ DWORD alingnto;
+ int a = ((int)mir_bool_strcmpi(buf,"Switch"))*2;
+
+ GetParamN(Params,pServiceName, SIZEOF(pServiceName),1,',',0);
+ // if (a) GetParamN(Params,pStatusServiceName, sizeof(pStatusServiceName),a+1,',',0);
+ Left = atoi(GetParamN(Params,buf2, SIZEOF(buf2),a+2,',',0));
+ Top = atoi(GetParamN(Params,buf2, SIZEOF(buf2),a+3,',',0));
+ Right = atoi(GetParamN(Params,buf2, SIZEOF(buf2),a+4,',',0));
+ Bottom = atoi(GetParamN(Params,buf2, SIZEOF(buf2),a+5,',',0));
+ GetParamN(Params,TL, SIZEOF(TL),a+6,',',0);
+
+ MinWidth = atoi(GetParamN(Params,buf2, SIZEOF(buf2),a+7,',',0));
+ MinHeight = atoi(GetParamN(Params,buf2, SIZEOF(buf2),a+8,',',0));
+ GetParamNT(Params,Hint, SIZEOF(Hint),a+9,',',0);
+ if (a)
+ {
+ GetParamN(Params,Section, SIZEOF(Section),2,',',0);
+ GetParamN(Params,Type, SIZEOF(Type),3,',',0);
+ }
+ alingnto = ((TL[0] == 'R') ? SBF_ALIGN_TL_RIGHT : 0 )
+ +((TL[0] == 'C') ? SBF_ALIGN_TL_HCENTER : 0 )
+ +((TL[1] == 'B') ? SBF_ALIGN_TL_BOTTOM : 0 )
+ +((TL[1] == 'C') ? SBF_ALIGN_TL_VCENTER : 0 )
+ +((TL[2] == 'R') ? SBF_ALIGN_BR_RIGHT : 0 )
+ +((TL[2] == 'C') ? SBF_ALIGN_BR_HCENTER : 0 )
+ +((TL[3] == 'B') ? SBF_ALIGN_BR_BOTTOM : 0 )
+ +((TL[3] == 'C') ? SBF_ALIGN_BR_VCENTER : 0 )
+ +((TL[4] == 'I') ? SBF_CALL_ON_PRESS : 0 );
+ if (a) res = ModernSkinButton_AddButton(pcli->hwndContactList,ObjectName+1,pServiceName,pStatusServiceName,"\0",Left,Top,Right,Bottom,alingnto,TranslateTS(Hint),Section,Type,MinWidth,MinHeight);
+ else res = ModernSkinButton_AddButton(pcli->hwndContactList,ObjectName+1,pServiceName,pStatusServiceName,"\0",Left,Top,Right,Bottom,alingnto,TranslateTS(Hint),NULL,NULL,MinWidth,MinHeight);
+ }
+ return res;
+}
+
+//Parse DB string and add object
+// Params is:
+// Glyph,None
+// Glyph,Solid, < ColorR>, < ColorG>, < ColorB>, < Alpha>
+// Glyph,Image,Filename,(TileBoth|TileVert|TileHor|StretchBoth), < MarginLeft>, < MarginTop>, < MarginRight>, < MarginBottom>, < Alpha>
+int RegisterObjectByParce(char * ObjectName, char * Params)
+{
+ if ( !ObjectName || !Params) return 0;
+ {
+ int res = 0;
+ SKINOBJECTDESCRIPTOR obj = {0};
+ char buf[250];
+ obj.szObjectID = mir_strdup(ObjectName);
+ GetParamN(Params,buf, SIZEOF(buf),0,',',0);
+ if (mir_bool_strcmpi(buf,"Glyph"))
+ obj.bType = OT_GLYPHOBJECT;
+ else if (mir_bool_strcmpi(buf,"Font"))
+ obj.bType = OT_FONTOBJECT;
+
+ switch (obj.bType)
+ {
+ case OT_GLYPHOBJECT:
+ {
+ GLYPHOBJECT gl = {0};
+ GetParamN(Params,buf, SIZEOF(buf),1,',',0);
+ if (mir_bool_strcmpi(buf,"Solid"))
+ {
+ //Solid
+ int r,g,b;
+ gl.Style = ST_BRUSH;
+ r = atoi(GetParamN(Params,buf, SIZEOF(buf),2,',',0));
+ g = atoi(GetParamN(Params,buf, SIZEOF(buf),3,',',0));
+ b = atoi(GetParamN(Params,buf, SIZEOF(buf),4,',',0));
+ gl.dwAlpha = atoi(GetParamN(Params,buf, SIZEOF(buf),5,',',0));
+ gl.dwColor = RGB(r,g,b);
+ }
+ else if (mir_bool_strcmpi(buf,"Image"))
+ {
+ //Image
+ gl.Style = ST_IMAGE;
+ gl.szFileName = mir_strdup(GetParamN(Params,buf, SIZEOF(buf),2,',',0));
+ gl.dwLeft = atoi(GetParamN(Params,buf, SIZEOF(buf),4,',',0));
+ gl.dwTop = atoi(GetParamN(Params,buf, SIZEOF(buf),5,',',0));
+ gl.dwRight = atoi(GetParamN(Params,buf, SIZEOF(buf),6,',',0));
+ gl.dwBottom = atoi(GetParamN(Params,buf, SIZEOF(buf),7,',',0));
+ gl.dwAlpha = atoi(GetParamN(Params,buf, SIZEOF(buf),8,',',0));
+ GetParamN(Params,buf, SIZEOF(buf),3,',',0);
+ if (mir_bool_strcmpi(buf,"TileBoth")) gl.FitMode = FM_TILE_BOTH;
+ else if (mir_bool_strcmpi(buf,"TileVert")) gl.FitMode = FM_TILE_VERT;
+ else if (mir_bool_strcmpi(buf,"TileHorz")) gl.FitMode = FM_TILE_HORZ;
+ else gl.FitMode = 0;
+ }
+ else if (mir_bool_strcmpi(buf,"Fragment"))
+ {
+ //Image
+ gl.Style = ST_FRAGMENT;
+ gl.szFileName = mir_strdup(GetParamN(Params,buf, SIZEOF(buf),2,',',0));
+
+ gl.clipArea.x = atoi(GetParamN(Params,buf, SIZEOF(buf),3,',',0));
+ gl.clipArea.y = atoi(GetParamN(Params,buf, SIZEOF(buf),4,',',0));
+ gl.szclipArea.cx = atoi(GetParamN(Params,buf, SIZEOF(buf),5,',',0));
+ gl.szclipArea.cy = atoi(GetParamN(Params,buf, SIZEOF(buf),6,',',0));
+
+ gl.dwLeft = atoi(GetParamN(Params,buf, SIZEOF(buf),8,',',0));
+ gl.dwTop = atoi(GetParamN(Params,buf, SIZEOF(buf),9,',',0));
+ gl.dwRight = atoi(GetParamN(Params,buf, SIZEOF(buf),10,',',0));
+ gl.dwBottom = atoi(GetParamN(Params,buf, SIZEOF(buf),11,',',0));
+ gl.dwAlpha = atoi(GetParamN(Params,buf, SIZEOF(buf),12,',',0));
+ GetParamN(Params,buf, SIZEOF(buf),7,',',0);
+ if (mir_bool_strcmpi(buf,"TileBoth")) gl.FitMode = FM_TILE_BOTH;
+ else if (mir_bool_strcmpi(buf,"TileVert")) gl.FitMode = FM_TILE_VERT;
+ else if (mir_bool_strcmpi(buf,"TileHorz")) gl.FitMode = FM_TILE_HORZ;
+ else gl.FitMode = 0;
+ }
+ else
+ {
+ //None
+ gl.Style = ST_SKIP;
+ }
+ obj.Data = &gl;
+ res = ske_AddDescriptorToSkinObjectList(&obj,NULL);
+ mir_free_and_nil(obj.szObjectID);
+ mir_free_and_nil(gl.szFileName);
+ return res;
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+
+int SkinDrawGlyphMask(HDC hdc, RECT * rcSize, RECT * rcClip, MODERNMASK * ModernMask)
+{
+ if ( !ModernMask) return 0;
+
+ SKINDRAWREQUEST rq;
+ rq.hDC = hdc;
+ rq.rcDestRect = *rcSize;
+ rq.rcClipRect = *rcClip;
+ strncpy(rq.szObjectID,"Masked draw",SIZEOF("Masked draw"));
+ return ske_Service_DrawGlyph((WPARAM)&rq,(LPARAM)ModernMask);
+}
+
+
+int __inline SkinDrawWindowBack(HWND hwndIn, HDC hdc, RECT * rcClip, char * objectID)
+{
+ SKINDRAWREQUEST rq;
+ POINT pt = {0};
+ RECT rc,r1;
+
+ HWND hwnd = (HWND)CallService(MS_CLUI_GETHWND,0,0);
+ if ( !objectID) return 0;
+ GetWindowRect(hwndIn,&r1);
+ pt.x = r1.left;
+ pt.y = r1.top;
+ //ClientToScreen(hwndIn,&pt);
+ GetWindowRect(hwnd,&rc);
+ OffsetRect(&rc,-pt.x ,-pt.y);
+ rq.hDC = hdc;
+ rq.rcDestRect = rc;
+ rq.rcClipRect = *rcClip;
+ strncpy(rq.szObjectID,objectID,SIZEOF(rq.szObjectID));
+ ///ske_Service_DrawGlyph((WPARAM)&rq,0); //$$$
+ return CallService(MS_SKIN_DRAWGLYPH,(WPARAM)&rq,0);
+}
diff --git a/plugins/Clist_modern/src/modern_statusbar.cpp b/plugins/Clist_modern/src/modern_statusbar.cpp
new file mode 100644
index 0000000000..f7e61abab1
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_statusbar.cpp
@@ -0,0 +1,1136 @@
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_statusbar.h"
+#include "./m_api/m_skin_eng.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_clcpaint.h"
+#include "hdr/modern_sync.h"
+
+BOOL tooltipshoing;
+POINT lastpnt;
+
+#define TM_STATUSBAR 23435234
+#define TM_STATUSBARHIDE 23435235
+
+HWND hModernStatusBar = NULL;
+HANDLE hFramehModernStatusBar = NULL;
+extern void ApplyViewMode(const char *Name, bool onlySelector = false );
+extern void SaveViewMode(const char *name, const TCHAR *szGroupFilter, const char *szProtoFilter, DWORD statusMask, DWORD stickyStatusMask, unsigned int options, unsigned int stickies, unsigned int operators, unsigned int lmdat);
+
+//int FindFrameID(HWND FrameHwnd);
+COLORREF sttGetColor(char * module, char * color, COLORREF defColor);
+
+#define DBFONTF_BOLD 1
+#define DBFONTF_ITALIC 2
+#define DBFONTF_UNDERLINE 4
+
+typedef struct _ProtoItemData
+{
+ HICON icon;
+ HICON extraIcon;
+ int iconIndex;
+ char * ProtoName;
+ char * AccountName;
+ int ProtoStatus;
+ TCHAR *ProtoHumanName;
+ char *ProtoEMailCount;
+ char * ProtoStatusText;
+ TCHAR * ProtoXStatus;
+ int ProtoPos;
+ int fullWidth;
+ RECT protoRect;
+ BOOL DoubleIcons;
+
+ BYTE showProtoIcon;
+ BYTE showProtoName;
+ BYTE showStatusName;
+ BYTE xStatusMode; // 0-only main, 1-xStatus, 2-main as overlay
+ BYTE connectingIcon;
+ BYTE showProtoEmails;
+ BYTE SBarRightClk;
+ int PaddingLeft;
+ int PaddingRight;
+
+ bool isDimmed;
+
+} ProtoItemData;
+
+ProtoItemData *ProtosData = NULL;
+int allocedItemData = 0;
+STATUSBARDATA g_StatusBarData = {0};
+
+
+char * ApendSubSetting(char * buf, int size, char *first, char *second)
+{
+ _snprintf(buf,size,"%sFont%s",first,second);
+ return buf;
+}
+
+int LoadStatusBarData()
+{
+ g_StatusBarData.perProtoConfig = db_get_b(NULL,"CLUI","SBarPerProto",SETTING_SBARPERPROTO_DEFAULT);
+ g_StatusBarData.showProtoIcon = db_get_b(NULL,"CLUI","SBarShow",SETTING_SBARSHOW_DEFAULT)&1;
+ g_StatusBarData.showProtoName = db_get_b(NULL,"CLUI","SBarShow",SETTING_SBARSHOW_DEFAULT)&2;
+ g_StatusBarData.showStatusName = db_get_b(NULL,"CLUI","SBarShow",SETTING_SBARSHOW_DEFAULT)&4;
+ g_StatusBarData.xStatusMode = (BYTE)(db_get_b(NULL,"CLUI","ShowXStatus",SETTING_SHOWXSTATUS_DEFAULT));
+ g_StatusBarData.connectingIcon = db_get_b(NULL,"CLUI","UseConnectingIcon",SETTING_USECONNECTINGICON_DEFAULT);
+ g_StatusBarData.showProtoEmails = db_get_b(NULL,"CLUI","ShowUnreadEmails",SETTING_SHOWUNREADEMAILS_DEFAULT);
+ g_StatusBarData.SBarRightClk = db_get_b(NULL,"CLUI","SBarRightClk",SETTING_SBARRIGHTCLK_DEFAULT);
+
+ g_StatusBarData.nProtosPerLine = db_get_b(NULL,"CLUI","StatusBarProtosPerLine",SETTING_PROTOSPERLINE_DEFAULT);
+ g_StatusBarData.Align = db_get_b(NULL,"CLUI","Align",SETTING_ALIGN_DEFAULT);
+ g_StatusBarData.VAlign = db_get_b(NULL,"CLUI","VAlign",SETTING_VALIGN_DEFAULT);
+ g_StatusBarData.sameWidth = db_get_b(NULL,"CLUI","EqualSections",SETTING_EQUALSECTIONS_DEFAULT);
+ g_StatusBarData.rectBorders.left = db_get_dw(NULL,"CLUI","LeftOffset",SETTING_LEFTOFFSET_DEFAULT);
+ g_StatusBarData.rectBorders.right = db_get_dw(NULL,"CLUI","RightOffset",SETTING_RIGHTOFFSET_DEFAULT);
+ g_StatusBarData.rectBorders.top = db_get_dw(NULL,"CLUI","TopOffset",SETTING_TOPOFFSET_DEFAULT);
+ g_StatusBarData.rectBorders.bottom = db_get_dw(NULL,"CLUI","BottomOffset",SETTING_BOTTOMOFFSET_DEFAULT);
+ g_StatusBarData.extraspace = (BYTE)db_get_dw(NULL,"CLUI","SpaceBetween",SETTING_SPACEBETWEEN_DEFAULT);
+
+ if (g_StatusBarData.BarFont) DeleteObject(g_StatusBarData.BarFont);
+ g_StatusBarData.BarFont = NULL;//LoadFontFromDB("ModernData","StatusBar",&g_StatusBarData.fontColor);
+ {
+ int vis = db_get_b(NULL,"CLUI","ShowSBar",SETTING_SHOWSBAR_DEFAULT);
+ int frameopt;
+ int frameID = Sync( FindFrameID, hModernStatusBar );
+ frameopt = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,frameID),0);
+ frameopt = frameopt & (~F_VISIBLE);
+ if (vis)
+ {
+ ShowWindow(hModernStatusBar,SW_SHOW);
+ frameopt |= F_VISIBLE;
+ }
+ else
+ {
+ ShowWindow(hModernStatusBar,SW_HIDE);
+ };
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_FLAGS,frameID),frameopt);
+ }
+ g_StatusBarData.TextEffectID = db_get_b(NULL,"StatusBar","TextEffectID",SETTING_TEXTEFFECTID_DEFAULT);
+ g_StatusBarData.TextEffectColor1 = db_get_dw(NULL,"StatusBar","TextEffectColor1",SETTING_TEXTEFFECTCOLOR1_DEFAULT);
+ g_StatusBarData.TextEffectColor2 = db_get_dw(NULL,"StatusBar","TextEffectColor2",SETTING_TEXTEFFECTCOLOR2_DEFAULT);
+
+ if (g_StatusBarData.hBmpBackground) {DeleteObject(g_StatusBarData.hBmpBackground); g_StatusBarData.hBmpBackground = NULL;}
+
+ if (g_CluiData.fDisableSkinEngine)
+ {
+ DBVARIANT dbv;
+ g_StatusBarData.bkColour = sttGetColor("StatusBar","BkColour",CLCDEFAULT_BKCOLOUR);
+ if (db_get_b(NULL,"StatusBar","UseBitmap",CLCDEFAULT_USEBITMAP)) {
+ if ( !DBGetContactSettingString(NULL,"StatusBar","BkBitmap",&dbv)) {
+ g_StatusBarData.hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ }
+ g_StatusBarData.bkUseWinColors = db_get_b(NULL,"StatusBar", "UseWinColours", CLCDEFAULT_USEWINDOWSCOLOURS);
+ g_StatusBarData.backgroundBmpUse = db_get_w(NULL,"StatusBar","BkBmpUse",CLCDEFAULT_BKBMPUSE);
+ }
+ SendMessage(pcli->hwndContactList,WM_SIZE,0,0);
+
+ return 1;
+}
+
+int BgStatusBarChange(WPARAM wParam,LPARAM lParam)
+{
+ if (MirandaExiting()) return 0;
+ LoadStatusBarData();
+ return 0;
+}
+
+//ProtocolData;
+int NewStatusPaintCallbackProc(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData)
+{
+ return ModernDrawStatusBar(hWnd,hDC);
+}
+
+int ModernDrawStatusBar(HWND hwnd, HDC hDC)
+{
+ if (hwnd == (HWND)-1) return 0;
+ if (GetParent(hwnd) == pcli->hwndContactList)
+ return ModernDrawStatusBarWorker(hwnd,hDC);
+ else
+ CLUI__cliInvalidateRect(hwnd,NULL,FALSE);
+ return 0;
+}
+
+int ModernDrawStatusBarWorker(HWND hWnd, HDC hDC)
+{
+ int line;
+ int iconHeight = GetSystemMetrics(SM_CYSMICON)+2;
+ int protosperline = 0;
+ int visProtoCount = 0;
+ int protoCount;
+ int SumWidth = 0;
+ int rectwidth = 0;
+ int aligndx = 0;
+ int * ProtoWidth = NULL;
+ int i,j,po = 0;
+
+ char servName[40];
+ char protoNameExt[40];
+ // Count visible protos
+ PROTOACCOUNT **accs;
+ RECT rc;
+ HFONT hOldFont;
+ int iconY, textY;
+ int spaceWidth;
+ int maxwidth = 0;
+ int xstatus = 0;
+ SIZE textSize = {0};
+ GetClientRect(hWnd,&rc);
+ if (g_CluiData.fDisableSkinEngine) {
+ if (g_StatusBarData.bkUseWinColors && xpt_IsThemed(g_StatusBarData.hTheme))
+ xpt_DrawTheme(g_StatusBarData.hTheme, hWnd, hDC, 0, 0, &rc, &rc);
+ else
+ DrawBackGround(hWnd, hDC, g_StatusBarData.hBmpBackground, g_StatusBarData.bkColour, g_StatusBarData.backgroundBmpUse );
+ }
+ else SkinDrawGlyph(hDC,&rc,&rc,"Main,ID=StatusBar"); //TBD
+
+ g_StatusBarData.nProtosPerLine = db_get_b(NULL,"CLUI","StatusBarProtosPerLine",SETTING_PROTOSPERLINE_DEFAULT);
+ hOldFont = g_clcPainter.ChangeToFont(hDC,NULL,FONTID_STATUSBAR_PROTONAME,NULL);
+
+ // hOldFont = SelectObject(hDC,g_StatusBarData.BarFont);
+ // SetTextColor(hDC,g_StatusBarData.fontColor);
+ {
+
+ GetTextExtentPoint32A(hDC," ",1,&textSize);
+ spaceWidth = textSize.cx;
+ textY = rc.top+((rc.bottom-rc.top-textSize.cy)>>1);
+ }
+ iconY = rc.top+((rc.bottom-rc.top-GetSystemMetrics(SM_CXSMICON))>>1);
+
+ {
+ ProtoEnumAccounts( &protoCount, &accs );
+ if (allocedItemData && ProtosData) {
+ for (int k = 0; k < allocedItemData; k++) {
+ mir_free(ProtosData[k].ProtoXStatus);
+ mir_free(ProtosData[k].ProtoName);
+ mir_free(ProtosData[k].AccountName);
+ mir_free(ProtosData[k].ProtoHumanName);
+ mir_free(ProtosData[k].ProtoEMailCount);
+ mir_free(ProtosData[k].ProtoStatusText);
+ }
+ mir_free_and_nil(ProtosData);
+ allocedItemData = 0;
+ }
+ if ( protoCount == 0 )
+ return 0;
+
+ ProtosData = (ProtoItemData*)mir_alloc(sizeof(ProtoItemData)*protoCount);
+ memset(ProtosData,0,sizeof(ProtoItemData)*protoCount);
+ for (j = 0; j < protoCount; j++)
+ {
+ int vis;
+ char buf[256];
+
+ i = pcli->pfnGetAccountIndexByPos(j);
+ if (i == -1)
+ vis = FALSE;
+ else
+ vis = pcli->pfnGetProtocolVisibility(accs[i]->szModuleName);
+ if ( !vis) continue;
+
+ mir_snprintf(buf, SIZEOF(buf), "SBarAccountIsCustom_%s", accs[i]->szModuleName);
+
+ if (g_StatusBarData.perProtoConfig && db_get_b(NULL, "CLUI", buf, SETTING_SBARACCOUNTISCUSTOM_DEFAULT))
+ {
+ mir_snprintf(buf, SIZEOF(buf), "HideAccount_%s", accs[i]->szModuleName);
+ if (db_get_b(NULL, "CLUI", buf, SETTING_SBARHIDEACCOUNT_DEFAULT))
+ continue;
+
+ mir_snprintf(buf, SIZEOF(buf), "SBarShow_%s", accs[i]->szModuleName);
+ {
+ BYTE showOps = db_get_b(NULL,"CLUI", buf, SETTING_SBARSHOW_DEFAULT);
+ ProtosData[visProtoCount].showProtoIcon = showOps&1;
+ ProtosData[visProtoCount].showProtoName = showOps&2;
+ ProtosData[visProtoCount].showStatusName = showOps&4;
+ }
+
+ mir_snprintf(buf, SIZEOF(buf), "ShowXStatus_%s", accs[i]->szModuleName);
+ ProtosData[visProtoCount].xStatusMode = db_get_b(NULL,"CLUI", buf, SETTING_SBARSHOW_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "UseConnectingIcon_%s", accs[i]->szModuleName);
+ ProtosData[visProtoCount].connectingIcon = db_get_b(NULL,"CLUI", buf, SETTING_USECONNECTINGICON_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "ShowUnreadEmails_%s", accs[i]->szModuleName);
+ ProtosData[visProtoCount].showProtoEmails = db_get_b(NULL,"CLUI", buf, SETTING_SHOWUNREADEMAILS_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "SBarRightClk_%s", accs[i]->szModuleName);
+ ProtosData[visProtoCount].SBarRightClk = db_get_b(NULL,"CLUI", buf, SETTING_SBARRIGHTCLK_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "PaddingLeft_%s", accs[i]->szModuleName);
+ ProtosData[visProtoCount].PaddingLeft = db_get_dw(NULL,"CLUI", buf, SETTING_PADDINGLEFT_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "PaddingRight_%s", accs[i]->szModuleName);
+ ProtosData[visProtoCount].PaddingRight = db_get_dw(NULL,"CLUI", buf, SETTING_PADDINGRIGHT_DEFAULT);
+ }
+ else
+ {
+ ProtosData[visProtoCount].showProtoIcon = g_StatusBarData.showProtoIcon;
+ ProtosData[visProtoCount].showProtoName = g_StatusBarData.showProtoName;
+ ProtosData[visProtoCount].showStatusName = g_StatusBarData.showStatusName;
+ ProtosData[visProtoCount].xStatusMode = g_StatusBarData.xStatusMode;
+ ProtosData[visProtoCount].connectingIcon = g_StatusBarData.connectingIcon;
+ ProtosData[visProtoCount].showProtoEmails = g_StatusBarData.showProtoEmails;
+ ProtosData[visProtoCount].SBarRightClk = 0;
+ ProtosData[visProtoCount].PaddingLeft = 0;
+ ProtosData[visProtoCount].PaddingRight = 0;
+ }
+
+ ProtosData[visProtoCount].ProtoStatus = CallProtoService(accs[i]->szModuleName,PS_GETSTATUS,0,0);
+
+ ProtosData[visProtoCount].ProtoEMailCount = NULL;
+ if (ProtosData[visProtoCount].ProtoStatus > ID_STATUS_OFFLINE)
+ {
+ // create service name
+ mir_snprintf(servName, SIZEOF(servName), "%s/GetUnreadEmailCount", accs[i]->szModuleName);
+ if (ProtosData[visProtoCount].showProtoEmails == 1 && ServiceExists(servName))
+ {
+ mir_snprintf(protoNameExt, SIZEOF(protoNameExt),"[%d]", (int) CallService(servName, 0, 0));
+ ProtosData[visProtoCount].ProtoEMailCount = mir_strdup(protoNameExt);
+ }
+ }
+
+ ProtosData[visProtoCount].ProtoHumanName = mir_tstrdup(accs[i]->tszAccountName);
+ ProtosData[visProtoCount].AccountName = mir_strdup(accs[i]->szModuleName);
+ ProtosData[visProtoCount].ProtoName = mir_strdup(accs[i]->szProtoName);
+ ProtosData[visProtoCount].ProtoStatusText = mir_strdup((char*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION,(WPARAM)ProtosData[visProtoCount].ProtoStatus,0));
+ ProtosData[visProtoCount].ProtoPos = visProtoCount;
+
+ ProtosData[visProtoCount].isDimmed = 0;
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_PROTOS)
+ {
+ char szTemp[2048];
+ mir_snprintf(szTemp, SIZEOF(szTemp), "%s|", ProtosData[visProtoCount].AccountName );
+ ProtosData[visProtoCount].isDimmed = strstr(g_CluiData.protoFilter, szTemp) ? 0 : 1;
+ }
+
+ visProtoCount++;
+ allocedItemData++;
+ }
+
+ // Calculate rects
+
+ //START MULTILINE HERE
+ {
+ int orig_protoCount = protoCount;
+ int orig_visProtoCount = visProtoCount;
+ ProtoItemData * orig_ProtosData = ProtosData;
+ int linecount;
+ if (g_StatusBarData.nProtosPerLine)
+ protosperline = g_StatusBarData.nProtosPerLine;
+ else if (orig_visProtoCount)
+ protosperline = orig_visProtoCount;
+ else if (protoCount)
+ {
+ protosperline = protoCount;
+ orig_visProtoCount = protoCount;
+ }
+ else
+ {
+ protosperline = 1;
+ orig_visProtoCount = 1;
+ }
+ protosperline = min(protosperline,orig_visProtoCount);
+ linecount = protosperline ? (orig_visProtoCount+(protosperline-1))/protosperline : 1; //divide with rounding to up
+ for (line = 0; line < linecount; line++)
+ {
+ int height;
+ int rowsdy;
+ int rowheight = max(textSize.cy+2,iconHeight);
+ protoCount = min(protosperline,(orig_protoCount-line*protosperline));
+ visProtoCount = min(protosperline,(orig_visProtoCount-line*protosperline));
+ ProtosData += line*protosperline;
+ GetClientRect(hWnd,&rc);
+
+ rc.top += g_StatusBarData.rectBorders.top;
+ rc.bottom -= g_StatusBarData.rectBorders.bottom;
+
+ aligndx = 0;
+ maxwidth = 0;
+ xstatus = 0;
+ SumWidth = 0;
+ height = (rowheight*linecount);
+
+ if (height > (rc.bottom - rc.top))
+ {
+ rowheight = (rc.bottom - rc.top) / linecount;
+ height = (rowheight*linecount);
+ }
+
+ rowsdy = ((rc.bottom-rc.top)-height)/2;
+ if (rowheight*(line)+rowsdy < rc.top-rowheight) continue;
+ if (rowheight*(line+1)+rowsdy>rc.bottom+rowheight)
+ {
+ ProtosData = orig_ProtosData;
+ break;
+ }
+ if (g_StatusBarData.VAlign == 0) //top
+ {
+ rc.bottom = rc.top+rowheight*(line+1);
+ rc.top = rc.top+rowheight*line+1;
+ }
+ else if (g_StatusBarData.VAlign == 1) //center
+ {
+ rc.bottom = rc.top+rowsdy+rowheight*(line+1);
+ rc.top = rc.top+rowsdy+rowheight*line+1;
+ }
+ else if (g_StatusBarData.VAlign == 2) //bottom
+ {
+ rc.top = rc.bottom - (rowheight*(linecount - line));
+ rc.bottom = rc.bottom - (rowheight*(linecount - line - 1)+1);
+ }
+
+ textY = rc.top+(((rc.bottom-rc.top)-textSize.cy)/2);
+ iconY = rc.top+(((rc.bottom-rc.top)-iconHeight)/2);
+
+ { //Code for each line
+ {
+ DWORD sw;
+ rectwidth = rc.right-rc.left-g_StatusBarData.rectBorders.left-g_StatusBarData.rectBorders.right;
+ if (visProtoCount>1) sw = (rectwidth-(g_StatusBarData.extraspace*(visProtoCount-1)))/visProtoCount;
+ else sw = rectwidth;
+ mir_free(ProtoWidth);
+ ProtoWidth = (int*)mir_alloc(sizeof(int)*visProtoCount);
+ for (i=0; i < visProtoCount; i++)
+ {
+ SIZE textSize;
+ DWORD w = 0;
+ // FIXME strange error occurs here due to Dimon log
+ w = ProtosData[i].PaddingLeft;
+ w += ProtosData[i].PaddingRight;
+
+ if ( ProtosData[i].showProtoIcon )
+ {
+
+ w += GetSystemMetrics(SM_CXSMICON)+1;
+
+ ProtosData[i].extraIcon = NULL;
+ if ((ProtosData[i].xStatusMode&8) && ProtosData[i].ProtoStatus>ID_STATUS_OFFLINE)
+ {
+ char str[MAXMODULELABELLENGTH];
+ mir_snprintf(str, SIZEOF(str), "%s/GetXStatus", ProtosData[i].AccountName);
+ if (ServiceExists(str))
+ {
+ char * dbTitle = "XStatusName";
+ char * dbTitle2 = NULL;
+ xstatus = CallProtoService(ProtosData[i].AccountName,"/GetXStatus",(WPARAM)&dbTitle,(LPARAM)&dbTitle2);
+ if (dbTitle && xstatus)
+ {
+ DBVARIANT dbv = {0};
+ if ( !DBGetContactSettingTString(NULL,ProtosData[i].AccountName,dbTitle,&dbv))
+ {
+ ProtosData[i].ProtoXStatus = mir_tstrdup(dbv.ptszVal);
+ db_free(&dbv);
+ }
+ }
+ }
+ }
+ if ((ProtosData[i].xStatusMode&3))
+ {
+ if (ProtosData[i].ProtoStatus>ID_STATUS_OFFLINE)
+ {
+ char str[MAXMODULELABELLENGTH];
+ mir_snprintf(str, SIZEOF(str), "%s/GetXStatusIcon", ProtosData[i].AccountName);
+ if (ServiceExists(str))
+ ProtosData[i].extraIcon = (HICON)CallService(str,0,0);
+ if (ProtosData[i].extraIcon && (ProtosData[i].xStatusMode&3) == 3)
+ w += GetSystemMetrics(SM_CXSMICON)+1;
+
+ }
+ }
+ }
+
+ if (ProtosData[i].showProtoName)
+ {
+ GetTextExtentPoint32(hDC,ProtosData[i].ProtoHumanName,lstrlen(ProtosData[i].ProtoHumanName),&textSize);
+ w += textSize.cx + 3 + spaceWidth;
+ }
+
+ if (ProtosData[i].showProtoEmails && ProtosData[i].ProtoEMailCount )
+ {
+ GetTextExtentPoint32A(hDC,ProtosData[i].ProtoEMailCount,lstrlenA(ProtosData[i].ProtoEMailCount),&textSize);
+ w += textSize.cx+3+spaceWidth;
+ }
+
+ if (ProtosData[i].showStatusName)
+ {
+ GetTextExtentPoint32A(hDC,ProtosData[i].ProtoStatusText,lstrlenA(ProtosData[i].ProtoStatusText),&textSize);
+ w += textSize.cx + 3 + spaceWidth;
+ }
+
+ if ((ProtosData[i].xStatusMode&8) && ProtosData[i].ProtoXStatus)
+ {
+ GetTextExtentPoint32(hDC,ProtosData[i].ProtoXStatus,lstrlen(ProtosData[i].ProtoXStatus),&textSize);
+ w += textSize.cx + 3 + spaceWidth;
+ }
+
+ if (( ProtosData[i].showProtoName) ||
+ (ProtosData[i].showProtoEmails && ProtosData[i].ProtoEMailCount ) ||
+ (ProtosData[i].showStatusName) ||
+ ((ProtosData[i].xStatusMode&8) && ProtosData[i].ProtoXStatus))
+ w -= spaceWidth;
+
+ ProtosData[i].fullWidth = w;
+ if (g_StatusBarData.sameWidth)
+ {
+ ProtoWidth[i] = sw;
+ SumWidth += w;
+ }
+ else
+ {
+ ProtoWidth[i] = w;
+ SumWidth += w;
+ }
+ }
+
+ // Reposition rects
+ for (i=0; i < visProtoCount; i++)
+ if (ProtoWidth[i]>maxwidth) maxwidth = ProtoWidth[i];
+
+ if (g_StatusBarData.sameWidth)
+ {
+ for (i=0; i < visProtoCount; i++)
+ ProtoWidth[i] = maxwidth;
+ SumWidth = maxwidth*visProtoCount;
+ }
+ SumWidth += (visProtoCount-1)*(g_StatusBarData.extraspace+1);
+
+ if (SumWidth>rectwidth)
+ {
+ float f = (float)rectwidth/SumWidth;
+ //dx = (int)(0.5+(float)dx/visProtoCount);
+ //SumWidth -= dx*visProtoCount;
+ SumWidth = 0;
+ for (i=0; i < visProtoCount; i++)
+ {
+ ProtoWidth[i] = (int)((float)ProtoWidth[i]*f);
+ SumWidth += ProtoWidth[i];
+ }
+ SumWidth += (visProtoCount-1)*(g_StatusBarData.extraspace+1);
+ }
+ }
+ if (g_StatusBarData.Align == 1) //center
+ aligndx = (rectwidth-SumWidth)>>1;
+ else if (g_StatusBarData.Align == 2) //right
+ aligndx = (rectwidth-SumWidth);
+ // Draw in rects
+ //ske_SelectTextEffect(hDC,g_StatusBarData.TextEffectID,g_StatusBarData.TextEffectColor1,g_StatusBarData.TextEffectColor2);
+ {
+ RECT r = rc;
+// r.top += g_StatusBarData.rectBorders.top;
+// r.bottom -= g_StatusBarData.rectBorders.bottom;
+ r.left += g_StatusBarData.rectBorders.left+aligndx;
+ for (i=0; i < visProtoCount; i++)
+ {
+ HRGN rgn;
+ int x = r.left;
+ HICON hIcon = NULL;
+ HICON hxIcon = NULL;
+ BOOL NeedDestroy = FALSE;
+ x = r.left;
+ x += ProtosData[i].PaddingLeft;
+ r.right = r.left+ProtoWidth[i];
+
+ if ( ProtosData[i].showProtoIcon )
+ {
+ if (ProtosData[i].ProtoStatus>ID_STATUS_OFFLINE && ((ProtosData[i].xStatusMode)&3)>0)
+ {
+ char str[MAXMODULELABELLENGTH];
+ mir_snprintf(str, SIZEOF(str), "%s/GetXStatusIcon", ProtosData[i].AccountName);
+ if (ServiceExists(str))
+ {
+ hxIcon = ProtosData[i].extraIcon;
+ if (hxIcon)
+ {
+ if (((ProtosData[i].xStatusMode)&3) == 2)
+ {
+ hIcon = GetMainStatusOverlay(ProtosData[i].ProtoStatus);
+ NeedDestroy = TRUE;
+ }
+ else if (((ProtosData[i].xStatusMode)&3) == 1)
+ {
+ hIcon = hxIcon;
+ NeedDestroy = TRUE;
+ hxIcon = NULL;
+ }
+
+ }
+ }
+ }
+ if (hIcon == NULL && (hxIcon == NULL || (((ProtosData[i].xStatusMode)&3) == 3)))
+ {
+ if (hIcon == NULL && (ProtosData[i].connectingIcon == 1) && ProtosData[i].ProtoStatus >= ID_STATUS_CONNECTING && ProtosData[i].ProtoStatus <= ID_STATUS_CONNECTING+MAX_CONNECT_RETRIES)
+ {
+ hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)ProtosData[i].AccountName,0);
+ if (hIcon) NeedDestroy = TRUE;
+ else hIcon = LoadSkinnedProtoIcon(ProtosData[i].AccountName,ProtosData[i].ProtoStatus);
+ }
+ else hIcon = LoadSkinnedProtoIcon(ProtosData[i].AccountName,ProtosData[i].ProtoStatus);
+ }
+
+
+ rgn = CreateRectRgn(r.left,r.top,r.right,r.bottom);
+ //
+ {
+ if (g_StatusBarData.sameWidth)
+ {
+ int fw = ProtosData[i].fullWidth;
+ int rw = r.right-r.left;
+ if (g_StatusBarData.Align == 1)
+ {
+ x = r.left+((rw-fw)/2);
+ }
+ else if (g_StatusBarData.Align == 2)
+ {
+ x = r.left+((rw-fw));
+ }
+ else x = r.left;
+ }
+ }
+
+
+ SelectClipRgn(hDC,rgn);
+ ProtosData[i].DoubleIcons = FALSE;
+
+ DWORD dim = ProtosData[i].isDimmed ? (( 64 << 24 ) | 0x80 ) : 0;
+
+ if ((ProtosData[i].xStatusMode&3) == 3)
+ {
+ if (hIcon) mod_DrawIconEx_helper(hDC,x,iconY,hIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL, DI_NORMAL|dim );
+ if (hxIcon)
+ {
+ mod_DrawIconEx_helper(hDC,x+GetSystemMetrics(SM_CXSMICON)+1,iconY,hxIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL|dim);
+ x += GetSystemMetrics(SM_CXSMICON)+1;
+ }
+ ProtosData[i].DoubleIcons = hIcon && hxIcon;
+ }
+ else
+ {
+ if (hxIcon) mod_DrawIconEx_helper(hDC,x,iconY,hxIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL|dim);
+ if (hIcon) mod_DrawIconEx_helper(hDC,x,iconY,hIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL| ((hxIcon && (ProtosData[i].xStatusMode&4))?(192 << 24):0 ) | dim );
+ }
+
+ if (( hxIcon || hIcon) && TRUE /* TODO g_StatusBarData.bDrawLockOverlay options to draw locked proto*/ )
+ {
+ if ( db_get_b( NULL,ProtosData[i].AccountName,"LockMainStatus",0 ))
+ {
+ HICON hLockOverlay = LoadSkinnedIcon(SKINICON_OTHER_STATUS_LOCKED);
+ if (hLockOverlay != NULL)
+ {
+ mod_DrawIconEx_helper(hDC, x, iconY, hLockOverlay, GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL | dim);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hLockOverlay, 0); }
+ }
+ }
+ if (hxIcon) DestroyIcon_protect(hxIcon);
+ if (NeedDestroy) DestroyIcon_protect(hIcon);
+ else CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ x += GetSystemMetrics(SM_CXSMICON)+1;
+ }
+ if (ProtosData[i].showProtoName)
+ {
+ SIZE textSize;
+ RECT rt = r;
+ rt.left = x+(spaceWidth>>1);
+ rt.top = textY;
+ ske_DrawText(hDC,ProtosData[i].ProtoHumanName,lstrlen(ProtosData[i].ProtoHumanName),&rt,0);
+
+ if ((ProtosData[i].showProtoEmails && ProtosData[i].ProtoEMailCount != NULL) || ProtosData[i].showStatusName || ((ProtosData[i].xStatusMode&8) && ProtosData[i].ProtoXStatus))
+ {
+ GetTextExtentPoint32(hDC, ProtosData[i].ProtoHumanName, lstrlen(ProtosData[i].ProtoHumanName), &textSize);
+ x += textSize.cx + 3;
+ }
+ }
+
+ if (ProtosData[i].showProtoEmails && ProtosData[i].ProtoEMailCount != NULL)
+ {
+ SIZE textSize;
+ RECT rt = r;
+ rt.left = x+(spaceWidth>>1);
+ rt.top = textY;
+ ske_DrawTextA(hDC,ProtosData[i].ProtoEMailCount,lstrlenA(ProtosData[i].ProtoEMailCount),&rt,0);
+ //TextOutS(hDC,x,textY,ProtosData[i].ProtoName,lstrlenA(ProtosData[i].ProtoName));
+ if (ProtosData[i].showStatusName || ((ProtosData[i].xStatusMode&8) && ProtosData[i].ProtoXStatus))
+ {
+ GetTextExtentPoint32A(hDC,ProtosData[i].ProtoEMailCount,lstrlenA(ProtosData[i].ProtoEMailCount),&textSize);
+ x += textSize.cx+3;
+ }
+ }
+
+ if (ProtosData[i].showStatusName)
+ {
+ SIZE textSize;
+ RECT rt = r;
+ rt.left = x+(spaceWidth>>1);
+ rt.top = textY;
+ ske_DrawTextA(hDC, ProtosData[i].ProtoStatusText, lstrlenA(ProtosData[i].ProtoStatusText),&rt,0);
+ if (((ProtosData[i].xStatusMode&8) && ProtosData[i].ProtoXStatus))
+ {
+ GetTextExtentPoint32A(hDC,ProtosData[i].ProtoStatusText,lstrlenA(ProtosData[i].ProtoStatusText),&textSize);
+ x += textSize.cx+3;
+ }
+ //TextOutS(hDC,x,textY,ProtosData[i].ProtoStatusText,lstrlenA(ProtosData[i].ProtoStatusText));
+ }
+
+ if ((ProtosData[i].xStatusMode&8) && ProtosData[i].ProtoXStatus)
+ {
+ RECT rt = r;
+ rt.left = x+(spaceWidth>>1);
+ rt.top = textY;
+ ske_DrawText(hDC,ProtosData[i].ProtoXStatus,lstrlen(ProtosData[i].ProtoXStatus),&rt,0);
+ //TextOutS(hDC,x,textY,ProtosData[i].ProtoStatusText,lstrlenA(ProtosData[i].ProtoStatusText));
+ }
+
+ ProtosData[i].protoRect = r;
+
+ r.left = r.right+g_StatusBarData.extraspace;
+ //SelectClipRgn(hDC,NULL);
+ DeleteObject(rgn);
+
+ }
+ }
+
+ mir_free_and_nil(ProtoWidth);
+ } //code for each line
+ ProtosData = orig_ProtosData;
+ }
+ }
+ }
+
+ SelectObject(hDC,hOldFont);
+ ske_ResetTextEffect(hDC);
+ return 0;
+}
+
+static BOOL _ModernStatus_OnExtraIconClick( int protoIndex )
+{
+ /** FIXME
+ Create Protocol services and
+ move This portion of code to related Protocols
+ */
+
+ if ( !mir_strcmpi( ProtosData[protoIndex].ProtoName, "ICQ" ))
+ {
+ if ( ProtosData[protoIndex].ProtoStatus < ID_STATUS_ONLINE ) return FALSE;
+
+ HMENU hMainStatusMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ if ( !hMainStatusMenu ) return FALSE;
+
+ HMENU hProtoStatusMenu = GetSubMenu( hMainStatusMenu, protoIndex );
+ if ( !hProtoStatusMenu ) return FALSE;
+
+ int extraStatusMenuIndex = 1;
+ HMENU hExtraStatusMenu = GetSubMenu( hProtoStatusMenu, extraStatusMenuIndex );
+ if ( !hExtraStatusMenu ) return FALSE;
+
+ POINT pt; GetCursorPos( &pt );
+ {
+ HWND hWnd = (HWND) CallService( MS_CLUI_GETHWND, 0 ,0 );
+ TrackPopupMenu( hExtraStatusMenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hWnd, NULL );
+ }
+ return TRUE;
+ }
+ else if ( !mir_strcmpi( ProtosData[protoIndex].ProtoName, "JABBER" ))
+ {
+ if ( ProtosData[protoIndex].ProtoStatus < ID_STATUS_ONLINE ) return FALSE;
+ // Show Moods
+ char szService[128];
+ mir_snprintf(szService, SIZEOF(szService), "%s/AdvStatusSet/Mood", ProtosData[protoIndex].AccountName );
+ if ( ServiceExists( szService ))
+ {
+ CallService( szService, 0 ,0 );
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+#define TOOLTIP_TOLERANCE 5
+LRESULT CALLBACK ModernStatusProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ static POINT ptToolTipShow = {0};
+ switch (msg)
+ {
+ case WM_CREATE:
+ g_StatusBarData.hTheme = xpt_AddThemeHandle(hwnd,L"STATUS");
+ break;
+ case WM_DESTROY:
+ xpt_FreeThemeForWindow(hwnd);
+ if (allocedItemData && ProtosData) {
+ for (int k = 0; k < allocedItemData; k++) {
+ mir_free(ProtosData[k].AccountName);
+ mir_free(ProtosData[k].ProtoName);
+ mir_free(ProtosData[k].ProtoEMailCount);
+ mir_free(ProtosData[k].ProtoHumanName);
+ mir_free(ProtosData[k].ProtoStatusText);
+ mir_free(ProtosData[k].ProtoEMailCount);
+ mir_free(ProtosData[k].ProtoXStatus);
+ }
+ mir_free_and_nil(ProtosData);
+ allocedItemData = 0;
+ }
+ break;
+ case WM_SIZE:
+ if ( !g_CluiData.fLayered || GetParent(hwnd) != pcli->hwndContactList)
+ InvalidateRect(hwnd,NULL,FALSE);
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ case WM_ERASEBKGND:
+ return 1;
+ case WM_PAINT:
+ if (GetParent(hwnd) == pcli->hwndContactList && g_CluiData.fLayered)
+ CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE,(WPARAM)hwnd,0);
+ else if (GetParent(hwnd) == pcli->hwndContactList && !g_CluiData.fLayered)
+ {
+ HDC hdc, hdc2;
+ HBITMAP hbmp,hbmpo;
+ RECT rc = {0};
+ GetClientRect(hwnd,&rc);
+ rc.right++;
+ rc.bottom++;
+ hdc = GetDC(hwnd);
+ hdc2 = CreateCompatibleDC(hdc);
+ hbmp = ske_CreateDIB32(rc.right,rc.bottom);
+ hbmpo = (HBITMAP)SelectObject(hdc2,hbmp);
+ SetBkMode(hdc2,TRANSPARENT);
+ ske_BltBackImage(hwnd,hdc2,&rc);
+ ModernDrawStatusBarWorker(hwnd,hdc2);
+ BitBlt(hdc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,
+ hdc2,rc.left,rc.top,SRCCOPY);
+ SelectObject(hdc2,hbmpo);
+ DeleteObject(hbmp);
+ mod_DeleteDC(hdc2);
+
+ SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
+ ReleaseDC(hwnd,hdc);
+ ValidateRect(hwnd,NULL);
+ }
+ else
+ {
+ HDC hdc, hdc2;
+ HBITMAP hbmp, hbmpo;
+ RECT rc;
+ PAINTSTRUCT ps;
+ HBRUSH br = GetSysColorBrush(COLOR_3DFACE);
+ GetClientRect(hwnd,&rc);
+ hdc = BeginPaint(hwnd,&ps);
+ hdc2 = CreateCompatibleDC(hdc);
+ hbmp = ske_CreateDIB32(rc.right,rc.bottom);
+ hbmpo = (HBITMAP) SelectObject(hdc2,hbmp);
+ FillRect(hdc2,&ps.rcPaint,br);
+ ModernDrawStatusBarWorker(hwnd,hdc2);
+ //BitBlt(hdc,ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right-ps.rcPaint.left,ps.rcPaint.bottom-ps.rcPaint.top,
+ // hdc2,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY);
+ BitBlt(hdc,ps.rcPaint.left,ps.rcPaint.top,ps.rcPaint.right-ps.rcPaint.left,ps.rcPaint.bottom-ps.rcPaint.top,
+ hdc2,ps.rcPaint.left,ps.rcPaint.top,SRCCOPY);
+ SelectObject(hdc2,hbmpo);
+ DeleteObject(hbmp);
+ mod_DeleteDC(hdc2);
+ ps.fErase = FALSE;
+ EndPaint(hwnd,&ps);
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ case WM_GETMINMAXINFO:{
+ RECT rct;
+ GetWindowRect(hwnd,&rct);
+ memset((LPMINMAXINFO)lParam,0,sizeof(MINMAXINFO));
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = 16;
+ ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = 16;
+ ((LPMINMAXINFO)lParam)->ptMaxTrackSize.x = 1600;
+ ((LPMINMAXINFO)lParam)->ptMaxTrackSize.y = 1600;
+ return(0);
+ }
+
+ case WM_SHOWWINDOW:
+ {
+ int res;
+ int ID;
+ if (tooltipshoing){
+ NotifyEventHooks(g_CluiData.hEventStatusBarHideToolTip,0,0);
+ tooltipshoing = FALSE;
+ };
+ ID=Sync( FindFrameID, hwnd );
+ if (ID)
+ {
+ res = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS,ID),0);
+ if (res >= 0) db_set_b(0,"CLUI","ShowSBar",(BYTE)(wParam/*(res&F_VISIBLE)*/?1:0));
+ }
+ }
+ break;
+ case WM_TIMER:
+ {
+ if (wParam == TM_STATUSBARHIDE)
+ {
+ KillTimer(hwnd,TM_STATUSBARHIDE);
+ if (tooltipshoing)
+ {
+ NotifyEventHooks(g_CluiData.hEventStatusBarHideToolTip,0,0);
+ tooltipshoing = FALSE;
+ ReleaseCapture();
+ };
+ }
+ else if (wParam == TM_STATUSBAR)
+ {
+ POINT pt;
+ KillTimer(hwnd,TM_STATUSBAR);
+ GetCursorPos(&pt);
+ if (pt.x == lastpnt.x && pt.y == lastpnt.y)
+ {
+ int i;
+ RECT rc;
+ ScreenToClient(hwnd,&pt);
+ for (i=0; i < allocedItemData; i++)
+ {
+ rc = ProtosData[i].protoRect;
+ if (PtInRect(&rc,pt))
+ {
+ NotifyEventHooks(g_CluiData.hEventStatusBarShowToolTip,(WPARAM)ProtosData[i].AccountName,0);
+ CLUI_SafeSetTimer(hwnd,TM_STATUSBARHIDE,db_get_w(NULL,"CLUIFrames","HideToolTipTime",SETTING_HIDETOOLTIPTIME_DEFAULT),0);
+ tooltipshoing = TRUE;
+ ClientToScreen(hwnd,&pt);
+ ptToolTipShow = pt;
+ SetCapture(hwnd);
+ return 0;
+ }
+ }
+ return 0;
+ }
+ }
+ return 0;
+ }
+ case WM_MOUSEMOVE:
+ if (tooltipshoing)
+ {
+ POINT pt;
+ GetCursorPos(&pt);
+ if (abs(pt.x-ptToolTipShow.x)>TOOLTIP_TOLERANCE || abs(pt.y-ptToolTipShow.y)>TOOLTIP_TOLERANCE)
+ {
+ KillTimer(hwnd,TM_STATUSBARHIDE);
+ NotifyEventHooks(g_CluiData.hEventStatusBarHideToolTip,0,0);
+ tooltipshoing = FALSE;
+ ReleaseCapture();
+ }
+ }
+ break;
+ case WM_SETCURSOR:
+ {
+ if (g_CluiData.bBehindEdgeSettings) CLUI_UpdateTimer(0);
+ {
+ POINT pt;
+ GetCursorPos(&pt);
+ SendMessage(GetParent(hwnd),msg,wParam,lParam);
+ if (pt.x == lastpnt.x && pt.y == lastpnt.y)
+ {
+ return(CLUI_TestCursorOnBorders());
+ };
+ lastpnt = pt;
+ if (tooltipshoing)
+ if (abs(pt.x-ptToolTipShow.x)>TOOLTIP_TOLERANCE || abs(pt.y-ptToolTipShow.y)>TOOLTIP_TOLERANCE)
+ {
+ KillTimer(hwnd,TM_STATUSBARHIDE);
+ NotifyEventHooks(g_CluiData.hEventStatusBarHideToolTip,0,0);
+ tooltipshoing = FALSE;
+ ReleaseCapture();
+ };
+ KillTimer(hwnd,TM_STATUSBAR);
+ CLUI_SafeSetTimer(hwnd,TM_STATUSBAR,db_get_w(NULL,"CLC","InfoTipHoverTime",CLCDEFAULT_INFOTIPTIME),0);
+
+ return(CLUI_TestCursorOnBorders());
+ }
+ }
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ {
+ RECT rc;
+ POINT pt;
+ int i;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ KillTimer(hwnd,TM_STATUSBARHIDE);
+ KillTimer(hwnd,TM_STATUSBAR);
+
+ if (tooltipshoing){
+ NotifyEventHooks(g_CluiData.hEventStatusBarHideToolTip,0,0);
+ };
+ tooltipshoing = FALSE;
+ for (i=0; i < allocedItemData; i++)
+ {
+ RECT rc1;
+ BOOL isOnExtra = FALSE;
+
+ rc = ProtosData[i].protoRect;
+ rc1 = rc;
+ rc1.left = rc.left+16;
+ rc1.right = rc1.left+16;
+ if (PtInRect(&rc,pt) && PtInRect(&rc1,pt) && ProtosData[i].DoubleIcons)
+ isOnExtra = TRUE;
+ if (PtInRect(&rc,pt))
+ {
+ HMENU hMenu = NULL;
+
+ BOOL bShift = ( GetKeyState( VK_SHIFT )&0x8000 );
+ BOOL bCtrl = ( GetKeyState( VK_CONTROL )&0x8000 );
+
+ if (( msg == WM_MBUTTONDOWN || ( msg == WM_RBUTTONDOWN && bCtrl ) || isOnExtra) && _ModernStatus_OnExtraIconClick( i ))
+ {
+ return TRUE;
+ }
+ if ( msg == WM_LBUTTONDOWN && bCtrl )
+ {
+ if ( g_CluiData.bFilterEffective != CLVM_FILTER_PROTOS || !bShift )
+ {
+ ApplyViewMode( "" );
+ mir_snprintf( g_CluiData.protoFilter, SIZEOF(g_CluiData.protoFilter), "%s|", ProtosData[i].AccountName );
+ g_CluiData.bFilterEffective = CLVM_FILTER_PROTOS;
+ }
+ else
+ {
+ char protoF[ sizeof(g_CluiData.protoFilter) ];
+ mir_snprintf( protoF, SIZEOF(protoF), "%s|", ProtosData[i].AccountName );
+ char * pos = strstri( g_CluiData.protoFilter, ProtosData[i].AccountName );
+ if ( pos )
+ {
+ // remove filter
+ int len = strlen( protoF );
+ memmove( pos, pos + len, strlen( pos + len ) + 1 );
+
+ if ( strlen( g_CluiData.protoFilter ) == 0 )
+ ApplyViewMode( "" );
+ else
+ g_CluiData.bFilterEffective = CLVM_FILTER_PROTOS;
+ }
+ else
+ {
+ //add filter
+ mir_snprintf( g_CluiData.protoFilter, SIZEOF(g_CluiData.protoFilter), "%s%s", g_CluiData.protoFilter, protoF );
+ g_CluiData.bFilterEffective = CLVM_FILTER_PROTOS;
+ }
+ }
+ if ( g_CluiData.bFilterEffective == CLVM_FILTER_PROTOS)
+ {
+ char filterName[ sizeof(g_CluiData.protoFilter) ] = { 0 };
+ filterName[0] = (char)13;
+
+ int protoCount;
+ PROTOACCOUNT ** accs;
+ ProtoEnumAccounts( &protoCount, &accs );
+
+ bool first = true;
+ for ( int pos = 0; pos < protoCount; pos++ )
+ {
+ int i = pcli->pfnGetAccountIndexByPos( pos );
+
+ if ( i < 0 && i >= protoCount )
+ continue;
+
+ char protoF[ sizeof(g_CluiData.protoFilter) ];
+ mir_snprintf( protoF, SIZEOF(protoF), "%s|", accs[i]->szModuleName );
+ if ( strstri( g_CluiData.protoFilter, protoF ))
+ {
+ char * temp = mir_utf8encodeT( accs[i]->tszAccountName );
+ if ( !first )
+ strncat( filterName, "; ", SIZEOF(filterName) - strlen(filterName));
+ strncat( filterName, temp, SIZEOF(filterName) - strlen(filterName));
+ first = false;
+ mir_free( temp );
+ }
+ }
+
+ SaveViewMode( filterName, _T(""), g_CluiData.protoFilter, 0, -1, 0, 0, 0, 0 );
+
+ ApplyViewMode( filterName );
+ }
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ CLUI__cliInvalidateRect( hwnd, NULL, FALSE );
+ SetCapture( NULL );
+ return 0;
+ }
+ if ( !hMenu)
+ {
+ if (msg == WM_RBUTTONDOWN)
+ {
+ BOOL a = ((g_StatusBarData.perProtoConfig && ProtosData[i].SBarRightClk) || g_StatusBarData.SBarRightClk );
+ if ( a ^ bShift )
+ hMenu = (HMENU)CallService(MS_CLIST_MENUGETMAIN,0,0);
+ else
+ hMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ }
+ else
+ {
+ hMenu = (HMENU)CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ unsigned int cpnl = 0;
+ int mcnt = GetMenuItemCount(hMenu);
+ for (int j = 0; j < mcnt; ++j) {
+ HMENU hMenus = GetSubMenu(hMenu, j);
+ if (hMenus && cpnl++ == i) {
+ hMenu = hMenus;
+ break;
+ }
+ }
+ }
+ }
+ ClientToScreen(hwnd,&pt);
+ {
+ HWND parent = GetParent(hwnd);
+ if (parent != pcli->hwndContactList) parent = GetParent(parent);
+ TrackPopupMenu(hMenu,TPM_TOPALIGN|TPM_LEFTALIGN|TPM_LEFTBUTTON,pt.x,pt.y,0,parent,NULL);
+ }
+ return 0;
+ }
+ }
+ GetClientRect( hwnd, &rc );
+ if ( PtInRect( &rc, pt ) && msg == WM_LBUTTONDOWN && g_CluiData.bFilterEffective == CLVM_FILTER_PROTOS )
+ {
+ ApplyViewMode( "" );
+ CLUI__cliInvalidateRect( hwnd, NULL, FALSE );
+ SetCapture( NULL );
+ return 0;
+ }
+ return SendMessage(GetParent(hwnd), msg, wParam, lParam );
+ }
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+HWND StatusBar_Create(HWND parent)
+{
+ WNDCLASS wndclass = {0};
+ TCHAR pluginname[] = _T("ModernStatusBar");
+ int h = GetSystemMetrics(SM_CYSMICON)+2;
+ if (GetClassInfo(g_hInst,pluginname,&wndclass) == 0)
+ {
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = ModernStatusProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = pluginname;
+ RegisterClass(&wndclass);
+ }
+ hModernStatusBar = CreateWindow(pluginname,pluginname,WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN,
+ 0,0,0,h,parent,NULL,g_hInst,NULL);
+ // register frame
+ {
+ CLISTFrame Frame;
+ memset(&Frame,0,sizeof(Frame));
+ Frame.cbSize = sizeof(CLISTFrame);
+ Frame.hWnd = hModernStatusBar;
+ Frame.align = alBottom;
+ Frame.hIcon = LoadSkinnedIcon (SKINICON_OTHER_MIRANDA);
+ Frame.Flags = (db_get_b(NULL,"CLUI","ShowSBar",SETTING_SHOWSBAR_DEFAULT)?F_VISIBLE:0)|F_LOCKED|F_NOBORDER|F_NO_SUBCONTAINER|F_TCHAR;
+ Frame.height = h;
+ Frame.tname = _T("Status Bar");
+ Frame.TBtname = TranslateT("Status Bar");
+ hFramehModernStatusBar = (HANDLE)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&Frame,(LPARAM)0);
+ CallService(MS_SKINENG_REGISTERPAINTSUB,(WPARAM)Frame.hWnd,(LPARAM)NewStatusPaintCallbackProc); //$$$$$ register sub for frame
+ }
+
+ LoadStatusBarData();
+ CLUIServices_ProtocolStatusChanged(0,0);
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME,-1,0);
+ return hModernStatusBar;
+}
diff --git a/plugins/Clist_modern/src/modern_statusbar_options.cpp b/plugins/Clist_modern/src/modern_statusbar_options.cpp
new file mode 100644
index 0000000000..7b9ac4b895
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_statusbar_options.cpp
@@ -0,0 +1,541 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_commonprototypes.h"
+#include "hdr/modern_defsettings.h"
+//#include "hdr/modern_effectenum.h"
+
+typedef struct _StatusBarProtocolOptions
+{
+ char *szName;
+ BOOL AccountIsCustomized;
+ BOOL HideAccount;
+ BYTE SBarShow;
+ BYTE SBarRightClk;
+ BYTE UseConnectingIcon;
+ BYTE ShowUnreadEmails;
+ BYTE ShowXStatus;
+ int PaddingLeft;
+ int PaddingRight;
+}
+ StatusBarProtocolOptions;
+
+static StatusBarProtocolOptions _GlobalOptions = {0};
+
+static void UpdateXStatusIconOptions(HWND hwndDlg, BOOL perProto, StatusBarProtocolOptions* dat, int curSelProto)
+{
+ int en = IsDlgButtonChecked(hwndDlg,IDC_SHOWSBAR) && IsDlgButtonChecked(hwndDlg,IDC_SHOWICON );
+
+ if (IsDlgButtonChecked(hwndDlg,IDC_SHOWBOTH)) CheckDlgButton(hwndDlg,IDC_SHOWNORMAL,FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWBOTH),en && IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && !IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL));
+
+ if (IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL)) CheckDlgButton(hwndDlg,IDC_SHOWBOTH,FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWNORMAL),en && IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && !IsDlgButtonChecked(hwndDlg,IDC_SHOWBOTH));
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSPARENTOVERLAY),en && IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL) && !IsDlgButtonChecked(hwndDlg,IDC_SHOWBOTH));
+
+ BYTE val = 0;
+ if (IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS)) {
+ if (IsDlgButtonChecked(hwndDlg,IDC_SHOWBOTH)) val = 3;
+ else if (IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL)) val = 2;
+ else val = 1;
+ val += IsDlgButtonChecked(hwndDlg,IDC_TRANSPARENTOVERLAY)?4:0;
+ }
+ val += IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUSNAME)?8:0;
+ if (perProto)
+ dat[curSelProto].ShowXStatus = val;
+ else
+ _GlobalOptions.ShowXStatus = val;
+}
+
+static void UpdateStatusBarOptionsDisplay(HWND hwndDlg)
+{
+ StatusBarProtocolOptions *dat = (StatusBarProtocolOptions*)GetWindowLongPtr(GetDlgItem(hwndDlg,IDC_STATUSBAR_PROTO_LIST),GWLP_USERDATA);
+ BOOL perProto = (BOOL)IsDlgButtonChecked(hwndDlg,IDC_STATUSBAR_PER_PROTO);
+ HWND hwndComboBox = GetDlgItem( hwndDlg, IDC_STATUSBAR_PROTO_LIST );
+ StatusBarProtocolOptions sbpo;
+ int curSelProto = SendMessage(hwndComboBox, CB_GETITEMDATA, SendMessage(hwndComboBox, CB_GETCURSEL, 0, 0), NULL) - 1; //first entry is the combo box is a constant.
+ if (curSelProto < 0)
+ perProto = FALSE;
+
+ if (perProto)
+ sbpo = dat[curSelProto];
+ else
+ sbpo = _GlobalOptions;
+
+ if (perProto) {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SBAR_USE_ACCOUNT_SETTINGS), TRUE);
+ CheckDlgButton(hwndDlg, IDC_SBAR_USE_ACCOUNT_SETTINGS, sbpo.AccountIsCustomized ? BST_CHECKED : BST_UNCHECKED);
+ }
+ else EnableWindow(GetDlgItem(hwndDlg, IDC_SBAR_USE_ACCOUNT_SETTINGS), FALSE);
+
+ CheckDlgButton(hwndDlg, IDC_SBAR_HIDE_ACCOUNT_COMPLETELY, sbpo.HideAccount ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_USECONNECTINGICON, sbpo.UseConnectingIcon ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWXSTATUSNAME, ((sbpo.ShowXStatus&8)>0) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWXSTATUS, ((sbpo.ShowXStatus&3)>0) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWNORMAL, ((sbpo.ShowXStatus&3) == 2) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWBOTH, ((sbpo.ShowXStatus&3) == 3) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWUNREADEMAIL, (sbpo.ShowUnreadEmails == 1) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_TRANSPARENTOVERLAY, ((sbpo.ShowXStatus&4)) ? BST_CHECKED : BST_UNCHECKED);
+ {
+ BYTE showOpts = sbpo.SBarShow;
+ CheckDlgButton(hwndDlg, IDC_SHOWICON, showOpts&1 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWPROTO, showOpts&2 ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_SHOWSTATUS, showOpts&4 ? BST_CHECKED : BST_UNCHECKED);
+ }
+ CheckDlgButton(hwndDlg, IDC_RIGHTSTATUS, sbpo.SBarRightClk ? BST_UNCHECKED : BST_CHECKED);
+ CheckDlgButton(hwndDlg, IDC_RIGHTMIRANDA, !IsDlgButtonChecked(hwndDlg,IDC_RIGHTSTATUS) ? BST_CHECKED : BST_UNCHECKED);
+
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_LEFT,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_LEFT,UDM_SETPOS,0,MAKELONG(sbpo.PaddingLeft,2));
+
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_RIGHT,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_RIGHT,UDM_SETPOS,0,MAKELONG(sbpo.PaddingRight,2));
+
+ if ( !sbpo.AccountIsCustomized)
+ UpdateXStatusIconOptions(hwndDlg, perProto, dat, curSelProto);
+
+ {
+ BOOL enableIcons = IsDlgButtonChecked(hwndDlg,IDC_SHOWICON );
+ BOOL enableOptions = !perProto || sbpo.AccountIsCustomized;
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SBAR_HIDE_ACCOUNT_COMPLETELY), enableOptions && perProto);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_USECONNECTINGICON), enableOptions && enableIcons);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWXSTATUSNAME), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWXSTATUS), enableOptions && enableIcons);
+
+ if ( !enableOptions) {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWNORMAL), enableOptions && enableIcons);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWBOTH), enableOptions && enableIcons );
+ EnableWindow(GetDlgItem(hwndDlg, IDC_TRANSPARENTOVERLAY), enableOptions && enableIcons);
+ }
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWUNREADEMAIL), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWICON), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWPROTO), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSTATUS), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHTSTATUS), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RIGHTMIRANDA), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_OFFSETICON_LEFT), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_OFFSETSPIN_LEFT), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_OFFSETICON_RIGHT), enableOptions);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_OFFSETSPIN_RIGHT), enableOptions);
+ }
+
+ if ( !perProto || sbpo.AccountIsCustomized)
+ UpdateXStatusIconOptions(hwndDlg, perProto, dat, curSelProto);
+}
+
+INT_PTR CALLBACK DlgProcSBarOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ StatusBarProtocolOptions *dat = (StatusBarProtocolOptions*)GetWindowLongPtr(GetDlgItem(hwndDlg,IDC_STATUSBAR_PROTO_LIST),GWLP_USERDATA);
+ LOGFONTA lf;
+ BOOL perProto = IsDlgButtonChecked(hwndDlg, IDC_STATUSBAR_PER_PROTO);
+ HWND hwndComboBox = GetDlgItem( hwndDlg, IDC_STATUSBAR_PROTO_LIST );
+ int curSelProto = SendMessage(hwndComboBox, CB_GETITEMDATA, SendMessage(hwndComboBox, CB_GETCURSEL, 0, 0), NULL) - 1; //first entry is the combo box is a constant.
+ if (curSelProto < 0)
+ perProto = FALSE;
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ perProto = (BOOL)db_get_b(NULL,"CLUI","SBarPerProto",SETTING_SBARPERPROTO_DEFAULT);
+
+ TranslateDialogDefault(hwndDlg);
+
+ CheckDlgButton(hwndDlg, IDC_SHOWSBAR, db_get_b(NULL,"CLUI","ShowSBar",SETTING_SHOWSBAR_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_STATUSBAR_PER_PROTO, perProto ? BST_CHECKED : BST_UNCHECKED);
+ {
+ // populate per-proto list box.
+ char *szName;
+ char buf[256];
+ int count;
+
+ SendMessage(hwndComboBox, CB_RESETCONTENT, 0, 0);
+
+ PROTOACCOUNT **accs;
+ ProtoEnumAccounts( &count, &accs );
+
+ dat = (StatusBarProtocolOptions*)mir_alloc(sizeof(StatusBarProtocolOptions)*count);
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_STATUSBAR_PROTO_LIST),GWLP_USERDATA,(LONG_PTR)dat);
+
+ SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM)TranslateT( " << Global>>" ));
+ SendMessage(hwndComboBox, CB_SETITEMDATA, 0, (LPARAM)0);
+
+ for (int i=0; i < count; i++ ) {
+ szName = accs[i]->szModuleName;
+ dat[i].szName = szName;
+
+ DWORD dwNewId = SendMessage(hwndComboBox, CB_ADDSTRING, 0, (LPARAM)accs[i]->tszAccountName);
+ SendMessage(hwndComboBox, CB_SETITEMDATA, dwNewId, (LPARAM)(i+1));
+
+ mir_snprintf(buf, SIZEOF(buf), "SBarAccountIsCustom_%s", szName);
+ dat[i].AccountIsCustomized = db_get_b(NULL,"CLUI", buf, SETTING_SBARACCOUNTISCUSTOM_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "HideAccount_%s", szName);
+ dat[i].HideAccount = db_get_b(NULL,"CLUI", buf, SETTING_SBARHIDEACCOUNT_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "SBarShow_%s", szName);
+ dat[i].SBarShow = db_get_b(NULL,"CLUI", buf, SETTING_SBARSHOW_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "SBarRightClk_%s", szName);
+ dat[i].SBarRightClk = db_get_b(NULL,"CLUI", buf, SETTING_SBARRIGHTCLK_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "ShowUnreadEmails_%s", szName);
+ dat[i].ShowUnreadEmails = db_get_b(NULL,"CLUI", buf, SETTING_SHOWUNREADEMAILS_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "ShowXStatus_%s", szName);
+ dat[i].ShowXStatus = db_get_b(NULL,"CLUI", buf, SETTING_SHOWXSTATUS_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "UseConnectingIcon_%s", szName);
+ dat[i].UseConnectingIcon = db_get_b(NULL,"CLUI", buf, SETTING_USECONNECTINGICON_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "PaddingLeft_%s", szName);
+ dat[i].PaddingLeft = db_get_dw(NULL,"CLUI", buf, SETTING_PADDINGLEFT_DEFAULT);
+
+ mir_snprintf(buf, SIZEOF(buf), "PaddingRight_%s", szName);
+ dat[i].PaddingRight = db_get_dw(NULL,"CLUI", buf, SETTING_PADDINGRIGHT_DEFAULT);
+ }
+
+ if (count)
+ SendMessage(hwndComboBox, CB_SETCURSEL, 0, 0);
+ }
+
+ _GlobalOptions.AccountIsCustomized = TRUE;
+ _GlobalOptions.SBarRightClk = db_get_b(NULL,"CLUI", "SBarRightClk", SETTING_SBARRIGHTCLK_DEFAULT);
+ _GlobalOptions.ShowUnreadEmails = db_get_b(NULL,"CLUI", "ShowUnreadEmails", SETTING_SHOWUNREADEMAILS_DEFAULT);
+ _GlobalOptions.ShowXStatus = db_get_b(NULL,"CLUI", "ShowXStatus", SETTING_SHOWXSTATUS_DEFAULT);
+ _GlobalOptions.UseConnectingIcon = db_get_b(NULL,"CLUI", "UseConnectingIcon", SETTING_USECONNECTINGICON_DEFAULT);
+ _GlobalOptions.SBarShow = db_get_b(NULL,"CLUI","SBarShow",SETTING_SBARSHOW_DEFAULT);
+
+ CheckDlgButton(hwndDlg, IDC_EQUALSECTIONS, db_get_b(NULL,"CLUI","EqualSections",SETTING_EQUALSECTIONS_DEFAULT) ? BST_CHECKED : BST_UNCHECKED);
+
+ SendDlgItemMessage(hwndDlg,IDC_MULTI_SPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_MULTI_SPIN,UDM_SETPOS,0,MAKELONG(db_get_b(NULL,"CLUI","StatusBarProtosPerLine",SETTING_PROTOSPERLINE_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN,UDM_SETPOS,0,MAKELONG(db_get_dw(NULL,"CLUI","LeftOffset",SETTING_LEFTOFFSET_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN2,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN2,UDM_SETPOS,0,MAKELONG(db_get_dw(NULL,"CLUI","RightOffset",SETTING_RIGHTOFFSET_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_SBAR_BORDER_TOP_SPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_SBAR_BORDER_TOP_SPIN,UDM_SETPOS,0,MAKELONG(db_get_dw(NULL,"CLUI","TopOffset",SETTING_TOPOFFSET_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_SBAR_BORDER_BOTTOM_SPIN,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_SBAR_BORDER_BOTTOM_SPIN,UDM_SETPOS,0,MAKELONG(db_get_dw(NULL,"CLUI","BottomOffset",SETTING_BOTTOMOFFSET_DEFAULT),0));
+
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN3,UDM_SETRANGE,0,MAKELONG(50,0));
+ SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN3,UDM_SETPOS,0,MAKELONG(db_get_dw(NULL,"CLUI","SpaceBetween",SETTING_SPACEBETWEEN_DEFAULT),2));
+
+ {
+ int i, item;
+ TCHAR *align[] = {_T("Left"), _T("Center"), _T("Right")};
+ for (i=0; i < SIZEOF(align); i++) {
+ item = SendDlgItemMessage(hwndDlg,IDC_SBAR_HORIZ_ALIGN,CB_ADDSTRING,0,(LPARAM)TranslateTS(align[i]));
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_SBAR_HORIZ_ALIGN, CB_SETCURSEL, db_get_b(NULL, "CLUI", "Align", SETTING_ALIGN_DEFAULT), 0);
+ }
+
+ {
+ int i, item;
+ TCHAR *align[] = {_T("Top"), _T("Center"), _T("Bottom")};
+ for (i=0; i < SIZEOF(align); i++) {
+ item = SendDlgItemMessage(hwndDlg,IDC_SBAR_VERT_ALIGN,CB_ADDSTRING,0,(LPARAM)TranslateTS(align[i]));
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_SBAR_VERT_ALIGN, CB_SETCURSEL, db_get_b(NULL, "CLUI", "VAlign", SETTING_VALIGN_DEFAULT), 0);
+ }
+
+ {
+ int en = IsDlgButtonChecked(hwndDlg,IDC_SHOWSBAR);
+ int en_icons = IsDlgButtonChecked(hwndDlg,IDC_SHOWICON );
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWICON),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWPROTO),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWSTATUS),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_RIGHTSTATUS),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_RIGHTMIRANDA),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_EQUALSECTIONS),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USECONNECTINGICON),en && en_icons);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USEOWNERDRAW),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN2),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON2),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN3),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON3),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON_BROWSE),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_ONLY_IF_DIFFERENT),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_COLOUR),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWXSTATUSNAME),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWXSTATUS),en && en_icons);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWBOTH),en && en_icons && IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && !IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWNORMAL),en && en_icons && IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && !IsDlgButtonChecked(hwndDlg,IDC_SHOWBOTH));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_TRANSPARENTOVERLAY),en && en_icons && IsDlgButtonChecked(hwndDlg,IDC_SHOWXSTATUS) && IsDlgButtonChecked(hwndDlg,IDC_SHOWNORMAL) && !IsDlgButtonChecked(hwndDlg,IDC_SHOWBOTH));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWUNREADEMAIL),en);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON_LEFT),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN_LEFT),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON_RIGHT),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN_RIGHT),en);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI_2),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI_COUNT),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI_SPIN),en);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUSBAR_PER_PROTO),en);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_STATUSBAR_PROTO_LIST), en && IsDlgButtonChecked(hwndDlg, IDC_STATUSBAR_PER_PROTO));
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SBAR_USE_ACCOUNT_SETTINGS), FALSE);
+ }
+
+ UpdateStatusBarOptionsDisplay(hwndDlg);
+ return TRUE;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_BUTTON1)
+ {
+ if (HIWORD(wParam) == BN_CLICKED)
+ {
+ CHOOSEFONTA fnt;
+ memset(&fnt,0,sizeof(CHOOSEFONTA));
+ fnt.lStructSize = sizeof(CHOOSEFONTA);
+ fnt.hwndOwner = hwndDlg;
+ fnt.Flags = CF_SCREENFONTS|CF_INITTOLOGFONTSTRUCT;
+ fnt.lpLogFont = &lf;
+ ChooseFontA(&fnt);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ return 0;
+ }
+ }
+ else if (LOWORD(wParam) == IDC_COLOUR || (LOWORD(wParam) == IDC_SBAR_HORIZ_ALIGN && HIWORD(wParam) == CBN_SELCHANGE)) SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ else if (LOWORD(wParam) == IDC_SHOWSBAR) {
+ int en = IsDlgButtonChecked(hwndDlg,IDC_SHOWSBAR);
+ int en_icons = IsDlgButtonChecked(hwndDlg,IDC_SHOWICON );
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWICON),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWPROTO),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWSTATUS),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_RIGHTSTATUS),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_RIGHTMIRANDA),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_EQUALSECTIONS),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USECONNECTINGICON),en && en_icons);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USEOWNERDRAW),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN2),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON2),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETSPIN3),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_OFFSETICON3),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_BORDER_TOP),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_BORDER_TOP_SPIN),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_BORDER_BOTTOM),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_BORDER_BOTTOM_SPIN),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_HORIZ_ALIGN),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_COLOUR),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_BUTTON1),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWXSTATUSNAME),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWXSTATUS),en && en_icons);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOWUNREADEMAIL),en);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI_2),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI_COUNT),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_MULTI_SPIN),en);
+
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUSBAR_PER_PROTO),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUSBAR_PROTO_LIST),en && IsDlgButtonChecked(hwndDlg,IDC_STATUSBAR_PER_PROTO));
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_USE_ACCOUNT_SETTINGS),en && IsDlgButtonChecked(hwndDlg,IDC_STATUSBAR_PER_PROTO));
+
+ UpdateStatusBarOptionsDisplay(hwndDlg);
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ }
+ else if (LOWORD(wParam) == IDC_STATUSBAR_PER_PROTO)
+ {
+ int en = IsDlgButtonChecked(hwndDlg,IDC_STATUSBAR_PER_PROTO);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_STATUSBAR_PROTO_LIST),en);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_HIDE_ACCOUNT_COMPLETELY), en && perProto);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SBAR_USE_ACCOUNT_SETTINGS), en);
+
+ UpdateStatusBarOptionsDisplay(hwndDlg);
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ }
+ else if (
+ LOWORD(wParam) == IDC_SHOWXSTATUS ||
+ LOWORD(wParam) == IDC_SHOWBOTH ||
+ LOWORD(wParam) == IDC_SHOWNORMAL ||
+ LOWORD(wParam) == IDC_TRANSPARENTOVERLAY ||
+ LOWORD(wParam) == IDC_SHOWXSTATUSNAME
+ )
+ {
+ UpdateXStatusIconOptions(hwndDlg, perProto, dat, curSelProto);
+ }
+ else if (LOWORD(wParam) == IDC_SBAR_USE_ACCOUNT_SETTINGS)
+ {
+ if (perProto) {
+ dat[curSelProto].AccountIsCustomized = IsDlgButtonChecked(hwndDlg, IDC_SBAR_USE_ACCOUNT_SETTINGS);
+ UpdateStatusBarOptionsDisplay(hwndDlg);
+ }
+ }
+ else if (LOWORD(wParam) == IDC_SBAR_HIDE_ACCOUNT_COMPLETELY)
+ {
+ if (perProto)
+ dat[curSelProto].HideAccount = IsDlgButtonChecked(hwndDlg, IDC_SBAR_HIDE_ACCOUNT_COMPLETELY);
+ }
+ else if (LOWORD(wParam) == IDC_USECONNECTINGICON)
+ {
+ if (perProto)
+ dat[curSelProto].UseConnectingIcon = IsDlgButtonChecked(hwndDlg, IDC_USECONNECTINGICON);
+ else
+ _GlobalOptions.UseConnectingIcon = IsDlgButtonChecked(hwndDlg, IDC_USECONNECTINGICON);
+ }
+ else if (LOWORD(wParam) == IDC_SHOWUNREADEMAIL)
+ {
+ if (perProto)
+ dat[curSelProto].ShowUnreadEmails = IsDlgButtonChecked(hwndDlg, IDC_SHOWUNREADEMAIL);
+ else
+ _GlobalOptions.ShowUnreadEmails = IsDlgButtonChecked(hwndDlg, IDC_SHOWUNREADEMAIL);
+ }
+ else if (LOWORD(wParam) == IDC_SHOWICON || LOWORD(wParam) == IDC_SHOWPROTO || LOWORD(wParam) == IDC_SHOWSTATUS)
+ {
+ BYTE val = (IsDlgButtonChecked(hwndDlg, IDC_SHOWICON)?1:0)|(IsDlgButtonChecked(hwndDlg, IDC_SHOWPROTO)?2:0)|(IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUS)?4:0);
+ if (perProto)
+ dat[curSelProto].SBarShow = val;
+ else
+ _GlobalOptions.SBarShow = val;
+
+ UpdateStatusBarOptionsDisplay(hwndDlg);
+ }
+ else if (LOWORD(wParam) == IDC_RIGHTSTATUS || LOWORD(wParam) == IDC_RIGHTMIRANDA)
+ {
+ if (perProto)
+ dat[curSelProto].SBarRightClk = IsDlgButtonChecked(hwndDlg,IDC_RIGHTMIRANDA);
+ else
+ _GlobalOptions.SBarRightClk = IsDlgButtonChecked(hwndDlg,IDC_RIGHTMIRANDA);
+ }
+ else if (LOWORD(wParam) == IDC_OFFSETICON_LEFT)
+ {
+ if (perProto)
+ dat[curSelProto].PaddingLeft = (DWORD)SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_LEFT,UDM_GETPOS,0,0);
+ else
+ _GlobalOptions.PaddingLeft = (DWORD)SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_LEFT,UDM_GETPOS,0,0);
+ }
+ else if (LOWORD(wParam) == IDC_OFFSETICON_RIGHT)
+ {
+ if (perProto)
+ dat[curSelProto].PaddingRight = (DWORD)SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_RIGHT,UDM_GETPOS,0,0);
+ else
+ _GlobalOptions.PaddingRight = (DWORD)SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN_RIGHT,UDM_GETPOS,0,0);
+ }
+ else if (
+ (
+ LOWORD(wParam) == IDC_MULTI_COUNT ||
+ LOWORD(wParam) == IDC_OFFSETICON ||
+ LOWORD(wParam) == IDC_OFFSETICON2 ||
+ LOWORD(wParam) == IDC_OFFSETICON3 ||
+ LOWORD(wParam) == IDC_SBAR_BORDER_BOTTOM ||
+ LOWORD(wParam) == IDC_SBAR_BORDER_TOP
+ ) && (
+ HIWORD(wParam) != EN_CHANGE ||
+ (HWND)lParam != GetFocus()
+ ))
+ return 0; // dont make apply enabled during buddy set crap
+ else if ( LOWORD(wParam) == IDC_STATUSBAR_PROTO_LIST )
+ {
+ UpdateStatusBarOptionsDisplay(hwndDlg);
+ return 0;
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY:
+ {
+ int count = db_get_dw(0,"Protocols","ProtoCount",-1);
+ db_set_b(NULL, "CLUI", "SBarPerProto", IsDlgButtonChecked(hwndDlg, IDC_STATUSBAR_PER_PROTO));
+
+ for (int i=0; i < count; i++) {
+ HWND hwndComboBox = GetDlgItem( hwndDlg, IDC_STATUSBAR_PROTO_LIST );
+ StatusBarProtocolOptions sbpo = dat[i];
+ char *defProto = sbpo.szName;
+
+ char settingBuf[256];
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "SBarAccountIsCustom_%s", defProto);
+ db_set_b(NULL,"CLUI",settingBuf,(BYTE)sbpo.AccountIsCustomized);
+
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "HideAccount_%s", defProto);
+ db_set_b(NULL,"CLUI",settingBuf,(BYTE)sbpo.HideAccount);
+
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "SBarShow_%s", defProto);
+ db_set_b(NULL,"CLUI",settingBuf,(BYTE)sbpo.SBarShow);
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "SBarRightClk_%s", defProto);
+ db_set_b(NULL,"CLUI",settingBuf,(BYTE)sbpo.SBarRightClk);
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "UseConnectingIcon_%s", defProto);
+ db_set_b(NULL,"CLUI",settingBuf,(BYTE)sbpo.UseConnectingIcon);
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "ShowUnreadEmails_%s", defProto);
+ db_set_b(NULL,"CLUI",settingBuf,(BYTE)sbpo.ShowUnreadEmails);
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "ShowXStatus_%s", defProto);
+ db_set_b(NULL,"CLUI",settingBuf,sbpo.ShowXStatus);
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "PaddingLeft_%s", defProto);
+ db_set_dw(NULL,"CLUI",settingBuf,sbpo.PaddingLeft);
+ mir_snprintf(settingBuf, SIZEOF(settingBuf), "PaddingRight_%s", defProto);
+ db_set_dw(NULL,"CLUI",settingBuf,sbpo.PaddingRight);
+ }
+
+ db_set_b(NULL,"CLUI","SBarShow",(BYTE)_GlobalOptions.SBarShow);
+ db_set_b(NULL,"CLUI","SBarRightClk",(BYTE)_GlobalOptions.SBarRightClk);
+ db_set_b(NULL,"CLUI","UseConnectingIcon",(BYTE)_GlobalOptions.UseConnectingIcon);
+ db_set_b(NULL,"CLUI","ShowUnreadEmails",(BYTE)_GlobalOptions.ShowUnreadEmails);
+ db_set_b(NULL,"CLUI","ShowXStatus",_GlobalOptions.ShowXStatus);
+ db_set_dw(NULL,"CLUI","PaddingLeft",_GlobalOptions.PaddingLeft);
+ db_set_dw(NULL,"CLUI","PaddingRight",_GlobalOptions.PaddingRight);
+
+
+ db_set_b(NULL,"CLUI","StatusBarProtosPerLine",(BYTE)SendDlgItemMessage(hwndDlg,IDC_MULTI_SPIN,UDM_GETPOS,0,0));
+ db_set_b(NULL,"CLUI","EqualSections",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_EQUALSECTIONS));
+ db_set_b(NULL,"CLUI","Align",(BYTE)SendDlgItemMessage(hwndDlg,IDC_SBAR_HORIZ_ALIGN,CB_GETCURSEL,0,0));
+ db_set_b(NULL,"CLUI","VAlign",(BYTE)SendDlgItemMessage(hwndDlg,IDC_SBAR_VERT_ALIGN,CB_GETCURSEL,0,0));
+ db_set_dw(NULL,"CLUI","LeftOffset",(DWORD)SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN,UDM_GETPOS,0,0));
+ db_set_dw(NULL,"CLUI","RightOffset",(DWORD)SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN2,UDM_GETPOS,0,0));
+ db_set_dw(NULL,"CLUI","TopOffset",(DWORD)SendDlgItemMessage(hwndDlg,IDC_SBAR_BORDER_TOP_SPIN,UDM_GETPOS,0,0));
+ db_set_dw(NULL,"CLUI","BottomOffset",(DWORD)SendDlgItemMessage(hwndDlg,IDC_SBAR_BORDER_BOTTOM_SPIN,UDM_GETPOS,0,0));
+ db_set_dw(NULL,"CLUI","SpaceBetween",(DWORD)SendDlgItemMessage(hwndDlg,IDC_OFFSETSPIN3,UDM_GETPOS,0,0));
+ db_set_dw(NULL,"ModernData","StatusBarFontCol",SendDlgItemMessage(hwndDlg,IDC_COLOUR,CPM_GETCOLOUR,0,0));
+ db_set_b(NULL,"CLUI","ShowSBar",(BYTE)IsDlgButtonChecked(hwndDlg,IDC_SHOWSBAR));
+
+ LoadStatusBarData();
+ CLUIServices_ProtocolStatusChanged(0,0);
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ mir_free(dat);
+ break;
+ }
+ return FALSE;
+}
diff --git a/plugins/Clist_modern/src/modern_sync.cpp b/plugins/Clist_modern/src/modern_sync.cpp
new file mode 100644
index 0000000000..df3572766e
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_sync.cpp
@@ -0,0 +1,147 @@
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_sync.h"
+
+struct SYNCCALLITEM
+{
+ WPARAM wParam;
+ LPARAM lParam;
+ int nResult;
+ HANDLE hDoneEvent;
+ PSYNCCALLBACKPROC pfnProc;
+};
+
+static void CALLBACK _SyncCallerUserAPCProc(void* param)
+{
+ SYNCCALLITEM* item = (SYNCCALLITEM*)param;
+ item->nResult = item->pfnProc(item->wParam, item->lParam);
+ SetEvent(item->hDoneEvent);
+}
+
+static INT_PTR SyncCaller(WPARAM proc, LPARAM lParam)
+{
+ typedef int (*P0PARAMFUNC)();
+ typedef int (*P1PARAMFUNC)(WPARAM);
+ typedef int (*P2PARAMFUNC)(WPARAM, LPARAM);
+ typedef int (*P3PARAMFUNC)(WPARAM, LPARAM, LPARAM);
+ typedef int (*P4PARAMFUNC)(WPARAM, LPARAM, LPARAM, LPARAM);
+
+ LPARAM * params = (LPARAM *)lParam;
+ int count = params[0];
+ switch (count) {
+ case 0:
+ return ((P0PARAMFUNC)proc)();
+
+ case 1:
+ return ((P1PARAMFUNC)proc)((WPARAM)params[1]);
+
+ case 2:
+ return ((P2PARAMFUNC)proc)((WPARAM)params[1],(LPARAM)params[2]);
+
+ case 3:
+ return ((P3PARAMFUNC)proc)((WPARAM)params[1],(LPARAM)params[2], (LPARAM)params[3]);
+
+ case 4:
+ return ((P4PARAMFUNC)proc)((WPARAM)params[1],(LPARAM)params[2], (LPARAM)params[3], (LPARAM)params[4]);
+ }
+ return 0;
+}
+
+int SyncCall(void * vproc, int count, ... )
+{
+ LPARAM params[5];
+ va_list va;
+ int i;
+ params[0] = (LPARAM)count;
+ va_start(va, count);
+ for (i=0; i < count && i < SIZEOF(params)-1; i++)
+ params[i+1] = va_arg(va,LPARAM);
+
+ va_end(va);
+ return SyncCallProxy(SyncCaller, (WPARAM)vproc, (LPARAM) params);
+}
+
+int SyncCallProxy(PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam, CRITICAL_SECTION * cs /*= NULL */)
+{
+ SYNCCALLITEM item = {0};
+
+ int nReturn = 0;
+
+ if ( cs != NULL ) {
+ if ( !fnTryEnterCriticalSection ) { // for poor OSes like Win98
+ EnterCriticalSection( cs );
+ int result = pfnProc( wParam, lParam );
+ LeaveCriticalSection( cs );
+ return result;
+ }
+
+ if ( fnTryEnterCriticalSection( cs )) { //simple call (Fastest)
+ int result = pfnProc(wParam,lParam);
+ LeaveCriticalSection( cs );
+ return result;
+ }
+ else { //Window SendMessage Call(Middle)
+ if ( SyncCallWinProcProxy( pfnProc, wParam, lParam, nReturn ) == S_OK)
+ return nReturn;
+ }
+ }
+ if ( SyncCallAPCProxy( pfnProc, wParam, lParam, nReturn ) == S_OK)
+ return nReturn;
+
+ return NULL;
+}
+
+HRESULT SyncCallWinProcProxy( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam, int& nReturn )
+{
+ nReturn = 0;
+ if (pcli->hwndContactList == NULL )
+ return E_FAIL;
+
+ SYNCCALLITEM item = {0};
+ item.wParam = wParam;
+ item.lParam = lParam;
+ item.pfnProc = pfnProc;
+ nReturn = SendMessage(pcli->hwndContactList, UM_SYNCCALL, (WPARAM)&item,0);
+ return S_OK;
+}
+
+HRESULT SyncCallAPCProxy( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam, int& hReturn )
+{
+ hReturn = 0;
+
+ if (pfnProc == NULL)
+ return E_FAIL;
+
+ if (GetCurrentThreadId() != g_dwMainThreadID) {
+ SYNCCALLITEM item = {0};
+ item.wParam = wParam;
+ item.lParam = lParam;
+ item.pfnProc = pfnProc;
+ item.hDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ CallFunctionAsync(_SyncCallerUserAPCProc, &item);
+
+ WaitForSingleObject(item.hDoneEvent, INFINITE);
+ CloseHandle(item.hDoneEvent);
+
+ hReturn = item.nResult;
+
+ return S_OK;
+ }
+ /* else */
+
+ hReturn = pfnProc(wParam, lParam);
+ return S_OK;
+}
+
+LRESULT SyncOnWndProcCall( WPARAM wParam )
+{
+ SYNCCALLITEM *psci = (SYNCCALLITEM *)wParam;
+ if (psci)
+ return psci->pfnProc( psci->wParam, psci->lParam );
+ return 0;
+}
+
+int DoCall( PSYNCCALLBACKPROC pfnProc, WPARAM wParam, LPARAM lParam )
+{
+ return SyncCallProxy( pfnProc, 0, lParam );
+}
diff --git a/plugins/Clist_modern/src/modern_tbbutton.cpp b/plugins/Clist_modern/src/modern_tbbutton.cpp
new file mode 100644
index 0000000000..9d0402324e
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_tbbutton.cpp
@@ -0,0 +1,503 @@
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_commonprototypes.h"
+#include "m_api/m_skinbutton.h"
+#include "hdr/modern_clcpaint.h"
+
+#include <m_button_int.h>
+#include <m_toptoolbar.h>
+
+#ifdef __MINGW32__
+#include <ctype.h>
+#endif
+
+#define BUTTON_POLLID 100
+#define BUTTON_POLLDELAY 50
+#define b2str(a) ((a) ? "True" : "False")
+
+void CustomizeToolbar(HWND);
+
+struct TBBUTTONDATA : public MButtonCtrl
+{
+ char *szButtonID; // button id
+ BOOL fSendOnDown; // send event on button pushed
+ BOOL fHotMark; // button is hot marked (e.g. current state)
+ BOOL fFocused;
+ int nFontID; // internal font ID
+ HANDLE ttbID; // control ID
+ TCHAR szText[128]; // text on the button
+ RECT rcMargins; // margins of inner content
+
+ HANDLE hIcolibHandle; // handle of icon in iconlib
+
+ XPTHANDLE hThemeButton;
+ XPTHANDLE hThemeToolbar;
+};
+
+static CRITICAL_SECTION csTips;
+static HWND hwndToolTips = NULL;
+static BOOL bThemed = FALSE;
+
+static HANDLE hButtonWindowList = NULL;
+static HANDLE hBkgChangedHook = NULL;
+
+static int OnIconLibIconChanged(WPARAM wParam, LPARAM lParam)
+{
+ WindowList_BroadcastAsync(hButtonWindowList, MBM_REFRESHICOLIBICON,0,0);
+ return 0;
+}
+
+static void InvalidateParentRect(HWND hwndChild, RECT * lpRect, BOOL fErase)
+{
+ LONG lExStyle = GetWindowLongPtr(hwndChild,GWL_EXSTYLE);
+ if (lExStyle & WS_EX_TRANSPARENT) {
+ NMHDR hdr;
+ hdr.hwndFrom = hwndChild;
+ hdr.idFrom = 0;
+ hdr.code = BUTTONNEEDREDRAW;
+ SendMessage(GetParent(hwndChild),WM_NOTIFY,(WPARAM)hwndChild,(LPARAM)&hdr);
+ }
+ else InvalidateRect(hwndChild,lpRect,fErase);
+}
+
+static int TBStateConvert2Flat(int state)
+{
+ switch (state) {
+ case PBS_NORMAL:
+ return TS_NORMAL;
+ case PBS_HOT:
+ return TS_HOT;
+ case PBS_PRESSED:
+ return TS_PRESSED;
+ case PBS_DISABLED:
+ return TS_DISABLED;
+ case PBS_DEFAULTED:
+ return TS_NORMAL;
+ }
+ return TS_NORMAL;
+}
+
+static void PaintWorker(TBBUTTONDATA *bct, HDC hdcPaint , POINT *pOffset)
+{
+ POINT offset = {0};
+ if (pOffset)
+ offset = *pOffset;
+
+ if ( !hdcPaint)
+ return; //early exit
+
+ RECT rcClient;
+ GetClientRect(bct->hwnd, &rcClient);
+ int width = rcClient.right - rcClient.left;
+ int height = rcClient.bottom - rcClient.top;
+
+ HBITMAP hbmMem;
+ HBITMAP hbmOld = NULL;
+ HDC hdcMem = pOffset ? hdcPaint : CreateCompatibleDC(hdcPaint);
+ HFONT hOldFont = (HFONT)SelectObject(hdcMem, bct->hFont);
+ if ( !pOffset) {
+ hbmMem = ske_CreateDIB32(width, height);
+ hbmOld = (HBITMAP)SelectObject(hdcMem, hbmMem);
+ }
+ else OffsetRect(&rcClient,offset.x,offset.y);
+
+ if ( !g_CluiData.fDisableSkinEngine) {
+ char szRequest[128];
+ /* painting */
+ mir_snprintf(szRequest,SIZEOF(szRequest),"Button,ID=%s,Hovered=%s,Pressed=%s,Focused=%s",
+ bct->szButtonID, // ID
+ b2str(bct->stateId == PBS_HOT), // Hovered
+ b2str(bct->stateId == PBS_PRESSED || bct->bIsPushed == TRUE), // Pressed
+ b2str(bct->fFocused)); // Focused
+
+ SkinDrawGlyph(hdcMem,&rcClient,&rcClient,szRequest);
+ }
+ else if (xpt_IsThemed(bct->hThemeToolbar)) {
+ RECT *rc = &rcClient;
+ int state = IsWindowEnabled(bct->hwnd) ? /*(bct->stateId == PBS_PRESSED || bct->bIsPushed == TRUE) ? PBS_PRESSED :*/ (bct->stateId == PBS_NORMAL && bct->bIsDefault ? PBS_DEFAULTED : bct->stateId) : PBS_DISABLED;
+ xpt_DrawTheme(bct->hThemeToolbar,bct->hwnd,hdcMem,TP_BUTTON, TBStateConvert2Flat(state), rc, rc);
+ }
+ else {
+ HBRUSH hbr = NULL;
+
+ if (bct->stateId == PBS_PRESSED || bct->stateId == PBS_HOT)
+ hbr = GetSysColorBrush(COLOR_3DLIGHT);
+ else {
+ RECT btnRect;
+ POINT pt = {0};
+ int ret;
+ HWND hwndParent = GetParent(bct->hwnd);
+ HDC dc = CreateCompatibleDC(NULL);
+ HBITMAP memBM, oldBM;
+ GetWindowRect(hwndParent,&btnRect);
+ memBM = ske_CreateDIB32( btnRect.right-btnRect.left, btnRect.bottom-btnRect.top );
+ oldBM = (HBITMAP)SelectObject ( dc, memBM );
+ ret = SendMessage(hwndParent,WM_ERASEBKGND,(WPARAM)dc,0);
+ GetWindowRect(bct->hwnd,&btnRect);
+ ClientToScreen(hwndParent,&pt);
+ OffsetRect(&btnRect,-pt.x,-pt.y);
+ if (ret)
+ BitBlt(hdcMem,0,0,btnRect.right-btnRect.left,btnRect.bottom-btnRect.top,dc,btnRect.left,btnRect.top,SRCCOPY);
+ oldBM = (HBITMAP)SelectObject ( dc, oldBM );
+ DeleteObject(memBM);
+ DeleteDC(dc);
+ if ( !ret) { //WM_ERASEBKG return false need to paint
+ HDC pdc = GetDC(hwndParent);
+ HBRUSH oldBrush = (HBRUSH)GetCurrentObject( pdc, OBJ_BRUSH );
+ hbr = (HBRUSH)SendMessage(hwndParent, WM_CTLCOLORDLG, (WPARAM)pdc, (LPARAM)hwndParent);
+ SelectObject(pdc,oldBrush);
+ ReleaseDC(hwndParent,pdc);
+ }
+ }
+ if (hbr) {
+ FillRect(hdcMem, &rcClient, hbr);
+ DeleteObject(hbr);
+ }
+ if (bct->stateId == PBS_HOT || bct->fFocused) {
+ if (bct->bIsPushed)
+ DrawEdge(hdcMem,&rcClient, EDGE_ETCHED,BF_RECT|BF_SOFT);
+ else
+ DrawEdge(hdcMem,&rcClient, BDR_RAISEDOUTER,BF_RECT|BF_SOFT|BF_FLAT);
+ }
+ else if (bct->stateId == PBS_PRESSED)
+ DrawEdge(hdcMem, &rcClient, BDR_SUNKENOUTER,BF_RECT|BF_SOFT);
+ }
+
+ RECT rcTemp = rcClient; //content rect
+ BYTE bPressed = (bct->stateId == PBS_PRESSED || bct->bIsPushed == TRUE)?1:0;
+ HICON hHasIcon = bct->hIcon ? bct->hIcon : NULL;
+ BOOL fHasText = (bct->szText[0] != '\0');
+
+ /* formatter */
+ RECT rcIcon;
+ RECT rcText;
+
+ if ( !g_CluiData.fDisableSkinEngine) {
+ /* correct rect according to rcMargins */
+
+ rcTemp.left += bct->rcMargins.left;
+ rcTemp.top += bct->rcMargins.top;
+ rcTemp.bottom -= bct->rcMargins.bottom;
+ rcTemp.right -= bct->rcMargins.right;
+ }
+
+ rcIcon = rcTemp;
+ rcText = rcTemp;
+
+ /* reposition button items */
+ if (hHasIcon && fHasText ) {
+ rcIcon.right = rcIcon.left+16; /* CXSM_ICON */
+ rcText.left = rcIcon.right+2;
+ }
+ else if (hHasIcon) {
+ rcIcon.left += (rcIcon.right-rcIcon.left)/2-8;
+ rcIcon.right = rcIcon.left+16;
+ }
+
+ /* Check sizes*/
+ if (hHasIcon && (rcIcon.right>rcTemp.right || rcIcon.bottom>rcTemp.bottom || rcIcon.left < rcTemp.left || rcIcon.top < rcTemp.top))
+ hHasIcon = NULL;
+
+ if (fHasText && (rcText.right>rcTemp.right || rcText.bottom>rcTemp.bottom || rcText.left < rcTemp.left || rcText.top < rcTemp.top))
+ fHasText = FALSE;
+
+ if (hHasIcon) {
+ /* center icon vertically */
+ rcIcon.top += (rcClient.bottom-rcClient.top)/2 - 8; /* CYSM_ICON/2 */
+ rcIcon.bottom = rcIcon.top + 16; /* CYSM_ICON */
+ /* draw it */
+ ske_DrawIconEx(hdcMem, rcIcon.left+bPressed, rcIcon.top+bPressed, hHasIcon,
+ 16, 16, 0, NULL, DI_NORMAL);
+ }
+
+ if (fHasText) {
+ BOOL bCentered = TRUE;
+ SetBkMode(hdcMem,TRANSPARENT);
+ if (bct->nFontID >= 0)
+ g_clcPainter.ChangeToFont(hdcMem,NULL,bct->nFontID,NULL);
+
+ RECT TextRequiredRect = rcText;
+ ske_DrawText(hdcMem, bct->szText, -1, &TextRequiredRect, DT_CENTER | DT_VCENTER | DT_CALCRECT | DT_SINGLELINE);
+ if (TextRequiredRect.right-TextRequiredRect.left>rcText.right-rcText.left)
+ bCentered = FALSE;
+
+ ske_DrawText(hdcMem, bct->szText, -1, &rcText, (bCentered ? DT_CENTER: 0) | DT_VCENTER | DT_SINGLELINE);
+ ske_ResetTextEffect(hdcMem);
+ }
+ if ( !pOffset)
+ BitBlt(hdcPaint,0,0,width,height,hdcMem,0,0,SRCCOPY);
+
+ // better to use try/finally but looks like last one is Microsoft specific
+ SelectObject(hdcMem,hOldFont);
+ if ( !pOffset) {
+ SelectObject(hdcMem,hbmOld);
+ DeleteObject(hbmMem);
+ DeleteDC(hdcMem);
+ }
+}
+
+static LRESULT CALLBACK ToolbarButtonProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TBBUTTONDATA *bct = (TBBUTTONDATA *) GetWindowLongPtr(hwndDlg, 0);
+ switch (msg) {
+ case WM_DESTROY:
+ xpt_FreeThemeForWindow(hwndDlg);
+ WindowList_Remove(hButtonWindowList, hwndDlg);
+ break; // DONT! fall thru
+
+ case WM_SETTEXT:
+ lstrcpyn(bct->szText, (TCHAR *)lParam, SIZEOF(bct->szText)-1);
+ bct->szText[SIZEOF(bct->szText)-1] = '\0';
+ break;
+
+ case WM_SETFONT:
+ // remember the font so we can use it later
+ bct->hFont = (HFONT) wParam; // maybe we should redraw?
+ bct->nFontID = (int) lParam - 1;
+ break;
+
+ case BUTTONSETSENDONDOWN:
+ bct->fSendOnDown = (BOOL) lParam;
+ break;
+
+ case BUTTONSETMARGINS:
+ if (lParam) bct->rcMargins = *(RECT*)lParam;
+ else {
+ RECT nillRect = {0};
+ bct->rcMargins = nillRect;
+ }
+ break;
+
+ case BUTTONSETID:
+ bct->szButtonID = (char *)lParam;
+ break;
+
+ case BUTTONDRAWINPARENT:
+ if (IsWindowVisible(hwndDlg))
+ PaintWorker(bct, (HDC) wParam, (POINT*) lParam);
+ break;
+
+ case WM_NCPAINT:
+ case WM_PAINT:
+ if (g_CluiData.fDisableSkinEngine) {
+ PAINTSTRUCT ps;
+ HDC hdcPaint = BeginPaint(hwndDlg, &ps);
+ if (hdcPaint) {
+ PaintWorker(bct, hdcPaint, NULL);
+ EndPaint(hwndDlg, &ps);
+ }
+ }
+ ValidateRect(hwndDlg,NULL);
+ bct->lResult = 0;
+ return 1;
+
+ case WM_CAPTURECHANGED:
+ if ((HWND)lParam != bct->hwnd && bct->stateId != PBS_DISABLED) {
+ // don't change states if disabled
+ bct->stateId = PBS_NORMAL;
+ InvalidateParentRect(bct->hwnd, NULL, TRUE);
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ {
+ int xPos = (( int )( short ) LOWORD( lParam ));
+ int yPos = (( int )( short ) HIWORD( lParam ));
+ POINT ptMouse = { xPos, yPos };
+
+ RECT rcClient;
+ GetClientRect( bct->hwnd, &rcClient );
+ if ( !PtInRect( &rcClient, ptMouse )) {
+ bct->fHotMark = FALSE;
+ ReleaseCapture();
+ }
+ else {
+ if (bct->stateId != PBS_DISABLED && bct->stateId != PBS_PRESSED) {
+ bct->stateId = PBS_PRESSED;
+ bct->fHotMark = TRUE;
+ InvalidateParentRect(bct->hwnd, NULL, TRUE);
+ if (bct->fSendOnDown) {
+ SendMessage(GetParent(hwndDlg), WM_COMMAND, MAKELONG(GetDlgCtrlID(hwndDlg), BN_CLICKED), (LPARAM) hwndDlg);
+ bct->stateId = PBS_NORMAL;
+ InvalidateParentRect(bct->hwnd, NULL, TRUE);
+ }
+ }
+ SetCapture( bct->hwnd );
+ }
+ }
+ bct->lResult = 0;
+ return 1;
+
+ case WM_LBUTTONUP:
+ if ( GetCapture() == bct->hwnd ) {
+ POINT ptMouse = { LOWORD(lParam), HIWORD(lParam) };
+
+ RECT rcClient;
+ GetClientRect( bct->hwnd, &rcClient );
+
+ if ( !PtInRect( &rcClient, ptMouse )) {
+ bct->fHotMark = FALSE;
+ ReleaseCapture();
+ break;
+ }
+
+ if (bct->bIsPushBtn)
+ bct->bIsPushed = !bct->bIsPushed;
+
+ if (bct->stateId != PBS_DISABLED) {
+ // don't change states if disabled
+ bct->stateId = PBS_HOT;
+ InvalidateParentRect(bct->hwnd, NULL, TRUE);
+ }
+ if ( !bct->fSendOnDown)
+ SendMessage(GetParent(hwndDlg), WM_COMMAND, MAKELONG(GetDlgCtrlID(hwndDlg), BN_CLICKED), (LPARAM) hwndDlg);
+ }
+ bct->fHotMark = FALSE;
+ bct->lResult = 0;
+ return 1;
+
+ case WM_MOUSEMOVE:
+ {
+ RECT rc;
+ POINT pt;
+ BOOL bPressed = (wParam & MK_LBUTTON) != 0;
+ if ( bPressed && !bct->fHotMark )
+ break;
+ GetWindowRect(hwndDlg, &rc);
+ GetCursorPos(&pt);
+ BOOL inClient = PtInRect(&rc, pt);
+ if ( inClient ) {
+ SetCapture( bct->hwnd );
+ if ( bct->stateId == PBS_NORMAL ) {
+ bct->stateId = PBS_HOT;
+ InvalidateParentRect(bct->hwnd, NULL, TRUE);
+ }
+ }
+
+ if ( !inClient && bct->stateId == PBS_PRESSED ) {
+ bct->stateId = PBS_HOT;
+ InvalidateParentRect(bct->hwnd, NULL, TRUE);
+ }
+ else if ( inClient && bct->stateId == PBS_HOT && bPressed ) {
+ if ( bct->fHotMark ) {
+ bct->stateId = PBS_PRESSED;
+ InvalidateParentRect(bct->hwnd, NULL, TRUE);
+ }
+ }
+ else if ( !inClient && !bPressed) {
+ bct->fHotMark = FALSE;
+ ReleaseCapture();
+ }
+ }
+ bct->lResult = 0;
+ return 1;
+
+ case WM_NCHITTEST:
+ {
+ LRESULT lr = SendMessage(GetParent(hwndDlg), WM_NCHITTEST, wParam, lParam);
+ if (lr == HTLEFT || lr == HTRIGHT || lr == HTBOTTOM || lr == HTTOP || lr == HTTOPLEFT || lr == HTTOPRIGHT
+ || lr == HTBOTTOMLEFT || lr == HTBOTTOMRIGHT) {
+ bct->lResult = HTTRANSPARENT;
+ return 1;
+ }
+ }
+ break;
+
+ case BM_SETCHECK:
+ if ( !bct->bIsPushBtn) break;
+ if (wParam == BST_CHECKED)
+ bct->bIsPushed = 1;
+ else if (wParam == BST_UNCHECKED)
+ bct->bIsPushed = 0;
+ InvalidateRect(bct->hwnd, NULL, TRUE);
+ bct->lResult = 0;
+ return 1;
+
+ case WM_ERASEBKGND:
+ bct->lResult = 1;
+ return 1;
+
+ case MBM_SETICOLIBHANDLE:
+ bct->hIcolibHandle = (HANDLE)lParam;
+ bct->hIcon = (bct->hIcolibHandle) ? Skin_GetIconByHandle(bct->hIcolibHandle) : NULL;
+ return 1;
+
+ case MBM_REFRESHICOLIBICON:
+ if (bct->hIcolibHandle)
+ bct->hIcon = (HICON)CallService(MS_SKIN2_GETICONBYHANDLE, 0 , (LPARAM) bct->hIcolibHandle);
+ else
+ bct->hIcon = NULL;
+ InvalidateRect(hwndDlg,NULL,TRUE);
+ pcli->pfnInvalidateRect(GetParent(GetParent(hwndDlg)),NULL,TRUE);
+ return 1;
+
+ case MBM_UPDATETRANSPARENTFLAG:
+ {
+ LONG flag = GetWindowLongPtr(hwndDlg,GWL_EXSTYLE);
+ LONG oldFlag = flag;
+ if (lParam == 2)
+ lParam = (g_CluiData.fDisableSkinEngine)?0:1;
+ flag &= ~WS_EX_TRANSPARENT;
+ if (lParam) flag |= WS_EX_TRANSPARENT;
+ if (flag != oldFlag) {
+ SetWindowLongPtr(hwndDlg,GWL_EXSTYLE,flag);
+ RedrawWindow(hwndDlg,NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW);
+ }
+ }
+ return 1;
+ }
+ return 0;
+}
+
+void MakeButtonSkinned(HWND hWnd)
+{
+ MButtonCustomize Custom;
+ Custom.cbLen = sizeof(TBBUTTONDATA);
+ Custom.fnPainter = (pfnPainterFunc)PaintWorker;
+ Custom.fnWindowProc = ToolbarButtonProc;
+ SendMessage(hWnd, BUTTONSETCUSTOM, 0, (LPARAM)&Custom);
+
+ TBBUTTONDATA* p = (TBBUTTONDATA*)GetWindowLongPtr(hWnd, 0);
+ p->nFontID = -1;
+ p->hThemeButton = xpt_AddThemeHandle(p->hwnd, L"BUTTON");
+ p->hThemeToolbar = xpt_AddThemeHandle(p->hwnd, L"TOOLBAR");
+ WindowList_Add(hButtonWindowList, hWnd, NULL);
+}
+
+static void CustomizeButton(HANDLE ttbid, HWND hWnd, LPARAM lParam)
+{
+ if (ttbid == TTB_WINDOW_HANDLE) {
+ CustomizeToolbar(hWnd);
+ return;
+ }
+
+ MakeButtonSkinned(hWnd);
+
+ TBBUTTONDATA* p = (TBBUTTONDATA*)GetWindowLongPtr(hWnd, 0);
+ p->szButtonID, "Toolbar.MissingID";
+ p->ttbID = ttbid;
+ SendMessage(hWnd, MBM_UPDATETRANSPARENTFLAG, 0, 2);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+int Buttons_ModuleLoaded(WPARAM wParam, LPARAM lParam)
+{
+ TopToolbar_SetCustomProc(CustomizeButton, 0);
+ return 0;
+}
+
+int Buttons_OnSkinModeSettingsChanged(WPARAM wParam, LPARAM lParam)
+{
+ WindowList_BroadcastAsync(hButtonWindowList, MBM_UPDATETRANSPARENTFLAG,0,2);
+ return 0;
+}
+
+HRESULT ToolbarButtonLoadModule()
+{
+ HookEvent(ME_SYSTEM_MODULESLOADED, Buttons_ModuleLoaded);
+
+ hButtonWindowList = (HANDLE) CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0);
+ hIconChangedHook = HookEvent(ME_SKIN2_ICONSCHANGED,OnIconLibIconChanged);
+ hBkgChangedHook = HookEvent(ME_BACKGROUNDCONFIG_CHANGED,Buttons_OnSkinModeSettingsChanged);
+ return S_OK;
+}
diff --git a/plugins/Clist_modern/src/modern_toolbar.cpp b/plugins/Clist_modern/src/modern_toolbar.cpp
new file mode 100644
index 0000000000..92a46dcd46
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_toolbar.cpp
@@ -0,0 +1,357 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+
+Copyright 2007 Artem Shpynov
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_commonprototypes.h"
+#include "./m_api/m_skinbutton.h"
+#include <m_toptoolbar.h>
+#include "hdr/modern_sync.h"
+
+struct
+{
+ char *pszButtonID, *pszButtonName, *pszServiceName;
+ char *pszTooltipUp, *pszTooltipDn;
+ int icoDefIdx, defResource, defResource2;
+ BOOL bVisByDefault;
+ HANDLE hButton;
+}
+static BTNS[] =
+{
+ { "MainMenu", "Main Menu", "CList/ShowMainMenu", "Main menu", NULL, 100 , IDI_RESETVIEW, IDI_RESETVIEW, TRUE },
+ { "StatusMenu", "Status Menu", "CList/ShowStatusMenu", "Status menu", NULL, 105 , IDI_RESETVIEW, IDI_RESETVIEW, TRUE },
+ { "AccoMgr", "Accounts", MS_PROTO_SHOWACCMGR, "Accounts...", NULL, 282 , IDI_ACCMGR, IDI_ACCMGR, TRUE },
+ { "ShowHideOffline","Show/Hide offline contacts", MS_CLIST_TOGGLEHIDEOFFLINE, "Hide offline contacts", "Show offline contacts", 110, IDI_RESETVIEW, IDI_RESETVIEW, TRUE },
+ { "FindUser","Find User", "FindAdd/FindAddCommand", "Find User", NULL, 140 , IDI_RESETVIEW, IDI_RESETVIEW, TRUE },
+ { "Options","Options", "Options/OptionsCommand", "Options", NULL, 150 , IDI_RESETVIEW, IDI_RESETVIEW, TRUE },
+ { "UseGroups","Use/Disable groups", MS_CLIST_TOGGLEGROUPS, "Use groups", "Disable Groups", 160, IDI_RESETVIEW, IDI_RESETVIEW, FALSE },
+ { "EnableSounds","Enable/Disable sounds", MS_CLIST_TOGGLESOUNDS, "Enable sounds", "Disable Sounds", 170, IDI_RESETVIEW, IDI_RESETVIEW, FALSE },
+ { "Minimize","Minimize", "CList/ShowHide", "Minimize", NULL, 180 , IDI_RESETVIEW, IDI_RESETVIEW, FALSE }
+};
+
+static void SetButtonPressed(int i, int state)
+{
+ CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)BTNS[i].hButton, state ? TTBST_PUSHED : TTBST_RELEASED);
+}
+
+static int Modern_InitButtons(WPARAM, LPARAM)
+{
+ for (int i=0; i < SIZEOF(BTNS); i++) {
+ TTBButton tbb = { 0 };
+ tbb.cbSize = sizeof(tbb);
+
+ if (BTNS[i].pszButtonID) {
+ tbb.name = LPGEN(BTNS[i].pszButtonID);
+ tbb.pszService = BTNS[i].pszServiceName;
+ tbb.pszTooltipUp = LPGEN(BTNS[i].pszTooltipUp);
+ tbb.pszTooltipDn = LPGEN(BTNS[i].pszTooltipDn);
+
+ char buf[255];
+ mir_snprintf(buf,SIZEOF(buf),"%s%s%s", TTB_OPTDIR, BTNS[i].pszButtonID, "_dn");
+ tbb.hIconHandleUp = RegisterIcolibIconHandle( buf, "Toolbar", BTNS[i].pszTooltipUp, _T("icons\\toolbar_icons.dll"),-BTNS[i].icoDefIdx, g_hInst, BTNS[i].defResource );
+
+ if (BTNS[i].pszTooltipDn) {
+ tbb.dwFlags |= TTBBF_ASPUSHBUTTON;
+
+ mir_snprintf(buf,SIZEOF(buf),"%s%s%s", TTB_OPTDIR, BTNS[i].pszButtonID, "_up");
+ tbb.hIconHandleDn = RegisterIcolibIconHandle( buf, "Toolbar", BTNS[i].pszTooltipDn, _T("icons\\toolbar_icons.dll"),-(BTNS[i].icoDefIdx+1), g_hInst, BTNS[i].defResource2 );
+ }
+ else tbb.hIconHandleDn = NULL;
+ }
+ else tbb.dwFlags |= TTBBF_ISSEPARATOR;
+
+ tbb.dwFlags |= (BTNS[i].bVisByDefault ? TTBBF_VISIBLE :0 );
+ BTNS[i].hButton = TopToolbar_AddButton(&tbb);
+ }
+
+ SetButtonPressed(3, db_get_b(NULL, "CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT));
+ SetButtonPressed(6, db_get_b(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT));
+ SetButtonPressed(7, db_get_b(NULL, "Skin", "UseSound", SETTING_ENABLESOUNDS_DEFAULT));
+ return 1;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define MTBM_LAYEREDPAINT (WM_USER+20)
+
+struct ModernToolbarCtrl : public TTBCtrl
+{
+ XPTHANDLE mtbXPTheme;
+};
+
+struct MTB_BUTTONINFO
+{
+ HWND hWindow;
+};
+
+struct
+{
+ HBITMAP mtb_hBmpBackground;
+ COLORREF mtb_bkColour;
+ WORD mtb_backgroundBmpUse;
+ BOOL mtb_useWinColors;
+}
+static tbdat = { 0 };
+
+COLORREF sttGetColor(char * module, char * color, COLORREF defColor);
+
+static int ehhToolBarSettingsChanged(WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam;
+ if ((HANDLE)wParam != NULL)
+ return 0;
+
+ if (!mir_strcmp(cws->szModule,"CList")) {
+ if (!mir_strcmp(cws->szSetting,"HideOffline"))
+ SetButtonPressed(3, cws->value.bVal);
+ else if (!mir_strcmp(cws->szSetting,"UseGroups"))
+ SetButtonPressed(6, cws->value.bVal);
+ }
+ else if (!mir_strcmp(cws->szModule,"Skin")) {
+ if (!mir_strcmp(cws->szSetting,"UseSound"))
+ SetButtonPressed(7, cws->value.bVal);
+ }
+
+ return 0;
+}
+
+static int ehhToolBarBackgroundSettingsChanged(WPARAM wParam, LPARAM lParam)
+{
+ if ( tbdat.mtb_hBmpBackground) {
+ DeleteObject(tbdat.mtb_hBmpBackground);
+ tbdat.mtb_hBmpBackground = NULL;
+ }
+ if (g_CluiData.fDisableSkinEngine) {
+ DBVARIANT dbv;
+ tbdat.mtb_bkColour = sttGetColor("ToolBar","BkColour",CLCDEFAULT_BKCOLOUR);
+ if ( db_get_b(NULL,"ToolBar","UseBitmap",CLCDEFAULT_USEBITMAP)) {
+ if ( !db_get_s(NULL, "ToolBar", "BkBitmap", &dbv, DBVT_TCHAR)) {
+ tbdat.mtb_hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.ptszVal);
+ db_free(&dbv);
+ }
+ }
+ tbdat.mtb_useWinColors = db_get_b(NULL, "ToolBar", "UseWinColours", CLCDEFAULT_USEWINDOWSCOLOURS);
+ tbdat.mtb_backgroundBmpUse = db_get_b(NULL, "ToolBar", "BkBmpUse", CLCDEFAULT_BKBMPUSE);
+ }
+ PostMessage(pcli->hwndContactList,WM_SIZE,0,0);
+ return 0;
+}
+
+static BOOL sttDrawToolBarBackground(HWND hwnd, HDC hdc, RECT * rect, ModernToolbarCtrl* pMTBInfo)
+{
+ BOOL bFloat = (GetParent(hwnd)!=pcli->hwndContactList);
+ if (g_CluiData.fDisableSkinEngine || !g_CluiData.fLayered || bFloat) {
+ HBRUSH hbr;
+
+ RECT rc;
+ if (rect)
+ rc=*rect;
+ else
+ GetClientRect(hwnd,&rc);
+
+ if ( !(tbdat.mtb_backgroundBmpUse && tbdat.mtb_hBmpBackground) && tbdat.mtb_useWinColors) {
+ if (xpt_IsThemed(pMTBInfo->mtbXPTheme))
+ xpt_DrawTheme(pMTBInfo->mtbXPTheme, pMTBInfo->hWnd, hdc, 0, 0, &rc, &rc);
+ else {
+ hbr = GetSysColorBrush(COLOR_3DFACE);
+ FillRect(hdc, &rc, hbr);
+ }
+ }
+ else if (!tbdat.mtb_hBmpBackground && !tbdat.mtb_useWinColors) {
+ hbr = CreateSolidBrush(tbdat.mtb_bkColour);
+ FillRect(hdc, &rc, hbr);
+ DeleteObject(hbr);
+ }
+ else DrawBackGround(hwnd, hdc, tbdat.mtb_hBmpBackground, tbdat.mtb_bkColour, tbdat.mtb_backgroundBmpUse);
+ }
+ return TRUE;
+}
+
+static void sttDrawNonLayeredSkinedBar(HWND hwnd, HDC hdc)
+{
+ RECT rc = {0};
+ GetClientRect(hwnd, &rc);
+ rc.right++;
+ rc.bottom++;
+ HDC hdc2 = CreateCompatibleDC(hdc);
+ HBITMAP hbmp = ske_CreateDIB32(rc.right, rc.bottom);
+ HBITMAP hbmpo = (HBITMAP)SelectObject(hdc2, hbmp);
+ if (GetParent(hwnd) != pcli->hwndContactList) {
+ HBRUSH br = GetSysColorBrush(COLOR_3DFACE);
+ FillRect(hdc2, &rc, br);
+ }
+ else ske_BltBackImage(hwnd, hdc2, &rc);
+
+ SendMessage(hwnd, MTBM_LAYEREDPAINT, (WPARAM)hdc2, 0);
+ BitBlt(hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, hdc2, rc.left, rc.top, SRCCOPY);
+ SelectObject(hdc2, hbmpo);
+ DeleteObject(hbmp);
+ mod_DeleteDC(hdc2);
+
+ SelectObject(hdc, (HFONT)GetStockObject(DEFAULT_GUI_FONT));
+ ValidateRect(hwnd, NULL);
+}
+
+static LRESULT CALLBACK toolbarWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ ModernToolbarCtrl* pMTBInfo = (ModernToolbarCtrl*)GetWindowLongPtr(hwnd, 0);
+
+ switch( msg ) {
+ case WM_ERASEBKGND:
+ pMTBInfo->lResult = (g_CluiData.fDisableSkinEngine) ? sttDrawToolBarBackground(hwnd, (HDC)wParam, NULL, pMTBInfo) : 0;
+ return 1;
+
+ case WM_NCPAINT:
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ BOOL bFloat = (GetParent(hwnd) != pcli->hwndContactList);
+ if (g_CluiData.fDisableSkinEngine|| !g_CluiData.fLayered || bFloat ) {
+ BeginPaint(hwnd,&ps);
+ if ((!g_CluiData.fLayered || bFloat) && !g_CluiData.fDisableSkinEngine)
+ sttDrawNonLayeredSkinedBar(hwnd, ps.hdc);
+ else
+ sttDrawToolBarBackground(hwnd, ps.hdc, &ps.rcPaint, pMTBInfo);
+ EndPaint(hwnd,&ps);
+ }
+ }
+
+ pMTBInfo->lResult = DefWindowProc(hwnd, msg, wParam, lParam);
+ return 1;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR) lParam)->code == BUTTONNEEDREDRAW)
+ pcli->pfnInvalidateRect(hwnd, NULL, FALSE);
+ pMTBInfo->lResult = 0;
+ return 1;
+
+ case MTBM_LAYEREDPAINT:
+ {
+ RECT MyRect={0};
+ HDC hDC=(HDC)wParam;
+ GetWindowRect(hwnd,&MyRect);
+
+ RECT rcClient;
+ GetClientRect(hwnd, &rcClient);
+ SkinDrawGlyph(hDC, &rcClient, &rcClient, "Bar,ID=ToolBar,Part=Background");
+
+ for (int i=0; i < pMTBInfo->pButtonList->realCount; i++) {
+ RECT childRect;
+ POINT Offset;
+ TTBCtrlButton* mtbi = (TTBCtrlButton*)pMTBInfo->pButtonList->items[i];
+ GetWindowRect(mtbi->hWindow, &childRect);
+ Offset.x = childRect.left - MyRect.left;;
+ Offset.y = childRect.top - MyRect.top;
+ SendMessage(mtbi->hWindow, BUTTONDRAWINPARENT, (WPARAM)hDC, (LPARAM)&Offset);
+ }
+ }
+ pMTBInfo->lResult = 0;
+ return 1;
+
+ case WM_DESTROY:
+ xpt_FreeThemeForWindow(hwnd);
+
+ default:
+ return 0;
+ }
+
+ pMTBInfo->lResult = TRUE;
+ return 1;
+}
+
+static int ToolBar_LayeredPaintProc(HWND hWnd, HDC hDC, RECT *rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData)
+{
+ return SendMessage(hWnd, MTBM_LAYEREDPAINT,(WPARAM)hDC,0);
+}
+
+void CustomizeToolbar(HWND hwnd)
+{
+ TTBCtrlCustomize custData = { sizeof(ModernToolbarCtrl), toolbarWndProc };
+ SendMessage(hwnd, TTB_SETCUSTOM, 0, (LPARAM)&custData);
+
+ ModernToolbarCtrl* pMTBInfo = (ModernToolbarCtrl*)GetWindowLongPtr(hwnd, 0);
+
+ CLISTFrame Frame = { 0 };
+ Frame.cbSize = sizeof(Frame);
+ Frame.tname = _T("Toolbar");
+ Frame.hWnd = hwnd;
+ Frame.align = alTop;
+ Frame.Flags = F_VISIBLE | F_NOBORDER | F_LOCKED | F_TCHAR | F_NO_SUBCONTAINER;
+ Frame.height = 18;
+ pMTBInfo->hFrame = (HANDLE)CallService(MS_CLIST_FRAMES_ADDFRAME, (WPARAM)&Frame, 0);
+
+ CallService(MS_SKINENG_REGISTERPAINTSUB,(WPARAM)hwnd,(LPARAM)ToolBar_LayeredPaintProc);
+
+ pMTBInfo->mtbXPTheme = xpt_AddThemeHandle(hwnd, L"TOOLBAR");
+}
+
+static int Toolbar_ModulesLoaded(WPARAM, LPARAM)
+{
+ CallService(MS_BACKGROUNDCONFIG_REGISTER, (WPARAM)"ToolBar Background/ToolBar",0);
+ HookEvent(ME_DB_CONTACT_SETTINGCHANGED, ehhToolBarSettingsChanged);
+ HookEvent(ME_BACKGROUNDCONFIG_CHANGED, ehhToolBarBackgroundSettingsChanged);
+ HookEvent(ME_TTB_INITBUTTONS, Modern_InitButtons);
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define TTB_OPTDIR "TopToolBar"
+
+#if defined(WIN64)
+ static char szUrl[] = "http://nightly.miranda.im/x64/toptoolbar.zip";
+#else
+ static char szUrl[] = "http://nightly.miranda.im/x32/toptoolbar.zip";
+#endif
+
+static TCHAR szWarning[] = LPGENT("To view a toolbar in Clist Modern you need the TopToolBar plugin. Click Yes to download it or Cancel to continue");
+
+static void CopySettings(const char* to, const char* from)
+{
+ db_set_b(NULL, TTB_OPTDIR, to, db_get_b(NULL,"ModernToolBar",from, 0));
+}
+
+HRESULT ToolbarLoadModule()
+{
+ BYTE bOldSetting = db_get_b(NULL, "CLUI", "ShowButtonBar", 255);
+ if (bOldSetting != 255) {
+ CopySettings("BUTTWIDTH", "option_Bar0_BtnWidth");
+ CopySettings("BUTTHEIGHT", "option_Bar0_BtnHeight");
+ CopySettings("BUTTGAP", "option_Bar0_BtnSpace");
+ CopySettings("BUTTAUTOSIZE", "option_Bar0_Autosize");
+ CopySettings("BUTTMULTI", "option_Bar0_Multiline");
+
+ db_unset(NULL, "CLUI", "ShowButtonBar");
+
+ CallService(MS_DB_MODULE_DELETE, 0, (LPARAM)"ModernToolBar");
+
+ if (bOldSetting == 1)
+ if (IDYES == MessageBox(NULL, TranslateTS(szWarning), TranslateT("Toolbar upgrade"), MB_ICONQUESTION | MB_YESNO))
+ CallService(MS_UTILS_OPENURL, 0, (LPARAM)szUrl);
+ }
+
+ ehhToolBarBackgroundSettingsChanged(0,0);
+ HookEvent(ME_SYSTEM_MODULESLOADED, Toolbar_ModulesLoaded);
+ return S_OK;
+}
diff --git a/plugins/Clist_modern/src/modern_viewmodebar.cpp b/plugins/Clist_modern/src/modern_viewmodebar.cpp
new file mode 100644
index 0000000000..ed156c8496
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_viewmodebar.cpp
@@ -0,0 +1,1574 @@
+/*
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2003 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+contact list view modes (CLVM)
+
+$Id: viewmodes.c 2998 2006-06-01 07:11:52Z nightwish2004 $
+
+*/
+
+#include "hdr/modern_commonheaders.h"
+#include "m_variables.h"
+#include "hdr/modern_cluiframes.h"
+#include "m_api/m_skinbutton.h"
+
+#define TIMERID_VIEWMODEEXPIRE 100
+
+void MakeButtonSkinned(HWND hWnd);
+
+typedef int (__cdecl *pfnEnumCallback)(char *szName);
+static HWND clvmHwnd = 0;
+static int clvm_curItem = 0;
+HMENU hViewModeMenu = 0;
+
+static HWND hwndSelector = 0;
+static HIMAGELIST himlViewModes = 0;
+static HANDLE hInfoItem = 0;
+static int nullImage;
+static DWORD stickyStatusMask = 0;
+static char g_szModename[2048];
+
+static int g_ViewModeOptDlg = FALSE;
+
+static UINT _page1Controls[] = {IDC_STATIC1, IDC_STATIC2, IDC_STATIC3, IDC_STATIC5, IDC_STATIC4,
+ IDC_STATIC8, IDC_ADDVIEWMODE, IDC_DELETEVIEWMODE, IDC_NEWVIEMODE, IDC_GROUPS, IDC_PROTOCOLS,
+ IDC_VIEWMODES, IDC_STATUSMODES, IDC_STATIC12, IDC_STATIC13, IDC_STATIC14, IDC_PROTOGROUPOP, IDC_GROUPSTATUSOP,
+ IDC_AUTOCLEAR, IDC_AUTOCLEARVAL, IDC_AUTOCLEARSPIN, IDC_STATIC15, IDC_STATIC16,
+ IDC_LASTMESSAGEOP, IDC_LASTMESSAGEUNIT, IDC_LASTMSG, IDC_LASTMSGVALUE, IDC_USEGROUPS, 0};
+
+static UINT _page2Controls[] = {IDC_CLIST, IDC_STATIC9, IDC_STATIC8, IDC_CLEARALL, IDC_CURVIEWMODE2, 0};
+
+void ApplyViewMode(const char *Name, bool onlySelector = false );
+static UINT _buttons[] = {IDC_RESETMODES, IDC_SELECTMODE, IDC_CONFIGUREMODES, 0};
+
+static BOOL sttDrawViewModeBackground(HWND hwnd, HDC hdc, RECT * rect);
+static void DeleteViewMode( char * szName );
+
+static int DrawViewModeBar(HWND hWnd, HDC hDC)
+{
+ RECT rc;
+ GetClientRect(hWnd, &rc);
+ SkinDrawGlyph(hDC,&rc,&rc,"ViewMode,ID=Background");
+ return 0;
+}
+
+static int ViewModePaintCallbackProc(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData)
+{
+ int i;
+ RECT MyRect = {0};
+ GetWindowRect(hWnd,&MyRect);
+ DrawViewModeBar(hWnd,hDC);
+ for (i=0; _buttons[i] != 0; i++)
+ {
+ RECT childRect;
+ POINT Offset;
+ GetWindowRect(GetDlgItem(hWnd, _buttons[i]),&childRect);
+ Offset.x = childRect.left-MyRect.left;
+ Offset.y = childRect.top-MyRect.top;
+ SendMessage(GetDlgItem(hWnd, _buttons[i]),BUTTONDRAWINPARENT,(WPARAM)hDC,(LPARAM)&Offset);
+
+ }
+ return 0;
+}
+
+/*
+ * enumerate all view modes, call the callback function with the mode name
+ * useful for filling lists, menus and so on..
+ */
+
+int CLVM_EnumProc(const char *szSetting, LPARAM lParam)
+{
+ pfnEnumCallback EnumCallback = (pfnEnumCallback)lParam;
+ if (szSetting != NULL)
+ EnumCallback((char *)szSetting);
+ return(0);
+}
+
+void CLVM_EnumModes(pfnEnumCallback EnumCallback)
+{
+ DBCONTACTENUMSETTINGS dbces;
+ dbces.pfnEnumProc = CLVM_EnumProc;
+ dbces.szModule = CLVM_MODULE;
+ dbces.ofsSettings = 0;
+ dbces.lParam = (LPARAM)EnumCallback;
+ CallService(MS_DB_CONTACT_ENUMSETTINGS,0,(LPARAM)&dbces);
+}
+
+int FillModes(char *szsetting)
+{
+ if (szsetting[0] == (char)246)
+ return 1;
+ if (szsetting[0] == (char)13)
+ return 1;
+
+ TCHAR * temp;
+ mir_utf8decode(szsetting,&temp);
+ if (temp) {
+ SendDlgItemMessage(clvmHwnd, IDC_VIEWMODES, LB_INSERTSTRING, -1, (LPARAM)temp);
+ mir_free(temp);
+ }
+
+ return 1;
+}
+
+static void ShowPage(HWND hwnd, int page)
+{
+ int i=0;
+ int pageChange = 0;
+
+ if (page == 0 && IsWindowVisible(GetDlgItem(hwnd, _page2Controls[0])))
+ pageChange = 1;
+
+ if (page == 1 && IsWindowVisible(GetDlgItem(hwnd, _page1Controls[0])))
+ pageChange = 1;
+
+ if (pageChange)
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+
+ switch(page) {
+ case 0:
+ while(_page1Controls[i] != 0)
+ ShowWindow(GetDlgItem(hwnd, _page1Controls[i++]), SW_SHOW);
+ i=0;
+ while(_page2Controls[i] != 0)
+ ShowWindow(GetDlgItem(hwnd, _page2Controls[i++]), SW_HIDE);
+ break;
+ case 1:
+ while(_page1Controls[i] != 0)
+ ShowWindow(GetDlgItem(hwnd, _page1Controls[i++]), SW_HIDE);
+ i=0;
+ while(_page2Controls[i] != 0)
+ ShowWindow(GetDlgItem(hwnd, _page2Controls[i++]), SW_SHOW);
+ break;
+ }
+ if (pageChange) {
+ SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
+ RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
+ }
+}
+
+static int UpdateClistItem(HANDLE hContact, DWORD mask)
+{
+ for (int i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++)
+ SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETEXTRAIMAGE, (WPARAM)hContact, MAKELONG(i - ID_STATUS_OFFLINE,
+ (1 << (i - ID_STATUS_OFFLINE)) & mask ? i - ID_STATUS_OFFLINE : nullImage));
+
+ return 0;
+}
+
+static DWORD GetMaskForItem(HANDLE hItem)
+{
+ DWORD dwMask = 0;
+
+ for (int i=0; i <= ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE; i++)
+ dwMask |= (SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_GETEXTRAIMAGE, (WPARAM)hItem, i) == nullImage ? 0 : 1 << i);
+
+ return dwMask;
+}
+
+static void UpdateStickies()
+{
+ DWORD localMask;
+ int i;
+ HANDLE hItem;
+
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while(hContact)
+ {
+ hItem = (HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM)hItem, (BYTE)db_get_dw(hContact, CLVM_MODULE, g_szModename, 0) ? 1 : 0);
+ localMask = HIWORD(db_get_dw(hContact, CLVM_MODULE, g_szModename, 0));
+ UpdateClistItem(hItem, (localMask == 0 || localMask == stickyStatusMask) ? stickyStatusMask : localMask);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+
+ for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++)
+ SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETEXTRAIMAGE, (WPARAM)hInfoItem, MAKELONG(i - ID_STATUS_OFFLINE, (1 << (i - ID_STATUS_OFFLINE)) & stickyStatusMask ? i - ID_STATUS_OFFLINE : ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE + 1));
+
+ hItem = (HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_GETNEXTITEM,CLGN_ROOT,0);
+ hItem = (HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST,CLM_GETNEXTITEM,CLGN_NEXTGROUP, (LPARAM)hItem);
+ while(hItem) {
+ for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++)
+ SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELONG(i - ID_STATUS_OFFLINE, nullImage));
+ hItem = (HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hItem);
+ }
+ ShowPage(clvmHwnd, 0);
+}
+
+static int FillDialog(HWND hwnd)
+{
+ LVCOLUMN lvc = {0};
+ HWND hwndList = GetDlgItem(hwnd, IDC_PROTOCOLS);
+ LVITEMA item = {0};
+ int protoCount = 0, i, newItem;
+ PROTOACCOUNT **accs;
+
+ CLVM_EnumModes(FillModes);
+ ListView_SetExtendedListViewStyle(GetDlgItem(hwnd, IDC_PROTOCOLS), LVS_EX_CHECKBOXES);
+ lvc.mask = LVCF_FMT;
+ lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT;
+ ListView_InsertColumn(GetDlgItem(hwnd, IDC_PROTOCOLS), 0, &lvc);
+
+ // fill protocols...
+ ProtoEnumAccounts( &protoCount, &accs );
+
+ item.mask = LVIF_TEXT;
+ item.iItem = 1000;
+ for (i=0; i < protoCount; i++)
+ {
+ item.pszText = accs[i]->szModuleName;
+ newItem = SendMessageA(hwndList, LVM_INSERTITEMA, 0, (LPARAM)&item);
+ }
+
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);
+ ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP);
+
+ // fill groups
+ {
+ LVITEM item = {0};
+ char buf[20];
+ DBVARIANT dbv = {0};
+
+ hwndList = GetDlgItem(hwnd, IDC_GROUPS);
+
+ ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES);
+ lvc.mask = LVCF_FMT;
+ lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT;
+ ListView_InsertColumn(hwndList, 0, &lvc);
+
+ item.mask = LVIF_TEXT;
+ item.iItem = 1000;
+
+ item.pszText = TranslateT("Ungrouped contacts");
+ newItem = SendMessage(hwndList, LVM_INSERTITEM, 0, (LPARAM)&item);
+
+ for (i=0;;i++)
+ {
+ mir_snprintf(buf, 20, "%d", i);
+ if (DBGetContactSettingTString(NULL, "CListGroups", buf, &dbv))
+ break;
+
+ item.pszText = &dbv.ptszVal[1];
+ newItem = SendMessage(hwndList, LVM_INSERTITEM, 0, (LPARAM)&item);
+ db_free(&dbv);
+ }
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);
+ ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP);
+ }
+ hwndList = GetDlgItem(hwnd, IDC_STATUSMODES);
+ ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES);
+ lvc.mask = LVCF_FMT;
+ lvc.fmt = LVCFMT_IMAGE | LVCFMT_LEFT;
+ ListView_InsertColumn(hwndList, 0, &lvc);
+ for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++)
+ {
+ LVITEM item = {0};
+ item.mask = LVIF_TEXT;
+ item.pszText = TranslateTS((TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)i, GSMDF_TCHAR_MY));
+ item.iItem = i - ID_STATUS_OFFLINE;
+ newItem = SendMessage(hwndList, LVM_INSERTITEM, 0, (LPARAM)&item);
+ }
+ ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE);
+ ListView_Arrange(hwndList, LVA_ALIGNLEFT | LVA_ALIGNTOP);
+
+ SendDlgItemMessage(hwnd, IDC_PROTOGROUPOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("And"));
+ SendDlgItemMessage(hwnd, IDC_PROTOGROUPOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Or"));
+ SendDlgItemMessage(hwnd, IDC_GROUPSTATUSOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("And"));
+ SendDlgItemMessage(hwnd, IDC_GROUPSTATUSOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Or"));
+
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Older than"));
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEOP, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Newer than"));
+
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Minutes"));
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Hours"));
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_INSERTSTRING, -1, (LPARAM)TranslateT("Days"));
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEOP, CB_SETCURSEL, 0, 0);
+ SendDlgItemMessage(hwnd, IDC_LASTMESSAGEUNIT, CB_SETCURSEL, 0, 0);
+ SetDlgItemInt(hwnd, IDC_LASTMSGVALUE, 0, 0);
+ return 0;
+}
+
+static void SetAllChildIcons(HWND hwndList,HANDLE hFirstItem,int iColumn,int iImage)
+{
+ int typeOfFirst,iOldIcon;
+ HANDLE hItem,hChildItem;
+
+ typeOfFirst = SendMessage(hwndList,CLM_GETITEMTYPE,(WPARAM)hFirstItem,0);
+ //check groups
+ if (typeOfFirst == CLCIT_GROUP) hItem = hFirstItem;
+ else hItem = (HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hFirstItem);
+ while(hItem)
+ {
+ hChildItem = (HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_CHILD,(LPARAM)hItem);
+ if (hChildItem)
+ SetAllChildIcons(hwndList,hChildItem,iColumn,iImage);
+ hItem = (HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hItem);
+ }
+ //check contacts
+ if (typeOfFirst == CLCIT_CONTACT) hItem = hFirstItem;
+ else hItem = (HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hFirstItem);
+ while(hItem) {
+ iOldIcon = SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn);
+ if (iOldIcon != 0xFF && iOldIcon != iImage) SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage));
+ hItem = (HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hItem);
+ }
+}
+
+static void SetIconsForColumn(HWND hwndList,HANDLE hItem,HANDLE hItemAll,int iColumn,int iImage)
+{
+ int itemType;
+
+ itemType = SendMessage(hwndList,CLM_GETITEMTYPE,(WPARAM)hItem,0);
+ if (itemType == CLCIT_CONTACT) {
+ int oldiImage = SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn);
+ if (oldiImage != 0xFF && oldiImage != iImage)
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage));
+ }
+ else if (itemType == CLCIT_INFO) {
+ int oldiImage = SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn);
+ if (oldiImage != 0xFF && oldiImage != iImage)
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage));
+ if (hItem == hItemAll)
+ SetAllChildIcons(hwndList,hItem,iColumn,iImage);
+ else
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage)); //hItemUnknown
+ }
+ else if (itemType == CLCIT_GROUP) {
+ int oldiImage = SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn);
+ if (oldiImage != 0xFF && oldiImage != iImage)
+ SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage));
+ hItem = (HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_CHILD,(LPARAM)hItem);
+ if (hItem)
+ SetAllChildIcons(hwndList,hItem,iColumn,iImage);
+ }
+}
+
+static int DeleteAutoModesCallback(char *szsetting)
+{
+ if ( szsetting[0] == (char)13 )
+ DeleteViewMode( szsetting );
+ return 1;
+}
+
+
+void SaveViewMode(const char *name, const TCHAR *szGroupFilter, const char *szProtoFilter, DWORD statusMask, DWORD stickyStatusMask, unsigned int options,
+ unsigned int stickies, unsigned int operators, unsigned int lmdat)
+{
+ CLVM_EnumModes( DeleteAutoModesCallback );
+
+ char szSetting[512];
+ mir_snprintf(szSetting, 512, "%c%s_PF", 246, name);
+ db_set_s(NULL, CLVM_MODULE, szSetting, szProtoFilter);
+ mir_snprintf(szSetting, 512, "%c%s_GF", 246, name);
+ db_set_ws(NULL, CLVM_MODULE, szSetting, szGroupFilter);
+ mir_snprintf(szSetting, 512, "%c%s_SM", 246, name);
+ db_set_dw(NULL, CLVM_MODULE, szSetting, statusMask);
+ mir_snprintf(szSetting, 512, "%c%s_SSM", 246, name);
+ db_set_dw(NULL, CLVM_MODULE, szSetting, stickyStatusMask);
+ mir_snprintf(szSetting, 512, "%c%s_OPT", 246, name);
+ db_set_dw(NULL, CLVM_MODULE, szSetting, options);
+ mir_snprintf(szSetting, 512, "%c%s_LM", 246, name);
+ db_set_dw(NULL, CLVM_MODULE, szSetting, lmdat);
+
+ db_set_dw(NULL, CLVM_MODULE, name, MAKELONG((unsigned short)operators, (unsigned short)stickies));
+}
+
+/*
+ * saves the state of the filter definitions for the current item
+ */
+
+void SaveState()
+{
+ TCHAR newGroupFilter[2048] = _T("|");
+ char newProtoFilter[2048] = "|";
+ int i, iLen;
+ HWND hwndList;
+ TCHAR *szTempModeName = NULL;
+ char *szModeName = NULL;
+ DWORD statusMask = 0;
+ HANDLE hContact, hItem;
+ DWORD operators = 0;
+
+ if (clvm_curItem == -1)
+ return;
+
+ {
+ LVITEMA item = {0};
+ char szTemp[256];
+
+ hwndList = GetDlgItem(clvmHwnd, IDC_PROTOCOLS);
+ for (i=0; i < ListView_GetItemCount(hwndList); i++) {
+ if (ListView_GetCheckState(hwndList, i)) {
+ item.mask = LVIF_TEXT;
+ item.pszText = szTemp;
+ item.cchTextMax = 255;
+ item.iItem = i;
+ SendMessageA(hwndList, LVM_GETITEMA, 0, (LPARAM)&item);
+ strncat(newProtoFilter, szTemp, 2048);
+ strncat(newProtoFilter, "|", 2048);
+ newProtoFilter[2047] = 0;
+ }
+ }
+ }
+
+ {
+ LVITEM item = {0};
+ TCHAR szTemp[256];
+
+ hwndList = GetDlgItem(clvmHwnd, IDC_GROUPS);
+
+ operators |= ListView_GetCheckState(hwndList, 0) ? CLVM_INCLUDED_UNGROUPED : 0;
+
+ for (i=0; i < ListView_GetItemCount(hwndList); i++) {
+ if (ListView_GetCheckState(hwndList, i)) {
+ item.mask = LVIF_TEXT;
+ item.pszText = szTemp;
+ item.cchTextMax = 255;
+ item.iItem = i;
+ SendMessage(hwndList, LVM_GETITEM, 0, (LPARAM)&item);
+ _tcsncat(newGroupFilter, szTemp, 2048);
+ _tcsncat(newGroupFilter, _T("|"), 2048);
+ newGroupFilter[2047] = 0;
+ }
+ }
+ }
+ hwndList = GetDlgItem(clvmHwnd, IDC_STATUSMODES);
+ for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ if (ListView_GetCheckState(hwndList, i - ID_STATUS_OFFLINE))
+ statusMask |= (1 << (i - ID_STATUS_OFFLINE));
+ }
+ iLen = SendMessage(GetDlgItem(clvmHwnd, IDC_VIEWMODES), LB_GETTEXTLEN, clvm_curItem, 0);
+ if (iLen) {
+ unsigned int stickies = 0;
+ DWORD dwGlobalMask, dwLocalMask;
+ BOOL translated;
+
+ szTempModeName = ( TCHAR* )mir_alloc((iLen + 1)*sizeof(TCHAR));
+ if (szTempModeName)
+ {
+ DWORD options, lmdat;
+ //char *vastring = NULL;
+ //int len = GetWindowTextLengthA(GetDlgItem(clvmHwnd, IDC_VARIABLES)) + 1;
+
+ //vastring = (char *)malloc(len);
+ //if (vastring)
+ //GetDlgItemTextA(clvmHwnd, IDC_VARIABLES, vastring, len);
+ SendDlgItemMessage(clvmHwnd, IDC_VIEWMODES, LB_GETTEXT, clvm_curItem, (LPARAM)szTempModeName);
+
+ {
+ szModeName = mir_utf8encodeT(szTempModeName);
+ }
+
+ dwGlobalMask = GetMaskForItem(hInfoItem);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while(hContact)
+ {
+ hItem = (HANDLE)SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ {
+ if (SendDlgItemMessage(clvmHwnd, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM)hItem, 0))
+ {
+ dwLocalMask = GetMaskForItem(hItem);
+ db_set_dw(hContact, CLVM_MODULE, szModeName, MAKELONG(1, (unsigned short)dwLocalMask));
+ stickies++;
+ }
+ else
+ {
+ if (db_get_dw(hContact, CLVM_MODULE, szModeName, 0))
+ db_set_dw(hContact, CLVM_MODULE, szModeName, 0);
+ }
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ operators |= ((SendDlgItemMessage(clvmHwnd, IDC_PROTOGROUPOP, CB_GETCURSEL, 0, 0) == 1 ? CLVM_PROTOGROUP_OP : 0) |
+ (SendDlgItemMessage(clvmHwnd, IDC_GROUPSTATUSOP, CB_GETCURSEL, 0, 0) == 1 ? CLVM_GROUPSTATUS_OP : 0) |
+ (IsDlgButtonChecked(clvmHwnd, IDC_AUTOCLEAR) ? CLVM_AUTOCLEAR : 0) |
+ (IsDlgButtonChecked(clvmHwnd, IDC_LASTMSG) ? CLVM_USELASTMSG : 0)|
+ (IsDlgButtonChecked(clvmHwnd, IDC_USEGROUPS) == BST_CHECKED ? CLVM_USEGROUPS : 0)|
+ (IsDlgButtonChecked(clvmHwnd, IDC_USEGROUPS) == BST_UNCHECKED ? CLVM_DONOTUSEGROUPS : 0)
+ );
+
+ options = SendDlgItemMessage(clvmHwnd, IDC_AUTOCLEARSPIN, UDM_GETPOS, 0, 0);
+
+ lmdat = MAKELONG(GetDlgItemInt(clvmHwnd, IDC_LASTMSGVALUE, &translated, FALSE),
+ MAKEWORD(SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEOP, CB_GETCURSEL, 0, 0),
+ SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEUNIT, CB_GETCURSEL, 0, 0)));
+
+ SaveViewMode(szModeName, newGroupFilter, newProtoFilter, statusMask, dwGlobalMask, options,
+ stickies, operators, lmdat);
+ //free(vastring);
+ if (szModeName && szModeName != (char*)szTempModeName)
+ mir_free(szModeName);
+ mir_free(szTempModeName);
+ szTempModeName = NULL;
+ szModeName = NULL;
+ }
+ }
+ EnableWindow(GetDlgItem(clvmHwnd, IDC_APPLY), FALSE);
+}
+
+/*
+ * updates the filter list boxes with the data taken from the filtering string
+ */
+
+static void UpdateFilters()
+{
+ DBVARIANT dbv_pf = {0};
+ DBVARIANT dbv_gf = {0};
+ char szSetting[128];
+ TCHAR *szTempBuf = NULL;
+ char *szBuf = NULL;
+ int iLen;
+ DWORD statusMask = 0, localMask = 0;
+ DWORD dwFlags;
+ DWORD opt;
+ TCHAR szTemp[100];
+
+ if (clvm_curItem == LB_ERR)
+ return;
+
+ iLen = SendDlgItemMessageA(clvmHwnd, IDC_VIEWMODES, LB_GETTEXTLEN, clvm_curItem, 0);
+
+ if ( iLen == 0 )
+ return;
+
+ szTempBuf = (TCHAR *)mir_alloc((iLen + 1)*sizeof(TCHAR));
+ SendDlgItemMessage(clvmHwnd, IDC_VIEWMODES, LB_GETTEXT, clvm_curItem, (LPARAM)szTempBuf);
+
+ szBuf = mir_utf8encodeT(szTempBuf);
+ strncpy(g_szModename, szBuf, SIZEOF(g_szModename));
+ g_szModename[SIZEOF(g_szModename) - 1] = 0;
+ mir_sntprintf(szTemp, 100, TranslateT("Configuring view mode: %s"), szTempBuf);
+ SetDlgItemText(clvmHwnd, IDC_CURVIEWMODE2, szTemp);
+ mir_snprintf(szSetting, 128, "%c%s_PF", 246, szBuf);
+ if (DBGetContactSettingString(NULL, CLVM_MODULE, szSetting, &dbv_pf))
+ goto cleanup;
+ mir_snprintf(szSetting, 128, "%c%s_GF", 246, szBuf);
+ if (DBGetContactSettingTString(NULL, CLVM_MODULE, szSetting, &dbv_gf))
+ goto cleanup;
+ mir_snprintf(szSetting, 128, "%c%s_OPT", 246, szBuf);
+ if ((opt = db_get_dw(NULL, CLVM_MODULE, szSetting, -1)) != -1)
+ {
+ SendDlgItemMessage(clvmHwnd, IDC_AUTOCLEARSPIN, UDM_SETPOS, 0, MAKELONG(LOWORD(opt), 0));
+ }
+ mir_snprintf(szSetting, 128, "%c%s_SM", 246, szBuf);
+ statusMask = db_get_dw(NULL, CLVM_MODULE, szSetting, 0);
+ mir_snprintf(szSetting, 128, "%c%s_SSM", 246, szBuf);
+ stickyStatusMask = db_get_dw(NULL, CLVM_MODULE, szSetting, -1);
+ dwFlags = db_get_dw(NULL, CLVM_MODULE, szBuf, 0);
+ {
+ LVITEMA item = {0};
+ char szTemp[256];
+ char szMask[256];
+ int i;
+ HWND hwndList = GetDlgItem(clvmHwnd, IDC_PROTOCOLS);
+
+ item.mask = LVIF_TEXT;
+ item.pszText = szTemp;
+ item.cchTextMax = 255;
+
+ for (i=0; i < ListView_GetItemCount(hwndList); i++)
+ {
+ item.iItem = i;
+ SendMessageA(hwndList, LVM_GETITEMA, 0, (LPARAM)&item);
+ mir_snprintf(szMask, 256, "%s|", szTemp);
+ if (dbv_pf.pszVal && strstr(dbv_pf.pszVal, szMask))
+ ListView_SetCheckState(hwndList, i, TRUE)
+ else
+ ListView_SetCheckState(hwndList, i, FALSE);
+ }
+ }
+ {
+ LVITEM item = {0};
+ TCHAR szTemp[256];
+ TCHAR szMask[256];
+ int i;
+ HWND hwndList = GetDlgItem(clvmHwnd, IDC_GROUPS);
+
+ item.mask = LVIF_TEXT;
+ item.pszText = szTemp;
+ item.cchTextMax = 255;
+
+ ListView_SetCheckState(hwndList, 0, dwFlags & CLVM_INCLUDED_UNGROUPED ? TRUE : FALSE);
+
+ for (i = 1; i < ListView_GetItemCount(hwndList); i++)
+ {
+ item.iItem = i;
+ SendMessage(hwndList, LVM_GETITEM, 0, (LPARAM)&item);
+ _sntprintf(szMask, 256, _T("%s|"), szTemp);
+ if (dbv_gf.ptszVal && _tcsstr(dbv_gf.ptszVal, szMask))
+ ListView_SetCheckState(hwndList, i, TRUE)
+ else
+ ListView_SetCheckState(hwndList, i, FALSE);
+ }
+ }
+ {
+ HWND hwndList = GetDlgItem(clvmHwnd, IDC_STATUSMODES);
+
+ for (int i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ if ((1 << (i - ID_STATUS_OFFLINE)) & statusMask)
+ ListView_SetCheckState(hwndList, i - ID_STATUS_OFFLINE, TRUE)
+ else
+ ListView_SetCheckState(hwndList, i - ID_STATUS_OFFLINE, FALSE);
+ }
+ }
+ SendDlgItemMessage(clvmHwnd, IDC_PROTOGROUPOP, CB_SETCURSEL, dwFlags & CLVM_PROTOGROUP_OP ? 1 : 0, 0);
+ SendDlgItemMessage(clvmHwnd, IDC_GROUPSTATUSOP, CB_SETCURSEL, dwFlags & CLVM_GROUPSTATUS_OP ? 1 : 0, 0);
+ CheckDlgButton(clvmHwnd, IDC_AUTOCLEAR, dwFlags & CLVM_AUTOCLEAR ? 1 : 0);
+ UpdateStickies();
+
+ {
+ int useLastMsg = dwFlags & CLVM_USELASTMSG;
+
+ int useGroupsState = (dwFlags & CLVM_USEGROUPS) ? BST_CHECKED : (dwFlags & CLVM_DONOTUSEGROUPS) ? BST_UNCHECKED : BST_INDETERMINATE ;
+
+ DWORD lmdat;
+ BYTE bTmp;
+
+ CheckDlgButton(clvmHwnd, IDC_LASTMSG, useLastMsg);
+ CheckDlgButton(clvmHwnd, IDC_USEGROUPS, useGroupsState);
+
+ EnableWindow(GetDlgItem(clvmHwnd, IDC_LASTMESSAGEOP), useLastMsg);
+ EnableWindow(GetDlgItem(clvmHwnd, IDC_LASTMSGVALUE), useLastMsg);
+ EnableWindow(GetDlgItem(clvmHwnd, IDC_LASTMESSAGEUNIT), useLastMsg);
+
+ mir_snprintf(szSetting, 128, "%c%s_LM", 246, szBuf);
+ lmdat = db_get_dw(NULL, CLVM_MODULE, szSetting, 0);
+
+ SetDlgItemInt(clvmHwnd, IDC_LASTMSGVALUE, LOWORD(lmdat), FALSE);
+ bTmp = LOBYTE(HIWORD(lmdat));
+ SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEOP, CB_SETCURSEL, bTmp, 0);
+ bTmp = HIBYTE(HIWORD(lmdat));
+ SendDlgItemMessage(clvmHwnd, IDC_LASTMESSAGEUNIT, CB_SETCURSEL, bTmp, 0);
+ }
+
+ ShowPage(clvmHwnd, 0);
+cleanup:
+ db_free(&dbv_pf);
+ db_free(&dbv_gf);
+ mir_free(szBuf);
+ mir_free(szTempBuf);
+}
+
+void DeleteViewMode( char * szName )
+{
+ char szSetting[256];
+
+ mir_snprintf(szSetting, 256, "%c%s_PF", 246, szName);
+ db_unset(NULL, CLVM_MODULE, szSetting);
+ mir_snprintf(szSetting, 256, "%c%s_GF", 246, szName);
+ db_unset(NULL, CLVM_MODULE, szSetting);
+ mir_snprintf(szSetting, 256, "%c%s_SM", 246, szName);
+ db_unset(NULL, CLVM_MODULE, szSetting);
+ mir_snprintf(szSetting, 256, "%c%s_VA", 246, szName);
+ db_unset(NULL, CLVM_MODULE, szSetting);
+ mir_snprintf(szSetting, 256, "%c%s_SSM", 246, szName);
+ db_unset(NULL, CLVM_MODULE, szSetting);
+ db_unset(NULL, CLVM_MODULE, szName);
+
+ if ( !strcmp(g_CluiData.current_viewmode, szName) && lstrlenA(szName) == lstrlenA(g_CluiData.current_viewmode)) {
+ g_CluiData.bFilterEffective = 0;
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ SetWindowText(hwndSelector, TranslateT("All contacts"));
+ }
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while(hContact)
+ {
+ if (db_get_dw(hContact, CLVM_MODULE, szName, -1) != -1)
+ db_set_dw(hContact, CLVM_MODULE, szName, 0);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+}
+
+#define IDI_SMALLDOT 211 //from miranda.exe
+INT_PTR CALLBACK DlgProcViewModesSetup(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ clvmHwnd = hwndDlg;
+
+ switch(msg) {
+ case WM_INITDIALOG:
+ {
+ int i=0;
+ TCITEM tci;
+ RECT rcClient;
+ CLCINFOITEM cii = {0};
+ HICON hIcon;
+
+ xpt_EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB);
+
+ himlViewModes = ImageList_Create(16, 16, ILC_MASK | (IsWinVerXPPlus() ? ILC_COLOR32 : ILC_COLOR16), 12, 0);
+ for (i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ hIcon = LoadSkinnedProtoIcon(NULL, i);
+ ImageList_AddIcon(himlViewModes, hIcon);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ }
+
+ hIcon = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_SMALLDOT), IMAGE_ICON, 16, 16, 0);
+ nullImage = ImageList_AddIcon(himlViewModes, hIcon);
+ DestroyIcon(hIcon);
+ GetClientRect(hwndDlg, &rcClient);
+
+ tci.mask = TCIF_PARAM|TCIF_TEXT;
+ tci.lParam = 0;
+ tci.pszText = TranslateT("Sticky contacts");
+ SendMessage(GetDlgItem(hwndDlg, IDC_TAB), TCM_INSERTITEM, (WPARAM)0, (LPARAM)&tci);
+
+ tci.pszText = TranslateT("Filtering");
+ SendMessage(GetDlgItem(hwndDlg, IDC_TAB), TCM_INSERTITEM, (WPARAM)0, (LPARAM)&tci);
+
+ TabCtrl_SetCurSel(GetDlgItem(hwndDlg, IDC_TAB), 0);
+
+ TranslateDialogDefault(hwndDlg);
+ FillDialog(hwndDlg);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADDVIEWMODE), FALSE);
+ {
+ LONG style = GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CLIST),GWL_STYLE);
+ style &= (~CLS_SHOWHIDDEN);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CLIST),GWL_STYLE,style);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETEXTRAIMAGELIST, 0, (LPARAM)himlViewModes);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETEXTRACOLUMNS, ID_STATUS_OUTTOLUNCH - ID_STATUS_OFFLINE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETBKBITMAP,0,(LPARAM)(HBITMAP)NULL);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETBKCOLOR,GetSysColor(COLOR_WINDOW),0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETGREYOUTFLAGS,0,0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETLEFTMARGIN,2,0);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETINDENT,10,0);
+ for (i=0;i <= FONTID_MAX;i++)
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETTEXTCOLOR,i,GetSysColor(COLOR_WINDOWTEXT));
+ cii.cbSize = sizeof(cii);
+ cii.hParentGroup = 0;
+ cii.pszText = TranslateT("*** All contacts ***");
+ hInfoItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_ADDINFOITEM, 0, (LPARAM)&cii);
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETHIDEEMPTYGROUPS, 1, 0);
+
+ int index = 0;
+
+ if ( g_CluiData.current_viewmode[0] != '\0' )
+ {
+ TCHAR * temp = mir_utf8decodeW( g_CluiData.current_viewmode );
+
+ if (temp) {
+ index = SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_FINDSTRING, -1, (LPARAM)temp );
+ mir_free(temp);
+ }
+ if ( index == -1 )
+ index = 0;
+ }
+
+ if (SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_SETCURSEL, index, 0) != LB_ERR)
+ {
+ clvm_curItem = index;
+ UpdateFilters();
+ }
+ else
+ clvm_curItem = -1;
+ g_ViewModeOptDlg = TRUE;
+ i=0;
+ while(_page2Controls[i] != 0)
+ ShowWindow(GetDlgItem(hwndDlg, _page2Controls[i++]), SW_HIDE);
+ ShowWindow(hwndDlg, SW_SHOWNORMAL);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), FALSE);
+ //EnableWindow(GetDlgItem(hwndDlg, IDC_VARIABLES), FALSE);
+ //EnableWindow(GetDlgItem(hwndDlg, IDC_VARIABLES), ServiceExists(MS_VARS_FORMATSTRING));
+ SendDlgItemMessage(hwndDlg, IDC_AUTOCLEARSPIN, UDM_SETRANGE, 0, MAKELONG(1000, 0));
+ SetWindowText(hwndDlg, TranslateT("Configure view modes"));
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDC_PROTOGROUPOP:
+ case IDC_GROUPSTATUSOP:
+ case IDC_LASTMESSAGEUNIT:
+ case IDC_LASTMESSAGEOP:
+ if (HIWORD(wParam) == CBN_SELCHANGE)
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), TRUE);
+ break;
+ case IDC_USEGROUPS:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), TRUE);
+ break;
+ case IDC_AUTOCLEAR:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), TRUE);
+ break;
+ case IDC_LASTMSG:
+ {
+ int bUseLastMsg = IsDlgButtonChecked(hwndDlg, IDC_LASTMSG);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LASTMESSAGEOP), bUseLastMsg);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LASTMESSAGEUNIT), bUseLastMsg);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LASTMSGVALUE), bUseLastMsg);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), TRUE);
+ break;
+ }
+ case IDC_AUTOCLEARVAL:
+ case IDC_LASTMSGVALUE:
+ if (HIWORD(wParam) == EN_CHANGE && GetFocus() == (HWND)lParam)
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), TRUE);
+ break;
+ case IDC_DELETEVIEWMODE:
+ {
+ if (MessageBox(0, TranslateT("Really delete this view mode? This cannot be undone"), TranslateT("Delete a view mode"), MB_YESNO | MB_ICONQUESTION) == IDYES)
+ {
+
+ int iLen = SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETTEXTLEN, SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0), 0);
+ if (iLen)
+ {
+ //TODO: UNICODE
+ TCHAR *szTempBuf = ( TCHAR* )malloc((iLen + 1)*sizeof(TCHAR));
+ char *szBuf = NULL;
+ if (szTempBuf)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETTEXT, SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0), (LPARAM)szTempBuf);
+ szBuf = mir_utf8encodeT(szTempBuf);
+ DeleteViewMode( szBuf );
+
+ SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_DELETESTRING, SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0), 0);
+ if (SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_SETCURSEL, 0, 0) != LB_ERR)
+ {
+ clvm_curItem = 0;
+ UpdateFilters();
+ }
+ else
+ clvm_curItem = -1;
+
+ if (szBuf && szBuf != (char*)szTempBuf) mir_free(szBuf);
+ if (szTempBuf) free(szTempBuf);
+ szTempBuf = NULL;
+ szBuf = NULL;
+ }
+ }
+ }
+ break;
+ }
+ case IDC_ADDVIEWMODE:
+ {
+ TCHAR szBuf[256];
+ szBuf[0] = 0;
+ GetDlgItemText(hwndDlg, IDC_NEWVIEMODE, szBuf, 256);
+ szBuf[255] = 0;
+
+ if (lstrlen(szBuf) > 0)
+ {
+ char *szUTF8Buf = mir_utf8encodeT(szBuf);
+
+ if (db_get_dw(NULL, CLVM_MODULE, szUTF8Buf, -1) != -1)
+ MessageBox(0, TranslateT("A view mode with this name does alredy exist"), TranslateT("Duplicate name"), MB_OK);
+ else
+ {
+ int iNewItem = SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_INSERTSTRING, -1, (LPARAM)szBuf);
+ if (iNewItem != LB_ERR)
+ {
+ SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_SETCURSEL, (WPARAM)iNewItem, 0);
+ SaveViewMode(szUTF8Buf, _T(""), "", 0, -1, 0, 0, 0, 0);
+ clvm_curItem = iNewItem;
+ UpdateStickies();
+ SendDlgItemMessage(hwndDlg, IDC_PROTOGROUPOP, CB_SETCURSEL, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_GROUPSTATUSOP, CB_SETCURSEL, 0, 0);
+ }
+ }
+ SetDlgItemText(hwndDlg, IDC_NEWVIEMODE, _T(""));
+ mir_free(szUTF8Buf);
+ }
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADDVIEWMODE), FALSE);
+ UpdateFilters();
+ break;
+ }
+ case IDC_CLEARALL:
+ {
+ HANDLE hItem;
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+
+ while(hContact)
+ {
+ hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM)hContact, 0);
+ if (hItem)
+ SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM)hItem, 0);
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ }
+ case IDOK:
+ case IDC_APPLY:
+ SaveState();
+ if (g_CluiData.bFilterEffective)
+ ApplyViewMode(g_CluiData.current_viewmode);
+ if (LOWORD(wParam) == IDOK)
+ DestroyWindow(hwndDlg);
+ break;
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ if (LOWORD(wParam) == IDC_NEWVIEMODE && HIWORD(wParam) == EN_CHANGE)
+ EnableWindow(GetDlgItem(hwndDlg, IDC_ADDVIEWMODE), TRUE);
+ if (LOWORD(wParam) == IDC_VIEWMODES && HIWORD(wParam) == LBN_SELCHANGE)
+ {
+ SaveState();
+ clvm_curItem = SendDlgItemMessage(hwndDlg, IDC_VIEWMODES, LB_GETCURSEL, 0, 0);
+ UpdateFilters();
+ //EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), TRUE);
+ //SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ break;
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR) lParam)->idFrom) {
+ case IDC_GROUPS:
+ case IDC_STATUSMODES:
+ case IDC_PROTOCOLS:
+ case IDC_CLIST:
+ if (((LPNMHDR) lParam)->code == NM_CLICK || ((LPNMHDR) lParam)->code == CLN_CHECKCHANGED)
+ EnableWindow(GetDlgItem(hwndDlg, IDC_APPLY), TRUE);
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case CLN_NEWCONTACT:
+ case CLN_LISTREBUILT:
+ //SetAllContactIcons(GetDlgItem(hwndDlg,IDC_CLIST));
+ //fall through
+ /*
+ case CLN_CONTACTMOVED:
+ SetListGroupIcons(GetDlgItem(hwndDlg,IDC_LIST),(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETNEXTITEM,CLGN_ROOT,0),hItemAll,NULL);
+ break;
+ case CLN_OPTIONSCHANGED:
+ ResetListOptions(GetDlgItem(hwndDlg,IDC_LIST));
+ break;
+ case CLN_CHECKCHANGED:
+ {
+ HANDLE hItem;
+ NMCLISTCONTROL *nm = (NMCLISTCONTROL*)lParam;
+ int typeOfItem = SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETITEMTYPE,(WPARAM)nm->hItem, 0);
+ break;
+ }*/
+ case NM_CLICK:
+ {
+ HANDLE hItem;
+ NMCLISTCONTROL *nm = (NMCLISTCONTROL*)lParam;
+ DWORD hitFlags;
+ int iImage;
+
+ if (nm->iColumn == -1)
+ break;
+ hItem = (HANDLE)SendDlgItemMessage(hwndDlg,IDC_CLIST,CLM_HITTEST,(WPARAM)&hitFlags,MAKELPARAM(nm->pt.x,nm->pt.y));
+ if (hItem == NULL) break;
+
+ if ( !(hitFlags&CLCHT_ONITEMEXTRA))
+ break;
+ iImage = SendDlgItemMessage(hwndDlg,IDC_CLIST,CLM_GETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(nm->iColumn,0));
+ if (iImage == nullImage)
+ iImage = nm->iColumn;
+ else if (iImage != 0xFF)
+ iImage = nullImage;
+ SetIconsForColumn(GetDlgItem(hwndDlg,IDC_CLIST),hItem,hInfoItem,nm->iColumn,iImage);
+ //SetListGroupIcons(GetDlgItem(hwndDlg,IDC_CLIST),(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETNEXTITEM,CLGN_ROOT,0),hInfoItem,NULL);
+ break;
+ }
+ }
+ break;
+ case IDC_TAB:
+ if (((LPNMHDR) lParam)->code == TCN_SELCHANGE) {
+ int id = TabCtrl_GetCurSel(GetDlgItem(hwndDlg, IDC_TAB));
+ if (id == 0)
+ ShowPage(hwndDlg, 0);
+ else
+ ShowPage(hwndDlg, 1);
+ break;
+ }
+
+ }
+ break;
+ }
+ case WM_DESTROY:
+ ImageList_RemoveAll(himlViewModes);
+ ImageList_Destroy(himlViewModes);
+ g_ViewModeOptDlg = FALSE;
+ break;
+ }
+ return FALSE;
+}
+
+static int menuCounter = 0;
+
+static int FillMenuCallback(char *szSetting)
+{
+ if (szSetting[0] == (char)246)
+ return 1;
+ if (szSetting[0] == (char)13)
+ return 1;
+
+ TCHAR * temp;
+ mir_utf8decode(szSetting,&temp);
+ if (temp) {
+ AppendMenu(hViewModeMenu, MFT_STRING, menuCounter++, temp);
+ mir_free(temp);
+ }
+ return 1;
+}
+
+void BuildViewModeMenu()
+{
+ if (hViewModeMenu)
+ DestroyMenu(hViewModeMenu);
+
+ menuCounter = 100;
+ hViewModeMenu = CreatePopupMenu();
+
+ AppendMenu(hViewModeMenu, MFT_STRING, 10002, TranslateT("All Contacts"));
+
+ AppendMenu(hViewModeMenu, MF_SEPARATOR, 0, NULL);
+
+ CLVM_EnumModes(FillMenuCallback);
+
+ if (GetMenuItemCount(hViewModeMenu) > 2)
+ AppendMenu(hViewModeMenu, MF_SEPARATOR, 0, NULL);
+ AppendMenu(hViewModeMenu, MFT_STRING, 10001, TranslateT("Setup View Modes..."));
+}
+
+LRESULT CALLBACK ViewModeFrameWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_CREATE:
+ {
+ RECT rcMargins = {12,0,2,0};
+ hwndSelector = CreateWindow( MIRANDABUTTONCLASS, _T(""), BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP , 0, 0, 20, 20,
+ hwnd, (HMENU) IDC_SELECTMODE, g_hInst, NULL);
+ MakeButtonSkinned(hwndSelector);
+ SendMessage(hwndSelector, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Select a view mode"), BATF_TCHAR);
+ SendMessage(hwndSelector, BUTTONSETMARGINS,0 ,(LPARAM) &rcMargins);
+ SendMessage(hwndSelector, BUTTONSETID,0 ,(LPARAM) "ViewMode.Select" );
+ SendMessage(hwndSelector, WM_SETFONT,0 ,(LPARAM) FONTID_VIEMODES+1 );
+ SendMessage(hwndSelector, BUTTONSETASFLATBTN, TRUE, 0 );
+ SendMessage(hwndSelector, MBM_UPDATETRANSPARENTFLAG, 0, 2);
+ SendMessage(hwndSelector, BUTTONSETSENDONDOWN, 0 ,(LPARAM) 1 );
+
+ //SendMessage(hwndSelector, BM_SETASMENUACTION, 1, 0);
+ HWND hwndButton = CreateWindow( MIRANDABUTTONCLASS, _T(""), BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 0, 0, 20, 20,
+ hwnd, (HMENU) IDC_CONFIGUREMODES, g_hInst, NULL);
+ MakeButtonSkinned(hwndButton);
+ SendMessage(hwndButton, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Setup view modes"), BATF_TCHAR);
+ SendMessage(hwndButton, BUTTONSETID,0 ,(LPARAM) "ViewMode.Setup" );
+ SendMessage(hwndButton, BUTTONSETASFLATBTN, TRUE, 0 );
+ SendMessage(hwndButton, MBM_UPDATETRANSPARENTFLAG, 0, 2);
+
+ hwndButton = CreateWindow( MIRANDABUTTONCLASS, _T(""), BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 0, 0, 20, 20,
+ hwnd, (HMENU) IDC_RESETMODES, g_hInst, NULL);
+ MakeButtonSkinned(hwndButton);
+ SendMessage(hwndButton, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Clear view mode and return to default display"), BATF_TCHAR);
+ SendMessage(hwndButton, BUTTONSETID,0 ,(LPARAM) "ViewMode.Clear" );
+ SendMessage(hwnd, WM_USER + 100, 0, 0);
+ SendMessage(hwndButton, BUTTONSETASFLATBTN, TRUE, 0 );
+ SendMessage(hwndButton, MBM_UPDATETRANSPARENTFLAG, 0, 2);
+ return FALSE;
+ }
+ case WM_NCCALCSIZE:
+ return 18;// FrameNCCalcSize(hwnd, DefWindowProc, wParam, lParam, hasTitleBar);
+ case WM_SIZE:
+ {
+ RECT rcCLVMFrame;
+ HDWP PosBatch = BeginDeferWindowPos(3);
+ GetClientRect(hwnd, &rcCLVMFrame);
+ PosBatch = DeferWindowPos(PosBatch, GetDlgItem(hwnd, IDC_RESETMODES), 0,
+ rcCLVMFrame.right - 23, 1, 22, 18, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS);
+ PosBatch = DeferWindowPos(PosBatch, GetDlgItem(hwnd, IDC_CONFIGUREMODES), 0,
+ rcCLVMFrame.right - 45, 1, 22, 18, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS);
+ PosBatch = DeferWindowPos(PosBatch, GetDlgItem(hwnd, IDC_SELECTMODE), 0,
+ 1, 1, rcCLVMFrame.right - 46, 18, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS);
+ EndDeferWindowPos(PosBatch);
+ }
+ break;
+
+ case WM_USER + 100:
+ SendMessage(GetDlgItem(hwnd, IDC_RESETMODES), MBM_SETICOLIBHANDLE, 0,
+ (LPARAM) RegisterIcolibIconHandle("CLN_CLVM_reset", "Contact List",Translate("Reset view mode"), _T("clisticons.dll"),9, g_hInst, IDI_RESETVIEW ));
+
+ SendMessage(GetDlgItem(hwnd, IDC_CONFIGUREMODES), MBM_SETICOLIBHANDLE, 0,
+ (LPARAM) RegisterIcolibIconHandle("CLN_CLVM_set", "Contact List",Translate("Setup view modes"), _T("clisticons.dll"), 10, g_hInst, IDI_SETVIEW ));
+
+ {
+ int bSkinned = db_get_b(NULL, "CLCExt", "bskinned", 0);
+ int i=0;
+
+ while(_buttons[i] != 0) {
+ //SendMessage(GetDlgItem(hwnd, _buttons[i]), BM_SETSKINNED, 0, bSkinned);
+ if (1 && bSkinned) {
+ SendDlgItemMessage(hwnd, _buttons[i], BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwnd, _buttons[i], BUTTONSETASFLATBTN + 10, 0, 0);
+ }
+ else {
+ SendDlgItemMessage(hwnd, _buttons[i], BUTTONSETASFLATBTN, TRUE, 1);
+ SendDlgItemMessage(hwnd, _buttons[i], BUTTONSETASFLATBTN + 10, 0, 1);
+ }
+ i++;
+ }
+ }
+
+ if (g_CluiData.bFilterEffective) {
+ TCHAR * temp;
+ //temp = alloca((strlen(szSetting)+1)*sizeof(TCHAR));
+ mir_utf8decode(g_CluiData.current_viewmode,&temp);
+ if (temp) {
+ SetWindowText(GetDlgItem(hwnd, IDC_SELECTMODE), temp );
+ mir_free(temp);
+ }
+ }
+ else SetWindowText(GetDlgItem(hwnd, IDC_SELECTMODE), TranslateT("All contacts"));
+ break;
+
+ case WM_ERASEBKGND:
+ if (g_CluiData.fDisableSkinEngine)
+ return sttDrawViewModeBackground(hwnd, (HDC)wParam, NULL);
+ else
+ return 0;
+
+ case WM_NCPAINT:
+ case WM_PAINT:
+ if (GetParent(hwnd) == pcli->hwndContactList && g_CluiData.fLayered)
+ ValidateRect(hwnd,NULL);
+
+ else if (GetParent(hwnd) != pcli->hwndContactList || !g_CluiData.fLayered) {
+ HDC hdc, hdc2;
+ HBITMAP hbmp,hbmpo;
+ RECT rc = {0};
+ GetClientRect(hwnd,&rc);
+ rc.right++;
+ rc.bottom++;
+ hdc = GetDC(hwnd);
+ hdc2 = CreateCompatibleDC(hdc);
+ hbmp = ske_CreateDIB32(rc.right,rc.bottom);
+ hbmpo = (HBITMAP)SelectObject(hdc2,hbmp);
+
+ if ( g_CluiData.fDisableSkinEngine )
+ sttDrawViewModeBackground( hwnd, hdc2, &rc );
+ else {
+ if (GetParent(hwnd) != pcli->hwndContactList) {
+ HBRUSH br = GetSysColorBrush(COLOR_3DFACE);
+ FillRect(hdc2,&rc,br);
+ }
+ else ske_BltBackImage(hwnd,hdc2,&rc);
+
+ DrawViewModeBar(hwnd,hdc2);
+ }
+
+ for (int i=0; _buttons[i] != 0; i++) {
+ RECT childRect;
+ RECT MyRect;
+ POINT Offset;
+ GetWindowRect(hwnd,&MyRect);
+ GetWindowRect(GetDlgItem(hwnd, _buttons[i]),&childRect);
+ Offset.x = childRect.left-MyRect.left;;
+ Offset.y = childRect.top-MyRect.top;
+ SendMessage(GetDlgItem(hwnd, _buttons[i]),BUTTONDRAWINPARENT,(WPARAM)hdc2,(LPARAM)&Offset);
+ }
+
+ BitBlt(hdc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,hdc2,rc.left,rc.top,SRCCOPY);
+ SelectObject(hdc2,hbmpo);
+ DeleteObject(hbmp);
+ mod_DeleteDC(hdc2);
+
+ SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
+
+ ReleaseDC(hwnd,hdc);
+ ValidateRect(hwnd,NULL);
+ }
+ return 0;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR) lParam)->code == BUTTONNEEDREDRAW)
+ pcli->pfnInvalidateRect(hwnd, NULL, FALSE);
+ return 0;
+
+ case WM_TIMER:
+ if (wParam == TIMERID_VIEWMODEEXPIRE) {
+ POINT pt;
+ RECT rcCLUI;
+
+ GetWindowRect(pcli->hwndContactList, &rcCLUI);
+ GetCursorPos(&pt);
+ if (PtInRect(&rcCLUI, pt))
+ break;
+
+ KillTimer(hwnd, wParam);
+ if ( !g_CluiData.old_viewmode[0])
+ SendMessage(hwnd, WM_COMMAND, IDC_RESETMODES, 0);
+ else
+ ApplyViewMode((const char *)g_CluiData.old_viewmode);
+ }
+ break;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case IDC_SELECTMODE:
+ {
+ RECT rc;
+ POINT pt;
+ int selection;
+ MENUITEMINFO mii = {0};
+ TCHAR szTemp[256];
+
+ BuildViewModeMenu();
+ GetWindowRect((HWND)lParam, &rc);
+ pt.x = rc.left;
+ pt.y = rc.bottom;
+ selection = TrackPopupMenu(hViewModeMenu,TPM_RETURNCMD|TPM_TOPALIGN|TPM_LEFTALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, GetParent(hwnd), NULL);
+ PostMessage(hwnd, WM_NULL, 0, 0);
+ if (selection)
+ {
+
+ if (selection == 10001)
+ goto clvm_config_command;
+ else if (selection == 10002)
+ goto clvm_reset_command;
+
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_STRING;
+ mii.dwTypeData = szTemp;
+ mii.cch = 256;
+ GetMenuItemInfo(hViewModeMenu, selection, FALSE, &mii);
+
+ char * temp = mir_utf8encodeT(szTemp);
+ ApplyViewMode(temp);
+ if (temp)
+ mir_free(temp);
+ }
+ break;
+ }
+ case IDC_RESETMODES:
+clvm_reset_command:
+ ApplyViewMode( "" );
+ break;
+
+ case IDC_CONFIGUREMODES:
+clvm_config_command:
+ if ( !g_ViewModeOptDlg)
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_OPT_VIEWMODES), 0, DlgProcViewModesSetup, 0);
+ break;
+ }
+
+ default:
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return TRUE;
+}
+
+static HWND hCLVMFrame;
+HWND g_hwndViewModeFrame;
+
+struct view_mode_t
+{
+ HBITMAP hBmpBackground;
+ COLORREF bkColour;
+ int useWinColors;
+ int backgroundBmpUse;
+
+ view_mode_t():
+ hBmpBackground( NULL),
+ bkColour( CLCDEFAULT_BKCOLOUR ),
+ useWinColors( CLCDEFAULT_USEWINDOWSCOLOURS ),
+ backgroundBmpUse( CLCDEFAULT_USEBITMAP )
+ {}
+};
+
+static view_mode_t view_mode;
+
+static BOOL sttDrawViewModeBackground(HWND hwnd, HDC hdc, RECT * rect)
+{
+ BOOL bFloat = (GetParent(hwnd) != pcli->hwndContactList);
+ if (g_CluiData.fDisableSkinEngine || !g_CluiData.fLayered || bFloat)
+ {
+ RECT rc;
+
+ if (rect) rc = *rect;
+ else GetClientRect(hwnd,&rc);
+
+ if ( !view_mode.hBmpBackground && !view_mode.useWinColors)
+ {
+ HBRUSH hbr = CreateSolidBrush(view_mode.bkColour);
+ FillRect(hdc, &rc, hbr);
+ DeleteObject(hbr);
+ }
+ else
+ {
+ DrawBackGround(hwnd,hdc,view_mode.hBmpBackground,view_mode.bkColour,view_mode.backgroundBmpUse);
+ }
+ }
+ return TRUE;
+}
+
+COLORREF sttGetColor(char * module, char * color, COLORREF defColor); //clcutils
+
+static int ehhViewModeBackgroundSettingsChanged(WPARAM wParam, LPARAM lParam)
+{
+ if (view_mode.hBmpBackground)
+ {
+ DeleteObject(view_mode.hBmpBackground);
+ view_mode.hBmpBackground = NULL;
+ }
+ if (g_CluiData.fDisableSkinEngine)
+ {
+ DBVARIANT dbv;
+ view_mode.bkColour = sttGetColor("ViewMode","BkColour",CLCDEFAULT_BKCOLOUR);
+ if (db_get_b(NULL,"ViewMode","UseBitmap",CLCDEFAULT_USEBITMAP)) {
+ if ( !DBGetContactSettingString(NULL,"ViewMode","BkBitmap",&dbv)) {
+ view_mode.hBmpBackground = (HBITMAP)CallService(MS_UTILS_LOADBITMAP,0,(LPARAM)dbv.pszVal);
+ db_free(&dbv);
+ }
+ }
+ view_mode.useWinColors = db_get_b(NULL, "ViewMode", "UseWinColours", CLCDEFAULT_USEWINDOWSCOLOURS);
+ view_mode.backgroundBmpUse = db_get_w(NULL, "ViewMode", "BkBmpUse", CLCDEFAULT_BKBMPUSE);
+ }
+ PostMessage(pcli->hwndContactList,WM_SIZE,0,0);
+ return 0;
+}
+
+void CreateViewModeFrame()
+{
+ CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"View Mode Background/ViewMode",0);
+ HookEvent(ME_BACKGROUNDCONFIG_CHANGED,ehhViewModeBackgroundSettingsChanged);
+ ehhViewModeBackgroundSettingsChanged(0,0);
+
+ CLISTFrame frame = {0};
+ WNDCLASS wndclass = {0};
+
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = ViewModeFrameWndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInst;
+ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wndclass.hbrBackground = (HBRUSH) GetSysColorBrush(COLOR_3DFACE);
+ wndclass.lpszMenuName = 0;
+ wndclass.lpszClassName = _T("CLVMFrameWindow");
+
+ RegisterClass(&wndclass);
+
+ ZeroMemory(&frame, sizeof(frame));
+ frame.cbSize = sizeof(frame);
+ frame.tname = _T("View modes");
+ frame.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);/*0;*/
+ frame.height = 18;
+ frame.TBtname = TranslateT("View Modes");
+ frame.Flags = F_VISIBLE|F_SHOWTBTIP|F_NOBORDER|F_NO_SUBCONTAINER|F_TCHAR;
+ frame.align = alBottom;
+ frame.hWnd = CreateWindowEx(0, _T("CLVMFrameWindow"), _T(CLVM_MODULE), WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_CLIPCHILDREN, 0, 0, 20, 20, pcli->hwndContactList, (HMENU) 0, g_hInst, NULL);
+ g_hwndViewModeFrame = frame.hWnd;
+ hCLVMFrame = (HWND)CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&frame,(LPARAM)0);
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)hCLVMFrame, FU_FMPOS);
+ CallService(MS_SKINENG_REGISTERPAINTSUB,(WPARAM)frame.hWnd,(LPARAM)ViewModePaintCallbackProc); //$$$$$ register sub for frame
+
+ ApplyViewMode(NULL); //Apply last selected view mode
+}
+
+const char *MakeVariablesString(const char *src, const char *UIN);
+
+void ApplyViewMode(const char *Name, bool onlySelector )
+{
+ char szSetting[256];
+ char * name = (char*)Name;
+ DBVARIANT dbv = {0};
+
+ BOOL wasNotViewMode = ( Name != NULL && g_CluiData.current_viewmode[0] == '\0' );
+
+ g_CluiData.bFilterEffective = 0;
+
+ mir_snprintf(szSetting, 256, "%c_LastMode", 246);
+
+ if ( !name) // Name is null - apply last stored view mode
+ {
+ if ( !DBGetContactSettingString(NULL, CLVM_MODULE, szSetting, &dbv))
+ {
+ name = (char*)_alloca(strlen(dbv.pszVal)+1);
+ strcpy(name,dbv.pszVal);
+ mir_free(dbv.pszVal);
+ }
+ else return;
+ }
+
+ if ( name[0] == '\0' )
+ {
+ // Reset View Mode
+ g_CluiData.bFilterEffective = 0;
+
+ { // remove last applied view mode
+ char szSetting[256];
+ mir_snprintf(szSetting, 256, "%c_LastMode", 246);
+ db_unset(NULL,CLVM_MODULE,szSetting);
+ }
+ if ( g_CluiData.bOldUseGroups != (BYTE) -1 )
+ CallService( MS_CLIST_SETUSEGROUPS, (WPARAM)g_CluiData.bOldUseGroups, 0 );
+
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ KillTimer(g_hwndViewModeFrame, TIMERID_VIEWMODEEXPIRE);
+ SetWindowText(GetDlgItem(g_hwndViewModeFrame, IDC_SELECTMODE), TranslateT("All contacts"));
+ if (g_CluiData.boldHideOffline != (BYTE)-1) CallService(MS_CLIST_SETHIDEOFFLINE, (WPARAM)g_CluiData.boldHideOffline, 0);
+ if (g_CluiData.bOldUseGroups != (BYTE)-1) CallService(MS_CLIST_SETUSEGROUPS, (WPARAM)g_CluiData.bOldUseGroups, 0);
+ g_CluiData.boldHideOffline = (BYTE)-1;
+ g_CluiData.bOldUseGroups = (BYTE) -1;
+ g_CluiData.current_viewmode[0] = 0;
+ g_CluiData.old_viewmode[0] = 0;
+ return;
+ }
+
+ if ( !onlySelector )
+ {
+ mir_snprintf(szSetting, 256, "%c%s_PF", 246, name);
+ if ( !DBGetContactSettingString(NULL, CLVM_MODULE, szSetting, &dbv)) {
+ if (lstrlenA(dbv.pszVal) >= 2)
+ {
+ strncpy(g_CluiData.protoFilter, dbv.pszVal, SIZEOF(g_CluiData.protoFilter));
+ g_CluiData.protoFilter[SIZEOF(g_CluiData.protoFilter) - 1] = 0;
+ g_CluiData.bFilterEffective |= CLVM_FILTER_PROTOS;
+ }
+ mir_free(dbv.pszVal);
+ }
+ mir_snprintf(szSetting, 256, "%c%s_GF", 246, name);
+ if ( !DBGetContactSettingTString(NULL, CLVM_MODULE, szSetting, &dbv))
+ {
+ if (lstrlen(dbv.ptszVal) >= 2)
+ {
+ _tcsncpy(g_CluiData.groupFilter, dbv.ptszVal, SIZEOF(g_CluiData.groupFilter));
+ g_CluiData.groupFilter[SIZEOF(g_CluiData.groupFilter) - 1] = 0;
+ g_CluiData.bFilterEffective |= CLVM_FILTER_GROUPS;
+ }
+ mir_free(dbv.ptszVal);
+ }
+ mir_snprintf(szSetting, 256, "%c%s_SM", 246, name);
+ g_CluiData.statusMaskFilter = db_get_dw(NULL, CLVM_MODULE, szSetting, -1);
+ if (g_CluiData.statusMaskFilter >= 1)
+ g_CluiData.bFilterEffective |= CLVM_FILTER_STATUS;
+
+ mir_snprintf(szSetting, 256, "%c%s_SSM", 246, name);
+ g_CluiData.stickyMaskFilter = db_get_dw(NULL, CLVM_MODULE, szSetting, -1);
+ if (g_CluiData.stickyMaskFilter != -1)
+ g_CluiData.bFilterEffective |= CLVM_FILTER_STICKYSTATUS;
+
+ g_CluiData.filterFlags = db_get_dw(NULL, CLVM_MODULE, name, 0);
+
+ KillTimer(g_hwndViewModeFrame, TIMERID_VIEWMODEEXPIRE);
+
+ if (g_CluiData.filterFlags & CLVM_AUTOCLEAR)
+ {
+ DWORD timerexpire;
+ mir_snprintf(szSetting, 256, "%c%s_OPT", 246, name);
+ timerexpire = LOWORD(db_get_dw(NULL, CLVM_MODULE, szSetting, 0));
+ strncpy(g_CluiData.old_viewmode, g_CluiData.current_viewmode, 256);
+ g_CluiData.old_viewmode[255] = 0;
+ CLUI_SafeSetTimer(g_hwndViewModeFrame, TIMERID_VIEWMODEEXPIRE, timerexpire * 1000, NULL);
+ }
+ else //store last selected view mode only if it is not autoclear
+ {
+ mir_snprintf(szSetting, 256, "%c_LastMode", 246);
+ db_set_s(NULL, CLVM_MODULE, szSetting, name);
+ }
+ strncpy(g_CluiData.current_viewmode, name, 256);
+ g_CluiData.current_viewmode[255] = 0;
+
+ if (g_CluiData.filterFlags & CLVM_USELASTMSG)
+ {
+ DWORD unit;
+ int i;
+ BYTE bSaved = g_CluiData.bSortByOrder[0];
+
+ g_CluiData.bSortByOrder[0] = SORTBY_LASTMSG;
+ for (i=0; i < clistCache->realCount; i++)
+ {
+ PDNCE pdnce = (PDNCE)clistCache->items[i];
+ pdnce->dwLastMsgTime = CompareContacts2_getLMTime(pdnce->hContact);
+ }
+ g_CluiData.bSortByOrder[0] = bSaved;
+
+ g_CluiData.bFilterEffective |= CLVM_FILTER_LASTMSG;
+ mir_snprintf(szSetting, 256, "%c%s_LM", 246, name);
+ g_CluiData.lastMsgFilter = db_get_dw(NULL, CLVM_MODULE, szSetting, 0);
+ if (LOBYTE(HIWORD(g_CluiData.lastMsgFilter)))
+ g_CluiData.bFilterEffective |= CLVM_FILTER_LASTMSG_NEWERTHAN;
+ else
+ g_CluiData.bFilterEffective |= CLVM_FILTER_LASTMSG_OLDERTHAN;
+ unit = LOWORD(g_CluiData.lastMsgFilter);
+ switch(HIBYTE(HIWORD(g_CluiData.lastMsgFilter))) {
+ case 0:
+ unit *= 60;
+ break;
+ case 1:
+ unit *= 3600;
+ break;
+ case 2:
+ unit *= 86400;
+ break;
+ }
+ g_CluiData.lastMsgFilter = unit;
+ }
+
+ if (HIWORD(g_CluiData.filterFlags) > 0)
+ g_CluiData.bFilterEffective |= CLVM_STICKY_CONTACTS;
+
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_STATUS)
+ {
+ if (g_CluiData.boldHideOffline == (BYTE)-1)
+ g_CluiData.boldHideOffline = db_get_b(NULL, "CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT);
+
+ CallService(MS_CLIST_SETHIDEOFFLINE, 0, 0);
+ }
+ else if ( g_CluiData.boldHideOffline != (BYTE)-1 )
+ {
+ CallService(MS_CLIST_SETHIDEOFFLINE, g_CluiData.boldHideOffline, 0);
+ g_CluiData.boldHideOffline = -1;
+ }
+
+ int bUseGroups = -1;
+
+ if (g_CluiData.filterFlags & CLVM_USEGROUPS)
+ bUseGroups = 1;
+ else if (g_CluiData.filterFlags & CLVM_DONOTUSEGROUPS)
+ bUseGroups = 0;
+
+ if (bUseGroups != -1)
+ {
+ if (g_CluiData.bOldUseGroups == (BYTE)-1)
+ g_CluiData.bOldUseGroups = db_get_b(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT);
+
+ CallService(MS_CLIST_SETUSEGROUPS, bUseGroups, 0);
+ }
+ else if (g_CluiData.bOldUseGroups != (BYTE)-1)
+ {
+ CallService(MS_CLIST_SETUSEGROUPS, g_CluiData.bOldUseGroups, 0);
+ g_CluiData.bOldUseGroups = -1;
+ }
+ }
+
+ TCHAR * temp = mir_utf8decodeW(( name[0] == (char)13 ) ? name + 1 : name );
+ SetWindowText(hwndSelector, temp);
+ mir_free(temp);
+
+ pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0);
+ CLUI__cliInvalidateRect(pcli->hwndStatus, NULL, FALSE);
+ //SetButtonStates(pcli->hwndContactList);
+}
+
+static int SkinSetViewMode(WPARAM wParam /*char * name*/, LPARAM lParam /*int index*/)
+{
+ if (wParam == 0 && lParam == 0)
+ {
+ ApplyViewMode( NULL );
+ }
+ else
+ {
+ if (wParam && !IsBadStringPtrA((const char*)wParam, -1))
+ ApplyViewMode((const char*)wParam);
+ }
+ return 0;
+}
diff --git a/plugins/Clist_modern/src/modern_xptheme.cpp b/plugins/Clist_modern/src/modern_xptheme.cpp
new file mode 100644
index 0000000000..0e1e9dddde
--- /dev/null
+++ b/plugins/Clist_modern/src/modern_xptheme.cpp
@@ -0,0 +1,265 @@
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_commonprototypes.h"
+#include "m_api/m_xpTheme.h"
+
+
+//statical
+
+typedef struct _tagXPTObject
+{
+ HANDLE hThemeHandle;
+ HWND hOwnerWindow;
+ LPCWSTR lpcwClassObject;
+} XPTObject;
+
+static SortedList * xptObjectList = NULL;
+static CRITICAL_SECTION xptCS;
+static BOOL xptModuleLoaded = FALSE;
+
+
+static HMODULE _xpt_ThemeAPIHandle = NULL; // handle to uxtheme.dll
+static HANDLE (WINAPI *_xpt_OpenThemeData)(HWND, LPCWSTR) = NULL;
+static HRESULT (WINAPI *_xpt_CloseThemeData)(HANDLE) = NULL;
+static BOOL (WINAPI *_xpt_IsThemeBackgroundPartiallyTransparent)(HANDLE, int,int) = NULL;
+static BOOL (WINAPI *_xpt_EnableThemeDialogTexture)(HANDLE, DWORD) = NULL;
+static HRESULT (WINAPI *_xpt_GetThemePartSize)(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, RECT *prc, int eSize, SIZE *psz ) = NULL;
+static HRESULT (WINAPI *_xpt_DrawThemeParentBackground)(HWND, HDC, const RECT *) = NULL;
+static HRESULT (WINAPI *_xpt_DrawThemeBackground)(HANDLE, HDC, int, int,const RECT *, const RECT *) = NULL;
+static HRESULT (WINAPI *_xpt_DrawThemeText)(HANDLE, HDC, int, int, LPCWSTR, int,DWORD, DWORD, const RECT *) = NULL;
+
+
+#undef MGPROC
+#define MGPROC(x) GetProcAddress(_xpt_ThemeAPIHandle,x)
+
+#define xptcheck if ( !xptModuleLoaded) return
+#define xptlock() EnterCriticalSection(&xptCS)
+#define xptunlock() LeaveCriticalSection(&xptCS)
+
+static void _sttXptObjectDestructor (void * pt)
+{
+ mir_free(pt);
+}
+
+static int _xpt_ThemeSupport()
+{
+ if (IsWinVerXPPlus()) {
+ if ( !_xpt_ThemeAPIHandle) {
+ _xpt_ThemeAPIHandle = GetModuleHandleA("uxtheme");
+ if (_xpt_ThemeAPIHandle) {
+ _xpt_OpenThemeData = (HANDLE(WINAPI *)(HWND, LPCWSTR))MGPROC("OpenThemeData");
+ _xpt_CloseThemeData = (HRESULT(WINAPI *)(HANDLE))MGPROC("CloseThemeData");
+ _xpt_IsThemeBackgroundPartiallyTransparent = (BOOL(WINAPI *)(HANDLE, int, int))MGPROC("IsThemeBackgroundPartiallyTransparent");
+ _xpt_DrawThemeParentBackground = (HRESULT(WINAPI *)(HWND, HDC, const RECT *))MGPROC("DrawThemeParentBackground");
+ _xpt_DrawThemeBackground = (HRESULT(WINAPI *)(HANDLE, HDC, int, int, const RECT *, const RECT *))MGPROC("DrawThemeBackground");
+ _xpt_DrawThemeText = (HRESULT(WINAPI *)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, DWORD, const RECT *))MGPROC("DrawThemeText");
+ _xpt_GetThemePartSize = (HRESULT(WINAPI *)(HTHEME , HDC , int , int , RECT *, int , SIZE * ))MGPROC("GetThemePartSize");
+ _xpt_EnableThemeDialogTexture = (BOOL (WINAPI *)(HANDLE, DWORD)) MGPROC("EnableThemeDialogTexture");
+ }
+ }
+ // Make sure all of these methods are valid (i would hope either all or none work)
+ if (_xpt_OpenThemeData &&
+ _xpt_CloseThemeData &&
+ _xpt_IsThemeBackgroundPartiallyTransparent &&
+ _xpt_DrawThemeParentBackground &&
+ _xpt_DrawThemeBackground &&
+ _xpt_DrawThemeText &&
+ _xpt_GetThemePartSize)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void _sttXptCloseThemeData(XPTObject * xptObject)
+{
+ _xpt_CloseThemeData(xptObject->hThemeHandle);
+ xptObject->hThemeHandle = NULL;
+}
+static void _sttXptReloadThemeData(XPTObject * xptObject)
+{
+ _xpt_CloseThemeData(xptObject->hThemeHandle);
+ xptObject->hThemeHandle = _xpt_OpenThemeData(xptObject->hOwnerWindow, xptObject->lpcwClassObject);
+}
+
+
+HRESULT XPThemesLoadModule()
+{
+ if (_xpt_ThemeSupport())
+ {
+ InitializeCriticalSection(&xptCS);
+ xptObjectList = List_Create(0,1);
+ xptModuleLoaded = TRUE;
+ }
+ return S_OK;
+}
+
+void XPThemesUnloadModule()
+{
+ xptcheck;
+ xptlock();
+ xptModuleLoaded = FALSE;
+ xptunlock();
+ li_ListDestruct(xptObjectList,_sttXptObjectDestructor);
+ DeleteCriticalSection(&xptCS);
+ FreeLibrary(_xpt_ThemeAPIHandle);
+}
+
+
+BOOL xpt_IsThemed(XPTHANDLE xptHandle)
+{
+ BOOL res = FALSE;
+ xptcheck FALSE;
+ if ( !xptHandle) return FALSE;
+ xptlock();
+ {
+ if (xpt_IsValidHandle(xptHandle) && ((XPTObject*) xptHandle)->hThemeHandle)
+ res = TRUE;
+ }
+ xptunlock();
+ return res;
+}
+
+BOOL xpt_IsValidHandle(XPTHANDLE xptHandle)
+{
+ BOOL res = FALSE;
+ xptcheck FALSE;
+ if ( !xptHandle) return FALSE;
+ xptlock();
+ {
+ if (List_IndexOf(xptObjectList, (void*)xptHandle) != -1)
+ res = TRUE;
+ }
+ xptunlock();
+ return res;
+}
+
+XPTHANDLE xpt_AddThemeHandle(HWND hwnd, LPCWSTR className)
+{
+ XPTHANDLE res = NULL;
+ xptcheck NULL;
+ xptlock();
+ {
+ XPTObject* xptObject = (XPTObject*)mir_calloc(sizeof(XPTObject));
+ xptObject->lpcwClassObject = className;
+ xptObject->hOwnerWindow = hwnd;
+ _sttXptReloadThemeData(xptObject);
+ List_InsertPtr(xptObjectList, (void*)xptObject);
+ res = (XPTHANDLE)xptObject;
+ }
+ xptunlock();
+ return res;
+}
+
+void xpt_FreeThemeHandle(XPTHANDLE xptHandle)
+{
+ xptcheck;
+ xptlock();
+ if (xpt_IsValidHandle(xptHandle))
+ {
+ XPTObject* xptObject = (XPTObject*)xptHandle;
+ _sttXptCloseThemeData(xptObject);
+ _sttXptObjectDestructor((void *) xptHandle);
+ List_Remove(xptObjectList, List_IndexOf(xptObjectList,(void *) xptHandle));
+ }
+ xptunlock();
+}
+void xpt_FreeThemeForWindow(HWND hwnd)
+{
+ xptcheck;
+ xptlock();
+ {
+ int i=0;
+ while (i < xptObjectList->realCount)
+ {
+ XPTObject* xptObject = (XPTObject*)xptObjectList->items[i];
+ if (xptObject->hOwnerWindow == hwnd)
+ {
+ _sttXptCloseThemeData(xptObject);
+ _sttXptObjectDestructor((void *) xptObject);
+ List_Remove(xptObjectList, i);
+ }
+ else
+ i++;
+ }
+ }
+ xptunlock();
+}
+
+void xpt_OnWM_THEMECHANGED()
+{
+ xptcheck;
+ xptlock();
+ {
+ int i;
+ for (i=0; i < xptObjectList->realCount; i++)
+ _sttXptReloadThemeData((XPTObject*)xptObjectList->items[i]);
+ }
+ xptunlock();
+}
+HRESULT xpt_DrawThemeBackground(XPTHANDLE xptHandle, HDC hdc, int type, int state, const RECT * sizeRect, const RECT * clipRect)
+{
+ HRESULT res = S_FALSE;
+ xptcheck S_FALSE;
+ xptlock();
+ if (xpt_IsThemed(xptHandle))
+ res = _xpt_DrawThemeBackground(((XPTObject*)xptHandle)->hThemeHandle, hdc, type, state, sizeRect, clipRect);
+ xptunlock();
+ return res;
+}
+HRESULT xpt_DrawThemeParentBackground(HWND hWnd, HDC hdc, const RECT * sizeRect)
+{
+ xptcheck S_FALSE;
+ return xpt_DrawThemeParentBackground(hWnd, hdc, sizeRect);
+}
+BOOL xpt_IsThemeBackgroundPartiallyTransparent(XPTHANDLE xptHandle, int type, int state)
+{
+ BOOL res = FALSE;
+ xptcheck FALSE;
+ xptlock();
+ if (xpt_IsThemed(xptHandle))
+ res = _xpt_IsThemeBackgroundPartiallyTransparent(((XPTObject*)xptHandle)->hThemeHandle, type, state);
+ xptunlock();
+ return res;
+}
+HRESULT xpt_DrawTheme(XPTHANDLE xptHandle, HWND hwnd, HDC hdc, int type, int state, const RECT *sizeRect, const RECT * clipRect)
+{
+ HRESULT res = S_FALSE;
+ xptcheck S_FALSE;
+ xptlock();
+ if (xpt_IsThemed(xptHandle))
+ {
+ if (_xpt_IsThemeBackgroundPartiallyTransparent(((XPTObject*)xptHandle)->hThemeHandle, type, state))
+ res = _xpt_DrawThemeParentBackground(hwnd,hdc,sizeRect);
+ res = _xpt_DrawThemeBackground(((XPTObject*)xptHandle)->hThemeHandle, hdc, type, state, sizeRect, clipRect);
+ }
+ xptunlock();
+ return res;
+}
+
+HRESULT xpt_DrawThemeText(XPTHANDLE xptHandle, HDC hdc, int type, int state, LPCTSTR lpStr, int len, DWORD flag1, DWORD flag2, const RECT * textRect)
+{
+ HRESULT res = S_FALSE;
+ xptcheck S_FALSE;
+ xptlock();
+ if (xpt_IsThemed(xptHandle))
+ _xpt_DrawThemeText(((XPTObject*)xptHandle)->hThemeHandle, hdc, type, state, (LPCWSTR)lpStr, len, flag1, flag2, textRect);
+ else
+ ske_DrawText(hdc,lpStr,len, (RECT*)textRect, flag1);
+ xptunlock();
+ return S_OK;
+}
+BOOL xpt_EnableThemeDialogTexture(HWND hwnd, DWORD flags)
+{
+ BOOL res = FALSE;
+ xptcheck res;
+ xptlock();
+ res = _xpt_EnableThemeDialogTexture(hwnd, flags);
+ xptunlock();
+ return res;
+}
+//usage outside
+// add theme data
+// in WM_DESTROY - release theme data
+// in paint xpt_DrawTheme
+
diff --git a/plugins/Clist_modern/src/resource.h b/plugins/Clist_modern/src/resource.h
new file mode 100644
index 0000000000..e9e7a01b5f
--- /dev/null
+++ b/plugins/Clist_modern/src/resource.h
@@ -0,0 +1,1053 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by resource.rc
+//
+#define IDC_ALWAYS_VISIBLEICON 0
+#define IDC_APPLY 3
+#define IDI_MIRANDA 102
+#define IDD_OPT_ITEM_CONTACT_TIME 102
+#define IDI_SMS 103
+#define IDD_OPT_ROWTMPL 103
+#define IDD_OPT_CLIST 126
+#define IDD_OPT_SOUND 134
+#define IDD_OPT_HOTKEYS 134
+#define IDD_OPT_CLIST_LISTBKG 135
+#define IDI_URL 138
+#define IDI_FINDUSER 161
+#define IDI_OPTIONS 163
+#define IDI_RENAME 173
+#define IDI_DELETE 175
+#define IDR_CONTEXT 180
+#define IDC_DROP 183
+#define IDI_SENDEMAIL 193
+#define IDR_CLISTMENU 199
+#define IDI_BLANK 200
+#define IDI_NOTICK 205
+#define IDI_TICK 206
+#define IDD_OPT_ICONS 207
+#define IDI_FILE 207
+#define IDI_TIMESTAMP 208
+#define IDI_CHANGEFONT 209
+#define IDI_ADDCONTACT 210
+#define IDI_SMALLDOT 211
+#define IDI_FILLEDBLOB 212
+#define IDD_READAWAYMSG 213
+#define IDI_EMPTYBLOB 213
+#define IDD_OPT_IGNORE 214
+#define IDC_DROPUSER 215
+#define IDD_OPT_VISIBILITY 215
+#define IDD_SETAWAYMSG 216
+#define IDI_DETAILSLOGO 216
+#define IDI_HIDE_AVATAR 217
+#define IDD_OPT_AWAYMSG 217
+#define IDI_SHOW_AVATAR 218
+#define IDD_OPT_CLUI 218
+#define IDD_INFO_SUMMARY 220
+#define IDD_INFO_CONTACT 221
+#define IDD_INFO_BACKGROUND 222
+#define IDD_INFO_NOTES 223
+#define IDD_ADDEMAIL 226
+#define IDD_ICONINDEX 227
+#define IDD_OPT_CLC 228
+#define IDD_OPT_CLCTEXT 229
+#define IDD_OPT_TRAY 229
+#define IDD_INFO_LOCATION 231
+#define IDD_INFO_WORK 232
+#define IDD_ADDPHONE 233
+#define IDD_OPT_SBAR 234
+#define IDD_INSTALLINI 235
+#define IDD_WARNINICHANGE 236
+#define IDD_INIIMPORTDONE 237
+#define IDB_SORTCOLUP 239
+#define IDB_SORTCOLDOWN 240
+#define IDD_OPT_NETLIB 246
+#define IDD_NETLIBLOGOPTS 247
+#define IDD_FILETRANSFERINFO 249
+#define IDD_OPT_FILETRANSFER 250
+#define IDD_FILEEXISTS 251
+#define IDD_OPT_SKIN 251
+#define IDD_DELETECONTACT 254
+#define IDD_DENYREASON 256
+#define IDD_ADDCONTACT 257
+#define IDD_OPT_CONTACT 261
+#define IDD_OPT_PROTOCOLORDER 262
+#define IDI_MULTISEND 263
+#define IDI_DOWNARROW 264
+#define IDD_CREDITS 265
+#define IDD_OPT_IDLE 268
+#define IDD_OPT_META_CLC 279
+#define IDI_ACCMGR 281
+#define IDI_NEWGROUP 282
+#define IDI_NEWGROUP2 283
+#define IDD_MODERNOPTS 288
+#define IDI_ICON1 290
+#define IDC_DEFAULTSUB 293
+#define IDC_DROPMETA 295
+#define IDC_CURSOR1 296
+#define IDC_REGROUP 296
+#define IDI_MIRANDA2 307
+#define IDI_CLIENTICQL5 315
+#define IDI_AVATAR_OVERLAY_NA 357
+#define IDI_AVATAR_OVERLAY_OCCUPIED 358
+#define IDI_AVATAR_OVERLAY_OFFLINE 359
+#define IDI_AVATAR_OVERLAY_ONLINE 360
+#define IDI_AVATAR_OVERLAY_PHONE 361
+#define IDI_ICON9 362
+#define IDI_AVATAR_OVERLAY_AWAY 362
+#define IDI_AVATAR_OVERLAY_DND 363
+#define IDI_AVATAR_OVERLAY_INVISIBLE 364
+#define IDI_AVATAR_OVERLAY_LUNCH 365
+#define IDI_ICON4 366
+#define IDI_AVATAR_OVERLAY_CHAT 366
+#define IDI_ICQC1 367
+#define IDI_ICQC2 368
+#define IDI_ICQC3 369
+#define IDI_ICQC4 370
+#define IDI_ICQC5 371
+#define IDI_ICQC6 372
+#define IDI_ICQC7 373
+#define IDI_ICQC8 374
+#define IDD_OPT_ITEMS 385
+#define IDD_OPT_ITEM_ROW 386
+#define IDD_OPT_ITEM_AVATAR 387
+#define IDD_OPT_ITEM_ICON 388
+#define IDD_OPT_ITEM_TEXT 389
+#define IDD_OPT_ITEM_SECOND_LINE 390
+#define IDD_OPT_ITEM_THIRD_LINE 391
+#define IDI_ICON2 396
+#define IDI_ICON3 397
+#define IDD_OPT_SKINEDITOR 398
+#define IDI_STATUS_OVERLAY_NA 400
+#define IDI_STATUS_OVERLAY_OCCUPIED 401
+#define IDI_STATUS_OVERLAY_OFFLINE 402
+#define IDI_STATUS_OVERLAY_ONLINE 403
+#define IDI_STATUS_OVERLAY_PHONE 404
+#define IDI_STATUS_OVERLAY_AWAY 405
+#define IDI_STATUS_OVERLAY_DND 406
+#define IDI_STATUS_OVERLAY_INVISIBLE 407
+#define IDI_STATUS_OVERLAY_LUNCH 408
+#define IDI_STATUS_OVERLAY_CHAT 409
+#define IDR_TGA_DEFAULT_SKIN 413
+#define IDR_MSF_DEFAULT_SKIN 413
+#define IDD_SKIN_TAB 415
+#define IDI_ROWCONT1 416
+#define IDI_ROWCONT2 417
+#define IDI_ROWCONT3 418
+#define IDD_TAB 450
+#define IDD_OPT_CLUI_2 451
+#define IDI_ALWAYSVIS 453
+#define IDI_ICON6 454
+#define IDI_NEVERVIS 454
+#define IDI_ICON5 455
+#define IDI_CHAT 455
+#define IDI_LISTENING_TO 456
+#define IDD_OPT_ITEM_EXTRAICONS 461
+#define IDD_OPT_CLCBKG 462
+#define IDI_FAVORITE_0 500
+#define IDI_FAVORITE_1 501
+#define IDI_FAVORITE_2 502
+#define IDI_FAVORITE_3 503
+#define IDI_SETVIEW 504
+#define IDI_RESETVIEW 505
+#define IDD_OPT_TOOLBAR 507
+#define IDC_RESETPROTOCOLDATA 1000
+#define IDC_SAVE 1001
+#define IDC_DEFBKCOLOR 1001
+#define IDI_ONTHEPHONE 1002
+#define IDC_MESSAGE 1002
+#define IDI_OUTTOLUNCH 1003
+#define IDC_AUTOCLOSE 1004
+#define IDC_FROM 1005
+#define IDC_AUTOMIN 1005
+#define IDC_DATE 1006
+#define IDC_DUMPRECV 1006
+#define IDC_MSG 1008
+#define IDC_PROXYDNS 1008
+#define IDC_NAME 1009
+#define IDC_PROXYTYPE 1009
+#define IDC_STATIC23 1010
+#define IDC_NAMEVAL 1010
+#define IDC_SPECIFYPORTS 1013
+#define IDC_ST_ENTERMSG 1013
+#define IDC_ST_ENTERURL 1014
+#define IDC_SPECIFYPORTSO 1014
+#define IDC_TEXT 1019
+#define IDC_SHOWNAMES 1024
+#define IDC_ABOUT 1032
+#define IDC_MYNOTES 1033
+#define IDC_URLS 1037
+#define IDC_REPLY 1039
+#define IDC_URL 1041
+#define IDC_REASON 1046
+#define IDC_EMAIL 1048
+#define IDC_NAMENICK 1049
+#define IDC_NAMEFIRST 1050
+#define IDC_NAMELAST 1051
+#define IDC_NICK 1053
+#define IDC_GENDER 1060
+#define IDC_CITY 1061
+#define IDC_STATE 1062
+#define IDC_COUNTRY 1063
+#define IDC_AGE 1064
+#define IDC_ZIP 1064
+#define IDC_PHONE 1065
+#define IDC_STREET 1065
+#define IDC_COMPANY 1066
+#define IDC_LANGUAGE1 1066
+#define IDC_TIMEZONE 1067
+#define IDC_DEPARTMENT 1067
+#define IDC_LOCALTIME 1068
+#define IDC_DETAILS 1069
+#define IDC_POSITION 1069
+#define IDC_LANGUAGE2 1069
+#define IDC_ADD 1070
+#define IDC_LANGUAGE3 1070
+#define IDC_MOREOPTIONS 1071
+#define IDC_USERMENU 1071
+#define IDC_DN 1072
+#define IDC_MIN2TRAY 1073
+#define IDC_ONTOP 1074
+#define IDC_SHOWMAINMENU 1075
+#define IDC_CLIENTDRAG 1076
+#define IDC_EVENTAREA 1077
+#define IDC_EDIT 1078
+#define IDC_LIST 1079
+#define IDC_HISTORY 1080
+#define IDC_USESOUND 1085
+#define IDC_TOOLWND 1097
+#define IDC_ONECLK 1098
+#define IDC_SHOWCAPTION 1098
+#define IDC_HIDEOFFLINE 1099
+#define IDC_SHOWHIDE 1100
+#define IDC_HIDEEMPTYGROUPS 1100
+#define IDC_SORTBYSTATUS 1101
+#define IDC_FADEINOUT 1101
+#define IDC_READMSG 1102
+#define IDC_AUTOSIZE 1102
+#define IDC_DISABLEGROUPS 1102
+#define IDC_AUTOSIZEUPWARD 1103
+#define IDC_ALWAYSSTATUS 1103
+#define IDC_NETSEARCH 1104
+#define IDC_CONFIRMDELETE 1104
+#define IDC_EXTRA_PROTO 1104
+#define IDC_SORTBYPROTO 1105
+#define IDC_SHOWOPTIONS 1105
+#define IDC_EXTRA_EMAIL 1105
+#define IDC_SEARCHURL 1106
+#define IDC_EXTRA_CELLULAR 1106
+#define IDC_EXTRA_ADV2 1107
+#define IDC_BUILDTIME 1108
+#define IDC_EXTRA_ADV1 1108
+#define IDC_EXTRA_WEB 1109
+#define IDC_EXTRA_CLIENT 1110
+#define IDC_LOCKSIZING 1111
+#define IDC_CHECKKEYCOLOR 1112
+#define IDC_NUMBER 1113
+#define IDC_UIN 1123
+#define IDC_TRANSPARENT 1124
+#define IDC_TRANSINACTIVE 1126
+#define IDC_TRANSACTIVE 1128
+#define IDC_FINDWHAT 1131
+#define IDC_FIND 1132
+#define IDC_FILE 1133
+#define IDC_PROFILELIST 1134
+#define IDC_NEWPROFILE 1135
+#define IDC_NEWPROFILENAME 1136
+#define IDC_TABS 1141
+#define IDC_RESULTS 1142
+#define IDC_STATUS 1144
+#define IDC_SCREENSAVE 1145
+#define IDC_TIMED 1146
+#define IDC_AWAYTIME 1147
+#define IDC_USEPROXY 1148
+#define IDC_SETNA 1148
+#define IDC_PROXYAUTH 1149
+#define IDC_NATIME 1149
+#define IDC_PROXYHOST 1150
+#define IDC_PROXYPORT 1151
+#define IDC_PROXYUSER 1152
+#define IDC_PROXYPASS 1153
+#define IDC_STATIC11 1154
+#define IDC_STATIC12 1155
+#define IDC_STATIC21 1156
+#define IDC_STATIC22 1157
+#define IDC_STATIC31 1158
+#define IDC_STATIC24 1158
+#define IDC_STATIC32 1159
+#define IDC_PROXYAUTHNTLM 1160
+#define IDC_HKSHOWHIDE 1162
+#define IDC_HKREADMSG 1163
+#define IDC_SOUNDLIST 1163
+#define IDC_HKSEARCH 1164
+#define IDC_CHANGE 1164
+#define IDC_PREVIEW 1165
+#define IDC_HKSHOWOPTIONS 1165
+#define IDC_PLUGINLIST 1167
+#define IDC_FEATURENAME 1168
+#define IDC_CHOOSE 1169
+#define IDC_TO 1170
+#define IDC_ABOUTGROUP 1175
+#define IDC_DESCRIPTION 1176
+#define IDC_AUTHOR 1177
+#define IDC_COPYRIGHT 1178
+#define IDC_VERSION 1179
+#define IDC_HOMEPAGE 1181
+#define IDC_RESTARTREQD 1182
+#define IDC_ICONSET 1183
+#define IDC_BROWSE 1184
+#define IDC_RUNATSTARTBROWSE 1185
+#define IDC_PAGETREE 1186
+#define IDC_RUNNOW 1186
+#define IDC_INACTIVEPERC 1187
+#define IDC_ACTIVEPERC 1188
+#define IDC_SEARCHNEWWND 1188
+#define IDC_RETRIEVING 1193
+#define IDC_TITLETEXT 1196
+#define IDC_GETMORE 1200
+#define IDC_VISIBLEICON 1204
+#define IDC_INVISIBLEICON 1205
+#define IDC_FILEICON 1206
+#define IDC_ONLINEICON 1207
+#define IDC_FILENAMES 1208
+#define IDC_ALLICON 1208
+#define IDC_DONTREPLY 1209
+#define IDC_NONEICON 1209
+#define IDC_USEPREVIOUS 1210
+#define IDC_NODIALOG 1211
+#define IDC_BORDER 1211
+#define IDC_USESPECIFIC 1212
+#define IDC_NOBORDERWND 1212
+#define IDC_FILEDIR 1213
+#define IDC_BORDER2 1213
+#define IDC_ROUNDCORNERS 1213
+#define IDC_ALLFILESPROGRESS 1217
+#define IDC_CURRENTSPEED 1219
+#define IDC_STAWAYTYPE 1220
+#define IDC_WHITERECT 1221
+#define IDC_ALLSPEED 1221
+#define IDC_CURRENTFILEPROGRESS 1222
+#define IDC_CURRENTFILEGROUP 1223
+#define IDC_FIRSTNAME 1224
+#define IDC_LASTNAME 1225
+#define IDC_CURRENTTRANSFERRED 1225
+#define IDC_DOBDAY 1226
+#define IDC_DOBMONTH 1227
+#define IDC_WEBPAGE 1228
+#define IDC_DOBYEAR 1228
+#define IDC_UPDATING 1231
+#define IDC_NAMEORDER 1234
+#define IDC_AUTOHIDE 1235
+#define IDC_HIDETIME 1236
+#define IDC_FRAMESGAP 1237
+#define IDC_CAPTIONSGAP 1238
+#define IDC_RECONNECTREQD 1239
+#define IDC_HIDETIME2 1239
+#define IDC_SHOWDELAY 1239
+#define IDC_HIDEDELAY 1240
+#define IDC_IMPORT 1241
+#define IDC_HIDEDELAY2 1241
+#define IDC_TOMAIN 1243
+#define IDC_TOPROTO 1244
+#define IDC_PROTOLIST 1245
+#define IDC_TODEFICON 1246
+#define IDC_IMPORTMULTI 1247
+#define IDC_MAXSIZEHEIGHT 1254
+#define IDC_MAXSIZESPIN 1255
+#define IDC_FONTID 1256
+#define IDC_MINSIZEHEIGHT 1256
+#define IDC_SAMETYPE 1257
+#define IDC_MAXSIZESPIN2 1257
+#define IDC_MINSIZESPIN 1257
+#define IDC_SAMESTYLE 1258
+#define IDC_SAMECOLOUR 1259
+#define IDC_SAMEAS 1260
+#define IDC_TYPEFACE 1261
+#define IDC_BOLD 1262
+#define IDC_ITALIC 1263
+#define IDC_COLOUR 1264
+#define IDC_UNDERLINE 1265
+#define IDC_COLOUR_MENUNORMAL 1265
+#define IDC_NOTCHECKFONTSIZE 1266
+#define IDC_COLOUR_MENU_SELECTED 1266
+#define IDC_COLOUR_MENUSELECTED 1266
+#define IDC_EFFECT_COLOUR1 1266
+#define IDC_HOTCOLOUR 1267
+#define IDC_COLOUR_FRAMES 1267
+#define IDC_VARIABLE_ROW_HEIGHT 1267
+#define IDC_SAMESIZE 1268
+#define IDC_COLOUR_STATUSBAR 1268
+#define IDC_VARIABLE_ROW_HEIGHT2 1268
+#define IDC_BKGCOLOUR 1269
+#define IDC_VARIABLE_ROW_HEIGHT3 1269
+#define IDC_EFFECT_COLOUR2 1269
+#define IDC_TXTCOLOUR 1270
+#define IDC_SAMECOLOUR2 1270
+#define IDC_SAMEEFFECT 1270
+#define IDC_FILENAME 1271
+#define IDC_SCROLL 1277
+#define IDC_PROPORTIONAL 1278
+#define IDC_SELCOLOUR 1281
+#define IDC_QUICKCOLOUR 1282
+#define IDC_SELCOLOUR2 1282
+#define IDC_SELTXTCOLOUR 1282
+#define IDC_SMOOTHTIME 1283
+#define IDC_SMOOTHTIMESPIN 1284
+#define IDC_GREYOUT 1285
+#define IDC_ROWHEIGHT 1285
+#define IDC_ROWHEIGHTSPIN 1286
+#define IDC_GREYOUTOPTS 1288
+#define IDC_GROUPINDENT 1289
+#define IDC_GROUPINDENTSPIN 1290
+#define IDC_LEFTMARGIN 1291
+#define IDC_SAMPLE 1292
+#define IDC_LEFTMARGINSPIN 1292
+#define IDC_FONTSIZE 1293
+#define IDC_LEFTMARGINSPIN2 1294
+#define IDC_LEFTMARGIN3 1295
+#define IDC_LEFTMARGINSPIN3 1296
+#define IDC_LEFTMARGIN4 1297
+#define IDC_STRETCHH 1298
+#define IDC_STRETCHV 1299
+#define IDC_TILEH 1300
+#define IDC_SCRIPT 1300
+#define IDC_TILEV 1301
+#define IDC_EFFECT_NAME 1301
+#define IDC_GAMMACORRECT 1302
+#define IDC_TILEVROWH 1302
+#define IDC_INTERESTS 1305
+#define IDC_EMAILS 1306
+#define IDC_PAST 1307
+#define IDC_HIDEOFFLINEOPTS 1308
+#define IDC_PHONES 1308
+#define IDC_SMS 1310
+#define IDC_AREA 1312
+#define IDC_UPDATE 1313
+#define IDC_DONTCYCLE 1315
+#define IDC_PRIMARYSTATUS 1316
+#define IDC_CYCLE 1317
+#define IDC_CYCLETIME 1318
+#define IDC_CYCLETIMESPIN 1319
+#define IDC_HIDETIMESPIN 1320
+#define IDC_MULTITRAY 1321
+#define IDC_FRAMESSPIN 1321
+#define IDC_ALWAYSMULTI 1322
+#define IDC_CAPTIONSSPIN 1322
+#define IDC_SHOWICON 1323
+#define IDC_HIDETIMESPIN2 1323
+#define IDC_ALWAYSMULTI2 1323
+#define IDC_ALWAYSPRIMARY 1323
+#define IDC_SHOWPROTO 1324
+#define IDC_HIDETIMESPIN3 1324
+#define IDC_SHOWSTATUS 1325
+#define IDC_HIDETIMESPIN4 1325
+#define IDC_EQUALSECTIONS 1326
+#define IDC_SHOWSIZEGRIP 1327
+#define IDC_SHOWXSTATUS 1327
+#define IDC_USEOWNERDRAW 1328
+#define IDC_SHOWNORMAL 1328
+#define IDC_SHOWSBAR 1329
+#define IDC_RIGHTMIRANDA 1330
+#define IDC_RIGHTSTATUS 1331
+#define IDC_SHOWNORMAL2 1332
+#define IDC_SHOWBOTH 1332
+#define IDC_ININAME 1333
+#define IDC_VIEWINI 1334
+#define IDC_SECURITYINFO 1335
+#define IDC_SHOWXSTATUSNAME 1335
+#define IDC_SETTINGNAME 1336
+#define IDC_NEWVALUE 1337
+#define IDC_WARNNOMORE 1338
+#define IDC_DELETE 1339
+#define IDC_RECYCLE 1340
+#define IDC_NEWNAME 1341
+#define IDC_MOVE 1342
+#define IDC_LEAVE 1343
+#define IDC_DISABLEENGINE 1343
+#define IDC_EXPERT 1346
+#define IDC_SORTBYNAME 1347
+#define IDC_STAUTOHIDESECS 1349
+#define IDC_STCLISTGROUP 1350
+#define IDC_DISABLEDRAGDROP 1351
+#define IDC_NOTEDITLABELS 1352
+#define IDC_SHOWSELALWAYS 1353
+#define IDC_TRACKSELECT 1354
+#define IDC_SHOWGROUPCOUNTS 1355
+#define IDC_HIDECOUNTSWHENEMPTY 1356
+#define IDC_DIVIDERONOFF 1357
+#define IDC_NOTNOTRANSLUCENTSEL 1358
+#define IDC_LINEWITHGROUPS 1359
+#define IDC_QUICKSEARCHVISONLY 1360
+#define IDC_SORTGROUPSALPHA 1361
+#define IDC_NOTNOSMOOTHSCROLLING 1362
+#define IDC_BITMAP 1363
+#define IDC_STWINDOWGROUP 1364
+#define IDC_STATIC01 1365
+#define IDC_STWINDOWGROUP3 1365
+#define IDC_CATEGORYLIST 1366
+#define IDC_STATIC2 1366
+#define IDC_STATIC3 1367
+#define IDC_STWINDOWGROUP2 1368
+#define IDC_LOADICONS 1369
+#define IDC_STATIC4 1369
+#define IDC_STATIC5 1370
+#define IDC_STICONSGROUP 1371
+#define IDC_STATIC6 1371
+#define IDC_STATIC7 1372
+#define IDC_STATIC8 1373
+#define IDC_STATIC9 1374
+#define IDC_MSGICON 1375
+#define IDC_STATIC10 1375
+#define IDC_URLICON 1376
+#define IDC_STATIC13 1376
+#define IDC_STNOPAGE 1377
+#define IDC_STCHECKMARKS 1380
+#define IDC_STSAMETEXT 1382
+#define IDC_STASTEXT 1383
+#define IDC_STSIZETEXT 1384
+#define IDC_STSAMETEXT2 1384
+#define IDC_STCOLOURTEXT 1385
+#define IDC_STSAMETEXT3 1385
+#define IDC_STHORZBAR 1386
+#define IDC_MIRANDA 1388
+#define IDC_STATUSBAR 1389
+#define IDC_PROTOIDGROUP 1392
+#define IDC_BYPROTOID 1393
+#define IDC_PROTOID 1394
+#define IDC_EMAILGROUP 1395
+#define IDC_BYEMAIL 1396
+#define IDC_STNAMENICK 1397
+#define IDC_NAMEGROUP 1398
+#define IDC_BYNAME 1399
+#define IDC_STNAMEFIRST 1400
+#define IDC_STNAMELAST 1401
+#define IDC_ADVANCEDGROUP 1402
+#define IDC_BYADVANCED 1403
+#define IDC_ADVANCED 1404
+#define IDC_CHECK13 1434
+#define IDC_STSIMPLERIGHT 1440
+#define IDC_NETLIBUSERS 1443
+#define IDC_STOFTENPORT 1445
+#define IDC_STATIC51 1446
+#define IDC_STATIC52 1447
+#define IDC_STATIC43 1448
+#define IDC_LOGOPTIONS 1449
+#define IDC_PORTSRANGE 1450
+#define IDC_TOCONSOLE 1451
+#define IDC_STATIC53 1451
+#define IDC_SHOWCONSOLEATSTART 1452
+#define IDC_PORTSRANGEO 1452
+#define IDC_STATIC54 1453
+#define IDC_SHOWCONSOLE 1454
+#define IDC_TOOUTPUTDEBUGSTRING 1455
+#define IDC_TOFILE 1456
+#define IDC_CLEARCONSOLE 1457
+#define IDC_RUNATSTART 1458
+#define IDC_DUMPSENT 1464
+#define IDC_DUMPPROXY 1466
+#define IDC_TEXTDUMPS 1467
+#define IDC_AUTODETECTTEXT 1468
+#define IDC_TIMEFORMAT 1469
+#define IDC_FILENAMEBROWSE 1470
+#define IDC_SHOWTHISDLGATSTART 1471
+#define IDC_FILEDIRBROWSE 1475
+#define IDC_ALLFILESGROUP 1476
+#define IDC_SCANCMDLINEBROWSE 1476
+#define IDC_ALLTRANSFERRED 1477
+#define IDC_OPENFOLDER 1478
+#define IDC_OPENFILE 1479
+#define IDC_TOTALSIZE 1480
+#define IDC_APPENDNICKTODIR 1483
+#define IDC_AUTOACCEPT 1484
+#define IDC_SCANCMDLINE 1485
+#define IDC_WARNBEFOREOPENING 1488
+#define IDC_SCANDURINGDL 1489
+#define IDC_SCANAFTERDL 1490
+#define IDC_NOSCANNER 1491
+#define IDC_ST_CMDLINE 1492
+#define IDC_ST_CMDLINEHELP 1493
+#define IDC_PROPERTIES 1496
+#define IDC_RESUME 1497
+#define IDC_EXISTINGICON 1499
+#define IDC_RESUMEALL 1500
+#define IDC_OVERWRITE 1501
+#define IDC_OVERWRITEALL 1502
+#define IDC_AVATAR_OVERLAY_ICON_CONTACT 1502
+#define IDC_SKIP 1503
+#define IDC_EXISTINGSIZE 1506
+#define IDC_EXISTINGDATE 1507
+#define IDC_EXISTINGTYPE 1508
+#define IDC_NEWICON 1509
+#define IDC_NEWSIZE 1510
+#define IDC_NEWDATE 1511
+#define IDC_NEWTYPE 1512
+#define IDC_SAVEAS 1513
+#define IDC_ASK 1516
+#define IDC_RENAME 1519
+#define IDC_VIRUSSCANNERGROUP 1520
+#define IDC_HIDE 1534
+#define IDC_TOPLINE 1535
+#define IDC_GPLBTN 1536
+#define IDC_MAIL 1536
+#define IDC_MYHANDLE 1540
+#define IDC_GROUP 1541
+#define IDC_ADDED 1542
+#define IDC_AUTH 1543
+#define IDC_PLUGINSTATIC1 1559
+#define IDC_DELETEHISTORY 1560
+#define IDC_HOTKEYURLSTR 1567
+#define IDC_SETNASTR 1568
+#define IDC_AAUTHOR 1569
+#define IDC_AHOMEPAGE 1570
+#define IDC_AVERSION 1571
+#define IDC_ACOPYRIGHT 1572
+#define IDC_ADESCRIPTION 1573
+#define IDC_PLUGINENABLE 1574
+#define IDC_AUTHREQ 1577
+#define IDC_AUTHGB 1578
+#define IDC_BRINGTOFRONT 1579
+#define IDC_PROTOCOL 1580
+#define IDC_CONTRIBLINK 1586
+#define IDC_HOMELINK 1587
+#define IDC_SUPPORTLINK 1588
+#define IDC_DEVS 1589
+#define IDC_GPL 1590
+#define IDC_LOGO 1591
+#define IDC_PROTOCOLORDER 1591
+#define IDC_PROTOCOLORDERWARNING 1592
+#define IDC_CREDITSTEXT 1595
+#define IDC_WSLOCK 1599
+#define IDC_BLINKTIME 1607
+#define IDC_BLINKSPIN 1608
+#define IDC_DISABLEBLINK 1609
+#define IDC_IDLE 1610
+#define IDC_SBPANELBEVEL 1611
+#define IDC_META 1611
+#define IDC_DROPSHADOW 1612
+#define IDC_METADBLCLK 1612
+#define IDC_NOSCROLLBAR 1613
+#define IDC_METAEXPAND 1613
+#define IDC_AEROGLASS 1613
+#define IDC_METASUBEXTRA 1614
+#define IDC_METASUBEXTRA_IGN 1615
+#define IDC_METASUB_HIDEOFFLINE 1616
+#define IDC_MIN_ROW_HEIGHT 1616
+#define IDC_MIN_ROW_HEIGHT_SPIN 1617
+#define IDC_TXT_TITLE1 1617
+#define IDC_ROW_BORDER 1618
+#define IDC_TXT_TITLE2 1618
+#define IDC_ROW_BORDER_SPIN 1619
+#define IDC_AVATAR_SIZE 1620
+#define IDC_TXT_TITLE4 1620
+#define IDC_AVATAR_SIZE_SPIN 1621
+#define IDC_ROW_BORDER2 1622
+#define IDC_AVATAR_CUSTOM_CORNER_SIZE 1622
+#define IDC_TXT_TITLE5 1622
+#define IDC_ROW_BORDER3 1623
+#define IDC_AVATAR_SIZE_SPIN2 1623
+#define IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN 1623
+#define IDC_TXT_TITLE3 1623
+#define IDC_ROW_BORDER_SPIN2 1624
+#define IDC_AVATAR_WIDTH 1624
+#define IDC_ROW_BORDER_SPIN3 1625
+#define IDC_AVATAR_SIZE_SPIN3 1625
+#define IDC_AVATAR_WIDTH_SPIN 1625
+#define IDC_BUTTON1 1633
+#define IDC_BUTTON_BROWSE 1633
+#define IDC_UP 1633
+#define IDC_BUTTON_UP 1633
+#define IDC_DOWN 1634
+#define IDC_C_SPLIT 1634
+#define IDC_PASTE 1634
+#define IDC_BUTTON4 1634
+#define IDC_BUTTON_DOWN 1634
+#define IDC_IDLECHECK 1636
+#define IDC_IDLEONWINDOWS 1637
+#define IDC_IDLEONMIRANDA 1638
+#define IDC_IDLEUSEGLI 1639
+#define IDC_SCREENSAVER 1642
+#define IDC_LOCKED 1643
+#define IDC_IDLESHORT 1644
+#define IDC_IDLELONG 1645
+#define IDC_IDLE1STTIME 1646
+#define IDC_IDLE2NDTIME 1647
+#define IDC_IDLEPRIVATE 1649
+#define IDC_AASTATUS 1650
+#define IDC_AASHORTIDLE 1651
+#define IDC_AALONGSTATUS 1652
+#define IDC_AALONGIDLE 1656
+#define IDC_NOOFFLINEMOVE 1657
+#define IDC_HOTKEYTREE 1657
+#define IDC_HILIGHTMODE 1658
+#define IDC_OFFLINETOROOT 1658
+#define IDC_HILIGHTMODE2 1659
+#define IDC_LOCATION 1659
+#define IDC_HILIGHTMODE1 1660
+#define IDC_SGROUP 1660
+#define IDC_HILIGHTMODE3 1661
+#define IDC_SLOC 1661
+#define IDC_ONDESKTOP 1662
+#define IDC_HILIGHTMODE4 1663
+#define IDC_SETHOTKEY 1759
+#define IDC_HKTITLE 1760
+#define IDC_CHECK1 1761
+#define IDC_USECONNECTINGICON 1761
+#define IDC_CHECK_METHOD 1761
+#define IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK 1761
+#define IDC_XSTATUS_HAS_PRIORITY 1761
+#define IDC_CONTLAYER 1761
+#define IDC_FRAME_META_CAPT 1762
+#define IDC_OFFSETICON 1762
+#define IDC_CHECK_COLOR 1762
+#define IDC_SHOW_STATUS_IF_NOAWAY 1762
+#define IDC_CHECK6 1762
+#define IDC_CHECK_AUTOSIZE 1762
+#define IDC_DISCOVER_AWAYMSG 1763
+#define IDC_OFFSETSPIN 1763
+#define IDC_CHECK_IMAGE 1763
+#define IDC_XSTATUS_HAS_PRIORITY2 1763
+#define IDC_USE_NAME_AND_MESSAGE 1763
+#define IDC_STATUSTEXT 1763
+#define IDC_CHECK9 1763
+#define IDC_DRAGTOSCROLL 1764
+#define IDC_OFFSETSUB 1764
+#define IDC_SUBINDENT 1764
+#define IDC_CHECK_ALPHA 1764
+#define IDC_AVATAR_DRAW_BORDER 1764
+#define IDC_OFFSETICON2 1764
+#define IDC_SHOW_STATUS_IF_NOAWAY2 1764
+#define IDC_SHOW_LISTENING_IF_NOAWAY 1764
+#define IDC_CHECK10 1764
+#define IDC_COMBO1 1765
+#define IDC_SUBINDENTSPIN 1765
+#define IDC_HIDEMETHOD 1765
+#define IDC_OFFSETSPIN2 1765
+#define IDC_ALIGNGROUPCOMBO 1765
+#define IDC_CHECK11 1765
+#define IDC_BKGRLIST 1766
+#define IDC_SUBIDENTCAPT 1766
+#define IDC_COMBO_FIT 1766
+#define IDC_OFFSETICON3 1766
+#define IDC_H_ALIGN 1766
+#define IDC_BC_STATIC 1767
+#define IDC_OBJECTSTREE 1767
+#define IDC_OFFSETSPIN3 1767
+#define IDC_REMOVE_OFFLINE_AWAYMSG 1767
+#define IDC_V_ALIGN 1767
+#define IDC_SC_STATIC 1768
+#define IDC_COMBO_SAME 1768
+#define IDC_TRANSPARENTOVERLAY 1768
+#define IDC_SHOWUNREADEMAIL 1769
+#define IDC_IDC_MULTI_COUNT 1771
+#define IDC_MULTI_COUNT 1771
+#define IDC_MULTI_SPIN 1772
+#define IDC_EDIT_FILENAME 1773
+#define IDC_EDIT_FILENAME2 1774
+#define IDC_EDIT_SKIN_FILENAME 1774
+#define IDC_OFFSETICON4 1774
+#define IDC_EDIT_LEFT 1775
+#define IDC_EDIT_RIGHT 1776
+#define IDC_EDIT_TOP 1777
+#define IDC_EDIT_BOTTOM 1778
+#define IDC_SPIN_LEFT 1779
+#define IDC_EDIT_ALPHA 1780
+#define IDC_SPIN_RIGHT 1781
+#define IDC_SPIN_TOP 1782
+#define IDC_SPIN_BOTTOM 1783
+#define IDC_SPIN_ALPHA 1784
+#define IDC_BUTTON_LOAD 1785
+#define IDC_BUTTON_SAVE 1786
+#define IDC_FRAME_GLYPH 1787
+#define IDC_BUTTON_LOAD2 1787
+#define IDC_BUTTON_APPLY_SKIN 1787
+#define IDC_STATIC_SAME 1788
+#define IDC_STATIC_MARGINS 1788
+#define IDC_FRAME_BACKGROUND 1789
+#define IDC_BUTTON_LOAD3 1789
+#define IDC_BUTTON_INFO 1789
+#define IDC_STATIC_STYLE 1790
+#define IDC_COMBO_STYLE 1791
+#define IDC_STATIC_COLOR 1792
+#define IDC_STATIC_ALPHA 1793
+#define IDC_FRAME_IMAGE 1794
+#define IDC_STATIC_LEFT 1795
+#define IDC_STATIC_RIGHT 1796
+#define IDC_STATIC_TOP 1797
+#define IDC_STATIC_BOTTOM 1798
+#define IDC_STATIC_FIT 1799
+#define IDC_STATIC_COLOR2 1800
+#define IDC_AVATAR_ROUND_CORNERS 1800
+#define IDC_STATIC_COLOR3 1801
+#define IDC_AVATAR_ALIGN_LEFT 1801
+#define IDC_DRAW_ON_AVATAR_SPACE 1801
+#define IDC_STATIC_COLOR4 1802
+#define IDC_AVATAR_OVERLAY_ICONS 1802
+#define IDC_STATIC_COLOR5 1803
+#define IDC_AVATAR_SIZE_L 1803
+#define IDC_AVATAR_SIZE_PIXELS 1804
+#define IDC_COLOUR_KEYCOLOR 1805
+#define IDC_COLOUR_KEY 1805
+#define IDC_IGNORE_SIZE 1805
+#define IDC_AVATAR_SIZE_PIXELS2 1805
+#define IDC_LIST1 1806
+#define IDC_OBJECTSLIST 1806
+#define IDC_IGNORE_SIZE2 1806
+#define IDC_ALIGN_RIGHT 1806
+#define IDC_AVATAR_SIZE_PIXELS3 1806
+#define IDC_CHECK2 1807
+#define IDC_OBJECTSLIST2 1807
+#define IDC_SKINS_LIST 1807
+#define IDC_LAYERENGINE 1807
+#define IDC_CHECK3 1808
+#define IDC_SNAPTOEDGES 1808
+#define IDC_LAYERENGINE2 1808
+#define IDC_CHECK4 1809
+#define IDC_SNAPTOEDGES2 1809
+#define IDC_DOCKTOSIDES 1809
+#define IDC_CHECK5 1810
+#define IDC_RADIO1 1811
+#define IDC_AVATAR_OVERLAY_ICON_NORMAL 1811
+#define IDC_EVENTAREA_NONE 1811
+#define IDC_RADIO2 1812
+#define IDC_AVATAR_OVERLAY_ICON_PROTOCOL 1812
+#define IDC_RADIO3 1813
+#define IDC_OVERLAY_ICON3 1813
+#define IDC_EVENTAREA_ALWAYS 1813
+#define IDC_RADIO4 1814
+#define IDC_RADIO5 1815
+#define IDC_CHECK7 1816
+#define IDC_TAB1 1816
+#define IDC_TAB 1816
+#define IDC_RADIO6 1817
+#define IDC_RADIO7 1818
+#define IDC_ALIGN_TO_LEFT 1818
+#define IDC_RADIO8 1819
+#define IDC_ALIGN_TO_RIGHT 1819
+#define IDC_CHECK8 1820
+#define IDC_LIST_ORDER 1820
+#define IDC_RADIO9 1820
+#define IDC_AVATAR_IGNORE_SIZE 1821
+#define IDC_RADIO10 1821
+#define IDC_NOTCHECKICONSIZE 1822
+#define IDC_RADIO11 1822
+#define IDC_RTL 1823
+#define IDC_RADIO12 1823
+#define IDC_REPLACE_SMILEYS 1824
+#define IDC_RADIO13 1824
+#define IDC_USE_PROTOCOL_SMILEYS 1825
+#define IDC_DRAW_SMILEYS_ON_FIRST_LINE 1826
+#define IDC_TOP_SPACE 1827
+#define IDC_RESIZE_SMILEYS 1827
+#define IDC_TOP_SPACE_SPIN 1828
+#define IDC_DRAW_SMILEYS_ON_FIRST_LINE2 1828
+#define IDC_APPEND_NICK 1828
+#define IDC_DRAW_SMILEYS 1829
+#define IDC_TRIM_TEXT 1829
+#define IDC_EMPTY 1830
+#define IDC_NICKNAME 1831
+#define IDC_STATUS_MESSAGE 1832
+#define IDC_VARIABLE_TEXT 1833
+#define IDC_DRAW_SMILEYS2 1834
+#define IDC_SHOW 1834
+#define IDC_CONTACT_TIME 1835
+#define IDC_LISTENING_TO 1836
+#define IDC_STATIC_PIXELS 1837
+#define IDC_STATIC_TEXT 1838
+#define IDC_AVATAR_BORDER_COLOR_L 1839
+#define IDC_AVATAR_BORDER_COLOR 1840
+#define IDC_VARIABLES_L 1841
+#define IDC_SHOW_ONLY_IF_DIFFERENT 1842
+#define IDC_COMBO2 1842
+#define IDC_EDIT1 1843
+#define IDC_CONTWIDTH 1843
+#define IDC_HIDE_GROUPSICON 1844
+#define IDC_STATIC_INFO 1845
+#define IDC_USEXSTATUS 1845
+#define IDC_HIDE_GROUPSICON3 1846
+#define IDC_DRAWSTATUSOVERLAY 1846
+#define IDC_DESIGNTREE 1848
+#define IDC_TYPE 1849
+#define IDC_R_SPLIT 1850
+#define IDC_PREVIEW_IMAGE 1851
+#define IDC_TITLEBAR_STATIC 1852
+#define IDC_EFFECT_COLOUR_TEXT1 1853
+#define IDC_EFFECT_COLOUR_SPIN1 1854
+#define IDC_OBJECT_TREE 1856
+#define IDC_FIT 1858
+#define IDC_E_X 1862
+#define IDC_E_Y 1863
+#define IDC_E_W 1864
+#define IDC_E_H 1865
+#define IDC_E_LEFT 1866
+#define IDC_E_TOP 1867
+#define IDC_E_RIGHT 1868
+#define IDC_E_BOTTOM 1869
+#define IDC_TREE1 1871
+#define IDC_SPIN_POSLEFT 1875
+#define IDC_SPIN_POSTOP 1876
+#define IDC_SPIN_WIDTH 1877
+#define IDC_SPIN_HEIGHT 1878
+#define IDC_GROUP_0 1879
+#define IDC_GROUP_1 1880
+#define IDC_GROUP_2 1881
+#define IDC_GROUP_3 1883
+#define IDC_COLOR 1884
+#define IDC_COPY 1885
+#define IDC_ST_COLOUR 1886
+#define IDC_ST_ALPHA 1887
+#define IDC_S_SIZE 1888
+#define IDC_EXTRAORDER 1889
+#define IDC_SKIN_TAB 1890
+#define IDC_ROWTREE 1955
+#define IDC_ADDCONTAINER 1956
+#define IDC_BUTTON2 1957
+#define IDC_DELCONTAINER 1957
+#define IDC_VALIGN 1958
+#define IDC_HALIGN 1959
+#define IDC_CONTTYPE 1960
+#define IDC_SPINCONTWIDTH 1966
+#define IDC_CONTHEIGHT 1967
+#define IDC_SPINCONTHEIGHT 1968
+#define IDC_CONTUP 1969
+#define IDC_BUTTON3 1970
+#define IDC_CONTDOWN 1970
+#define IDC_MULTI 2000
+#define IDC_MULTI_2 2001
+#define IDC_FRAMESORDER 2002
+#define IDC_USEWINCOL 2004
+#define IDC_MINIMODE 2005
+#define IDC_BTNORDER 2006
+#define IDC_TBSHOW 2007
+#define IDC_STATIC_W 2008
+#define IDC_STATIC_H 2009
+#define IDC_STATIC_S 2010
+#define IDC_TEXT_W 2011
+#define IDC_TEXT_H 2012
+#define IDC_TEXT_S 2013
+#define IDC_SPIN_W 2014
+#define IDC_SPIN_H 2015
+#define IDC_SPIN_S 2016
+#define IDC_CHECK_MULTILINE 2017
+#define IDC_CHECK_ATOSIZE 2018
+#define IDC_SBAR_HORIZ_ALIGN 2019
+#define IDC_SBAR_TOP_BORDER 2020
+#define IDC_SBAR_BOTTOM_BORDER 2021
+#define IDC_STATUSBAR_PER_PROTO 2022
+#define IDC_OFFSETICON_RIGHT 2023
+#define IDC_OFFSETSPIN_RIGHT 2024
+#define IDC_OFFSETICON_LEFT 2025
+#define IDC_OFFSETSPIN_LEFT 2026
+#define IDC_STATUSBAR_PROTO_LIST 2027
+#define IDC_SBAR_USE_ACCOUNT_SETTINGS 2028
+#define IDC_SBAR_HIDE_ACCOUNT_COMPLETELY 2029
+#define IDC_SBAR_BORDER_TOP 2030
+#define IDC_SBAR_BORDER_TOP_SPIN 2031
+#define IDC_SBAR_BORDER_BOTTOM 2032
+#define IDC_SBAR_BORDER_BOTTOM_SPIN 2033
+#define IDC_SBAR_VERT_ALIGN 2034
+#define IDC_CLSORT1 6666
+#define IDC_CLSORT2 6667
+#define IDC_CLSORT3 6668
+#define IDC_WINCOLOUR 6669
+#define IDD_OPT_CLCBKG3 11268
+#define IDD_OPT_EXTFRAMES 11269
+#define IDC_MENUITEMS 11710
+#define IDC_MENUOBJECTS 11711
+#define IDC_NOTSUPPORTWARNING 11712
+#define IDC_INSERTSEPARATOR 11715
+#define IDC_GENMENU_SERVICE 11716
+#define IDC_GENMENU_CUSTOMNAME 11717
+#define IDC_GENMENU_SET 11718
+#define IDC_GENMENU_SET2 11719
+#define IDC_GENMENU_DEFAULT 11719
+#define IDC_ICONBLINK 11720
+#define IDC_ICONBLINK2 11721
+#define IDC_SHOW_AVATARS 11721
+#define IDC_SHOW_AVATARS2 11722
+#define IDC_SHOW_ANIAVATARS 11722
+#define IDC_SHOW_STATUSMSG 11723
+#define IDC_HIDE_ICON_ON_AVATAR 11723
+#define IDC_SHOW_ANIAVATARS2 11723
+#define IDC_AVATAR_FASTDRAW 11723
+#define IDC_SHOW_STATUSMSG2 11724
+#define IDC_SHOW_STATUS_MSG 11724
+#define IDC_SUBIDENTCAPT2 11767
+#define IDC_SUBIDENTCAPT3 11768
+#define IDC_SUBIDENTCAPT4 11769
+#define IDC_RIGHTMARGIN 11800
+#define IDC_TOPMARGIN 11801
+#define IDC_BOTTOMMARGIN 11802
+#define IDC_RIGHTMARGINSPIN 11803
+#define IDC_EFFECT_COLOUR_TEXT2 11803
+#define IDC_TOPMARGINSPIN 11804
+#define IDC_BOTTOMMARGINSPIN 11805
+#define IDC_EFFECT_COLOUR_SPIN2 11806
+#define IDC_LEFTMARGIN2 12931
+#define IDC_LEFTMARGINSPIN4 12981
+#define IDD_OPT_VIEWMODES 19100
+#define IDC_VIEWMODES 19102
+#define IDC_PROTOCOLS 19103
+#define IDC_ADDVIEWMODE 19104
+#define IDC_DELETEVIEWMODE 19105
+#define IDC_NEWVIEMODE 19106
+#define IDC_GROUPS 19107
+#define IDC_STATUSMODES 19108
+#define IDC_CLIST 19109
+#define IDC_CLEARALL 19110
+#define IDC_PROTOGROUPOP 19111
+#define IDC_GROUPSTATUSOP 19112
+#define IDC_STATIC14 19113
+#define IDC_AUTOCLEAR 19114
+#define IDC_AUTOCLEARVAL 19115
+#define IDC_AUTOCLEARSPIN 19116
+#define IDC_STATIC15 19117
+#define IDC_STATIC16 19118
+#define IDC_CURVIEWMODE2 19119
+#define IDC_LASTMSG 19120
+#define IDC_LASTMESSAGEOP 19121
+#define IDC_LASTMSGVALUE 19122
+#define IDC_LASTMESSAGEUNIT 19123
+#define IDC_STATIC1 19124
+#define IDC_RESETMODES 19125
+#define IDC_LASTMSG2 19125
+#define IDC_SELECTMODE 19126
+#define IDC_CONFIGUREMODES 19127
+#define IDC_USEGROUPS 19128
+#define IDI_SEARCHALL 32548
+#define ID_ICQ_EXIT 40001
+#define IDM_COPY 40001
+#define ID_RESET 40002
+#define POPUP_HIDEEMPTYGROUPS 40003
+#define POPUP_NEWSUBGROUP 40004
+#define POPUP_HIDEOFFLINE 40005
+#define POPUP_GROUPHIDEOFFLINE 40006
+#define POPUP_HIDEOFFLINEROOT 40007
+#define POPUP_DISABLEGROUPS 40008
+#define IDC_SENDMESSAGE 40009
+#define IDM_COPYALL 40011
+#define IDM_SELECTALL 40012
+#define IDM_CLEAR 40013
+#define IDM_OPENNEW 40014
+#define IDM_OPENEXISTING 40015
+#define IDM_COPYLINK 40016
+#define POPUP_HIDEMIRANDA 40017
+#define POPUP_GROUPSHOWOFFLINE 40019
+#define ID_MINIMIZE 40021
+#define ID_TRAY_HIDE 40038
+#define ID_TRAY_EXIT 40040
+#define POPUP_NEWGROUP 40050
+#define POPUP_RENAMEGROUP 40052
+#define POPUP_DELETEGROUP 40053
+#define IDC_FRAME_META 40054
+#define IDC_FRAME_META2 40055
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 509
+#define _APS_NEXT_COMMAND_VALUE 40022
+#define _APS_NEXT_CONTROL_VALUE 2024
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/Clist_modern/src/version.h b/plugins/Clist_modern/src/version.h
new file mode 100644
index 0000000000..73152f4f57
--- /dev/null
+++ b/plugins/Clist_modern/src/version.h
@@ -0,0 +1,15 @@
+#define BUILD_NUM 11
+#define BUILD_NUM_STR "11"
+
+#define COREVERSION_NUM 0, 9, 0,
+#define COREVERSION_NUM_STR "0, 9, 0 "
+
+#define MINIMAL_COREVERSION_NUM PLUGIN_MAKE_VERSION(0, 9, 0, 0)
+#define MINIMAL_COREVERSION 0, 9, 0, 0
+#define MINIMAL_COREVERSION_STR "0, 9, 0, 0 "
+
+#define FILE_VERSION COREVERSION_NUM BUILD_NUM
+#define FILE_VERSION_STR COREVERSION_NUM_STR " build " BUILD_NUM_STR " "
+
+#define PRODUCT_VERSION FILE_VERSION
+#define PRODUCT_VERSION_STR FILE_VERSION_STR