From 2ab468f0ac05d1f257fbf8aa6add9512eabbcc20 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Fri, 13 Jul 2012 07:39:26 +0000 Subject: Clist_modern: changed folder structure git-svn-id: http://svn.miranda-ng.org/main/trunk@939 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Clist_modern/src/MString.cpp | 205 + plugins/Clist_modern/src/hdr/MString.h | 2304 ++++++++++ plugins/Clist_modern/src/hdr/modern_awaymsg.h | 37 + plugins/Clist_modern/src/hdr/modern_cache_funcs.h | 46 + plugins/Clist_modern/src/hdr/modern_callproc.h | 128 + plugins/Clist_modern/src/hdr/modern_clc.h | 515 +++ plugins/Clist_modern/src/hdr/modern_clcpaint.h | 191 + plugins/Clist_modern/src/hdr/modern_clist.h | 165 + plugins/Clist_modern/src/hdr/modern_clui.h | 193 + plugins/Clist_modern/src/hdr/modern_cluiframes.h | 150 + .../Clist_modern/src/hdr/modern_commonheaders.h | 460 ++ .../Clist_modern/src/hdr/modern_commonprototypes.h | 356 ++ plugins/Clist_modern/src/hdr/modern_defsettings.h | 284 ++ plugins/Clist_modern/src/hdr/modern_effectenum.h | 93 + plugins/Clist_modern/src/hdr/modern_gettextasync.h | 5 + .../Clist_modern/src/hdr/modern_global_structure.h | 92 + plugins/Clist_modern/src/hdr/modern_image_array.h | 104 + .../src/hdr/modern_layered_window_engine.h | 51 + plugins/Clist_modern/src/hdr/modern_log.h | 27 + plugins/Clist_modern/src/hdr/modern_popup.h | 48 + plugins/Clist_modern/src/hdr/modern_row.h | 86 + .../Clist_modern/src/hdr/modern_rowheight_funcs.h | 70 + plugins/Clist_modern/src/hdr/modern_skinengine.h | 148 + .../Clist_modern/src/hdr/modern_skinned_profile.h | 245 ++ plugins/Clist_modern/src/hdr/modern_skinselector.h | 88 + plugins/Clist_modern/src/hdr/modern_static_clui.h | 246 ++ .../src/hdr/modern_static_cluiframes_service.h | 192 + plugins/Clist_modern/src/hdr/modern_statusbar.h | 44 + plugins/Clist_modern/src/hdr/modern_statusmodes.h | 43 + plugins/Clist_modern/src/hdr/modern_sync.h | 98 + plugins/Clist_modern/src/hdr/modern_tstring.h | 58 + plugins/Clist_modern/src/init.cpp | 244 + plugins/Clist_modern/src/m_api/m_skin_eng.h | 434 ++ plugins/Clist_modern/src/m_api/m_skinbutton.h | 31 + plugins/Clist_modern/src/m_api/m_skinned_profile.h | 44 + plugins/Clist_modern/src/m_api/m_xpTheme.h | 35 + plugins/Clist_modern/src/modern_aniavatars.cpp | 1300 ++++++ plugins/Clist_modern/src/modern_awaymsg.cpp | 232 + plugins/Clist_modern/src/modern_cachefuncs.cpp | 968 ++++ plugins/Clist_modern/src/modern_callproc.cpp | 20 + plugins/Clist_modern/src/modern_clc.cpp | 2107 +++++++++ plugins/Clist_modern/src/modern_clcidents.cpp | 299 ++ plugins/Clist_modern/src/modern_clcitems.cpp | 819 ++++ plugins/Clist_modern/src/modern_clcmsgs.cpp | 262 ++ plugins/Clist_modern/src/modern_clcopts.cpp | 2068 +++++++++ plugins/Clist_modern/src/modern_clcpaint.cpp | 3385 ++++++++++++++ plugins/Clist_modern/src/modern_clcutils.cpp | 870 ++++ plugins/Clist_modern/src/modern_clistevents.cpp | 624 +++ plugins/Clist_modern/src/modern_clistmenus.cpp | 217 + plugins/Clist_modern/src/modern_clistmod.cpp | 567 +++ plugins/Clist_modern/src/modern_clistopts.cpp | 1282 ++++++ plugins/Clist_modern/src/modern_clistsettings.cpp | 531 +++ plugins/Clist_modern/src/modern_clisttray.cpp | 736 ++++ plugins/Clist_modern/src/modern_clui.cpp | 3111 +++++++++++++ plugins/Clist_modern/src/modern_cluiframes.cpp | 4222 ++++++++++++++++++ plugins/Clist_modern/src/modern_cluiservices.cpp | 178 + plugins/Clist_modern/src/modern_commonheaders.cpp | 247 ++ plugins/Clist_modern/src/modern_contact.cpp | 219 + plugins/Clist_modern/src/modern_docking.cpp | 372 ++ plugins/Clist_modern/src/modern_extraimage.cpp | 509 +++ plugins/Clist_modern/src/modern_framesmenu.cpp | 214 + plugins/Clist_modern/src/modern_gdiplus.cpp | 308 ++ plugins/Clist_modern/src/modern_gettextasync.cpp | 205 + plugins/Clist_modern/src/modern_global.cpp | 35 + plugins/Clist_modern/src/modern_groupmenu.cpp | 754 ++++ plugins/Clist_modern/src/modern_image_array.cpp | 705 +++ plugins/Clist_modern/src/modern_keyboard.cpp | 67 + plugins/Clist_modern/src/modern_log.cpp | 46 + plugins/Clist_modern/src/modern_newrowopts.cpp | 198 + plugins/Clist_modern/src/modern_popup.cpp | 131 + plugins/Clist_modern/src/modern_row.cpp | 789 ++++ .../Clist_modern/src/modern_rowheight_funcs.cpp | 796 ++++ plugins/Clist_modern/src/modern_rowtemplateopt.cpp | 704 +++ plugins/Clist_modern/src/modern_skinbutton.cpp | 815 ++++ plugins/Clist_modern/src/modern_skineditor.cpp | 841 ++++ plugins/Clist_modern/src/modern_skinengine.cpp | 4650 ++++++++++++++++++++ .../Clist_modern/src/modern_skinned_profile.cpp | 115 + plugins/Clist_modern/src/modern_skinopt.cpp | 771 ++++ plugins/Clist_modern/src/modern_skinselector.cpp | 792 ++++ plugins/Clist_modern/src/modern_statusbar.cpp | 1136 +++++ .../Clist_modern/src/modern_statusbar_options.cpp | 541 +++ plugins/Clist_modern/src/modern_sync.cpp | 147 + plugins/Clist_modern/src/modern_tbbutton.cpp | 503 +++ plugins/Clist_modern/src/modern_toolbar.cpp | 357 ++ plugins/Clist_modern/src/modern_viewmodebar.cpp | 1574 +++++++ plugins/Clist_modern/src/modern_xptheme.cpp | 265 ++ plugins/Clist_modern/src/resource.h | 1053 +++++ plugins/Clist_modern/src/version.h | 15 + 88 files changed, 51232 insertions(+) create mode 100644 plugins/Clist_modern/src/MString.cpp create mode 100644 plugins/Clist_modern/src/hdr/MString.h create mode 100644 plugins/Clist_modern/src/hdr/modern_awaymsg.h create mode 100644 plugins/Clist_modern/src/hdr/modern_cache_funcs.h create mode 100644 plugins/Clist_modern/src/hdr/modern_callproc.h create mode 100644 plugins/Clist_modern/src/hdr/modern_clc.h create mode 100644 plugins/Clist_modern/src/hdr/modern_clcpaint.h create mode 100644 plugins/Clist_modern/src/hdr/modern_clist.h create mode 100644 plugins/Clist_modern/src/hdr/modern_clui.h create mode 100644 plugins/Clist_modern/src/hdr/modern_cluiframes.h create mode 100644 plugins/Clist_modern/src/hdr/modern_commonheaders.h create mode 100644 plugins/Clist_modern/src/hdr/modern_commonprototypes.h create mode 100644 plugins/Clist_modern/src/hdr/modern_defsettings.h create mode 100644 plugins/Clist_modern/src/hdr/modern_effectenum.h create mode 100644 plugins/Clist_modern/src/hdr/modern_gettextasync.h create mode 100644 plugins/Clist_modern/src/hdr/modern_global_structure.h create mode 100644 plugins/Clist_modern/src/hdr/modern_image_array.h create mode 100644 plugins/Clist_modern/src/hdr/modern_layered_window_engine.h create mode 100644 plugins/Clist_modern/src/hdr/modern_log.h create mode 100644 plugins/Clist_modern/src/hdr/modern_popup.h create mode 100644 plugins/Clist_modern/src/hdr/modern_row.h create mode 100644 plugins/Clist_modern/src/hdr/modern_rowheight_funcs.h create mode 100644 plugins/Clist_modern/src/hdr/modern_skinengine.h create mode 100644 plugins/Clist_modern/src/hdr/modern_skinned_profile.h create mode 100644 plugins/Clist_modern/src/hdr/modern_skinselector.h create mode 100644 plugins/Clist_modern/src/hdr/modern_static_clui.h create mode 100644 plugins/Clist_modern/src/hdr/modern_static_cluiframes_service.h create mode 100644 plugins/Clist_modern/src/hdr/modern_statusbar.h create mode 100644 plugins/Clist_modern/src/hdr/modern_statusmodes.h create mode 100644 plugins/Clist_modern/src/hdr/modern_sync.h create mode 100644 plugins/Clist_modern/src/hdr/modern_tstring.h create mode 100644 plugins/Clist_modern/src/init.cpp create mode 100644 plugins/Clist_modern/src/m_api/m_skin_eng.h create mode 100644 plugins/Clist_modern/src/m_api/m_skinbutton.h create mode 100644 plugins/Clist_modern/src/m_api/m_skinned_profile.h create mode 100644 plugins/Clist_modern/src/m_api/m_xpTheme.h create mode 100644 plugins/Clist_modern/src/modern_aniavatars.cpp create mode 100644 plugins/Clist_modern/src/modern_awaymsg.cpp create mode 100644 plugins/Clist_modern/src/modern_cachefuncs.cpp create mode 100644 plugins/Clist_modern/src/modern_callproc.cpp create mode 100644 plugins/Clist_modern/src/modern_clc.cpp create mode 100644 plugins/Clist_modern/src/modern_clcidents.cpp create mode 100644 plugins/Clist_modern/src/modern_clcitems.cpp create mode 100644 plugins/Clist_modern/src/modern_clcmsgs.cpp create mode 100644 plugins/Clist_modern/src/modern_clcopts.cpp create mode 100644 plugins/Clist_modern/src/modern_clcpaint.cpp create mode 100644 plugins/Clist_modern/src/modern_clcutils.cpp create mode 100644 plugins/Clist_modern/src/modern_clistevents.cpp create mode 100644 plugins/Clist_modern/src/modern_clistmenus.cpp create mode 100644 plugins/Clist_modern/src/modern_clistmod.cpp create mode 100644 plugins/Clist_modern/src/modern_clistopts.cpp create mode 100644 plugins/Clist_modern/src/modern_clistsettings.cpp create mode 100644 plugins/Clist_modern/src/modern_clisttray.cpp create mode 100644 plugins/Clist_modern/src/modern_clui.cpp create mode 100644 plugins/Clist_modern/src/modern_cluiframes.cpp create mode 100644 plugins/Clist_modern/src/modern_cluiservices.cpp create mode 100644 plugins/Clist_modern/src/modern_commonheaders.cpp create mode 100644 plugins/Clist_modern/src/modern_contact.cpp create mode 100644 plugins/Clist_modern/src/modern_docking.cpp create mode 100644 plugins/Clist_modern/src/modern_extraimage.cpp create mode 100644 plugins/Clist_modern/src/modern_framesmenu.cpp create mode 100644 plugins/Clist_modern/src/modern_gdiplus.cpp create mode 100644 plugins/Clist_modern/src/modern_gettextasync.cpp create mode 100644 plugins/Clist_modern/src/modern_global.cpp create mode 100644 plugins/Clist_modern/src/modern_groupmenu.cpp create mode 100644 plugins/Clist_modern/src/modern_image_array.cpp create mode 100644 plugins/Clist_modern/src/modern_keyboard.cpp create mode 100644 plugins/Clist_modern/src/modern_log.cpp create mode 100644 plugins/Clist_modern/src/modern_newrowopts.cpp create mode 100644 plugins/Clist_modern/src/modern_popup.cpp create mode 100644 plugins/Clist_modern/src/modern_row.cpp create mode 100644 plugins/Clist_modern/src/modern_rowheight_funcs.cpp create mode 100644 plugins/Clist_modern/src/modern_rowtemplateopt.cpp create mode 100644 plugins/Clist_modern/src/modern_skinbutton.cpp create mode 100644 plugins/Clist_modern/src/modern_skineditor.cpp create mode 100644 plugins/Clist_modern/src/modern_skinengine.cpp create mode 100644 plugins/Clist_modern/src/modern_skinned_profile.cpp create mode 100644 plugins/Clist_modern/src/modern_skinopt.cpp create mode 100644 plugins/Clist_modern/src/modern_skinselector.cpp create mode 100644 plugins/Clist_modern/src/modern_statusbar.cpp create mode 100644 plugins/Clist_modern/src/modern_statusbar_options.cpp create mode 100644 plugins/Clist_modern/src/modern_sync.cpp create mode 100644 plugins/Clist_modern/src/modern_tbbutton.cpp create mode 100644 plugins/Clist_modern/src/modern_toolbar.cpp create mode 100644 plugins/Clist_modern/src/modern_viewmodebar.cpp create mode 100644 plugins/Clist_modern/src/modern_xptheme.cpp create mode 100644 plugins/Clist_modern/src/resource.h create mode 100644 plugins/Clist_modern/src/version.h (limited to 'plugins/Clist_modern/src') 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 +#include +#include +#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(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(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 + +#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::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::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 + +int __stdcall ChTraitsCRT::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::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 +#include +#include + +#ifdef __MINGW32__ +#include + +__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&() + { + return *(CMSimpleStringT*)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(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(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 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(size); + BOOL fSuccess=::CharToOemBuffA(pstrString, pstrString, dwSize); + } + + static void ConvertToAnsi( _CharType* pstrString, size_t size) + { + if(size>UINT_MAX) + return; + + DWORD dwSize=static_cast(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(ch)); + } + + static int __stdcall IsSpace( wchar_t ch ) + { + return iswspace( static_cast(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::Format(PCXSTR pszFormat, ... ) +{ + va_list argList; + va_start( argList, pszFormat ); + FormatV( pszFormat, argList ); + va_end( argList ); +} + +template< typename BaseType, class StringTraits > +inline void CMStringT::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 + +////////////////////////////////////////////////////////////////////////// +// 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 : 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 _callParams1 : 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 : 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 : 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 +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include + +#include "modern_global_structure.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "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.bSTATESTATE_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 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 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 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 + + +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 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 + +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 +#include +//#include + +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 ValueList_t; + typedef std::map 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 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 params( proc, a, b, c ); + DoCall((PSYNCCALLBACKPROC) PARAMS3::DoSyncCall, 0, (LPARAM) ¶ms ); + return params.GetResult(); +}; + + +// 2 params + +template 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 params( proc, a, b ); + DoCall((PSYNCCALLBACKPROC) PARAMS2::DoSyncCall, 0, (LPARAM) ¶ms ); + return params.GetResult(); +}; + + +// 1 param +template 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 params( proc, a ); + DoCall((PSYNCCALLBACKPROC) PARAMS1::DoSyncCall, 0, (LPARAM) ¶ms ); + 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)¶ms, 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 +__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 +//TODO: ADD HERE other definitions of part and states from +//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] + 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("")); RemoveTag(to,_T("")); + RemoveTag(to,_T("")); RemoveTag(to,_T("")); + RemoveTag(to,_T("")); RemoveTag(to,_T("")); + + 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("")); RemoveTag(to,_T("")); + RemoveTag(to,_T("")); RemoveTag(to,_T("")); + RemoveTag(to,_T("")); RemoveTag(to,_T("")); + 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 savedGroup( 4 ); + OBJLIST savedContact( 4 ); + OBJLIST 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 +#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,¶m,FALSE) && !param) + ret |= CLS_EX_NOSMOOTHSCROLLING; + if (SystemParametersInfo(SPI_GETHOTTRACKING,0,¶m,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( ¶m, dwParamHash, szValue, dwValueHash ); + _AddParameter( mpModernMask, ¶m ); +} +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 +#include +#include "hdr/modern_clist.h" +#include "hdr/modern_commonprototypes.h" +#include "hdr/modern_sync.h" +#include "hdr/modern_clui.h" +#include +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 +#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(¶m,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)¶m); + //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 +#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 +#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) ¶m, (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)¶m); + 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 + +#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(>aCS) +#define gtaunlock LeaveCriticalSection( >aCS ) + +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(>aCS); + 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(>aCS); +} 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)¶m); + //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)¶m); + //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 + +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 +#include +#include + + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#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, "", strlen(word))) cont = TC_ROW; + else if ( !_strnicmp(word, "", strlen(word))) cont = TC_COL; + else if ( !_strnicmp(word, "/>", strlen(word)) || + !_strnicmp(word, "", strlen(word)) || + !_strnicmp(word, "", 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(""); + { + //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 +#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 +#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 )¶m )) + 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 +#include +#include + +/*******************************/ +// 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* ¶m, 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]),¶m,sizeof(MASKPARAM)); + curParam++; + memset(¶m,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 = ≷ + 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 +#include + +#ifdef __MINGW32__ +#include +#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 +#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 -- cgit v1.2.3