summaryrefslogtreecommitdiff
path: root/plugins/Clist_modern/src/modern_clcitems.cpp
diff options
context:
space:
mode:
authorRozhuk Ivan <rozhuk.im@gmail.com>2014-11-27 00:44:57 +0000
committerRozhuk Ivan <rozhuk.im@gmail.com>2014-11-27 00:44:57 +0000
commit117cf2ba6883c5b3ff8b275f4c56eb562a219b95 (patch)
tree748e5d8b028b589151183452cbdb3306a7afa2c1 /plugins/Clist_modern/src/modern_clcitems.cpp
parentbd1e3d8fe219dcbc55584d95dfba6ddae0d01d2c (diff)
Clist_modern: code cleanup, review required
git-svn-id: http://svn.miranda-ng.org/main/trunk@11113 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/Clist_modern/src/modern_clcitems.cpp')
-rw-r--r--plugins/Clist_modern/src/modern_clcitems.cpp1493
1 files changed, 746 insertions, 747 deletions
diff --git a/plugins/Clist_modern/src/modern_clcitems.cpp b/plugins/Clist_modern/src/modern_clcitems.cpp
index 402a242098..9c5ecc6c1e 100644
--- a/plugins/Clist_modern/src/modern_clcitems.cpp
+++ b/plugins/Clist_modern/src/modern_clcitems.cpp
@@ -1,747 +1,746 @@
-/*
-
-Miranda NG: the free IM client for Microsoft* Windows*
-
-Copyright (c) 2012-14 Miranda NG project (http://miranda-ng.org),
-Copyright (c) 2000-08 Miranda ICQ/IM project,
-all portions of this codebase are copyrighted to the people
-listed in contributors.txt.
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "hdr/modern_commonheaders.h"
-#include "hdr/modern_clc.h"
-#include "hdr/modern_clist.h"
-#include "m_metacontacts.h"
-#include "hdr/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 = pdnce___GetStatus(cacheEntry);
-
- if (!showOfflineHereGroup && bHideOffline && !cacheEntry->m_cache_nNoHiddenOffline && 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_cache_cszProto;
- 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_cache_cszProto;
- 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 (!lstrcmp(_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->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_cache_cszProto;
- cont->proto = szProto;
-
- if (szProto != NULL && !pcli->pfnIsHiddenMode(dat, pdnce___GetStatus(cacheEntry)))
- 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) return NULL;
- if (group == NULL) return NULL;
- if (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, DWORD flags, int groupId, int calcTotalMembers)
-{
- int i = 0;
- int f = 0;
- DWORD groupFlags;
-
- if (wildcmp(_T2A(szName), "-@-HIDDEN-GROUP-@-"))
- return NULL;
-
- for (i = 1;; i++) {
- TCHAR *szGroupName = pcli->pfnGetGroupName(i, &groupFlags);
- if (szGroupName == NULL) break;
- if (!mir_tstrcmpi(szGroupName, szName)) f = 1;
- }
-
- if (f)
- return NULL;
-
- char buf[20];
- _itoa_s(i-1, buf, 10);
-
- TCHAR b2[255];
- mir_sntprintf(b2, SIZEOF(b2), _T("#%s"), szName);
- b2[0] = 1 | GROUPF_EXPANDED;
- db_set_ws(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_cache_cszProto, 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 hItem)
-{
- ClcData *dat = (ClcData *)GetWindowLongPtr(hwnd, 0);
- ClearRowByIndexCache();
- corecli.pfnDeleteItemFromTree(hwnd, hItem);
-
- // check here contacts are not resorting
- if (hwnd == pcli->hwndContactTree)
- pcli->pfnFreeCacheItem(pcli->pfnGetCacheEntry(hItem));
- dat->needsResort = 1;
- ClearRowByIndexCache();
-}
-
-__inline BOOL CLCItems_IsShowOfflineGroup(ClcGroup* group)
-{
- DWORD groupFlags = 0;
- if (!group) return FALSE;
- if (group->hideOffline) return FALSE;
- 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 (MCONTACT)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;
- static int rebuildCounter = 0;
-
- BOOL PlaceOfflineToRoot = db_get_b(NULL, "CList", "PlaceOfflineToRoot", SETTING_PLACEOFFLINETOROOT_DEFAULT);
- KillTimer(hwnd, TIMERID_REBUILDAFTER);
-
- ClearRowByIndexCache();
- ImageArray_Clear(&dat->avatar_cache);
- RowHeights_Clear(dat);
- RowHeights_GetMaxRowHeight(dat, hwnd);
- TRACEVAR("Rebuild Entire List %d times\n", ++rebuildCounter);
-
- dat->list.expanded = 1;
- dat->list.hideOffline = db_get_b(NULL, "CLC", "HideOfflineRoot", SETTING_HIDEOFFLINEATROOT_DEFAULT) && style&CLS_USEGROUPS;
- dat->list.cl.count = dat->list.cl.limit = 0;
- dat->list.cl.increment = 50;
- dat->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 (lstrlen(cacheEntry->tszGroup) == 0)
- group = &dat->list;
- else
- group = cli_AddGroup(hwnd, dat, cacheEntry->tszGroup, (DWORD)-1, 0, 0);
-
- if (group != NULL) {
- WORD wStatus = pdnce___GetStatus(cacheEntry);
- if (wStatus == ID_STATUS_OFFLINE && PlaceOfflineToRoot)
- group = &dat->list;
-
- group->totalMembers++;
-
- if (!(style & CLS_NOHIDEOFFLINE) && (style & CLS_HIDEOFFLINE || group->hideOffline)) {
- if (cacheEntry->m_cache_cszProto == NULL) {
- if (!pcli->pfnIsHiddenMode(dat, ID_STATUS_OFFLINE) || cacheEntry->m_cache_nNoHiddenOffline || CLCItems_IsShowOfflineGroup(group))
- cont = AddContactToGroup(dat, group, cacheEntry);
- }
- else if (!pcli->pfnIsHiddenMode(dat, wStatus) || cacheEntry->m_cache_nNoHiddenOffline || CLCItems_IsShowOfflineGroup(group))
- cont = AddContactToGroup(dat, group, cacheEntry);
- }
- else cont = AddContactToGroup(dat, group, cacheEntry);
- }
- }
- if (cont) {
- cont->SubAllocated = 0;
- if (cont->proto && dat->IsMetaContactsEnabled && 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<SavedGroupState_t> savedGroup(4);
- OBJLIST<SavedContactState_t> savedContact(4);
- OBJLIST<SavedInfoState_t> 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);
-}
-
-
-WORD pdnce___GetStatus(ClcCacheEntry *pdnce)
-{
- return (!pdnce) ? ID_STATUS_OFFLINE : pdnce->m_cache_nStatus;
-}
-
-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;
- InvalidateDNCEbyPointer(hContact, p, 0);
- p->szSecondLineText = NULL;
- p->szThirdLineText = NULL;
- p->ssSecondLine.plText = NULL;
- p->ssThirdLine.plText = NULL;
- return p;
-}
-
-void cliInvalidateDisplayNameCacheEntry(MCONTACT hContact)
-{
- if (hContact == INVALID_CONTACT_ID)
- corecli.pfnInvalidateDisplayNameCacheEntry(INVALID_CONTACT_ID);
- else {
- ClcCacheEntry *p = pcli->pfnGetCacheEntry(hContact);
- if (p)
- InvalidateDNCEbyPointer(hContact, p, 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);
-}
-
-char* 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);
- BOOL fEmbedded = dat->force_in_dialog;
- // 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->isUnknown && !fEmbedded)
- return 1; //'Unknown Contact'
- if (dat->filterSearch && dat->szQuickSearch && 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 && !fEmbedded) {
- 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, SIZEOF(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, SIZEOF(szGroupMask), _T("%s|"), &dbv.ptszVal[0]);
- filterResult = (g_CluiData.filterFlags & CLVM_PROTOGROUP_OP) ? (filterResult | (_tcsstr(g_CluiData.groupFilter, szGroupMask) ? 1 : 0)) : (filterResult & (_tcsstr(g_CluiData.groupFilter, szGroupMask) ? 1 : 0));
- mir_free(dbv.ptszVal);
- }
- else if (g_CluiData.filterFlags & CLVM_INCLUDED_UNGROUPED)
- filterResult = (g_CluiData.filterFlags & CLVM_PROTOGROUP_OP) ? filterResult : filterResult & 1;
- else
- filterResult = (g_CluiData.filterFlags & CLVM_PROTOGROUP_OP) ? filterResult : filterResult & 0;
- }
- if (g_CluiData.bFilterEffective & CLVM_FILTER_STATUS) {
- WORD wStatus = db_get_w(hContact, szProto, "Status", ID_STATUS_OFFLINE);
- filterResult = (g_CluiData.filterFlags & CLVM_GROUPSTATUS_OP) ? ((filterResult | ((1 << (wStatus - ID_STATUS_OFFLINE)) & g_CluiData.statusMaskFilter ? 1 : 0))) : (filterResult & ((1 << (wStatus - ID_STATUS_OFFLINE)) & g_CluiData.statusMaskFilter ? 1 : 0));
- }
- if (g_CluiData.bFilterEffective & CLVM_FILTER_LASTMSG) {
- if (pdnce && 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;
-}
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (c) 2012-14 Miranda NG project (http://miranda-ng.org),
+Copyright (c) 2000-08 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "hdr/modern_commonheaders.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_clist.h"
+#include "m_metacontacts.h"
+#include "hdr/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 = pdnce___GetStatus(cacheEntry);
+
+ if (!showOfflineHereGroup && bHideOffline && !cacheEntry->m_cache_nNoHiddenOffline && 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_cache_cszProto;
+ 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_cache_cszProto;
+ 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 (!lstrcmp(_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->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_cache_cszProto;
+ cont->proto = szProto;
+
+ if (szProto != NULL && !pcli->pfnIsHiddenMode(dat, pdnce___GetStatus(cacheEntry)))
+ 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) return NULL;
+ if (group == NULL) return NULL;
+ if (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, DWORD flags, int groupId, int calcTotalMembers)
+{
+ int i = 0;
+ int f = 0;
+ DWORD groupFlags;
+
+ if (wildcmp(_T2A(szName), "-@-HIDDEN-GROUP-@-"))
+ return NULL;
+
+ for (i = 1;; i++) {
+ TCHAR *szGroupName = pcli->pfnGetGroupName(i, &groupFlags);
+ if (szGroupName == NULL) break;
+ if (!mir_tstrcmpi(szGroupName, szName)) f = 1;
+ }
+
+ if (f)
+ return NULL;
+
+ char buf[20];
+ _itoa_s(i-1, buf, 10);
+
+ TCHAR b2[255];
+ mir_sntprintf(b2, SIZEOF(b2), _T("#%s"), szName);
+ b2[0] = 1 | GROUPF_EXPANDED;
+ db_set_ws(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_cache_cszProto, 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 hItem)
+{
+ ClcData *dat = (ClcData *)GetWindowLongPtr(hwnd, 0);
+ ClearRowByIndexCache();
+ corecli.pfnDeleteItemFromTree(hwnd, hItem);
+
+ // check here contacts are not resorting
+ if (hwnd == pcli->hwndContactTree)
+ pcli->pfnFreeCacheItem(pcli->pfnGetCacheEntry(hItem));
+ dat->needsResort = 1;
+ ClearRowByIndexCache();
+}
+
+__inline BOOL CLCItems_IsShowOfflineGroup(ClcGroup* group)
+{
+ DWORD groupFlags = 0;
+ if (!group) return FALSE;
+ if (group->hideOffline) return FALSE;
+ 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 (MCONTACT)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;
+ static int rebuildCounter = 0;
+
+ BOOL PlaceOfflineToRoot = db_get_b(NULL, "CList", "PlaceOfflineToRoot", SETTING_PLACEOFFLINETOROOT_DEFAULT);
+ KillTimer(hwnd, TIMERID_REBUILDAFTER);
+
+ ClearRowByIndexCache();
+ ImageArray_Clear(&dat->avatar_cache);
+ RowHeights_Clear(dat);
+ RowHeights_GetMaxRowHeight(dat, hwnd);
+ TRACEVAR("Rebuild Entire List %d times\n", ++rebuildCounter);
+
+ dat->list.expanded = 1;
+ dat->list.hideOffline = db_get_b(NULL, "CLC", "HideOfflineRoot", SETTING_HIDEOFFLINEATROOT_DEFAULT) && style&CLS_USEGROUPS;
+ dat->list.cl.count = dat->list.cl.limit = 0;
+ dat->list.cl.increment = 50;
+ dat->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 (lstrlen(cacheEntry->tszGroup) == 0)
+ group = &dat->list;
+ else
+ group = cli_AddGroup(hwnd, dat, cacheEntry->tszGroup, (DWORD)-1, 0, 0);
+
+ if (group != NULL) {
+ WORD wStatus = pdnce___GetStatus(cacheEntry);
+ if (wStatus == ID_STATUS_OFFLINE && PlaceOfflineToRoot)
+ group = &dat->list;
+
+ group->totalMembers++;
+
+ if (!(style & CLS_NOHIDEOFFLINE) && (style & CLS_HIDEOFFLINE || group->hideOffline)) {
+ if (cacheEntry->m_cache_cszProto == NULL) {
+ if (!pcli->pfnIsHiddenMode(dat, ID_STATUS_OFFLINE) || cacheEntry->m_cache_nNoHiddenOffline || CLCItems_IsShowOfflineGroup(group))
+ cont = AddContactToGroup(dat, group, cacheEntry);
+ }
+ else if (!pcli->pfnIsHiddenMode(dat, wStatus) || cacheEntry->m_cache_nNoHiddenOffline || CLCItems_IsShowOfflineGroup(group))
+ cont = AddContactToGroup(dat, group, cacheEntry);
+ }
+ else cont = AddContactToGroup(dat, group, cacheEntry);
+ }
+ }
+ if (cont) {
+ cont->SubAllocated = 0;
+ if (cont->proto && dat->IsMetaContactsEnabled && 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<SavedGroupState_t> savedGroup(4);
+ OBJLIST<SavedContactState_t> savedContact(4);
+ OBJLIST<SavedInfoState_t> 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);
+}
+
+
+WORD pdnce___GetStatus(ClcCacheEntry *pdnce)
+{
+ return (!pdnce) ? ID_STATUS_OFFLINE : pdnce->m_cache_nStatus;
+}
+
+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;
+ InvalidateDNCEbyPointer(hContact, p, 0);
+ p->szSecondLineText = NULL;
+ p->szThirdLineText = NULL;
+ p->ssSecondLine.plText = NULL;
+ p->ssThirdLine.plText = NULL;
+ return p;
+}
+
+void cliInvalidateDisplayNameCacheEntry(MCONTACT hContact)
+{
+ if (hContact == INVALID_CONTACT_ID)
+ corecli.pfnInvalidateDisplayNameCacheEntry(INVALID_CONTACT_ID);
+ else {
+ ClcCacheEntry *p = pcli->pfnGetCacheEntry(hContact);
+ if (p)
+ InvalidateDNCEbyPointer(hContact, p, 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);
+}
+
+char* 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->isUnknown && dat != NULL && !dat->force_in_dialog)
+ return 1; //'Unknown Contact'
+ if (dat != NULL && dat->filterSearch && dat->szQuickSearch && 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, SIZEOF(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, SIZEOF(szGroupMask), _T("%s|"), &dbv.ptszVal[0]);
+ filterResult = (g_CluiData.filterFlags & CLVM_PROTOGROUP_OP) ? (filterResult | (_tcsstr(g_CluiData.groupFilter, szGroupMask) ? 1 : 0)) : (filterResult & (_tcsstr(g_CluiData.groupFilter, szGroupMask) ? 1 : 0));
+ mir_free(dbv.ptszVal);
+ }
+ else if (g_CluiData.filterFlags & CLVM_INCLUDED_UNGROUPED)
+ filterResult = (g_CluiData.filterFlags & CLVM_PROTOGROUP_OP) ? filterResult : filterResult & 1;
+ else
+ filterResult = (g_CluiData.filterFlags & CLVM_PROTOGROUP_OP) ? filterResult : filterResult & 0;
+ }
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_STATUS) {
+ WORD wStatus = db_get_w(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ filterResult = (g_CluiData.filterFlags & CLVM_GROUPSTATUS_OP) ? ((filterResult | ((1 << (wStatus - ID_STATUS_OFFLINE)) & g_CluiData.statusMaskFilter ? 1 : 0))) : (filterResult & ((1 << (wStatus - ID_STATUS_OFFLINE)) & g_CluiData.statusMaskFilter ? 1 : 0));
+ }
+ if (g_CluiData.bFilterEffective & CLVM_FILTER_LASTMSG) {
+ 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;
+}