From 123fa87f68c42b4f121ad315623a9fb5a39ab30c Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 14 Apr 2023 23:33:11 +0300 Subject: all LogStreamInEvents implementations unified, old memory allocation schema dropped --- include/m_srmm_int.h | 28 +++- libs/win32/mir_app.lib | Bin 247240 -> 248080 bytes libs/win64/mir_app.lib | Bin 244384 -> 245244 bytes plugins/Scriver/src/globals.h | 2 +- plugins/Scriver/src/msglog.cpp | 256 ++++++++++++------------------------ plugins/Scriver/src/msgoptions.cpp | 6 +- plugins/TabSRMM/src/globals.cpp | 7 +- plugins/TabSRMM/src/msgdlgother.cpp | 4 +- plugins/TabSRMM/src/msglog.cpp | 231 ++++++++++---------------------- plugins/TabSRMM/src/msgoptions.cpp | 10 +- plugins/TabSRMM/src/msgs.h | 7 +- plugins/TabSRMM/src/sendqueue.cpp | 11 +- src/core/stdmsg/src/msglog.cpp | 146 +++++--------------- src/mir_app/src/mir_app.def | 2 + src/mir_app/src/mir_app64.def | 2 + src/mir_app/src/srmm_log_rtf.cpp | 104 +++++++++++++++ 16 files changed, 345 insertions(+), 471 deletions(-) diff --git a/include/m_srmm_int.h b/include/m_srmm_int.h index dc1d2303fd..817558e664 100644 --- a/include/m_srmm_int.h +++ b/include/m_srmm_int.h @@ -148,6 +148,25 @@ EXTERN_C MIR_APP_DLL(void) UnregisterSrmmLog(HANDLE); ///////////////////////////////////////////////////////////////////////////////////////// // Standard built-in RTF logger class +struct RtfLogStreamBase +{ + int stage; + MCONTACT hContact; + MEVENT hDbEvent, hDbEventLast; + int eventsToInsert; + int isFirst, isEmpty; + + CMStringA buf; + DB::EventInfo *dbei; + class CRtfLogWindow *pLog; +}; + +#ifdef SRMM_OWN_STRUCTURES + struct RtfLogStreamData; +#else + struct RtfLogStreamData : public RtfLogStreamBase {}; +#endif + class MIR_APP_EXPORT CRtfLogWindow : public CSrmmLogWindow { protected: @@ -159,9 +178,16 @@ public: CRtfLogWindow(CMsgDialog &pDlg); ~CRtfLogWindow() override; - virtual void AppendUnicodeString(CMStringA &str, const wchar_t *pwszBuf) = 0; + virtual void AppendUnicodeString(CMStringA &str, const wchar_t *pwszBuf) = 0; + + virtual void CreateRtfHeader(RtfLogStreamData *dat) = 0; + virtual bool CreateRtfEvent(RtfLogStreamData *dat, DB::EventInfo &dbei) = 0; + virtual void CreateRtfTail(RtfLogStreamData *dat); + virtual INT_PTR WndProc(UINT msg, WPARAM wParam, LPARAM lParam); + void StreamRtfEvents(RtfLogStreamData *dat, bool bAppend); + //////////////////////////////////////////////////////////////////////////////////////// void Attach() override; void Detach() override; diff --git a/libs/win32/mir_app.lib b/libs/win32/mir_app.lib index e3cbf06fe8..820cc36f10 100644 Binary files a/libs/win32/mir_app.lib and b/libs/win32/mir_app.lib differ diff --git a/libs/win64/mir_app.lib b/libs/win64/mir_app.lib index e81866f711..8d0712009a 100644 Binary files a/libs/win64/mir_app.lib and b/libs/win64/mir_app.lib differ diff --git a/plugins/Scriver/src/globals.h b/plugins/Scriver/src/globals.h index 995d823ebb..69758366a4 100644 --- a/plugins/Scriver/src/globals.h +++ b/plugins/Scriver/src/globals.h @@ -135,6 +135,6 @@ int ImageList_AddIcon_Ex2(HIMAGELIST hIml, HICON hIcon); int ImageList_ReplaceIcon_Ex(HIMAGELIST hIml, int nIndex, int id); int ImageList_AddIcon_ProtoEx(HIMAGELIST hIml, const char *szProto, int status); -void StreamInTestEvents(HWND hEditWnd, GlobalMessageData *gdat); +void StreamInTestEvents(CDlgBase *pDlg, GlobalMessageData *gdat); #endif diff --git a/plugins/Scriver/src/msglog.cpp b/plugins/Scriver/src/msglog.cpp index 6b3e777bca..9371504a9d 100644 --- a/plugins/Scriver/src/msglog.cpp +++ b/plugins/Scriver/src/msglog.cpp @@ -31,27 +31,11 @@ static int logPixelSY; static char* pLogIconBmpBits[3]; static HIMAGELIST g_hImageList; -#define STREAMSTAGE_HEADER 0 -#define STREAMSTAGE_EVENTS 1 -#define STREAMSTAGE_TAIL 2 -#define STREAMSTAGE_STOP 3 - -struct LogStreamData +struct RtfLogStreamData : public RtfLogStreamBase { - int stage; - MCONTACT hContact; - MEVENT hDbEvent, hDbEventLast; - char *buffer; - size_t bufferOffset, bufferLen; - int eventsToInsert; - int isFirst; - class CLogWindow *pLog; GlobalMessageData *gdat; - DB::EventInfo *dbei; }; -static DWORD CALLBACK LogStreamInEvents(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb); - bool DbEventIsMessageOrCustom(const DB::EventInfo &dbei) { return dbei.eventType == EVENTTYPE_MESSAGE || dbei.eventType == EVENTTYPE_FILE || dbei.isSrmm(); @@ -108,51 +92,6 @@ static void AppendUnicodeToBuffer(CMStringA &buf, const wchar_t *line) buf.AppendChar('}'); } -// mir_free() the return value -static char* CreateRTFHeader() -{ - HDC hdc = GetDC(nullptr); - logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); - ReleaseDC(nullptr, hdc); - - CMStringA buf; - - buf.Append("{\\rtf1\\ansi\\deff0{\\fonttbl"); - for (int i = 0; i < fontOptionsListSize; i++) { - LOGFONT lf; - LoadMsgDlgFont(i, &lf, nullptr); - buf.AppendFormat("{\\f%u\\fnil\\fcharset%u %S;}", i, lf.lfCharSet, lf.lfFaceName); - } - buf.Append("}{\\colortbl "); - - COLORREF colour; - for (int i = 0; i < fontOptionsListSize; i++) { - LoadMsgDlgFont(i, nullptr, &colour); - buf.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - } - if (GetSysColorBrush(COLOR_HOTLIGHT) == nullptr) - colour = RGB(0, 0, 255); - else - colour = GetSysColor(COLOR_HOTLIGHT); - buf.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - colour = g_plugin.getDword(SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR); - buf.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - colour = g_plugin.getDword(SRMSGSET_INCOMINGBKGCOLOUR, SRMSGDEFSET_INCOMINGBKGCOLOUR); - buf.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - colour = g_plugin.getDword(SRMSGSET_OUTGOINGBKGCOLOUR, SRMSGDEFSET_OUTGOINGBKGCOLOUR); - buf.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - colour = g_plugin.getDword(SRMSGSET_LINECOLOUR, SRMSGDEFSET_LINECOLOUR); - buf.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - buf.Append("}"); - return buf.Detach(); -} - -// mir_free() the return value -static char* CreateRTFTail() -{ - return mir_strdup("}"); -} - // return value is static static char* SetToStyle(int style) { @@ -222,7 +161,7 @@ int isSameDate(time_t time1, time_t time2) return 0; } -static void AppendWithCustomLinks(DBEVENTINFO &dbei, int style, CMStringA &buf) +static void AppendWithCustomLinks(const DB::EventInfo &dbei, int style, CMStringA &buf) { if (dbei.pBlob == nullptr) return; @@ -322,6 +261,13 @@ void FreeMsgLogIcons(void) ///////////////////////////////////////////////////////////////////////////////////////// // CLogWindow - built-in log window +const char *szBuiltinEvents[] = { + "O Lord, bless this Thy hand grenade that with it Thou mayest blow Thine enemies", + "to tiny bits, in Thy mercy", + "Lorem ipsum dolor sit amet,", + "consectetur adipisicing elit", +}; + class CLogWindow : public CRtfLogWindow { typedef CRtfLogWindow CSuper; @@ -372,12 +318,63 @@ public: m_rtf.SendMsg(EM_AUTOURLDETECT, TRUE, 0); } - char* CreateRTFFromEvent(DB::EventInfo &dbei, LogStreamData *streamData) + void CreateRtfHeader(RtfLogStreamData *streamData) override + { + HDC hdc = GetDC(nullptr); + logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); + ReleaseDC(nullptr, hdc); + + auto &buf = streamData->buf; + + buf.Append("{\\rtf1\\ansi\\deff0{\\fonttbl"); + for (int i = 0; i < fontOptionsListSize; i++) { + LOGFONT lf; + LoadMsgDlgFont(i, &lf, nullptr); + buf.AppendFormat("{\\f%u\\fnil\\fcharset%u %S;}", i, lf.lfCharSet, lf.lfFaceName); + } + buf.Append("}{\\colortbl "); + + COLORREF colour; + for (int i = 0; i < fontOptionsListSize; i++) { + LoadMsgDlgFont(i, nullptr, &colour); + buf.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + } + if (GetSysColorBrush(COLOR_HOTLIGHT) == nullptr) + colour = RGB(0, 0, 255); + else + colour = GetSysColor(COLOR_HOTLIGHT); + buf.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + colour = g_plugin.getDword(SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR); + buf.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + colour = g_plugin.getDword(SRMSGSET_INCOMINGBKGCOLOUR, SRMSGDEFSET_INCOMINGBKGCOLOUR); + buf.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + colour = g_plugin.getDword(SRMSGSET_OUTGOINGBKGCOLOUR, SRMSGDEFSET_OUTGOINGBKGCOLOUR); + buf.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + colour = g_plugin.getDword(SRMSGSET_LINECOLOUR, SRMSGDEFSET_LINECOLOUR); + buf.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + buf.Append("}"); + } + + bool CreateRtfEvent(RtfLogStreamData *streamData, DB::EventInfo &dbei) override { + if (!DbEventIsShown(dbei)) + return false; + + if (streamData->dbei) { + if (streamData->eventsToInsert == _countof(szBuiltinEvents)) + return false; + + dbei.flags = DBEF_UTF | ((streamData->eventsToInsert < 2) ? DBEF_SENT : 0); + dbei.pBlob = (uint8_t *)TranslateU(szBuiltinEvents[streamData->eventsToInsert]); + dbei.cbBlob = (int)mir_strlen((char *)dbei.pBlob); + } + int style, showColon = 0; int isGroupBreak = TRUE; int highlight = 0; + auto *gdat = streamData->gdat; + auto &buf = streamData->buf; if ((gdat->flags.bGroupMessages) && dbei.flags == LOWORD(m_lastEventType) && dbei.eventType == EVENTTYPE_MESSAGE && HIWORD(m_lastEventType) == EVENTTYPE_MESSAGE && @@ -385,21 +382,21 @@ public: isGroupBreak = FALSE; } + bool bIsRtl = (dbei.flags & DBEF_RTL) != 0; ptrW wszText(DbEvent_GetTextW(&dbei, CP_UTF8)), wszNick; // test contact - if (m_pDlg.m_hContact != 0) { + if (streamData->dbei == 0) { if (dbei.flags & DBEF_SENT) wszNick = Contact::GetInfo(CNF_DISPLAY, 0, m_pDlg.m_szProto); else wszNick = mir_wstrdup(Clist_GetContactDisplayName(m_pDlg.m_hContact)); + + if (!m_pDlg.m_bUseRtl && Utils_IsRtl(wszText)) + bIsRtl = true; } else wszNick = mir_wstrdup((dbei.flags & DBEF_SENT) ? TranslateT("Me") : TranslateT("My contact")); - if (!m_pDlg.m_bUseRtl && Utils_IsRtl(wszText)) - dbei.flags |= DBEF_RTL; - - CMStringA buf; if (!streamData->isFirst && !m_isMixed) { if (isGroupBreak || gdat->flags.bMarkFollowups) buf.Append("\\par"); @@ -407,13 +404,13 @@ public: buf.Append("\\line"); } - if (dbei.flags & DBEF_RTL) + if (bIsRtl) m_isMixed = 1; if (!streamData->isFirst && isGroupBreak && (gdat->flags.bDrawLines)) buf.AppendFormat("\\sl-1\\slmult0\\highlight%d\\cf%d\\fs1 \\par\\sl0", fontOptionsListSize + 4, fontOptionsListSize + 4); - buf.Append((dbei.flags & DBEF_RTL) ? "\\rtlpar" : "\\ltrpar"); + buf.Append(bIsRtl ? "\\rtlpar" : "\\ltrpar"); if (dbei.eventType == EVENTTYPE_MESSAGE) highlight = fontOptionsListSize + 2 + ((dbei.flags & DBEF_SENT) ? 1 : 0); @@ -429,7 +426,7 @@ public: } streamData->isFirst = FALSE; if (m_isMixed) { - if (dbei.flags & DBEF_RTL) + if (bIsRtl) buf.Append("\\ltrch\\rtlch"); else buf.Append("\\rtlch\\ltrch"); @@ -505,7 +502,7 @@ public: showColon = 1; } if (showColon && dbei.eventType == EVENTTYPE_MESSAGE) { - if (dbei.flags & DBEF_RTL) + if (bIsRtl) buf.AppendFormat("\\~%s: ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYCOLON : MSGFONTID_YOURCOLON)); else buf.AppendFormat("%s: ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYCOLON : MSGFONTID_YOURCOLON)); @@ -549,7 +546,7 @@ public: m_lastEventTime = dbei.timestamp; m_lastEventType = MAKELONG(dbei.flags, dbei.eventType); - return buf.Detach(); + return true; } void LogEvents(MEVENT hDbEventFirst, int count, bool bAppend) override @@ -561,7 +558,7 @@ public: m_rtf.SetDraw(false); m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&oldSel); - LogStreamData streamData = {}; + RtfLogStreamData streamData = {}; streamData.hContact = m_pDlg.m_hContact; streamData.hDbEvent = hDbEventFirst; streamData.hDbEventLast = m_pDlg.m_hDbEventLast; @@ -570,9 +567,6 @@ public: streamData.isFirst = bAppend ? m_rtf.GetRichTextLength() == 0 : 1; streamData.gdat = &g_dat; - EDITSTREAM stream = {}; - stream.pfnCallback = LogStreamInEvents; - stream.dwCookie = (DWORD_PTR)&streamData; sel.cpMin = 0; POINT scrollPos; @@ -606,7 +600,8 @@ public: m_isMixed = 0; } - m_rtf.SendMsg(EM_STREAMIN, bAppend ? SFF_SELECTION | SF_RTF : SFF_SELECTION | SF_RTF, (LPARAM)&stream); + StreamRtfEvents(&streamData, bAppend); + if (bottomScroll) { sel.cpMin = sel.cpMax = -1; m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel); @@ -814,91 +809,7 @@ public: ///////////////////////////////////////////////////////////////////////////////////////// -const char *szBuiltinEvents[] = { - "O Lord, bless this Thy hand grenade that with it Thou mayest blow Thine enemies", - "to tiny bits, in Thy mercy", - "Lorem ipsum dolor sit amet,", - "consectetur adipisicing elit", -}; - -static DWORD CALLBACK LogStreamInEvents(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) -{ - LogStreamData *dat = (LogStreamData *)dwCookie; - - if (dat->buffer == nullptr) { - dat->bufferOffset = 0; - switch (dat->stage) { - case STREAMSTAGE_HEADER: - dat->buffer = CreateRTFHeader(); - dat->stage = STREAMSTAGE_EVENTS; - break; - - case STREAMSTAGE_EVENTS: - // predefined text event - if (dat->dbei != nullptr) { - dat->dbei->flags = DBEF_UTF | ((dat->eventsToInsert < 2) ? DBEF_SENT : 0); - dat->dbei->pBlob = (uint8_t *)TranslateU(szBuiltinEvents[dat->eventsToInsert++]); - dat->dbei->cbBlob = (int)mir_strlen((char *)dat->dbei->pBlob); - dat->buffer = dat->pLog->CreateRTFFromEvent(*dat->dbei, dat); - if (dat->eventsToInsert == _countof(szBuiltinEvents)) { - dat->dbei->pBlob = nullptr; - dat->dbei = nullptr; - } - } - // usual database event - else if (dat->eventsToInsert) { - do { - dat->buffer = nullptr; - - DB::EventInfo dbei(dat->hDbEvent); - if (dbei && DbEventIsShown(dbei)) { - dat->buffer = dat->pLog->CreateRTFFromEvent(dbei, dat); - - if (!(dbei.flags & DBEF_SENT) && (dbei.eventType == EVENTTYPE_MESSAGE || dbei.isSrmm())) { - db_event_markRead(dat->hContact, dat->hDbEvent); - g_clistApi.pfnRemoveEvent(dat->hContact, dat->hDbEvent); - } - else if (dbei.eventType == EVENTTYPE_JABBER_CHATSTATES || dbei.eventType == EVENTTYPE_JABBER_PRESENCE) - db_event_markRead(dat->hContact, dat->hDbEvent); - } - - if (dat->buffer) - dat->hDbEventLast = dat->hDbEvent; - dat->hDbEvent = db_event_next(dat->hContact, dat->hDbEvent); - if (--dat->eventsToInsert == 0) - break; - } while (dat->buffer == nullptr && dat->hDbEvent); - } - if (dat->buffer) - break; - - dat->stage = STREAMSTAGE_TAIL; - __fallthrough; - - case STREAMSTAGE_TAIL: - dat->buffer = CreateRTFTail(); - dat->stage = STREAMSTAGE_STOP; - break; - - case STREAMSTAGE_STOP: - *pcb = 0; - return 0; - } - dat->bufferLen = mir_strlen(dat->buffer); - } - *pcb = min(cb, LONG(dat->bufferLen - dat->bufferOffset)); - memcpy(pbBuff, dat->buffer + dat->bufferOffset, *pcb); - dat->bufferOffset += *pcb; - if (dat->bufferOffset == dat->bufferLen) { - mir_free(dat->buffer); - dat->buffer = nullptr; - } - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void StreamInTestEvents(HWND hEditWnd, GlobalMessageData *gdat) +void StreamInTestEvents(CDlgBase *pDlg, GlobalMessageData *gdat) { DB::EventInfo dbei; dbei.flags = DBEF_UTF; @@ -906,22 +817,19 @@ void StreamInTestEvents(HWND hEditWnd, GlobalMessageData *gdat) dbei.timestamp = time(0); dbei.szModule = SRMM_MODULE; - CMsgDialog *dat = new CMsgDialog(0, false); + auto *pLog = new CLogWindow(*(CMsgDialog*)pDlg); - LogStreamData streamData = {}; + RtfLogStreamData streamData = {}; streamData.isFirst = TRUE; streamData.dbei = &dbei; - streamData.pLog = new CLogWindow(*dat); + streamData.pLog = pLog; streamData.gdat = gdat; + pLog->StreamRtfEvents(&streamData, false); - EDITSTREAM stream = { 0 }; - stream.pfnCallback = LogStreamInEvents; - stream.dwCookie = (DWORD_PTR)&streamData; - SendMessage(hEditWnd, EM_STREAMIN, SF_RTF, (LPARAM)&stream); - SendMessage(hEditWnd, EM_HIDESELECTION, FALSE, 0); + SendDlgItemMessage(pDlg->GetHwnd(), IDC_SRMM_LOG, EM_HIDESELECTION, FALSE, 0); - delete streamData.pLog; - delete dat; + dbei.pBlob = nullptr; + delete pLog; } ///////////////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/Scriver/src/msgoptions.cpp b/plugins/Scriver/src/msgoptions.cpp index 226307dcd2..3ffb686ae7 100644 --- a/plugins/Scriver/src/msgoptions.cpp +++ b/plugins/Scriver/src/msgoptions.cpp @@ -296,12 +296,12 @@ public: void onChange_Cascade(CCtrlCheck *pCheck) { - chkSavePerContact.SetState(!pCheck->GetState()); + chkSavePerContact.SetState(!pCheck->IsChecked()); } void onChange_SavePerContact(CCtrlCheck *pCheck) { - chkCascade.SetState(!pCheck->GetState()); + chkCascade.SetState(!pCheck->IsChecked()); } }; @@ -528,7 +528,7 @@ class CLogOptionsDlg : public CBaseOptionDlg pf2.dxOffset = (gdat.flags.bIndentText) ? gdat.indentSize * 1440 / g_dat.logPixelSX : 0; m_rtf.SendMsg(EM_SETPARAFORMAT, 0, (LPARAM)&pf2); - StreamInTestEvents(m_rtf.GetHwnd(), &gdat); + StreamInTestEvents(this, &gdat); } public: diff --git a/plugins/TabSRMM/src/globals.cpp b/plugins/TabSRMM/src/globals.cpp index 7c7a649412..997bd3780c 100644 --- a/plugins/TabSRMM/src/globals.cpp +++ b/plugins/TabSRMM/src/globals.cpp @@ -494,10 +494,9 @@ void CGlobals::logStatusChange(WPARAM wParam, const CContactCache *c) else text.Format(TranslateT("changed status from %s to %s."), szOldStatus, szNewStatus); - T2Utf szMsg(text); - DBEVENTINFO dbei = {}; - dbei.pBlob = (uint8_t*)(char*)szMsg; - dbei.cbBlob = (int)mir_strlen(szMsg) + 1; + DB::EventInfo dbei; + dbei.pBlob = (uint8_t*)T2Utf(text).detach(); + dbei.cbBlob = (int)mir_strlen((char*)dbei.pBlob); dbei.flags = DBEF_UTF | DBEF_READ; dbei.eventType = EVENTTYPE_STATUSCHANGE; dbei.timestamp = time(0); diff --git a/plugins/TabSRMM/src/msgdlgother.cpp b/plugins/TabSRMM/src/msgdlgother.cpp index 2360894d31..68b97ba962 100644 --- a/plugins/TabSRMM/src/msgdlgother.cpp +++ b/plugins/TabSRMM/src/msgdlgother.cpp @@ -1413,7 +1413,7 @@ void CMsgDialog::LoadSplitter() ///////////////////////////////////////////////////////////////////////////////////////// -void CMsgDialog::LogEvent(DBEVENTINFO &dbei) +void CMsgDialog::LogEvent(DB::EventInfo &dbei) { if (m_iLogMode != WANT_BUILTIN_LOG) { dbei.flags |= DBEF_TEMPORARY; @@ -1424,7 +1424,7 @@ void CMsgDialog::LogEvent(DBEVENTINFO &dbei) db_event_delete(hDbEvent); } } - else LOG()->LogEvents(0, 1, true, &dbei); + else LOG()->LogEvents(0, 0, true, &dbei); } ///////////////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/TabSRMM/src/msglog.cpp b/plugins/TabSRMM/src/msglog.cpp index 59b68b9bc5..c48d5d1d4d 100644 --- a/plugins/TabSRMM/src/msglog.cpp +++ b/plugins/TabSRMM/src/msglog.cpp @@ -80,22 +80,9 @@ COLORREF fontcolors[MSGDLGFONTCOUNT + 2]; static HICON Logicons[NR_LOGICONS]; -#define STREAMSTAGE_HEADER 0 -#define STREAMSTAGE_EVENTS 1 -#define STREAMSTAGE_TAIL 2 -#define STREAMSTAGE_STOP 3 -struct LogStreamData +struct RtfLogStreamData : public RtfLogStreamBase { - int stage; - MCONTACT hContact; - MEVENT hDbEvent, hDbEventLast; - char *buffer; - int bufferOffset, bufferLen; - int eventsToInsert; - int isEmpty; int isAppend; - class CLogWindow *pLog; - DBEVENTINFO *dbei; }; __forceinline char* GetRTFFont(uint32_t dwIndex) @@ -303,68 +290,6 @@ static void AppendUnicodeToBuffer(CMStringA &str, const wchar_t *line, int mode) str.AppendChar('}'); } -///////////////////////////////////////////////////////////////////////////////////////// -// mir_free() the return value - -static char* CreateRTFHeader(CLogWindow *pLog) -{ - int i; - CMStringA str; - auto &dat = pLog->GetDialog(); - TLogTheme *theme = &dat.m_pContainer->m_theme; - LOGFONTW *logFonts = theme->logFonts; - COLORREF *fontColors = theme->fontColors; - - str.Append("{\\rtf1\\ansi\\deff0{\\fonttbl"); - - for (i = 0; i < MSGDLGFONTCOUNT; i++) - str.AppendFormat("{\\f%u\\fnil\\fcharset%u %S;}", i, logFonts[i].lfCharSet, logFonts[i].lfFaceName); - str.AppendFormat("{\\f%u\\fnil\\fcharset%u %s;}", MSGDLGFONTCOUNT, logFonts[i].lfCharSet, "Arial"); - - str.Append("}{\\colortbl "); - for (i = 0; i < MSGDLGFONTCOUNT; i++) - str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(fontColors[i]), GetGValue(fontColors[i]), GetBValue(fontColors[i])); - - COLORREF colour = (GetSysColorBrush(COLOR_HOTLIGHT) == nullptr) ? RGB(0, 0, 255) : GetSysColor(COLOR_HOTLIGHT); - str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - - // OnO: Create incoming and outcoming colours - colour = theme->inbg; - str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - colour = theme->outbg; - str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - colour = theme->bg; - str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - colour = theme->hgrid; - str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - colour = theme->oldinbg; - str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - colour = theme->oldoutbg; - str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - colour = theme->statbg; - str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - - // custom template colors... - for (i = 1; i <= 5; i++) { - colour = theme->custom_colors[i - 1]; - if (colour == 0) - colour = RGB(1, 1, 1); - str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - } - - // bbcode colors... - for (auto &p : Utils::rtf_clrs) - str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(p->clr), GetGValue(p->clr), GetBValue(p->clr)); - - // paragraph header - str.AppendFormat("}"); - - // indent - if (!(dat.m_dwFlags & MWF_LOG_INDENT)) - str.AppendFormat("\\li%u\\ri%u\\fi%u\\tx%u", 2 * 15, 2 * 15, 0, 70 * 15); - return str.Detach(); -} - static void AppendTimeStamp(wchar_t *szFinalTimestamp, int isSent, CMStringA &str, int skipFont, CMsgDialog *dat, int iFontIDOffset) { if (!skipFont) { @@ -399,12 +324,6 @@ static wchar_t* Template_MakeRelativeDate(HANDLE hTimeZone, time_t check, wchar_ return szResult; } -// mir_free() the return value -static char *CreateRTFTail() -{ - return mir_strdup("}"); -} - bool DbEventIsShown(const DB::EventInfo &dbei) { if (!IsCustomEvent(dbei.eventType) || dbei.isSrmm()) @@ -413,57 +332,6 @@ bool DbEventIsShown(const DB::EventInfo &dbei) return IsStatusEvent(dbei.eventType); } -static DWORD CALLBACK LogStreamInEvents(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) -{ - LogStreamData *dat = (LogStreamData*)dwCookie; - - if (dat->buffer == nullptr) { - dat->bufferOffset = 0; - switch (dat->stage) { - case STREAMSTAGE_HEADER: - mir_free(dat->buffer); - dat->buffer = CreateRTFHeader(dat->pLog); - dat->stage = STREAMSTAGE_EVENTS; - break; - - case STREAMSTAGE_EVENTS: - if (dat->eventsToInsert) { - do { - mir_free(dat->buffer); - dat->buffer = dat->pLog->CreateRTFFromDbEvent(dat); - if (dat->buffer) - dat->hDbEventLast = dat->hDbEvent; - dat->hDbEvent = db_event_next(dat->hContact, dat->hDbEvent); - if (--dat->eventsToInsert == 0) - break; - } while (dat->buffer == nullptr && dat->hDbEvent); - - if (dat->buffer) - break; - } - dat->stage = STREAMSTAGE_TAIL; - __fallthrough; - - case STREAMSTAGE_TAIL: - mir_free(dat->buffer); - dat->buffer = CreateRTFTail(); - dat->stage = STREAMSTAGE_STOP; - break; - - case STREAMSTAGE_STOP: - *pcb = 0; - return 0; - } - dat->bufferLen = (int)mir_strlen(dat->buffer); - } - *pcb = min(cb, dat->bufferLen - dat->bufferOffset); - memcpy(pbBuff, dat->buffer + dat->bufferOffset, *pcb); - dat->bufferOffset += *pcb; - if (dat->bufferOffset == dat->bufferLen) - replaceStr(dat->buffer, nullptr); - return 0; -} - ///////////////////////////////////////////////////////////////////////////////////////// INT_PTR CLogWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam) @@ -618,23 +486,79 @@ void CLogWindow::Attach() ///////////////////////////////////////////////////////////////////////////////////////// -char* CLogWindow::CreateRTFFromDbEvent(LogStreamData *streamData) +void CLogWindow::CreateRtfHeader(RtfLogStreamData *streamData) { + int i; + auto &str = streamData->buf; + auto &dat = m_pDlg; + TLogTheme *theme = &dat.m_pContainer->m_theme; + LOGFONTW *logFonts = theme->logFonts; + COLORREF *fontColors = theme->fontColors; + + str.Append("{\\rtf1\\ansi\\deff0{\\fonttbl"); + + for (i = 0; i < MSGDLGFONTCOUNT; i++) + str.AppendFormat("{\\f%u\\fnil\\fcharset%u %S;}", i, logFonts[i].lfCharSet, logFonts[i].lfFaceName); + str.AppendFormat("{\\f%u\\fnil\\fcharset%u %s;}", MSGDLGFONTCOUNT, logFonts[i].lfCharSet, "Arial"); + + str.Append("}{\\colortbl "); + for (i = 0; i < MSGDLGFONTCOUNT; i++) + str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(fontColors[i]), GetGValue(fontColors[i]), GetBValue(fontColors[i])); + + COLORREF colour = (GetSysColorBrush(COLOR_HOTLIGHT) == nullptr) ? RGB(0, 0, 255) : GetSysColor(COLOR_HOTLIGHT); + str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + + // OnO: Create incoming and outcoming colours + colour = theme->inbg; + str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + colour = theme->outbg; + str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + colour = theme->bg; + str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + colour = theme->hgrid; + str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + colour = theme->oldinbg; + str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + colour = theme->oldoutbg; + str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + colour = theme->statbg; + str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + + // custom template colors... + for (i = 1; i <= 5; i++) { + colour = theme->custom_colors[i - 1]; + if (colour == 0) + colour = RGB(1, 1, 1); + str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + } + + // bbcode colors... + for (auto &p : Utils::rtf_clrs) + str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(p->clr), GetGValue(p->clr), GetBValue(p->clr)); + + // paragraph header + str.AppendFormat("}"); + + // indent + if (!(dat.m_dwFlags & MWF_LOG_INDENT)) + str.AppendFormat("\\li%u\\ri%u\\fi%u\\tx%u", 2 * 15, 2 * 15, 0, 70 * 15); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +bool CLogWindow::CreateRtfEvent(RtfLogStreamData *streamData, DB::EventInfo &dbei) +{ + if (!DbEventIsShown(dbei)) + return false; + + if (streamData->dbei && streamData->eventsToInsert > 0) + return false; + HANDLE hTimeZone = nullptr; struct tm event_time = { 0 }; bool skipToNext = false, skipFont = false; bool isBold = false, isItalic = false, isUnderline = false; - DB::EventInfo dbei; - if (streamData->dbei != nullptr) - memcpy(&dbei, streamData->dbei, sizeof(DBEVENTINFO)); - else { - dbei.cbBlob = -1; - db_event_get(streamData->hDbEvent, &dbei); - if (!DbEventIsShown(dbei)) - return nullptr; - } - auto *dat = &m_pDlg; if (dbei.eventType == EVENTTYPE_MESSAGE && !dbei.markedRead()) dat->m_cache->updateStats(TSessionStats::SET_LAST_RCV, mir_strlen((char *)dbei.pBlob)); @@ -653,7 +577,7 @@ char* CLogWindow::CreateRTFFromDbEvent(LogStreamData *streamData) msg.TrimRight(); dat->FormatRaw(msg, 1, FALSE); - CMStringA str; + auto &str = streamData->buf; // means: last \\par was deleted to avoid new line at end of log if (dat->m_bLastParaDeleted) { @@ -1184,9 +1108,6 @@ skip: str.Append("\\par"); - if (streamData->dbei != nullptr) - dbei.pBlob = 0; - dat->m_iLastEventType = MAKELONG((dbei.flags & (DBEF_SENT | DBEF_READ | DBEF_RTL)), dbei.eventType); dat->m_lastEventTime = dbei.timestamp; return str.Detach(); @@ -1199,7 +1120,7 @@ void CLogWindow::LogEvents(MEVENT hDbEventFirst, int count, bool fAppend) LogEvents(hDbEventFirst, count, fAppend, nullptr); } -void CLogWindow::LogEvents(MEVENT hDbEventFirst, int count, bool fAppend, DBEVENTINFO *dbei_s) +void CLogWindow::LogEvents(MEVENT hDbEventFirst, int count, bool fAppend, DB::EventInfo *dbei_s) { CHARRANGE oldSel, sel; @@ -1228,7 +1149,7 @@ void CLogWindow::LogEvents(MEVENT hDbEventFirst, int count, bool fAppend, DBEVEN m_rtf.SendMsg(EM_HIDESELECTION, TRUE, 0); m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&oldSel); - LogStreamData streamData = { 0 }; + RtfLogStreamData streamData = { 0 }; streamData.hContact = m_pDlg.m_hContact; streamData.hDbEvent = hDbEventFirst; streamData.pLog = this; @@ -1237,10 +1158,6 @@ void CLogWindow::LogEvents(MEVENT hDbEventFirst, int count, bool fAppend, DBEVEN streamData.dbei = dbei_s; streamData.isAppend = fAppend; - EDITSTREAM stream = { 0 }; - stream.pfnCallback = LogStreamInEvents; - stream.dwCookie = (DWORD_PTR)&streamData; - LONG startAt; if (fAppend) { GETTEXTLENGTHEX gtxl = { 0 }; @@ -1262,7 +1179,7 @@ void CLogWindow::LogEvents(MEVENT hDbEventFirst, int count, bool fAppend, DBEVEN // begin to draw m_rtf.SetDraw(false); - m_rtf.SendMsg(EM_STREAMIN, fAppend ? SFF_SELECTION | SF_RTF : SFF_SELECTION | SF_RTF, (LPARAM)&stream); + StreamRtfEvents(&streamData, true); m_pDlg.m_hDbEventLast = streamData.hDbEventLast; @@ -1287,8 +1204,7 @@ void CLogWindow::LogEvents(MEVENT hDbEventFirst, int count, bool fAppend, DBEVEN if (streamData.dbei != nullptr) isSent = (streamData.dbei->flags & DBEF_SENT) != 0; else { - DBEVENTINFO dbei = {}; - db_event_get(hDbEventFirst, &dbei); + DB::EventInfo dbei(hDbEventFirst, false); isSent = (dbei.flags & DBEF_SENT) != 0; } @@ -1306,7 +1222,6 @@ void CLogWindow::LogEvents(MEVENT hDbEventFirst, int count, bool fAppend, DBEVEN m_rtf.SetDraw(true); InvalidateRect(m_rtf.GetHwnd(), nullptr, FALSE); EnableWindow(GetDlgItem(m_pDlg.m_hwnd, IDC_QUOTE), m_pDlg.m_hDbEventLast != 0); - mir_free(streamData.buffer); } ///////////////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/TabSRMM/src/msgoptions.cpp b/plugins/TabSRMM/src/msgoptions.cpp index db48cbabdf..d94ecf0eb8 100644 --- a/plugins/TabSRMM/src/msgoptions.cpp +++ b/plugins/TabSRMM/src/msgoptions.cpp @@ -622,15 +622,15 @@ public: T2Utf szText((iIndex == 6) ? TranslateT("is now offline (was online)") : TranslateT("The quick brown fox jumps over the lazy dog.")); - DBEVENTINFO dbei = {}; + DB::EventInfo dbei; dbei.szModule = m_szProto; dbei.timestamp = time(0); dbei.eventType = (iIndex == 6) ? EVENTTYPE_STATUSCHANGE : EVENTTYPE_MESSAGE; dbei.eventType = (iIndex == 7) ? EVENTTYPE_ERRMSG : dbei.eventType; if (dbei.eventType == EVENTTYPE_ERRMSG) dbei.szModule = (char *)TranslateT("Sample error message"); - dbei.pBlob = (uint8_t *)szText.get(); - dbei.cbBlob = (int)mir_strlen((char *)dbei.pBlob) + 1; + dbei.pBlob = (uint8_t *)szText.detach(); + dbei.cbBlob = (int)mir_strlen((char *)dbei.pBlob); dbei.flags = (iIndex == 1 || iIndex == 3 || iIndex == 5) ? DBEF_SENT : 0; dbei.flags |= (m_bRtl ? DBEF_RTL : 0); m_lastEventTime = (iIndex == 4 || iIndex == 5) ? time(0) - 1 : 0; @@ -639,10 +639,10 @@ public: m_dwFlags = (m_bRtl ? m_dwFlags | MWF_LOG_RTL : m_dwFlags & ~MWF_LOG_RTL); m_dwFlags = (iIndex == 0 || iIndex == 1) ? m_dwFlags & ~MWF_LOG_GROUPMODE : m_dwFlags | MWF_LOG_GROUPMODE; mir_snwprintf(m_wszMyNickname, TranslateT("My Nickname")); - LOG()->LogEvents(0, 1, false, &dbei); + LOG()->LogEvents(0, 0, false, &dbei); if (m_bFirstUse) { if (m_bRtl) - LOG()->LogEvents(0, 1, false, &dbei); + LOG()->LogEvents(0, 0, false, &dbei); m_bFirstUse = false; } if (m_bChanged) diff --git a/plugins/TabSRMM/src/msgs.h b/plugins/TabSRMM/src/msgs.h index ba0af19cfd..e92ab942e1 100644 --- a/plugins/TabSRMM/src/msgs.h +++ b/plugins/TabSRMM/src/msgs.h @@ -631,7 +631,7 @@ public: return ((CLogWindow *)m_pLog); } - void LogEvent(DBEVENTINFO &dbei); + void LogEvent(DB::EventInfo &dbei); void DM_OptionsApplied(bool bRemakeLog = true); void DM_RecalcPictureSize(void); @@ -687,7 +687,8 @@ public: CSuper(pDlg) {} - char *CreateRTFFromDbEvent(struct LogStreamData *streamData); + void CreateRtfHeader(RtfLogStreamData *streamData) override; + bool CreateRtfEvent(RtfLogStreamData *streamData, DB::EventInfo &dbei) override; void AppendUnicodeString(CMStringA &str, const wchar_t *pwszBuf) override; void Attach() override; @@ -706,7 +707,7 @@ public: return m_rtf.GetRichTextRtf(bText, bSelection); } - void LogEvents(MEVENT hDbEventFirst, int count, bool bAppend, DBEVENTINFO *dbei); + void LogEvents(MEVENT hDbEventFirst, int count, bool bAppend, DB::EventInfo *dbei); void ReplaceIcons(LONG startAt, int fAppend, BOOL isSent); void ScrollToBottom(bool, bool); diff --git a/plugins/TabSRMM/src/sendqueue.cpp b/plugins/TabSRMM/src/sendqueue.cpp index 9b4e11b583..4f6c35a3cd 100644 --- a/plugins/TabSRMM/src/sendqueue.cpp +++ b/plugins/TabSRMM/src/sendqueue.cpp @@ -340,7 +340,7 @@ void SendQueue::logError(CMsgDialog *dat, int iSendJobIndex, const wchar_t *szEr return; size_t iMsgLen; - DBEVENTINFO dbei = {}; + DB::EventInfo dbei; dbei.eventType = EVENTTYPE_ERRMSG; if (iSendJobIndex >= 0) { dbei.pBlob = (uint8_t *)m_jobs[iSendJobIndex].szSendBuffer; @@ -356,6 +356,8 @@ void SendQueue::logError(CMsgDialog *dat, int iSendJobIndex, const wchar_t *szEr dbei.timestamp = time(0); dbei.szModule = (char *)szErrMsg; dat->LogEvent(dbei); + + dbei.pBlob = nullptr; } ///////////////////////////////////////////////////////////////////////////////////////// @@ -539,14 +541,13 @@ int SendQueue::doSendLater(int iJobIndex, CMsgDialog *dat, MCONTACT hContact, bo else szNote = TranslateT("The send later feature is not available on this protocol."); - T2Utf utfText(szNote); - DBEVENTINFO dbei = {}; + DB::EventInfo dbei; dbei.eventType = EVENTTYPE_MESSAGE; dbei.flags = DBEF_SENT | DBEF_UTF; dbei.szModule = Proto_GetBaseAccountName(dat->m_hContact); dbei.timestamp = time(0); - dbei.cbBlob = (int)mir_strlen(utfText) + 1; - dbei.pBlob = (uint8_t*)(char*)utfText; + dbei.pBlob = (uint8_t*)mir_utf8encodeW(szNote); + dbei.cbBlob = (int)mir_strlen((char*)dbei.pBlob); dat->LogEvent(dbei); if (dat->m_hDbEventFirst == 0) diff --git a/src/core/stdmsg/src/msglog.cpp b/src/core/stdmsg/src/msglog.cpp index 6613e14726..92fac27943 100644 --- a/src/core/stdmsg/src/msglog.cpp +++ b/src/core/stdmsg/src/msglog.cpp @@ -29,20 +29,8 @@ extern IconItem iconList[]; static char *pLogIconBmpBits[3]; -#define STREAMSTAGE_HEADER 0 -#define STREAMSTAGE_EVENTS 1 -#define STREAMSTAGE_TAIL 2 -#define STREAMSTAGE_STOP 3 - -struct LogStreamData +struct RtfLogStreamData : public RtfLogStreamBase { - int stage; - MEVENT hDbEvent, hDbEventLast; - MCONTACT hContact; - CMStringA buf; - int eventsToInsert; - bool isEmpty; - class CLogWindow *pLog; }; static int logPixelSY; @@ -146,39 +134,6 @@ static void AppendToBufferWithRTF(CMStringA &buf, const wchar_t *line) buf.AppendChar('}'); } -#define FONT_FORMAT "{\\f%u\\fnil\\fcharset%u %S;}" - -static void CreateRTFHeader(CMStringA &buffer) -{ - HDC hdc = GetDC(nullptr); - logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); - ReleaseDC(nullptr, hdc); - - buffer.Append("{\\rtf1\\ansi\\deff0{\\fonttbl"); - - LOGFONT lf; - for (int i = 0; LoadMsgDlgFont(i, &lf, nullptr); i++) - buffer.AppendFormat(FONT_FORMAT, i, lf.lfCharSet, lf.lfFaceName); - - buffer.Append("}{\\colortbl "); - COLORREF colour; - for (int i = 0; LoadMsgDlgFont(i, nullptr, &colour); i++) - buffer.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - - if (GetSysColorBrush(COLOR_HOTLIGHT) == nullptr) - colour = RGB(0, 0, 255); - else - colour = GetSysColor(COLOR_HOTLIGHT); - buffer.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - buffer.Append("}"); -} - -// mir_free() the return value -static void CreateRTFTail(CMStringA &buffer) -{ - buffer = "}"; -} - //return value is static static void SetToStyle(int style, CMStringA &dest) { @@ -276,23 +231,40 @@ public: m_rtf.SendMsg(EM_AUTOURLDETECT, TRUE, 0); } - bool CreateRTFFromDbEvent(LogStreamData *dat) + #define FONT_FORMAT "{\\f%u\\fnil\\fcharset%u %S;}" + + void CreateRtfHeader(RtfLogStreamData *dat) override { - DB::EventInfo dbei(dat->hDbEvent); - if (!dbei) - return false; + HDC hdc = GetDC(nullptr); + logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); + ReleaseDC(nullptr, hdc); + + auto &buffer = dat->buf; + buffer.Append("{\\rtf1\\ansi\\deff0{\\fonttbl"); + + LOGFONT lf; + for (int i = 0; LoadMsgDlgFont(i, &lf, nullptr); i++) + buffer.AppendFormat(FONT_FORMAT, i, lf.lfCharSet, lf.lfFaceName); + + buffer.Append("}{\\colortbl "); + COLORREF colour; + for (int i = 0; LoadMsgDlgFont(i, nullptr, &colour); i++) + buffer.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + + if (GetSysColorBrush(COLOR_HOTLIGHT) == nullptr) + colour = RGB(0, 0, 255); + else + colour = GetSysColor(COLOR_HOTLIGHT); + buffer.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + buffer.Append("}"); + } + + bool CreateRtfEvent(RtfLogStreamData *dat, DB::EventInfo &dbei) override + { if (!DbEventIsShown(dbei)) return false; - if (!(dbei.flags & DBEF_SENT) && (dbei.eventType == EVENTTYPE_MESSAGE || dbei.isSrmm())) { - db_event_markRead(dat->hContact, dat->hDbEvent); - g_clistApi.pfnRemoveEvent(dat->hContact, dat->hDbEvent); - } - else if (dbei.eventType == EVENTTYPE_JABBER_CHATSTATES || dbei.eventType == EVENTTYPE_JABBER_PRESENCE) { - db_event_markRead(dat->hContact, dat->hDbEvent); - } - CMStringA &buf = dat->buf; bool bIsRtl = m_pDlg.m_bIsAutoRTL; if (!bIsRtl && !dat->isEmpty) @@ -426,17 +398,13 @@ public: m_rtf.SetDraw(false); m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&oldSel); - LogStreamData streamData = {}; + RtfLogStreamData streamData = {}; streamData.hContact = m_pDlg.m_hContact; streamData.hDbEvent = hDbEventFirst; streamData.pLog = this; streamData.eventsToInsert = count; streamData.isEmpty = !bAppend || GetWindowTextLength(m_rtf.GetHwnd()) == 0; - EDITSTREAM stream = {}; - stream.pfnCallback = LogStreamInEvents; - stream.dwCookie = (DWORD_PTR)&streamData; - if (!streamData.isEmpty) { bottomScroll = GetFocus() != m_rtf.GetHwnd() && AtBottom(); if (!bottomScroll) @@ -462,7 +430,6 @@ public: mir_strcpy(szSep2, bAppend ? "\\par\\sl0" : "\\sl1000"); mir_strcpy(szSep2_RTL, bAppend ? "\\rtlpar\\rtlmark\\par\\sl1000" : "\\sl1000"); - m_rtf.SendMsg(EM_STREAMIN, bAppend ? SFF_SELECTION | SF_RTF : SF_RTF, (LPARAM)&stream); if (bottomScroll) { sel.cpMin = sel.cpMax = -1; m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel); @@ -706,57 +673,6 @@ public: } }; -static DWORD CALLBACK LogStreamInEvents(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) -{ - LogStreamData *dat = (LogStreamData *)dwCookie; - - if (dat->buf.IsEmpty()) { - switch (dat->stage) { - case STREAMSTAGE_HEADER: - CreateRTFHeader(dat->buf); - dat->stage = STREAMSTAGE_EVENTS; - break; - - case STREAMSTAGE_EVENTS: - if (dat->eventsToInsert) { - bool bOk; - do { - bOk = dat->pLog->CreateRTFFromDbEvent(dat); - if (bOk) - dat->hDbEventLast = dat->hDbEvent; - dat->hDbEvent = db_event_next(dat->hContact, dat->hDbEvent); - if (--dat->eventsToInsert == 0) - break; - } while (!bOk && dat->hDbEvent); - - if (bOk) { - dat->isEmpty = false; - break; - } - } - dat->stage = STREAMSTAGE_TAIL; - __fallthrough; - - case STREAMSTAGE_TAIL: - CreateRTFTail(dat->buf); - dat->stage = STREAMSTAGE_STOP; - break; - case STREAMSTAGE_STOP: - *pcb = 0; - return 0; - } - } - - *pcb = min(cb, dat->buf.GetLength()); - memcpy(pbBuff, dat->buf.GetBuffer(), *pcb); - if (dat->buf.GetLength() == *pcb) - dat->buf.Empty(); - else - dat->buf.Delete(0, *pcb); - - return 0; -} - ///////////////////////////////////////////////////////////////////////////////////////// // Module entry point diff --git a/src/mir_app/src/mir_app.def b/src/mir_app/src/mir_app.def index 6086dfd503..f2f4b08172 100644 --- a/src/mir_app/src/mir_app.def +++ b/src/mir_app/src/mir_app.def @@ -853,3 +853,5 @@ Chat_IsMuted @941 NONAME ?GetDialog@CSrmmLogWindow@@QBEAAVCMsgDialog@@XZ @969 NONAME ?isHistory@EventInfo@DB@@QBE_NXZ @970 NONAME ?isSrmm@EventInfo@DB@@QBE_NXZ @971 NONAME +?CreateRtfTail@CRtfLogWindow@@UAEXPAURtfLogStreamData@@@Z @972 NONAME +?StreamRtfEvents@CRtfLogWindow@@QAEXPAURtfLogStreamData@@_N@Z @973 NONAME diff --git a/src/mir_app/src/mir_app64.def b/src/mir_app/src/mir_app64.def index 678dd85842..5151b526c4 100644 --- a/src/mir_app/src/mir_app64.def +++ b/src/mir_app/src/mir_app64.def @@ -853,3 +853,5 @@ Chat_IsMuted @941 NONAME ?GetDialog@CSrmmLogWindow@@QEBAAEAVCMsgDialog@@XZ @969 NONAME ?isHistory@EventInfo@DB@@QEBA_NXZ @970 NONAME ?isSrmm@EventInfo@DB@@QEBA_NXZ @971 NONAME +?CreateRtfTail@CRtfLogWindow@@UEAAXPEAURtfLogStreamData@@@Z @972 NONAME +?StreamRtfEvents@CRtfLogWindow@@QEAAXPEAURtfLogStreamData@@_N@Z @973 NONAME diff --git a/src/mir_app/src/srmm_log_rtf.cpp b/src/mir_app/src/srmm_log_rtf.cpp index eae329a4f0..88a8466f93 100644 --- a/src/mir_app/src/srmm_log_rtf.cpp +++ b/src/mir_app/src/srmm_log_rtf.cpp @@ -27,6 +27,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "stdafx.h" #include "chat.h" +#define STREAMSTAGE_HEADER 0 +#define STREAMSTAGE_EVENTS 1 +#define STREAMSTAGE_TAIL 2 +#define STREAMSTAGE_STOP 3 + #define EVENTTYPE_STATUSCHANGE 25368 #define EVENTTYPE_ERRMSG 25366 @@ -61,6 +66,13 @@ void CRtfLogWindow::Attach() ///////////////////////////////////////////////////////////////////////////////////////// +void CRtfLogWindow::CreateRtfTail(RtfLogStreamData *dat) +{ + dat->buf = "}"; +} + +///////////////////////////////////////////////////////////////////////////////////////// + void CRtfLogWindow::Detach() { mir_unsubclassWindow(m_rtf.GetHwnd(), stubLogProc); @@ -263,6 +275,98 @@ void CRtfLogWindow::ScrollToBottom() ///////////////////////////////////////////////////////////////////////////////////////// +#define EVENTTYPE_JABBER_CHATSTATES 2000 +#define EVENTTYPE_JABBER_PRESENCE 2001 + +static bool CreateRtfFromDbEvent(RtfLogStreamData *dat) +{ + DB::EventInfo dbei(dat->hDbEvent); + if (!dbei) + return false; + + if (!dat->pLog->CreateRtfEvent(dat, dbei)) + return false; + + if (!(dbei.flags & DBEF_SENT) && (dbei.eventType == EVENTTYPE_MESSAGE || dbei.isSrmm())) { + db_event_markRead(dat->hContact, dat->hDbEvent); + g_clistApi.pfnRemoveEvent(dat->hContact, dat->hDbEvent); + } + else if (dbei.eventType == EVENTTYPE_JABBER_CHATSTATES || dbei.eventType == EVENTTYPE_JABBER_PRESENCE) { + db_event_markRead(dat->hContact, dat->hDbEvent); + } + + return true; +} + +static DWORD CALLBACK LogStreamInEvents(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) +{ + auto *dat = (RtfLogStreamData *)dwCookie; + + if (dat->buf.IsEmpty()) { + switch (dat->stage) { + case STREAMSTAGE_HEADER: + dat->pLog->CreateRtfHeader(dat); + dat->stage = STREAMSTAGE_EVENTS; + break; + + case STREAMSTAGE_EVENTS: + if (dat->dbei) { + if (dat->pLog->CreateRtfEvent(dat, *dat->dbei)) { + dat->eventsToInsert++; + break; + } + } + else if (dat->eventsToInsert) { + bool bOk; + do { + bOk = CreateRtfFromDbEvent(dat); + if (bOk) + dat->hDbEventLast = dat->hDbEvent; + + dat->hDbEvent = db_event_next(dat->hContact, dat->hDbEvent); + if (--dat->eventsToInsert == 0) + break; + } while (!bOk && dat->hDbEvent); + + if (bOk) { + dat->isEmpty = false; + break; + } + } + dat->stage = STREAMSTAGE_TAIL; + __fallthrough; + + case STREAMSTAGE_TAIL: + dat->pLog->CreateRtfTail(dat); + dat->stage = STREAMSTAGE_STOP; + break; + + case STREAMSTAGE_STOP: + *pcb = 0; + return 0; + } + } + + *pcb = min(cb, dat->buf.GetLength()); + memcpy(pbBuff, dat->buf.GetBuffer(), *pcb); + if (dat->buf.GetLength() == *pcb) + dat->buf.Empty(); + else + dat->buf.Delete(0, *pcb); + + return 0; +} + +void CRtfLogWindow::StreamRtfEvents(RtfLogStreamData *dat, bool bAppend) +{ + EDITSTREAM stream = {}; + stream.pfnCallback = LogStreamInEvents; + stream.dwCookie = (DWORD_PTR)dat; + m_rtf.SendMsg(EM_STREAMIN, bAppend ? SFF_SELECTION | SF_RTF : SF_RTF, (LPARAM)&stream); +} + +///////////////////////////////////////////////////////////////////////////////////////// + static wchar_t szTrimString[] = L":;,.!?\'\"><()[]- \r\n"; INT_PTR CRtfLogWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam) -- cgit v1.2.3