static void RestoreUnreadMessageAlerts(void) { OBJLIST<MSavedEvent> arEvents(10, NumericKeySortT); for (MCONTACT hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) { for (MEVENT hDbEvent = db_event_firstUnread(hContact); hDbEvent; hDbEvent = db_event_next(hContact, hDbEvent)) { DBEVENTINFO dbei = { sizeof(dbei) }; dbei.cbBlob = 0; db_event_get(hDbEvent, &dbei); if ((dbei.flags & (DBEF_SENT | DBEF_READ)) || !DbEventIsMessageOrCustom(&dbei)) continue; int windowAlreadyExists = WindowList_Find(g_dat.hMessageWindowList, hContact) != NULL; if (windowAlreadyExists) continue; if (IsAutoPopup(hContact) && !windowAlreadyExists) { NewMessageWindowLParam newData = { 0 }; newData.hContact = hContact; newData.flags = NMWLP_INCOMING; HWND hParent = GetParentWindow(newData.hContact, FALSE); CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSG), hParent, DlgProcMessage, (LPARAM)&newData); } else arEvents.insert(new MSavedEvent(hContact, hDbEvent)); } } TCHAR toolTip[256]; CLISTEVENT cle = {}; cle.hIcon = Skin_LoadIcon(SKINICON_EVENT_MESSAGE); cle.pszService = "SRMsg/ReadMessage"; cle.flags = CLEF_TCHAR; cle.ptszTooltip = toolTip; for (int i = 0; i < arEvents.getCount(); i++) { MSavedEvent &e = arEvents[i]; mir_sntprintf(toolTip, TranslateT("Message from %s"), pcli->pfnGetContactDisplayName(e.hContact, 0)); cle.hContact = e.hContact; cle.hDbEvent = e.hEvent; pcli->pfnAddEvent(&cle); } }
BOOL CDb3Mmap::MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub) { mir_cslock lck(m_csDbAccess); DBContact *dbMeta = (DBContact*)DBRead(ccMeta->dwDriverData, NULL); DBContact *dbSub = (DBContact*)DBRead(ccSub->dwDriverData, NULL); if (dbMeta->signature != DBCONTACT_SIGNATURE || dbSub->signature != DBCONTACT_SIGNATURE) return 1; // special cases if (dbSub->ofsFirstEvent == 0) // hurrah, nothing to do return 0; LIST<DBEvent> arEvents(20000, SortEvent); BOOL ret = 0; __try { if (dbMeta->ofsFirstEvent == 0) { // simply chain history to a meta dbMeta->eventCount = dbSub->eventCount; dbMeta->ofsFirstEvent = dbSub->ofsFirstEvent; dbMeta->ofsLastEvent = dbSub->ofsLastEvent; dbMeta->ofsFirstUnread = dbSub->ofsFirstUnread; dbMeta->tsFirstUnread = dbSub->tsFirstUnread; } else { // there're events in both meta's & sub's event chains // relink sub's event chain to meta without changing events themselves for (DWORD ofsMeta = dbMeta->ofsFirstEvent; ofsMeta != 0;) { DBEvent *pev = (DBEvent*)DBRead(ofsMeta, NULL); if (pev->signature != DBEVENT_SIGNATURE) { // broken chain, don't touch it ret = 2; __leave; } arEvents.insert(pev); ofsMeta = pev->ofsNext; } for (DWORD ofsSub = dbSub->ofsFirstEvent; ofsSub != 0;) { DBEvent *pev = (DBEvent*)DBRead(ofsSub, NULL); if (pev->signature != DBEVENT_SIGNATURE) { // broken chain, don't touch it ret = 2; __leave; } arEvents.insert(pev); ofsSub = pev->ofsNext; } // all events are in memory, valid & sorted in the right order. // ready? steady? go! dbMeta->eventCount = arEvents.getCount(); DBEvent *pFirst = arEvents[0]; dbMeta->ofsFirstEvent = DWORD(PBYTE(pFirst) - m_pDbCache); pFirst->ofsPrev = 0; dbMeta->ofsFirstUnread = pFirst->markedRead() ? 0 : dbMeta->ofsFirstEvent; DBEvent *pLast = arEvents[arEvents.getCount() - 1]; dbMeta->ofsLastEvent = DWORD(PBYTE(pLast) - m_pDbCache); pLast->ofsNext = 0; for (int i = 1; i < arEvents.getCount(); i++) { DBEvent *pPrev = arEvents[i - 1], *pNext = arEvents[i]; pPrev->ofsNext = DWORD(PBYTE(pNext) - m_pDbCache); pNext->ofsPrev = DWORD(PBYTE(pPrev) - m_pDbCache); if (dbMeta->ofsFirstUnread == 0 && !pNext->markedRead()) dbMeta->ofsFirstUnread = pPrev->ofsNext; } } // remove any traces of history from sub dbSub->ofsFirstEvent = dbSub->ofsLastEvent = dbSub->ofsFirstUnread = dbSub->tsFirstUnread = 0; } __except (EXCEPTION_EXECUTE_HANDLER) { ret = 3; } FlushViewOfFile(m_pDbCache, 0); return ret; }