From 2ad9dacc6b572b8a2d7d925668cae10abec5ef95 Mon Sep 17 00:00:00 2001 From: Tobias Weimer Date: Thu, 24 Mar 2016 21:07:55 +0000 Subject: CList_modern: cleanup git-svn-id: http://svn.miranda-ng.org/main/trunk@16537 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Clist_modern/src/cluiframes.cpp | 9 +- plugins/Clist_modern/src/modern_cachefuncs.cpp | 39 +- plugins/Clist_modern/src/modern_clc.cpp | 3704 +++++++++++----------- plugins/Clist_modern/src/modern_clcitems.cpp | 1479 +++++---- plugins/Clist_modern/src/modern_clcmsgs.cpp | 3 +- plugins/Clist_modern/src/modern_clcpaint.cpp | 8 +- plugins/Clist_modern/src/modern_skinselector.cpp | 10 +- plugins/Clist_modern/src/modern_skinselector.h | 7 - 8 files changed, 2626 insertions(+), 2633 deletions(-) (limited to 'plugins/Clist_modern') diff --git a/plugins/Clist_modern/src/cluiframes.cpp b/plugins/Clist_modern/src/cluiframes.cpp index fd8987d36e..4356d59893 100644 --- a/plugins/Clist_modern/src/cluiframes.cpp +++ b/plugins/Clist_modern/src/cluiframes.cpp @@ -2439,14 +2439,7 @@ void DrawBackGround(HWND hwnd, HDC mhdc, HBITMAP hBmpBackground, COLORREF bkColo } break; case CLB_STRETCHH: - if (backgroundBmpUse & CLBF_PROPORTIONAL) { - destw = clRect.right; - //desth = destw*bmp.bmHeight / bmp.bmWidth; - } - else { - destw = clRect.right; - //desth = bmp.bmHeight; - } + destw = clRect.right; break; case CLB_STRETCHV: if (backgroundBmpUse & CLBF_PROPORTIONAL) { diff --git a/plugins/Clist_modern/src/modern_cachefuncs.cpp b/plugins/Clist_modern/src/modern_cachefuncs.cpp index f6451f1849..ebf7b25640 100644 --- a/plugins/Clist_modern/src/modern_cachefuncs.cpp +++ b/plugins/Clist_modern/src/modern_cachefuncs.cpp @@ -2,7 +2,7 @@ Miranda NG: the free IM client for Microsoft* Windows* -Copyright (ñ) 2012-16 Miranda NG project (http://miranda-ng.org), +Copyright (c) 2012-16 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. @@ -49,7 +49,7 @@ void CListSettings_FreeCacheItemDataOption(ClcCacheEntry *pDst, DWORD flag); ///////////////////////////////////////////////////////////////////////////////////////// // Get time zone for contact - +// void Cache_GetTimezone(ClcData *dat, MCONTACT hContact) { ClcCacheEntry *pdnce = pcli->pfnGetCacheEntry(hContact); @@ -64,7 +64,7 @@ void Cache_GetTimezone(ClcData *dat, MCONTACT hContact) ///////////////////////////////////////////////////////////////////////////////////////// // Get all lines of text - +// void Cache_GetText(ClcData *dat, ClcContact *contact, BOOL forceRenew) { Cache_GetFirstLineText(dat, contact); @@ -173,7 +173,7 @@ void CSmileyString::DestroySmileyList() ///////////////////////////////////////////////////////////////////////////////////////// // Parsing of text for smiley - +// void CSmileyString::ReplaceSmileys(SHORTDATA *dat, ClcCacheEntry *pdnce, TCHAR * szText, BOOL replace_smileys) { int last_pos = 0; @@ -273,7 +273,7 @@ void CSmileyString::ReplaceSmileys(SHORTDATA *dat, ClcCacheEntry *pdnce, TCHAR * ///////////////////////////////////////////////////////////////////////////////////////// // Getting Status name // returns -1 for XStatus, 1 for Status - +// int GetStatusName(TCHAR *text, int text_size, ClcCacheEntry *pdnce, BOOL xstatus_has_priority) { BOOL noAwayMsg = FALSE; @@ -320,7 +320,7 @@ int GetStatusName(TCHAR *text, int text_size, ClcCacheEntry *pdnce, BOOL xstatus ///////////////////////////////////////////////////////////////////////////////////////// // Get Listening to information - +// void GetListeningTo(TCHAR *text, int text_size, ClcCacheEntry *pdnce) { *text = _T('\0'); @@ -336,7 +336,7 @@ void GetListeningTo(TCHAR *text, int text_size, ClcCacheEntry *pdnce) ///////////////////////////////////////////////////////////////////////////////////////// // Getting Status message(Away message) // returns -1 for XStatus, 1 for Status - +// int GetStatusMessage(TCHAR *text, int text_size, ClcCacheEntry *pdnce, BOOL xstatus_has_priority) { BOOL noAwayMsg = FALSE; @@ -383,7 +383,7 @@ int GetStatusMessage(TCHAR *text, int text_size, ClcCacheEntry *pdnce, BOOL xsta ///////////////////////////////////////////////////////////////////////////////////////// // 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, @@ -423,15 +423,16 @@ int Cache_GetLineText( if (tszXStatusName != NULL && tszXStatusName[0] != 0) { TCHAR *tmp = NEWTSTR_ALLOCA(text); mir_sntprintf(text, text_size, _T("%s: %s"), tszXStatusName, tmp); + CopySkipUnprintableChars(text, text, text_size - 1); } - CopySkipUnprintableChars(text, text, text_size - 1); } else if (use_name_and_message_for_xstatus && xstatus_has_priority) { // Try to get XStatusName ptrT tszXStatusName(db_get_tsa(pdnce->hContact, pdnce->m_pszProto, "XStatusName")); - if (tszXStatusName != NULL && tszXStatusName[0] != 0) + if (tszXStatusName != NULL && tszXStatusName[0] != 0) { mir_tstrncpy(text, tszXStatusName, text_size); - CopySkipUnprintableChars(text, text, text_size - 1); + CopySkipUnprintableChars(text, text, text_size - 1); + } } if (text[0] == '\0') { @@ -470,9 +471,9 @@ int Cache_GetLineText( return TEXT_EMPTY; } -/* -* Get the text for First Line -*/ +///////////////////////////////////////////////////////////////////////////////////////// +// Get the text for First Line +// void Cache_GetFirstLineText(ClcData *dat, ClcContact *contact) { if (GetCurrentThreadId() != g_dwMainThreadID) @@ -506,7 +507,7 @@ void Cache_GetFirstLineText(ClcData *dat, ClcContact *contact) ///////////////////////////////////////////////////////////////////////////////////////// // Get the text for Second Line - +// void Cache_GetSecondLineText(SHORTDATA *dat, ClcCacheEntry *pdnce) { TCHAR Text[240 - EXTRA_ICON_COUNT] = { 0 }; @@ -531,7 +532,7 @@ void Cache_GetSecondLineText(SHORTDATA *dat, ClcCacheEntry *pdnce) ///////////////////////////////////////////////////////////////////////////////////////// // Get the text for Third Line - +// void Cache_GetThirdLineText(SHORTDATA *dat, ClcCacheEntry *pdnce) { TCHAR Text[240 - EXTRA_ICON_COUNT] = { 0 }; @@ -565,7 +566,7 @@ void RemoveTag(TCHAR *to, TCHAR *tag) ///////////////////////////////////////////////////////////////////////////////////////// //Copy string with removing Escape chars from text and BBcodes - +// static int CopySkipUnprintableChars(TCHAR *to, TCHAR * buf, DWORD size) { DWORD i; @@ -611,8 +612,10 @@ static int CopySkipUnprintableChars(TCHAR *to, TCHAR * buf, DWORD size) 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) { return ExecuteOnAllContactsOfGroup(&dat->list, func, param); @@ -644,7 +647,7 @@ static BOOL ExecuteOnAllContactsOfGroup(ClcGroup *group, ExecuteOnAllContactsFun ///////////////////////////////////////////////////////////////////////////////////////// // Avatar working routines - +// BOOL UpdateAllAvatarsProxy(ClcContact *contact, BOOL, void *param) { Cache_GetAvatar((ClcData *)param, contact); diff --git a/plugins/Clist_modern/src/modern_clc.cpp b/plugins/Clist_modern/src/modern_clc.cpp index 8f62018a4f..5b79dede54 100644 --- a/plugins/Clist_modern/src/modern_clc.cpp +++ b/plugins/Clist_modern/src/modern_clc.cpp @@ -1,1855 +1,1855 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-16 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. -*/ - -/************************************************************************/ -/* Module responsible for working with contact list control */ -/************************************************************************/ - -#include "stdafx.h" -#include "m_skin.h" -#include "modern_commonprototypes.h" - -#include "modern_clc.h" -#include "modern_clist.h" -#include "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; -static BOOL g_bSortTimerIsSet = FALSE; -static ClcContact *hitcontact = NULL; -HANDLE hSkinFolder; -TCHAR SkinsFolder[MAX_PATH]; - -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(); - - -int ReloadSkinFolder(WPARAM, LPARAM) -{ - FoldersGetCustomPathT(hSkinFolder, SkinsFolder, _countof(SkinsFolder), _T(DEFAULT_SKIN_FOLDER)); - return 0; -} - -static int clcHookSmileyAddOptionsChanged(WPARAM, 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(wParam, (ACKDATA*)lParam); -} - -static int clcHookIconsChanged(WPARAM, LPARAM) -{ - int i; - if (MirandaExiting()) return 0; - for (i = 0; i < _countof(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, _countof(g_pAvatarOverlayIcons) * 2, 1); - - for (i = 0; i < _countof(g_pAvatarOverlayIcons); i++) { - HICON hIcon = IcoLib_GetIcon(g_pAvatarOverlayIcons[i].name); - g_pAvatarOverlayIcons[i].listID = ImageList_AddIcon(hAvatarOverlays, hIcon); - IcoLib_Release(g_pAvatarOverlayIcons[i].name); - - hIcon = IcoLib_GetIcon(g_pStatusOverlayIcons[i].name); - g_pStatusOverlayIcons[i].listID = ImageList_AddIcon(hAvatarOverlays, hIcon); - IcoLib_Release(g_pStatusOverlayIcons[i].name); - } - - g_hListeningToIcon = IcoLib_GetIcon("LISTENING_TO_ICON"); - - pcli->pfnClcBroadcast(INTM_INVALIDATE, 0, 0); - AniAva_UpdateOptions(); - return 0; -} - -static int clcMetaModeChanged(WPARAM, LPARAM) -{ - pcli->pfnClcBroadcast(INTM_RELOADOPTIONS, 0, 0); - return 0; -} - -static int clcMetacontactChanged(WPARAM, LPARAM) -{ - pcli->pfnClcBroadcast(INTM_NAMEORDERCHANGED, 0, 0); - return 0; -} - -static int clcHookSettingChanged(WPARAM hContact, LPARAM lParam) -{ - if (MirandaExiting()) - return 0; - - DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam; - if (hContact == NULL) { - if (!strcmp(cws->szModule, "CListGroups")) - pcli->pfnClcBroadcast(INTM_GROUPSCHANGED, hContact, lParam); - else if (!strcmp(cws->szSetting, "XStatusId") || !strcmp(cws->szSetting, "XStatusName")) - cliCluiProtocolStatusChanged(0, cws->szModule); - else if (!strcmp(cws->szModule, "CList")) { +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (c) 2012-16 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. +*/ + +/************************************************************************/ +/* Module responsible for working with contact list control */ +/************************************************************************/ + +#include "stdafx.h" +#include "m_skin.h" +#include "modern_commonprototypes.h" + +#include "modern_clc.h" +#include "modern_clist.h" +#include "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; +static BOOL g_bSortTimerIsSet = FALSE; +static ClcContact *hitcontact = NULL; +HANDLE hSkinFolder; +TCHAR SkinsFolder[MAX_PATH]; + +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(); + + +int ReloadSkinFolder(WPARAM, LPARAM) +{ + FoldersGetCustomPathT(hSkinFolder, SkinsFolder, _countof(SkinsFolder), _T(DEFAULT_SKIN_FOLDER)); + return 0; +} + +static int clcHookSmileyAddOptionsChanged(WPARAM, 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(wParam, (ACKDATA*)lParam); +} + +static int clcHookIconsChanged(WPARAM, LPARAM) +{ + int i; + if (MirandaExiting()) return 0; + for (i = 0; i < _countof(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, _countof(g_pAvatarOverlayIcons) * 2, 1); + + for (i = 0; i < _countof(g_pAvatarOverlayIcons); i++) { + HICON hIcon = IcoLib_GetIcon(g_pAvatarOverlayIcons[i].name); + g_pAvatarOverlayIcons[i].listID = ImageList_AddIcon(hAvatarOverlays, hIcon); + IcoLib_Release(g_pAvatarOverlayIcons[i].name); + + hIcon = IcoLib_GetIcon(g_pStatusOverlayIcons[i].name); + g_pStatusOverlayIcons[i].listID = ImageList_AddIcon(hAvatarOverlays, hIcon); + IcoLib_Release(g_pStatusOverlayIcons[i].name); + } + + g_hListeningToIcon = IcoLib_GetIcon("LISTENING_TO_ICON"); + + pcli->pfnClcBroadcast(INTM_INVALIDATE, 0, 0); + AniAva_UpdateOptions(); + return 0; +} + +static int clcMetaModeChanged(WPARAM, LPARAM) +{ + pcli->pfnClcBroadcast(INTM_RELOADOPTIONS, 0, 0); + return 0; +} + +static int clcMetacontactChanged(WPARAM, LPARAM) +{ + pcli->pfnClcBroadcast(INTM_NAMEORDERCHANGED, 0, 0); + return 0; +} + +static int clcHookSettingChanged(WPARAM hContact, LPARAM lParam) +{ + if (MirandaExiting()) + return 0; + + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam; + if (hContact == NULL) { + if (!strcmp(cws->szModule, "CListGroups")) + pcli->pfnClcBroadcast(INTM_GROUPSCHANGED, hContact, lParam); + else if (!strcmp(cws->szSetting, "XStatusId") || !strcmp(cws->szSetting, "XStatusName")) + cliCluiProtocolStatusChanged(0, cws->szModule); + else if (!strcmp(cws->szModule, "CList")) { if (!strcmp(cws->szSetting, "OnTop")) SetWindowPos(pcli->hwndContactList, cws->value.bVal ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); } - } - else { - if (!strcmp(cws->szSetting, "TickTS")) - pcli->pfnClcBroadcast(INTM_STATUSCHANGED, hContact, 0); - else if (!strcmp(cws->szModule, "UserInfo")) { - if (!strcmp(cws->szSetting, "Timezone")) - pcli->pfnClcBroadcast(INTM_TIMEZONECHANGED, hContact, 0); - } - else if (!strcmp(cws->szModule, "CList")) { - if (!strcmp(cws->szSetting, "StatusMsg")) - pcli->pfnClcBroadcast(INTM_STATUSMSGCHANGED, hContact, 0); - } - else if (!strcmp(cws->szModule, "ContactPhoto")) { - if (!strcmp(cws->szSetting, "File")) - pcli->pfnClcBroadcast(INTM_AVATARCHANGED, hContact, 0); - } - else { - if ((!strcmp(cws->szSetting, "XStatusName") || !strcmp(cws->szSetting, "XStatusMsg"))) - pcli->pfnClcBroadcast(INTM_STATUSMSGCHANGED, hContact, 0); - else if (!strcmp(cws->szSetting, "XStatusId")) - pcli->pfnClcBroadcast(INTM_STATUSCHANGED, hContact, 0); - else if (!strcmp(cws->szSetting, "Timezone")) - pcli->pfnClcBroadcast(INTM_TIMEZONECHANGED, hContact, 0); - else if (!strcmp(cws->szSetting, "ListeningTo")) - pcli->pfnClcBroadcast(INTM_STATUSMSGCHANGED, hContact, 0); - else if (!strcmp(cws->szSetting, "Transport") || !strcmp(cws->szSetting, "IsTransported")) { - pcli->pfnInvalidateDisplayNameCacheEntry(hContact); - pcli->pfnClcBroadcast(CLM_AUTOREBUILD, hContact, 0); - } - } - } - return 0; -} - -static int clcHookDbEventAdded(WPARAM hContact, LPARAM lParam) -{ - g_CluiData.t_now = time(NULL); - if (hContact && lParam) { - DBEVENTINFO dbei = { sizeof(dbei) }; - db_event_get(lParam, &dbei); - if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) { - db_set_dw(hContact, "CList", "mf_lastmsg", dbei.timestamp); - ClcCacheEntry *pdnce = pcli->pfnGetCacheEntry(hContact); - if (pdnce) - pdnce->dwLastMsgTime = dbei.timestamp; - } - } - return 0; -} - -static int clcHookBkgndConfigChanged(WPARAM, 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, ClcData *dat, int index, const TCHAR *text, int prefixOk, BOOL fSearchUp) -{ - ClcGroup *group = &dat->list; - int testlen = (int)mir_tstrlen(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) { - bool found; - if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) { - found = true; - } - else if (dat->filterSearch) { - TCHAR *lowered_szText = CharLowerW(NEWTSTR_ALLOCA(group->cl.items[group->scanIndex]->szText)); - TCHAR *lowered_search = CharLowerW(NEWTSTR_ALLOCA(dat->szQuickSearch)); - found = _tcsstr(lowered_szText, lowered_search) != NULL; - } - else { - found = ((prefixOk && CSTR_EQUAL == CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, text, -1, group->cl.items[group->scanIndex]->szText, testlen)) || (!prefixOk && !mir_tstrcmpi(text, group->cl.items[group->scanIndex]->szText))); - } - if (found) { - 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(ClcGroup *group, ClcContact *contact) -{ - if (g_CluiData.bFilterEffective) return FALSE; - - if (!contact) return FALSE; - ClcCacheEntry *pdnce = pcli->pfnGetCacheEntry(contact->hContact); - if (!pdnce) return FALSE; - if (pdnce->m_bNoHiddenOffline) return TRUE; - - if (!group) return FALSE; - if (group->hideOffline) return FALSE; - - if (CLCItems_IsShowOfflineGroup(group)) return TRUE; - - return FALSE; -} - -static LRESULT clcOnCreate(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - dat = (ClcData*)mir_calloc(sizeof(ClcData)); - SetWindowLongPtr(hwnd, 0, (LONG_PTR)dat); - dat->hCheckBoxTheme = xpt_AddThemeHandle(hwnd, L"BUTTON"); - dat->m_paintCouter = 0; - dat->hWnd = hwnd; - - ImageArray_Initialize(&dat->avatar_cache, FALSE, 20); //this array will be used to keep small avatars too - - RowHeights_Initialize(dat); - - dat->needsResort = 1; - dat->MetaIgnoreEmptyExtra = db_get_b(NULL, "CLC", "MetaIgnoreEmptyExtra", SETTING_METAIGNOREEMPTYEXTRA_DEFAULT); - - dat->IsMetaContactsEnabled = (!(GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_MANUALUPDATE)) && db_mc_isEnabled(); - - 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; - - corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); - LoadCLCOptions(hwnd, dat, TRUE); - 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); - - TRACE("Create New ClistControl TO END\r\n"); - return 0; -} - -static LRESULT clcOnHitTest(ClcData *, HWND hwnd, UINT, WPARAM wParam, LPARAM lParam) -{ - return DefWindowProc(hwnd, WM_NCHITTEST, wParam, lParam); -} - -static LRESULT clcOnCommand(ClcData *dat, HWND hwnd, UINT, WPARAM wParam, LPARAM lParam) -{ - ClcContact *contact; - int hit = pcli->pfnGetRowByIndex(dat, dat->selection, &contact, NULL); - if (hit != -1) { - switch (LOWORD(wParam)) { - case POPUP_NEWSUBGROUP: - if (contact->type == CLCIT_GROUP) { - 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_GROUPSHOWOFFLINE: - if (contact->type == CLCIT_GROUP) { - CallService(MS_CLIST_GROUPSETFLAGS, contact->groupId, MAKELPARAM(CLCItems_IsShowOfflineGroup(contact->group) ? 0 : GROUPF_SHOWOFFLINE, GROUPF_SHOWOFFLINE)); - pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0); - } - return 0; - } - } - - return corecli.pfnContactListControlWndProc(hwnd, WM_COMMAND, wParam, lParam); -} - -static LRESULT clcOnSize(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) { - RECT rc = { 0 }; - GetClientRect(hwnd, &rc); - if (rc.right == 0) - return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); - - rc.bottom = max(dat->row_min_heigh, 1); - - HDC hdc = GetDC(hwnd); - int depth = GetDeviceCaps(hdc, BITSPIXEL); - if (depth < 16) - depth = 16; - HBITMAP hBmp = CreateBitmap(rc.right, rc.bottom, 1, depth, NULL); - HBITMAP hBmpMask = CreateBitmap(rc.right, rc.bottom, 1, 1, NULL); - HDC hdcMem = CreateCompatibleDC(hdc); - HBITMAP hoBmp = (HBITMAP)SelectObject(hdcMem, hBmp); - HBRUSH hBrush = CreateSolidBrush((dat->useWindowsColours || dat->force_in_dialog) ? GetSysColor(COLOR_HIGHLIGHT) : dat->selBkColour); - FillRect(hdcMem, &rc, hBrush); - DeleteObject(hBrush); - - HBITMAP 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, ILC_COLOR32 | 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(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(); - } - return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); -} -static LRESULT clcOnPaint(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (IsWindowVisible(hwnd)) { - if (!g_CluiData.fLayered || GetParent(hwnd) != pcli->hwndContactList) { - PAINTSTRUCT ps; - HDC 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(ClcData *, HWND, UINT, WPARAM, LPARAM) -{ - return 1; -} - -static LRESULT clcOnKeyDown(ClcData *dat, HWND hwnd, UINT, WPARAM wParam, LPARAM lParam) -{ - 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); - int pageSize = (dat->rowHeight) ? clRect.bottom / dat->rowHeight : 0; - int selMoved = 0; - int changeGroupExpand = 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; - } - - dat->selection = index; - pcli->pfnInvalidateRect(hwnd, NULL, FALSE); - pcli->pfnEnsureVisible(hwnd, dat, dat->selection, 0); - return 0; - } - - 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); - dat->szQuickSearch[0] = 0; - if (dat->filterSearch) - pcli->pfnSaveStateAndRebuildList(hwnd, dat); - 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) { - ClcContact *contact; - ClcGroup *group; - int hit = cliGetRowByIndex(dat, dat->selection, &contact, &group); - if (hit == -1) { - SetCapture(hwnd); - return 0; - } - - 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 - ClcContact *ht = NULL; - KillTimer(hwnd, TIMERID_SUBEXPAND); - contact->SubExpanded = 0; - db_set_b(contact->hContact, "CList", "Expanded", 0); - ht = contact; - dat->needsResort = 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) { - ClcContact *ht = NULL; - KillTimer(hwnd, TIMERID_SUBEXPAND); - contact->SubExpanded = 1; - db_set_b(contact->hContact, "CList", "Expanded", 1); - ht = contact; - dat->needsResort = 1; - pcli->pfnSortCLC(hwnd, dat, 1); - cliRecalcScrollBar(hwnd, dat); - if (ht) { - ClcContact *contact2; - ClcGroup *group2; - if (FindItem(hwnd, dat, contact->hContact, &contact2, &group2, NULL, FALSE)) { - int 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; } - } - } - } - } - if (selMoved) { - 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(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: - KillTimer(hwnd, TIMERID_SUBEXPAND); - { - ClcContact *ht = NULL; - 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->needsResort = 1; - pcli->pfnSortCLC(hwnd, dat, 1); - cliRecalcScrollBar(hwnd, dat); - if (ht) { - int i = 0; - ClcContact *contact; - 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); - } -} - - -static LRESULT clcOnActivate(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(ClcData *, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (!CLUI_IsInMainWindow(hwnd)) - return DefWindowProc(hwnd, msg, wParam, lParam); - - if (g_CluiData.nBehindEdgeState > 0) - CLUI_ShowFromBehindEdge(); - - if (g_CluiData.bBehindEdgeSettings) - CLUI_UpdateTimer(); - - int lResult = CLUI_TestCursorOnBorders(); - return lResult ? lResult : DefWindowProc(hwnd, msg, wParam, lParam); -} - -static LRESULT clcOnLButtonDown(ClcData *dat, HWND hwnd, UINT, WPARAM, LPARAM lParam) -{ - POINT pt = { LOWORD(lParam), HIWORD(lParam) }; - ClientToScreen(hwnd, &pt); - int 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; - } - - 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); - - ClcContact *contact; - ClcGroup *group; - DWORD hitFlags; - int 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) { - 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 && (hitFlags & CLCHT_ONITEMICON)) { - ClcGroup *selgroup; - 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)) { - int bNewState = (contact->flags & CONTACTF_CHECKED) == 0; // inversion - - if (contact->type == CLCIT_GROUP) - pcli->pfnSetGroupChildCheckboxes(contact->group, bNewState); - else - pcli->pfnSetContactCheckboxes(contact, bNewState); - pcli->pfnRecalculateGroupCheckboxes(hwnd, dat); - CLUI__cliInvalidateRect(hwnd, NULL, FALSE); - - NMCLISTCONTROL nm; - 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; - nm.hItem = (hit == -1 || hitFlags & CLCHT_NOWHERE) ? NULL : 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(ClcData *dat, HWND hwnd, UINT, 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(ClcData *dat, HWND hwnd, UINT, WPARAM wParam, LPARAM lParam) -{ - BOOL isOutside = FALSE; - if (CLUI_IsInMainWindow(hwnd)) { - if (g_CluiData.bBehindEdgeSettings) - CLUI_UpdateTimer(); - CLUI_TestCursorOnBorders(); - } - - if (clcProceedDragToScroll(hwnd, (short)HIWORD(lParam))) - return 0; - - if (dat->dragStage & DRAGSTAGEF_MAYBERENAME) { - POINT pt = UNPACK_POINT(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 = UNPACK_POINT(lParam); - ClientToScreen(hwnd, &pt); - HWND 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 = UNPACK_POINT(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) { - ClcContact *contact; - cliGetRowByIndex(dat, dat->iDragItem, &contact, NULL); - - NMCLISTCONTROL nm; - 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; - } - - ClcContact *contSour, *contDest; - - switch (target) { - case DROPTARGET_ONSELF: - break; - - case DROPTARGET_ONCONTACT: - cliGetRowByIndex(dat, dat->iDragItem, &contSour, NULL); - if (contSour->isChat()) - break; - if (contSour->type == CLCIT_CONTACT && mir_strcmp(contSour->proto, META_PROTO)) { - if (!contSour->isSubcontact) - hNewCursor = LoadCursor(g_hMirApp, MAKEINTRESOURCE(IDC_DROPUSER)); /// Add to meta - else - hNewCursor = LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_DROPMETA)); - } - break; - - case DROPTARGET_ONMETACONTACT: - cliGetRowByIndex(dat, dat->selection, &contDest, NULL); - cliGetRowByIndex(dat, dat->iDragItem, &contSour, NULL); - if (contSour->isChat() || contDest->isChat()) - break; - if (contSour->type == CLCIT_CONTACT && mir_strcmp(contSour->proto, META_PROTO)) { - if (!contSour->isSubcontact) - hNewCursor = LoadCursor(g_hMirApp, 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: - cliGetRowByIndex(dat, dat->selection, &contDest, NULL); - cliGetRowByIndex(dat, dat->iDragItem, &contSour, NULL); - if (contSour->isChat() || contDest->isChat()) - break; - if (contSour->type == CLCIT_CONTACT && mir_strcmp(contSour->proto, META_PROTO)) { - if (!contSour->isSubcontact) - hNewCursor = LoadCursor(g_hMirApp, 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(g_hMirApp, MAKEINTRESOURCE(IDC_DROPUSER)); - break; - - case DROPTARGET_INSERTION: - hNewCursor = LoadCursor(g_hMirApp, MAKEINTRESOURCE(IDC_DROP)); - break; - - case DROPTARGET_OUTSIDE: - 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) { - dat->dragAutoScrolling = (pt.y < 0) ? -1 : 1; - CLUI_SafeSetTimer(hwnd, TIMERID_DRAGAUTOSCROLL, dat->scrollTime, NULL); - } - SendMessage(hwnd, WM_TIMER, TIMERID_DRAGAUTOSCROLL, 0); - } - - dat->dragStage |= DRAGSTAGEF_OUTSIDE; - { - ClcContact *contact; - cliGetRowByIndex(dat, dat->iDragItem, &contact, NULL); - - NMCLISTCONTROL nm; - 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: - ClcGroup *group = NULL; - cliGetRowByIndex(dat, dat->iDragItem, NULL, &group); - if (group && group->parent) { - cliGetRowByIndex(dat, dat->iDragItem, &contSour, NULL); - if (!contSour->isSubcontact) - hNewCursor = LoadCursor(g_hMirApp, MAKEINTRESOURCE(IDC_DROPUSER)); - } - break; - } - SetCursor(hNewCursor); - } - return 0; -} - -static LRESULT clcOnLButtonUp(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) { - TCHAR Wording[500]; - ClcContact *contDest, *contSour; - POINT pt = UNPACK_POINT(lParam); - int target = GetDropTargetInformation(hwnd, dat, pt); - switch (target) { - case DROPTARGET_ONSELF: - break; - - case DROPTARGET_ONCONTACT: - cliGetRowByIndex(dat, dat->iDragItem, &contSour, NULL); - cliGetRowByIndex(dat, dat->selection, &contDest, NULL); - if (contSour->isChat() || contDest->isChat()) - break; - if (contSour->type == CLCIT_CONTACT) { - MCONTACT hcontact = contSour->hContact; - if (mir_strcmp(contSour->proto, META_PROTO)) { - if (!contSour->isSubcontact) { - MCONTACT hDest = contDest->hContact; - mir_sntprintf(Wording, TranslateT("Do you want contact '%s' to be converted to metacontact and '%s' be added to it?"), contDest->szText, contSour->szText); - int res = MessageBox(hwnd, Wording, TranslateT("Converting to metacontact"), MB_OKCANCEL | MB_ICONQUESTION); - if (res == 1) { - MCONTACT handle = CallService(MS_MC_CONVERTTOMETA, hDest, 0); - if (!handle) - return 0; - - CallService(MS_MC_ADDTOMETA, hcontact, handle); - } - } - else { - hcontact = contSour->hContact; - MCONTACT hdest = contDest->hContact; - mir_sntprintf(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); - int res = MessageBox(hwnd, Wording, TranslateT("Converting to metacontact (moving)"), MB_OKCANCEL | MB_ICONQUESTION); - if (res == 1) { - MCONTACT handle = (MCONTACT)CallService(MS_MC_CONVERTTOMETA, (WPARAM)hdest, 0); - if (!handle) - return 0; - - CallService(MS_MC_REMOVEFROMMETA, 0, hcontact); - CallService(MS_MC_ADDTOMETA, hcontact, handle); - } - } - } - } - break; - - case DROPTARGET_ONMETACONTACT: - cliGetRowByIndex(dat, dat->iDragItem, &contSour, NULL); - cliGetRowByIndex(dat, dat->selection, &contDest, NULL); - if (contSour->isChat() || contDest->isChat()) - break; - if (contSour->type == CLCIT_CONTACT) { - if (!mir_strcmp(contSour->proto, META_PROTO)) - break; - if (!contSour->isSubcontact) { - MCONTACT hcontact = contSour->hContact; - MCONTACT handle = contDest->hContact; - mir_sntprintf(Wording, TranslateT("Do you want contact '%s' to be added to metacontact '%s'?"), contSour->szText, contDest->szText); - int res = MessageBox(hwnd, Wording, TranslateT("Adding contact to metacontact"), MB_OKCANCEL | MB_ICONQUESTION); - if (res == 1) { - if (!handle) - return 0; - CallService(MS_MC_ADDTOMETA, hcontact, handle); - } - } - else if (contSour->subcontacts == contDest) { - MCONTACT hsour = contSour->hContact; - mir_sntprintf(Wording, TranslateT("Do you want contact '%s' to be default?"), contSour->szText); - int res = MessageBox(hwnd, Wording, TranslateT("Set default contact"), MB_OKCANCEL | MB_ICONQUESTION); - if (res == 1) - db_mc_setDefault(contDest->hContact, hsour, true); - } - else { - MCONTACT hcontact = contSour->hContact; - MCONTACT handle = contDest->hContact; - mir_sntprintf(Wording, TranslateT("Do you want contact '%s' to be removed from metacontact '%s' and added to '%s'?"), contSour->szText, contSour->subcontacts->szText, contDest->szText); - int res = MessageBox(hwnd, Wording, TranslateT("Changing metacontacts (moving)"), MB_OKCANCEL | MB_ICONQUESTION); - if (res == 1) { - if (!handle) - return 0; - - CallService(MS_MC_REMOVEFROMMETA, 0, hcontact); - CallService(MS_MC_ADDTOMETA, hcontact, handle); - } - } - } - break; - - case DROPTARGET_ONSUBCONTACT: - cliGetRowByIndex(dat, dat->iDragItem, &contSour, NULL); - cliGetRowByIndex(dat, dat->selection, &contDest, NULL); - if (contSour->isChat() || contDest->isChat()) - break; - if (contSour->type == CLCIT_CONTACT) { - if (!mir_strcmp(contSour->proto, META_PROTO)) - break; - if (!contSour->isSubcontact) { - MCONTACT hcontact = contSour->hContact; - MCONTACT handle = contDest->subcontacts->hContact; - mir_sntprintf(Wording, TranslateT("Do you want contact '%s' to be added to metacontact '%s'?"), contSour->szText, contDest->subcontacts->szText); - int res = MessageBox(hwnd, Wording, TranslateT("Changing metacontacts (moving)"), MB_OKCANCEL | MB_ICONQUESTION); - if (res == 1) { - if (!handle) - return 0; - - CallService(MS_MC_ADDTOMETA, hcontact, handle); - } - } - else if (contSour->subcontacts != contDest->subcontacts) { - MCONTACT hcontact = contSour->hContact; - MCONTACT handle = contDest->subcontacts->hContact; - mir_sntprintf(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); - int res = MessageBox(hwnd, Wording, TranslateT("Changing metacontacts (moving)"), MB_OKCANCEL | MB_ICONQUESTION); - if (res == 1) { - if (!handle) - return 0; - - CallService(MS_MC_REMOVEFROMMETA, 0, hcontact); - CallService(MS_MC_ADDTOMETA, hcontact, handle); - } - } - } - break; - - case DROPTARGET_ONGROUP: - corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); - break; - - case DROPTARGET_INSERTION: - { - ClcContact *contact, *destcontact; - ClcGroup *group, *destgroup; - BOOL NeedRename = FALSE; - TCHAR newName[128] = { 0 }; - pcli->pfnGetRowByIndex(dat, dat->iDragItem, &contact, &group); - int 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)mir_tstrlen(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, _T("%s\\%s"), sourceGrName, shortGroup); - else - mir_tstrncpy(newName, shortGroup, _countof(newName)); - } - mir_free(groupName); - mir_free(sourceGrName); - } - int 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(ClcData *, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - KillTimer(hwnd, TIMERID_SUBEXPAND); - hitcontact = NULL; - return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); -} - -static LRESULT clcOnDestroy(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - for (int 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->hBmpBackground) { - DeleteObject(dat->hBmpBackground); - dat->hBmpBackground = NULL; - } - - ImageArray_Clear(&dat->avatar_cache); - DeleteDC(dat->avatar_cache.hdc); - ImageArray_Free(&dat->avatar_cache, FALSE); - if (dat->himlHighlight) { - ImageList_Destroy(dat->himlHighlight); - dat->himlHighlight = NULL; - } - - RowHeights_Free(dat); - corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); - xpt_FreeThemeForWindow(hwnd); - return 0; -} - -static LRESULT clcOnIntmGroupChanged(ClcData *dat, HWND hwnd, UINT, WPARAM wParam, LPARAM) -{ - WORD iExtraImage[EXTRA_ICON_COUNT]; - BYTE flags = 0; - - ClcContact *contact; - if (!pcli->pfnFindItem(hwnd, dat, wParam, &contact, NULL, NULL)) - memset(iExtraImage, 0xFF, sizeof(iExtraImage)); - else { - memcpy(iExtraImage, contact->iExtraImage, sizeof(iExtraImage)); - flags = contact->flags; - } - pcli->pfnDeleteItemFromTree(hwnd, wParam); - if (GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_SHOWHIDDEN || !db_get_b(wParam, "CList", "Hidden", 0)) { - NMCLISTCONTROL nm; - pcli->pfnAddContactToTree(hwnd, dat, wParam, 1, 1); - if (pcli->pfnFindItem(hwnd, dat, wParam, &contact, NULL, NULL)) { - memcpy(contact->iExtraImage, iExtraImage, sizeof(iExtraImage)); - 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->needsResort = 1; - } - SetTimer(hwnd, TIMERID_REBUILDAFTER, 1, NULL); - return 0; -} - -static LRESULT clcOnIntmIconChanged(ClcData *dat, HWND hwnd, UINT, WPARAM wParam, LPARAM lParam) -{ - ClcContact *contact = NULL; - ClcGroup *group = NULL; - int recalcScrollBar = 0, shouldShow; - BOOL needRepaint = FALSE; - int contacticon = corecli.pfnGetContactIcon(wParam); - MCONTACT hSelItem = NULL; - ClcContact *selcontact = NULL; - - char *szProto = GetContactProto(wParam); - WORD status = (szProto == NULL) ? ID_STATUS_OFFLINE : GetContactCachedStatus(wParam); - BOOL image_is_special = (LOWORD(contacticon) != (LOWORD(lParam))); //check only base icons - - int nHiddenStatus = CLVM_GetContactHiddenStatus(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 = cli_GetContactIcon(wParam) != 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, 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 = (DWORD_PTR)pcli->pfnContactToHItem(selcontact); - pcli->pfnAddContactToTree(hwnd, dat, wParam, (style & CLS_CONTACTLIST) == 0, 0); - recalcScrollBar = 1; - needRepaint = TRUE; - pcli->pfnFindItem(hwnd, dat, wParam, &contact, NULL, NULL); - if (contact) { - contact->iImage = lParam; - contact->image_is_special = image_is_special; - pcli->pfnNotifyNewContact(hwnd, wParam); - dat->needsResort = 1; - } - } - } - else { - //item in list already - if (contact && contact->iImage == lParam) - return 0; - - if (!shouldShow && !(style & CLS_NOHIDEOFFLINE) && (style & CLS_HIDEOFFLINE || group->hideOffline) && clcItemNotHiddenOffline(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 = (DWORD_PTR)pcli->pfnContactToHItem(selcontact); - pcli->pfnRemoveItemFromGroup(hwnd, group, contact, (style & CLS_CONTACTLIST) == 0); - needRepaint = TRUE; - recalcScrollBar = 1; - dat->needsResort = 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->needsResort = 1; - needRepaint = TRUE; - } - else if (dat->m_paintCouter == contact->lastPaintCounter) //if contacts is visible - needRepaint = TRUE; - } - } - - if (hSelItem) { - 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; - } - - if (dat->needsResort) { - 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(ClcData *dat, HWND hwnd, UINT, WPARAM hContact, LPARAM) -{ - ClcContact *contact; - if (FindItem(hwnd, dat, hContact, &contact, NULL, NULL, FALSE)) - Cache_GetAvatar(dat, contact); - else if (hContact == 0) - UpdateAllAvatars(dat); - - CLUI__cliInvalidateRect(hwnd, NULL, FALSE); - return 0; -} - -static LRESULT clcOnIntmTimeZoneChanged(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - ClcContact *contact; - if (!FindItem(hwnd, dat, wParam, &contact, NULL, NULL, FALSE)) - return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); - - if (contact) { - Cache_GetTimezone(dat, contact->hContact); - Cache_GetText(dat, contact, 1); - cliRecalcScrollBar(hwnd, dat); - } - return 0; -} - -static LRESULT clcOnIntmNameChanged(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - int ret = corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); - - pcli->pfnInvalidateDisplayNameCacheEntry(wParam); - - ClcContact *contact; - if (!FindItem(hwnd, dat, wParam, &contact, NULL, NULL, FALSE)) - return ret; - - if (contact) { - mir_tstrncpy(contact->szText, pcli->pfnGetContactDisplayName(wParam, 0), _countof(contact->szText)); - Cache_GetText(dat, contact, 1); - cliRecalcScrollBar(hwnd, dat); - } - - dat->needsResort = 1; - return ret; -} - -static LRESULT clcOnIntmApparentModeChanged(ClcData *, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); -} - -static LRESULT clcOnIntmStatusMsgChanged(ClcData *dat, HWND hwnd, UINT msg, WPARAM hContact, LPARAM lParam) -{ - if (hContact == NULL || IsHContactInfo(hContact) || IsHContactGroup(hContact)) - return corecli.pfnContactListControlWndProc(hwnd, msg, hContact, lParam); - - ClcContact *contact; - if (!FindItem(hwnd, dat, hContact, &contact, NULL, NULL, FALSE)) - return corecli.pfnContactListControlWndProc(hwnd, msg, hContact, lParam); - - if (contact) { - Cache_GetText(dat, contact, 1); - cliRecalcScrollBar(hwnd, dat); - PostMessage(hwnd, INTM_INVALIDATE, 0, 0); - } - return corecli.pfnContactListControlWndProc(hwnd, msg, hContact, lParam); -} - -static LRESULT clcOnIntmNotOnListChanged(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - DBCONTACTWRITESETTING *dbcws = (DBCONTACTWRITESETTING*)lParam; - - ClcContact *contact; - if (!FindItem(hwnd, dat, 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(ClcData *dat, HWND hwnd, UINT, WPARAM, 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(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - int ret = corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); - if (wParam != 0) { - ClcCacheEntry *pdnce = pcli->pfnGetCacheEntry(wParam); - if (pdnce && pdnce->m_pszProto) { - pdnce->m_iStatus = GetStatusForContact(pdnce->hContact, pdnce->m_pszProto); - if (!dat->force_in_dialog && (dat->second_line_show || dat->third_line_show)) - gtaRenewText(pdnce->hContact); - SendMessage(hwnd, INTM_ICONCHANGED, wParam, corecli.pfnGetContactIcon(wParam)); - - ClcContact *contact; - if (FindItem(hwnd, dat, wParam, &contact, NULL, NULL, TRUE)) { - if (contact && contact->type == CLCIT_CONTACT) { - if (!contact->image_is_special && pdnce->getStatus() > ID_STATUS_OFFLINE) - contact->iImage = corecli.pfnGetContactIcon(wParam); - if (contact->isSubcontact && contact->subcontacts && contact->subcontacts->type == CLCIT_CONTACT) - pcli->pfnClcBroadcast(INTM_STATUSCHANGED, contact->subcontacts->hContact, 0); //forward status changing to host meta contact - } - } - } - } - - if (db_get_b(NULL, "CList", "PlaceOfflineToRoot", SETTING_PLACEOOFLINETOROOT_DEFAULT)) - pcli->pfnInitAutoRebuild(hwnd); - else - PostMessage(hwnd, INTM_INVALIDATE, 0, 0); - - return ret; -} - -static LRESULT clcOnIntmReloadOptions(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); - pcli->pfnLoadClcOptions(hwnd, dat, FALSE); - LoadCLCOptions(hwnd, dat, FALSE); - pcli->pfnSaveStateAndRebuildList(hwnd, dat); - pcli->pfnSortCLC(hwnd, dat, 1); - if (IsWindowVisible(hwnd)) - pcli->pfnInvalidateRect(GetParent(hwnd), NULL, FALSE); - return TRUE; -} - -static int clcHookModulesLoaded(WPARAM, LPARAM) -{ - if (MirandaExiting()) - return 0; - - if (!ServiceExists(MS_AV_GETAVATARBITMAP)) - MessageBox(NULL, - TranslateT("Clist Modern requires AVS plugin to be present. Install it using PluginUpdater or download from http://wiki.miranda-ng.org/Download"), - TranslateT("Error loading plugin"), MB_ICONERROR | MB_OK); - - HookEvent(ME_AV_AVATARCHANGED, clcHookAvatarChanged); - - HookEvent(ME_MODERNOPT_INITIALIZE, ModernOptInit); - HookEvent(ME_MODERNOPT_INITIALIZE, ModernSkinOptInit); - - HookEvent(ME_FOLDERS_PATH_CHANGED, ReloadSkinFolder); - hSkinFolder = FoldersRegisterCustomPathT(LPGEN("Skins"), LPGEN("Modern contact list"), MIRANDA_PATHT _T("\\") _T(DEFAULT_SKIN_FOLDER)); - FoldersGetCustomPathT(hSkinFolder, SkinsFolder, _countof(SkinsFolder), _T(DEFAULT_SKIN_FOLDER)); - - // Get icons - TCHAR szMyPath[MAX_PATH]; - GetModuleFileName(g_hInst, szMyPath, _countof(szMyPath)); - - SKINICONDESC sid = { 0 }; - sid.defaultFile.t = szMyPath; - sid.flags = SIDF_PATH_TCHAR; - - sid.section.a = LPGEN("Contact list"); - sid.description.a = LPGEN("Listening to"); - sid.pszName = "LISTENING_TO_ICON"; - sid.iDefaultIndex = -IDI_LISTENING_TO; - IcoLib_AddIcon(&sid); - - sid.section.a = LPGEN("Contact list") "/" LPGEN("Avatar overlay"); - for (int i = 0; i < _countof(g_pAvatarOverlayIcons); i++) { - sid.description.a = g_pAvatarOverlayIcons[i].description; - sid.pszName = g_pAvatarOverlayIcons[i].name; - sid.iDefaultIndex = -g_pAvatarOverlayIcons[i].id; - IcoLib_AddIcon(&sid); - } - - sid.section.a = LPGEN("Contact list") "/" LPGEN("Status overlay"); - for (int i = 0; i < _countof(g_pStatusOverlayIcons); i++) { - sid.description.a = g_pStatusOverlayIcons[i].description; - sid.pszName = g_pStatusOverlayIcons[i].name; - sid.iDefaultIndex = -g_pStatusOverlayIcons[i].id; - IcoLib_AddIcon(&sid); - } - - clcHookIconsChanged(0, 0); - - 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); - - HookEvent(ME_SMILEYADD_OPTIONSCHANGED, clcHookSmileyAddOptionsChanged); - } - - CallService(MS_BACKGROUNDCONFIG_REGISTER, (WPARAM)(LPGEN("List background")"/CLC"), 0); - CallService(MS_BACKGROUNDCONFIG_REGISTER, (WPARAM)(LPGEN("Menu background")"/Menu"), 0); - CallService(MS_BACKGROUNDCONFIG_REGISTER, (WPARAM)(LPGEN("Status bar background")"/StatusBar"), 0); - CallService(MS_BACKGROUNDCONFIG_REGISTER, (WPARAM)(LPGEN("Frames title bar 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; -} - -HRESULT ClcLoadModule() -{ - g_himlCListClc = (HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0); - - HookEvent(ME_MC_SUBCONTACTSCHANGED, clcMetacontactChanged); - HookEvent(ME_MC_ENABLED, clcMetaModeChanged); - HookEvent(ME_DB_CONTACT_SETTINGCHANGED, clcHookSettingChanged); - HookEvent(ME_OPT_INITIALISE, ClcOptInit); - 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(MCONTACT, ACKDATA *ack) -{ - if (MirandaExiting()) return 0; - if (ack->type == ACKTYPE_STATUS) { - if (ack->result == ACKRESULT_SUCCESS) { - for (int i = 0; i < pcli->hClcProtoCount; i++) { - if (!mir_strcmp(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); - return 0; - } - } - } - } - else if (ack->type == ACKTYPE_AWAYMSG) { - if (ack->result == ACKRESULT_SUCCESS && ack->lParam) { - 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 { - 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_strcmpi(val, "")) - db_set_s(ack->hContact, "CList", "StatusMsg", ""); - else - gtaRenewText(ack->hContact); - mir_free(val); - } - } - } - } - else if (ack->type == ACKTYPE_EMAIL) { - CLUIUnreadEmailCountChanged(0, 0); - } - return 0; -} - -int ClcGetShortData(ClcData* pData, 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; - - mir_tstrncpy(pShortData->second_line_text, pData->second_line_text, _countof(pShortData->second_line_text)); - - 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; - - // Third line - 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; - - mir_tstrncpy(pShortData->third_line_text, pData->third_line_text, _countof(pShortData->third_line_text)); - - 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) -{ - if (IsDragToScrollMode) - return 0; - - ClcData *dat = (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); - - ClcData *dat = (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); - } -} + } + else { + if (!strcmp(cws->szSetting, "TickTS")) + pcli->pfnClcBroadcast(INTM_STATUSCHANGED, hContact, 0); + else if (!strcmp(cws->szModule, "UserInfo")) { + if (!strcmp(cws->szSetting, "Timezone")) + pcli->pfnClcBroadcast(INTM_TIMEZONECHANGED, hContact, 0); + } + else if (!strcmp(cws->szModule, "CList")) { + if (!strcmp(cws->szSetting, "StatusMsg")) + pcli->pfnClcBroadcast(INTM_STATUSMSGCHANGED, hContact, 0); + } + else if (!strcmp(cws->szModule, "ContactPhoto")) { + if (!strcmp(cws->szSetting, "File")) + pcli->pfnClcBroadcast(INTM_AVATARCHANGED, hContact, 0); + } + else { + if ((!strcmp(cws->szSetting, "XStatusName") || !strcmp(cws->szSetting, "XStatusMsg"))) + pcli->pfnClcBroadcast(INTM_STATUSMSGCHANGED, hContact, 0); + else if (!strcmp(cws->szSetting, "XStatusId")) + pcli->pfnClcBroadcast(INTM_STATUSCHANGED, hContact, 0); + else if (!strcmp(cws->szSetting, "Timezone")) + pcli->pfnClcBroadcast(INTM_TIMEZONECHANGED, hContact, 0); + else if (!strcmp(cws->szSetting, "ListeningTo")) + pcli->pfnClcBroadcast(INTM_STATUSMSGCHANGED, hContact, 0); + else if (!strcmp(cws->szSetting, "Transport") || !strcmp(cws->szSetting, "IsTransported")) { + pcli->pfnInvalidateDisplayNameCacheEntry(hContact); + pcli->pfnClcBroadcast(CLM_AUTOREBUILD, hContact, 0); + } + } + } + return 0; +} + +static int clcHookDbEventAdded(WPARAM hContact, LPARAM lParam) +{ + g_CluiData.t_now = time(NULL); + if (hContact && lParam) { + DBEVENTINFO dbei = { sizeof(dbei) }; + db_event_get(lParam, &dbei); + if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) { + db_set_dw(hContact, "CList", "mf_lastmsg", dbei.timestamp); + ClcCacheEntry *pdnce = pcli->pfnGetCacheEntry(hContact); + if (pdnce) + pdnce->dwLastMsgTime = dbei.timestamp; + } + } + return 0; +} + +static int clcHookBkgndConfigChanged(WPARAM, 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, ClcData *dat, int index, const TCHAR *text, int prefixOk, BOOL fSearchUp) +{ + ClcGroup *group = &dat->list; + int testlen = (int)mir_tstrlen(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) { + bool found; + if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) { + found = true; + } + else if (dat->filterSearch) { + TCHAR *lowered_szText = CharLowerW(NEWTSTR_ALLOCA(group->cl.items[group->scanIndex]->szText)); + TCHAR *lowered_search = CharLowerW(NEWTSTR_ALLOCA(dat->szQuickSearch)); + found = _tcsstr(lowered_szText, lowered_search) != NULL; + } + else { + found = ((prefixOk && CSTR_EQUAL == CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, text, -1, group->cl.items[group->scanIndex]->szText, testlen)) || (!prefixOk && !mir_tstrcmpi(text, group->cl.items[group->scanIndex]->szText))); + } + if (found) { + 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(ClcGroup *group, ClcContact *contact) +{ + if (g_CluiData.bFilterEffective) return FALSE; + + if (!contact) return FALSE; + ClcCacheEntry *pdnce = pcli->pfnGetCacheEntry(contact->hContact); + if (!pdnce) return FALSE; + if (pdnce->m_bNoHiddenOffline) return TRUE; + + if (!group) return FALSE; + if (group->hideOffline) return FALSE; + + if (CLCItems_IsShowOfflineGroup(group)) return TRUE; + + return FALSE; +} + +static LRESULT clcOnCreate(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + dat = (ClcData*)mir_calloc(sizeof(ClcData)); + SetWindowLongPtr(hwnd, 0, (LONG_PTR)dat); + dat->hCheckBoxTheme = xpt_AddThemeHandle(hwnd, L"BUTTON"); + dat->m_paintCouter = 0; + dat->hWnd = hwnd; + + ImageArray_Initialize(&dat->avatar_cache, FALSE, 20); //this array will be used to keep small avatars too + + RowHeights_Initialize(dat); + + dat->needsResort = 1; + dat->MetaIgnoreEmptyExtra = db_get_b(NULL, "CLC", "MetaIgnoreEmptyExtra", SETTING_METAIGNOREEMPTYEXTRA_DEFAULT); + + dat->IsMetaContactsEnabled = (!(GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_MANUALUPDATE)) && db_mc_isEnabled(); + + 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; + + corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); + LoadCLCOptions(hwnd, dat, TRUE); + 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); + + TRACE("Create New ClistControl TO END\r\n"); + return 0; +} + +static LRESULT clcOnHitTest(ClcData *, HWND hwnd, UINT, WPARAM wParam, LPARAM lParam) +{ + return DefWindowProc(hwnd, WM_NCHITTEST, wParam, lParam); +} + +static LRESULT clcOnCommand(ClcData *dat, HWND hwnd, UINT, WPARAM wParam, LPARAM lParam) +{ + ClcContact *contact; + int hit = pcli->pfnGetRowByIndex(dat, dat->selection, &contact, NULL); + if (hit != -1) { + switch (LOWORD(wParam)) { + case POPUP_NEWSUBGROUP: + if (contact->type == CLCIT_GROUP) { + 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_GROUPSHOWOFFLINE: + if (contact->type == CLCIT_GROUP) { + CallService(MS_CLIST_GROUPSETFLAGS, contact->groupId, MAKELPARAM(CLCItems_IsShowOfflineGroup(contact->group) ? 0 : GROUPF_SHOWOFFLINE, GROUPF_SHOWOFFLINE)); + pcli->pfnClcBroadcast(CLM_AUTOREBUILD, 0, 0); + } + return 0; + } + } + + return corecli.pfnContactListControlWndProc(hwnd, WM_COMMAND, wParam, lParam); +} + +static LRESULT clcOnSize(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) { + RECT rc = { 0 }; + GetClientRect(hwnd, &rc); + if (rc.right == 0) + return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); + + rc.bottom = max(dat->row_min_heigh, 1); + + HDC hdc = GetDC(hwnd); + int depth = GetDeviceCaps(hdc, BITSPIXEL); + if (depth < 16) + depth = 16; + HBITMAP hBmp = CreateBitmap(rc.right, rc.bottom, 1, depth, NULL); + HBITMAP hBmpMask = CreateBitmap(rc.right, rc.bottom, 1, 1, NULL); + HDC hdcMem = CreateCompatibleDC(hdc); + HBITMAP hoBmp = (HBITMAP)SelectObject(hdcMem, hBmp); + HBRUSH hBrush = CreateSolidBrush((dat->useWindowsColours || dat->force_in_dialog) ? GetSysColor(COLOR_HIGHLIGHT) : dat->selBkColour); + FillRect(hdcMem, &rc, hBrush); + DeleteObject(hBrush); + + HBITMAP 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, ILC_COLOR32 | 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(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(); + } + return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); +} +static LRESULT clcOnPaint(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (IsWindowVisible(hwnd)) { + if (!g_CluiData.fLayered || GetParent(hwnd) != pcli->hwndContactList) { + PAINTSTRUCT ps; + HDC 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(ClcData *, HWND, UINT, WPARAM, LPARAM) +{ + return 1; +} + +static LRESULT clcOnKeyDown(ClcData *dat, HWND hwnd, UINT, WPARAM wParam, LPARAM lParam) +{ + 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); + int pageSize = (dat->rowHeight) ? clRect.bottom / dat->rowHeight : 0; + int selMoved = 0; + int changeGroupExpand = 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; + } + + dat->selection = index; + pcli->pfnInvalidateRect(hwnd, NULL, FALSE); + pcli->pfnEnsureVisible(hwnd, dat, dat->selection, 0); + return 0; + } + + 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); + dat->szQuickSearch[0] = 0; + if (dat->filterSearch) + pcli->pfnSaveStateAndRebuildList(hwnd, dat); + 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) { + ClcContact *contact; + ClcGroup *group; + int hit = cliGetRowByIndex(dat, dat->selection, &contact, &group); + if (hit == -1) { + SetCapture(hwnd); + return 0; + } + + 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 + ClcContact *ht = NULL; + KillTimer(hwnd, TIMERID_SUBEXPAND); + contact->SubExpanded = 0; + db_set_b(contact->hContact, "CList", "Expanded", 0); + ht = contact; + dat->needsResort = 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) { + ClcContact *ht = NULL; + KillTimer(hwnd, TIMERID_SUBEXPAND); + contact->SubExpanded = 1; + db_set_b(contact->hContact, "CList", "Expanded", 1); + ht = contact; + dat->needsResort = 1; + pcli->pfnSortCLC(hwnd, dat, 1); + cliRecalcScrollBar(hwnd, dat); + if (ht) { + ClcContact *contact2; + ClcGroup *group2; + if (FindItem(hwnd, dat, contact->hContact, &contact2, &group2, NULL, FALSE)) { + int 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; } + } + } + } + } + if (selMoved) { + 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(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: + KillTimer(hwnd, TIMERID_SUBEXPAND); + { + ClcContact *ht = NULL; + 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->needsResort = 1; + pcli->pfnSortCLC(hwnd, dat, 1); + cliRecalcScrollBar(hwnd, dat); + if (ht) { + int i = 0; + ClcContact *contact; + 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); + } +} + + +static LRESULT clcOnActivate(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(ClcData *, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (!CLUI_IsInMainWindow(hwnd)) + return DefWindowProc(hwnd, msg, wParam, lParam); + + if (g_CluiData.nBehindEdgeState > 0) + CLUI_ShowFromBehindEdge(); + + if (g_CluiData.bBehindEdgeSettings) + CLUI_UpdateTimer(); + + int lResult = CLUI_TestCursorOnBorders(); + return lResult ? lResult : DefWindowProc(hwnd, msg, wParam, lParam); +} + +static LRESULT clcOnLButtonDown(ClcData *dat, HWND hwnd, UINT, WPARAM, LPARAM lParam) +{ + POINT pt = { LOWORD(lParam), HIWORD(lParam) }; + ClientToScreen(hwnd, &pt); + int 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; + } + + 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); + + ClcContact *contact; + ClcGroup *group; + DWORD hitFlags; + int 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) { + 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 && (hitFlags & CLCHT_ONITEMICON)) { + ClcGroup *selgroup; + 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)) { + int bNewState = (contact->flags & CONTACTF_CHECKED) == 0; // inversion + + if (contact->type == CLCIT_GROUP) + pcli->pfnSetGroupChildCheckboxes(contact->group, bNewState); + else + pcli->pfnSetContactCheckboxes(contact, bNewState); + pcli->pfnRecalculateGroupCheckboxes(hwnd, dat); + CLUI__cliInvalidateRect(hwnd, NULL, FALSE); + + NMCLISTCONTROL nm; + 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; + nm.hItem = (hit == -1 || hitFlags & CLCHT_NOWHERE) ? NULL : 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(ClcData *dat, HWND hwnd, UINT, 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(ClcData *dat, HWND hwnd, UINT, WPARAM wParam, LPARAM lParam) +{ + BOOL isOutside = FALSE; + if (CLUI_IsInMainWindow(hwnd)) { + if (g_CluiData.bBehindEdgeSettings) + CLUI_UpdateTimer(); + CLUI_TestCursorOnBorders(); + } + + if (clcProceedDragToScroll(hwnd, (short)HIWORD(lParam))) + return 0; + + if (dat->dragStage & DRAGSTAGEF_MAYBERENAME) { + POINT pt = UNPACK_POINT(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 = UNPACK_POINT(lParam); + ClientToScreen(hwnd, &pt); + HWND 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 = UNPACK_POINT(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) { + ClcContact *contact; + cliGetRowByIndex(dat, dat->iDragItem, &contact, NULL); + + NMCLISTCONTROL nm; + 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; + } + + ClcContact *contSour, *contDest; + + switch (target) { + case DROPTARGET_ONSELF: + break; + + case DROPTARGET_ONCONTACT: + cliGetRowByIndex(dat, dat->iDragItem, &contSour, NULL); + if (contSour->isChat()) + break; + if (contSour->type == CLCIT_CONTACT && mir_strcmp(contSour->proto, META_PROTO)) { + if (!contSour->isSubcontact) + hNewCursor = LoadCursor(g_hMirApp, MAKEINTRESOURCE(IDC_DROPUSER)); /// Add to meta + else + hNewCursor = LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_DROPMETA)); + } + break; + + case DROPTARGET_ONMETACONTACT: + cliGetRowByIndex(dat, dat->selection, &contDest, NULL); + cliGetRowByIndex(dat, dat->iDragItem, &contSour, NULL); + if (contSour->isChat() || contDest->isChat()) + break; + if (contSour->type == CLCIT_CONTACT && mir_strcmp(contSour->proto, META_PROTO)) { + if (!contSour->isSubcontact) + hNewCursor = LoadCursor(g_hMirApp, 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: + cliGetRowByIndex(dat, dat->selection, &contDest, NULL); + cliGetRowByIndex(dat, dat->iDragItem, &contSour, NULL); + if (contSour->isChat() || contDest->isChat()) + break; + if (contSour->type == CLCIT_CONTACT && mir_strcmp(contSour->proto, META_PROTO)) { + if (!contSour->isSubcontact) + hNewCursor = LoadCursor(g_hMirApp, 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(g_hMirApp, MAKEINTRESOURCE(IDC_DROPUSER)); + break; + + case DROPTARGET_INSERTION: + hNewCursor = LoadCursor(g_hMirApp, MAKEINTRESOURCE(IDC_DROP)); + break; + + case DROPTARGET_OUTSIDE: + 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) { + dat->dragAutoScrolling = (pt.y < 0) ? -1 : 1; + CLUI_SafeSetTimer(hwnd, TIMERID_DRAGAUTOSCROLL, dat->scrollTime, NULL); + } + SendMessage(hwnd, WM_TIMER, TIMERID_DRAGAUTOSCROLL, 0); + } + + dat->dragStage |= DRAGSTAGEF_OUTSIDE; + { + ClcContact *contact; + cliGetRowByIndex(dat, dat->iDragItem, &contact, NULL); + + NMCLISTCONTROL nm; + 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: + ClcGroup *group = NULL; + cliGetRowByIndex(dat, dat->iDragItem, NULL, &group); + if (group && group->parent) { + cliGetRowByIndex(dat, dat->iDragItem, &contSour, NULL); + if (!contSour->isSubcontact) + hNewCursor = LoadCursor(g_hMirApp, MAKEINTRESOURCE(IDC_DROPUSER)); + } + break; + } + SetCursor(hNewCursor); + } + return 0; +} + +static LRESULT clcOnLButtonUp(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) { + TCHAR Wording[500]; + ClcContact *contDest, *contSour; + POINT pt = UNPACK_POINT(lParam); + int target = GetDropTargetInformation(hwnd, dat, pt); + switch (target) { + case DROPTARGET_ONSELF: + break; + + case DROPTARGET_ONCONTACT: + cliGetRowByIndex(dat, dat->iDragItem, &contSour, NULL); + cliGetRowByIndex(dat, dat->selection, &contDest, NULL); + if (contSour->isChat() || contDest->isChat()) + break; + if (contSour->type == CLCIT_CONTACT) { + MCONTACT hcontact = contSour->hContact; + if (mir_strcmp(contSour->proto, META_PROTO)) { + if (!contSour->isSubcontact) { + MCONTACT hDest = contDest->hContact; + mir_sntprintf(Wording, TranslateT("Do you want contact '%s' to be converted to metacontact and '%s' be added to it?"), contDest->szText, contSour->szText); + int res = MessageBox(hwnd, Wording, TranslateT("Converting to metacontact"), MB_OKCANCEL | MB_ICONQUESTION); + if (res == 1) { + MCONTACT handle = CallService(MS_MC_CONVERTTOMETA, hDest, 0); + if (!handle) + return 0; + + CallService(MS_MC_ADDTOMETA, hcontact, handle); + } + } + else { + hcontact = contSour->hContact; + MCONTACT hdest = contDest->hContact; + mir_sntprintf(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); + int res = MessageBox(hwnd, Wording, TranslateT("Converting to metacontact (moving)"), MB_OKCANCEL | MB_ICONQUESTION); + if (res == 1) { + MCONTACT handle = (MCONTACT)CallService(MS_MC_CONVERTTOMETA, (WPARAM)hdest, 0); + if (!handle) + return 0; + + CallService(MS_MC_REMOVEFROMMETA, 0, hcontact); + CallService(MS_MC_ADDTOMETA, hcontact, handle); + } + } + } + } + break; + + case DROPTARGET_ONMETACONTACT: + cliGetRowByIndex(dat, dat->iDragItem, &contSour, NULL); + cliGetRowByIndex(dat, dat->selection, &contDest, NULL); + if (contSour->isChat() || contDest->isChat()) + break; + if (contSour->type == CLCIT_CONTACT) { + if (!mir_strcmp(contSour->proto, META_PROTO)) + break; + if (!contSour->isSubcontact) { + MCONTACT hcontact = contSour->hContact; + MCONTACT handle = contDest->hContact; + mir_sntprintf(Wording, TranslateT("Do you want contact '%s' to be added to metacontact '%s'?"), contSour->szText, contDest->szText); + int res = MessageBox(hwnd, Wording, TranslateT("Adding contact to metacontact"), MB_OKCANCEL | MB_ICONQUESTION); + if (res == 1) { + if (!handle) + return 0; + CallService(MS_MC_ADDTOMETA, hcontact, handle); + } + } + else if (contSour->subcontacts == contDest) { + MCONTACT hsour = contSour->hContact; + mir_sntprintf(Wording, TranslateT("Do you want contact '%s' to be default?"), contSour->szText); + int res = MessageBox(hwnd, Wording, TranslateT("Set default contact"), MB_OKCANCEL | MB_ICONQUESTION); + if (res == 1) + db_mc_setDefault(contDest->hContact, hsour, true); + } + else { + MCONTACT hcontact = contSour->hContact; + MCONTACT handle = contDest->hContact; + mir_sntprintf(Wording, TranslateT("Do you want contact '%s' to be removed from metacontact '%s' and added to '%s'?"), contSour->szText, contSour->subcontacts->szText, contDest->szText); + int res = MessageBox(hwnd, Wording, TranslateT("Changing metacontacts (moving)"), MB_OKCANCEL | MB_ICONQUESTION); + if (res == 1) { + if (!handle) + return 0; + + CallService(MS_MC_REMOVEFROMMETA, 0, hcontact); + CallService(MS_MC_ADDTOMETA, hcontact, handle); + } + } + } + break; + + case DROPTARGET_ONSUBCONTACT: + cliGetRowByIndex(dat, dat->iDragItem, &contSour, NULL); + cliGetRowByIndex(dat, dat->selection, &contDest, NULL); + if (contSour->isChat() || contDest->isChat()) + break; + if (contSour->type == CLCIT_CONTACT) { + if (!mir_strcmp(contSour->proto, META_PROTO)) + break; + if (!contSour->isSubcontact) { + MCONTACT hcontact = contSour->hContact; + MCONTACT handle = contDest->subcontacts->hContact; + mir_sntprintf(Wording, TranslateT("Do you want contact '%s' to be added to metacontact '%s'?"), contSour->szText, contDest->subcontacts->szText); + int res = MessageBox(hwnd, Wording, TranslateT("Changing metacontacts (moving)"), MB_OKCANCEL | MB_ICONQUESTION); + if (res == 1) { + if (!handle) + return 0; + + CallService(MS_MC_ADDTOMETA, hcontact, handle); + } + } + else if (contSour->subcontacts != contDest->subcontacts) { + MCONTACT hcontact = contSour->hContact; + MCONTACT handle = contDest->subcontacts->hContact; + mir_sntprintf(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); + int res = MessageBox(hwnd, Wording, TranslateT("Changing metacontacts (moving)"), MB_OKCANCEL | MB_ICONQUESTION); + if (res == 1) { + if (!handle) + return 0; + + CallService(MS_MC_REMOVEFROMMETA, 0, hcontact); + CallService(MS_MC_ADDTOMETA, hcontact, handle); + } + } + } + break; + + case DROPTARGET_ONGROUP: + corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); + break; + + case DROPTARGET_INSERTION: + { + ClcContact *contact, *destcontact; + ClcGroup *group, *destgroup; + BOOL NeedRename = FALSE; + TCHAR newName[128] = { 0 }; + pcli->pfnGetRowByIndex(dat, dat->iDragItem, &contact, &group); + int 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)mir_tstrlen(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, _T("%s\\%s"), sourceGrName, shortGroup); + else + mir_tstrncpy(newName, shortGroup, _countof(newName)); + } + mir_free(groupName); + mir_free(sourceGrName); + } + int 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(ClcData *, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + KillTimer(hwnd, TIMERID_SUBEXPAND); + hitcontact = NULL; + return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); +} + +static LRESULT clcOnDestroy(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + for (int 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->hBmpBackground) { + DeleteObject(dat->hBmpBackground); + dat->hBmpBackground = NULL; + } + + ImageArray_Clear(&dat->avatar_cache); + DeleteDC(dat->avatar_cache.hdc); + ImageArray_Free(&dat->avatar_cache, FALSE); + if (dat->himlHighlight) { + ImageList_Destroy(dat->himlHighlight); + dat->himlHighlight = NULL; + } + + RowHeights_Free(dat); + corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); + xpt_FreeThemeForWindow(hwnd); + return 0; +} + +static LRESULT clcOnIntmGroupChanged(ClcData *dat, HWND hwnd, UINT, WPARAM wParam, LPARAM) +{ + WORD iExtraImage[EXTRA_ICON_COUNT]; + BYTE flags = 0; + + ClcContact *contact; + if (!pcli->pfnFindItem(hwnd, dat, wParam, &contact, NULL, NULL)) + memset(iExtraImage, 0xFF, sizeof(iExtraImage)); + else { + memcpy(iExtraImage, contact->iExtraImage, sizeof(iExtraImage)); + flags = contact->flags; + } + pcli->pfnDeleteItemFromTree(hwnd, wParam); + if (GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_SHOWHIDDEN || !db_get_b(wParam, "CList", "Hidden", 0)) { + NMCLISTCONTROL nm; + pcli->pfnAddContactToTree(hwnd, dat, wParam, 1, 1); + if (pcli->pfnFindItem(hwnd, dat, wParam, &contact, NULL, NULL)) { + memcpy(contact->iExtraImage, iExtraImage, sizeof(iExtraImage)); + 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->needsResort = 1; + } + SetTimer(hwnd, TIMERID_REBUILDAFTER, 1, NULL); + return 0; +} + +static LRESULT clcOnIntmIconChanged(ClcData *dat, HWND hwnd, UINT, WPARAM wParam, LPARAM lParam) +{ + ClcContact *contact = NULL; + ClcGroup *group = NULL; + int recalcScrollBar = 0, shouldShow; + BOOL needRepaint = FALSE; + int contacticon = corecli.pfnGetContactIcon(wParam); + MCONTACT hSelItem = NULL; + ClcContact *selcontact = NULL; + + char *szProto = GetContactProto(wParam); + WORD status = (szProto == NULL) ? ID_STATUS_OFFLINE : GetContactCachedStatus(wParam); + BOOL image_is_special = (LOWORD(contacticon) != (LOWORD(lParam))); //check only base icons + + int nHiddenStatus = CLVM_GetContactHiddenStatus(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 = cli_GetContactIcon(wParam) != 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, 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 = (DWORD_PTR)pcli->pfnContactToHItem(selcontact); + pcli->pfnAddContactToTree(hwnd, dat, wParam, (style & CLS_CONTACTLIST) == 0, 0); + recalcScrollBar = 1; + needRepaint = TRUE; + pcli->pfnFindItem(hwnd, dat, wParam, &contact, NULL, NULL); + if (contact) { + contact->iImage = lParam; + contact->image_is_special = image_is_special; + pcli->pfnNotifyNewContact(hwnd, wParam); + dat->needsResort = 1; + } + } + } + else { + //item in list already + if (contact && contact->iImage == lParam) + return 0; + + if (!shouldShow && !(style & CLS_NOHIDEOFFLINE) && (style & CLS_HIDEOFFLINE || group->hideOffline) && clcItemNotHiddenOffline(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 = (DWORD_PTR)pcli->pfnContactToHItem(selcontact); + pcli->pfnRemoveItemFromGroup(hwnd, group, contact, (style & CLS_CONTACTLIST) == 0); + needRepaint = TRUE; + recalcScrollBar = 1; + dat->needsResort = 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->needsResort = 1; + needRepaint = TRUE; + } + else if (dat->m_paintCouter == contact->lastPaintCounter) //if contacts is visible + needRepaint = TRUE; + } + } + + if (hSelItem) { + 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; + } + + if (dat->needsResort) { + 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(ClcData *dat, HWND hwnd, UINT, WPARAM hContact, LPARAM) +{ + ClcContact *contact; + if (FindItem(hwnd, dat, hContact, &contact, NULL, NULL, FALSE)) + Cache_GetAvatar(dat, contact); + else if (hContact == 0) + UpdateAllAvatars(dat); + + CLUI__cliInvalidateRect(hwnd, NULL, FALSE); + return 0; +} + +static LRESULT clcOnIntmTimeZoneChanged(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + ClcContact *contact; + if (!FindItem(hwnd, dat, wParam, &contact, NULL, NULL, FALSE)) + return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); + + if (contact) { + Cache_GetTimezone(dat, contact->hContact); + Cache_GetText(dat, contact, 1); + cliRecalcScrollBar(hwnd, dat); + } + return 0; +} + +static LRESULT clcOnIntmNameChanged(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + int ret = corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); + + pcli->pfnInvalidateDisplayNameCacheEntry(wParam); + + ClcContact *contact; + if (!FindItem(hwnd, dat, wParam, &contact, NULL, NULL, FALSE)) + return ret; + + if (contact) { + mir_tstrncpy(contact->szText, pcli->pfnGetContactDisplayName(wParam, 0), _countof(contact->szText)); + Cache_GetText(dat, contact, 1); + cliRecalcScrollBar(hwnd, dat); + } + + dat->needsResort = 1; + return ret; +} + +static LRESULT clcOnIntmApparentModeChanged(ClcData *, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + return corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); +} + +static LRESULT clcOnIntmStatusMsgChanged(ClcData *dat, HWND hwnd, UINT msg, WPARAM hContact, LPARAM lParam) +{ + if (hContact == NULL || IsHContactInfo(hContact) || IsHContactGroup(hContact)) + return corecli.pfnContactListControlWndProc(hwnd, msg, hContact, lParam); + + ClcContact *contact; + if (!FindItem(hwnd, dat, hContact, &contact, NULL, NULL, FALSE)) + return corecli.pfnContactListControlWndProc(hwnd, msg, hContact, lParam); + + if (contact) { + Cache_GetText(dat, contact, 1); + cliRecalcScrollBar(hwnd, dat); + PostMessage(hwnd, INTM_INVALIDATE, 0, 0); + } + return corecli.pfnContactListControlWndProc(hwnd, msg, hContact, lParam); +} + +static LRESULT clcOnIntmNotOnListChanged(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + DBCONTACTWRITESETTING *dbcws = (DBCONTACTWRITESETTING*)lParam; + + ClcContact *contact; + if (!FindItem(hwnd, dat, 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(ClcData *dat, HWND hwnd, UINT, WPARAM, 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(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + int ret = corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); + if (wParam != 0) { + ClcCacheEntry *pdnce = pcli->pfnGetCacheEntry(wParam); + if (pdnce && pdnce->m_pszProto) { + pdnce->m_iStatus = GetStatusForContact(pdnce->hContact, pdnce->m_pszProto); + if (!dat->force_in_dialog && (dat->second_line_show || dat->third_line_show)) + gtaRenewText(pdnce->hContact); + SendMessage(hwnd, INTM_ICONCHANGED, wParam, corecli.pfnGetContactIcon(wParam)); + + ClcContact *contact; + if (FindItem(hwnd, dat, wParam, &contact, NULL, NULL, TRUE)) { + if (contact && contact->type == CLCIT_CONTACT) { + if (!contact->image_is_special && pdnce->getStatus() > ID_STATUS_OFFLINE) + contact->iImage = corecli.pfnGetContactIcon(wParam); + if (contact->isSubcontact && contact->subcontacts && contact->subcontacts->type == CLCIT_CONTACT) + pcli->pfnClcBroadcast(INTM_STATUSCHANGED, contact->subcontacts->hContact, 0); //forward status changing to host meta contact + } + } + } + } + + if (db_get_b(NULL, "CList", "PlaceOfflineToRoot", SETTING_PLACEOOFLINETOROOT_DEFAULT)) + pcli->pfnInitAutoRebuild(hwnd); + else + PostMessage(hwnd, INTM_INVALIDATE, 0, 0); + + return ret; +} + +static LRESULT clcOnIntmReloadOptions(ClcData *dat, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + corecli.pfnContactListControlWndProc(hwnd, msg, wParam, lParam); + pcli->pfnLoadClcOptions(hwnd, dat, FALSE); + LoadCLCOptions(hwnd, dat, FALSE); + pcli->pfnSaveStateAndRebuildList(hwnd, dat); + pcli->pfnSortCLC(hwnd, dat, 1); + if (IsWindowVisible(hwnd)) + pcli->pfnInvalidateRect(GetParent(hwnd), NULL, FALSE); + return TRUE; +} + +static int clcHookModulesLoaded(WPARAM, LPARAM) +{ + if (MirandaExiting()) + return 0; + + if (!ServiceExists(MS_AV_GETAVATARBITMAP)) + MessageBox(NULL, + TranslateT("Clist Modern requires AVS plugin to be present. Install it using PluginUpdater or download from http://wiki.miranda-ng.org/Download"), + TranslateT("Error loading plugin"), MB_ICONERROR | MB_OK); + + HookEvent(ME_AV_AVATARCHANGED, clcHookAvatarChanged); + + HookEvent(ME_MODERNOPT_INITIALIZE, ModernOptInit); + HookEvent(ME_MODERNOPT_INITIALIZE, ModernSkinOptInit); + + HookEvent(ME_FOLDERS_PATH_CHANGED, ReloadSkinFolder); + hSkinFolder = FoldersRegisterCustomPathT(LPGEN("Skins"), LPGEN("Modern contact list"), MIRANDA_PATHT _T("\\") _T(DEFAULT_SKIN_FOLDER)); + FoldersGetCustomPathT(hSkinFolder, SkinsFolder, _countof(SkinsFolder), _T(DEFAULT_SKIN_FOLDER)); + + // Get icons + TCHAR szMyPath[MAX_PATH]; + GetModuleFileName(g_hInst, szMyPath, _countof(szMyPath)); + + SKINICONDESC sid = { 0 }; + sid.defaultFile.t = szMyPath; + sid.flags = SIDF_PATH_TCHAR; + + sid.section.a = LPGEN("Contact list"); + sid.description.a = LPGEN("Listening to"); + sid.pszName = "LISTENING_TO_ICON"; + sid.iDefaultIndex = -IDI_LISTENING_TO; + IcoLib_AddIcon(&sid); + + sid.section.a = LPGEN("Contact list") "/" LPGEN("Avatar overlay"); + for (int i = 0; i < _countof(g_pAvatarOverlayIcons); i++) { + sid.description.a = g_pAvatarOverlayIcons[i].description; + sid.pszName = g_pAvatarOverlayIcons[i].name; + sid.iDefaultIndex = -g_pAvatarOverlayIcons[i].id; + IcoLib_AddIcon(&sid); + } + + sid.section.a = LPGEN("Contact list") "/" LPGEN("Status overlay"); + for (int i = 0; i < _countof(g_pStatusOverlayIcons); i++) { + sid.description.a = g_pStatusOverlayIcons[i].description; + sid.pszName = g_pStatusOverlayIcons[i].name; + sid.iDefaultIndex = -g_pStatusOverlayIcons[i].id; + IcoLib_AddIcon(&sid); + } + + clcHookIconsChanged(0, 0); + + 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); + + HookEvent(ME_SMILEYADD_OPTIONSCHANGED, clcHookSmileyAddOptionsChanged); + } + + CallService(MS_BACKGROUNDCONFIG_REGISTER, (WPARAM)(LPGEN("List background")"/CLC"), 0); + CallService(MS_BACKGROUNDCONFIG_REGISTER, (WPARAM)(LPGEN("Menu background")"/Menu"), 0); + CallService(MS_BACKGROUNDCONFIG_REGISTER, (WPARAM)(LPGEN("Status bar background")"/StatusBar"), 0); + CallService(MS_BACKGROUNDCONFIG_REGISTER, (WPARAM)(LPGEN("Frames title bar 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; +} + +HRESULT ClcLoadModule() +{ + g_himlCListClc = (HIMAGELIST)CallService(MS_CLIST_GETICONSIMAGELIST, 0, 0); + + HookEvent(ME_MC_SUBCONTACTSCHANGED, clcMetacontactChanged); + HookEvent(ME_MC_ENABLED, clcMetaModeChanged); + HookEvent(ME_DB_CONTACT_SETTINGCHANGED, clcHookSettingChanged); + HookEvent(ME_OPT_INITIALISE, ClcOptInit); + 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(MCONTACT, ACKDATA *ack) +{ + if (MirandaExiting()) return 0; + if (ack->type == ACKTYPE_STATUS) { + if (ack->result == ACKRESULT_SUCCESS) { + for (int i = 0; i < pcli->hClcProtoCount; i++) { + if (!mir_strcmp(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); + return 0; + } + } + } + } + else if (ack->type == ACKTYPE_AWAYMSG) { + if (ack->result == ACKRESULT_SUCCESS && ack->lParam) { + 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 { + 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_strcmpi(val, "")) + db_set_s(ack->hContact, "CList", "StatusMsg", ""); + else + gtaRenewText(ack->hContact); + mir_free(val); + } + } + } + } + else if (ack->type == ACKTYPE_EMAIL) { + CLUIUnreadEmailCountChanged(0, 0); + } + return 0; +} + +int ClcGetShortData(ClcData* pData, 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; + + mir_tstrncpy(pShortData->second_line_text, pData->second_line_text, _countof(pShortData->second_line_text)); + + 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; + + // Third line + 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; + + mir_tstrncpy(pShortData->third_line_text, pData->third_line_text, _countof(pShortData->third_line_text)); + + 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) +{ + if (IsDragToScrollMode) + return 0; + + ClcData *dat = (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); + + ClcData *dat = (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); + } +} diff --git a/plugins/Clist_modern/src/modern_clcitems.cpp b/plugins/Clist_modern/src/modern_clcitems.cpp index 2a9c992cf6..087d67ab56 100644 --- a/plugins/Clist_modern/src/modern_clcitems.cpp +++ b/plugins/Clist_modern/src/modern_clcitems.cpp @@ -1,750 +1,749 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-16 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. -*/ - -#include "stdafx.h" -#include "modern_clc.h" -#include "modern_clist.h" -#include "m_metacontacts.h" -#include "modern_commonprototypes.h" - -void AddSubcontacts(ClcData *dat, ClcContact *cont, BOOL showOfflineHereGroup) -{ - ClcCacheEntry *cacheEntry = pcli->pfnGetCacheEntry(cont->hContact); - cont->SubExpanded = (db_get_b(cont->hContact, "CList", "Expanded", 0) && (db_get_b(NULL, "CLC", "MetaExpanding", SETTING_METAEXPANDING_DEFAULT))); - int subcount = db_mc_getSubCount(cont->hContact); - if (subcount <= 0) { - cont->isSubcontact = 0; - cont->subcontacts = NULL; - cont->SubAllocated = 0; - return; - } - - cont->isSubcontact = 0; - mir_free(cont->subcontacts); - cont->subcontacts = (ClcContact *)mir_calloc(sizeof(ClcContact)*subcount); - cont->SubAllocated = subcount; - int i = 0; - int bHideOffline = db_get_b(NULL, "CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT); - for (int j = 0; j < subcount; j++) { - MCONTACT hsub = db_mc_getSub(cont->hContact, j); - cacheEntry = pcli->pfnGetCacheEntry(hsub); - WORD wStatus = cacheEntry->getStatus(); - - if (!showOfflineHereGroup && bHideOffline && !cacheEntry->m_bNoHiddenOffline && wStatus == ID_STATUS_OFFLINE) - continue; - - ClcContact& p = cont->subcontacts[i]; - p.hContact = cacheEntry->hContact; - - p.avatar_pos = AVATAR_POS_DONT_HAVE; - Cache_GetAvatar(dat, &p); - - p.iImage = corecli.pfnGetContactIcon(cacheEntry->hContact); - memset(p.iExtraImage, 0xFF, sizeof(p.iExtraImage)); - p.proto = cacheEntry->m_pszProto; - p.type = CLCIT_CONTACT; - p.flags = 0;//CONTACTF_ONLINE; - p.isSubcontact = i + 1; - p.lastPaintCounter = 0; - p.subcontacts = cont; - p.image_is_special = FALSE; - //p.status = cacheEntry->status; - Cache_GetTimezone(dat, (&p)->hContact); - Cache_GetText(dat, &p, 1); - - char *szProto = cacheEntry->m_pszProto; - if (szProto != NULL && !pcli->pfnIsHiddenMode(dat, wStatus)) - p.flags |= CONTACTF_ONLINE; - int apparentMode = szProto != NULL ? cacheEntry->ApparentMode : 0; - if (apparentMode == ID_STATUS_OFFLINE) p.flags |= CONTACTF_INVISTO; - else if (apparentMode == ID_STATUS_ONLINE) p.flags |= CONTACTF_VISTO; - else if (apparentMode) p.flags |= CONTACTF_VISTO | CONTACTF_INVISTO; - if (cacheEntry->NotOnList) p.flags |= CONTACTF_NOTONLIST; - int idleMode = szProto != NULL ? cacheEntry->IdleTS : 0; - if (idleMode) p.flags |= CONTACTF_IDLE; - i++; - } - - cont->SubAllocated = i; - if (!i && cont->subcontacts != NULL) - mir_free_and_nil(cont->subcontacts); -} - -int cli_AddItemToGroup(ClcGroup *group, int iAboveItem) -{ - if (group == NULL) - return 0; - - iAboveItem = corecli.pfnAddItemToGroup(group, iAboveItem); - ClearRowByIndexCache(); - return iAboveItem; -} - -ClcGroup* cli_AddGroup(HWND hwnd, ClcData *dat, const TCHAR *szName, DWORD flags, int groupId, int calcTotalMembers) -{ - ClearRowByIndexCache(); - if (!dat->force_in_dialog && !(GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_SHOWHIDDEN)) - if (!mir_tstrcmp(_T("-@-HIDDEN-GROUP-@-"), szName)) { //group is hidden - ClearRowByIndexCache(); - return NULL; - } - - ClcGroup *result = corecli.pfnAddGroup(hwnd, dat, szName, flags, groupId, calcTotalMembers); - ClearRowByIndexCache(); - return result; -} - -void cli_FreeContact(ClcContact *p) -{ - if (p->SubAllocated) { - if (p->subcontacts && !p->isSubcontact) { - for (int 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->SubAllocated = 0; - } - - 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(ClcGroup* group) -{ - corecli.pfnFreeGroup(group); - ClearRowByIndexCache(); -} - -int cli_AddInfoItemToGroup(ClcGroup *group, int flags, const TCHAR *pszText) -{ - int i = corecli.pfnAddInfoItemToGroup(group, flags, pszText); - ClearRowByIndexCache(); - return i; -} - -static void _LoadDataToContact(ClcContact *cont, ClcGroup *group, ClcData *dat, MCONTACT hContact) -{ - 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); - - ClcCacheEntry *cacheEntry = pcli->pfnGetCacheEntry(hContact); - char *szProto = cacheEntry->m_pszProto; - cont->proto = szProto; - - if (szProto != NULL && !pcli->pfnIsHiddenMode(dat, cacheEntry->m_iStatus)) - cont->flags |= CONTACTF_ONLINE; - - WORD 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; - - DWORD idleMode = szProto != NULL ? cacheEntry->IdleTS : 0; - if (idleMode) - cont->flags |= CONTACTF_IDLE; - - // Add subcontacts - if (szProto) - if (dat->IsMetaContactsEnabled && mir_strcmp(cont->proto, META_PROTO) == 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 = corecli.pfnGetContactIcon(hContact); - cont->bContactRate = db_get_b(hContact, "CList", "Rate", 0); -} - -static ClcContact* AddContactToGroup(ClcData *dat, ClcGroup *group, ClcCacheEntry *cacheEntry) -{ - if (cacheEntry == NULL || group == NULL || dat == NULL) - return NULL; - - MCONTACT hContact = cacheEntry->hContact; - dat->needsResort = 1; - int i; - 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 = pcli->pfnGetCacheEntry(hContact); - ClearRowByIndexCache(); - return group->cl.items[i]; -} - -void* AddTempGroup(HWND hwnd, ClcData *dat, const TCHAR *szName) -{ - if (wildcmp(_T2A(szName), "-@-HIDDEN-GROUP-@-")) - return NULL; - - int i; - DWORD groupFlags; - for (i = 1;; i++) { - TCHAR *szGroupName = pcli->pfnGetGroupName(i, &groupFlags); - if (szGroupName == NULL) - break; - if (!mir_tstrcmpi(szGroupName, szName)) - return NULL; - } - - char buf[20]; - _itoa_s(i - 1, buf, 10); - - TCHAR b2[255]; - mir_sntprintf(b2, _T("#%s"), szName); - b2[0] = 1 | GROUPF_EXPANDED; - db_set_ts(NULL, "CListGroups", buf, b2); - pcli->pfnGetGroupName(i, &groupFlags); - return cli_AddGroup(hwnd, dat, szName, groupFlags, i, 0); -} - -void cli_AddContactToTree(HWND hwnd, ClcData *dat, MCONTACT hContact, int updateTotalCount, int checkHideOffline) -{ - ClcCacheEntry *cacheEntry = pcli->pfnGetCacheEntry(hContact); - if (dat->IsMetaContactsEnabled && cacheEntry && cacheEntry->m_bIsSub) - return; //contact should not be added - - if (!dat->IsMetaContactsEnabled && cacheEntry && !mir_strcmp(cacheEntry->m_pszProto, META_PROTO)) - return; - - corecli.pfnAddContactToTree(hwnd, dat, hContact, updateTotalCount, checkHideOffline); - - ClcGroup *group; - ClcContact *cont; - if (FindItem(hwnd, dat, hContact, &cont, &group, NULL, FALSE)) - _LoadDataToContact(cont, group, dat, hContact); -} - -void cli_DeleteItemFromTree(HWND hwnd, MCONTACT hContact) -{ - ClcData *dat = (ClcData *)GetWindowLongPtr(hwnd, 0); - ClearRowByIndexCache(); - corecli.pfnDeleteItemFromTree(hwnd, hContact); - - // check here contacts are not resorting - if (hwnd == pcli->hwndContactTree) { +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (ñ) 2012-16 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. +*/ + +#include "stdafx.h" +#include "modern_clc.h" +#include "modern_clist.h" +#include "m_metacontacts.h" +#include "modern_commonprototypes.h" + +void AddSubcontacts(ClcData *dat, ClcContact *cont, BOOL showOfflineHereGroup) +{ + ClcCacheEntry *cacheEntry = pcli->pfnGetCacheEntry(cont->hContact); + cont->SubExpanded = (db_get_b(cont->hContact, "CList", "Expanded", 0) && (db_get_b(NULL, "CLC", "MetaExpanding", SETTING_METAEXPANDING_DEFAULT))); + int subcount = db_mc_getSubCount(cont->hContact); + if (subcount <= 0) { + cont->isSubcontact = 0; + cont->subcontacts = NULL; + cont->SubAllocated = 0; + return; + } + + cont->isSubcontact = 0; + mir_free(cont->subcontacts); + cont->subcontacts = (ClcContact *)mir_calloc(sizeof(ClcContact)*subcount); + cont->SubAllocated = subcount; + int i = 0; + int bHideOffline = db_get_b(NULL, "CList", "HideOffline", SETTING_HIDEOFFLINE_DEFAULT); + for (int j = 0; j < subcount; j++) { + MCONTACT hsub = db_mc_getSub(cont->hContact, j); + cacheEntry = pcli->pfnGetCacheEntry(hsub); + WORD wStatus = cacheEntry->getStatus(); + + if (!showOfflineHereGroup && bHideOffline && !cacheEntry->m_bNoHiddenOffline && wStatus == ID_STATUS_OFFLINE) + continue; + + ClcContact& p = cont->subcontacts[i]; + p.hContact = cacheEntry->hContact; + + p.avatar_pos = AVATAR_POS_DONT_HAVE; + Cache_GetAvatar(dat, &p); + + p.iImage = corecli.pfnGetContactIcon(cacheEntry->hContact); + memset(p.iExtraImage, 0xFF, sizeof(p.iExtraImage)); + p.proto = cacheEntry->m_pszProto; + p.type = CLCIT_CONTACT; + p.flags = 0;//CONTACTF_ONLINE; + p.isSubcontact = i + 1; + p.lastPaintCounter = 0; + p.subcontacts = cont; + p.image_is_special = FALSE; + //p.status = cacheEntry->status; + Cache_GetTimezone(dat, (&p)->hContact); + Cache_GetText(dat, &p, 1); + + char *szProto = cacheEntry->m_pszProto; + if (szProto != NULL && !pcli->pfnIsHiddenMode(dat, wStatus)) + p.flags |= CONTACTF_ONLINE; + int apparentMode = szProto != NULL ? cacheEntry->ApparentMode : 0; + if (apparentMode == ID_STATUS_OFFLINE) p.flags |= CONTACTF_INVISTO; + else if (apparentMode == ID_STATUS_ONLINE) p.flags |= CONTACTF_VISTO; + else if (apparentMode) p.flags |= CONTACTF_VISTO | CONTACTF_INVISTO; + if (cacheEntry->NotOnList) p.flags |= CONTACTF_NOTONLIST; + int idleMode = szProto != NULL ? cacheEntry->IdleTS : 0; + if (idleMode) p.flags |= CONTACTF_IDLE; + i++; + } + + cont->SubAllocated = i; + if (!i && cont->subcontacts != NULL) + mir_free_and_nil(cont->subcontacts); +} + +int cli_AddItemToGroup(ClcGroup *group, int iAboveItem) +{ + if (group == NULL) + return 0; + + iAboveItem = corecli.pfnAddItemToGroup(group, iAboveItem); + ClearRowByIndexCache(); + return iAboveItem; +} + +ClcGroup* cli_AddGroup(HWND hwnd, ClcData *dat, const TCHAR *szName, DWORD flags, int groupId, int calcTotalMembers) +{ + ClearRowByIndexCache(); + if (!dat->force_in_dialog && !(GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_SHOWHIDDEN)) + if (!mir_tstrcmp(_T("-@-HIDDEN-GROUP-@-"), szName)) { //group is hidden + ClearRowByIndexCache(); + return NULL; + } + + ClcGroup *result = corecli.pfnAddGroup(hwnd, dat, szName, flags, groupId, calcTotalMembers); + ClearRowByIndexCache(); + return result; +} + +void cli_FreeContact(ClcContact *p) +{ + if (p->SubAllocated) { + if (p->subcontacts && !p->isSubcontact) { + for (int 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->SubAllocated = 0; + } + + 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(ClcGroup* group) +{ + corecli.pfnFreeGroup(group); + ClearRowByIndexCache(); +} + +int cli_AddInfoItemToGroup(ClcGroup *group, int flags, const TCHAR *pszText) +{ + int i = corecli.pfnAddInfoItemToGroup(group, flags, pszText); + ClearRowByIndexCache(); + return i; +} + +static void _LoadDataToContact(ClcContact *cont, ClcGroup *group, ClcData *dat, MCONTACT hContact) +{ + 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); + + ClcCacheEntry *cacheEntry = pcli->pfnGetCacheEntry(hContact); + char *szProto = cacheEntry->m_pszProto; + cont->proto = szProto; + + if (szProto != NULL && !pcli->pfnIsHiddenMode(dat, cacheEntry->m_iStatus)) + cont->flags |= CONTACTF_ONLINE; + + WORD 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; + + DWORD idleMode = szProto != NULL ? cacheEntry->IdleTS : 0; + if (idleMode) + cont->flags |= CONTACTF_IDLE; + + // Add subcontacts + if (szProto) + if (dat->IsMetaContactsEnabled && mir_strcmp(cont->proto, META_PROTO) == 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 = corecli.pfnGetContactIcon(hContact); + cont->bContactRate = db_get_b(hContact, "CList", "Rate", 0); +} + +static ClcContact* AddContactToGroup(ClcData *dat, ClcGroup *group, ClcCacheEntry *cacheEntry) +{ + if (cacheEntry == NULL || group == NULL || dat == NULL) + return NULL; + + MCONTACT hContact = cacheEntry->hContact; + dat->needsResort = 1; + int i; + 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 = pcli->pfnGetCacheEntry(hContact); + ClearRowByIndexCache(); + return group->cl.items[i]; +} + +void* AddTempGroup(HWND hwnd, ClcData *dat, const TCHAR *szName) +{ + if (wildcmp(_T2A(szName), "-@-HIDDEN-GROUP-@-")) + return NULL; + + int i; + DWORD groupFlags; + for (i = 1;; i++) { + TCHAR *szGroupName = pcli->pfnGetGroupName(i, &groupFlags); + if (szGroupName == NULL) + break; + if (!mir_tstrcmpi(szGroupName, szName)) + return NULL; + } + + char buf[20]; + _itoa_s(i - 1, buf, 10); + + TCHAR b2[255]; + mir_sntprintf(b2, _T("#%s"), szName); + b2[0] = 1 | GROUPF_EXPANDED; + db_set_ts(NULL, "CListGroups", buf, b2); + pcli->pfnGetGroupName(i, &groupFlags); + return cli_AddGroup(hwnd, dat, szName, groupFlags, i, 0); +} + +void cli_AddContactToTree(HWND hwnd, ClcData *dat, MCONTACT hContact, int updateTotalCount, int checkHideOffline) +{ + ClcCacheEntry *cacheEntry = pcli->pfnGetCacheEntry(hContact); + if (dat->IsMetaContactsEnabled && cacheEntry && cacheEntry->m_bIsSub) + return; //contact should not be added + + if (!dat->IsMetaContactsEnabled && cacheEntry && !mir_strcmp(cacheEntry->m_pszProto, META_PROTO)) + return; + + corecli.pfnAddContactToTree(hwnd, dat, hContact, updateTotalCount, checkHideOffline); + + ClcGroup *group; + ClcContact *cont; + if (FindItem(hwnd, dat, hContact, &cont, &group, NULL, FALSE)) + _LoadDataToContact(cont, group, dat, hContact); +} + +void cli_DeleteItemFromTree(HWND hwnd, MCONTACT hContact) +{ + ClcData *dat = (ClcData *)GetWindowLongPtr(hwnd, 0); + ClearRowByIndexCache(); + corecli.pfnDeleteItemFromTree(hwnd, hContact); + + // check here contacts are not resorting + if (hwnd == pcli->hwndContactTree) { int idx = clistCache.getIndex((ClcCacheEntry*)&hContact); if (idx != -1) { - pcli->pfnFreeCacheItem(clistCache[idx]); - clistCache.remove(idx); - } - } - - dat->needsResort = 1; - ClearRowByIndexCache(); -} - -bool CLCItems_IsShowOfflineGroup(ClcGroup *group) -{ - if (!group) return false; - if (group->hideOffline) return false; - - DWORD groupFlags = 0; - pcli->pfnGetGroupName(group->groupId, &groupFlags); - return (groupFlags & GROUPF_SHOWOFFLINE) != 0; -} - -MCONTACT SaveSelection(ClcData *dat) -{ - ClcContact *selcontact = NULL; - if (pcli->pfnGetRowByIndex(dat, dat->selection, &selcontact, NULL) == -1) - return NULL; - - return (DWORD_PTR)pcli->pfnContactToHItem(selcontact); -} - -int RestoreSelection(ClcData *dat, MCONTACT 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, ClcData *dat) -{ - DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE); - ClcGroup *group = NULL; - static int rebuildCounter = 0; - - BOOL PlaceOfflineToRoot = db_get_b(NULL, "CList", "PlaceOfflineToRoot", SETTING_PLACEOFFLINETOROOT_DEFAULT); - KillTimer(hwnd, TIMERID_REBUILDAFTER); + pcli->pfnFreeCacheItem(clistCache[idx]); + clistCache.remove(idx); + } + } + + dat->needsResort = 1; + ClearRowByIndexCache(); +} + +bool CLCItems_IsShowOfflineGroup(ClcGroup *group) +{ + if (!group) return false; + if (group->hideOffline) return false; + + DWORD groupFlags = 0; + pcli->pfnGetGroupName(group->groupId, &groupFlags); + return (groupFlags & GROUPF_SHOWOFFLINE) != 0; +} + +MCONTACT SaveSelection(ClcData *dat) +{ + ClcContact *selcontact = NULL; + if (pcli->pfnGetRowByIndex(dat, dat->selection, &selcontact, NULL) == -1) + return NULL; + + return (DWORD_PTR)pcli->pfnContactToHItem(selcontact); +} + +int RestoreSelection(ClcData *dat, MCONTACT 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, ClcData *dat) +{ + DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE); + ClcGroup *group = NULL; + static int rebuildCounter = 0; + + BOOL PlaceOfflineToRoot = db_get_b(NULL, "CList", "PlaceOfflineToRoot", SETTING_PLACEOFFLINETOROOT_DEFAULT); + KillTimer(hwnd, TIMERID_REBUILDAFTER); pcli->bAutoRebuild = false; - - 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->needsResort = 1; - - MCONTACT hSelected = SaveSelection(dat); - dat->selection = -1; - dat->HiLightMode = db_get_b(NULL, "CLC", "HiLightMode", SETTING_HILIGHTMODE_DEFAULT); - - for (int i = 1;; i++) { - DWORD groupFlags; - TCHAR *szGroupName = pcli->pfnGetGroupName(i, &groupFlags); //UNICODE - if (szGroupName == NULL) - break; - cli_AddGroup(hwnd, dat, szGroupName, groupFlags, i, 0); - } - - for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { - ClcContact *cont = NULL; - ClcCacheEntry *cacheEntry = pcli->pfnGetCacheEntry(hContact); - - int nHiddenStatus = CLVM_GetContactHiddenStatus(hContact, NULL, dat); - if ((style & CLS_SHOWHIDDEN && nHiddenStatus != -1) || !nHiddenStatus) { - if (mir_tstrlen(cacheEntry->tszGroup) == 0) - group = &dat->list; - else - group = cli_AddGroup(hwnd, dat, cacheEntry->tszGroup, (DWORD)-1, 0, 0); - - if (group != NULL) { - if (cacheEntry->m_iStatus == ID_STATUS_OFFLINE && PlaceOfflineToRoot) - group = &dat->list; - - group->totalMembers++; - - if (!(style & CLS_NOHIDEOFFLINE) && (style & CLS_HIDEOFFLINE || group->hideOffline)) { - if (cacheEntry->m_pszProto == NULL) { - if (!pcli->pfnIsHiddenMode(dat, ID_STATUS_OFFLINE) || cacheEntry->m_bNoHiddenOffline || CLCItems_IsShowOfflineGroup(group)) - cont = AddContactToGroup(dat, group, cacheEntry); - } - else if (!pcli->pfnIsHiddenMode(dat, cacheEntry->m_iStatus) || cacheEntry->m_bNoHiddenOffline || CLCItems_IsShowOfflineGroup(group)) - cont = AddContactToGroup(dat, group, cacheEntry); - } - else cont = AddContactToGroup(dat, group, cacheEntry); - } - } - if (cont) { - cont->SubAllocated = 0; - if (cont->proto && dat->IsMetaContactsEnabled && mir_strcmp(cont->proto, META_PROTO) == 0) - AddSubcontacts(dat, cont, CLCItems_IsShowOfflineGroup(group)); - } - } - - 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, ClcData *dat, int useInsertionSort) -{ - MCONTACT hSelected = SaveSelection(dat); - corecli.pfnSortCLC(hwnd, dat, useInsertionSort); - RestoreSelection(dat, hSelected); -} - -int GetNewSelection(ClcGroup *group, int selection, int direction) -{ - if (selection < 0) - return 0; - - int lastcount = 0, count = 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 && 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 -{ - MCONTACT hContact; - WORD iExtraImage[EXTRA_ICON_COUNT]; - int checked; -}; - -struct SavedGroupState_t -{ - int groupId, expanded; -}; - -struct SavedInfoState_t -{ - int parentId; - ClcContact contact; -}; - -BOOL LOCK_RECALC_SCROLLBAR = FALSE; -void cli_SaveStateAndRebuildList(HWND hwnd, ClcData *dat) -{ - LOCK_RECALC_SCROLLBAR = TRUE; - - NMCLISTCONTROL nm; - int i, j; - OBJLIST savedGroup(4); - OBJLIST savedContact(4); - OBJLIST savedInfo(4); - - ClcGroup *group; - ClcContact *contact; - - pcli->pfnHideInfoTip(hwnd, dat); - KillTimer(hwnd, TIMERID_INFOTIP); - KillTimer(hwnd, TIMERID_RENAME); - pcli->pfnEndRename(hwnd, dat, 1); - - dat->needsResort = 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; - memcpy(p->iExtraImage, group->cl.items[group->scanIndex]->iExtraImage, sizeof(p->iExtraImage)); - 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) { - memcpy(group->cl.items[group->scanIndex]->iExtraImage, savedContact[i].iExtraImage, sizeof(contact->iExtraImage)); - if (savedContact[i].checked) - group->cl.items[group->scanIndex]->flags |= CONTACTF_CHECKED; - break; - } - } - group->scanIndex++; - } - - for (i = 0; i < savedInfo.getCount(); i++) { - if (savedInfo[i].parentId == -1) - group = &dat->list; - else { - if (!pcli->pfnFindItem(hwnd, dat, 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; - } - - 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); -} - -ClcContact* cliCreateClcContact() -{ - ClcContact* contact = (ClcContact*)mir_calloc(sizeof(ClcContact)); - memset(contact->iExtraImage, 0xFF, sizeof(contact->iExtraImage)); - return contact; -} - -ClcCacheEntry* cliCreateCacheItem(MCONTACT hContact) -{ - ClcCacheEntry *p = (ClcCacheEntry *)mir_calloc(sizeof(ClcCacheEntry)); - if (p == NULL) - return NULL; - - p->hContact = hContact; - p->m_pszProto = GetContactProto(hContact); + + 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->needsResort = 1; + + MCONTACT hSelected = SaveSelection(dat); + dat->selection = -1; + dat->HiLightMode = db_get_b(NULL, "CLC", "HiLightMode", SETTING_HILIGHTMODE_DEFAULT); + + for (int i = 1;; i++) { + DWORD groupFlags; + TCHAR *szGroupName = pcli->pfnGetGroupName(i, &groupFlags); //UNICODE + if (szGroupName == NULL) + break; + cli_AddGroup(hwnd, dat, szGroupName, groupFlags, i, 0); + } + + for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { + ClcContact *cont = NULL; + ClcCacheEntry *cacheEntry = pcli->pfnGetCacheEntry(hContact); + + int nHiddenStatus = CLVM_GetContactHiddenStatus(hContact, NULL, dat); + if ((style & CLS_SHOWHIDDEN && nHiddenStatus != -1) || !nHiddenStatus) { + if (mir_tstrlen(cacheEntry->tszGroup) == 0) + group = &dat->list; + else + group = cli_AddGroup(hwnd, dat, cacheEntry->tszGroup, (DWORD)-1, 0, 0); + + if (group != NULL) { + if (cacheEntry->m_iStatus == ID_STATUS_OFFLINE && PlaceOfflineToRoot) + group = &dat->list; + + group->totalMembers++; + + if (!(style & CLS_NOHIDEOFFLINE) && (style & CLS_HIDEOFFLINE || group->hideOffline)) { + if (cacheEntry->m_pszProto == NULL) { + if (!pcli->pfnIsHiddenMode(dat, ID_STATUS_OFFLINE) || cacheEntry->m_bNoHiddenOffline || CLCItems_IsShowOfflineGroup(group)) + cont = AddContactToGroup(dat, group, cacheEntry); + } + else if (!pcli->pfnIsHiddenMode(dat, cacheEntry->m_iStatus) || cacheEntry->m_bNoHiddenOffline || CLCItems_IsShowOfflineGroup(group)) + cont = AddContactToGroup(dat, group, cacheEntry); + } + else cont = AddContactToGroup(dat, group, cacheEntry); + } + } + if (cont) { + cont->SubAllocated = 0; + if (cont->proto && dat->IsMetaContactsEnabled && mir_strcmp(cont->proto, META_PROTO) == 0) + AddSubcontacts(dat, cont, CLCItems_IsShowOfflineGroup(group)); + } + } + + 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, ClcData *dat, int useInsertionSort) +{ + MCONTACT hSelected = SaveSelection(dat); + corecli.pfnSortCLC(hwnd, dat, useInsertionSort); + RestoreSelection(dat, hSelected); +} + +int GetNewSelection(ClcGroup *group, int selection, int direction) +{ + if (selection < 0) + return 0; + + int lastcount = 0, count = 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 && 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 +{ + MCONTACT hContact; + WORD iExtraImage[EXTRA_ICON_COUNT]; + int checked; +}; + +struct SavedGroupState_t +{ + int groupId, expanded; +}; + +struct SavedInfoState_t +{ + int parentId; + ClcContact contact; +}; + +BOOL LOCK_RECALC_SCROLLBAR = FALSE; +void cli_SaveStateAndRebuildList(HWND hwnd, ClcData *dat) +{ + LOCK_RECALC_SCROLLBAR = TRUE; + + NMCLISTCONTROL nm; + int i, j; + OBJLIST savedGroup(4); + OBJLIST savedContact(4); + OBJLIST savedInfo(4); + + ClcGroup *group; + ClcContact *contact; + + pcli->pfnHideInfoTip(hwnd, dat); + KillTimer(hwnd, TIMERID_INFOTIP); + KillTimer(hwnd, TIMERID_RENAME); + pcli->pfnEndRename(hwnd, dat, 1); + + dat->needsResort = 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; + memcpy(p->iExtraImage, group->cl.items[group->scanIndex]->iExtraImage, sizeof(p->iExtraImage)); + 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) { + memcpy(group->cl.items[group->scanIndex]->iExtraImage, savedContact[i].iExtraImage, sizeof(contact->iExtraImage)); + if (savedContact[i].checked) + group->cl.items[group->scanIndex]->flags |= CONTACTF_CHECKED; + break; + } + } + group->scanIndex++; + } + + for (i = 0; i < savedInfo.getCount(); i++) { + if (savedInfo[i].parentId == -1) + group = &dat->list; + else { + if (!pcli->pfnFindItem(hwnd, dat, 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; + } + + 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); +} + +ClcContact* cliCreateClcContact() +{ + ClcContact* contact = (ClcContact*)mir_calloc(sizeof(ClcContact)); + memset(contact->iExtraImage, 0xFF, sizeof(contact->iExtraImage)); + return contact; +} + +ClcCacheEntry* cliCreateCacheItem(MCONTACT hContact) +{ + ClcCacheEntry *p = (ClcCacheEntry *)mir_calloc(sizeof(ClcCacheEntry)); + if (p == NULL) + return NULL; + + p->hContact = hContact; + p->m_pszProto = GetContactProto(hContact); p->dwLastMsgTime = -1; p->bIsHidden = -1; p->m_bNoHiddenOffline = -1; p->IdleTS = -1; p->NotOnList = -1; p->IsExpanded = -1; - return p; -} - -void cliInvalidateDisplayNameCacheEntry(MCONTACT hContact) -{ - if (hContact == INVALID_CONTACT_ID) - corecli.pfnInvalidateDisplayNameCacheEntry(INVALID_CONTACT_ID); - else { - ClcCacheEntry *p = pcli->pfnGetCacheEntry(hContact); - if (p) + return p; +} + +void cliInvalidateDisplayNameCacheEntry(MCONTACT hContact) +{ + if (hContact == INVALID_CONTACT_ID) + corecli.pfnInvalidateDisplayNameCacheEntry(INVALID_CONTACT_ID); + else { + ClcCacheEntry *p = pcli->pfnGetCacheEntry(hContact); + if (p) p->m_iStatus = 0; - } -} - -void cli_SetContactCheckboxes(ClcContact *cc, int checked) -{ - corecli.pfnSetContactCheckboxes(cc, checked); - - for (int i = 0; i < cc->SubAllocated; i++) - corecli.pfnSetContactCheckboxes(&cc->subcontacts[i], checked); -} - -TCHAR* cli_GetGroupCountsText(ClcData *dat, ClcContact *contact) -{ - return corecli.pfnGetGroupCountsText(dat, contact); -} - -int cliGetGroupContentsCount(ClcGroup *group, int visibleOnly) -{ - int count = group->cl.count; - 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(MCONTACT hContact, char *szProto, ClcData *dat) -{ - int dbHidden = db_get_b(hContact, "CList", "Hidden", 0); // default hidden state, always respect it. - int filterResult = 1; - int searchResult = 0; - DBVARIANT dbv = { 0 }; - char szTemp[64]; - TCHAR szGroupMask[256]; - DWORD dwLocalMask; - ClcCacheEntry *pdnce = pcli->pfnGetCacheEntry(hContact); - // always hide subcontacts (but show them on embedded contact lists) - - if (dat != NULL && dat->IsMetaContactsEnabled && db_mc_isSub(hContact)) - return -1; //subcontact - if (pdnce && pdnce->m_bIsUnknown && dat != NULL && !dat->force_in_dialog) - return 1; //'Unknown Contact' - if (dat != NULL && dat->filterSearch && pdnce && pdnce->tszName) { - // search filtering - TCHAR *lowered_name = CharLowerW(NEWTSTR_ALLOCA(pdnce->tszName)); - TCHAR *lowered_search = CharLowerW(NEWTSTR_ALLOCA(dat->szQuickSearch)); - searchResult = _tcsstr(lowered_name, lowered_search) ? 0 : 1; - } - if (pdnce && g_CluiData.bFilterEffective && dat != NULL && !dat->force_in_dialog) { - if (szProto == NULL) - szProto = GetContactProto(hContact); - // 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)) | searchResult; - } - return 0 | searchResult; - } - } - // check the proto, use it as a base filter result for all further checks - if (g_CluiData.bFilterEffective & CLVM_FILTER_PROTOS) { - mir_snprintf(szTemp, "%s|", szProto); - filterResult = strstr(g_CluiData.protoFilter, szTemp) ? 1 : 0; - } - if (g_CluiData.bFilterEffective & CLVM_FILTER_GROUPS) { - if (!db_get_ts(hContact, "CList", "Group", &dbv)) { - mir_sntprintf(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) { - if (pdnce->dwLastMsgTime != -1) { - DWORD 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 | searchResult); - } - - return dbHidden | searchResult; -} + } +} + +void cli_SetContactCheckboxes(ClcContact *cc, int checked) +{ + corecli.pfnSetContactCheckboxes(cc, checked); + + for (int i = 0; i < cc->SubAllocated; i++) + corecli.pfnSetContactCheckboxes(&cc->subcontacts[i], checked); +} + +TCHAR* cli_GetGroupCountsText(ClcData *dat, ClcContact *contact) +{ + return corecli.pfnGetGroupCountsText(dat, contact); +} + +int cliGetGroupContentsCount(ClcGroup *group, int visibleOnly) +{ + int count = group->cl.count; + 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(MCONTACT hContact, char *szProto, ClcData *dat) +{ + int dbHidden = db_get_b(hContact, "CList", "Hidden", 0); // default hidden state, always respect it. + int filterResult = 1; + int searchResult = 0; + DBVARIANT dbv = { 0 }; + char szTemp[64]; + TCHAR szGroupMask[256]; + DWORD dwLocalMask; + ClcCacheEntry *pdnce = pcli->pfnGetCacheEntry(hContact); + // always hide subcontacts (but show them on embedded contact lists) + + if (dat != NULL && dat->IsMetaContactsEnabled && db_mc_isSub(hContact)) + return -1; //subcontact + if (pdnce && pdnce->m_bIsUnknown && dat != NULL && !dat->force_in_dialog) + return 1; //'Unknown Contact' + if (dat != NULL && dat->filterSearch && pdnce && pdnce->tszName) { + // search filtering + TCHAR *lowered_name = CharLowerW(NEWTSTR_ALLOCA(pdnce->tszName)); + TCHAR *lowered_search = CharLowerW(NEWTSTR_ALLOCA(dat->szQuickSearch)); + searchResult = _tcsstr(lowered_name, lowered_search) ? 0 : 1; + } + if (pdnce && g_CluiData.bFilterEffective && dat != NULL && !dat->force_in_dialog) { + if (szProto == NULL) + szProto = GetContactProto(hContact); + // 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)) | searchResult; + } + return 0 | searchResult; + } + } + // check the proto, use it as a base filter result for all further checks + if (g_CluiData.bFilterEffective & CLVM_FILTER_PROTOS) { + mir_snprintf(szTemp, "%s|", szProto); + filterResult = strstr(g_CluiData.protoFilter, szTemp) ? 1 : 0; + } + if (g_CluiData.bFilterEffective & CLVM_FILTER_GROUPS) { + if (!db_get_ts(hContact, "CList", "Group", &dbv)) { + mir_sntprintf(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) { + if (pdnce->dwLastMsgTime != -1) { + DWORD 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 | searchResult); + } + + return dbHidden | searchResult; +} diff --git a/plugins/Clist_modern/src/modern_clcmsgs.cpp b/plugins/Clist_modern/src/modern_clcmsgs.cpp index eec91381b3..6748c9eaa4 100644 --- a/plugins/Clist_modern/src/modern_clcmsgs.cpp +++ b/plugins/Clist_modern/src/modern_clcmsgs.cpp @@ -26,8 +26,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "modern_clc.h" #include "modern_commonprototypes.h" +///////////////////////////////////////////////////////////////////////////////////////// //processing of all the CLM_ messages incoming - +// LRESULT cli_ProcessExternalMessages(HWND hwnd, ClcData *dat, UINT msg, WPARAM wParam, LPARAM lParam) { ClcContact *contact = NULL; diff --git a/plugins/Clist_modern/src/modern_clcpaint.cpp b/plugins/Clist_modern/src/modern_clcpaint.cpp index 4638fad9f8..cfaa374d46 100644 --- a/plugins/Clist_modern/src/modern_clcpaint.cpp +++ b/plugins/Clist_modern/src/modern_clcpaint.cpp @@ -553,8 +553,11 @@ MODERNMASK* CLCPaint::_GetCLCContactRowBackModernMask(ClcGroup *group, ClcContac switch (Drawing->type) { case CLCIT_GROUP: _AddParamShort(mpModernMask, hi_Type, hi_Group); - _AddParamShort(mpModernMask, hi_Open, (Drawing->group && Drawing->group->expanded) ? hi_True : hi_False); - _AddParamShort(mpModernMask, hi_IsEmpty, (Drawing->group->cl.count == 0) ? hi_True : hi_False); + if (Drawing->group) + { + _AddParamShort(mpModernMask, hi_Open, Drawing->group->expanded ? hi_True : hi_False); + _AddParamShort(mpModernMask, hi_IsEmpty, (Drawing->group->cl.count == 0) ? hi_True : hi_False); + } break; case CLCIT_CONTACT: @@ -1413,6 +1416,7 @@ void CLCPaint::_PaintRowItemsEx(HWND hwnd, HDC hdcMem, ClcData *dat, ClcContact } } } + break; case TC_TIME: TCHAR szResult[80]; diff --git a/plugins/Clist_modern/src/modern_skinselector.cpp b/plugins/Clist_modern/src/modern_skinselector.cpp index 89e7f970a2..26fd11ec91 100644 --- a/plugins/Clist_modern/src/modern_skinselector.cpp +++ b/plugins/Clist_modern/src/modern_skinselector.cpp @@ -57,7 +57,7 @@ DWORD mod_CalcHash(const char *szStr) return hash; } -int AddModernMaskToList(MODERNMASK *mm, LISTMODERNMASK * mmTemplateList) +static 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)); @@ -77,7 +77,7 @@ int ClearMaskList(LISTMODERNMASK * mmTemplateList) return 0; } -int DeleteMaskByItID(DWORD mID, LISTMODERNMASK *mmTemplateList) +static int DeleteMaskByItID(DWORD mID, LISTMODERNMASK *mmTemplateList) { if (!mmTemplateList) return -1; if (mID >= mmTemplateList->dwMaskCnt) return -1; @@ -103,7 +103,7 @@ int DeleteMaskByItID(DWORD mID, LISTMODERNMASK *mmTemplateList) } -int ExchangeMasksByID(DWORD mID1, DWORD mID2, LISTMODERNMASK * mmTemplateList) +static int ExchangeMasksByID(DWORD mID1, DWORD mID2, LISTMODERNMASK * mmTemplateList) { if (!mmTemplateList) return 0; if (mID1 >= mmTemplateList->dwMaskCnt) return 0; @@ -232,7 +232,7 @@ static BOOL _GetParamValue(char *szText, unsigned int &start, unsigned int lengt return (value || param); } -int ParseToModernMask(MODERNMASK *mm, char *szText) +static int ParseToModernMask(MODERNMASK *mm, char *szText) { if (!mm || !szText) return -1; @@ -279,7 +279,7 @@ int ParseToModernMask(MODERNMASK *mm, char *szText) return 0; }; -BOOL CompareModernMask(MODERNMASK *mmValue, MODERNMASK *mmTemplate) +static BOOL CompareModernMask(MODERNMASK *mmValue, MODERNMASK *mmTemplate) { //TODO BOOL res = TRUE; diff --git a/plugins/Clist_modern/src/modern_skinselector.h b/plugins/Clist_modern/src/modern_skinselector.h index c145595c9d..e0cc3606c7 100644 --- a/plugins/Clist_modern/src/modern_skinselector.h +++ b/plugins/Clist_modern/src/modern_skinselector.h @@ -65,18 +65,11 @@ struct LISTMODERNMASK }; /// PROTOTYPES -int AddModernMaskToList(MODERNMASK *mm, LISTMODERNMASK *mmTemplateList); int AddStrModernMaskToList(DWORD maskID, char *szStr, char *objectName, LISTMODERNMASK *mmTemplateList); 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); int RegisterObjectByParce(char * ObjectName, char *Params); SKINOBJECTDESCRIPTOR* skin_FindObjectByRequest(char *szValue, LISTMODERNMASK *mmTemplateList); -- cgit v1.2.3