summaryrefslogtreecommitdiff
path: root/plugins/Clist_modern/modern_clcitems.cpp
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2012-06-17 12:44:02 +0000
committerGeorge Hazan <george.hazan@gmail.com>2012-06-17 12:44:02 +0000
commitf673f034c2fef25e932a12fbd5e2772f90c75e6d (patch)
treeaeaac57c13fd2a23e47e437d804957d67e5413ee /plugins/Clist_modern/modern_clcitems.cpp
parentbce08282b66209eb482726a7ec6c89083db327ac (diff)
Clist_mw & Clist_modern renamed
git-svn-id: http://svn.miranda-ng.org/main/trunk@455 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/Clist_modern/modern_clcitems.cpp')
-rw-r--r--plugins/Clist_modern/modern_clcitems.cpp823
1 files changed, 823 insertions, 0 deletions
diff --git a/plugins/Clist_modern/modern_clcitems.cpp b/plugins/Clist_modern/modern_clcitems.cpp
new file mode 100644
index 0000000000..367bbb57de
--- /dev/null
+++ b/plugins/Clist_modern/modern_clcitems.cpp
@@ -0,0 +1,823 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2008 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "hdr/modern_commonheaders.h"
+#include "m_clc.h"
+#include "hdr/modern_clc.h"
+#include "hdr/modern_clist.h"
+#include "m_metacontacts.h"
+#include "hdr/modern_commonprototypes.h"
+
+void AddSubcontacts(struct ClcData *dat, struct ClcContact * cont, BOOL showOfflineHereGroup)
+{
+ int subcount,i,j;
+ HANDLE hsub;
+ pdisplayNameCacheEntry cacheEntry;
+ cacheEntry=(pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(cont->hContact);
+ cont->SubExpanded=(ModernGetSettingByte(cont->hContact,"CList","Expanded",0) && (ModernGetSettingByte(NULL,"CLC","MetaExpanding",SETTING_METAEXPANDING_DEFAULT)));
+ subcount=(int)CallService(MS_MC_GETNUMCONTACTS,(WPARAM)cont->hContact,0);
+
+ if (subcount <= 0) {
+ cont->isSubcontact=0;
+ cont->subcontacts=NULL;
+ cont->SubAllocated=0;
+ return;
+ }
+
+ cont->isSubcontact=0;
+ mir_free(cont->subcontacts);
+ cont->subcontacts=(struct ClcContact *) mir_calloc(sizeof(struct ClcContact)*subcount);
+ cont->SubAllocated=subcount;
+ i=0;
+ for (j=0; j<subcount; j++) {
+ WORD wStatus;
+
+ hsub=(HANDLE)CallService(MS_MC_GETSUBCONTACT,(WPARAM)cont->hContact,j);
+ cacheEntry=(pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hsub);
+ wStatus=pdnce___GetStatus( cacheEntry );
+ if (showOfflineHereGroup||(!(ModernGetSettingByte(NULL,"CLC","MetaHideOfflineSub",SETTING_METAHIDEOFFLINESUB_DEFAULT) && ModernGetSettingByte(NULL,"CList","HideOffline",SETTING_HIDEOFFLINE_DEFAULT) ) ||
+ wStatus!=ID_STATUS_OFFLINE )
+ //&&
+ //(!cacheEntry->Hidden || style&CLS_SHOWHIDDEN)
+ )
+
+ {
+ cont->subcontacts[i].hContact=cacheEntry->m_cache_hContact;
+
+ cont->subcontacts[i].avatar_pos = AVATAR_POS_DONT_HAVE;
+ Cache_GetAvatar(dat, &cont->subcontacts[i]);
+
+ cont->subcontacts[i].iImage=CallService(MS_CLIST_GETCONTACTICON,(WPARAM)cacheEntry->m_cache_hContact,1);
+ memset(cont->subcontacts[i].iExtraImage,0xFF,sizeof(cont->subcontacts[i].iExtraImage));
+ memset((void*)cont->subcontacts[i].iWideExtraImage,0xFF,sizeof(cont->subcontacts[i].iWideExtraImage));
+ cont->subcontacts[i].proto=cacheEntry->m_cache_cszProto;
+ cont->subcontacts[i].type=CLCIT_CONTACT;
+ cont->subcontacts[i].flags=0;//CONTACTF_ONLINE;
+ cont->subcontacts[i].isSubcontact=i+1;
+ cont->subcontacts[i].lastPaintCounter=0;
+ cont->subcontacts[i].subcontacts=cont;
+ cont->subcontacts[i].image_is_special=FALSE;
+ //cont->subcontacts[i].status=cacheEntry->status;
+ Cache_GetTimezone(dat, (&cont->subcontacts[i])->hContact);
+ Cache_GetText(dat, &cont->subcontacts[i],1);
+
+ {
+ int apparentMode;
+ char *szProto;
+ int idleMode;
+ szProto=cacheEntry->m_cache_cszProto;
+ if(szProto!=NULL && !pcli->pfnIsHiddenMode(dat,wStatus))
+ cont->subcontacts[i].flags|=CONTACTF_ONLINE;
+ apparentMode=szProto!=NULL?cacheEntry->ApparentMode:0;
+ apparentMode=szProto!=NULL?cacheEntry->ApparentMode:0;
+ if(apparentMode==ID_STATUS_OFFLINE) cont->subcontacts[i].flags|=CONTACTF_INVISTO;
+ else if(apparentMode==ID_STATUS_ONLINE) cont->subcontacts[i].flags|=CONTACTF_VISTO;
+ else if(apparentMode) cont->subcontacts[i].flags|=CONTACTF_VISTO|CONTACTF_INVISTO;
+ if(cacheEntry->NotOnList) cont->subcontacts[i].flags|=CONTACTF_NOTONLIST;
+ idleMode=szProto!=NULL?cacheEntry->IdleTS:0;
+ if (idleMode) cont->subcontacts[i].flags|=CONTACTF_IDLE;
+ }
+ i++;
+ } }
+
+ cont->SubAllocated=i;
+ if (!i && cont->subcontacts != NULL) mir_free_and_nill(cont->subcontacts);
+}
+
+int cli_AddItemToGroup(struct ClcGroup *group,int iAboveItem)
+{
+ if ( group == NULL ) return 0;
+
+ iAboveItem = corecli.pfnAddItemToGroup( group, iAboveItem );
+ ClearRowByIndexCache();
+ return iAboveItem;
+}
+
+struct ClcGroup *cli_AddGroup(HWND hwnd,struct ClcData *dat,const TCHAR *szName,DWORD flags,int groupId,int calcTotalMembers)
+{
+ struct ClcGroup* result;
+ ClearRowByIndexCache();
+ if (!dat->force_in_dialog && !(GetWindowLongPtr(hwnd, GWL_STYLE) & CLS_SHOWHIDDEN))
+ if (!lstrcmp(_T("-@-HIDDEN-GROUP-@-"),szName)) //group is hidden
+ {
+ ClearRowByIndexCache();
+ return NULL;
+ }
+ result = corecli.pfnAddGroup( hwnd, dat, szName, flags, groupId, calcTotalMembers);
+ /* ToDo: fix some times valid contact with valid group are placed to root
+ if ( result == NULL )
+ {
+ result = &dat->list;
+ }
+ */
+ ClearRowByIndexCache();
+ return result;
+}
+
+void cli_FreeContact(struct ClcContact *p)
+{
+ if ( p->SubAllocated) {
+ if ( p->subcontacts && !p->isSubcontact) {
+ int i;
+ for ( i = 0 ; i < p->SubAllocated ; i++ ) {
+ p->subcontacts[i].ssText.DestroySmileyList();
+ if ( p->subcontacts[i].avatar_pos==AVATAR_POS_ANIMATED )
+ AniAva_RemoveAvatar( p->subcontacts[i].hContact );
+ p->subcontacts[i].avatar_pos=AVATAR_POS_DONT_HAVE;
+ }
+ mir_free_and_nill(p->subcontacts);
+ } }
+
+ p->ssText.DestroySmileyList();
+ if ( p->avatar_pos==AVATAR_POS_ANIMATED )
+ AniAva_RemoveAvatar( p->hContact );
+ p->avatar_pos=AVATAR_POS_DONT_HAVE;
+ corecli.pfnFreeContact( p );
+}
+
+void cli_FreeGroup( struct ClcGroup* group )
+{
+ corecli.pfnFreeGroup( group );
+ ClearRowByIndexCache();
+}
+
+int cli_AddInfoItemToGroup(struct ClcGroup *group,int flags,const TCHAR *pszText)
+{
+ int i = corecli.pfnAddInfoItemToGroup( group, flags, pszText );
+ ClearRowByIndexCache();
+ return i;
+}
+
+static void _LoadDataToContact(struct ClcContact * cont, struct ClcGroup *group, struct ClcData *dat, HANDLE hContact)
+{
+ pdisplayNameCacheEntry cacheEntry=NULL;
+ WORD apparentMode;
+ DWORD idleMode;
+ char * szProto;
+
+ if (!cont) return;
+ cont->type=CLCIT_CONTACT;
+ cont->SubAllocated=0;
+ cont->isSubcontact=0;
+ cont->subcontacts=NULL;
+ cont->szText[0]=0;
+ cont->lastPaintCounter=0;
+ cont->image_is_special=FALSE;
+ cont->hContact=hContact;
+
+ pcli->pfnInvalidateDisplayNameCacheEntry(hContact);
+ cacheEntry=(pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+
+ szProto=cacheEntry->m_cache_cszProto;
+ cont->proto=szProto;
+
+ if(szProto!=NULL&&!pcli->pfnIsHiddenMode(dat,pdnce___GetStatus( cacheEntry )))
+ cont->flags |= CONTACTF_ONLINE;
+
+ apparentMode=szProto!=NULL?cacheEntry->ApparentMode:0;
+
+ if (apparentMode)
+ switch (apparentMode)
+ {
+ case ID_STATUS_OFFLINE:
+ cont->flags|=CONTACTF_INVISTO;
+ break;
+ case ID_STATUS_ONLINE:
+ cont->flags|=CONTACTF_VISTO;
+ break;
+ default:
+ cont->flags|=CONTACTF_VISTO|CONTACTF_INVISTO;
+ }
+
+ if(cacheEntry->NotOnList)
+ cont->flags|=CONTACTF_NOTONLIST;
+ idleMode=szProto!=NULL?cacheEntry->IdleTS:0;
+
+ if (idleMode)
+ cont->flags|=CONTACTF_IDLE;
+
+
+ //Add subcontacts
+ if (szProto)
+ {
+ if ( g_szMetaModuleName && dat->IsMetaContactsEnabled && mir_strcmp(cont->proto,g_szMetaModuleName)==0)
+ AddSubcontacts(dat,cont,CLCItems_IsShowOfflineGroup(group));
+ }
+ cont->lastPaintCounter=0;
+ cont->avatar_pos=AVATAR_POS_DONT_HAVE;
+ Cache_GetAvatar(dat,cont);
+ Cache_GetText(dat,cont,1);
+ Cache_GetTimezone(dat,cont->hContact);
+ cont->iImage=CallService(MS_CLIST_GETCONTACTICON,(WPARAM)hContact,1);
+ cont->bContactRate=ModernGetSettingByte(hContact, "CList", "Rate",0);
+}
+
+static struct ClcContact * AddContactToGroup(struct ClcData *dat,struct ClcGroup *group, pdisplayNameCacheEntry cacheEntry)
+{
+ HANDLE hContact;
+ int i;
+ if (cacheEntry==NULL) return NULL;
+ if (group==NULL) return NULL;
+ if (dat==NULL) return NULL;
+ hContact=cacheEntry->m_cache_hContact;
+ dat->NeedResort=1;
+ for(i=group->cl.count-1;i>=0;i--)
+ if(group->cl.items[i]->type!=CLCIT_INFO || !(group->cl.items[i]->flags&CLCIIF_BELOWCONTACTS)) break;
+ i=cli_AddItemToGroup(group,i+1);
+
+ _LoadDataToContact(group->cl.items[i], group, dat, hContact);
+ cacheEntry=(pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ ClearRowByIndexCache();
+ return group->cl.items[i];
+}
+
+void * AddTempGroup(HWND hwnd,struct ClcData *dat,const TCHAR *szName,DWORD flags,int groupId,int calcTotalMembers)
+{
+ int i=0;
+ int f=0;
+ TCHAR * szGroupName;
+ DWORD groupFlags;
+ char *mbuf=mir_u2a((TCHAR *)szName);
+
+ if (wildcmp(mbuf,"-@-HIDDEN-GROUP-@-",0))
+ {
+ mir_free_and_nill(mbuf);
+ return NULL;
+ }
+ mir_free_and_nill(mbuf);
+ for(i=1;;i++)
+ {
+ szGroupName = pcli->pfnGetGroupName(i,&groupFlags);
+ if(szGroupName==NULL) break;
+ if (!mir_tstrcmpi(szGroupName,szName)) f=1;
+ }
+ if (!f)
+ {
+ char buf[20];
+ TCHAR b2[255];
+ void * res=NULL;
+ mir_snprintf(buf,SIZEOF(buf),"%d",(i-1));
+ mir_sntprintf(b2,SIZEOF(b2),_T("#%s"),szName);
+ b2[0]=1|GROUPF_EXPANDED;
+ ModernWriteSettingTString(NULL,"CListGroups",buf,b2);
+ pcli->pfnGetGroupName(i,&groupFlags);
+ res=cli_AddGroup(hwnd,dat,szName,groupFlags,i,0);
+ return res;
+ }
+ return NULL;
+}
+
+void cli_AddContactToTree(HWND hwnd,struct ClcData *dat,HANDLE hContact,int updateTotalCount,int checkHideOffline)
+{
+ struct ClcGroup *group;
+ struct ClcContact * cont;
+ pdisplayNameCacheEntry cacheEntry=(pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+ if(dat->IsMetaContactsEnabled && cacheEntry && cacheEntry->m_cache_nHiddenSubcontact) return; //contact should not be added
+ if (!dat->IsMetaContactsEnabled && cacheEntry && g_szMetaModuleName && !mir_strcmp(cacheEntry->m_cache_cszProto,g_szMetaModuleName)) return;
+ corecli.pfnAddContactToTree(hwnd,dat,hContact,updateTotalCount,checkHideOffline);
+ if (FindItem(hwnd,dat,hContact,&cont,&group,NULL,FALSE))
+ _LoadDataToContact(cont, group, dat, hContact);
+ return;
+}
+
+void cli_DeleteItemFromTree(HWND hwnd,HANDLE hItem)
+{
+ struct ClcData *dat = (struct ClcData *) GetWindowLongPtr(hwnd, 0);
+ ClearRowByIndexCache();
+ corecli.pfnDeleteItemFromTree(hwnd, hItem);
+
+ //check here contacts are not resorting
+ if (hwnd==pcli->hwndContactTree)
+ pcli->pfnFreeCacheItem(pcli->pfnGetCacheEntry(hItem));
+ dat->NeedResort=1;
+ ClearRowByIndexCache();
+}
+
+
+__inline BOOL CLCItems_IsShowOfflineGroup(struct ClcGroup* group)
+{
+ DWORD groupFlags=0;
+ if (!group) return FALSE;
+ if (group->hideOffline) return FALSE;
+ pcli->pfnGetGroupName(group->groupId,&groupFlags);
+ return (groupFlags&GROUPF_SHOWOFFLINE)!=0;
+}
+
+HANDLE SaveSelection( struct ClcData *dat )
+{
+ ClcContact * selcontact = NULL;
+
+ if ( pcli->pfnGetRowByIndex( dat, dat->selection, &selcontact, NULL ) == -1 )
+ return NULL;
+ else
+ return pcli->pfnContactToHItem( selcontact );
+}
+
+int RestoreSelection( struct ClcData *dat, HANDLE hSelected )
+{
+ ClcContact * selcontact = NULL;
+ ClcGroup * selgroup = NULL;
+
+ if ( !hSelected || !pcli->pfnFindItem( dat->hWnd, dat, hSelected, &selcontact, &selgroup, NULL) )
+ {
+ dat->selection = -1;
+ return dat->selection;
+ }
+
+ if ( !selcontact->isSubcontact )
+ {
+ dat->selection = pcli->pfnGetRowsPriorTo( &dat->list, selgroup, li.List_IndexOf((SortedList*)&selgroup->cl, selcontact ) );
+ }
+ else
+ {
+ dat->selection = pcli->pfnGetRowsPriorTo(&dat->list, selgroup, li.List_IndexOf((SortedList*)&selgroup->cl, selcontact->subcontacts ) );
+
+ if (dat->selection != -1 )
+ dat->selection += selcontact->isSubcontact;
+ }
+ return dat->selection;
+
+}
+
+void cliRebuildEntireList(HWND hwnd,struct ClcData *dat)
+{
+ DWORD style=GetWindowLongPtr(hwnd,GWL_STYLE);
+ HANDLE hContact;
+ struct ClcContact * cont;
+ struct ClcGroup *group;
+ static int rebuildCounter=0;
+
+ BOOL PlaceOfflineToRoot=ModernGetSettingByte(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=ModernGetSettingByte(NULL,"CLC","HideOfflineRoot",SETTING_HIDEOFFLINEATROOT_DEFAULT) && style&CLS_USEGROUPS;
+ dat->list.cl.count = dat->list.cl.limit = 0;
+ dat->list.cl.increment = 50;
+ dat->NeedResort=1;
+
+ HANDLE hSelected = SaveSelection( dat );
+ dat->selection=-1;
+ dat->HiLightMode=ModernGetSettingByte(NULL,"CLC","HiLightMode",SETTING_HILIGHTMODE_DEFAULT);
+ {
+ int i;
+ TCHAR *szGroupName;
+ DWORD groupFlags;
+
+ for(i=1;;i++) {
+ szGroupName=pcli->pfnGetGroupName(i,&groupFlags); //UNICODE
+ if(szGroupName==NULL) break;
+ cli_AddGroup(hwnd,dat,szGroupName,groupFlags,i,0);
+ }
+ }
+
+ hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0);
+ while(hContact)
+ {
+ pdisplayNameCacheEntry cacheEntry=NULL;
+ int nHiddenStatus;
+ cont=NULL;
+ cacheEntry=(pdisplayNameCacheEntry)pcli->pfnGetCacheEntry(hContact);
+
+ nHiddenStatus=CLVM_GetContactHiddenStatus(hContact, NULL, dat);
+ if ( (style&CLS_SHOWHIDDEN && nHiddenStatus!=-1) || !nHiddenStatus)
+ {
+
+ if(lstrlen(cacheEntry->m_cache_tcsGroup)==0)
+ group=&dat->list;
+ else {
+ group=cli_AddGroup(hwnd,dat,cacheEntry->m_cache_tcsGroup,(DWORD)-1,0,0);
+ }
+ if(group!=NULL)
+ {
+ WORD wStatus=pdnce___GetStatus( cacheEntry );
+ if (wStatus==ID_STATUS_OFFLINE)
+ if (PlaceOfflineToRoot)
+ group=&dat->list;
+ group->totalMembers++;
+
+ if (!(style&CLS_NOHIDEOFFLINE) && (style&CLS_HIDEOFFLINE || group->hideOffline))
+ {
+ if(cacheEntry->m_cache_cszProto==NULL) {
+ if (!pcli->pfnIsHiddenMode(dat,ID_STATUS_OFFLINE)||cacheEntry->m_cache_nNoHiddenOffline || CLCItems_IsShowOfflineGroup(group))
+ cont=AddContactToGroup(dat,group,cacheEntry);
+ }
+ else
+ if (!pcli->pfnIsHiddenMode(dat,wStatus)||cacheEntry->m_cache_nNoHiddenOffline || CLCItems_IsShowOfflineGroup(group))
+ cont=AddContactToGroup(dat,group,cacheEntry);
+ }
+ else cont=AddContactToGroup(dat,group,cacheEntry);
+ }
+ }
+ if (cont)
+ {
+ cont->SubAllocated=0;
+ if (cont->proto && g_szMetaModuleName && dat->IsMetaContactsEnabled && strcmp(cont->proto,g_szMetaModuleName)==0)
+ AddSubcontacts(dat,cont,CLCItems_IsShowOfflineGroup(group));
+ }
+ hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0);
+ }
+
+ if(style&CLS_HIDEEMPTYGROUPS) {
+ group=&dat->list;
+ group->scanIndex=0;
+ for (;;) {
+ if(group->scanIndex==group->cl.count) {
+ group=group->parent;
+ if(group==NULL) break;
+ }
+ else if(group->cl.items[group->scanIndex]->type==CLCIT_GROUP) {
+ if(group->cl.items[group->scanIndex]->group->cl.count==0) {
+ group=pcli->pfnRemoveItemFromGroup(hwnd,group,group->cl.items[group->scanIndex],0);
+ }
+ else {
+ group=group->cl.items[group->scanIndex]->group;
+ group->scanIndex=0;
+ }
+ continue;
+ }
+ group->scanIndex++;
+ }
+ }
+
+ pcli->pfnSortCLC(hwnd,dat,0);
+
+ RestoreSelection( dat, hSelected );
+
+}
+
+void cli_SortCLC( HWND hwnd, struct ClcData *dat, int useInsertionSort )
+{
+ HANDLE hSelected = SaveSelection( dat );
+
+ corecli.pfnSortCLC(hwnd,dat,useInsertionSort);
+
+ RestoreSelection( dat, hSelected );
+}
+
+int GetNewSelection(struct ClcGroup *group, int selection, int direction)
+{
+ int lastcount=0, count=0;//group->cl.count;
+ if (selection<0) {
+ return 0;
+ }
+ group->scanIndex=0;
+ for (;;) {
+ if(group->scanIndex==group->cl.count) {
+ group=group->parent;
+ if(group==NULL) break;
+ group->scanIndex++;
+ continue;
+ }
+ if (count>=selection) return count;
+ lastcount = count;
+ count++;
+ if (!direction) {
+ if (count>selection) return lastcount;
+ }
+ if(group->cl.items[group->scanIndex]->type==CLCIT_GROUP && (group->cl.items[group->scanIndex]->group->expanded)) {
+ group=group->cl.items[group->scanIndex]->group;
+ group->scanIndex=0;
+ continue;
+ }
+ group->scanIndex++;
+ }
+ return lastcount;
+}
+
+struct SavedContactState_t {
+ HANDLE hContact;
+ BYTE iExtraImage[MAXEXTRACOLUMNS];
+ WORD iWideExtraImage[MAXEXTRACOLUMNS];
+ int checked;
+};
+
+struct SavedGroupState_t {
+ int groupId,expanded;
+};
+
+struct SavedInfoState_t {
+ int parentId;
+ struct ClcContact contact;
+};
+
+BOOL LOCK_RECALC_SCROLLBAR=FALSE;
+void cli_SaveStateAndRebuildList(HWND hwnd, struct ClcData *dat)
+{
+ LOCK_RECALC_SCROLLBAR=TRUE;
+
+ NMCLISTCONTROL nm;
+ int i, j;
+ OBJLIST<SavedGroupState_t> savedGroup( 4 );
+ OBJLIST<SavedContactState_t> savedContact( 4 );
+ OBJLIST<SavedInfoState_t> savedInfo( 4 );
+
+ struct ClcGroup *group;
+ struct ClcContact *contact;
+
+ pcli->pfnHideInfoTip(hwnd, dat);
+ KillTimer(hwnd, TIMERID_INFOTIP);
+ KillTimer(hwnd, TIMERID_RENAME);
+ pcli->pfnEndRename(hwnd, dat, 1);
+
+ dat->NeedResort = 1;
+ group = &dat->list;
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL)
+ break;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+
+ SavedGroupState_t* p = new SavedGroupState_t;
+ p->groupId = group->groupId;
+ p->expanded = group->expanded;
+ savedGroup.insert( p );
+ continue;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) {
+ SavedContactState_t* p = new SavedContactState_t;
+ p->hContact = group->cl.items[group->scanIndex]->hContact;
+ CopyMemory(p->iExtraImage, group->cl.items[group->scanIndex]->iExtraImage,
+ sizeof(group->cl.items[group->scanIndex]->iExtraImage));
+
+ CopyMemory((void*)p->iWideExtraImage, (void*)group->cl.items[group->scanIndex]->iWideExtraImage,
+ sizeof(group->cl.items[group->scanIndex]->iWideExtraImage));
+
+ p->checked = group->cl.items[group->scanIndex]->flags & CONTACTF_CHECKED;
+ savedContact.insert( p );
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_INFO) {
+ SavedInfoState_t* p = new SavedInfoState_t;
+ memset( p, 0, sizeof( SavedInfoState_t ));
+ if (group->parent == NULL)
+ p->parentId = -1;
+ else
+ p->parentId = group->groupId;
+ p->contact = *group->cl.items[group->scanIndex];
+ savedInfo.insert( p );
+ }
+ group->scanIndex++;
+ }
+
+ pcli->pfnFreeGroup(&dat->list);
+ pcli->pfnRebuildEntireList(hwnd, dat);
+
+ group = &dat->list;
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ group = group->parent;
+ if (group == NULL)
+ break;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ for (i = 0; i < savedGroup.getCount(); i++)
+ if (savedGroup[i].groupId == group->groupId) {
+ group->expanded = savedGroup[i].expanded;
+ break;
+ }
+ continue;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) {
+ for (i = 0; i < savedContact.getCount(); i++)
+ if (savedContact[i].hContact == group->cl.items[group->scanIndex]->hContact) {
+ CopyMemory(group->cl.items[group->scanIndex]->iExtraImage, savedContact[i].iExtraImage,
+ sizeof(group->cl.items[group->scanIndex]->iExtraImage));
+
+ CopyMemory((void*)group->cl.items[group->scanIndex]->iWideExtraImage, (void*)savedContact[i].iWideExtraImage,
+ sizeof(group->cl.items[group->scanIndex]->iWideExtraImage));
+
+ if (savedContact[i].checked)
+ group->cl.items[group->scanIndex]->flags |= CONTACTF_CHECKED;
+ break;
+ }
+ }
+ group->scanIndex++;
+ }
+ savedGroup.destroy();
+ savedContact.destroy();
+
+ for (i = 0; i < savedInfo.getCount(); i++) {
+ if (savedInfo[i].parentId == -1)
+ group = &dat->list;
+ else {
+ if (!pcli->pfnFindItem(hwnd, dat, (HANDLE) (savedInfo[i].parentId | HCONTACT_ISGROUP), &contact, NULL, NULL))
+ continue;
+ group = contact->group;
+ }
+ j = pcli->pfnAddInfoItemToGroup(group, savedInfo[i].contact.flags, _T(""));
+ *group->cl.items[j] = savedInfo[i].contact;
+ }
+ savedInfo.destroy();
+
+ LOCK_RECALC_SCROLLBAR=FALSE;
+ pcli->pfnRecalculateGroupCheckboxes(hwnd, dat);
+
+ pcli->pfnRecalcScrollBar(hwnd, dat);
+ nm.hdr.code = CLN_LISTREBUILT;
+ nm.hdr.hwndFrom = hwnd;
+ nm.hdr.idFrom = GetDlgCtrlID(hwnd);
+ SendMessage(GetParent(hwnd), WM_NOTIFY, 0, (LPARAM) & nm);
+}
+
+
+WORD pdnce___GetStatus(pdisplayNameCacheEntry pdnce)
+{
+ if (!pdnce)
+ return ID_STATUS_OFFLINE;
+ else
+ return pdnce->m_cache_nStatus;
+ /*
+ // this stub will replace direct usage of m_cache_nStatus and will be substituted by getting info from DB directrly
+ if (!pdnce) return ID_STATUS_OFFLINE;
+ if (!pdnce->m_cache_cszProto) return ID_STATUS_OFFLINE;
+ if (!pdnce->m_cache_hContact) return ID_STATUS_OFFLINE;
+ return DBGetContactSettingWord( pdnce->m_cache_hContact, pdnce->m_cache_cszProto, "Status" , ID_STATUS_OFFLINE );
+ */
+}
+
+
+void pdnce___SetStatus( pdisplayNameCacheEntry pdnce, WORD wStatus )
+{
+ if (pdnce) pdnce->m_cache_nStatus=wStatus;
+}
+struct ClcContact* cliCreateClcContact( void )
+{
+ struct ClcContact* contact=(struct ClcContact*)mir_calloc(sizeof( struct ClcContact ) );
+ memset((void*)contact->iWideExtraImage,0xFF,sizeof(contact->iWideExtraImage));
+ return contact;
+}
+
+ClcCacheEntryBase* cliCreateCacheItem( HANDLE hContact )
+{
+ pdisplayNameCacheEntry p = (pdisplayNameCacheEntry)mir_calloc(sizeof( displayNameCacheEntry ));
+ if ( p )
+ {
+ memset(p,0,sizeof( displayNameCacheEntry ));
+ p->m_cache_hContact = hContact;
+ InvalidateDNCEbyPointer(hContact,p,0);
+ p->szSecondLineText=NULL;
+ p->szThirdLineText=NULL;
+ p->ssSecondLine.plText=NULL;
+ p->ssThirdLine.plText=NULL;
+ }
+ return (ClcCacheEntryBase*)p;
+}
+
+
+
+void cliInvalidateDisplayNameCacheEntry(HANDLE hContact)
+{
+ pdisplayNameCacheEntry p;
+ p = (pdisplayNameCacheEntry) pcli->pfnGetCacheEntry(hContact);
+ if (p) InvalidateDNCEbyPointer(hContact,p,0);
+ return;
+}
+
+char* cli_GetGroupCountsText(struct ClcData *dat, struct ClcContact *contact)
+{
+ char * res;
+
+ res=corecli.pfnGetGroupCountsText(dat, contact);
+
+ return res;
+}
+
+int cliGetGroupContentsCount(struct ClcGroup *group, int visibleOnly)
+{
+ int count = group->cl.count;
+ struct ClcGroup *topgroup = group;
+
+ group->scanIndex = 0;
+ for (;;) {
+ if (group->scanIndex == group->cl.count) {
+ if (group == topgroup)
+ break;
+ group = group->parent;
+ }
+ else if (group->cl.items[group->scanIndex]->type == CLCIT_GROUP && (!(visibleOnly&0x01) || group->cl.items[group->scanIndex]->group->expanded)) {
+ group = group->cl.items[group->scanIndex]->group;
+ group->scanIndex = 0;
+ count += group->cl.count;
+ continue;
+ }
+ else if ((group->cl.items[group->scanIndex]->type == CLCIT_CONTACT) &&
+ (group->cl.items[group->scanIndex]->subcontacts !=NULL) &&
+ ((group->cl.items[group->scanIndex]->SubExpanded || (!visibleOnly))))
+ {
+ count+=group->cl.items[group->scanIndex]->SubAllocated;
+ }
+ group->scanIndex++;
+ }
+ return count;
+}
+
+/*
+* checks the currently active view mode filter and returns true, if the contact should be hidden
+* if no view mode is active, it returns the CList/Hidden setting
+* also cares about sub contacts (if meta is active)
+*/
+
+int __fastcall CLVM_GetContactHiddenStatus(HANDLE hContact, char *szProto, struct ClcData *dat)
+{
+ int dbHidden = ModernGetSettingByte(hContact, "CList", "Hidden", 0); // default hidden state, always respect it.
+ int filterResult = 1;
+ DBVARIANT dbv = {0};
+ char szTemp[64];
+ TCHAR szGroupMask[256];
+ DWORD dwLocalMask;
+ PDNCE pdnce=(PDNCE)pcli->pfnGetCacheEntry(hContact);
+ BOOL fEmbedded=dat->force_in_dialog;
+ // always hide subcontacts (but show them on embedded contact lists)
+
+ if(g_CluiData.bMetaAvail && dat != NULL && dat->IsMetaContactsEnabled && g_szMetaModuleName && ModernGetSettingByte(hContact, g_szMetaModuleName, "IsSubcontact", 0))
+ return -1; //subcontact
+ if (pdnce && pdnce->isUnknown && !fEmbedded)
+ return 1; //'Unknown Contact'
+ if(pdnce && g_CluiData.bFilterEffective && !fEmbedded)
+ {
+ if(szProto == NULL)
+ szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ // check stickies first (priority), only if we really have stickies defined (CLVM_STICKY_CONTACTS is set).
+ if(g_CluiData.bFilterEffective & CLVM_STICKY_CONTACTS)
+ {
+ if ((dwLocalMask = ModernGetSettingDword(hContact, CLVM_MODULE, g_CluiData.current_viewmode, 0)) != 0) {
+ if(g_CluiData.bFilterEffective & CLVM_FILTER_STICKYSTATUS)
+ {
+ WORD wStatus = ModernGetSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ return !((1 << (wStatus - ID_STATUS_OFFLINE)) & HIWORD(dwLocalMask));
+ }
+ return 0;
+ }
+ }
+ // check the proto, use it as a base filter result for all further checks
+ if(g_CluiData.bFilterEffective & CLVM_FILTER_PROTOS) {
+ mir_snprintf(szTemp, SIZEOF(szTemp), "%s|", szProto);
+ filterResult = strstr(g_CluiData.protoFilter, szTemp) ? 1 : 0;
+ }
+ if(g_CluiData.bFilterEffective & CLVM_FILTER_GROUPS) {
+ if (!ModernGetSettingTString(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 = ModernGetSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ filterResult = (g_CluiData.filterFlags & CLVM_GROUPSTATUS_OP) ? ((filterResult | ((1 << (wStatus - ID_STATUS_OFFLINE)) & g_CluiData.statusMaskFilter ? 1 : 0))) : (filterResult & ((1 << (wStatus - ID_STATUS_OFFLINE)) & g_CluiData.statusMaskFilter ? 1 : 0));
+ }
+ if(g_CluiData.bFilterEffective & CLVM_FILTER_LASTMSG)
+ {
+ DWORD now;
+ PDNCE pdnce=(PDNCE)pcli->pfnGetCacheEntry(hContact);
+ if (pdnce)
+ {
+ now = g_CluiData.t_now;
+ now -= g_CluiData.lastMsgFilter;
+ if(g_CluiData.bFilterEffective & CLVM_FILTER_LASTMSG_OLDERTHAN)
+ filterResult = filterResult & (pdnce->dwLastMsgTime < now);
+ else if(g_CluiData.bFilterEffective & CLVM_FILTER_LASTMSG_NEWERTHAN)
+ filterResult = filterResult & (pdnce->dwLastMsgTime > now);
+ }
+ }
+ return (dbHidden | !filterResult);
+ }
+ else
+ return dbHidden;
+}