From 48540940b6c28bb4378abfeb500ec45a625b37b6 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 15 May 2012 10:38:20 +0000 Subject: initial commit git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/modernb/modern_cachefuncs.cpp | 1115 +++++++++++++++++++++++++++++++++ 1 file changed, 1115 insertions(+) create mode 100644 plugins/modernb/modern_cachefuncs.cpp (limited to 'plugins/modernb/modern_cachefuncs.cpp') diff --git a/plugins/modernb/modern_cachefuncs.cpp b/plugins/modernb/modern_cachefuncs.cpp new file mode 100644 index 0000000000..eee59c82f0 --- /dev/null +++ b/plugins/modernb/modern_cachefuncs.cpp @@ -0,0 +1,1115 @@ +/* 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)// && !dat->isStarting) + { + 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, PDNCE pdnce, TCHAR *szText, BOOL replace_smileys) +{ + iMaxSmileyHeight = 0; + DestroySmileyList(); + + if (szText == NULL) return; + + int text_size = (int)_tcslen( szText ); + + plText = li.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); + + li.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; + li.List_Insert( plText, piece, plText->realCount); + } +} + +void CSmileyString::_CopySmileyList( SortedList *plInput ) +{ +// ASSERT( plText == NULL ); + + if ( !plInput || plInput->realCount == 0 ) return; + plText=li.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 ); + li.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 ) + { + int i; + for ( 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); + } + } + } + li.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 (ModernGetSettingByte(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->m_cache_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); + + if (spr == NULL || (INT_PTR)spr == CALLSERVICE_NOTFOUND) + { + // Did not find a simley + return; + } + + // Lets add smileys + plText = li.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; + li.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 ); + + li.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; + + li.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->m_cache_hContact && pdnce->m_cache_cszProto) + { + DBVARIANT dbv={0}; + if (!ModernGetSettingTString(pdnce->m_cache_hContact, pdnce->m_cache_cszProto, "XStatusName", &dbv)) + { + //lstrcpyn(text, dbv.pszVal, text_size); + CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1); + ModernDBFreeVariant(&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->m_cache_hContact && pdnce->m_cache_cszProto) + { + DBVARIANT dbv={0}; + if (!ModernGetSettingTString(pdnce->m_cache_hContact, pdnce->m_cache_cszProto, "XStatusName", &dbv)) + { + //lstrcpyn(text, dbv.pszVal, text_size); + CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1); + ModernDBFreeVariant(&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 (!ModernGetSettingTString(pdnce->m_cache_hContact, pdnce->m_cache_cszProto, "ListeningTo", &dbv)) + { + CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1); + ModernDBFreeVariant(&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->m_cache_hContact && pdnce->m_cache_cszProto) + { + // Try to get XStatusMsg + if (!ModernGetSettingTString(pdnce->m_cache_hContact, pdnce->m_cache_cszProto, "XStatusMsg", &dbv)) + { + //lstrcpyn(text, dbv.pszVal, text_size); + CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1); + ModernDBFreeVariant(&dbv); + + if (text[0] != '\0') + return -1; + } + } + + // Get StatusMsg + if (pdnce->m_cache_hContact && text[0] == '\0') + { + if (!ModernGetSettingTString(pdnce->m_cache_hContact, "CList", "StatusMsg", &dbv)) + { + //lstrcpyn(text, dbv.pszVal, text_size); + CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1); + ModernDBFreeVariant(&dbv); + + if (text[0] != '\0') + return 1; + } + } + + // Get XStatusMsg + if (!noAwayMsg && !xstatus_has_priority && pdnce->m_cache_hContact && pdnce->m_cache_cszProto && text[0] == '\0') + { + // Try to get XStatusMsg + if (!ModernGetSettingTString(pdnce->m_cache_hContact, pdnce->m_cache_cszProto, "XStatusMsg", &dbv)) + { + //lstrcpyn(text, dbv.pszVal, text_size); + CopySkipUnprintableChars(text, dbv.ptszVal, text_size-1); + ModernDBFreeVariant(&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 (!ModernGetSettingTString(pdnce->m_cache_hContact, pdnce->m_cache_cszProto, "XStatusMsg", &dbv)) + { + if (dbv.ptszVal != NULL && dbv.ptszVal[0] != 0) + { + TCHAR *tmp = mir_tstrdup(text); + mir_sntprintf(text, text_size, TEXT("%s: %s"), tmp, dbv.pszVal); + mir_free_and_nill(tmp); + CopySkipUnprintableChars(text, text, text_size-1); + } + ModernDBFreeVariant(&dbv); + } + } + + return TEXT_STATUS; + } + case TEXT_NICKNAME: + { + if (pdnce->m_cache_hContact && pdnce->m_cache_cszProto) + { + DBVARIANT dbv={0}; + if (!ModernGetSettingTString(pdnce->m_cache_hContact, pdnce->m_cache_cszProto, "Nick", &dbv)) + { + lstrcpyn(text, dbv.ptszVal, text_size); + ModernDBFreeVariant(&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 (!ModernGetSettingTString(pdnce->m_cache_hContact, pdnce->m_cache_cszProto, "XStatusName", &dbv)) + { + if (dbv.pszVal != NULL && dbv.pszVal[0] != 0) + { + TCHAR *tmp = mir_tstrdup(text); + + mir_sntprintf(text, text_size, TEXT("%s: %s"), dbv.pszVal, tmp); + mir_free_and_nill(tmp); + } + CopySkipUnprintableChars(text, text, text_size-1); + ModernDBFreeVariant(&dbv); + } + } + else if (use_name_and_message_for_xstatus && xstatus_has_priority) + { + DBVARIANT dbv={0}; + // Try to get XStatusName + if (!ModernGetSettingTString(pdnce->m_cache_hContact, pdnce->m_cache_cszProto, "XStatusName", &dbv)) + { + if (dbv.pszVal != NULL && dbv.pszVal[0] != 0) + mir_sntprintf(text, text_size, TEXT("%s"), dbv.pszVal); + CopySkipUnprintableChars(text, text, text_size-1); + ModernDBFreeVariant(&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->m_cache_tcsName, pdnce->m_cache_hContact); + lstrcpyn(text, tmp, text_size); + if (tmp) 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 (!ModernGetSettingTString(pdnce->m_cache_hContact, pdnce->m_cache_cszProto, "Nick", &dbv)) + { + TCHAR nick[SIZEOF(contact->szText)]; + lstrcpyn(nick, dbv.ptszVal, SIZEOF(contact->szText)); + ModernDBFreeVariant(&dbv); + + if (_tcsnicmp(name, nick, lstrlen(name)) == 0) { + // They are the same -> use the nick to keep the case + lstrcpyn(contact->szText, nick, SIZEOF(contact->szText)); + } else if (_tcsnicmp(name, nick, lstrlen(nick)) == 0) { + // They are the same -> use the nick to keep the case + 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]=_T('\0'); //to be sure that it is null terminated string + //LockCacheItem(hContact, __FILE__,__LINE__); + + if (pdnce->szSecondLineText) 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); + } + } + //UnlockCacheItem(hContact); +} + +/* +* 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); + + // LockCacheItem(hContact, __FILE__,__LINE__); + Text[SIZEOF(Text)-1]=_T('\0'); //to be sure that it is null terminated string + + if (pdnce->szThirdLineText) 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); + } + } + // UnlockCacheItem(hContact); +} + + +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; i0 && 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) +{ + int scanIndex, i; + if (group) + for(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 (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 + { + HDC hdc; + HBITMAP hDrawBmp,oldBmp; + void * pt; + + // 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"))) + { + int res; + if (old_pos==AVATAR_POS_ANIMATED) + AniAva_RemoveAvatar(contact->hContact); + + 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 + hdc = CreateCompatibleDC(dat->avatar_cache.hdc); + hDrawBmp = ske_CreateDIB32Point(width_clip, height_clip,&pt); + oldBmp=(HBITMAP)SelectObject(hdc, hDrawBmp); + //need to draw avatar bitmap here + { + RECT real_rc={0,0,width_clip, height_clip}; + /* + if (ServiceExists(MS_AV_BLENDDRAWAVATAR)) + { + AVATARDRAWREQUEST adr; + + adr.cbSize = sizeof(AVATARDRAWREQUEST); + adr.hContact = contact->hContact; + adr.hTargetDC = hdc; + adr.rcDraw = real_rc; + adr.dwFlags = 0; + adr.alpha = 255; + CallService(MS_AV_BLENDDRAWAVATAR, 0, (LPARAM) &adr); + } + else + */ + { + 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 && !ModernGetSettingByte(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 && !ModernGetSettingByte(contact->hContact, "CList", "HideContactAvatar", 0)) + { + DBVARIANT dbv; + if (!ModernGetSettingTString(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) + } + ModernDBFreeVariant(&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 ); + } + } +} + + + -- cgit v1.2.3