From a30cc711b287d245e0edc7c63e53da95c0999203 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 24 Jul 2012 06:59:45 +0000 Subject: SplashScreen, SRMM: changed folder structure git-svn-id: http://svn.miranda-ng.org/main/trunk@1151 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/SRMM/src/msglog.cpp | 645 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 645 insertions(+) create mode 100644 plugins/SRMM/src/msglog.cpp (limited to 'plugins/SRMM/src/msglog.cpp') diff --git a/plugins/SRMM/src/msglog.cpp b/plugins/SRMM/src/msglog.cpp new file mode 100644 index 0000000000..d24cda4032 --- /dev/null +++ b/plugins/SRMM/src/msglog.cpp @@ -0,0 +1,645 @@ +/* +Copyright 2000-2010 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "commonheaders.h" + +extern HANDLE hIconLibItem[]; + +static int logPixelSY; +#define LOGICON_MSG_IN 0 +#define LOGICON_MSG_OUT 1 +#define LOGICON_MSG_NOTICE 2 +static PBYTE pLogIconBmpBits[3]; +static int logIconBmpSize[ SIZEOF(pLogIconBmpBits) ]; + +#define STREAMSTAGE_HEADER 0 +#define STREAMSTAGE_EVENTS 1 +#define STREAMSTAGE_TAIL 2 +#define STREAMSTAGE_STOP 3 +struct LogStreamData +{ + int stage; + HANDLE hContact; + HANDLE hDbEvent, hDbEventLast; + char *buffer; + int bufferOffset, bufferLen; + int eventsToInsert; + int isEmpty; + struct SrmmWindowData *dlgDat; +}; + +static char szSep2[40], szSep2_RTL[50]; + +static void AppendToBuffer(char **buffer, int *cbBufferEnd, int *cbBufferAlloced, const char *fmt, ...) +{ + va_list va; + int charsDone; + + va_start(va, fmt); + for (;;) { + charsDone = mir_vsnprintf(*buffer + *cbBufferEnd, *cbBufferAlloced - *cbBufferEnd, fmt, va); + if (charsDone >= 0) + break; + *cbBufferAlloced += 1024; + *buffer = (char *) mir_realloc(*buffer, *cbBufferAlloced); + } + va_end(va); + *cbBufferEnd += charsDone; +} + +static const TCHAR *bbcodes[] = { _T("[b]"), _T("[i]"), _T("[u]"), _T("[s]"), _T("[/b]"), _T("[/i]"), _T("[/u]"), _T("[/s]") }; +static const char *bbcodefmt[] = { "\\b ", "\\i ", "\\ul ", "\\strike ", "\\b0 ", "\\i0 ", "\\ul0 ", "\\strike0 " }; + +static int AppendToBufferWithRTF(char **buffer, int *cbBufferEnd, int *cbBufferAlloced, TCHAR* line) +{ + DWORD textCharsCount = 0; + char *d; + int lineLen; + + if (line == NULL) + return 0; + + lineLen = (int)_tcslen(line) * 9 + 8; + if (*cbBufferEnd + lineLen > *cbBufferAlloced) + { + cbBufferAlloced[0] += (lineLen + 1024 - lineLen % 1024); + *buffer = (char *) mir_realloc(*buffer, *cbBufferAlloced); + } + + d = *buffer + *cbBufferEnd; + strcpy(d, "{\\uc1 "); + d += 6; + + for (; *line; line++, textCharsCount++) + { + if (*line == '\r' && line[1] == '\n') + { + memcpy(d, "\\par ", 5); + line++; + d += 5; + } + else if (*line == '\n') { + memcpy(d, "\\par ", 5); + d += 5; + } + else if (*line == '\t') + { + memcpy(d, "\\tab ", 5); + d += 5; + } + else if (*line == '\\' || *line == '{' || *line == '}') + { + *d++ = '\\'; + *d++ = (char) *line; + } + else if (*line == '[' && (g_dat->flags & SMF_SHOWFORMAT)) + { + int i, found = 0; + for (i = 0; i < SIZEOF(bbcodes); ++i) + { + if (line[1] == bbcodes[i][1]) + { + size_t lenb = _tcslen(bbcodes[i]); + if (!_tcsnicmp(line, bbcodes[i], lenb)) + { + size_t len = strlen(bbcodefmt[i]); + memcpy(d, bbcodefmt[i], len); + d += len; + line += lenb - 1; + found = 1; + break; + } + } + } + if (!found) + { + if (!_tcsnicmp(line, _T("[url"), 4)) + { + TCHAR* tag = _tcschr(line + 4, ']'); + if (tag) + { + TCHAR *tagu = (line[4] == '=') ? line + 5 : tag + 1; + TCHAR *tage = _tcsstr(tag, _T("[/url]")); + if (!tage) tage = _tcsstr(tag, _T("[/URL]")); + if (tage) + { + *tag = 0; + *tage = 0; + d += sprintf(d, "{\\field{\\*\\fldinst HYPERLINK \"%s\"}{\\fldrslt %s}}", mir_t2a(tagu), mir_t2a(tag + 1)); +// d += sprintf(d, "{\\field{\\*\\fldinst HYPERLINK \"%s\"}{\\fldrslt \\ul\\cf%d %s}}", mir_t2a(tagu), msgDlgFontCount, mir_t2a(tag + 1)); + line = tage + 5; + found = 1; + } + } + } + else if (!_tcsnicmp(line, _T("[color="), 7)) + { + TCHAR* tag = _tcschr(line + 7, ']'); + if (tag) + { + line = tag; + found = 1; + } + } + else if (!_tcsnicmp(line, _T("[/color]"), 8)) + { + line += 7; + found = 1; + } + } + if (!found) + { + if (*line < 128) *d++ = (char) *line; + else d += sprintf(d, "\\u%d ?", *line); + } + } + else if (*line < 128) *d++ = (char) *line; + else d += sprintf(d, "\\u%d ?", *line); + } + + *(d++) = '}'; + *d = 0; + + *cbBufferEnd = (int) (d - *buffer); + return textCharsCount; +} + +#define FONT_FORMAT "{\\f%u\\fnil\\fcharset%u %S;}" + +static char *CreateRTFHeader(struct SrmmWindowData *dat) +{ + char *buffer; + int bufferAlloced, bufferEnd; + int i; + LOGFONT lf; + COLORREF colour; + HDC hdc; + + hdc = GetDC(NULL); + logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); + ReleaseDC(NULL, hdc); + bufferEnd = 0; + bufferAlloced = 1024; + buffer = (char *) mir_alloc(bufferAlloced); + buffer[0] = '\0'; + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "{\\rtf1\\ansi\\deff0{\\fonttbl"); + + for (i = 0; i < msgDlgFontCount; i++) { + LoadMsgDlgFont(i, &lf, NULL); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, FONT_FORMAT, i, lf.lfCharSet, lf.lfFaceName); + } + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}{\\colortbl "); + for (i = 0; i < msgDlgFontCount; i++) { + LoadMsgDlgFont(i, NULL, &colour); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + } + if (GetSysColorBrush(COLOR_HOTLIGHT) == NULL) + colour = RGB(0, 0, 255); + else + colour = GetSysColor(COLOR_HOTLIGHT); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}"); + //AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}\\pard"); + return buffer; +} + +//mir_free() the return value +static char *CreateRTFTail(struct SrmmWindowData *dat) +{ + char *buffer; + int bufferAlloced, bufferEnd; + + bufferEnd = 0; + bufferAlloced = 1024; + buffer = (char *) mir_alloc(bufferAlloced); + buffer[0] = '\0'; + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}"); + return buffer; +} + +//return value is static +static char *SetToStyle(int style) +{ + static char szStyle[128]; + LOGFONT lf; + + LoadMsgDlgFont(style, &lf, NULL); + wsprintfA(szStyle, "\\f%u\\cf%u\\b%d\\i%d\\fs%u", style, style, lf.lfWeight >= FW_BOLD ? 1 : 0, lf.lfItalic, 2 * abs(lf.lfHeight) * 74 / logPixelSY); + return szStyle; +} + +int DbEventIsForMsgWindow(DBEVENTINFO *dbei) +{ + DBEVENTTYPEDESCR* et = ( DBEVENTTYPEDESCR* )CallService( MS_DB_EVENT_GETTYPE, ( WPARAM )dbei->szModule, ( LPARAM )dbei->eventType ); + return et && ( et->flags & DETF_MSGWINDOW ); +} + +int DbEventIsShown(DBEVENTINFO * dbei, struct SrmmWindowData *dat) +{ + switch (dbei->eventType) { + case EVENTTYPE_MESSAGE: + return 1; + case EVENTTYPE_JABBER_CHATSTATES: + case EVENTTYPE_JABBER_PRESENCE: + case EVENTTYPE_STATUSCHANGE: + case EVENTTYPE_FILE: + return (dbei->flags & DBEF_READ) == 0; + } + return DbEventIsForMsgWindow(dbei); +} + +//mir_free() the return value +static char *CreateRTFFromDbEvent(struct SrmmWindowData *dat, HANDLE hContact, HANDLE hDbEvent, struct LogStreamData *streamData) +{ + char *buffer; + int bufferAlloced, bufferEnd; + DBEVENTINFO dbei = { 0 }; + int showColon = 0; + + dbei.cbSize = sizeof(dbei); + dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM) hDbEvent, 0); + if (dbei.cbBlob == -1) + return NULL; + dbei.pBlob = (PBYTE) mir_alloc(dbei.cbBlob); + CallService(MS_DB_EVENT_GET, (WPARAM) hDbEvent, (LPARAM) & dbei); + if (!DbEventIsShown(&dbei, dat)) { + mir_free(dbei.pBlob); + return NULL; + } + if (!(dbei.flags & DBEF_SENT) && (dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei))) + { + CallService(MS_DB_EVENT_MARKREAD, (WPARAM) hContact, (LPARAM) hDbEvent); + CallService(MS_CLIST_REMOVEEVENT, (WPARAM) hContact, (LPARAM) hDbEvent); + } + else if (dbei.eventType == EVENTTYPE_STATUSCHANGE || dbei.eventType == EVENTTYPE_JABBER_CHATSTATES || dbei.eventType == EVENTTYPE_JABBER_PRESENCE) { + CallService(MS_DB_EVENT_MARKREAD, (WPARAM) hContact, (LPARAM) hDbEvent); + } + bufferEnd = 0; + bufferAlloced = 1024; + buffer = (char *) mir_alloc(bufferAlloced); + buffer[0] = '\0'; + + if (!dat->bIsAutoRTL && !streamData->isEmpty) + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\par"); + + if (dbei.flags & DBEF_RTL) { + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\rtlpar"); + dat->bIsAutoRTL = TRUE; + } + else + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\ltrpar"); + + streamData->isEmpty = 0; + + if (dat->bIsAutoRTL) { + if(dbei.flags & DBEF_RTL) { + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\ltrch\\rtlch"); + }else{ + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\rtlch\\ltrch"); + } + } + + if (g_dat->flags&SMF_SHOWICONS) { + int i; + + switch (dbei.eventType) { + case EVENTTYPE_MESSAGE: + if (dbei.flags & DBEF_SENT) { + i = LOGICON_MSG_OUT; + } + else { + i = LOGICON_MSG_IN; + } + break; + case EVENTTYPE_JABBER_CHATSTATES: + case EVENTTYPE_JABBER_PRESENCE: + case EVENTTYPE_STATUSCHANGE: + case EVENTTYPE_FILE: + default: + i = LOGICON_MSG_NOTICE; + break; + } + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\f0\\fs14"); + while (bufferAlloced - bufferEnd < logIconBmpSize[i]) + bufferAlloced += 1024; + buffer = (char *) mir_realloc(buffer, bufferAlloced); + CopyMemory(buffer + bufferEnd, pLogIconBmpBits[i], logIconBmpSize[i]); + bufferEnd += logIconBmpSize[i]; + } + if (g_dat->flags & SMF_SHOWTIME) + { + const TCHAR* szFormat; + TCHAR str[64]; + + if (g_dat->flags & SMF_SHOWSECS) + szFormat = g_dat->flags & SMF_SHOWDATE ? _T("d s") : _T("s"); + else + szFormat = g_dat->flags & SMF_SHOWDATE ? _T("d t") : _T("t"); + + tmi.printTimeStamp(NULL, dbei.timestamp, szFormat, str, SIZEOF(str), 0); + + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYTIME : MSGFONTID_YOURTIME)); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, str); + showColon = 1; + } + if (!(g_dat->flags&SMF_HIDENAMES) && dbei.eventType != EVENTTYPE_STATUSCHANGE && dbei.eventType != EVENTTYPE_JABBER_CHATSTATES && dbei.eventType != EVENTTYPE_JABBER_PRESENCE) { + TCHAR* szName; + CONTACTINFO ci = {0}; + + if (dbei.flags & DBEF_SENT) { + ci.cbSize = sizeof(ci); + ci.szProto = dbei.szModule; + ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; + if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) { + // CNF_DISPLAY always returns a string type + szName = ci.pszVal; + } + } + else szName = ( TCHAR* ) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR); + + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYNAME : MSGFONTID_YOURNAME)); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, szName); + showColon = 1; + if (ci.pszVal) + mir_free(ci.pszVal); + } + + if (showColon) + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "%s :", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYCOLON : MSGFONTID_YOURCOLON)); + + switch (dbei.eventType) { + default: + case EVENTTYPE_MESSAGE: + { + TCHAR* msg = DbGetEventTextT( &dbei, CP_ACP ); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYMSG : MSGFONTID_YOURMSG)); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, msg); + + mir_free(msg); + break; + } + case EVENTTYPE_JABBER_CHATSTATES: + case EVENTTYPE_JABBER_PRESENCE: + case EVENTTYPE_STATUSCHANGE: + { + TCHAR *msg, *szName; + CONTACTINFO ci = {0}; + + if (dbei.flags & DBEF_SENT) { + ci.cbSize = sizeof(ci); + ci.hContact = NULL; + ci.szProto = dbei.szModule; + ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; + + if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) { + // CNF_DISPLAY always returns a string type + szName = ci.pszVal; + } + } + else szName = ( TCHAR* )CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR); + + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(MSGFONTID_NOTICE)); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, szName); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, _T(" ")); + + msg = DbGetEventTextT( &dbei, CP_ACP ); + if ( msg ) { + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, msg); + mir_free( msg ); + } + mir_free(ci.pszVal); + break; + } + case EVENTTYPE_FILE: + { + char* filename = (char*)dbei.pBlob + sizeof(DWORD); + char* descr = filename + strlen( filename ) + 1; + TCHAR* ptszFileName = DbGetEventStringT( &dbei, filename ); + + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(MSGFONTID_NOTICE)); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, + (dbei.flags & DBEF_SENT) ? TranslateT("File sent") : TranslateT("File received")); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, ": "); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, ptszFileName); + mir_free( ptszFileName ); + + if ( *descr != 0 ) { + TCHAR* ptszDescr = DbGetEventStringT( &dbei, descr ); + AppendToBuffer( &buffer, &bufferEnd, &bufferAlloced, " (" ); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, ptszDescr); + AppendToBuffer( &buffer, &bufferEnd, &bufferAlloced, ")" ); + mir_free( ptszDescr ); + } + break; + } } + + if(dat->bIsAutoRTL) + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\par"); + + mir_free(dbei.pBlob); + return buffer; +} + +static DWORD CALLBACK LogStreamInEvents(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb) +{ + struct LogStreamData *dat = (struct LogStreamData *) dwCookie; + + if (dat->buffer == NULL) + { + dat->bufferOffset = 0; + switch (dat->stage) + { + case STREAMSTAGE_HEADER: + dat->buffer = CreateRTFHeader(dat->dlgDat); + dat->stage = STREAMSTAGE_EVENTS; + break; + + case STREAMSTAGE_EVENTS: + if (dat->eventsToInsert) + { + do + { + dat->buffer = CreateRTFFromDbEvent(dat->dlgDat, dat->hContact, dat->hDbEvent, dat); + if (dat->buffer) + dat->hDbEventLast = dat->hDbEvent; + dat->hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) dat->hDbEvent, 0); + if (--dat->eventsToInsert == 0) + break; + } while (dat->buffer == NULL && dat->hDbEvent); + if (dat->buffer) + { + dat->isEmpty = 0; + break; + } + } + dat->stage = STREAMSTAGE_TAIL; + //fall through + case STREAMSTAGE_TAIL: + dat->buffer = CreateRTFTail(dat->dlgDat); + dat->stage = STREAMSTAGE_STOP; + break; + case STREAMSTAGE_STOP: + *pcb = 0; + return 0; + } + dat->bufferLen = (int)strlen(dat->buffer); + } + *pcb = min(cb, dat->bufferLen - dat->bufferOffset); + CopyMemory(pbBuff, dat->buffer + dat->bufferOffset, *pcb); + dat->bufferOffset += *pcb; + if (dat->bufferOffset == dat->bufferLen) + { + mir_free(dat->buffer); + dat->buffer = NULL; + } + return 0; +} + +void StreamInEvents(HWND hwndDlg, HANDLE hDbEventFirst, int count, int fAppend) +{ + EDITSTREAM stream = {0}; + struct LogStreamData streamData = {0}; + struct SrmmWindowData *dat = (struct SrmmWindowData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + CHARRANGE oldSel, sel; + POINT scrollPos; + BOOL bottomScroll = TRUE; + + HWND hwndLog = GetDlgItem(hwndDlg, IDC_LOG); + + SendMessage(hwndLog, WM_SETREDRAW, FALSE, 0); + SendMessage(hwndLog, EM_EXGETSEL, 0, (LPARAM) & oldSel); + streamData.hContact = dat->hContact; + streamData.hDbEvent = hDbEventFirst; + streamData.dlgDat = dat; + streamData.eventsToInsert = count; + streamData.isEmpty = !fAppend || GetWindowTextLength(hwndLog) == 0; + stream.pfnCallback = LogStreamInEvents; + stream.dwCookie = (DWORD_PTR)&streamData; + + if (!streamData.isEmpty) + { + bottomScroll = (GetFocus() != hwndLog); + if (bottomScroll && (GetWindowLongPtr(hwndLog, GWL_STYLE) & WS_VSCROLL)) + { + SCROLLINFO si = {0}; + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; + GetScrollInfo(hwndLog, SB_VERT, &si); + bottomScroll = (si.nPos + (int)si.nPage) >= si.nMax; + } + if (!bottomScroll) + SendMessage(hwndLog, EM_GETSCROLLPOS, 0, (LPARAM) & scrollPos); + } + if (fAppend) + { + sel.cpMin = sel.cpMax = -1; + SendMessage(hwndLog, EM_EXSETSEL, 0, (LPARAM) & sel); + } + + strcpy(szSep2, fAppend ? "\\par\\sl0" : "\\sl1000"); + strcpy(szSep2_RTL, fAppend ? "\\rtlpar\\rtlmark\\par\\sl1000" : "\\sl1000"); + + SendMessage(hwndLog, EM_STREAMIN, fAppend ? SFF_SELECTION | SF_RTF : SF_RTF, (LPARAM) & stream); + if (bottomScroll) + { + sel.cpMin = sel.cpMax = -1; + SendMessage(hwndLog, EM_EXSETSEL, 0, (LPARAM) & sel); + if (GetWindowLongPtr(hwndLog, GWL_STYLE) & WS_VSCROLL) + { + SendMessage(hwndDlg, DM_SCROLLLOGTOBOTTOM, 0, 0); + PostMessage(hwndDlg, DM_SCROLLLOGTOBOTTOM, 0, 0); + } + } + else + { + SendMessage(hwndLog, EM_EXSETSEL, 0, (LPARAM) & oldSel); + SendMessage(hwndLog, EM_SETSCROLLPOS, 0, (LPARAM) & scrollPos); + } + + SendMessage(hwndLog, WM_SETREDRAW, TRUE, 0); + if (bottomScroll) + RedrawWindow(hwndLog, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + dat->hDbEventLast = streamData.hDbEventLast; +} + +#define RTFPICTHEADERMAXSIZE 78 +void LoadMsgLogIcons(void) +{ + HICON hIcon; + HBITMAP hBmp, hoBmp; + HDC hdc, hdcMem; + BITMAPINFOHEADER bih = { 0 }; + int widthBytes, i; + RECT rc; + HBRUSH hBkgBrush; + int rtfHeaderSize; + PBYTE pBmpBits; + + hBkgBrush = CreateSolidBrush(DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR)); + bih.biSize = sizeof(bih); + bih.biBitCount = 24; + bih.biCompression = BI_RGB; + bih.biHeight = 10; + bih.biPlanes = 1; + bih.biWidth = 10; + widthBytes = ((bih.biWidth * bih.biBitCount + 31) >> 5) * 4; + rc.top = rc.left = 0; + rc.right = bih.biWidth; + rc.bottom = bih.biHeight; + hdc = GetDC(NULL); + hBmp = CreateCompatibleBitmap(hdc, bih.biWidth, bih.biHeight); + hdcMem = CreateCompatibleDC(hdc); + pBmpBits = (PBYTE) mir_alloc(widthBytes * bih.biHeight); + + for (i = 0; i < SIZEOF(pLogIconBmpBits); i++) { + hIcon = Skin_GetIconByHandle(hIconLibItem[i]); + pLogIconBmpBits[i] = (PBYTE) mir_alloc(RTFPICTHEADERMAXSIZE + (bih.biSize + widthBytes * bih.biHeight) * 2); + //I can't seem to get binary mode working. No matter. + rtfHeaderSize = sprintf((char*)pLogIconBmpBits[i], "{\\pict\\dibitmap0\\wbmbitspixel%u\\wbmplanes1\\wbmwidthbytes%u\\picw%u\\pich%u ", bih.biBitCount, widthBytes, bih.biWidth, bih.biHeight); + hoBmp = (HBITMAP) SelectObject(hdcMem, hBmp); + FillRect(hdcMem, &rc, hBkgBrush); + DrawIconEx(hdcMem, 0, 0, hIcon, bih.biWidth, bih.biHeight, 0, NULL, DI_NORMAL); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); + + SelectObject(hdcMem, hoBmp); + GetDIBits(hdc, hBmp, 0, bih.biHeight, pBmpBits, (BITMAPINFO *) & bih, DIB_RGB_COLORS); + { + int n; + for (n = 0; n < sizeof(BITMAPINFOHEADER); n++) + sprintf((char*)pLogIconBmpBits[i] + rtfHeaderSize + n * 2, "%02X", ((PBYTE) & bih)[n]); + for (n = 0; n < widthBytes * bih.biHeight; n += 4) + sprintf((char*)pLogIconBmpBits[i] + rtfHeaderSize + (bih.biSize + n) * 2, "%02X%02X%02X%02X", pBmpBits[n], pBmpBits[n + 1], pBmpBits[n + 2], pBmpBits[n + 3]); + } + logIconBmpSize[i] = rtfHeaderSize + (bih.biSize + widthBytes * bih.biHeight) * 2 + 1; + pLogIconBmpBits[i][logIconBmpSize[i] - 1] = '}'; + } + mir_free(pBmpBits); + DeleteDC(hdcMem); + DeleteObject(hBmp); + ReleaseDC(NULL, hdc); + DeleteObject(hBkgBrush); +} + +void FreeMsgLogIcons(void) +{ + int i; + for (i = 0; i < SIZEOF(pLogIconBmpBits); i++) + mir_free(pLogIconBmpBits[i]); +} -- cgit v1.2.3