summaryrefslogtreecommitdiff
path: root/plugins/Clist_modern/src/modern_cachefuncs.cpp
diff options
context:
space:
mode:
authorRozhuk Ivan <rozhuk.im@gmail.com>2014-11-27 00:44:57 +0000
committerRozhuk Ivan <rozhuk.im@gmail.com>2014-11-27 00:44:57 +0000
commit117cf2ba6883c5b3ff8b275f4c56eb562a219b95 (patch)
tree748e5d8b028b589151183452cbdb3306a7afa2c1 /plugins/Clist_modern/src/modern_cachefuncs.cpp
parentbd1e3d8fe219dcbc55584d95dfba6ddae0d01d2c (diff)
Clist_modern: code cleanup, review required
git-svn-id: http://svn.miranda-ng.org/main/trunk@11113 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/Clist_modern/src/modern_cachefuncs.cpp')
-rw-r--r--plugins/Clist_modern/src/modern_cachefuncs.cpp1804
1 files changed, 904 insertions, 900 deletions
diff --git a/plugins/Clist_modern/src/modern_cachefuncs.cpp b/plugins/Clist_modern/src/modern_cachefuncs.cpp
index 2caf524487..87fae9df20 100644
--- a/plugins/Clist_modern/src/modern_cachefuncs.cpp
+++ b/plugins/Clist_modern/src/modern_cachefuncs.cpp
@@ -1,900 +1,904 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (c) 2012-14 Miranda NG project (http://miranda-ng.org),
-Copyright (c) 2000-08 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) (ClcContact *contact, BOOL subcontact, void *param);
-
-
-/***********************************/
-/** Module static declarations **/
-/***********************************/
-
-/* Module Static Prototypes */
-
-static int CopySkipUnprintableChars(TCHAR *to, TCHAR * buf, DWORD size);
-
-static BOOL ExecuteOnAllContacts(ClcData *dat, ExecuteOnAllContactsFuncPtr func, void *param);
-static BOOL ExecuteOnAllContactsOfGroup(ClcGroup *group, ExecuteOnAllContactsFuncPtr func, void *param);
-int CLUI_SyncGetShortData(WPARAM wParam, LPARAM lParam);
-void CListSettings_FreeCacheItemData(ClcCacheEntry *pDst);
-void CListSettings_FreeCacheItemDataOption( ClcCacheEntry *pDst, DWORD flag );
-/*
- * Get time zone for contact
- */
-void Cache_GetTimezone(ClcData *dat, MCONTACT hContact)
-{
- ClcCacheEntry *pdnce = pcli->pfnGetCacheEntry(hContact);
- if (dat == NULL && pcli->hwndContactTree)
- dat = (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(hContact, 0, flags);
- }
-}
-
-/*
- * Get all lines of text
- */
-
-void Cache_GetText(ClcData *dat, ClcContact *contact, BOOL forceRenew)
-{
- Cache_GetFirstLineText(dat, contact);
- if (!dat->force_in_dialog) {
- ClcCacheEntry *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, ClcCacheEntry *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
- {
- 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;
-
- ICONINFO icon;
- if ( GetIconInfo(piece->smiley, &icon)) {
- BITMAP bm;
- 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, ClcCacheEntry *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 && strcmp(pdnce->m_cache_cszProto, META_PROTO) == 0) {
- MCONTACT hContact = db_mc_getMostOnline(pdnce->hContact);
- if (hContact != 0)
- sp.Protocolname = GetContactProto(hContact);
- }
- }
- 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, ClcCacheEntry *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 (!db_get_ts(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 = pcli->pfnGetStatusModeDescription(nStatus, 0);
- if (tmp && *tmp) {
- _tcsncpy_s(text, text_size, tmp, _TRUNCATE);
- return 1;
- }
-
- // Get XStatusName
- if (!noAwayMsg && !noXstatus && !xstatus_has_priority && pdnce->hContact && pdnce->m_cache_cszProto) {
- DBVARIANT dbv = { 0 };
- if (!db_get_ts(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusName", &dbv)) {
- 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, ClcCacheEntry *pdnce)
-{
- DBVARIANT dbv = { 0 };
- WORD wStatus = pdnce___GetStatus(pdnce);
- text[0] = _T('\0');
-
- if (wStatus == ID_STATUS_OFFLINE || wStatus == 0)
- return;
-
- if (!db_get_ts(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, ClcCacheEntry *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 (!db_get_ts(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 (!db_get_ts(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 (!db_get_ts(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(
- ClcCacheEntry *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 (!db_get_ts(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 (!db_get_ts(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 (!db_get_ts(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 (!db_get_ts(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(ClcData *dat, ClcContact *contact)
-{
- if (GetCurrentThreadId() != g_dwMainThreadID)
- return;
-
- ClcCacheEntry *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 (!db_get_ts(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, ClcCacheEntry *pdnce)
-{
- TCHAR Text[240-EXTRA_ICON_COUNT] = {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, ClcCacheEntry *pdnce)
-{
- TCHAR Text[240-EXTRA_ICON_COUNT] = {0};
- int type = TEXT_EMPTY;
- if (dat->third_line_show)
- type = Cache_GetLineText(pdnce, dat->third_line_type,(TCHAR*)Text, SIZEOF(Text), dat->third_line_text,
- dat->third_line_xstatus_has_priority,dat->third_line_show_status_if_no_away,dat->third_line_show_listening_if_no_away,
- dat->third_line_use_name_and_message_for_xstatus, dat->contact_time_show_only_if_different);
-
- Text[SIZEOF(Text)-1] = 0; //to be sure that it is null terminated string
-
- mir_free(pdnce->szThirdLineText);
-
- if (dat->third_line_show)//Text[0] != '\0')
- pdnce->szThirdLineText = mir_tstrdup((TCHAR*)Text);
- else
- pdnce->szThirdLineText = NULL;
-
- if (pdnce->szThirdLineText) {
- if (type == TEXT_LISTENING_TO && pdnce->szThirdLineText[0] != _T('\0'))
- pdnce->ssThirdLine.AddListeningToIcon(dat, pdnce, pdnce->szThirdLineText, dat->third_line_draw_smileys);
- else
- pdnce->ssThirdLine.ReplaceSmileys(dat, pdnce, pdnce->szThirdLineText, dat->third_line_draw_smileys);
- }
-}
-
-void RemoveTag(TCHAR *to, TCHAR *tag)
-{
- TCHAR *st = to;
- int len = (int)_tcslen(tag);
- int lastsize = (int)_tcslen(to)+1;
- while (st = _tcsstr(st,tag)) {
- lastsize -= len;
- memmove((void*)st,(void*)(st+len),(lastsize)*sizeof(TCHAR));
- }
-}
-
-/*
-* Copy string with removing Escape chars from text
-* And BBcodes
-*/
-static int CopySkipUnprintableChars(TCHAR *to, TCHAR * buf, DWORD size)
-{
- DWORD i;
- BOOL keep = 0;
- TCHAR * cp = to;
- if (!to) return 0;
- if (!buf) {
- to[0] = '\0';
- return 0;
- }
-
- for (i=0; i < size; i++) {
- if (buf[i] == 0) break;
- if (buf[i] > 0 && buf[i] < ' ') {
- *cp = ' ';
- if (!keep) cp++;
- keep = 1;
- }
- else {
- keep = 0;
- *cp = buf[i];
- cp++;
- }
- }
- *cp = 0;
-
- //remove bbcodes: [b] [i] [u] <b> <i> <u>
- RemoveTag(to,_T("[b]")); RemoveTag(to,_T("[/b]"));
- RemoveTag(to,_T("[u]")); RemoveTag(to,_T("[/u]"));
- RemoveTag(to,_T("[i]")); RemoveTag(to,_T("[/i]"));
-
- RemoveTag(to,_T("<b>")); RemoveTag(to,_T("</b>"));
- RemoveTag(to,_T("<u>")); RemoveTag(to,_T("</u>"));
- RemoveTag(to,_T("<i>")); RemoveTag(to,_T("</i>"));
-
- RemoveTag(to,_T("[B]")); RemoveTag(to,_T("[/b]"));
- RemoveTag(to,_T("[U]")); RemoveTag(to,_T("[/u]"));
- RemoveTag(to,_T("[I]")); RemoveTag(to,_T("[/i]"));
-
- RemoveTag(to,_T("<B>")); RemoveTag(to,_T("</B>"));
- RemoveTag(to,_T("<U>")); RemoveTag(to,_T("</U>"));
- RemoveTag(to,_T("<I>")); RemoveTag(to,_T("</I>"));
- return i;
-}
-
-// If ExecuteOnAllContactsFuncPtr returns FALSE, stop loop
-// Return TRUE if finished, FALSE if was stoped
-static BOOL ExecuteOnAllContacts(ClcData *dat, ExecuteOnAllContactsFuncPtr func, void *param)
-{
- BOOL res;
- res = ExecuteOnAllContactsOfGroup(&dat->list, func, param);
- return res;
-}
-
-static BOOL ExecuteOnAllContactsOfGroup(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(ClcContact *contact, BOOL subcontact, void *param)
-{
- Cache_GetAvatar((ClcData *)param, contact);
- return TRUE;
-}
-
-void UpdateAllAvatars(ClcData *dat)
-{
- ExecuteOnAllContacts(dat,UpdateAllAvatarsProxy,dat);
-}
-
-BOOL ReduceAvatarPosition(ClcContact *contact, BOOL subcontact, void *param)
-{
- if (contact->avatar_pos >= *((int *)param))
- contact->avatar_pos--;
-
- return TRUE;
-}
-
-void Cache_ProceedAvatarInList(ClcData *dat, 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 (wildcmpit(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;
- DrawAvatarImageWithGDIp(hdc, 0, 0, w, h,ace->hbmPic, 0, 0, ace->bmWidth,ace->bmHeight,ace->dwFlags,255);
- }
- 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(ClcData *dat, ClcContact *contact)
-{
- int old_pos = contact->avatar_pos;
- // workaround for avatar service and other wich destroys service on OK_TOEXIT
- if (g_CluiData.bSTATE != STATE_NORMAL || (dat->use_avatar_service && !ServiceExists(MS_AV_GETAVATARBITMAP))) {
- 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 (!db_get_ts(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);
- 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);
- 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 );
- }
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (c) 2012-14 Miranda NG project (http://miranda-ng.org),
+Copyright (c) 2000-08 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) (ClcContact *contact, BOOL subcontact, void *param);
+
+
+/***********************************/
+/** Module static declarations **/
+/***********************************/
+
+/* Module Static Prototypes */
+
+static int CopySkipUnprintableChars(TCHAR *to, TCHAR * buf, DWORD size);
+
+static BOOL ExecuteOnAllContacts(ClcData *dat, ExecuteOnAllContactsFuncPtr func, void *param);
+static BOOL ExecuteOnAllContactsOfGroup(ClcGroup *group, ExecuteOnAllContactsFuncPtr func, void *param);
+int CLUI_SyncGetShortData(WPARAM wParam, LPARAM lParam);
+void CListSettings_FreeCacheItemData(ClcCacheEntry *pDst);
+void CListSettings_FreeCacheItemDataOption( ClcCacheEntry *pDst, DWORD flag );
+/*
+ * Get time zone for contact
+ */
+void Cache_GetTimezone(ClcData *dat, MCONTACT hContact)
+{
+ ClcCacheEntry *pdnce = pcli->pfnGetCacheEntry(hContact);
+ if (dat == NULL && pcli->hwndContactTree)
+ dat = (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(hContact, 0, flags);
+ }
+}
+
+/*
+ * Get all lines of text
+ */
+
+void Cache_GetText(ClcData *dat, ClcContact *contact, BOOL forceRenew)
+{
+ Cache_GetFirstLineText(dat, contact);
+ if (!dat->force_in_dialog) {
+ ClcCacheEntry *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, ClcCacheEntry *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
+ {
+ 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;
+
+ ICONINFO icon;
+ if ( GetIconInfo(piece->smiley, &icon)) {
+ BITMAP bm;
+ 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, ClcCacheEntry *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 && strcmp(pdnce->m_cache_cszProto, META_PROTO) == 0) {
+ MCONTACT hContact = db_mc_getMostOnline(pdnce->hContact);
+ if (hContact != 0)
+ sp.Protocolname = GetContactProto(hContact);
+ }
+ }
+ 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, ClcCacheEntry *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 (!db_get_ts(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 = pcli->pfnGetStatusModeDescription(nStatus, 0);
+ if (tmp && *tmp) {
+ _tcsncpy_s(text, text_size, tmp, _TRUNCATE);
+ return 1;
+ }
+
+ // Get XStatusName
+ if (!noAwayMsg && !noXstatus && !xstatus_has_priority && pdnce->hContact && pdnce->m_cache_cszProto) {
+ DBVARIANT dbv = { 0 };
+ if (!db_get_ts(pdnce->hContact, pdnce->m_cache_cszProto, "XStatusName", &dbv)) {
+ 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, ClcCacheEntry *pdnce)
+{
+ DBVARIANT dbv = { 0 };
+ WORD wStatus = pdnce___GetStatus(pdnce);
+ text[0] = _T('\0');
+
+ if (wStatus == ID_STATUS_OFFLINE || wStatus == 0)
+ return;
+
+ if (!db_get_ts(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, ClcCacheEntry *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 (!db_get_ts(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 (!db_get_ts(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 (!db_get_ts(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(
+ ClcCacheEntry *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)
+{
+
+ if (text == NULL)
+ return TEXT_EMPTY;
+ 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 (!db_get_ts(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 (!db_get_ts(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 (!db_get_ts(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 (!db_get_ts(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(ClcData *dat, ClcContact *contact)
+{
+ if (GetCurrentThreadId() != g_dwMainThreadID)
+ return;
+
+ ClcCacheEntry *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 (!db_get_ts(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, ClcCacheEntry *pdnce)
+{
+ TCHAR Text[240-EXTRA_ICON_COUNT] = {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, ClcCacheEntry *pdnce)
+{
+ TCHAR Text[240-EXTRA_ICON_COUNT] = {0};
+ int type = TEXT_EMPTY;
+ if (dat->third_line_show)
+ type = Cache_GetLineText(pdnce, dat->third_line_type,(TCHAR*)Text, SIZEOF(Text), dat->third_line_text,
+ dat->third_line_xstatus_has_priority,dat->third_line_show_status_if_no_away,dat->third_line_show_listening_if_no_away,
+ dat->third_line_use_name_and_message_for_xstatus, dat->contact_time_show_only_if_different);
+
+ Text[SIZEOF(Text)-1] = 0; //to be sure that it is null terminated string
+
+ mir_free(pdnce->szThirdLineText);
+
+ if (dat->third_line_show)//Text[0] != '\0')
+ pdnce->szThirdLineText = mir_tstrdup((TCHAR*)Text);
+ else
+ pdnce->szThirdLineText = NULL;
+
+ if (pdnce->szThirdLineText) {
+ if (type == TEXT_LISTENING_TO && pdnce->szThirdLineText[0] != _T('\0'))
+ pdnce->ssThirdLine.AddListeningToIcon(dat, pdnce, pdnce->szThirdLineText, dat->third_line_draw_smileys);
+ else
+ pdnce->ssThirdLine.ReplaceSmileys(dat, pdnce, pdnce->szThirdLineText, dat->third_line_draw_smileys);
+ }
+}
+
+void RemoveTag(TCHAR *to, TCHAR *tag)
+{
+ TCHAR *st = to;
+ int len = (int)_tcslen(tag);
+ int lastsize = (int)_tcslen(to)+1;
+ while (st = _tcsstr(st,tag)) {
+ lastsize -= len;
+ memmove((void*)st,(void*)(st+len),(lastsize)*sizeof(TCHAR));
+ }
+}
+
+/*
+* Copy string with removing Escape chars from text
+* And BBcodes
+*/
+static int CopySkipUnprintableChars(TCHAR *to, TCHAR * buf, DWORD size)
+{
+ DWORD i;
+ BOOL keep = 0;
+ TCHAR * cp = to;
+ if (!to) return 0;
+ if (!buf) {
+ to[0] = '\0';
+ return 0;
+ }
+
+ for (i=0; i < size; i++) {
+ if (buf[i] == 0) break;
+ if (buf[i] > 0 && buf[i] < ' ') {
+ *cp = ' ';
+ if (!keep) cp++;
+ keep = 1;
+ }
+ else {
+ keep = 0;
+ *cp = buf[i];
+ cp++;
+ }
+ }
+ *cp = 0;
+
+ //remove bbcodes: [b] [i] [u] <b> <i> <u>
+ RemoveTag(to,_T("[b]")); RemoveTag(to,_T("[/b]"));
+ RemoveTag(to,_T("[u]")); RemoveTag(to,_T("[/u]"));
+ RemoveTag(to,_T("[i]")); RemoveTag(to,_T("[/i]"));
+
+ RemoveTag(to,_T("<b>")); RemoveTag(to,_T("</b>"));
+ RemoveTag(to,_T("<u>")); RemoveTag(to,_T("</u>"));
+ RemoveTag(to,_T("<i>")); RemoveTag(to,_T("</i>"));
+
+ RemoveTag(to,_T("[B]")); RemoveTag(to,_T("[/b]"));
+ RemoveTag(to,_T("[U]")); RemoveTag(to,_T("[/u]"));
+ RemoveTag(to,_T("[I]")); RemoveTag(to,_T("[/i]"));
+
+ RemoveTag(to,_T("<B>")); RemoveTag(to,_T("</B>"));
+ RemoveTag(to,_T("<U>")); RemoveTag(to,_T("</U>"));
+ RemoveTag(to,_T("<I>")); RemoveTag(to,_T("</I>"));
+ return i;
+}
+
+// If ExecuteOnAllContactsFuncPtr returns FALSE, stop loop
+// Return TRUE if finished, FALSE if was stoped
+static BOOL ExecuteOnAllContacts(ClcData *dat, ExecuteOnAllContactsFuncPtr func, void *param)
+{
+ BOOL res;
+ res = ExecuteOnAllContactsOfGroup(&dat->list, func, param);
+ return res;
+}
+
+static BOOL ExecuteOnAllContactsOfGroup(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(ClcContact *contact, BOOL subcontact, void *param)
+{
+ Cache_GetAvatar((ClcData *)param, contact);
+ return TRUE;
+}
+
+void UpdateAllAvatars(ClcData *dat)
+{
+ ExecuteOnAllContacts(dat,UpdateAllAvatarsProxy,dat);
+}
+
+BOOL ReduceAvatarPosition(ClcContact *contact, BOOL subcontact, void *param)
+{
+ if (contact->avatar_pos >= *((int *)param))
+ contact->avatar_pos--;
+
+ return TRUE;
+}
+
+void Cache_ProceedAvatarInList(ClcData *dat, 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 (wildcmpit(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;
+ DrawAvatarImageWithGDIp(hdc, 0, 0, w, h,ace->hbmPic, 0, 0, ace->bmWidth,ace->bmHeight,ace->dwFlags,255);
+ }
+ 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(ClcData *dat, ClcContact *contact)
+{
+ int old_pos = contact->avatar_pos;
+ // workaround for avatar service and other wich destroys service on OK_TOEXIT
+ if (g_CluiData.bSTATE != STATE_NORMAL || (dat->use_avatar_service && !ServiceExists(MS_AV_GETAVATARBITMAP))) {
+ 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 (!db_get_ts(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);
+ 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);
+ 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 );
+ }
+}