summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2023-04-14 17:59:03 +0300
committerGeorge Hazan <ghazan@miranda.im>2023-04-14 17:59:03 +0300
commitf12d6a4000cfce521392200635d1cadc63dba934 (patch)
tree86d408068682d7b1e239877df857ac95f7f25297 /src
parentaa5197082f1567e37b85911752b92a489d6515c3 (diff)
SRMM code unification
Diffstat (limited to 'src')
-rw-r--r--src/core/stdmsg/src/chat_window.cpp104
-rw-r--r--src/core/stdmsg/src/msgdialog.cpp2
-rw-r--r--src/core/stdmsg/src/msglog.cpp857
-rw-r--r--src/core/stdmsg/src/msgs.h17
-rw-r--r--src/mir_app/src/db_events.cpp10
-rw-r--r--src/mir_app/src/mir_app.def2
-rw-r--r--src/mir_app/src/mir_app64.def2
-rw-r--r--src/mir_app/src/srmm_log_rtf.cpp25
8 files changed, 518 insertions, 501 deletions
diff --git a/src/core/stdmsg/src/chat_window.cpp b/src/core/stdmsg/src/chat_window.cpp
index a8806f0cbc..c78e3d1d0e 100644
--- a/src/core/stdmsg/src/chat_window.cpp
+++ b/src/core/stdmsg/src/chat_window.cpp
@@ -107,110 +107,6 @@ void CMsgDialog::UpdateStatusBar()
/////////////////////////////////////////////////////////////////////////////////////////
-void CLogWindow::LogEvents(LOGINFO *lin, bool bRedraw)
-{
- auto *si = m_pDlg.m_si;
- if (lin == nullptr || si == nullptr)
- return;
-
- 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.bStripFormat = FALSE;
-
- bool bFlag = false;
-
- EDITSTREAM stream = {};
- stream.pfnCallback = Srmm_LogStreamCallback;
- stream.dwCookie = (DWORD_PTR)& streamData;
-
- SCROLLINFO scroll;
- scroll.cbSize = sizeof(SCROLLINFO);
- scroll.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
- GetScrollInfo(m_rtf.GetHwnd(), SB_VERT, &scroll);
-
- POINT point = {};
- m_rtf.SendMsg(EM_GETSCROLLPOS, 0, (LPARAM)&point);
-
- // do not scroll to bottom if there is a selection
- CHARRANGE oldsel, sel;
- m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&oldsel);
- if (oldsel.cpMax != oldsel.cpMin)
- m_rtf.SetDraw(false);
-
- //set the insertion point at the bottom
- sel.cpMin = sel.cpMax = m_rtf.GetRichTextLength();
- m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
-
- // fix for the indent... must be a M$ bug
- if (sel.cpMax == 0)
- bRedraw = TRUE;
-
- // should the event(s) be appended to the current log
- WPARAM wp = bRedraw ? SF_RTF : SFF_SELECTION | SF_RTF;
-
- //get the number of pixels per logical inch
- if (bRedraw) {
- HDC hdc = GetDC(nullptr);
- g_chatApi.logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY);
- g_chatApi.logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX);
- ReleaseDC(nullptr, hdc);
- m_rtf.SetDraw(false);
- bFlag = true;
- }
-
- // stream in the event(s)
- streamData.lin = lin;
- streamData.bRedraw = bRedraw;
- 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))) {
- CHARRANGE newsel;
- newsel.cpMax = -1;
- newsel.cpMin = sel.cpMin;
- if (newsel.cpMin < 0)
- newsel.cpMin = 0;
-
- SMADD_RICHEDIT3 sm = {};
- sm.cbSize = sizeof(sm);
- sm.hwndRichEditControl = m_rtf.GetHwnd();
- sm.Protocolname = si->pszModule;
- sm.rangeToReplace = bRedraw ? nullptr : &newsel;
- sm.disableRedraw = TRUE;
- sm.hContact = si->hContact;
- CallService(MS_SMILEYADD_REPLACESMILEYS, 0, (LPARAM)&sm);
- }
-
- // scroll log to bottom if the log was previously scrolled to bottom, else restore old position
- if (bRedraw || (UINT)scroll.nPos >= (UINT)scroll.nMax - scroll.nPage - 5 || scroll.nMax - scroll.nMin - scroll.nPage < 50)
- ScrollToBottom();
- else
- m_rtf.SendMsg(EM_SETSCROLLPOS, 0, (LPARAM)&point);
-
- // do we need to restore the selection
- if (oldsel.cpMax != oldsel.cpMin) {
- m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&oldsel);
- m_rtf.SetDraw(true);
- InvalidateRect(m_rtf.GetHwnd(), nullptr, TRUE);
- }
-
- // need to invalidate the window
- if (bFlag) {
- sel.cpMin = sel.cpMax = m_rtf.GetRichTextLength();
- m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
- m_rtf.SetDraw(true);
- InvalidateRect(m_rtf.GetHwnd(), nullptr, TRUE);
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
INT_PTR CALLBACK CMsgDialog::FilterWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int iFlags;
diff --git a/src/core/stdmsg/src/msgdialog.cpp b/src/core/stdmsg/src/msgdialog.cpp
index 08f0036782..cfeca501ef 100644
--- a/src/core/stdmsg/src/msgdialog.cpp
+++ b/src/core/stdmsg/src/msgdialog.cpp
@@ -922,7 +922,7 @@ LRESULT CMsgDialog::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam)
}
if (wParam == VK_NEXT || wParam == VK_PRIOR) {
- ((CLogWindow *)m_pLog)->WndProc(msg, wParam, lParam);
+ ((CRtfLogWindow *)m_pLog)->WndProc(msg, wParam, lParam);
return TRUE;
}
}
diff --git a/src/core/stdmsg/src/msglog.cpp b/src/core/stdmsg/src/msglog.cpp
index 318e246ae3..d9c7c5f69b 100644
--- a/src/core/stdmsg/src/msglog.cpp
+++ b/src/core/stdmsg/src/msglog.cpp
@@ -42,7 +42,7 @@ struct LogStreamData
CMStringA buf;
int eventsToInsert;
bool isEmpty;
- CMsgDialog *dlgDat;
+ class CLogWindow *pLog;
};
static int logPixelSY;
@@ -51,6 +51,8 @@ static char szSep2[40], szSep2_RTL[50];
static const wchar_t *bbcodes[] = { L"[b]", L"[i]", L"[u]", L"[s]", L"[/b]", L"[/i]", L"[/u]", L"[/s]" };
static const char *bbcodefmt[] = { "\\b ", "\\i ", "\\ul ", "\\strike ", "\\b0 ", "\\i0 ", "\\ul0 ", "\\strike0 " };
+static DWORD CALLBACK LogStreamInEvents(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb);
+
static void AppendPlainUnicode(CMStringA &buf, const wchar_t *str)
{
for (; *str; str++) {
@@ -198,214 +200,6 @@ bool DbEventIsShown(const DBEVENTINFO *dbei)
return dbei->eventType == EVENTTYPE_MESSAGE || dbei->eventType == EVENTTYPE_FILE || DbEventIsForMsgWindow(dbei);
}
-static bool CreateRTFFromDbEvent(LogStreamData *dat)
-{
- DB::EventInfo dbei(dat->hDbEvent);
- if (!dbei)
- return false;
-
- if (!DbEventIsShown(&dbei))
- return false;
-
- if (!(dbei.flags & DBEF_SENT) && (dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei))) {
- 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 = dat->dlgDat->m_bIsAutoRTL;
- if (!bIsRtl && !dat->isEmpty)
- buf.Append("\\par");
-
- if (dbei.flags & DBEF_RTL) {
- buf.Append("\\rtlpar");
- bIsRtl = true;
- }
- else buf.Append("\\ltrpar");
-
- dat->isEmpty = false;
-
- if (bIsRtl) {
- if (dbei.flags & DBEF_RTL)
- buf.Append("\\ltrch\\rtlch");
- else
- buf.Append("\\rtlch\\ltrch");
- }
-
- if (g_plugin.bShowIcons) {
- int i = ((dbei.eventType == EVENTTYPE_MESSAGE) ? ((dbei.flags & DBEF_SENT) ? LOGICON_MSG_OUT : LOGICON_MSG_IN): LOGICON_MSG_NOTICE);
-
- buf.Append("\\f0\\fs14");
- buf.Append(pLogIconBmpBits[i]);
- }
-
- int showColon = 0;
- if (g_plugin.bShowTime) {
- const wchar_t* szFormat;
- wchar_t str[64];
-
- if (g_plugin.bShowSecs)
- szFormat = g_plugin.bShowDate ? L"d s" : L"s";
- else
- szFormat = g_plugin.bShowDate ? L"d t" : L"t";
-
- TimeZone_PrintTimeStamp(nullptr, dbei.timestamp, szFormat, str, _countof(str), 0);
-
- SetToStyle((dbei.flags & DBEF_SENT) ? MSGFONTID_MYTIME : MSGFONTID_YOURTIME, buf);
- AppendToBufferWithRTF(buf, str);
- showColon = 1;
- }
-
- if (g_plugin.bShowNames && dbei.eventType != EVENTTYPE_JABBER_CHATSTATES && dbei.eventType != EVENTTYPE_JABBER_PRESENCE) {
- wchar_t *szName;
-
- if (dbei.flags & DBEF_SENT) {
- if (wchar_t *p = Contact::GetInfo(CNF_DISPLAY, 0, dbei.szModule))
- szName = NEWWSTR_ALLOCA(p);
- else
- szName = TranslateT("Me");
- }
- else szName = Clist_GetContactDisplayName(dat->hContact);
-
- SetToStyle((dbei.flags & DBEF_SENT) ? MSGFONTID_MYNAME : MSGFONTID_YOURNAME, buf);
- AppendToBufferWithRTF(buf, szName);
- showColon = 1;
- }
-
- if (showColon)
- SetToStyle((dbei.flags & DBEF_SENT) ? MSGFONTID_MYCOLON : MSGFONTID_YOURCOLON, buf);
-
- wchar_t *msg, *szName;
- switch (dbei.eventType) {
- case EVENTTYPE_JABBER_CHATSTATES:
- case EVENTTYPE_JABBER_PRESENCE:
- if (dbei.flags & DBEF_SENT) {
- if (wchar_t *p = Contact::GetInfo(CNF_DISPLAY, 0, dbei.szModule)) {
- szName = NEWWSTR_ALLOCA(p);
- mir_free(p);
- }
- else szName = L"";
- }
- else szName = Clist_GetContactDisplayName(dat->hContact);
-
- SetToStyle(MSGFONTID_NOTICE, buf);
- AppendToBufferWithRTF(buf, szName);
- AppendToBufferWithRTF(buf, L" ");
-
- msg = DbEvent_GetTextW(&dbei, CP_ACP);
- if (msg) {
- AppendToBufferWithRTF(buf, msg);
- mir_free(msg);
- }
- break;
-
- case EVENTTYPE_FILE:
- SetToStyle(MSGFONTID_NOTICE, buf);
- {
- DB::FILE_BLOB blob(dbei);
- if (blob.isOffline()) {
- AppendToBufferWithRTF(buf, TranslateT("Offline file"));
- buf.Append(" {\\field{\\*\\fldinst HYPERLINK \"");
- buf.AppendFormat("ofile:%ul", dat->hDbEvent);
- buf.Append("\"}{\\fldrslt{\\ul ");
- AppendToBufferWithRTF(buf, blob.getName());
- buf.AppendFormat("}}} | %uKB", blob.getSize() / 1024);
-
- CMStringA szHost;
- if (const char *b = strstr(blob.getUrl(), "://"))
- for (b = b + 3; *b != 0 && *b != '/' && *b != ':'; b++)
- szHost.AppendChar(*b);
-
- if (!szHost.IsEmpty())
- buf.AppendFormat(" on %s", szHost.c_str());
-
- if (blob.getSize() > 0 && blob.getSize() == blob.getTransferred()) {
- buf.AppendChar(' ');
- AppendToBufferWithRTF(buf, TranslateT("Completed"));
- }
- }
- else {
- AppendToBufferWithRTF(buf, (dbei.flags & DBEF_SENT) ? TranslateT("File sent") : TranslateT("File received"));
- buf.Append(": ");
- AppendToBufferWithRTF(buf, blob.getName());
-
- if (mir_wstrlen(blob.getDescr())) {
- buf.Append(" (");
- AppendToBufferWithRTF(buf, blob.getDescr());
- buf.Append(")");
- }
- }
- }
- break;
-
- case EVENTTYPE_MESSAGE:
- default:
- msg = DbEvent_GetTextW(&dbei, CP_ACP);
- SetToStyle((dbei.eventType == EVENTTYPE_MESSAGE) ? ((dbei.flags & DBEF_SENT) ? MSGFONTID_MYMSG : MSGFONTID_YOURMSG) : MSGFONTID_NOTICE, buf);
- AppendToBufferWithRTF(buf, msg);
- mir_free(msg);
- }
-
- if (bIsRtl)
- buf.Append("\\par");
-
- return true;
-}
-
-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 = 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;
-}
-
#define RTFPICTHEADERMAXSIZE 78
void LoadMsgLogIcons(void)
{
@@ -461,204 +255,519 @@ void FreeMsgLogIcons(void)
}
/////////////////////////////////////////////////////////////////////////////////////////
+// Log window class
-void CLogWindow::Attach()
+class CLogWindow : public CRtfLogWindow
{
- CSuper::Attach();
+ typedef CRtfLogWindow CSuper;
- // get around a lame bug in the Windows template resource code where richedits are limited to 0x7FFF
- m_rtf.SendMsg(EM_LIMITTEXT, sizeof(wchar_t) * 0x7FFFFFFF, 0);
- m_rtf.SendMsg(EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_LINK | ENM_SCROLL);
- m_rtf.SendMsg(EM_HIDESELECTION, TRUE, 0);
- m_rtf.SendMsg(EM_AUTOURLDETECT, TRUE, 0);
-}
+public:
+ CLogWindow(CMsgDialog &pDlg) :
+ CSuper(pDlg)
+ {}
-void CLogWindow::LogEvents(MEVENT hDbEventFirst, int count, bool bAppend)
-{
- CHARRANGE oldSel, sel;
- BOOL bottomScroll = TRUE;
- POINT scrollPos;
-
- m_rtf.SetDraw(false);
- m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&oldSel);
-
- LogStreamData streamData = {};
- streamData.hContact = m_pDlg.m_hContact;
- streamData.hDbEvent = hDbEventFirst;
- streamData.dlgDat = &m_pDlg;
- 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)
- m_rtf.SendMsg(EM_GETSCROLLPOS, 0, (LPARAM)&scrollPos);
+ void AppendUnicodeString(CMStringA &str, const wchar_t *pwszBuf)
+ {
+ AppendToBufferWithRTF(str, pwszBuf);
}
- FINDTEXTEXA fi;
- if (bAppend) {
- sel.cpMin = sel.cpMax = -1;
- m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
- fi.chrg.cpMin = 0;
- }
- else {
- GETTEXTLENGTHEX gtxl = { 0 };
- gtxl.flags = GTL_DEFAULT | GTL_PRECISE | GTL_NUMCHARS;
- gtxl.codepage = 1200;
- fi.chrg.cpMin = m_rtf.SendMsg(EM_GETTEXTLENGTHEX, (WPARAM)&gtxl, 0);
+ void Attach() override
+ {
+ CSuper::Attach();
- sel.cpMin = sel.cpMax = m_rtf.GetRichTextLength();
- m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+ // get around a lame bug in the Windows template resource code where richedits are limited to 0x7FFF
+ m_rtf.SendMsg(EM_LIMITTEXT, sizeof(wchar_t) * 0x7FFFFFFF, 0);
+ m_rtf.SendMsg(EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_LINK | ENM_SCROLL);
+ m_rtf.SendMsg(EM_HIDESELECTION, TRUE, 0);
+ m_rtf.SendMsg(EM_AUTOURLDETECT, TRUE, 0);
}
- mir_strcpy(szSep2, bAppend ? "\\par\\sl0" : "\\sl1000");
- mir_strcpy(szSep2_RTL, bAppend ? "\\rtlpar\\rtlmark\\par\\sl1000" : "\\sl1000");
+ bool CreateRTFFromDbEvent(LogStreamData *dat)
+ {
+ DB::EventInfo dbei(dat->hDbEvent);
+ if (!dbei)
+ return false;
- 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);
- }
- else {
- m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&oldSel);
- m_rtf.SendMsg(EM_SETSCROLLPOS, 0, (LPARAM)&scrollPos);
+ if (!DbEventIsShown(&dbei))
+ return false;
+
+ if (!(dbei.flags & DBEF_SENT) && (dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei))) {
+ 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)
+ buf.Append("\\par");
+
+ if (dbei.flags & DBEF_RTL) {
+ buf.Append("\\rtlpar");
+ bIsRtl = true;
+ }
+ else buf.Append("\\ltrpar");
+
+ dat->isEmpty = false;
+
+ if (bIsRtl) {
+ if (dbei.flags & DBEF_RTL)
+ buf.Append("\\ltrch\\rtlch");
+ else
+ buf.Append("\\rtlch\\ltrch");
+ }
+
+ if (g_plugin.bShowIcons) {
+ int i = ((dbei.eventType == EVENTTYPE_MESSAGE) ? ((dbei.flags & DBEF_SENT) ? LOGICON_MSG_OUT : LOGICON_MSG_IN) : LOGICON_MSG_NOTICE);
+
+ buf.Append("\\f0\\fs14");
+ buf.Append(pLogIconBmpBits[i]);
+ }
+
+ int showColon = 0;
+ if (g_plugin.bShowTime) {
+ const wchar_t *szFormat;
+ wchar_t str[64];
+
+ if (g_plugin.bShowSecs)
+ szFormat = g_plugin.bShowDate ? L"d s" : L"s";
+ else
+ szFormat = g_plugin.bShowDate ? L"d t" : L"t";
+
+ TimeZone_PrintTimeStamp(nullptr, dbei.timestamp, szFormat, str, _countof(str), 0);
+
+ SetToStyle((dbei.flags & DBEF_SENT) ? MSGFONTID_MYTIME : MSGFONTID_YOURTIME, buf);
+ AppendToBufferWithRTF(buf, str);
+ showColon = 1;
+ }
+
+ if (g_plugin.bShowNames && dbei.eventType != EVENTTYPE_JABBER_CHATSTATES && dbei.eventType != EVENTTYPE_JABBER_PRESENCE) {
+ wchar_t *szName;
+
+ if (dbei.flags & DBEF_SENT) {
+ if (wchar_t *p = Contact::GetInfo(CNF_DISPLAY, 0, dbei.szModule))
+ szName = NEWWSTR_ALLOCA(p);
+ else
+ szName = TranslateT("Me");
+ }
+ else szName = Clist_GetContactDisplayName(dat->hContact);
+
+ SetToStyle((dbei.flags & DBEF_SENT) ? MSGFONTID_MYNAME : MSGFONTID_YOURNAME, buf);
+ AppendToBufferWithRTF(buf, szName);
+ showColon = 1;
+ }
+
+ if (showColon)
+ SetToStyle((dbei.flags & DBEF_SENT) ? MSGFONTID_MYCOLON : MSGFONTID_YOURCOLON, buf);
+
+ wchar_t *msg, *szName;
+ switch (dbei.eventType) {
+ case EVENTTYPE_JABBER_CHATSTATES:
+ case EVENTTYPE_JABBER_PRESENCE:
+ if (dbei.flags & DBEF_SENT) {
+ if (wchar_t *p = Contact::GetInfo(CNF_DISPLAY, 0, dbei.szModule)) {
+ szName = NEWWSTR_ALLOCA(p);
+ mir_free(p);
+ }
+ else szName = L"";
+ }
+ else szName = Clist_GetContactDisplayName(dat->hContact);
+
+ SetToStyle(MSGFONTID_NOTICE, buf);
+ AppendToBufferWithRTF(buf, szName);
+ AppendToBufferWithRTF(buf, L" ");
+
+ msg = DbEvent_GetTextW(&dbei, CP_ACP);
+ if (msg) {
+ AppendToBufferWithRTF(buf, msg);
+ mir_free(msg);
+ }
+ break;
+
+ case EVENTTYPE_FILE:
+ SetToStyle(MSGFONTID_NOTICE, buf);
+ {
+ DB::FILE_BLOB blob(dbei);
+ if (blob.isOffline()) {
+ InsertFileLink(buf, dat->hDbEvent, blob);
+ }
+ else {
+ AppendToBufferWithRTF(buf, (dbei.flags & DBEF_SENT) ? TranslateT("File sent") : TranslateT("File received"));
+ buf.Append(": ");
+ AppendToBufferWithRTF(buf, blob.getName());
+
+ if (mir_wstrlen(blob.getDescr())) {
+ buf.Append(" (");
+ AppendToBufferWithRTF(buf, blob.getDescr());
+ buf.Append(")");
+ }
+ }
+ }
+ break;
+
+ case EVENTTYPE_MESSAGE:
+ default:
+ msg = DbEvent_GetTextW(&dbei, CP_ACP);
+ SetToStyle((dbei.eventType == EVENTTYPE_MESSAGE) ? ((dbei.flags & DBEF_SENT) ? MSGFONTID_MYMSG : MSGFONTID_YOURMSG) : MSGFONTID_NOTICE, buf);
+ AppendToBufferWithRTF(buf, msg);
+ mir_free(msg);
+ }
+
+ if (bIsRtl)
+ buf.Append("\\par");
+
+ return true;
}
- if (g_plugin.bSmileyInstalled) {
- SMADD_RICHEDIT3 smre;
- smre.cbSize = sizeof(SMADD_RICHEDIT3);
- smre.hwndRichEditControl = m_rtf.GetHwnd();
+ /////////////////////////////////////////////////////////////////////////////////////////
- MCONTACT hContact = db_mc_getSrmmSub(m_pDlg.m_hContact);
- smre.Protocolname = (hContact != 0) ? Proto_GetBaseAccountName(hContact) : m_pDlg.m_szProto;
+ void LogEvents(MEVENT hDbEventFirst, int count, bool bAppend) override
+ {
+ CHARRANGE oldSel, sel;
+ BOOL bottomScroll = TRUE;
+ POINT scrollPos;
- if (fi.chrg.cpMin > 0) {
- sel.cpMin = fi.chrg.cpMin;
- sel.cpMax = -1;
- smre.rangeToReplace = &sel;
+ m_rtf.SetDraw(false);
+ m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&oldSel);
+
+ LogStreamData 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)
+ m_rtf.SendMsg(EM_GETSCROLLPOS, 0, (LPARAM)&scrollPos);
}
- else smre.rangeToReplace = nullptr;
- smre.disableRedraw = TRUE;
- smre.hContact = m_pDlg.m_hContact;
- smre.flags = 0;
- CallService(MS_SMILEYADD_REPLACESMILEYS, 0, (LPARAM)&smre);
+ FINDTEXTEXA fi;
+ if (bAppend) {
+ sel.cpMin = sel.cpMax = -1;
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+ fi.chrg.cpMin = 0;
+ }
+ else {
+ GETTEXTLENGTHEX gtxl = { 0 };
+ gtxl.flags = GTL_DEFAULT | GTL_PRECISE | GTL_NUMCHARS;
+ gtxl.codepage = 1200;
+ fi.chrg.cpMin = m_rtf.SendMsg(EM_GETTEXTLENGTHEX, (WPARAM)&gtxl, 0);
+
+ sel.cpMin = sel.cpMax = m_rtf.GetRichTextLength();
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+ }
+
+ 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);
+ }
+ else {
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&oldSel);
+ m_rtf.SendMsg(EM_SETSCROLLPOS, 0, (LPARAM)&scrollPos);
+ }
+
+ if (g_plugin.bSmileyInstalled) {
+ SMADD_RICHEDIT3 smre;
+ smre.cbSize = sizeof(SMADD_RICHEDIT3);
+ smre.hwndRichEditControl = m_rtf.GetHwnd();
+
+ MCONTACT hContact = db_mc_getSrmmSub(m_pDlg.m_hContact);
+ smre.Protocolname = (hContact != 0) ? Proto_GetBaseAccountName(hContact) : m_pDlg.m_szProto;
+
+ if (fi.chrg.cpMin > 0) {
+ sel.cpMin = fi.chrg.cpMin;
+ sel.cpMax = -1;
+ smre.rangeToReplace = &sel;
+ }
+ else smre.rangeToReplace = nullptr;
+
+ smre.disableRedraw = TRUE;
+ smre.hContact = m_pDlg.m_hContact;
+ smre.flags = 0;
+ CallService(MS_SMILEYADD_REPLACESMILEYS, 0, (LPARAM)&smre);
+ }
+
+ m_rtf.SetDraw(true);
+ if (bottomScroll || AtBottom()) {
+ ScrollToBottom();
+ RedrawWindow(m_rtf.GetHwnd(), nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
+ }
+
+ m_pDlg.m_hDbEventLast = streamData.hDbEventLast;
}
- m_rtf.SetDraw(true);
- if (bottomScroll || AtBottom()) {
- ScrollToBottom();
- RedrawWindow(m_rtf.GetHwnd(), nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ void LogEvents(struct LOGINFO *lin, bool bRedraw) override
+ {
+ auto *si = m_pDlg.m_si;
+ if (lin == nullptr || si == nullptr)
+ return;
+
+ 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.bStripFormat = FALSE;
+
+ bool bFlag = false;
+
+ EDITSTREAM stream = {};
+ stream.pfnCallback = Srmm_LogStreamCallback;
+ stream.dwCookie = (DWORD_PTR)&streamData;
+
+ SCROLLINFO scroll;
+ scroll.cbSize = sizeof(SCROLLINFO);
+ scroll.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
+ GetScrollInfo(m_rtf.GetHwnd(), SB_VERT, &scroll);
+
+ POINT point = {};
+ m_rtf.SendMsg(EM_GETSCROLLPOS, 0, (LPARAM)&point);
+
+ // do not scroll to bottom if there is a selection
+ CHARRANGE oldsel, sel;
+ m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&oldsel);
+ if (oldsel.cpMax != oldsel.cpMin)
+ m_rtf.SetDraw(false);
+
+ //set the insertion point at the bottom
+ sel.cpMin = sel.cpMax = m_rtf.GetRichTextLength();
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+
+ // fix for the indent... must be a M$ bug
+ if (sel.cpMax == 0)
+ bRedraw = TRUE;
+
+ // should the event(s) be appended to the current log
+ WPARAM wp = bRedraw ? SF_RTF : SFF_SELECTION | SF_RTF;
+
+ //get the number of pixels per logical inch
+ if (bRedraw) {
+ HDC hdc = GetDC(nullptr);
+ g_chatApi.logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY);
+ g_chatApi.logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX);
+ ReleaseDC(nullptr, hdc);
+ m_rtf.SetDraw(false);
+ bFlag = true;
+ }
+
+ // stream in the event(s)
+ streamData.lin = lin;
+ streamData.bRedraw = bRedraw;
+ 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))) {
+ CHARRANGE newsel;
+ newsel.cpMax = -1;
+ newsel.cpMin = sel.cpMin;
+ if (newsel.cpMin < 0)
+ newsel.cpMin = 0;
+
+ SMADD_RICHEDIT3 sm = {};
+ sm.cbSize = sizeof(sm);
+ sm.hwndRichEditControl = m_rtf.GetHwnd();
+ sm.Protocolname = si->pszModule;
+ sm.rangeToReplace = bRedraw ? nullptr : &newsel;
+ sm.disableRedraw = TRUE;
+ sm.hContact = si->hContact;
+ CallService(MS_SMILEYADD_REPLACESMILEYS, 0, (LPARAM)&sm);
+ }
+
+ // scroll log to bottom if the log was previously scrolled to bottom, else restore old position
+ if (bRedraw || (UINT)scroll.nPos >= (UINT)scroll.nMax - scroll.nPage - 5 || scroll.nMax - scroll.nMin - scroll.nPage < 50)
+ ScrollToBottom();
+ else
+ m_rtf.SendMsg(EM_SETSCROLLPOS, 0, (LPARAM)&point);
+
+ // do we need to restore the selection
+ if (oldsel.cpMax != oldsel.cpMin) {
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&oldsel);
+ m_rtf.SetDraw(true);
+ InvalidateRect(m_rtf.GetHwnd(), nullptr, TRUE);
+ }
+
+ // need to invalidate the window
+ if (bFlag) {
+ sel.cpMin = sel.cpMax = m_rtf.GetRichTextLength();
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+ m_rtf.SetDraw(true);
+ InvalidateRect(m_rtf.GetHwnd(), nullptr, TRUE);
+ }
}
- m_pDlg.m_hDbEventLast = streamData.hDbEventLast;
-}
+ /////////////////////////////////////////////////////////////////////////////////////////
-void CLogWindow::UpdateOptions()
-{
- if (m_pDlg.isChat())
- m_rtf.SendMsg(EM_SETBKGNDCOLOR, 0, g_Settings.crLogBackground);
- else {
- // configure message history for proper RTL formatting
- PARAFORMAT2 pf2;
- memset(&pf2, 0, sizeof(pf2));
- pf2.cbSize = sizeof(pf2);
-
- pf2.wEffects = PFE_RTLPARA;
- pf2.dwMask = PFM_RTLPARA;
- m_rtf.SendMsg(EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
-
- pf2.wEffects = 0;
- m_rtf.SendMsg(EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
-
- m_rtf.SendMsg(EM_SETLANGOPTIONS, 0, m_rtf.SendMsg(EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD);
- m_rtf.SendMsg(EM_SETBKGNDCOLOR, 0, g_plugin.getDword(SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR));
+ void UpdateOptions() override
+ {
+ if (m_pDlg.isChat())
+ m_rtf.SendMsg(EM_SETBKGNDCOLOR, 0, g_Settings.crLogBackground);
+ else {
+ // configure message history for proper RTL formatting
+ PARAFORMAT2 pf2;
+ memset(&pf2, 0, sizeof(pf2));
+ pf2.cbSize = sizeof(pf2);
+
+ pf2.wEffects = PFE_RTLPARA;
+ pf2.dwMask = PFM_RTLPARA;
+ m_rtf.SendMsg(EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
+
+ pf2.wEffects = 0;
+ m_rtf.SendMsg(EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
+
+ m_rtf.SendMsg(EM_SETLANGOPTIONS, 0, m_rtf.SendMsg(EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD);
+ m_rtf.SendMsg(EM_SETBKGNDCOLOR, 0, g_plugin.getDword(SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR));
+ }
}
-}
-/////////////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////////////////
-static const CHARRANGE rangeAll = { 0, -1 };
+ INT_PTR WndProc(UINT msg, WPARAM wParam, LPARAM lParam) override
+ {
+ CHARRANGE sel;
-INT_PTR CLogWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam)
-{
- CHARRANGE sel;
-
- switch (msg) {
- case WM_CONTEXTMENU:
- // we display context menu here only for private chats, group chats are processed by the core
- if (!m_pDlg.isChat()) {
- POINT pt;
- GetCursorPos(&pt);
-
- SetFocus(m_rtf.GetHwnd());
-
- HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_CONTEXT));
- HMENU hSubMenu = GetSubMenu(hMenu, 0);
- TranslateMenu(hSubMenu);
-
- CHARRANGE all = { 0, -1 };
- m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel);
- if (sel.cpMin == sel.cpMax)
- EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED);
-
- switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, m_pDlg.m_hwnd, nullptr)) {
- case IDM_COPY:
- m_rtf.SendMsg(WM_COPY, 0, 0);
- break;
- case IDM_COPYALL:
- m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&all);
- m_rtf.SendMsg(WM_COPY, 0, 0);
- m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
- break;
- case IDM_SELECTALL:
- m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&all);
- break;
- case IDM_CLEAR:
- Clear();
- m_pDlg.m_hDbEventFirst = 0;
- break;
+ switch (msg) {
+ case WM_CONTEXTMENU:
+ // we display context menu here only for private chats, group chats are processed by the core
+ if (!m_pDlg.isChat()) {
+ POINT pt;
+ GetCursorPos(&pt);
+
+ SetFocus(m_rtf.GetHwnd());
+
+ HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_CONTEXT));
+ HMENU hSubMenu = GetSubMenu(hMenu, 0);
+ TranslateMenu(hSubMenu);
+
+ CHARRANGE all = { 0, -1 };
+ m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel);
+ if (sel.cpMin == sel.cpMax)
+ EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED);
+
+ switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, m_pDlg.m_hwnd, nullptr)) {
+ case IDM_COPY:
+ m_rtf.SendMsg(WM_COPY, 0, 0);
+ break;
+ case IDM_COPYALL:
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&all);
+ m_rtf.SendMsg(WM_COPY, 0, 0);
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+ break;
+ case IDM_SELECTALL:
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&all);
+ break;
+ case IDM_CLEAR:
+ Clear();
+ m_pDlg.m_hDbEventFirst = 0;
+ break;
+ }
+ DestroyMenu(hSubMenu);
+ DestroyMenu(hMenu);
+ return TRUE;
}
- DestroyMenu(hSubMenu);
- DestroyMenu(hMenu);
- return TRUE;
- }
- break;
-
- case WM_LBUTTONUP:
- if (g_plugin.bAutoCopy) {
- m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel);
- if (sel.cpMin != sel.cpMax) {
- m_rtf.SendMsg(WM_COPY, 0, 0);
- sel.cpMin = sel.cpMax;
- m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+ break;
+
+ case WM_LBUTTONUP:
+ if (g_plugin.bAutoCopy) {
+ m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel);
+ if (sel.cpMin != sel.cpMax) {
+ m_rtf.SendMsg(WM_COPY, 0, 0);
+ sel.cpMin = sel.cpMax;
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+ }
+ SetFocus(m_pDlg.m_message.GetHwnd());
}
- SetFocus(m_pDlg.m_message.GetHwnd());
- }
- break;
-
- case WM_KEYDOWN:
- bool isShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
- bool isCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
- bool isAlt = (GetKeyState(VK_MENU) & 0x8000) != 0;
-
- if (wParam == 0x57 && isCtrl && !isAlt) { // ctrl-w (close window)
- m_pDlg.CloseTab();
- return TRUE;
+ break;
+
+ case WM_KEYDOWN:
+ bool isShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0;
+ bool isCtrl = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
+ bool isAlt = (GetKeyState(VK_MENU) & 0x8000) != 0;
+
+ if (wParam == 0x57 && isCtrl && !isAlt) { // ctrl-w (close window)
+ m_pDlg.CloseTab();
+ return TRUE;
+ }
+
+ if (m_pDlg.ProcessHotkeys(wParam, isShift, isCtrl, isAlt))
+ return FALSE;
}
- if (m_pDlg.ProcessHotkeys(wParam, isShift, isCtrl, isAlt))
- return FALSE;
+ return CSuper::WndProc(msg, wParam, lParam);
}
+};
- return CSuper::WndProc(msg, wParam, lParam);
+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;
}
-CSrmmLogWindow *logBuilder(CMsgDialog &pDlg)
+/////////////////////////////////////////////////////////////////////////////////////////
+// Module entry point
+
+CSrmmLogWindow* logBuilder(CMsgDialog &pDlg)
{
return new CLogWindow(pDlg);
}
diff --git a/src/core/stdmsg/src/msgs.h b/src/core/stdmsg/src/msgs.h
index 59458e220a..2dc98a0e66 100644
--- a/src/core/stdmsg/src/msgs.h
+++ b/src/core/stdmsg/src/msgs.h
@@ -31,23 +31,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define EVENTTYPE_JABBER_CHATSTATES 2000
#define EVENTTYPE_JABBER_PRESENCE 2001
-class CLogWindow : public CRtfLogWindow
-{
- typedef CRtfLogWindow CSuper;
-
-public:
- CLogWindow(CMsgDialog &pDlg) :
- CSuper(pDlg)
- {}
-
- void Attach() override;
- void LogEvents(MEVENT hDbEventFirst, int count, bool bAppend) override;
- void LogEvents(struct LOGINFO *, bool) override;
- void UpdateOptions() override;
-
- INT_PTR WndProc(UINT msg, WPARAM wParam, LPARAM lParam) override;
-};
-
class CMsgDialog : public CSrmmBaseDialog
{
friend class CLogWindow;
diff --git a/src/mir_app/src/db_events.cpp b/src/mir_app/src/db_events.cpp
index c3135bfa76..29436c5f51 100644
--- a/src/mir_app/src/db_events.cpp
+++ b/src/mir_app/src/db_events.cpp
@@ -91,14 +91,14 @@ MIR_APP_DLL(DBEVENTTYPEDESCR*) DbEvent_GetType(const char *szModule, int eventTy
/////////////////////////////////////////////////////////////////////////////////////////
-static wchar_t* getEventString(DBEVENTINFO *dbei, LPSTR &buf)
+static wchar_t* getEventString(const DB::EventInfo *dbei, LPSTR &buf)
{
LPSTR in = buf;
buf += mir_strlen(buf) + 1;
- return (dbei->flags & DBEF_UTF) ? mir_utf8decodeW(in) : mir_a2u(in);
+ return dbei->getString(in);
}
-static INT_PTR DbEventGetTextWorker(DB::EventInfo *dbei, int codepage, int datatype)
+static INT_PTR DbEventGetTextWorker(const DB::EventInfo *dbei, int codepage, int datatype)
{
if (dbei == nullptr || dbei->szModule == nullptr)
return 0;
@@ -205,12 +205,12 @@ static INT_PTR DbEventGetTextWorker(DB::EventInfo *dbei, int codepage, int datat
return 0;
}
-MIR_APP_DLL(char*) DbEvent_GetTextA(DBEVENTINFO *dbei, int codepage)
+MIR_APP_DLL(char*) DbEvent_GetTextA(const DBEVENTINFO *dbei, int codepage)
{
return (char*)DbEventGetTextWorker((DB::EventInfo *)dbei, codepage, DBVT_ASCIIZ);
}
-MIR_APP_DLL(wchar_t*) DbEvent_GetTextW(DBEVENTINFO *dbei, int codepage)
+MIR_APP_DLL(wchar_t*) DbEvent_GetTextW(const DBEVENTINFO *dbei, int codepage)
{
return (wchar_t*)DbEventGetTextWorker((DB::EventInfo *)dbei, codepage, DBVT_WCHAR);
}
diff --git a/src/mir_app/src/mir_app.def b/src/mir_app/src/mir_app.def
index d586c688c3..021694711d 100644
--- a/src/mir_app/src/mir_app.def
+++ b/src/mir_app/src/mir_app.def
@@ -849,3 +849,5 @@ Chat_IsMuted @941 NONAME
?getSize@FILE_BLOB@DB@@QBEIXZ @965 NONAME
?getTransferred@FILE_BLOB@DB@@QBEIXZ @966 NONAME
?getString@EventInfo@DB@@QBEPA_WPBD@Z @967 NONAME
+?InsertFileLink@CRtfLogWindow@@IAEXAAV?$CMStringT@DV?$ChTraitsCRT@D@@@@IABVFILE_BLOB@DB@@@Z @968 NONAME
+?GetDialog@CSrmmLogWindow@@QBEAAVCMsgDialog@@XZ @969 NONAME
diff --git a/src/mir_app/src/mir_app64.def b/src/mir_app/src/mir_app64.def
index 0d86eeb01a..b888eb1a3b 100644
--- a/src/mir_app/src/mir_app64.def
+++ b/src/mir_app/src/mir_app64.def
@@ -849,3 +849,5 @@ Chat_IsMuted @941 NONAME
?getSize@FILE_BLOB@DB@@QEBAIXZ @965 NONAME
?getTransferred@FILE_BLOB@DB@@QEBAIXZ @966 NONAME
?getString@EventInfo@DB@@QEBAPEA_WPEBD@Z @967 NONAME
+?InsertFileLink@CRtfLogWindow@@IEAAXAEAV?$CMStringT@DV?$ChTraitsCRT@D@@@@IAEBVFILE_BLOB@DB@@@Z @968 NONAME
+?GetDialog@CSrmmLogWindow@@QEBAAEAVCMsgDialog@@XZ @969 NONAME
diff --git a/src/mir_app/src/srmm_log_rtf.cpp b/src/mir_app/src/srmm_log_rtf.cpp
index dec151b43d..eae329a4f0 100644
--- a/src/mir_app/src/srmm_log_rtf.cpp
+++ b/src/mir_app/src/srmm_log_rtf.cpp
@@ -124,6 +124,31 @@ wchar_t* CRtfLogWindow::GetSelection()
/////////////////////////////////////////////////////////////////////////////////////////
+void CRtfLogWindow::InsertFileLink(CMStringA &buf, MEVENT hEvent, const DB::FILE_BLOB &blob)
+{
+ AppendUnicodeString(buf, TranslateT("Offline file"));
+ buf.Append(" {\\field{\\*\\fldinst HYPERLINK \"");
+ buf.AppendFormat("ofile:%ul", hEvent);
+ buf.Append("\"}{\\fldrslt{\\ul ");
+ AppendUnicodeString(buf, blob.getName());
+ buf.AppendFormat("}}} | %uKB", blob.getSize() / 1024);
+
+ CMStringA szHost;
+ if (const char *b = strstr(blob.getUrl(), "://"))
+ for (b = b + 3; *b != 0 && *b != '/' && *b != ':'; b++)
+ szHost.AppendChar(*b);
+
+ if (!szHost.IsEmpty())
+ buf.AppendFormat(" on %s", szHost.c_str());
+
+ if (blob.getSize() > 0 && blob.getSize() == blob.getTransferred()) {
+ buf.AppendChar(' ');
+ AppendUnicodeString(buf, TranslateT("Completed"));
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
INT_PTR CRtfLogWindow::Notify(WPARAM, LPARAM lParam)
{
LPNMHDR hdr = (LPNMHDR)lParam;