#include "headers.h" void CacheThreadFunc(void *arg); // Event bool HistoryArray::ItemData::load(EventLoadMode mode) { if (mode == ELM_NOTHING) return true; if ((mode == ELM_INFO) && (!dbeOk || !dbe.cbSize)) { dbeOk = true; dbe.cbSize = sizeof(dbe); dbe.cbBlob = 0; dbe.pBlob = 0; CallService(MS_DB_EVENT_GET, (WPARAM)hEvent, (LPARAM)&dbe); return true; } if ((mode == ELM_DATA) && (!dbeOk || !dbe.cbBlob)) { dbeOk = true; dbe.cbSize = sizeof(dbe); dbe.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hEvent, 0); dbe.pBlob = (PBYTE)calloc(dbe.cbBlob+1, 1); CallService(MS_DB_EVENT_GET, (WPARAM)hEvent, (LPARAM)&dbe); int aLength = 0; atext = 0; wtext = 0; switch (dbe.eventType) { case EVENTTYPE_STATUSCHANGE: case EVENTTYPE_MESSAGE: { atext = (char *)dbe.pBlob; atext_del = false; aLength = lstrlenA(atext); if (dbe.cbBlob > aLength+1) { wtext = (WCHAR *)(dbe.pBlob + aLength + 1); wtext_del = false; } break; } case EVENTTYPE_AUTHREQUEST: { atext = new char[512]; atext_del = true; if ((dbe.cbBlob>8) && *(dbe.pBlob+8)) { mir_snprintf(atext, 512, ("%s requested authorization"), dbe.pBlob + 8); } else { mir_snprintf(atext, 512, ("%d requested authorization"), *(DWORD*)(dbe.pBlob)); } aLength = lstrlenA(atext); break; } case EVENTTYPE_ADDED: { atext = new char[512]; atext_del = true; if ((dbe.cbBlob>8) && *(dbe.pBlob+8)) { mir_snprintf(atext, 512, ("%s added you to the contact list"), dbe.pBlob + 8); } else { mir_snprintf(atext, 512, ("%d added you to the contact list"), *(DWORD*)(dbe.pBlob)); } aLength = lstrlenA(atext); break; } } if (atext && !wtext) { #ifdef UNICODE int bufSize = MultiByteToWideChar(CP_ACP, 0, atext, aLength+1, 0, 0); wtext = new WCHAR[bufSize+1]; MultiByteToWideChar(CP_ACP, 0, atext, aLength+1, wtext, bufSize); wtext_del = true; #else this->wtext = 0; wtext_del = false; #endif } else if (!atext && wtext) { // strange situation, really :) I'll fix this later } else if (!atext && !wtext) { atext = ""; atext_del = false; wtext = L""; wtext_del = false; } return true; } return false; } HistoryArray::ItemData::~ItemData() { if (dbeOk && dbe.pBlob) { free(dbe.pBlob); dbe.pBlob = 0; } if (wtext && wtext_del) delete [] wtext; if (atext && atext_del) delete [] atext; if (data) MTextDestroy(data); } // Array HistoryArray::HistoryArray() { head = tail = 0; caching = false; caching_complete = true; InitializeCriticalSection(&csItems); } HistoryArray::~HistoryArray() { DeleteCriticalSection(&csItems); clear(); } bool HistoryArray::allocateBlock(int count) { ItemBlock *newBlock = new ItemBlock; newBlock->items = new ItemData[count]; newBlock->count = count; newBlock->prev = tail; newBlock->next = 0; if (tail) { tail->next = newBlock; } else { head = newBlock; } tail = newBlock; return true; } void HistoryArray::clear() { while (head) { ItemBlock *next = head->next; // for (int i = 0; i < head->count; ++i) // destroyEvent(head->items[i]); delete [] head->items; head = next; } head = tail = 0; preBlock = 0; preIndex = 0; } bool HistoryArray::addHistory(HANDLE hContact, EventLoadMode mode) { int count = CallService(MS_DB_EVENT_GETCOUNT, (WPARAM)hContact, 0); allocateBlock(count); int i = 0; HANDLE hEvent = (HANDLE)CallService(MS_DB_EVENT_FINDFIRST, (WPARAM)hContact, 0); while (hEvent) { tail->items[i].hContact = hContact; tail->items[i].hEvent = hEvent; ++i; hEvent = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hEvent, 0); } char buf[666]; return true; } bool HistoryArray::addEvent(HANDLE hContact, HANDLE hEvent, EventLoadMode mode) { allocateBlock(1); tail->items[0].hContact = hContact; tail->items[0].hEvent = hEvent; if (mode != ELM_NOTHING) tail->items[0].load(mode); return true; } /* bool HistoryArray::preloadEvents(int count) { for (int i = 0; i < count; ++i) { preBlock->items[preIndex].load(ELM_DATA); if (++preIndex == preBlock->count) { preBlock = preBlock->next; if (!preBlock) return false; preIndex = 0; } } return true; } */ HistoryArray::ItemData *HistoryArray::get(int id, EventLoadMode mode) { caching = false; if (caching) EnterCriticalSection(&csItems); int offset = 0; for (ItemBlock *p = head; p; p = p->next) { if (id < offset + p->count) { if (mode != ELM_NOTHING) p->items[id - offset].load(mode); if (caching) { if (caching_complete) caching = false; LeaveCriticalSection(&csItems); } return p->items + id - offset; } offset += p->count; } if (caching) { if (caching_complete) caching = false; LeaveCriticalSection(&csItems); } return 0; } /////////////////////////////////////////////////////////// // Cache data void HistoryArray::CacheThreadFunc(void *arg) { HistoryArray *_this = (HistoryArray *)arg; _this->caching_complete = true; _endthread(); }