void DeleteItemFromTree(HWND hwnd,HANDLE hItem) { struct ClcContact *contact; struct ClcGroup *group; struct ClcData *dat=(struct ClcData*)GetWindowLong(hwnd,0); ClearRowByIndexCache(); if(!FindItem(hwnd,dat,hItem,&contact,&group,NULL,TRUE)) { DBVARIANT dbv; int i,nameOffset; if(!IsHContactContact(hItem)) return; ClearClcContactCache(dat,hItem); if(DBGetContactSettingTString(hItem,"CList","Group",&dbv)) {DBFreeVariant(&dbv); return;} //decrease member counts of all parent groups too group=&dat->list; nameOffset=0; for(i=0;;i++) { if(group->scanIndex==group->contactCount) break; if(group->contact[i].type==CLCIT_GROUP) { int len=lstrlen(group->contact[i].szText); //TODO unicode to dbv.pszVal if(!_tcsncmp(group->contact[i].szText,(TCHAR*)dbv.pszVal+nameOffset,len) && ((TCHAR)dbv.pszVal[nameOffset+len]==TEXT('\\') || (TCHAR)dbv.pszVal[nameOffset+len]==TEXT('\0'))) { group->totalMembers--; if((TCHAR)dbv.pszVal[nameOffset+len]==TEXT('\0')) break; } } } mir_free(dbv.pszVal); DBFreeVariant(&dbv); } else RemoveItemFromGroup(hwnd,group,contact,1); dat->NeedResort=1; ClearRowByIndexCache(); }
void DeleteItemFromTree(HWND hwnd,HANDLE hItem) { struct ClcContact *contact; ClcGroup *group; struct ClcData *dat = (struct ClcData*)GetWindowLongPtr(hwnd,0); ClearRowByIndexCache(); dat->needsResort = 1; if ( !FindItem(hwnd,dat,hItem,&contact,&group,NULL)) { DBVARIANT dbv; int i,nameOffset; if ( !IsHContactContact(hItem)) return; ClearClcContactCache(dat,hItem); if (db_get_ts(hItem,"CList","Group",&dbv)) return; //decrease member counts of all parent groups too group = &dat->list; nameOffset = 0; for (i = 0;;i++) { if (group->scanIndex == group->cl.count) break; if (group->cl.items[i]->type == CLCIT_GROUP) { int len = lstrlen(group->cl.items[i]->szText); if ( !_tcsncmp(group->cl.items[i]->szText,dbv.ptszVal+nameOffset,len) && (dbv.ptszVal[nameOffset+len] == '\\' || dbv.pszVal[nameOffset+len] == '\0')) { group->totalMembers--; if (dbv.pszVal[nameOffset+len] == '\0') break; } } } mir_free(dbv.pszVal); } else RemoveItemFromGroup(hwnd,group,contact,1); ClearRowByIndexCache(); }
struct ClcGroup *RemoveItemFromGroup(HWND hwnd,struct ClcGroup *group,struct ClcContact *contact,int updateTotalCount) { int iContact; struct ClcData* dat=(struct ClcData*)GetWindowLong(hwnd,0); ClearRowByIndexCache(); if(contact->type==CLCIT_CONTACT) ClearClcContactCache(dat,contact->hContact); iContact=((unsigned)contact-(unsigned)group->contact)/sizeof(struct ClcContact); if(iContact>=group->contactCount) return group; if(contact->type==CLCIT_GROUP) { FreeGroup(contact->group); mir_free(contact->group); } group->contactCount--; if(updateTotalCount && contact->type==CLCIT_CONTACT) group->totalMembers--; // free on contact deletion) if (contact->szText) mir_free(contact->szText); if (contact->szSecondLineText) mir_free(contact->szSecondLineText); if (contact->szThirdLineText) mir_free(contact->szThirdLineText); memmove(group->contact+iContact,group->contact+iContact+1,sizeof(struct ClcContact)*(group->contactCount-iContact)); if((GetWindowLong(hwnd,GWL_STYLE)&CLS_HIDEEMPTYGROUPS) && group->contactCount==0) { int i; if(group->parent==NULL) return group; for(i=0;i<group->parent->contactCount;i++) if(group->parent->contact[i].type==CLCIT_GROUP && group->parent->contact[i].groupId==group->groupId) break; if(i==group->parent->contactCount) return group; //never happens return RemoveItemFromGroup(hwnd,group->parent,&group->parent->contact[i],0); } ClearRowByIndexCache(); return group; }
LRESULT CALLBACK ContactListControlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { struct ClcData *dat = (struct ClcData*)GetWindowLongPtr(hwnd,0); if ( msg >= CLM_FIRST && msg < CLM_LAST ) return pcli->pfnProcessExternalMessages(hwnd,dat,msg,wParam,lParam); switch (msg) { case WM_CREATE: dat = (struct ClcData*)mir_calloc( sizeof(struct ClcData)); SetWindowLong(hwnd,0,(LPARAM)dat); InitDisplayNameCache(&dat->lCLCContactsCache); break; case INTM_ICONCHANGED: { struct ClcContact *contact=NULL; struct ClcGroup *group=NULL; int recalcScrollBar=0,shouldShow; HANDLE hSelItem=NULL; struct ClcContact *selcontact=NULL; pdisplayNameCacheEntry cacheEntry = GetContactFullCacheEntry((HANDLE)wParam); WORD status; int NeedResort=0; char *szProto = cacheEntry->szProto; if(szProto==NULL) status=ID_STATUS_OFFLINE; else status=cacheEntry->status; shouldShow=(GetWindowLong(hwnd,GWL_STYLE)&CLS_SHOWHIDDEN || !cacheEntry->Hidden) && (!pcli->pfnIsHiddenMode(dat,status)||cacheEntry->noHiddenOffline || CallService(MS_CLIST_GETCONTACTICON,wParam,0)!=LOWORD(lParam)); //this means an offline msg is flashing, so the contact should be shown if(!FindItem(hwnd,dat,(HANDLE)wParam,&contact,&group,NULL)) { if(shouldShow && CallService(MS_DB_CONTACT_IS, wParam, 0)) { if(dat->selection>=0 && GetRowByIndex(dat,dat->selection,&selcontact,NULL)!=-1) hSelItem=pcli->pfnContactToHItem(selcontact); AddContactToTree(hwnd,dat,(HANDLE)wParam,0,0); NeedResort=1; recalcScrollBar=1; FindItem(hwnd,dat,(HANDLE)wParam,&contact,NULL,NULL); if (contact) { contact->iImage=(WORD)lParam; pcli->pfnNotifyNewContact(hwnd,(HANDLE)wParam); dat->NeedResort=1; } } } else { //item in list already DWORD style=GetWindowLong(hwnd,GWL_STYLE); if(contact->iImage== (WORD)lParam) break; if (sortByStatus) dat->NeedResort=1; if(!shouldShow && !(style&CLS_NOHIDEOFFLINE) && (style&CLS_HIDEOFFLINE || group->hideOffline)) { if(dat->selection>=0 && GetRowByIndex(dat,dat->selection,&selcontact,NULL)!=-1) hSelItem=pcli->pfnContactToHItem(selcontact); RemoveItemFromGroup(hwnd,group,contact,0); recalcScrollBar=1; dat->NeedResort=1; } else { int oldflags; contact->iImage=(WORD)lParam; oldflags=contact->flags; if(!pcli->pfnIsHiddenMode(dat,status)||cacheEntry->noHiddenOffline) contact->flags|=CONTACTF_ONLINE; else contact->flags&=~CONTACTF_ONLINE; if (oldflags!=contact->flags) dat->NeedResort=1; } } if(hSelItem) { struct ClcGroup *selgroup; if(FindItem(hwnd,dat,hSelItem,&selcontact,&selgroup,NULL)) dat->selection=GetRowsPriorTo(&dat->list,selgroup,li.List_IndexOf((SortedList*)&selgroup->cl, selcontact)); else dat->selection=-1; } SortClcByTimer(hwnd); if(recalcScrollBar) RecalcScrollBar(hwnd,dat); goto LBL_Exit; } case INTM_STATUSMSGCHANGED: { struct ClcContact *contact=NULL; struct ClcGroup *group=NULL; DBVARIANT dbv; if (!(dat->style&CLS_SHOWSTATUSMESSAGES)) break; if(FindItem(hwnd,dat,(HANDLE)wParam,&contact,&group,NULL) && contact!=NULL) { contact->flags &= ~CONTACTF_STATUSMSG; if (!DBGetContactSettingTString((HANDLE)wParam, "CList", "StatusMsg", &dbv)) { int j; if (dbv.ptszVal==NULL||_tcslen(dbv.ptszVal)==0) break; lstrcpyn(contact->szStatusMsg, dbv.ptszVal, SIZEOF(contact->szStatusMsg)); for (j=(int)_tcslen(contact->szStatusMsg)-1;j>=0;j--) { if (contact->szStatusMsg[j]=='\r' || contact->szStatusMsg[j]=='\n' || contact->szStatusMsg[j]=='\t') { contact->szStatusMsg[j] = ' '; } } DBFreeVariant(&dbv); if (_tcslen(contact->szStatusMsg)>0) { contact->flags |= CONTACTF_STATUSMSG; dat->NeedResort=TRUE; } } } InvalidateRect(hwnd,NULL,TRUE); SortClcByTimer(hwnd); RecalcScrollBar(hwnd,dat); goto LBL_Exit; } case WM_TIMER: if (wParam==TIMERID_DELAYEDREPAINT) { KillTimer(hwnd,TIMERID_DELAYEDREPAINT); InvalidateRect(hwnd,NULL,FALSE); break; } if ( wParam == TIMERID_SUBEXPAND) { KillTimer(hwnd,TIMERID_SUBEXPAND); if (hitcontact) { if (hitcontact->SubExpanded) hitcontact->SubExpanded=0; else hitcontact->SubExpanded=1; DBWriteContactSettingByte(hitcontact->hContact,"CList","Expanded",hitcontact->SubExpanded); } hitcontact=NULL; dat->NeedResort=1; SortCLC(hwnd,dat,1); RecalcScrollBar(hwnd,dat); break; } break; case WM_DESTROY: FreeDisplayNameCache(&dat->lCLCContactsCache); stopStatusUpdater = 1; break; } { LRESULT res = saveContactListControlWndProc(hwnd, msg, wParam, lParam); switch (msg) { case WM_CREATE: mir_forkthread(StatusUpdaterThread,0); break; } return res; } LBL_Exit: return DefWindowProc(hwnd, msg, wParam, lParam); }
void RebuildEntireList(HWND hwnd,struct ClcData *dat) { // char *szProto; DWORD style=GetWindowLong(hwnd,GWL_STYLE); HANDLE hContact; struct ClcContact * cont; struct ClcGroup *group; //DBVARIANT dbv; int tick=GetTickCount(); KillTimer(hwnd,TIMERID_REBUILDAFTER); //EnterCriticalSection(&(dat->lockitemCS)); //ShowTracePopup("RebuildEntireList"); #ifdef _DEBUG { static int num_calls = 0; char tmp[128]; mir_snprintf(tmp, sizeof(tmp), "********************* RebuildEntireList (%d)\r\n", num_calls); num_calls++; TRACE(tmp); } #endif ClearRowByIndexCache(); ClearClcContactCache(dat,INVALID_HANDLE_VALUE); ImageArray_Clear(&dat->avatar_cache); RowHeights_Clear(dat); RowHeights_GetMaxRowHeight(dat, hwnd); dat->list.expanded=1; dat->list.hideOffline=DBGetContactSettingByte(NULL,"CLC","HideOfflineRoot",0); dat->list.contactCount=0; dat->list.totalMembers=0; dat->NeedResort=1; dat->selection=-1; dat->HiLightMode=DBGetContactSettingByte(NULL,"CLC","HiLightMode",0); { int i; TCHAR *szGroupName; DWORD groupFlags; for(i=1;;i++) { szGroupName=(TCHAR*)CallService(MS_CLIST_GROUPGETNAMET,i,(LPARAM)&groupFlags); //UNICODE if(szGroupName==NULL) break; AddGroup(hwnd,dat,szGroupName,groupFlags,i,0); } lastGroupId=i; } hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); while(hContact) { pdisplayNameCacheEntry cacheEntry; cont=NULL; cacheEntry=GetContactFullCacheEntry(hContact); //cacheEntry->ClcContact=NULL; ClearClcContactCache(dat,hContact); if((dat->IsMetaContactsEnabled||MyStrCmp(cacheEntry->szProto,"MetaContacts"))&&(style&CLS_SHOWHIDDEN || !cacheEntry->Hidden) && (!cacheEntry->HiddenSubcontact || !dat->IsMetaContactsEnabled )) { if(lstrlen(cacheEntry->szGroup)==0) group=&dat->list; else { group=AddGroup(hwnd,dat,cacheEntry->szGroup,(DWORD)-1,0,0); // if (!group) group=AddTempGroup(hwnd,dat,cacheEntry->szGroup,(DWORD)-1,0,0); //mir_free(dbv.pszVal); } if(group!=NULL) { if (cacheEntry->status==ID_STATUS_OFFLINE) if (DBGetContactSettingByte(NULL,"CList","PlaceOfflineToRoot",0)) group=&dat->list; group->totalMembers++; if(!(style&CLS_NOHIDEOFFLINE) && (style&CLS_HIDEOFFLINE || group->hideOffline)) { //szProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)hContact,0); if(cacheEntry->szProto==NULL) { if(!IsHiddenMode(dat,ID_STATUS_OFFLINE)||cacheEntry->noHiddenOffline) cont=AddContactToGroup(dat,group,cacheEntry); } else if(!IsHiddenMode(dat,cacheEntry->status)||cacheEntry->noHiddenOffline) cont=AddContactToGroup(dat,group,cacheEntry); } else cont=AddContactToGroup(dat,group,cacheEntry); } } if (cont) { cont->SubAllocated=0; if (cont->proto && strcmp(cont->proto,"MetaContacts")==0) AddSubcontacts(dat,cont); } 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->contactCount) { group=group->parent; if(group==NULL) break; } else if(group->contact[group->scanIndex].type==CLCIT_GROUP) { if(group->contact[group->scanIndex].group->contactCount==0) { group=RemoveItemFromGroup(hwnd,group,&group->contact[group->scanIndex],0); } else { group=group->contact[group->scanIndex].group; group->scanIndex=0; } continue; } group->scanIndex++; } } SortCLC(hwnd,dat,0); // LOCK_IMAGE_UPDATING=0; //LeaveCriticalSection(&(dat->lockitemCS)); #ifdef _DEBUG tick=GetTickCount()-tick; { char buf[255]; //sprintf(buf,"%s %s took %i ms",__FILE__,__LINE__,tick); sprintf(buf,"RebuildEntireList %d \r\n",tick); TRACE(buf); DBWriteContactSettingDword((HANDLE)0,"CLUI","PF:Last RebuildEntireList Time:",tick); } #endif }
void RebuildEntireList(HWND hwnd,struct ClcData *dat) { // char *szProto; DWORD style = GetWindowLongPtr(hwnd,GWL_STYLE); struct ClcContact * cont; ClcGroup *group; //DBVARIANT dbv; int tick = GetTickCount(); ClearRowByIndexCache(); ClearClcContactCache(dat,INVALID_HANDLE_VALUE); dat->list.expanded = 1; dat->list.hideOffline = db_get_b(NULL,"CLC","HideOfflineRoot",0); memset( &dat->list.cl, 0, sizeof( dat->list.cl )); dat->list.cl.increment = 30; dat->needsResort = 1; dat->selection = -1; { int i; TCHAR *szGroupName; DWORD groupFlags; for (i = 1;;i++) { szGroupName = pcli->pfnGetGroupName(i,&groupFlags); if (szGroupName == NULL) break; AddGroup(hwnd,dat,szGroupName,groupFlags,i,0); } } for (HANDLE hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { ClcCacheEntry *cacheEntry; cont = NULL; cacheEntry = GetContactFullCacheEntry(hContact); //cacheEntry->ClcContact = NULL; ClearClcContactCache(dat,hContact); if (cacheEntry == NULL) MessageBoxA(0,"Fail To Get CacheEntry for hContact","!!!!!!!!",0); if (style&CLS_SHOWHIDDEN || !cacheEntry->bIsHidden) { if (lstrlen(cacheEntry->tszGroup) == 0) group = &dat->list; else { group = AddGroup(hwnd,dat,cacheEntry->tszGroup,(DWORD)-1,0,0); //mir_free(dbv.pszVal); } if (group != NULL) { group->totalMembers++; if ( !(style & CLS_NOHIDEOFFLINE) && (style & CLS_HIDEOFFLINE || group->hideOffline)) { if (cacheEntry->szProto == NULL) { if ( !pcli->pfnIsHiddenMode(dat,ID_STATUS_OFFLINE)||cacheEntry->noHiddenOffline) cont = AddContactToGroup(dat,group,cacheEntry); } else if ( !pcli->pfnIsHiddenMode(dat,cacheEntry->status)||cacheEntry->noHiddenOffline) cont = AddContactToGroup(dat,group,cacheEntry); } else cont = AddContactToGroup(dat,group,cacheEntry); } } if (cont && cont->proto) { cont->SubAllocated = 0; if (strcmp(cont->proto,"MetaContacts") == 0) AddSubcontacts(cont); } } 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 = RemoveItemFromGroup(hwnd,group,group->cl.items[group->scanIndex],0); } else { group = group->cl.items[group->scanIndex]->group; group->scanIndex = 0; } continue; } group->scanIndex++; } } SortCLC(hwnd,dat,0); tick = GetTickCount()-tick; { char buf[255]; //sprintf(buf,"%s %s took %i ms",__FILE__,__LINE__,tick); mir_snprintf(buf, SIZEOF(buf), "RebuildEntireList %d \r\n", tick); OutputDebugStringA(buf); db_set_dw((HANDLE)0,"CLUI","PF:Last RebuildEntireList Time:",tick); } }