From 0f09bc6a33604e79996caaf6ff021226e96e53fd Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sat, 15 Apr 2023 20:37:26 +0300 Subject: =?UTF-8?q?fixes=20#3458=20(tabSRMM:=20=D0=B4=D0=B2=D0=BE=D1=8F?= =?UTF-8?q?=D1=82=D1=81=D1=8F=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/m_chat.h | 1 + include/m_chat_int.h | 27 ++++----- include/m_srmm_int.h | 2 +- plugins/IEView/src/ieview_logger.cpp | 18 +++--- plugins/NewStory/src/history_log.cpp | 8 +-- plugins/Scriver/src/msglog.cpp | 12 ++-- plugins/TabSRMM/src/chat_log.cpp | 86 ++++++++++++++--------------- plugins/TabSRMM/src/msgdlgother.cpp | 3 +- plugins/TabSRMM/src/msglog.cpp | 14 ++--- plugins/TabSRMM/src/msgs.h | 2 +- src/core/stdmsg/src/msglog.cpp | 12 ++-- src/mir_app/src/chat.h | 1 + src/mir_app/src/chat_log.cpp | 62 +++++++++++---------- src/mir_app/src/chat_manager.cpp | 103 ++++++++++------------------------- src/mir_app/src/chat_svc.cpp | 22 +------- src/mir_app/src/chat_tools.cpp | 22 ++++++++ src/mir_app/src/srmm_base.cpp | 32 ++++++----- src/mir_app/src/srmm_log_hpp.cpp | 20 +++---- src/mir_app/src/srmm_log_rtf.cpp | 27 +++++++-- 19 files changed, 225 insertions(+), 249 deletions(-) diff --git a/include/m_chat.h b/include/m_chat.h index 92e4e6329b..bd5967dc9f 100644 --- a/include/m_chat.h +++ b/include/m_chat.h @@ -381,6 +381,7 @@ struct GCEVENT INT_PTR dwItemData; // User specified data. uint32_t time; // Timestamp of the event + MEVENT hEvent; // Database event }; MIR_APP_DLL(int) Chat_Event(GCEVENT*); diff --git a/include/m_chat_int.h b/include/m_chat_int.h index cf0e1b5778..807845380b 100644 --- a/include/m_chat_int.h +++ b/include/m_chat_int.h @@ -111,17 +111,17 @@ struct FONTINFO struct LOGINFO { - wchar_t *ptszText; - wchar_t *ptszNick; - wchar_t *ptszUID; - wchar_t *ptszStatus; - wchar_t *ptszUserInfo; + ptrW ptszText; + ptrW ptszNick; + ptrW ptszUID; + ptrW ptszStatus; + ptrW ptszUserInfo; bool bIsMe; bool bIsHighlighted; bool bSimple; time_t time; + MEVENT hEvent; int iType; - LOGINFO *next, *prev; }; struct STATUSINFO @@ -153,9 +153,9 @@ struct MIR_APP_EXPORT SESSION_INFO : public MZeroedObject, public MNonCopyable wchar_t* ptszTopic; int iType; - int iEventCount; - int iStatusCount; + int iStatusCount, iLastEvent; int iTrayFlags, iPopupFlags; + int currentHovered; uint16_t wStatus; uint16_t wState; @@ -163,10 +163,7 @@ struct MIR_APP_EXPORT SESSION_INFO : public MZeroedObject, public MNonCopyable void* pItemData; time_t LastTime; - int currentHovered; - CMsgDialog *pDlg; - LOGINFO *pLog, *pLogEnd; USERINFO *pMe; STATUSINFO *pStatuses; MODULEINFO *pMI; @@ -174,6 +171,7 @@ struct MIR_APP_EXPORT SESSION_INFO : public MZeroedObject, public MNonCopyable LIST arKeys; OBJLIST arUsers; + OBJLIST arEvents; wchar_t pszLogFileName[MAX_PATH]; @@ -196,10 +194,9 @@ struct GCLogStreamDataBase { char* buffer; int bufferOffset, bufferLen; + int iStartEvent; + bool bStripFormat, bRedraw; HWND hwnd; - LOGINFO* lin; - BOOL bStripFormat; - BOOL bRedraw; SESSION_INFO *si; }; @@ -301,8 +298,6 @@ struct CHAT_MANAGER wchar_t* (*UM_FindUserAutoComplete)(SESSION_INFO *si, const wchar_t* pszOriginal, const wchar_t* pszCurrent); BOOL (*UM_RemoveUser)(SESSION_INFO *si, const wchar_t *pszUID); - BOOL (*LM_RemoveAll)(LOGINFO **ppLogListStart, LOGINFO **ppLogListEnd); - BOOL (*SetOffline)(MCONTACT hContact, BOOL bHide); BOOL (*SetAllOffline)(BOOL bHide, const char *pszModule); diff --git a/include/m_srmm_int.h b/include/m_srmm_int.h index 817558e664..9163536e5c 100644 --- a/include/m_srmm_int.h +++ b/include/m_srmm_int.h @@ -128,7 +128,7 @@ public: virtual HWND GetHwnd() = 0; virtual wchar_t* GetSelection() = 0; virtual void LogEvents(MEVENT hDbEventFirst, int count, bool bAppend) = 0; - virtual void LogEvents(struct LOGINFO *, bool) = 0; + virtual void LogEvents(struct SESSION_INFO *si, int iStart, bool bAppend) = 0; virtual void Resize() = 0; virtual void ScrollToBottom() = 0; virtual void UpdateOptions() {}; diff --git a/plugins/IEView/src/ieview_logger.cpp b/plugins/IEView/src/ieview_logger.cpp index 9da4150847..6f613882c2 100644 --- a/plugins/IEView/src/ieview_logger.cpp +++ b/plugins/IEView/src/ieview_logger.cpp @@ -103,7 +103,7 @@ public: HandleIEEvent(0, LPARAM(&event)); } - void LogEvents(LOGINFO *pLog, bool bRedraw) override + void LogEvents(SESSION_INFO *si, int iStart, bool bRedraw) override { IEVIEWEVENTDATA ied = {}; ied.dwFlags = IEEDF_UNICODE_NICK; @@ -116,13 +116,15 @@ public: event.eventData = &ied; event.count = 1; - while (pLog) { - ied.szNick.w = pLog->ptszNick; - ied.szText.w = pLog->ptszText; - ied.time = pLog->time; - ied.bIsMe = pLog->bIsMe; + for (int i = iStart; i < si->arEvents.getCount(); i++) { + auto &lin = si->arEvents[i]; - switch (pLog->iType) { + ied.szNick.w = lin.ptszNick; + ied.szText.w = lin.ptszText; + ied.time = lin.time; + ied.bIsMe = lin.bIsMe; + + switch (lin.iType) { case GC_EVENT_MESSAGE: ied.iType = IEED_GC_EVENT_MESSAGE; ied.dwData = IEEDD_GC_SHOW_NICK; @@ -165,8 +167,6 @@ public: ied.dwData |= IEEDD_GC_SHOW_TIME | IEEDD_GC_SHOW_ICON; ied.dwFlags = IEEDF_UNICODE_TEXT | IEEDF_UNICODE_NICK; HandleIEEvent(0, LPARAM(&event)); - - pLog = pLog->prev; } if (bRedraw) diff --git a/plugins/NewStory/src/history_log.cpp b/plugins/NewStory/src/history_log.cpp index 05b53ca28a..87b0b7fc9d 100644 --- a/plugins/NewStory/src/history_log.cpp +++ b/plugins/NewStory/src/history_log.cpp @@ -60,12 +60,10 @@ public: SendMessage(m_hwnd, NSM_ADDEVENTS, (LPARAM)&tmp, 0); } - void LogEvents(LOGINFO *pLog, bool) override + void LogEvents(SESSION_INFO *si, int iStart, bool) override { - while (pLog) { - SendMessage(m_hwnd, NSM_ADDCHATEVENT, (WPARAM)m_pDlg.getChat(), (LPARAM)pLog); - pLog = pLog->prev; - } + for (int i=iStart; i < si->arEvents.getCount(); i++) + SendMessage(m_hwnd, NSM_ADDCHATEVENT, (WPARAM)m_pDlg.getChat(), (LPARAM)&si->arEvents[i]); } void Resize() override diff --git a/plugins/Scriver/src/msglog.cpp b/plugins/Scriver/src/msglog.cpp index 9371504a9d..8a16ebd013 100644 --- a/plugins/Scriver/src/msglog.cpp +++ b/plugins/Scriver/src/msglog.cpp @@ -643,20 +643,20 @@ public: //////////////////////////////////////////////////////////////////////////////////////// - void LogEvents(struct LOGINFO *lin, bool bRedraw) override + void LogEvents(SESSION_INFO *si, int iStart, bool bRedraw) override { - auto *si = m_pDlg.m_si; - if (m_rtf.GetHwnd() == nullptr || lin == nullptr || si == nullptr) + if (m_rtf.GetHwnd() == nullptr || si == nullptr || si == nullptr) return; - if (!bRedraw && (si->iType == GCW_CHATROOM || si->iType == GCW_PRIVMESS) && !(m_pDlg.m_iLogFilterFlags & lin->iType)) + auto &lin = si->arEvents[iStart]; + if (!bRedraw && (si->iType == GCW_CHATROOM || si->iType == GCW_PRIVMESS) && !(m_pDlg.m_iLogFilterFlags & lin.iType)) return; LOGSTREAMDATA streamData; memset(&streamData, 0, sizeof(streamData)); streamData.hwnd = m_rtf.GetHwnd(); streamData.si = si; - streamData.lin = lin; + streamData.iStartEvent = iStart; streamData.bStripFormat = FALSE; streamData.isFirst = bRedraw ? 1 : m_rtf.GetRichTextLength() == 0; @@ -702,7 +702,7 @@ public: m_rtf.SendMsg(EM_STREAMIN, wp, (LPARAM)&stream); // do smileys - if (g_dat.smileyAddInstalled && (bRedraw || (lin->ptszText && lin->iType != GC_EVENT_JOIN && lin->iType != GC_EVENT_NICK && lin->iType != GC_EVENT_ADDSTATUS && lin->iType != GC_EVENT_REMOVESTATUS))) { + if (g_dat.smileyAddInstalled && (bRedraw || (lin.ptszText && lin.iType != GC_EVENT_JOIN && lin.iType != GC_EVENT_NICK && lin.iType != GC_EVENT_ADDSTATUS && lin.iType != GC_EVENT_REMOVESTATUS))) { newsel.cpMax = -1; newsel.cpMin = sel.cpMin; if (newsel.cpMin < 0) diff --git a/plugins/TabSRMM/src/chat_log.cpp b/plugins/TabSRMM/src/chat_log.cpp index 950fe19d77..624384a362 100644 --- a/plugins/TabSRMM/src/chat_log.cpp +++ b/plugins/TabSRMM/src/chat_log.cpp @@ -34,11 +34,11 @@ * the srmm module and then modified to fit the chat module. */ -static int EventToIndex(LOGINFO *lin) +static int EventToIndex(const LOGINFO &lin) { - switch (lin->iType) { + switch (lin.iType) { case GC_EVENT_MESSAGE: - if (lin->bIsMe) + if (lin.bIsMe) return 10; else return 9; @@ -69,11 +69,11 @@ static int EventToIndex(LOGINFO *lin) return 0; } -static uint8_t EventToSymbol(LOGINFO *lin) +static uint8_t EventToSymbol(const LOGINFO &lin) { - switch (lin->iType) { + switch (lin.iType) { case GC_EVENT_MESSAGE: - return (lin->bIsMe) ? 0x37 : 0x38; + return (lin.bIsMe) ? 0x37 : 0x38; case GC_EVENT_JOIN: return 0x34; case GC_EVENT_PART: @@ -98,11 +98,11 @@ static uint8_t EventToSymbol(LOGINFO *lin) return 0x73; } -static int EventToIcon(LOGINFO *lin) +static int EventToIcon(const LOGINFO &lin) { - switch (lin->iType) { + switch (lin.iType) { case GC_EVENT_MESSAGE: - if (lin->bIsMe) + if (lin.bIsMe) return ICON_MESSAGEOUT; else return ICON_MESSAGE; @@ -133,7 +133,7 @@ static int EventToIcon(LOGINFO *lin) return 0; } -static void Log_AppendRTF(LOGSTREAMDATA *streamData, bool simpleMode, CMStringA &str, const wchar_t *line) +static void Log_AppendRTF(LOGSTREAMDATA *streamData, const LOGINFO &lin, bool simpleMode, CMStringA &str, const wchar_t *line) { int textCharsCount = 0; @@ -175,7 +175,7 @@ static void Log_AppendRTF(LOGSTREAMDATA *streamData, bool simpleMode, CMStringA case 'C': case 'F': if (!g_Settings.bStripFormat && !streamData->bStripFormat) { - int j = streamData->lin->bIsHighlighted ? 16 : EventToIndex(streamData->lin); + int j = lin.bIsHighlighted ? 16 : EventToIndex(lin); if (*line == 'C') res.AppendFormat("\\cf%u ", j + 1); else @@ -198,7 +198,7 @@ static void Log_AppendRTF(LOGSTREAMDATA *streamData, bool simpleMode, CMStringA case 'r': if (!streamData->bStripFormat) { - int index = EventToIndex(streamData->lin); + int index = EventToIndex(lin); res.AppendFormat("%s ", g_chatApi.Log_SetStyle(index)); } break; @@ -220,19 +220,19 @@ static void Log_AppendRTF(LOGSTREAMDATA *streamData, bool simpleMode, CMStringA str += res; } -static void AddEventToBuffer(CMStringA &str, LOGSTREAMDATA *streamData) +static void AddEventToBuffer(CMStringA &str, LOGSTREAMDATA *streamData, const LOGINFO &lin) { - if (streamData == nullptr || streamData->lin == nullptr) + if (streamData == nullptr) return; CMStringW wszCaption; - bool bTextUsed = Chat_GetDefaultEventDescr(streamData->si, streamData->lin, wszCaption); + bool bTextUsed = Chat_GetDefaultEventDescr(streamData->si, &lin, wszCaption); if (!wszCaption.IsEmpty()) - Log_AppendRTF(streamData, !bTextUsed, str, wszCaption); - if (!bTextUsed && streamData->lin->ptszText) { + Log_AppendRTF(streamData, lin, !bTextUsed, str, wszCaption); + if (!bTextUsed && lin.ptszText) { if (!wszCaption.IsEmpty()) - Log_AppendRTF(streamData, false, str, L" "); - Log_AppendRTF(streamData, false, str, streamData->lin->ptszText); + Log_AppendRTF(streamData, lin, false, str, L" "); + Log_AppendRTF(streamData, lin, false, str, lin.ptszText); } } @@ -304,7 +304,6 @@ char* Log_CreateRtfHeader(void) char* Log_CreateRTF(LOGSTREAMDATA *streamData) { - LOGINFO *lin = streamData->lin; SESSION_INFO *si = streamData->si; MODULEINFO *mi = si->pMI; @@ -321,10 +320,13 @@ char* Log_CreateRTF(LOGSTREAMDATA *streamData) str.Append(header); // ### RTF BODY (one iteration per event that should be streamed in) - while (lin) { + int iEventCount = si->arEvents.getCount(); + for (int i = streamData->iStartEvent; i < iEventCount; i++) { + auto &lin = si->arEvents[i]; + // filter - if ((si->iType != GCW_CHATROOM && si->iType != GCW_PRIVMESS) || (si->pDlg->m_iLogFilterFlags & lin->iType) != 0) { - if (lin->next != nullptr) + if ((si->iType != GCW_CHATROOM && si->iType != GCW_PRIVMESS) || (si->pDlg->m_iLogFilterFlags & lin.iType) != 0) { + if (i != 0) str.Append("\\par "); if (streamData->dat->m_bDividerWanted) { @@ -332,19 +334,19 @@ char* Log_CreateRTF(LOGSTREAMDATA *streamData) if (szStyle_div[0] == 0) mir_snprintf(szStyle_div, "\\f%u\\cf%u\\ul0\\b%d\\i%d\\fs%u", 17, 18, 0, 0, 5); - if (lin->prev || !streamData->bRedraw) + if (i != iEventCount - 1 || !streamData->bRedraw) str.AppendFormat("\\qc\\sl-1\\highlight%d %s ---------------------------------------------------------------------------------------\\par ", 18, szStyle_div); streamData->dat->m_bDividerWanted = false; } // create new line, and set font and color str.AppendFormat("\\ql\\sl0%s ", g_chatApi.Log_SetStyle(0)); - str.AppendFormat("\\v~-+%p+-~\\v0 ", lin); + str.AppendFormat("\\v~-+%p+-~\\v0 ", &lin); // Insert icon if (g_Settings.bLogSymbols) // use symbols str.AppendFormat("%s %c", g_chatApi.Log_SetStyle(17), EventToSymbol(lin)); else if (g_Settings.dwIconFlags) { - int iIndex = lin->bIsHighlighted ? ICON_HIGHLIGHT : EventToIcon(lin); + int iIndex = lin.bIsHighlighted ? ICON_HIGHLIGHT : EventToIcon(lin); str.Append("\\f0\\fs14"); str.Append(g_chatApi.pLogIconBmpBits[iIndex]); } @@ -354,14 +356,14 @@ char* Log_CreateRTF(LOGSTREAMDATA *streamData) static char szStyle[256]; LOGFONT &F = g_chatApi.aFonts[0].lf; int iii; - if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) { - iii = lin->bIsHighlighted ? 16 : (lin->bIsMe ? 2 : 1); + if (lin.ptszNick && lin.iType == GC_EVENT_MESSAGE) { + iii = lin.bIsHighlighted ? 16 : (lin.bIsMe ? 2 : 1); mir_snprintf(szStyle, "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\ul%d\\fs%u", iii + 1, F.lfWeight >= FW_BOLD ? 1 : 0, F.lfItalic, F.lfUnderline, 2 * abs(F.lfHeight) * 74 / g_chatApi.logPixelSY); str.Append(szStyle); } else { - iii = lin->bIsHighlighted ? 16 : EventToIndex(lin); + iii = lin.bIsHighlighted ? 16 : EventToIndex(lin); mir_snprintf(szStyle, "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\ul%d\\fs%u", iii + 1, F.lfWeight >= FW_BOLD ? 1 : 0, F.lfItalic, F.lfUnderline, 2 * abs(F.lfHeight) * 74 / g_chatApi.logPixelSY); str.Append(szStyle); @@ -378,54 +380,52 @@ char* Log_CreateRTF(LOGSTREAMDATA *streamData) if (g_Settings.bShowTime) { wchar_t szTimeStamp[30], szOldTimeStamp[30]; - wcsncpy_s(szTimeStamp, g_chatApi.MakeTimeStamp(g_Settings.pszTimeStamp, lin->time), _TRUNCATE); + wcsncpy_s(szTimeStamp, g_chatApi.MakeTimeStamp(g_Settings.pszTimeStamp, lin.time), _TRUNCATE); wcsncpy_s(szOldTimeStamp, g_chatApi.MakeTimeStamp(g_Settings.pszTimeStamp, si->LastTime), _TRUNCATE); if (!g_Settings.bShowTimeIfChanged || si->LastTime == 0 || mir_wstrcmp(szTimeStamp, szOldTimeStamp)) { - si->LastTime = lin->time; - Log_AppendRTF(streamData, TRUE, str, szTimeStamp); + si->LastTime = lin.time; + Log_AppendRTF(streamData, lin, TRUE, str, szTimeStamp); } str.Append("\\tab "); } // Insert the nick - if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) { + if (lin.ptszNick && lin.iType == GC_EVENT_MESSAGE) { char pszIndicator[3] = "\0\0"; int crNickIndex = 0; if (g_Settings.bLogClassicIndicators || g_Settings.bColorizeNicksInLog) - pszIndicator[0] = GetIndicator(si, lin->ptszNick, &crNickIndex); + pszIndicator[0] = GetIndicator(si, lin.ptszNick, &crNickIndex); - str.Append(g_chatApi.Log_SetStyle(lin->bIsMe ? 2 : 1)); + str.Append(g_chatApi.Log_SetStyle(lin.bIsMe ? 2 : 1)); str.AppendChar(' '); if (g_Settings.bLogClassicIndicators) str.Append(pszIndicator); - CMStringW pszTemp(lin->bIsMe ? g_Settings.pszOutgoingNick : g_Settings.pszIncomingNick); - if (!lin->bIsMe) { + CMStringW pszTemp(lin.bIsMe ? g_Settings.pszOutgoingNick : g_Settings.pszIncomingNick); + if (!lin.bIsMe) { if (g_Settings.bClickableNicks) pszTemp.Replace(L"%n", CLICKNICK_BEGIN L"%n" CLICKNICK_END); if (g_Settings.bColorizeNicksInLog && pszIndicator[0]) str.AppendFormat("\\cf%u ", OPTIONS_FONTCOUNT + Utils::rtf_clrs.getCount() + streamData->crCount + crNickIndex); } - pszTemp.Replace(L"%n", lin->ptszNick); + pszTemp.Replace(L"%n", lin.ptszNick); if (g_Settings.bNewLineAfterNames) pszTemp.AppendChar('\n'); - Log_AppendRTF(streamData, TRUE, str, pszTemp); + Log_AppendRTF(streamData, lin, TRUE, str, pszTemp); str.AppendChar(' '); } // Insert the message - str.Append(g_chatApi.Log_SetStyle(lin->bIsHighlighted ? 16 : EventToIndex(lin))); + str.Append(g_chatApi.Log_SetStyle(lin.bIsHighlighted ? 16 : EventToIndex(lin))); str.AppendChar(' '); - streamData->lin = lin; - AddEventToBuffer(str, streamData); + AddEventToBuffer(str, streamData, lin); } - lin = lin->prev; } // ### RTF END diff --git a/plugins/TabSRMM/src/msgdlgother.cpp b/plugins/TabSRMM/src/msgdlgother.cpp index 68b97ba962..1b3003ee04 100644 --- a/plugins/TabSRMM/src/msgdlgother.cpp +++ b/plugins/TabSRMM/src/msgdlgother.cpp @@ -2498,8 +2498,7 @@ LBL_SkipEnd: void CMsgDialog::tabClearLog() { if (isChat()) { - g_chatApi.LM_RemoveAll(&m_si->pLog, &m_si->pLogEnd); - m_si->iEventCount = 0; + m_si->arEvents.destroy(); m_si->LastTime = 0; PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); } diff --git a/plugins/TabSRMM/src/msglog.cpp b/plugins/TabSRMM/src/msglog.cpp index c48d5d1d4d..709b44a3d0 100644 --- a/plugins/TabSRMM/src/msglog.cpp +++ b/plugins/TabSRMM/src/msglog.cpp @@ -1226,13 +1226,13 @@ void CLogWindow::LogEvents(MEVENT hDbEventFirst, int count, bool fAppend, DB::Ev ///////////////////////////////////////////////////////////////////////////////////////// -void CLogWindow::LogEvents(LOGINFO *lin, bool bRedraw) +void CLogWindow::LogEvents(SESSION_INFO *si, int iStart, bool bRedraw) { - auto *si = m_pDlg.m_si; - if (m_rtf.GetHwnd() == nullptr || lin == nullptr || si == nullptr) + if (m_rtf.GetHwnd() == nullptr || si == nullptr) return; - if (!bRedraw && m_pDlg.AllowTyping() && !(m_pDlg.m_iLogFilterFlags & lin->iType)) + auto &lin = si->arEvents[iStart]; + if (!bRedraw && m_pDlg.AllowTyping() && !(m_pDlg.m_iLogFilterFlags & lin.iType)) return; bool bFlag = false, bDoReplace, bAtBottom = AtBottom(); @@ -1241,7 +1241,7 @@ void CLogWindow::LogEvents(LOGINFO *lin, bool bRedraw) memset(&streamData, 0, sizeof(streamData)); streamData.hwnd = m_rtf.GetHwnd(); streamData.si = si; - streamData.lin = lin; + streamData.iStartEvent = iStart; streamData.bStripFormat = FALSE; streamData.dat = &m_pDlg; @@ -1285,7 +1285,7 @@ void CLogWindow::LogEvents(LOGINFO *lin, bool bRedraw) // for new added events, only replace in message or action events. // no need to replace smileys or math formulas elsewhere - bDoReplace = (bRedraw || (lin->ptszText && (lin->iType == GC_EVENT_MESSAGE || lin->iType == GC_EVENT_ACTION))); + bDoReplace = (bRedraw || (lin.ptszText && (lin.iType == GC_EVENT_MESSAGE || lin.iType == GC_EVENT_ACTION))); // replace marked nicknames with hyperlinks to make the nicks clickable if (g_Settings.bClickableNicks) { @@ -1344,7 +1344,7 @@ void CLogWindow::LogEvents(LOGINFO *lin, bool bRedraw) // this uses hidden marks in the rich text to find the events which should be deleted if (si->bTrimmed) { wchar_t szPattern[50]; - mir_snwprintf(szPattern, L"~-+%p+-~", si->pLogEnd); + mir_snwprintf(szPattern, L"~-+%p+-~", &lin); FINDTEXTEX fi; fi.lpstrText = szPattern; diff --git a/plugins/TabSRMM/src/msgs.h b/plugins/TabSRMM/src/msgs.h index e92ab942e1..79032e37b0 100644 --- a/plugins/TabSRMM/src/msgs.h +++ b/plugins/TabSRMM/src/msgs.h @@ -693,7 +693,7 @@ public: void AppendUnicodeString(CMStringA &str, const wchar_t *pwszBuf) override; void Attach() override; void LogEvents(MEVENT hDbEventFirst, int count, bool bAppend) override; - void LogEvents(struct LOGINFO *, bool) override; + void LogEvents(SESSION_INFO *si, int iStart, bool) override; void ScrollToBottom() override; void UpdateOptions() override; diff --git a/src/core/stdmsg/src/msglog.cpp b/src/core/stdmsg/src/msglog.cpp index 92fac27943..d70f1dedee 100644 --- a/src/core/stdmsg/src/msglog.cpp +++ b/src/core/stdmsg/src/msglog.cpp @@ -471,20 +471,20 @@ public: ///////////////////////////////////////////////////////////////////////////////////////// - void LogEvents(struct LOGINFO *lin, bool bRedraw) override + void LogEvents(SESSION_INFO *si, int iStart, bool bRedraw) override { - auto *si = m_pDlg.m_si; - if (lin == nullptr || si == nullptr) + if (si == nullptr) return; - if (!bRedraw && si->iType == GCW_CHATROOM && (m_pDlg.m_iLogFilterFlags & lin->iType) == 0) + auto &lin = si->arEvents[iStart]; + if (!bRedraw && si->iType == GCW_CHATROOM && (m_pDlg.m_iLogFilterFlags & lin.iType) == 0) return; LOGSTREAMDATA streamData; memset(&streamData, 0, sizeof(streamData)); streamData.hwnd = m_rtf.GetHwnd(); streamData.si = si; - streamData.lin = lin; + streamData.iStartEvent = iStart; streamData.bStripFormat = FALSE; bool bFlag = false; @@ -533,7 +533,7 @@ public: m_rtf.SendMsg(EM_STREAMIN, wp, (LPARAM)&stream); // do smileys - if (g_plugin.bSmileyInstalled && (bRedraw || (lin->ptszText && lin->iType != GC_EVENT_JOIN && lin->iType != GC_EVENT_NICK && lin->iType != GC_EVENT_ADDSTATUS && lin->iType != GC_EVENT_REMOVESTATUS))) { + if (g_plugin.bSmileyInstalled && (bRedraw || (lin.ptszText && lin.iType != GC_EVENT_JOIN && lin.iType != GC_EVENT_NICK && lin.iType != GC_EVENT_ADDSTATUS && lin.iType != GC_EVENT_REMOVESTATUS))) { CHARRANGE newsel; newsel.cpMax = -1; newsel.cpMin = sel.cpMin; diff --git a/src/mir_app/src/chat.h b/src/mir_app/src/chat.h index 04fa195b9c..df5141f2e1 100644 --- a/src/mir_app/src/chat.h +++ b/src/mir_app/src/chat.h @@ -129,6 +129,7 @@ int ShowPopup(MCONTACT hContact, SESSION_INFO *si, HICON hIcon, char* CSrmmLogWindow *Srmm_GetLogWindow(CMsgDialog *pDlg); +void Chat_EventToGC(SESSION_INFO *si, MEVENT hDbEvent); void Chat_RemoveContact(MCONTACT hContact); CMStringW Chat_GetFolderName(SESSION_INFO *si = nullptr); diff --git a/src/mir_app/src/chat_log.cpp b/src/mir_app/src/chat_log.cpp index 151662ab5d..5f82bace10 100644 --- a/src/mir_app/src/chat_log.cpp +++ b/src/mir_app/src/chat_log.cpp @@ -30,11 +30,11 @@ char *pLogIconBmpBits[14]; #define RTFCACHELINESIZE 128 static char CHAT_rtfFontsGlobal[OPTIONS_FONTCOUNT][RTFCACHELINESIZE]; -static int EventToIndex(LOGINFO *lin) +static int EventToIndex(const LOGINFO &lin) { - switch (lin->iType) { + switch (lin.iType) { case GC_EVENT_MESSAGE: - if (lin->bIsMe) + if (lin.bIsMe) return 10; else return 9; @@ -54,11 +54,11 @@ static int EventToIndex(LOGINFO *lin) return 0; } -static int EventToIcon(LOGINFO *lin) +static int EventToIcon(const LOGINFO &lin) { - switch (lin->iType) { + switch (lin.iType) { case GC_EVENT_MESSAGE: - if (lin->bIsMe) + if (lin.bIsMe) return ICON_MESSAGEOUT; else return ICON_MESSAGE; @@ -89,6 +89,7 @@ char* Log_SetStyle(int style) static int Log_AppendRTF(LOGSTREAMDATA *streamData, bool simpleMode, CMStringA &buf, const wchar_t *line) { int textCharsCount = 0; + auto &lin = streamData->si->arEvents[streamData->iStartEvent]; for (; *line; line++, textCharsCount++) { if (*line == '\r' && line[1] == '\n') { @@ -129,7 +130,7 @@ static int Log_AppendRTF(LOGSTREAMDATA *streamData, bool simpleMode, CMStringA & case 'C': case 'F': if (!g_Settings->bStripFormat && !streamData->bStripFormat) { - int j = streamData->lin->bIsHighlighted ? 16 : EventToIndex(streamData->lin); + int j = lin.bIsHighlighted ? 16 : EventToIndex(lin); if (*line == 'C') mir_snprintf(szTemp, "\\cf%u ", j + 1); else @@ -154,7 +155,7 @@ static int Log_AppendRTF(LOGSTREAMDATA *streamData, bool simpleMode, CMStringA & case 'r': if (!streamData->bStripFormat) { - int index = EventToIndex(streamData->lin); + int index = EventToIndex(lin); mir_snprintf(szTemp, "%s ", Log_SetStyle(index)); } break; @@ -252,16 +253,16 @@ MIR_APP_DLL(bool) Chat_GetDefaultEventDescr(const SESSION_INFO *si, const LOGINF return false; } -static void AddEventToBuffer(CMStringA &buf, LOGSTREAMDATA *streamData) +static void AddEventToBuffer(CMStringA &buf, LOGSTREAMDATA *streamData, const LOGINFO &lin) { CMStringW wszCaption; - bool bTextUsed = Chat_GetDefaultEventDescr(streamData->si, streamData->lin, wszCaption); + bool bTextUsed = Chat_GetDefaultEventDescr(streamData->si, &lin, wszCaption); if (!wszCaption.IsEmpty()) Log_AppendRTF(streamData, !bTextUsed, buf, wszCaption); - if (!bTextUsed && streamData->lin->ptszText) { + if (!bTextUsed && lin.ptszText) { if (!wszCaption.IsEmpty()) Log_AppendRTF(streamData, false, buf, L" "); - Log_AppendRTF(streamData, false, buf, streamData->lin->ptszText); + Log_AppendRTF(streamData, false, buf, lin.ptszText); } } @@ -287,20 +288,22 @@ char* Log_CreateRTF(LOGSTREAMDATA *streamData) buf.Append(header); // ### RTF BODY (one iteration per event that should be streamed in) - for (LOGINFO *lin = streamData->lin; lin; lin = lin->prev) { + for (int i = 0; i < si->arEvents.getCount(); i++) { + auto &lin = si->arEvents[i]; + // filter if (si->iType == GCW_CHATROOM || si->iType == GCW_PRIVMESS) - if (!(si->pDlg->m_iLogFilterFlags & lin->iType)) + if (!(si->pDlg->m_iLogFilterFlags & lin.iType)) continue; // create new line, and set font and color - if (lin->next != nullptr) + if (i != 0) buf.Append("\\par "); buf.AppendFormat("%s ", Log_SetStyle(0)); // Insert icon - if ((lin->iType & g_Settings->dwIconFlags) || lin->bIsHighlighted && (g_Settings->dwIconFlags & GC_EVENT_HIGHLIGHT)) { - int iIndex = (lin->bIsHighlighted && (g_Settings->dwIconFlags & GC_EVENT_HIGHLIGHT)) ? ICON_HIGHLIGHT : EventToIcon(lin); + if ((lin.iType & g_Settings->dwIconFlags) || lin.bIsHighlighted && (g_Settings->dwIconFlags & GC_EVENT_HIGHLIGHT)) { + int iIndex = (lin.bIsHighlighted && (g_Settings->dwIconFlags & GC_EVENT_HIGHLIGHT)) ? ICON_HIGHLIGHT : EventToIcon(lin); buf.Append("\\f0\\fs14"); buf.Append(pLogIconBmpBits[iIndex]); } @@ -309,12 +312,12 @@ char* Log_CreateRTF(LOGSTREAMDATA *streamData) LOGFONT &lf = g_chatApi.aFonts[0].lf; // colored timestamps - if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) { - int iii = lin->bIsHighlighted ? 16 : (lin->bIsMe ? 2 : 1); + if (lin.ptszNick && lin.iType == GC_EVENT_MESSAGE) { + int iii = lin.bIsHighlighted ? 16 : (lin.bIsMe ? 2 : 1); buf.AppendFormat("\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\fs%u", iii + 1, lf.lfWeight >= FW_BOLD ? 1 : 0, lf.lfItalic, 2 * abs(lf.lfHeight) * 74 / g_chatApi.logPixelSY); } else { - int iii = lin->bIsHighlighted ? 16 : EventToIndex(lin); + int iii = lin.bIsHighlighted ? 16 : EventToIndex(lin); buf.AppendFormat("\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\fs%u", iii + 1, lf.lfWeight >= FW_BOLD ? 1 : 0, lf.lfItalic, 2 * abs(lf.lfHeight) * 74 / g_chatApi.logPixelSY); } } @@ -323,33 +326,32 @@ char* Log_CreateRTF(LOGSTREAMDATA *streamData) if (g_Settings->dwIconFlags) buf.Append("\\tab "); - //insert timestamp + // insert timestamp if (g_Settings->bShowTime) { wchar_t szTimeStamp[100], szOldTimeStamp[100]; - wcsncpy_s(szTimeStamp, MakeTimeStamp(g_Settings->pszTimeStamp, lin->time), _TRUNCATE); + wcsncpy_s(szTimeStamp, MakeTimeStamp(g_Settings->pszTimeStamp, lin.time), _TRUNCATE); wcsncpy_s(szOldTimeStamp, MakeTimeStamp(g_Settings->pszTimeStamp, si->LastTime), _TRUNCATE); if (!g_Settings->bShowTimeIfChanged || si->LastTime == 0 || mir_wstrcmp(szTimeStamp, szOldTimeStamp)) { - si->LastTime = lin->time; + si->LastTime = lin.time; Log_AppendRTF(streamData, true, buf, szTimeStamp); } buf.Append("\\tab "); } // Insert the nick - if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) { - buf.AppendFormat("%s ", Log_SetStyle(lin->bIsMe ? 2 : 1)); + if (lin.ptszNick && lin.iType == GC_EVENT_MESSAGE) { + buf.AppendFormat("%s ", Log_SetStyle(lin.bIsMe ? 2 : 1)); - CMStringW tmp((lin->bIsMe) ? g_Settings->pszOutgoingNick : g_Settings->pszIncomingNick); - tmp.Replace(L"%n", lin->ptszNick); + CMStringW tmp((lin.bIsMe) ? g_Settings->pszOutgoingNick : g_Settings->pszIncomingNick); + tmp.Replace(L"%n", lin.ptszNick); Log_AppendRTF(streamData, TRUE, buf, tmp); buf.AppendChar(' '); } // Insert the message - buf.AppendFormat("%s ", Log_SetStyle(lin->bIsHighlighted ? 16 : EventToIndex(lin))); - streamData->lin = lin; - AddEventToBuffer(buf, streamData); + buf.AppendFormat("%s ", Log_SetStyle(lin.bIsHighlighted ? 16 : EventToIndex(lin))); + AddEventToBuffer(buf, streamData, lin); } // ### RTF END diff --git a/src/mir_app/src/chat_manager.cpp b/src/mir_app/src/chat_manager.cpp index 23984f3601..3917e19801 100644 --- a/src/mir_app/src/chat_manager.cpp +++ b/src/mir_app/src/chat_manager.cpp @@ -56,76 +56,24 @@ static int compareModules(const MODULEINFO *p1, const MODULEINFO *p2) static LIST g_arModules(5, compareModules); ///////////////////////////////////////////////////////////////////////////////////////// -// Log manager functions -// Necessary to keep track of events in a window log - -static LOGINFO* LM_AddEvent(LOGINFO **ppLogListStart, LOGINFO **ppLogListEnd) -{ - if (!ppLogListStart || !ppLogListEnd) - return nullptr; - - LOGINFO *node = (LOGINFO *)mir_calloc(sizeof(LOGINFO)); - if (*ppLogListStart == nullptr) { // list is empty - *ppLogListStart = node; - *ppLogListEnd = node; - node->next = nullptr; - node->prev = nullptr; - } - else { - ppLogListStart[0]->prev = node; - node->next = *ppLogListStart; - *ppLogListStart = node; - ppLogListStart[0]->prev = nullptr; - } - - return node; -} +// Session Manager functions +// Keeps track of all sessions and its windows -static BOOL LM_TrimLog(LOGINFO **ppLogListStart, LOGINFO **ppLogListEnd, int iCount) +static int CompareEvents(const LOGINFO *p1, const LOGINFO *p2) { - LOGINFO *pTemp = *ppLogListEnd; - while (pTemp != nullptr && iCount > 0) { - *ppLogListEnd = pTemp->prev; - if (*ppLogListEnd == nullptr) - *ppLogListStart = nullptr; + if (p1->time != p2->time) + return (p1->time < p2->time) ? -1 : 1; - mir_free(pTemp->ptszNick); - mir_free(pTemp->ptszUserInfo); - mir_free(pTemp->ptszText); - mir_free(pTemp->ptszStatus); - mir_free(pTemp); - pTemp = *ppLogListEnd; - iCount--; - } - ppLogListEnd[0]->next = nullptr; - - return TRUE; -} - -static BOOL LM_RemoveAll(LOGINFO **ppLogListStart, LOGINFO **ppLogListEnd) -{ - while (*ppLogListStart != nullptr) { - LOGINFO *pLast = ppLogListStart[0]->next; - mir_free(ppLogListStart[0]->ptszText); - mir_free(ppLogListStart[0]->ptszNick); - mir_free(ppLogListStart[0]->ptszStatus); - mir_free(ppLogListStart[0]->ptszUserInfo); - mir_free(*ppLogListStart); - *ppLogListStart = pLast; - } - *ppLogListStart = nullptr; - *ppLogListEnd = nullptr; - return TRUE; + return (int)p1->hEvent - (int)p2->hEvent; } -///////////////////////////////////////////////////////////////////////////////////////// -// Session Manager functions -// Keeps track of all sessions and its windows - SESSION_INFO::SESSION_INFO() : arKeys(10, CompareKeys), - arUsers(10, CompareUser) -{} + arUsers(10, CompareUser), + arEvents(10, CompareEvents) +{ + iLastEvent = MAXINT/2; +} SESSION_INFO::~SESSION_INFO() {} @@ -186,8 +134,8 @@ void SM_FreeSession(SESSION_INFO *si) UM_RemoveAll(si); g_chatApi.TM_RemoveAll(&si->pStatuses); - g_chatApi.LM_RemoveAll(&si->pLog, &si->pLogEnd); + si->arEvents.destroy(); si->iStatusCount = 0; mir_free(si->pszModule); @@ -251,23 +199,32 @@ BOOL SM_AddEvent(SESSION_INFO *si, GCEVENT *gce, bool bIsHighlighted) if (si == nullptr) return TRUE; - LOGINFO *li = LM_AddEvent(&si->pLog, &si->pLogEnd); - si->iEventCount++; + LOGINFO *li = new LOGINFO(); + li->time = gce->time; + li->bIsHighlighted = bIsHighlighted; + if (si->pMI->bDatabase && gce->hEvent) { + li->hEvent = gce->hEvent; + if (si->arEvents.find(li)) { + delete li; + return TRUE; + } + } + else li->hEvent = si->iLastEvent++; li->iType = gce->iType; li->ptszNick = mir_wstrdup(gce->pszNick.w); li->ptszText = mir_wstrdup(gce->pszText.w); li->ptszStatus = mir_wstrdup(gce->pszStatus.w); li->ptszUserInfo = mir_wstrdup(gce->pszUserInfo.w); - li->bIsMe = gce->bIsMe; - li->time = gce->time; - li->bIsHighlighted = bIsHighlighted; + + si->arEvents.insert(li); + + if (g_Settings->iEventLimit > 0 && si->arEvents.getCount() > g_Settings->iEventLimit + 20) { + for (int i = si->arEvents.getCount() - g_Settings->iEventLimit; i >= 0; i--) + si->arEvents.remove(0); - if (g_Settings->iEventLimit > 0 && si->iEventCount > g_Settings->iEventLimit + 20) { - LM_TrimLog(&si->pLog, &si->pLogEnd, si->iEventCount - g_Settings->iEventLimit); si->bTrimmed = true; - si->iEventCount = g_Settings->iEventLimit; return FALSE; } return TRUE; @@ -881,8 +838,6 @@ static void ResetApi() g_chatApi.UM_FindUserAutoComplete = ::UM_FindUserAutoComplete; g_chatApi.UM_RemoveUser = ::UM_RemoveUser; - g_chatApi.LM_RemoveAll = ::LM_RemoveAll; - g_chatApi.SetOffline = ::SetOffline; g_chatApi.SetAllOffline = ::SetAllOffline; g_chatApi.DoRtfToTags = ::DoRtfToTags; diff --git a/src/mir_app/src/chat_svc.cpp b/src/mir_app/src/chat_svc.cpp index 0e590cdeb3..cc573729c6 100644 --- a/src/mir_app/src/chat_svc.cpp +++ b/src/mir_app/src/chat_svc.cpp @@ -329,8 +329,7 @@ static int RoomControlHandler(int iCommand, SESSION_INFO *si) break; case WINDOW_CLEARLOG: - g_chatApi.LM_RemoveAll(&si->pLog, &si->pLogEnd); - si->iEventCount = 0; + si->arEvents.destroy(); si->LastTime = 0; if (si->pDlg) si->pDlg->ClearLog(); @@ -821,23 +820,8 @@ static int OnEventAdded(WPARAM hContact, LPARAM hDbEvent) return 0; if (Contact::IsGroupChat(hContact)) { - if (auto *si = SM_FindSessionByContact(hContact)) { - DB::EventInfo dbei(hDbEvent); - if (dbei) { - auto *szProto = Proto_GetBaseAccountName(si->hContact); - if (si && !mir_strcmp(szProto, dbei.szModule) && dbei.eventType == EVENTTYPE_MESSAGE && dbei.szUserId) { - CMStringA szText((char *)dbei.pBlob); - szText.Replace("%", "%%"); - - GCEVENT gce = { si, GC_EVENT_MESSAGE }; - gce.dwFlags = GCEF_ADDTOLOG | GCEF_UTF8; - gce.pszUID.a = dbei.szUserId; - gce.pszText.a = szText; - gce.time = dbei.timestamp; - Chat_Event(&gce); - } - } - } + if (auto *si = SM_FindSessionByContact(hContact)) + Chat_EventToGC(si, hDbEvent); } else { g_clistApi.pfnRemoveEvent(hContact, 1); diff --git a/src/mir_app/src/chat_tools.cpp b/src/mir_app/src/chat_tools.cpp index 938db7b19c..48f5271745 100644 --- a/src/mir_app/src/chat_tools.cpp +++ b/src/mir_app/src/chat_tools.cpp @@ -737,6 +737,28 @@ wchar_t* GetChatLogsFilename(SESSION_INFO *si, time_t tTime) return si->pszLogFileName; } +void Chat_EventToGC(SESSION_INFO *si, MEVENT hDbEvent) +{ + DB::EventInfo dbei(hDbEvent); + if (!dbei) + return; + + auto *szProto = Proto_GetBaseAccountName(si->hContact); + if (mir_strcmp(szProto, dbei.szModule) || dbei.eventType != EVENTTYPE_MESSAGE || !dbei.szUserId) + return; + + CMStringA szText((char *)dbei.pBlob); + szText.Replace("%", "%%"); + + GCEVENT gce = { si, GC_EVENT_MESSAGE }; + gce.dwFlags = GCEF_ADDTOLOG | GCEF_UTF8; + gce.pszUID.a = dbei.szUserId; + gce.pszText.a = szText; + gce.time = dbei.timestamp; + gce.hEvent = hDbEvent; + Chat_Event(&gce); +} + ///////////////////////////////////////////////////////////////////////////////////////// MIR_APP_DLL(wchar_t*) Chat_GetGroup() diff --git a/src/mir_app/src/srmm_base.cpp b/src/mir_app/src/srmm_base.cpp index 6e567643d6..8c7b9b69df 100644 --- a/src/mir_app/src/srmm_base.cpp +++ b/src/mir_app/src/srmm_base.cpp @@ -74,7 +74,7 @@ CSrmmBaseDialog::CSrmmBaseDialog(CMPluginBase &pPlugin, int idDialog, SESSION_IN m_bBGSet = true; } - m_bFilterEnabled = m_bFilterEnabled = db_get_b(m_hContact, CHAT_MODULE, "FilterEnabled", Chat::bFilterEnabled) != 0; + m_bFilterEnabled = db_get_b(m_hContact, CHAT_MODULE, "FilterEnabled", Chat::bFilterEnabled) != 0; m_iLogFilterFlags = Chat::iFilterFlags; m_bNicklistEnabled = Chat::bShowNicklist; } @@ -581,8 +581,9 @@ INT_PTR CSrmmBaseDialog::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) void CSrmmBaseDialog::AddLog() { - if (m_si->pLogEnd) - m_pLog->LogEvents(m_si->pLog, false); + int iEventCount = m_si->arEvents.getCount(); + if (iEventCount) + m_pLog->LogEvents(m_si, iEventCount-1, false); else m_pLog->Clear(); } @@ -617,8 +618,10 @@ void CSrmmBaseDialog::UpdateOptions() void RedrawLog2(SESSION_INFO *si) { si->LastTime = 0; - if (si->pLog) - si->pDlg->log()->LogEvents(si->pLogEnd, TRUE); + + int iEventCount = si->arEvents.getCount(); + if (iEventCount) + si->pDlg->log()->LogEvents(si, 0, TRUE); } static void __cdecl phase2(SESSION_INFO *si) @@ -631,22 +634,23 @@ static void __cdecl phase2(SESSION_INFO *si) void CSrmmBaseDialog::RedrawLog() { m_si->LastTime = 0; - if (m_si->pLog) { - LOGINFO *pLog = m_si->pLog; - if (m_si->iEventCount > 60) { + + int iEventCount = m_si->arEvents.getCount(); + if (iEventCount) { + if (iEventCount > 60) { int index = 0; while (index < 59) { - if (pLog->next == nullptr) + if (iEventCount == 0) break; - pLog = pLog->next; - if (m_si->iType != GCW_CHATROOM || !m_bFilterEnabled || (m_iLogFilterFlags & pLog->iType) != 0) + iEventCount--; + if (m_si->iType != GCW_CHATROOM || (m_iLogFilterFlags & m_si->arEvents[iEventCount].iType) != 0) index++; } - m_pLog->LogEvents(pLog, true); + m_pLog->LogEvents(m_si, iEventCount, true); mir_forkThread(phase2, m_si); } - else m_pLog->LogEvents(m_si->pLogEnd, true); + else m_pLog->LogEvents(m_si, 0, true); } else ClearLog(); } @@ -684,7 +688,7 @@ void CSrmmBaseDialog::UpdateChatLog() } m_si->bHistoryInit = true; - m_pLog->LogEvents(m_si->pLogEnd, false); + m_pLog->LogEvents(m_si, 0, false); } void CSrmmBaseDialog::UpdateFilterButton() diff --git a/src/mir_app/src/srmm_log_hpp.cpp b/src/mir_app/src/srmm_log_hpp.cpp index 584ed539f9..cfdca891d0 100644 --- a/src/mir_app/src/srmm_log_hpp.cpp +++ b/src/mir_app/src/srmm_log_hpp.cpp @@ -109,7 +109,7 @@ public: CallService(MS_HPP_EG_EVENT, 0, (LPARAM)&event); } - void CHppLogWindow::LogEvents(LOGINFO *pLog, bool) + void CHppLogWindow::LogEvents(SESSION_INFO *si, int iStart, bool) override { IEVIEWEVENTDATA ied = {}; ied.dwFlags = IEEDF_UNICODE_NICK | IEEDF_UNICODE_TEXT; @@ -122,14 +122,16 @@ public: event.eventData = &ied; event.count = 1; - while (pLog) { - if (pLog->ptszText) { - ied.szNick.w = pLog->ptszNick; - ied.szText.w = pLog->ptszText; - ied.time = pLog->time; - ied.bIsMe = pLog->bIsMe; + for (int i=iStart; i < si->arEvents.getCount(); i++) { + auto &pLog = si->arEvents[i]; + + if (pLog.ptszText) { + ied.szNick.w = pLog.ptszNick; + ied.szText.w = pLog.ptszText; + ied.time = pLog.time; + ied.bIsMe = pLog.bIsMe; - switch (pLog->iType) { + switch (pLog.iType) { case GC_EVENT_MESSAGE: ied.iType = IEED_GC_EVENT_MESSAGE; ied.dwData = IEEDD_GC_SHOW_NICK; @@ -173,8 +175,6 @@ public: ied.dwFlags = IEEDF_UNICODE_TEXT | IEEDF_UNICODE_NICK; CallService(MS_HPP_EG_EVENT, 0, (LPARAM) & event); } - - pLog = pLog->prev; } } diff --git a/src/mir_app/src/srmm_log_rtf.cpp b/src/mir_app/src/srmm_log_rtf.cpp index 88a8466f93..b38eb0f4eb 100644 --- a/src/mir_app/src/srmm_log_rtf.cpp +++ b/src/mir_app/src/srmm_log_rtf.cpp @@ -359,10 +359,26 @@ static DWORD CALLBACK LogStreamInEvents(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG 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); + if (Contact::IsGroupChat(dat->hContact)) { + if (auto *si = SM_FindSessionByContact(dat->hContact)) { + bool bDone = false; + + for (MEVENT hDbEvent = dat->hDbEvent; hDbEvent && dat->eventsToInsert; dat->eventsToInsert--) { + Chat_EventToGC(si, dat->hDbEvent); + dat->hDbEvent = db_event_next(dat->hContact, dat->hDbEvent); + bDone = true; + } + + if (bDone && si->pDlg) + si->pDlg->RedrawLog(); + } + } + else { + EDITSTREAM stream = {}; + stream.pfnCallback = LogStreamInEvents; + stream.dwCookie = (DWORD_PTR)dat; + m_rtf.SendMsg(EM_STREAMIN, bAppend ? SFF_SELECTION | SF_RTF : SF_RTF, (LPARAM)&stream); + } } ///////////////////////////////////////////////////////////////////////////////////////// @@ -505,8 +521,7 @@ INT_PTR CRtfLogWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam) case IDM_CLEAR: m_rtf.SetText(L""); if (auto *si = m_pDlg.m_si) { - g_chatApi.LM_RemoveAll(&si->pLog, &si->pLogEnd); - si->iEventCount = 0; + si->arEvents.destroy(); si->LastTime = 0; } PostMessage(m_pDlg.m_hwnd, WM_MOUSEACTIVATE, 0, 0); -- cgit v1.2.3