INT_PTR Meta_Default(WPARAM hSub, LPARAM) { DBCachedContact *cc = currDb->m_cache->GetCachedContact(db_mc_getMeta(hSub)); if (cc && cc->IsMeta()) db_mc_setDefault(cc->contactID, hSub, true); return 0; }
// we assume that it could be called only for the metacontacts static int Meta_SrmmIconClicked(WPARAM hMeta, LPARAM lParam) { StatusIconClickData *sicd = (StatusIconClickData*)lParam; if (lstrcmpA(sicd->szModule, META_PROTO)) return 0; DBCachedContact *cc = CheckMeta(hMeta); if (cc == NULL) return 0; HMENU hMenu = CreatePopupMenu(); int iDefault = Meta_GetContactNumber(cc, db_mc_getSrmmSub(cc->contactID)); MENUITEMINFO mii = { sizeof(mii) }; mii.fMask = MIIM_ID | MIIM_STATE | MIIM_STRING; for (int i = 0; i < cc->nSubs; i++) { char *szProto = GetContactProto(cc->pSubs[i]); if (szProto == NULL) continue; PROTOACCOUNT *pa = ProtoGetAccount(szProto); if (pa == NULL) continue; CMString tszNick; if (options.menu_contact_label == DNT_DID) tszNick = cli.pfnGetContactDisplayName(cc->pSubs[i], 0); else Meta_GetSubNick(hMeta, i, tszNick); tszNick.AppendFormat(_T(" [%s]"), pa->tszAccountName); mii.wID = i + 1; mii.fState = (i == iDefault) ? MFS_CHECKED : MFS_ENABLED; mii.dwTypeData = tszNick.GetBuffer(); mii.cch = tszNick.GetLength(); InsertMenuItem(hMenu, i, TRUE, &mii); } UINT res = TrackPopupMenu(hMenu, TPM_NONOTIFY | TPM_RETURNCMD | TPM_BOTTOMALIGN | TPM_LEFTALIGN, sicd->clickLocation.x, sicd->clickLocation.y, 0, cli.hwndContactTree, NULL); if (res > 0) { MCONTACT hChosen = Meta_GetContactHandle(cc, res - 1); MetaSrmmData tmp = { cc->contactID }; if (MetaSrmmData *p = arMetaWindows.find(&tmp)) p->m_hSub = hChosen; db_mc_setDefault(cc->contactID, hChosen, true); } return 0; }
STDMETHODIMP_(MEVENT) CDbxKyoto::AddEvent(MCONTACT contactID, DBEVENTINFO *dbei) { if (dbei == NULL || dbei->cbSize != sizeof(DBEVENTINFO)) return 0; if (dbei->timestamp == 0) return 0; DBEvent dbe; dbe.dwSignature = DBEVENT_SIGNATURE; dbe.contactID = contactID; // store native or subcontact's id dbe.ofsModuleName = GetModuleNameOfs(dbei->szModule); dbe.timestamp = dbei->timestamp; dbe.flags = dbei->flags; dbe.wEventType = dbei->eventType; dbe.cbBlob = dbei->cbBlob; BYTE *pBlob = dbei->pBlob; MCONTACT contactNotifyID = contactID; DBCachedContact *cc, *ccSub = NULL; if ((cc = m_cache->GetCachedContact(contactID)) == NULL) return 0; if (cc->IsSub()) { ccSub = cc; if ((cc = m_cache->GetCachedContact(cc->parentID)) == NULL) return 0; // set default sub to the event's source if (!(dbei->flags & DBEF_SENT)) db_mc_setDefault(cc->contactID, contactID, false); contactID = cc->contactID; // and add an event to a metahistory if (db_mc_isEnabled()) contactNotifyID = contactID; } if (m_safetyMode) if (NotifyEventHooks(hEventFilterAddedEvent, contactNotifyID, (LPARAM)dbei)) return NULL; mir_ptr<BYTE> pCryptBlob; if (m_bEncrypted) { size_t len; BYTE *pResult = m_crypto->encodeBuffer(pBlob, dbe.cbBlob, &len); if (pResult != NULL) { pCryptBlob = pBlob = pResult; dbe.cbBlob = (DWORD)len; dbe.flags |= DBEF_ENCRYPTED; } } DWORD dwEventId; { mir_cslock lck(m_csDbAccess); dwEventId = ++m_dwMaxEventId; BYTE *pDest = (BYTE*)_alloca(sizeof(DBEvent) + dbe.cbBlob); memcpy(pDest, &dbe, sizeof(DBEvent)); memcpy(pDest + sizeof(DBEvent), pBlob, dbe.cbBlob); m_dbEvents.set((LPCSTR)&dwEventId, sizeof(int), (LPCSTR)pDest, sizeof(DBEvent) + dbe.cbBlob); // add a sorting key DBEventSortingKey key2 = { contactID, dbe.timestamp, dwEventId }; m_dbEventsSort.set((LPCSTR)&key2, sizeof(key2), "", 1); cc->Advance(dwEventId, dbe); m_dbContacts.set((LPCSTR)&contactID, sizeof(int), (LPCSTR)&cc->dbc, sizeof(DBContact)); // insert an event into a sub's history too if (ccSub != NULL) { key2.dwContactId = ccSub->contactID; m_dbEventsSort.set((LPCSTR)&key2, sizeof(key2), "", 1); ccSub->Advance(dwEventId, dbe); m_dbContacts.set((LPCSTR)&ccSub->contactID, sizeof(int), (LPCSTR)&ccSub->dbc, sizeof(DBContact)); } } // Notify only in safe mode or on really new events if (m_safetyMode) NotifyEventHooks(hEventAddedEvent, contactNotifyID, dwEventId); return dwEventId; }
STDMETHODIMP_(HANDLE) CDb3Mmap::AddEvent(MCONTACT contactID, DBEVENTINFO *dbei) { if (dbei == NULL || dbei->cbSize != sizeof(DBEVENTINFO)) return 0; if (dbei->timestamp == 0) return 0; DBEvent dbe; dbe.signature = DBEVENT_SIGNATURE; dbe.contactID = contactID; // store native or subcontact's id dbe.timestamp = dbei->timestamp; dbe.flags = dbei->flags; dbe.wEventType = dbei->eventType; dbe.cbBlob = dbei->cbBlob; BYTE *pBlob = dbei->pBlob; MCONTACT contactNotifyID = contactID; DBCachedContact *ccSub = NULL; if (contactID != 0) { DBCachedContact *cc = m_cache->GetCachedContact(contactID); if (cc == NULL) return NULL; if (cc->IsSub()) { ccSub = cc; // set default sub to the event's source db_mc_setDefault(cc->parentID, contactID, false); contactID = cc->parentID; // and add an event to a metahistory if (db_mc_isEnabled()) contactNotifyID = contactID; } } if (NotifyEventHooks(hEventFilterAddedEvent, contactNotifyID, (LPARAM)dbei)) return NULL; mir_ptr<BYTE> pCryptBlob; if (m_bEncrypted) { size_t len; BYTE *pResult = m_crypto->encodeBuffer(pBlob, dbe.cbBlob, &len); if (pResult != NULL) { pCryptBlob = pBlob = pResult; dbe.cbBlob = (DWORD)len; dbe.flags |= DBEF_ENCRYPTED; } } bool neednotify; mir_cslockfull lck(m_csDbAccess); DWORD ofsContact = GetContactOffset(contactID); DBContact dbc = *(DBContact*)DBRead(ofsContact, sizeof(DBContact), NULL); if (dbc.signature != DBCONTACT_SIGNATURE) return NULL; DWORD ofsNew = CreateNewSpace(offsetof(DBEvent, blob) + dbe.cbBlob); dbe.ofsModuleName = GetModuleNameOfs(dbei->szModule); // find where to put it - sort by timestamp if (dbc.eventCount == 0) { dbe.ofsPrev = dbe.ofsNext = 0; dbc.ofsFirstEvent = dbc.ofsLastEvent = ofsNew; } else { DBEvent *dbeTest = (DBEvent*)DBRead(dbc.ofsFirstEvent, sizeof(DBEvent), NULL); // Should new event be placed before first event in chain? if (dbe.timestamp < dbeTest->timestamp) { dbe.ofsPrev = 0; dbe.ofsNext = dbc.ofsFirstEvent; dbc.ofsFirstEvent = ofsNew; dbeTest = (DBEvent*)DBRead(dbe.ofsNext, sizeof(DBEvent), NULL); dbeTest->ofsPrev = ofsNew; DBWrite(dbe.ofsNext, dbeTest, sizeof(DBEvent)); } else { // Loop through the chain, starting at the end DWORD ofsThis = dbc.ofsLastEvent; dbeTest = (DBEvent*)DBRead(ofsThis, sizeof(DBEvent), NULL); for (;;) { // If the new event's timesstamp is equal to or greater than the // current dbevent, it will be inserted after. If not, continue // with the previous dbevent in chain. if (dbe.timestamp >= dbeTest->timestamp) { dbe.ofsPrev = ofsThis; dbe.ofsNext = dbeTest->ofsNext; dbeTest->ofsNext = ofsNew; DBWrite(ofsThis, dbeTest, sizeof(DBEvent)); if (dbe.ofsNext == 0) dbc.ofsLastEvent = ofsNew; else { dbeTest = (DBEvent*)DBRead(dbe.ofsNext, sizeof(DBEvent), NULL); dbeTest->ofsPrev = ofsNew; DBWrite(dbe.ofsNext, dbeTest, sizeof(DBEvent)); } break; } ofsThis = dbeTest->ofsPrev; dbeTest = (DBEvent*)DBRead(ofsThis, sizeof(DBEvent), NULL); } } } dbc.eventCount++; if (!(dbe.flags & (DBEF_READ | DBEF_SENT))) { if (dbe.timestamp < dbc.tsFirstUnread || dbc.tsFirstUnread == 0) { dbc.tsFirstUnread = dbe.timestamp; dbc.ofsFirstUnread = ofsNew; } neednotify = true; } else neednotify = m_safetyMode; if (ccSub != NULL) { DBContact *pSub = (DBContact*)DBRead(ccSub->dwDriverData, sizeof(DBContact), NULL); pSub->eventCount++; } DBWrite(ofsContact, &dbc, sizeof(DBContact)); DBWrite(ofsNew, &dbe, offsetof(DBEvent, blob)); DBWrite(ofsNew + offsetof(DBEvent, blob), pBlob, dbe.cbBlob); DBFlush(0); lck.unlock(); log1("add event @ %08x", ofsNew); // Notify only in safe mode or on really new events if (neednotify) NotifyEventHooks(hEventAddedEvent, contactNotifyID, (LPARAM)ofsNew); return (HANDLE)ofsNew; }