//************************************************************************ // returns the entry for the specified handle //************************************************************************ CListEntry<CContactListEntry*,CContactListGroup*> *CContactList::FindContactInGroup(MCONTACT hContact,CListContainer<CContactListEntry*,CContactListGroup*> *pGroup) { if(hContact == NULL) return NULL; CListItem<CContactListEntry*,CContactListGroup*> *pItemEntry = NULL; CListEntry<CContactListEntry*,CContactListGroup*> *pEntry = NULL; CListContainer<CContactListEntry*,CContactListGroup*> *pGroupEntry = NULL; CListContainer<CContactListEntry*,CContactListGroup*>::iterator iter = pGroup->begin(); while(iter != pGroup->end()) { if((*iter)->GetType() == ITEM) { pItemEntry = (CListItem<CContactListEntry*,CContactListGroup*>*)*iter; if(pItemEntry->GetItemData()->hHandle == hContact) return *iter; } else { pGroupEntry = (CListContainer<CContactListEntry*,CContactListGroup*> *)*iter; if(pGroupEntry->GetGroupData()->hMetaContact == hContact) return *iter; pEntry = FindContactInGroup(hContact,pGroupEntry); if(pEntry) return pEntry; } iter++; } return NULL; }
//************************************************************************ // updates the message count for the specified contact //************************************************************************ void CContactList::UpdateMessageCounter(CListEntry<CContactListEntry*,CContactListGroup*> *pContactEntry) { CContactListEntry *pEntry = GetContactData(pContactEntry); if(!pEntry) { return; } int iOldMessages = pEntry->iMessages; bool bSort = false; HANDLE hEvent= NULL; hEvent = db_event_firstUnread(pEntry->hHandle); if(CAppletManager::IsMessageWindowOpen(pEntry->hHandle) || (hEvent == NULL && pEntry->iMessages > 0)) { pEntry->iMessages = 0; bSort = true; } else { pEntry->iMessages = 0; HANDLE hLastEvent = db_event_last(pEntry->hHandle); while(hLastEvent != NULL && hEvent != NULL) { pEntry->iMessages++; if(hLastEvent == hEvent) break; hLastEvent = db_event_prev(hLastEvent); } } if(pEntry->iMessages >= 100) pEntry->strMessages = _T(">99"); else { char buffer[8]; buffer[0] = 0; itoa(pEntry->iMessages,buffer,10); pEntry->strMessages = toTstring(buffer); } CListContainer<CContactListEntry*,CContactListGroup*>* pContainer = ((CListContainer<CContactListEntry*,CContactListGroup*>*)pContactEntry->GetParent()); // Update the contacts group if it has one if(pContainer->GetType() != ROOT) { // Update the groups event count if(iOldMessages != 0 && pEntry->iMessages == 0) ChangeGroupObjectCounters(pContainer->GetGroupData()->strPath,0,0,-1); else if(iOldMessages == 0 && pEntry->iMessages != 0) ChangeGroupObjectCounters(pContainer->GetGroupData()->strPath,0,0,1); else return; // sort the groups parent ((CListContainer<CContactListEntry*,CContactListGroup*>*)pContainer->GetParent())->sort(CContactList::CompareEntries); } }
//************************************************************************ // called when a contacts status has changed //************************************************************************ void CContactList::OnStatusChange(MCONTACT hContact,int iStatus) { // find the entry in the list CListEntry<CContactListEntry *,CContactListGroup*> *pContactEntry = FindContact(hContact); if(!pContactEntry) { AddContact(hContact); return; } CContactListEntry *pItemData = GetContactData(pContactEntry); if(!pItemData) { return; } // get the old status int iOldStatus = pItemData->iStatus; // Update the list entry TCHAR *szStatus = pcli->pfnGetStatusModeDescription(iStatus, 0); if(szStatus != NULL) pItemData->strStatus =toTstring(szStatus); pItemData->iStatus = iStatus; // update the contacts group CListContainer<CContactListEntry*,CContactListGroup*>* pGroup = ((CListContainer<CContactListEntry*,CContactListGroup*>*)pContactEntry->GetParent()); if(pGroup->GetType() != ROOT) { if(!db_mc_isSub(hContact) && iStatus == ID_STATUS_OFFLINE && iOldStatus != ID_STATUS_OFFLINE) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,-1); else if(!db_mc_isSub(hContact) && iStatus != ID_STATUS_OFFLINE && iOldStatus == ID_STATUS_OFFLINE) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,1); } // check if the entry is still visible if(!IsVisible(pItemData)) { RemoveContact(hContact); return; } // sort the list pGroup->sort(CContactList::CompareEntries); }
//************************************************************************ // called when a contacts status has changed //************************************************************************ void CContactList::OnStatusChange(HANDLE hContact,int iStatus) { // find the entry in the list CListEntry<CContactListEntry *,CContactListGroup*> *pContactEntry = FindContact(hContact); if(!pContactEntry) { AddContact(hContact); return; } CContactListEntry *pItemData = GetContactData(pContactEntry); if(!pItemData) { return; } // get the old status int iOldStatus = pItemData->iStatus; // Update the list entry char *szStatus = (char *) CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, iStatus, 0); if(szStatus != NULL) pItemData->strStatus =toTstring(szStatus); pItemData->iStatus = iStatus; // update the contacts group CListContainer<CContactListEntry*,CContactListGroup*>* pGroup = ((CListContainer<CContactListEntry*,CContactListGroup*>*)pContactEntry->GetParent()); if(pGroup->GetType() != ROOT) { if(!CAppletManager::IsSubContact(hContact) && iStatus == ID_STATUS_OFFLINE && iOldStatus != ID_STATUS_OFFLINE) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,-1); else if(!CAppletManager::IsSubContact(hContact) && iStatus != ID_STATUS_OFFLINE && iOldStatus == ID_STATUS_OFFLINE) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,1); } // check if the entry is still visible if(!IsVisible(pItemData)) { RemoveContact(hContact); return; } // sort the list pGroup->sort(CContactList::CompareEntries); }
//************************************************************************ // returns the entry for the specified group name //************************************************************************ CListContainer<CContactListEntry*,CContactListGroup*> *CContactList::FindGroupInGroup(tstring strGroup,CListContainer<CContactListEntry*,CContactListGroup*> *pGroup) { CListContainer<CContactListEntry*,CContactListGroup*>::iterator iter = pGroup->begin(); CListContainer<CContactListEntry*,CContactListGroup*> *pItem = NULL; while(!pGroup->empty() && iter != pGroup->end()) { if((*iter)->GetType() == CONTAINER) { pItem = (CListContainer<CContactListEntry*,CContactListGroup*>*)*iter; if(pItem->GetGroupData()->strName == strGroup) return pItem; //pItem = FindGroupInGroup(strGroup,(CListContainer<CContactListEntry*,CContactListGroup*> *)*iter); //if(pItem) // return pItem; } iter++; } return NULL; }
//************************************************************************ // called when a contacts nickname has changed //************************************************************************ void CContactList::OnContactNickChanged(MCONTACT hContact, tstring strNick) { CListEntry<CContactListEntry *,CContactListGroup*> *pContactEntry = FindContact(hContact); if(!pContactEntry) return; if(pContactEntry->GetType() == CONTAINER) { CListContainer *pGroup = ((CListContainer<CContactListEntry*,CContactListGroup*>*)pContactEntry); pGroup->GetGroupData()->strName = strNick; tstring strPath = GetContactGroupPath(hContact); pGroup->GetGroupData()->strPath = strPath + (strPath.empty()?_T(""):_T("\\")) + strNick; } CContactListEntry* pEntry = GetContactData(pContactEntry); if(!pEntry) { return; } pEntry->strName = strNick; ((CListContainer<CContactListEntry*,CContactListGroup*>*)pContactEntry->GetParent())->sort(CContactList::CompareEntries); }
//************************************************************************ // Adds a group //************************************************************************ CListContainer<CContactListEntry*,CContactListGroup*> *CContactList::AddGroupByString(tstring strGroup) { tstring strParse = strGroup; tstring strPath = _T(""); CListContainer<CContactListEntry*,CContactListGroup*> *pGroup = (CListContainer<CContactListEntry*,CContactListGroup*>*)this; CListContainer<CContactListEntry*,CContactListGroup*> *pGroup2 = NULL; tstring::size_type pos; while((pos = strParse.find('\\')) != tstring::npos ) { strGroup = strParse.substr(0,pos); strParse = strParse.substr(pos+1); strPath += strGroup; if(pGroup2 = FindGroupInGroup(strGroup,pGroup)) pGroup = pGroup2; else { CContactListGroup *pGroupObject = GetGroupObjectByPath(strPath); if(!pGroupObject) pGroupObject = CreateGroupObjectByPath(strPath); pGroup2 = pGroup->InsertGroup(pGroup->begin(),pGroupObject); pGroup->sort(CContactList::CompareEntries); pGroup = pGroup2; } ASSERT(pGroup != NULL); strPath += _T("\\"); } strPath += strParse; if(pGroup2 = FindGroupInGroup(strParse,pGroup)) return pGroup2; else { CContactListGroup *pGroupObject = GetGroupObjectByPath(strPath); if(!pGroupObject) pGroupObject = CreateGroupObjectByPath(strPath); pGroup2 = pGroup->InsertGroup(pGroup->begin(),pGroupObject); pGroup->sort(CContactList::CompareEntries); return pGroup2; } }
//************************************************************************ // called when a contacts group has changed //************************************************************************ void CContactList::OnContactGroupChanged(MCONTACT hContact,tstring strGroup) { bool bMetaContact = false; strGroup = GetContactGroupPath(hContact); // Decrease the membercount of the old group CListEntry<CContactListEntry *,CContactListGroup*> *pContactEntry = FindContact(hContact); CContactListGroup *pOldGroup = NULL; // If the contactentry was not found, try adding the contact (metacontacts fix) if(!pContactEntry) { return; } if(pContactEntry->GetType() == CONTAINER) bMetaContact = true; CListContainer<CContactListEntry*,CContactListGroup*>* pContainer = ((CListContainer<CContactListEntry*,CContactListGroup*>*)pContactEntry->GetParent()); // Update the contacts group if it has one if(pContainer->GetType() != ROOT) { pOldGroup = pContainer->GetGroupData(); if(!db_mc_isSub(hContact)) ChangeGroupObjectCounters(pOldGroup->strPath,-1); } // increase the membercount of the new group, and check if it needs to be created if(!strGroup.empty()) { CContactListGroup *pGroup = GetGroupObjectByPath(strGroup); if(!pGroup) pGroup = CreateGroupObjectByPath(strGroup); if(!db_mc_isSub(hContact)) ChangeGroupObjectCounters(strGroup,1); } // move subcontacts if(pContactEntry->GetType() == CONTAINER) { CListContainer<CContactListEntry*,CContactListGroup*> *pGroup = (CListContainer<CContactListEntry*,CContactListGroup*>*)pContactEntry; CListContainer<CContactListEntry*,CContactListGroup*>::iterator iter = pGroup->begin(); while(!pGroup->empty()) { iter = pGroup->begin(); if((*iter)->GetType() == ITEM) OnContactGroupChanged(GetContactData(*iter)->hHandle,_T("")); Sleep(1); } } // update the list RemoveContact(hContact); AddContact(hContact); if(bMetaContact) { tstring strName = CAppletManager::GetContactDisplayname(hContact); tstring strPath = _T(""); if(pOldGroup) strPath += pOldGroup->strPath; strPath += (strPath.empty()?_T(""):_T("\\")) + strName; DeleteGroupObjectByPath(strPath); } // check if the old group ( if it exists ) needs to be deleted if(pOldGroup && !pOldGroup->hMetaContact && pOldGroup->iMembers <= 0 && pOldGroup->iGroups <= 0) DeleteGroupObjectByPath(pOldGroup->strPath); }
//************************************************************************ // removes a contact from the list //************************************************************************ void CContactList::RemoveContact(MCONTACT hContact) { CListContainer<CContactListEntry*,CContactListGroup*> *pGroup = NULL; ///tstring strGroup = GetContactGroupPath(hContact); CListEntry<CContactListEntry*,CContactListGroup*> *pContactEntry = FindContact(hContact); if(!pContactEntry) { return; } if( !CConfig::GetBoolSetting(CLIST_USEGROUPS)){ if(pContactEntry->GetType() == ITEM) RemoveItem(((CListItem<CContactListEntry*,CContactListGroup*>*)pContactEntry)->GetItemData()); else RemoveGroup(((CListContainer<CContactListEntry*,CContactListGroup*>*)pContactEntry)->GetGroupData()); } else { pGroup = (CListContainer<CContactListEntry*,CContactListGroup*>*)pContactEntry->GetParent(); ASSERT(pGroup != NULL); CContactListEntry *pEntry = GetContactData(pContactEntry); if(!pEntry) { return; } // Update the contacts group if it has one if(pGroup->GetType() != ROOT) { if(!db_mc_isSub(hContact) && pEntry->iStatus != ID_STATUS_OFFLINE) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,-1); if(!db_mc_isSub(hContact) && pEntry->iMessages > 0) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,0,-pEntry->iMessages); } if(pContactEntry->GetType() == ITEM) pGroup->RemoveItem(((CListItem<CContactListEntry*,CContactListGroup*>*)pContactEntry)->GetItemData()); else { pGroup->RemoveGroup(((CListContainer<CContactListEntry*,CContactListGroup*>*)pContactEntry)->GetGroupData()); // Reenumerate all subcontacts (maybe MetaContacts was disabled int numContacts = db_mc_getSubCount(hContact); for(int i=0;i<numContacts;i++) { MCONTACT hSubContact = db_mc_getSub(hContact, i); if(!FindContact(hSubContact)) AddContact(hSubContact); } } CListContainer<CContactListEntry*,CContactListGroup*> *pParent = (CListContainer<CContactListEntry*,CContactListGroup*>*)pGroup->GetParent(); while(pParent != NULL && pGroup->IsEmpty() && !pGroup->GetGroupData()->hMetaContact) { pParent->RemoveGroup(pGroup->GetGroupData()); pGroup = pParent; pParent = (CListContainer<CContactListEntry*,CContactListGroup*>*)pGroup->GetParent(); } } }
//************************************************************************ // adds a contact to the list //************************************************************************ void CContactList::AddContact(MCONTACT hContact) { CListContainer<CContactListEntry*,CContactListGroup*> *pGroup = NULL; tstring strName = CAppletManager::GetContactDisplayname(hContact); char *szProto = GetContactProto(hContact); tstring strGroup = GetContactGroupPath(hContact); // ignore contacts without a valid protocoll if(szProto == NULL) return; int iStatus = db_get_w(hContact,szProto,"Status",ID_STATUS_OFFLINE); TCHAR *szStatus = pcli->pfnGetStatusModeDescription(iStatus, 0); CContactListEntry *psContact = new CContactListEntry(); psContact->strName = strName; psContact->iMessages = 0; psContact->hHandle = hContact; psContact->iStatus = iStatus; if(szStatus != NULL) psContact->strStatus =toTstring(szStatus); psContact->strProto = toTstring(szProto); // check wether the contact should be listed if(!IsVisible(psContact)) { delete psContact; return; } // Don't add metacontacts as contacts if(!mir_strcmpi(szProto,"MetaContacts")) { if(!CConfig::GetBoolSetting(CLIST_USEGROUPS)) strGroup = _T(""); strGroup += (strGroup.empty()?_T(""):_T("\\"))+psContact->strName; pGroup = GetGroupByString(strGroup); if(pGroup == NULL) pGroup = AddGroupByString(strGroup); pGroup->GetGroupData()->hMetaContact = hContact; pGroup->GetGroupData()->pContactListEntry = psContact; pGroup = (CListContainer<CContactListEntry*,CContactListGroup*>*)pGroup->GetParent(); if(pGroup->GetType() != ROOT && iStatus != ID_STATUS_OFFLINE) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,1); pGroup->sort(CContactList::CompareEntries); // check that all subcontacts exist int numContacts = db_mc_getSubCount(hContact); MCONTACT hSubContact = NULL; for(int i=0;i<numContacts;i++) { hSubContact = db_mc_getSub(hContact, i); RemoveContact(hSubContact); AddContact(hSubContact); } return; } else if(db_mc_isSub(hContact)) { MCONTACT hMetaContact = db_mc_getMeta(hContact); // check that the metacontact exists if(!FindContact(hMetaContact)) AddContact(hMetaContact); } CListItem<CContactListEntry*,CContactListGroup*> *pItem = NULL; if((!db_mc_isSub(hContact) && !CConfig::GetBoolSetting(CLIST_USEGROUPS)) || strGroup.empty()) { pItem = AddItem(psContact); ((CListContainer<CContactListEntry*,CContactListGroup*>*)this)->sort(CContactList::CompareEntries); } else { pGroup = GetGroupByString(strGroup); if(pGroup == NULL) { pGroup = AddGroupByString(strGroup); } pItem = pGroup->AddItem(psContact); if(!db_mc_isSub(hContact) && iStatus != ID_STATUS_OFFLINE) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,1); pGroup->sort(CContactList::CompareEntries); } UpdateMessageCounter((CListEntry<CContactListEntry*,CContactListGroup*>*)pItem); }
//************************************************************************ // adds a contact to the list //************************************************************************ void CContactList::AddContact(HANDLE hContact) { CListContainer<CContactListEntry*,CContactListGroup*> *pGroup = NULL; tstring strName = CAppletManager::GetContactDisplayname(hContact); char *szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(UINT)hContact,0); tstring strGroup = GetContactGroupPath(hContact); // ignore contacts without a valid protocoll if(szProto == NULL) return; int iStatus = db_get_w(hContact,szProto,"Status",ID_STATUS_OFFLINE); char *szStatus = (char *) CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, iStatus, 0); CContactListEntry *psContact = new CContactListEntry(); psContact->strName = strName; psContact->iMessages = 0; psContact->hHandle = hContact; psContact->iStatus = iStatus; if(szStatus != NULL) psContact->strStatus =toTstring(szStatus); psContact->strProto = toTstring(szProto); // check wether the contact should be listed if(!IsVisible(psContact)) { delete psContact; return; } // Don't add metacontacts as contacts if(!stricmp(szProto,"MetaContacts")) { if(!CConfig::GetBoolSetting(CLIST_USEGROUPS)) strGroup = _T(""); strGroup += (strGroup.empty()?_T(""):_T("\\"))+psContact->strName; pGroup = GetGroupByString(strGroup); if(pGroup == NULL) pGroup = AddGroupByString(strGroup); pGroup->GetGroupData()->hMetaContact = hContact; pGroup->GetGroupData()->pContactListEntry = psContact; pGroup = (CListContainer<CContactListEntry*,CContactListGroup*>*)pGroup->GetParent(); if(pGroup->GetType() != ROOT && iStatus != ID_STATUS_OFFLINE) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,1); pGroup->sort(CContactList::CompareEntries); // check that all subcontacts exist int numContacts = CallService(MS_MC_GETNUMCONTACTS,(WPARAM)hContact,0); HANDLE hSubContact = NULL; for(int i=0;i<numContacts;i++) { hSubContact = (HANDLE *) CallService(MS_MC_GETSUBCONTACT, (WPARAM)hContact, (LPARAM)i); RemoveContact(hSubContact); AddContact(hSubContact); } return; } else if(CAppletManager::IsSubContact(hContact)) { HANDLE hMetaContact = (HANDLE *) CallService(MS_MC_GETMETACONTACT, (WPARAM)hContact, 0); // check that the metacontact exists if(!FindContact(hMetaContact)) { AddContact(hMetaContact); } } CListItem<CContactListEntry*,CContactListGroup*> *pItem = NULL; if((!CAppletManager::IsSubContact(hContact) && !CConfig::GetBoolSetting(CLIST_USEGROUPS)) || strGroup.empty()) { pItem = AddItem(psContact); ((CListContainer<CContactListEntry*,CContactListGroup*>*)this)->sort(CContactList::CompareEntries); } else { pGroup = GetGroupByString(strGroup); if(pGroup == NULL) { pGroup = AddGroupByString(strGroup); } pItem = pGroup->AddItem(psContact); if(!CAppletManager::IsSubContact(hContact) && iStatus != ID_STATUS_OFFLINE) ChangeGroupObjectCounters(pGroup->GetGroupData()->strPath,0,1); pGroup->sort(CContactList::CompareEntries); } UpdateMessageCounter((CListEntry<CContactListEntry*,CContactListGroup*>*)pItem); }