示例#1
0
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);
	}
}
示例#2
0
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;
}