summaryrefslogtreecommitdiff
path: root/plugins
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 /plugins
parentaa5197082f1567e37b85911752b92a489d6515c3 (diff)
SRMM code unification
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Scriver/src/msgdialog.cpp9
-rw-r--r--plugins/Scriver/src/msglog.cpp718
-rw-r--r--plugins/Scriver/src/msgs.cpp4
-rw-r--r--plugins/Scriver/src/msgs.h27
-rw-r--r--plugins/Scriver/src/msgutils.cpp5
-rw-r--r--plugins/TabSRMM/src/msgdlgutils.cpp3
-rw-r--r--plugins/TabSRMM/src/msglog.cpp464
-rw-r--r--plugins/TabSRMM/src/msgs.h74
8 files changed, 626 insertions, 678 deletions
diff --git a/plugins/Scriver/src/msgdialog.cpp b/plugins/Scriver/src/msgdialog.cpp
index 4c6c1f9af0..4112c792de 100644
--- a/plugins/Scriver/src/msgdialog.cpp
+++ b/plugins/Scriver/src/msgdialog.cpp
@@ -171,10 +171,6 @@ bool CMsgDialog::OnInitDialog()
m_nTypeMode = PROTOTYPE_SELFTYPING_OFF;
timerType.Start(1000);
- m_lastEventType = -1;
- m_lastEventTime = time(0);
- m_startTime = time(0);
-
m_bUseRtl = g_plugin.getByte(m_hContact, "UseRTL", 0) != 0;
PARAFORMAT2 pf2;
@@ -434,7 +430,7 @@ void CMsgDialog::onClick_Quote(CCtrlButton*)
if (!dbei)
return;
- if (DbEventIsMessageOrCustom(&dbei)) {
+ if (DbEventIsMessageOrCustom(dbei)) {
buffer = DbEvent_GetTextW(&dbei, CP_ACP);
if (buffer != nullptr) {
CMStringW quotedBuffer(GetQuotedTextW(buffer));
@@ -1077,7 +1073,7 @@ INT_PTR CMsgDialog::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam)
while (hDbEvent != 0) {
DBEVENTINFO dbei = {};
db_event_get(hDbEvent, &dbei);
- if (!(dbei.flags & DBEF_SENT) && DbEventIsMessageOrCustom(&dbei))
+ if (!(dbei.flags & DBEF_SENT) && DbEventIsMessageOrCustom(dbei))
g_clistApi.pfnRemoveEvent(m_hContact, hDbEvent);
hDbEvent = db_event_next(m_hContact, hDbEvent);
}
@@ -1140,7 +1136,6 @@ INT_PTR CMsgDialog::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam)
return TRUE;
case DM_REMAKELOG:
- m_lastEventType = -1;
if (wParam == 0 || wParam == m_hContact)
m_pLog->LogEvents(m_hDbEventFirst, -1, 0);
diff --git a/plugins/Scriver/src/msglog.cpp b/plugins/Scriver/src/msglog.cpp
index 5bd6e406f7..0359c1cdf7 100644
--- a/plugins/Scriver/src/msglog.cpp
+++ b/plugins/Scriver/src/msglog.cpp
@@ -45,20 +45,22 @@ struct LogStreamData
size_t bufferOffset, bufferLen;
int eventsToInsert;
int isFirst;
- CMsgDialog *dlgDat;
+ class CLogWindow *pLog;
GlobalMessageData *gdat;
- EventData *events;
+ DB::EventInfo *dbei;
};
-bool DbEventIsCustomForMsgWindow(const DBEVENTINFO *dbei)
+static DWORD CALLBACK LogStreamInEvents(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb);
+
+bool DbEventIsCustomForMsgWindow(const DBEVENTINFO &dbei)
{
- DBEVENTTYPEDESCR *et = DbEvent_GetType(dbei->szModule, dbei->eventType);
+ DBEVENTTYPEDESCR *et = DbEvent_GetType(dbei.szModule, dbei.eventType);
return et && (et->flags & DETF_MSGWINDOW);
}
-bool DbEventIsMessageOrCustom(const DBEVENTINFO* dbei)
+bool DbEventIsMessageOrCustom(const DBEVENTINFO &dbei)
{
- return dbei->eventType == EVENTTYPE_MESSAGE || DbEventIsCustomForMsgWindow(dbei);
+ return dbei.eventType == EVENTTYPE_MESSAGE || dbei.eventType == EVENTTYPE_FILE || DbEventIsCustomForMsgWindow(dbei);
}
bool DbEventIsShown(const DBEVENTINFO &dbei)
@@ -73,107 +75,15 @@ bool DbEventIsShown(const DBEVENTINFO &dbei)
return 0;
}
- return DbEventIsCustomForMsgWindow(&dbei);
-}
-
-EventData* CMsgDialog::GetEventFromDB(MCONTACT hContact, MEVENT hDbEvent)
-{
- DB::EventInfo dbei(hDbEvent);
- if (!dbei)
- return nullptr;
-
- if (!DbEventIsShown(dbei))
- return nullptr;
-
- EventData *evt = (EventData*)mir_calloc(sizeof(EventData));
- evt->custom = DbEventIsCustomForMsgWindow(&dbei);
- if (!(dbei.flags & DBEF_SENT) && (dbei.eventType == EVENTTYPE_MESSAGE || evt->custom)) {
- db_event_markRead(hContact, hDbEvent);
- g_clistApi.pfnRemoveEvent(hContact, hDbEvent);
- }
- else if (dbei.eventType == EVENTTYPE_JABBER_CHATSTATES || dbei.eventType == EVENTTYPE_JABBER_PRESENCE)
- db_event_markRead(hContact, hDbEvent);
-
- evt->eventType = dbei.eventType;
- evt->dwFlags = (dbei.flags & DBEF_READ ? IEEDF_READ : 0) | (dbei.flags & DBEF_SENT ? IEEDF_SENT : 0) | (dbei.flags & DBEF_RTL ? IEEDF_RTL : 0);
- evt->dwFlags |= IEEDF_UNICODE_TEXT | IEEDF_UNICODE_NICK;
-
- if (m_bUseRtl)
- evt->dwFlags |= IEEDF_RTL;
-
- evt->time = dbei.timestamp;
- evt->szNick.w = nullptr;
- if (evt->dwFlags & IEEDF_SENT)
- evt->szNick.w = Contact::GetInfo(CNF_DISPLAY, 0, m_szProto);
- else
- evt->szNick.w = mir_wstrdup(Clist_GetContactDisplayName(hContact));
-
- evt->szText.w = DbEvent_GetTextW(&dbei, CP_UTF8);
-
- if (!m_bUseRtl && Utils_IsRtl(evt->szText.w))
- evt->dwFlags |= IEEDF_RTL;
-
- return evt;
-}
-
-static EventData* GetTestEvent(uint32_t flags)
-{
- EventData *evt = (EventData *)mir_calloc(sizeof(EventData));
- evt->eventType = EVENTTYPE_MESSAGE;
- evt->dwFlags = IEEDF_READ | flags;
- evt->dwFlags |= IEEDF_UNICODE_TEXT | IEEDF_UNICODE_NICK;
- evt->time = time(0);
- return evt;
+ return DbEventIsCustomForMsgWindow(dbei);
}
-static EventData* GetTestEvents()
+static void AppendUnicodeToBuffer(CMStringA &buf, const wchar_t *line)
{
- EventData *evt, *firstEvent, *prevEvent;
- firstEvent = prevEvent = evt = GetTestEvent(IEEDF_SENT);
- evt->szNick.w = mir_wstrdup(TranslateT("Me"));
- evt->szText.w = mir_wstrdup(TranslateT("O Lord, bless this Thy hand grenade that with it Thou mayest blow Thine enemies"));
-
- evt = GetTestEvent(IEEDF_SENT);
- evt->szNick.w = mir_wstrdup(TranslateT("Me"));
- evt->szText.w = mir_wstrdup(TranslateT("to tiny bits, in Thy mercy"));
- prevEvent->next = evt;
- prevEvent = evt;
-
- evt = GetTestEvent(0);
- evt->szNick.w = mir_wstrdup(TranslateT("My contact"));
- evt->szText.w = mir_wstrdup(TranslateT("Lorem ipsum dolor sit amet,"));
- prevEvent->next = evt;
- prevEvent = evt;
-
- evt = GetTestEvent(0);
- evt->szNick.w = mir_wstrdup(TranslateT("My contact"));
- evt->szText.w = mir_wstrdup(TranslateT("consectetur adipisicing elit"));
- prevEvent->next = evt;
- prevEvent = evt;
- return firstEvent;
-}
+ buf.Append("{\\uc1 ");
-static void freeEvent(EventData *evt)
-{
- mir_free(evt->szNick.w);
- mir_free(evt->szText.w);
- mir_free(evt);
-}
-
-static int AppendUnicodeOrAnsiiToBufferL(CMStringA &buf, const wchar_t *line, size_t maxLen, BOOL isAnsii)
-{
- if (maxLen == -1)
- maxLen = mir_wstrlen(line);
-
- const wchar_t *maxLine = line + maxLen;
-
- if (isAnsii)
- buf.Append("{");
- else
- buf.Append("{\\uc1 ");
-
- int wasEOL = 0, textCharsCount = 0;
- for (; line < maxLine; line++, textCharsCount++) {
+ int wasEOL = 0;
+ for (; *line; line++) {
wasEOL = 0;
if (*line == '\r' && line[1] == '\n') {
buf.Append("\\line ");
@@ -194,9 +104,6 @@ static int AppendUnicodeOrAnsiiToBufferL(CMStringA &buf, const wchar_t *line, si
else if (*line < 128) {
buf.AppendChar((char)*line);
}
- else if (isAnsii) {
- buf.AppendFormat("\\'%02x", (*line) & 0xFF);
- }
else {
buf.AppendFormat("\\u%d ?", *line);
}
@@ -205,18 +112,6 @@ static int AppendUnicodeOrAnsiiToBufferL(CMStringA &buf, const wchar_t *line, si
buf.AppendChar(' ');
buf.AppendChar('}');
-
- return textCharsCount;
-}
-
-static int AppendAnsiToBuffer(CMStringA &buf, const char *line)
-{
- return AppendUnicodeOrAnsiiToBufferL(buf, _A2T(line), -1, true);
-}
-
-static int AppendUnicodeToBuffer(CMStringA &buf, const wchar_t *line)
-{
- return AppendUnicodeOrAnsiiToBufferL(buf, line, -1, false);
}
// mir_free() the return value
@@ -333,276 +228,22 @@ int isSameDate(time_t time1, time_t time2)
return 0;
}
-static void AppendWithCustomLinks(EventData *evt, int style, CMStringA &buf)
+static void AppendWithCustomLinks(DBEVENTINFO &dbei, int style, CMStringA &buf)
{
- if (evt->szText.w == nullptr)
+ if (dbei.pBlob == nullptr)
return;
- BOOL isAnsii = (evt->dwFlags & IEEDF_UNICODE_TEXT) == 0;
wchar_t *wText;
- size_t len;
- if (isAnsii) {
- len = mir_strlen(evt->szText.a);
- wText = mir_a2u(evt->szText.a);
- }
- else {
- wText = evt->szText.w;
- len = (int)mir_wstrlen(evt->szText.w);
- }
-
- if (len > 0) {
- buf.AppendFormat("%s ", SetToStyle(style));
- AppendUnicodeOrAnsiiToBufferL(buf, wText, len, isAnsii);
- }
-
- if (isAnsii)
- mir_free(wText);
-}
-
-// mir_free() the return value
-char* CMsgDialog::CreateRTFFromEvent(EventData *evt, GlobalMessageData *gdat, LogStreamData *streamData)
-{
- int style, showColon = 0;
- int isGroupBreak = TRUE;
- int highlight = 0;
-
- if ((gdat->flags.bGroupMessages) && evt->dwFlags == LOWORD(m_lastEventType) &&
- evt->eventType == EVENTTYPE_MESSAGE && HIWORD(m_lastEventType) == EVENTTYPE_MESSAGE &&
- (isSameDate(evt->time, m_lastEventTime)) && ((((int)evt->time < m_startTime) == (m_lastEventTime < m_startTime)) || !(evt->dwFlags & IEEDF_READ))) {
- isGroupBreak = FALSE;
- }
-
- CMStringA buf;
- if (!streamData->isFirst && !m_isMixed) {
- if (isGroupBreak || gdat->flags.bMarkFollowups)
- buf.Append("\\par");
- else
- buf.Append("\\line");
- }
-
- if (evt->dwFlags & IEEDF_RTL)
- 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((evt->dwFlags & IEEDF_RTL) ? "\\rtlpar" : "\\ltrpar");
-
- if (evt->eventType == EVENTTYPE_MESSAGE)
- highlight = fontOptionsListSize + 2 + ((evt->dwFlags & IEEDF_SENT) ? 1 : 0);
+ if ((dbei.flags & DBEF_UTF) == 0)
+ wText = mir_a2u((char*)dbei.pBlob);
else
- highlight = fontOptionsListSize + 1;
-
- buf.AppendFormat("\\highlight%d\\cf%d", highlight, highlight);
- if (!streamData->isFirst && m_isMixed) {
- if (isGroupBreak)
- buf.Append("\\sl-1 \\par\\sl0");
- else
- buf.Append("\\sl-1 \\line\\sl0");
- }
- streamData->isFirst = FALSE;
- if (m_isMixed) {
- if (evt->dwFlags & IEEDF_RTL)
- buf.Append("\\ltrch\\rtlch");
- else
- buf.Append("\\rtlch\\ltrch");
- }
- if ((gdat->flags.bShowIcons) && isGroupBreak) {
- int i = LOGICON_MSG_NOTICE;
-
- switch (evt->eventType) {
- case EVENTTYPE_MESSAGE:
- if (evt->dwFlags & IEEDF_SENT)
- i = LOGICON_MSG_OUT;
- else
- i = LOGICON_MSG_IN;
- break;
-
- default:
- i = LOGICON_MSG_NOTICE;
- break;
- }
-
- buf.Append("\\fs1 ");
- buf.Append(pLogIconBmpBits[i]);
- buf.AppendChar(' ');
- }
-
- if (gdat->flags.bShowTime && (evt->eventType != EVENTTYPE_MESSAGE ||
- (gdat->flags.bMarkFollowups || isGroupBreak || !(gdat->flags.bGroupMessages)))) {
- wchar_t *timestampString = nullptr;
- if (gdat->flags.bGroupMessages && evt->eventType == EVENTTYPE_MESSAGE) {
- if (isGroupBreak) {
- if (!gdat->flags.bMarkFollowups)
- timestampString = TimestampToString(gdat->flags, evt->time, 0);
- else if (gdat->flags.bShowDate)
- timestampString = TimestampToString(gdat->flags, evt->time, 1);
- }
- else if (gdat->flags.bMarkFollowups)
- timestampString = TimestampToString(gdat->flags, evt->time, 2);
- }
- else timestampString = TimestampToString(gdat->flags, evt->time, 0);
-
- if (timestampString != nullptr) {
- buf.AppendFormat("%s ", SetToStyle(evt->dwFlags & IEEDF_SENT ? MSGFONTID_MYTIME : MSGFONTID_YOURTIME));
- AppendUnicodeToBuffer(buf, timestampString);
- }
- if (evt->eventType != EVENTTYPE_MESSAGE)
- buf.AppendFormat("%s: ", SetToStyle(evt->dwFlags & IEEDF_SENT ? MSGFONTID_MYCOLON : MSGFONTID_YOURCOLON));
- showColon = 1;
- }
- if ((!(gdat->flags.bHideNames) && evt->eventType == EVENTTYPE_MESSAGE && isGroupBreak) || evt->eventType == EVENTTYPE_JABBER_CHATSTATES || evt->eventType == EVENTTYPE_JABBER_PRESENCE) {
- if (evt->eventType == EVENTTYPE_MESSAGE) {
- if (showColon)
- buf.AppendFormat(" %s ", SetToStyle(evt->dwFlags & IEEDF_SENT ? MSGFONTID_MYNAME : MSGFONTID_YOURNAME));
- else
- buf.AppendFormat("%s ", SetToStyle(evt->dwFlags & IEEDF_SENT ? MSGFONTID_MYNAME : MSGFONTID_YOURNAME));
- }
- else buf.AppendFormat("%s ", SetToStyle(MSGFONTID_NOTICE));
-
- if (evt->dwFlags & IEEDF_UNICODE_NICK)
- AppendUnicodeToBuffer(buf, evt->szNick.w);
- else
- AppendAnsiToBuffer(buf, evt->szNick.a);
-
- showColon = 1;
- if (evt->eventType == EVENTTYPE_MESSAGE && gdat->flags.bGroupMessages) {
- if (gdat->flags.bMarkFollowups)
- buf.Append("\\par");
- else
- buf.Append("\\line");
- showColon = 0;
- }
- }
+ wText = mir_utf8decodeW((char *)dbei.pBlob);
- if (gdat->flags.bShowTime && gdat->flags.bGroupMessages && gdat->flags.bMarkFollowups && evt->eventType == EVENTTYPE_MESSAGE && isGroupBreak) {
- buf.AppendFormat(" %s ", SetToStyle(evt->dwFlags & IEEDF_SENT ? MSGFONTID_MYTIME : MSGFONTID_YOURTIME));
- AppendUnicodeToBuffer(buf, TimestampToString(gdat->flags, evt->time, 2));
- showColon = 1;
- }
- if (showColon && evt->eventType == EVENTTYPE_MESSAGE) {
- if (evt->dwFlags & IEEDF_RTL)
- buf.AppendFormat("\\~%s: ", SetToStyle(evt->dwFlags & IEEDF_SENT ? MSGFONTID_MYCOLON : MSGFONTID_YOURCOLON));
- else
- buf.AppendFormat("%s: ", SetToStyle(evt->dwFlags & IEEDF_SENT ? MSGFONTID_MYCOLON : MSGFONTID_YOURCOLON));
- }
- switch (evt->eventType) {
- case EVENTTYPE_JABBER_CHATSTATES:
- case EVENTTYPE_JABBER_PRESENCE:
- case EVENTTYPE_FILE:
- style = MSGFONTID_NOTICE;
+ if (wText) {
buf.AppendFormat("%s ", SetToStyle(style));
- if (evt->eventType == EVENTTYPE_FILE) {
- if (evt->dwFlags & IEEDF_SENT)
- AppendUnicodeToBuffer(buf, TranslateT("File sent"));
- else
- AppendUnicodeToBuffer(buf, TranslateT("File received"));
- AppendUnicodeToBuffer(buf, L":");
- }
- AppendUnicodeToBuffer(buf, L" ");
-
- if (evt->szText.w != nullptr) {
- if (evt->dwFlags & IEEDF_UNICODE_TEXT)
- AppendUnicodeToBuffer(buf, evt->szText.w);
- else
- AppendAnsiToBuffer(buf, evt->szText.a);
- }
- break;
-
- default:
- if (gdat->flags.bMsgOnNewline && showColon)
- buf.Append("\\line");
-
- style = evt->dwFlags & IEEDF_SENT ? MSGFONTID_MYMSG : MSGFONTID_YOURMSG;
- AppendWithCustomLinks(evt, style, buf);
- break;
- }
-
- if (m_isMixed)
- buf.Append("\\par");
-
- m_lastEventTime = evt->time;
- m_lastEventType = MAKELONG(evt->dwFlags, evt->eventType);
- return buf.Detach();
-}
-
-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:
- if (dat->events != nullptr) {
- EventData *evt = dat->events;
- dat->buffer = nullptr;
- dat->buffer = dat->dlgDat->CreateRTFFromEvent(evt, dat->gdat, dat);
- dat->events = evt->next;
- freeEvent(evt);
- }
- else if (dat->eventsToInsert) {
- do {
- EventData *evt = dat->dlgDat->GetEventFromDB(dat->hContact, dat->hDbEvent);
- dat->buffer = nullptr;
- if (evt != nullptr) {
- dat->buffer = dat->dlgDat->CreateRTFFromEvent(evt, dat->gdat, dat);
- freeEvent(evt);
- }
- 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;
+ AppendUnicodeToBuffer(buf, wText);
+ mir_free(wText);
}
- return 0;
-}
-
-void StreamInTestEvents(HWND hEditWnd, GlobalMessageData *gdat)
-{
- CMsgDialog *dat = new CMsgDialog(0, false);
-
- LogStreamData streamData = { 0 };
- streamData.isFirst = TRUE;
- streamData.events = GetTestEvents();
- streamData.dlgDat = dat;
- streamData.gdat = gdat;
-
- 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);
-
- delete dat;
}
#define RTFPICTHEADERMAXSIZE 78
@@ -691,10 +332,21 @@ class CLogWindow : public CRtfLogWindow
{
typedef CRtfLogWindow CSuper;
+ int m_isMixed = 0;
+ int m_lastEventType = -1;
+ time_t m_startTime, m_lastEventTime;
+
public:
CLogWindow(CMsgDialog &pDlg) :
CSuper(pDlg)
- {}
+ {
+ m_lastEventTime = m_startTime = time(0);
+ }
+
+ void AppendUnicodeString(CMStringA &str, const wchar_t *pwszBuf) override
+ {
+ AppendUnicodeToBuffer(str, pwszBuf);
+ }
void Attach() override
{
@@ -726,8 +378,191 @@ public:
m_rtf.SendMsg(EM_AUTOURLDETECT, TRUE, 0);
}
+ char* CreateRTFFromEvent(DB::EventInfo &dbei, LogStreamData *streamData)
+ {
+ int style, showColon = 0;
+ int isGroupBreak = TRUE;
+ int highlight = 0;
+ auto *gdat = streamData->gdat;
+
+ if ((gdat->flags.bGroupMessages) && dbei.flags == LOWORD(m_lastEventType) &&
+ dbei.eventType == EVENTTYPE_MESSAGE && HIWORD(m_lastEventType) == EVENTTYPE_MESSAGE &&
+ (isSameDate(dbei.timestamp, m_lastEventTime)) && ((((int)dbei.timestamp < m_startTime) == (m_lastEventTime < m_startTime)) || !(dbei.flags & DBEF_READ))) {
+ isGroupBreak = FALSE;
+ }
+
+ ptrW wszText(DbEvent_GetTextW(&dbei, CP_UTF8)), wszNick;
+
+ // test contact
+ if (m_pDlg.m_hContact != 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));
+ }
+ 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");
+ else
+ buf.Append("\\line");
+ }
+
+ if (dbei.flags & DBEF_RTL)
+ 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");
+
+ if (dbei.eventType == EVENTTYPE_MESSAGE)
+ highlight = fontOptionsListSize + 2 + ((dbei.flags & DBEF_SENT) ? 1 : 0);
+ else
+ highlight = fontOptionsListSize + 1;
+
+ buf.AppendFormat("\\highlight%d\\cf%d", highlight, highlight);
+ if (!streamData->isFirst && m_isMixed) {
+ if (isGroupBreak)
+ buf.Append("\\sl-1 \\par\\sl0");
+ else
+ buf.Append("\\sl-1 \\line\\sl0");
+ }
+ streamData->isFirst = FALSE;
+ if (m_isMixed) {
+ if (dbei.flags & DBEF_RTL)
+ buf.Append("\\ltrch\\rtlch");
+ else
+ buf.Append("\\rtlch\\ltrch");
+ }
+ if ((gdat->flags.bShowIcons) && isGroupBreak) {
+ int i = LOGICON_MSG_NOTICE;
+
+ switch (dbei.eventType) {
+ case EVENTTYPE_MESSAGE:
+ if (dbei.flags & DBEF_SENT)
+ i = LOGICON_MSG_OUT;
+ else
+ i = LOGICON_MSG_IN;
+ break;
+
+ default:
+ i = LOGICON_MSG_NOTICE;
+ break;
+ }
+
+ buf.Append("\\fs1 ");
+ buf.Append(pLogIconBmpBits[i]);
+ buf.AppendChar(' ');
+ }
+
+ if (gdat->flags.bShowTime && (dbei.eventType != EVENTTYPE_MESSAGE ||
+ (gdat->flags.bMarkFollowups || isGroupBreak || !(gdat->flags.bGroupMessages)))) {
+ wchar_t *timestampString = nullptr;
+ if (gdat->flags.bGroupMessages && dbei.eventType == EVENTTYPE_MESSAGE) {
+ if (isGroupBreak) {
+ if (!gdat->flags.bMarkFollowups)
+ timestampString = TimestampToString(gdat->flags, dbei.timestamp, 0);
+ else if (gdat->flags.bShowDate)
+ timestampString = TimestampToString(gdat->flags, dbei.timestamp, 1);
+ }
+ else if (gdat->flags.bMarkFollowups)
+ timestampString = TimestampToString(gdat->flags, dbei.timestamp, 2);
+ }
+ else timestampString = TimestampToString(gdat->flags, dbei.timestamp, 0);
+
+ if (timestampString != nullptr) {
+ buf.AppendFormat("%s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYTIME : MSGFONTID_YOURTIME));
+ AppendUnicodeToBuffer(buf, timestampString);
+ }
+ if (dbei.eventType != EVENTTYPE_MESSAGE)
+ buf.AppendFormat("%s: ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYCOLON : MSGFONTID_YOURCOLON));
+ showColon = 1;
+ }
+ if ((!(gdat->flags.bHideNames) && dbei.eventType == EVENTTYPE_MESSAGE && isGroupBreak) || dbei.eventType == EVENTTYPE_JABBER_CHATSTATES || dbei.eventType == EVENTTYPE_JABBER_PRESENCE) {
+ if (dbei.eventType == EVENTTYPE_MESSAGE) {
+ if (showColon)
+ buf.AppendFormat(" %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYNAME : MSGFONTID_YOURNAME));
+ else
+ buf.AppendFormat("%s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYNAME : MSGFONTID_YOURNAME));
+ }
+ else buf.AppendFormat("%s ", SetToStyle(MSGFONTID_NOTICE));
+
+ AppendUnicodeToBuffer(buf, wszNick);
+
+ showColon = 1;
+ if (dbei.eventType == EVENTTYPE_MESSAGE && gdat->flags.bGroupMessages) {
+ if (gdat->flags.bMarkFollowups)
+ buf.Append("\\par");
+ else
+ buf.Append("\\line");
+ showColon = 0;
+ }
+ }
+
+ if (gdat->flags.bShowTime && gdat->flags.bGroupMessages && gdat->flags.bMarkFollowups && dbei.eventType == EVENTTYPE_MESSAGE && isGroupBreak) {
+ buf.AppendFormat(" %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYTIME : MSGFONTID_YOURTIME));
+ AppendUnicodeToBuffer(buf, TimestampToString(gdat->flags, dbei.timestamp, 2));
+ showColon = 1;
+ }
+ if (showColon && dbei.eventType == EVENTTYPE_MESSAGE) {
+ if (dbei.flags & DBEF_RTL)
+ 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));
+ }
+ switch (dbei.eventType) {
+ case EVENTTYPE_JABBER_CHATSTATES:
+ case EVENTTYPE_JABBER_PRESENCE:
+ case EVENTTYPE_FILE:
+ style = MSGFONTID_NOTICE;
+ buf.AppendFormat("%s ", SetToStyle(style));
+ if (dbei.eventType == EVENTTYPE_FILE) {
+ DB::FILE_BLOB blob(dbei);
+ if (blob.isOffline()) {
+ InsertFileLink(buf, streamData->hDbEvent, blob);
+ break;
+ }
+
+ if (dbei.flags & DBEF_SENT)
+ AppendUnicodeToBuffer(buf, TranslateT("File sent"));
+ else
+ AppendUnicodeToBuffer(buf, TranslateT("File received"));
+ AppendUnicodeToBuffer(buf, L":");
+ }
+ AppendUnicodeToBuffer(buf, L" ");
+
+ if (wszText != nullptr)
+ AppendUnicodeToBuffer(buf, wszText);
+ break;
+
+ default:
+ if (gdat->flags.bMsgOnNewline && showColon)
+ buf.Append("\\line");
+
+ style = dbei.flags & DBEF_SENT ? MSGFONTID_MYMSG : MSGFONTID_YOURMSG;
+ AppendWithCustomLinks(dbei, style, buf);
+ break;
+ }
+
+ if (m_isMixed)
+ buf.Append("\\par");
+
+ m_lastEventTime = dbei.timestamp;
+ m_lastEventType = MAKELONG(dbei.flags, dbei.eventType);
+ return buf.Detach();
+ }
+
void LogEvents(MEVENT hDbEventFirst, int count, bool bAppend) override
{
+ if (!bAppend)
+ m_lastEventType = -1;
+
CHARRANGE oldSel, sel;
m_rtf.SetDraw(false);
m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&oldSel);
@@ -736,7 +571,7 @@ public:
streamData.hContact = m_pDlg.m_hContact;
streamData.hDbEvent = hDbEventFirst;
streamData.hDbEventLast = m_pDlg.m_hDbEventLast;
- streamData.dlgDat = &m_pDlg;
+ streamData.pLog = this;
streamData.eventsToInsert = count;
streamData.isFirst = bAppend ? m_rtf.GetRichTextLength() == 0 : 1;
streamData.gdat = &g_dat;
@@ -774,7 +609,7 @@ public:
sel.cpMax = m_rtf.GetRichTextLength();
m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
fi.chrg.cpMin = 0;
- m_pDlg.m_isMixed = 0;
+ m_isMixed = 0;
}
m_rtf.SendMsg(EM_STREAMIN, bAppend ? SFF_SELECTION | SF_RTF : SFF_SELECTION | SF_RTF, (LPARAM)&stream);
@@ -817,6 +652,8 @@ public:
m_pDlg.m_hDbEventLast = streamData.hDbEventLast;
}
+ ////////////////////////////////////////////////////////////////////////////////////////
+
void LogEvents(struct LOGINFO *lin, bool bRedraw) override
{
auto *si = m_pDlg.m_si;
@@ -982,6 +819,121 @@ 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 || DbEventIsCustomForMsgWindow(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);
+ }
+
+ 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)
+{
+ DB::EventInfo dbei;
+ dbei.flags = DBEF_UTF;
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.timestamp = time(0);
+ dbei.szModule = SRMM_MODULE;
+
+ CMsgDialog *dat = new CMsgDialog(0, false);
+
+ LogStreamData streamData = {};
+ streamData.isFirst = TRUE;
+ streamData.dbei = &dbei;
+ streamData.pLog = new CLogWindow(*dat);
+ streamData.gdat = gdat;
+
+ 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);
+
+ delete streamData.pLog;
+ delete dat;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Module entry point
+
CSrmmLogWindow* logBuilder(CMsgDialog &pDlg)
{
return new CLogWindow(pDlg);
diff --git a/plugins/Scriver/src/msgs.cpp b/plugins/Scriver/src/msgs.cpp
index 498dfe43e3..b3e0026f77 100644
--- a/plugins/Scriver/src/msgs.cpp
+++ b/plugins/Scriver/src/msgs.cpp
@@ -91,7 +91,7 @@ static int MessageEventAdded(WPARAM hContact, LPARAM hDbEvent)
if (dbei.eventType == EVENTTYPE_MESSAGE && (dbei.flags & DBEF_READ))
return 0;
- if (dbei.flags & DBEF_SENT || !DbEventIsMessageOrCustom(&dbei))
+ if (dbei.flags & DBEF_SENT || !DbEventIsMessageOrCustom(dbei))
return 0;
/* does a window for the contact exist? */
@@ -239,7 +239,7 @@ static void RestoreUnreadMessageAlerts(void)
DBEVENTINFO dbei = {};
if (db_event_get(hDbEvent, &dbei))
continue;
- if (dbei.markedRead() || !DbEventIsMessageOrCustom(&dbei) || !Proto_GetBaseAccountName(hContact))
+ if (dbei.markedRead() || !DbEventIsMessageOrCustom(dbei) || !Proto_GetBaseAccountName(hContact))
continue;
int windowAlreadyExists = Srmm_FindWindow(hContact) != nullptr;
diff --git a/plugins/Scriver/src/msgs.h b/plugins/Scriver/src/msgs.h
index 3daa951eea..ce0e5c082c 100644
--- a/plugins/Scriver/src/msgs.h
+++ b/plugins/Scriver/src/msgs.h
@@ -29,23 +29,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MSGERROR_RETRY 1
#define MSGERROR_DONE 2
-struct EventData
-{
- int cbSize;
- int iType;
- uint32_t dwFlags;
- const char *fontName;
- int fontSize;
- int fontStyle;
- COLORREF color;
- MAllStrings szNick; // Nick, usage depends on type of event
- MAllStrings szText; // Text, usage depends on type of event
- uint32_t time;
- uint32_t eventType;
- BOOL custom;
- EventData *next;
-};
-
struct ToolbarButton
{
wchar_t *name;
@@ -97,9 +80,6 @@ class CMsgDialog : public CSrmmBaseDialog
HICON m_hStatusIcon, m_hStatusIconBig, m_hStatusIconOverlay;
char *m_szProto;
- time_t m_startTime, m_lastEventTime;
- int m_lastEventType;
- int m_isMixed;
bool m_bUseRtl;
HBITMAP m_hbmpAvatarPic;
@@ -192,9 +172,6 @@ public:
wchar_t *m_wszInitialText;
- char* CreateRTFFromEvent(EventData *evt, GlobalMessageData *gdat, struct LogStreamData *streamData);
- EventData *GetEventFromDB(MCONTACT hContact, MEVENT hDbEvent);
-
void Reattach(HWND hwndContainer);
};
@@ -216,8 +193,8 @@ public:
#define EVENTTYPE_JABBER_PRESENCE 2001
bool DbEventIsShown(const DBEVENTINFO &dbei);
-bool DbEventIsCustomForMsgWindow(const DBEVENTINFO *dbei);
-bool DbEventIsMessageOrCustom(const DBEVENTINFO *dbei);
+bool DbEventIsCustomForMsgWindow(const DBEVENTINFO &dbei);
+bool DbEventIsMessageOrCustom(const DBEVENTINFO &dbei);
void LoadMsgLogIcons(void);
void FreeMsgLogIcons(void);
int IsAutoPopup(MCONTACT hContact);
diff --git a/plugins/Scriver/src/msgutils.cpp b/plugins/Scriver/src/msgutils.cpp
index dff0e00e10..b2abbe2a55 100644
--- a/plugins/Scriver/src/msgutils.cpp
+++ b/plugins/Scriver/src/msgutils.cpp
@@ -28,7 +28,6 @@ void CMsgDialog::ClearLog()
CSuper::ClearLog();
m_hDbEventFirst = 0;
- m_lastEventType = -1;
}
void CMsgDialog::CloseTab()
@@ -102,7 +101,7 @@ void CMsgDialog::EventAdded(MEVENT hDbEvent, const DBEVENTINFO &dbei)
else
SendMessage(m_hwnd, DM_REMAKELOG, 0, 0);
- if (!(dbei.flags & DBEF_SENT) && !DbEventIsCustomForMsgWindow(&dbei)) {
+ if (!(dbei.flags & DBEF_SENT) && !DbEventIsCustomForMsgWindow(dbei)) {
if (!bIsActive) {
m_iShowUnread = 1;
UpdateIcon();
@@ -124,7 +123,7 @@ bool CMsgDialog::GetFirstEvent()
if (m_hDbEventFirst != 0) {
DBEVENTINFO dbei = {};
db_event_get(m_hDbEventFirst, &dbei);
- if (DbEventIsMessageOrCustom(&dbei) && !(dbei.flags & DBEF_READ) && !(dbei.flags & DBEF_SENT))
+ if (DbEventIsMessageOrCustom(dbei) && !(dbei.flags & DBEF_READ) && !(dbei.flags & DBEF_SENT))
notifyUnread = true;
}
diff --git a/plugins/TabSRMM/src/msgdlgutils.cpp b/plugins/TabSRMM/src/msgdlgutils.cpp
index eff4705074..f3ed376965 100644
--- a/plugins/TabSRMM/src/msgdlgutils.cpp
+++ b/plugins/TabSRMM/src/msgdlgutils.cpp
@@ -320,6 +320,9 @@ bool IsStringValidLink(wchar_t *pszText)
if (pszText[0] == '\\' && pszText[1] == '\\')
return true;
+ if (!mir_wstrncmp(pszText, L"ofile:", 6))
+ return true;
+
if (mir_wstrlen(pszText) < 5 || wcschr(pszText, '"'))
return false;
diff --git a/plugins/TabSRMM/src/msglog.cpp b/plugins/TabSRMM/src/msglog.cpp
index 3499e97cc3..36c76a92ad 100644
--- a/plugins/TabSRMM/src/msglog.cpp
+++ b/plugins/TabSRMM/src/msglog.cpp
@@ -94,7 +94,7 @@ struct LogStreamData
int eventsToInsert;
int isEmpty;
int isAppend;
- CMsgDialog *dlgDat;
+ class CLogWindow *pLog;
DBEVENTINFO *dbei;
};
@@ -234,12 +234,11 @@ static int TSAPI GetColorIndex(char *rtffont)
return 0;
}
-static int AppendUnicodeToBuffer(CMStringA &str, const wchar_t *line, int mode)
+static void AppendUnicodeToBuffer(CMStringA &str, const wchar_t *line, int mode)
{
str.Append("{\\uc1 ");
- int textCharsCount = 0;
- for (; *line; line++, textCharsCount++) {
+ for (; *line; line++) {
if (*line == 127 && line[1] != 0) {
wchar_t code = line[2];
if (((code == '0' || code == '1') && line[3] == ' ') || (line[1] == 'c' && code == 'x')) {
@@ -302,17 +301,19 @@ static int AppendUnicodeToBuffer(CMStringA &str, const wchar_t *line, int mode)
}
str.AppendChar('}');
- return textCharsCount;
}
/////////////////////////////////////////////////////////////////////////////////////////
+// mir_free() the return value
-static void Build_RTF_Header(CMStringA &str, CMsgDialog *dat)
+static char* CreateRTFHeader(CLogWindow *pLog)
{
int i;
- LOGFONTW *logFonts = dat->m_pContainer->m_theme.logFonts;
- COLORREF *fontColors = dat->m_pContainer->m_theme.fontColors;
- TLogTheme *theme = &dat->m_pContainer->m_theme;
+ 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");
@@ -359,15 +360,8 @@ static void Build_RTF_Header(CMStringA &str, CMsgDialog *dat)
str.AppendFormat("}");
// indent
- if (!(dat->m_dwFlags & MWF_LOG_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);
-}
-
-// mir_free() the return value
-static char* CreateRTFHeader(CMsgDialog *dat)
-{
- CMStringA str;
- Build_RTF_Header(str, dat);
return str.Detach();
}
@@ -425,7 +419,212 @@ bool DbEventIsForMsgWindow(const DBEVENTINFO *dbei)
return et && (et->flags & DETF_MSGWINDOW);
}
-static char* Template_CreateRTFFromDbEvent(CMsgDialog *dat, MCONTACT hContact, MEVENT hDbEvent, LogStreamData *streamData)
+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)
+{
+ bool isCtrl, isShift, isAlt;
+
+ switch (msg) {
+ case WM_KILLFOCUS:
+ if (wParam != (WPARAM)m_rtf.GetHwnd() && 0 != wParam) {
+ CHARRANGE cr;
+ m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&cr);
+ if (cr.cpMax != cr.cpMin) {
+ cr.cpMin = cr.cpMax;
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&cr);
+ }
+ }
+ break;
+
+ case WM_CHAR:
+ m_pDlg.KbdState(isShift, isCtrl, isAlt);
+ if (wParam == 0x03 && isCtrl) // Ctrl+C
+ return m_pDlg.WMCopyHandler(msg, wParam, lParam);
+ if (wParam == 0x11 && isCtrl) // Ctrl+Q
+ m_pDlg.m_btnQuote.Click();
+ break;
+
+ case WM_LBUTTONUP:
+ if (m_pDlg.isChat() && g_Settings.bClickableNicks) {
+ POINT pt = { LOWORD(lParam), HIWORD(lParam) };
+ CheckCustomLink(m_rtf.GetHwnd(), &pt, msg, wParam, lParam, TRUE);
+ }
+
+ if (g_plugin.bAutoCopy) {
+ CHARRANGE sel;
+ SendMessage(m_rtf.GetHwnd(), EM_EXGETSEL, 0, (LPARAM)&sel);
+ if (sel.cpMin != sel.cpMax) {
+ SendMessage(m_rtf.GetHwnd(), WM_COPY, 0, 0);
+ sel.cpMin = sel.cpMax;
+ SendMessage(m_rtf.GetHwnd(), EM_EXSETSEL, 0, (LPARAM)&sel);
+ SetFocus(m_pDlg.m_message.GetHwnd());
+ }
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ case WM_RBUTTONUP:
+ case WM_RBUTTONDOWN:
+ case WM_RBUTTONDBLCLK:
+ if (m_pDlg.isChat() && g_Settings.bClickableNicks) {
+ POINT pt = { LOWORD(lParam), HIWORD(lParam) };
+ CheckCustomLink(m_rtf.GetHwnd(), &pt, msg, wParam, lParam, TRUE);
+ }
+ break;
+
+ case WM_SETCURSOR:
+ if (g_Settings.bClickableNicks && m_pDlg.isChat() && (LOWORD(lParam) == HTCLIENT)) {
+ POINT pt;
+ GetCursorPos(&pt);
+ ScreenToClient(m_rtf.GetHwnd(), &pt);
+ if (CheckCustomLink(m_rtf.GetHwnd(), &pt, msg, wParam, lParam, FALSE))
+ return TRUE;
+ }
+ break;
+
+ case WM_SYSKEYUP:
+ if (wParam == VK_MENU) {
+ m_pDlg.ProcessHotkeysByMsgFilter(m_rtf, msg, wParam, lParam);
+ return 0;
+ }
+ break;
+
+ case WM_SYSKEYDOWN:
+ m_pDlg.m_bkeyProcessed = false;
+ if (m_pDlg.ProcessHotkeysByMsgFilter(m_rtf, msg, wParam, lParam)) {
+ m_pDlg.m_bkeyProcessed = true;
+ return 0;
+ }
+ break;
+
+ case WM_SYSCHAR:
+ if (m_pDlg.m_bkeyProcessed) {
+ m_pDlg.m_bkeyProcessed = false;
+ return 0;
+ }
+ break;
+
+ case WM_KEYDOWN:
+ m_pDlg.KbdState(isShift, isCtrl, isAlt);
+ if (wParam == VK_INSERT && isCtrl)
+ return m_pDlg.WMCopyHandler(msg, wParam, lParam);
+
+ if (wParam == 0x57 && isCtrl) { // ctrl-w (close window)
+ PostMessage(m_pDlg.m_hwnd, WM_CLOSE, 0, 1);
+ return TRUE;
+ }
+
+ break;
+
+ case WM_COPY:
+ return m_pDlg.WMCopyHandler(msg, wParam, lParam);
+
+ case WM_NCCALCSIZE:
+ return CSkin::NcCalcRichEditFrame(m_rtf.GetHwnd(), &m_pDlg, ID_EXTBKHISTORY, msg, wParam, lParam, stubLogProc);
+
+ case WM_NCPAINT:
+ return CSkin::DrawRichEditFrame(m_rtf.GetHwnd(), &m_pDlg, ID_EXTBKHISTORY, msg, wParam, lParam, stubLogProc);
+
+ case WM_CONTEXTMENU:
+ if (!m_pDlg.isChat()) {
+ POINT pt;
+ if (lParam == 0xFFFFFFFF) {
+ CHARRANGE sel;
+ m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel);
+ m_rtf.SendMsg(EM_POSFROMCHAR, (WPARAM)&pt, (LPARAM)sel.cpMax);
+ ClientToScreen(m_rtf.GetHwnd(), &pt);
+ }
+ else {
+ pt.x = GET_X_LPARAM(lParam);
+ pt.y = GET_Y_LPARAM(lParam);
+ }
+
+ m_pDlg.ShowPopupMenu(m_rtf, pt);
+ return TRUE;
+ }
+ }
+
+ return CSuper::WndProc(msg, wParam, lParam);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CLogWindow::AppendUnicodeString(CMStringA &str, const wchar_t *pwszBuf)
+{
+ AppendUnicodeToBuffer(str, pwszBuf, 0);
+}
+
+void CLogWindow::Attach()
+{
+ CSuper::Attach();
+
+ m_rtf.SendMsg(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0, 0));
+ m_rtf.SendMsg(EM_AUTOURLDETECT, TRUE, 0);
+ m_rtf.SendMsg(EM_EXLIMITTEXT, 0, 0x7FFFFFFF);
+ m_rtf.SendMsg(EM_SETUNDOLIMIT, 0, 0);
+ m_rtf.SendMsg(EM_HIDESELECTION, TRUE, 0);
+ m_rtf.SendMsg(EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_KEYEVENTS | ENM_LINK);
+ m_rtf.SendMsg(EM_SETEDITSTYLE, SES_EXTENDBACKCOLOR, SES_EXTENDBACKCOLOR);
+ m_rtf.SendMsg(EM_SETLANGOPTIONS, 0, m_rtf.SendMsg(EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOFONTSIZEADJUST);
+ m_rtf.SendMsg(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3));
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+char* CLogWindow::CreateRTFFromDbEvent(LogStreamData *streamData)
{
HANDLE hTimeZone = nullptr;
struct tm event_time = { 0 };
@@ -437,19 +636,20 @@ static char* Template_CreateRTFFromDbEvent(CMsgDialog *dat, MCONTACT hContact, M
memcpy(&dbei, streamData->dbei, sizeof(DBEVENTINFO));
else {
dbei.cbBlob = -1;
- db_event_get(hDbEvent, &dbei);
+ 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));
BOOL isSent = (dbei.flags & DBEF_SENT);
BOOL bIsStatusChangeEvent = IsStatusEvent(dbei.eventType);
if (!isSent && (bIsStatusChangeEvent || dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei))) {
- db_event_markRead(hContact, hDbEvent);
- g_clistApi.pfnRemoveEvent(hContact, hDbEvent);
+ db_event_markRead(streamData->hContact, streamData->hDbEvent);
+ g_clistApi.pfnRemoveEvent(streamData->hContact, streamData->hDbEvent);
}
CMStringW msg(ptrW(DbEvent_GetTextW(&dbei, CP_UTF8)));
@@ -549,7 +749,7 @@ static char* Template_CreateRTFFromDbEvent(CMsgDialog *dat, MCONTACT hContact, M
memmove(dat->m_hHistoryEvents, &dat->m_hHistoryEvents[1], sizeof(HANDLE) * (dat->m_maxHistory - 1));
dat->m_curHistory--;
}
- dat->m_hHistoryEvents[dat->m_curHistory++] = hDbEvent;
+ dat->m_hHistoryEvents[dat->m_curHistory++] = streamData->hDbEvent;
}
str.Append("\\ul0\\b0\\i0\\v0 ");
@@ -851,8 +1051,13 @@ static char* Template_CreateRTFFromDbEvent(CMsgDialog *dat, MCONTACT hContact, M
str.Append(GetRTFFont(iFontIDOffset + (isSent ? MSGFONTID_MYMISC : MSGFONTID_YOURMISC)));
str.AppendChar(' ');
}
-
- AppendUnicodeToBuffer(str, ptrW(DbEvent_GetTextW(&dbei, CP_ACP)), 0);
+ {
+ DB::FILE_BLOB blob(dbei);
+ if (blob.isOffline())
+ InsertFileLink(str, streamData->hDbEvent, blob);
+ else
+ AppendUnicodeToBuffer(str, ptrW(DbEvent_GetTextW(&dbei, CP_ACP)), 0);
+ }
break;
default:
@@ -981,7 +1186,7 @@ skip:
}
if (dat->m_hHistoryEvents)
- str.AppendFormat(dat->m_szMicroLf, MSGDLGFONTCOUNT + 1 + ((isSent) ? 1 : 0), hDbEvent);
+ str.AppendFormat(dat->m_szMicroLf, MSGDLGFONTCOUNT + 1 + ((isSent) ? 1 : 0), streamData->hDbEvent);
str.Append("\\par");
@@ -993,204 +1198,8 @@ skip:
return str.Detach();
}
-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->dlgDat);
- dat->stage = STREAMSTAGE_EVENTS;
- break;
-
- case STREAMSTAGE_EVENTS:
- if (dat->eventsToInsert) {
- do {
- mir_free(dat->buffer);
- dat->buffer = Template_CreateRTFFromDbEvent(dat->dlgDat, dat->hContact, dat->hDbEvent, 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)
-{
- bool isCtrl, isShift, isAlt;
-
- switch (msg) {
- case WM_KILLFOCUS:
- if (wParam != (WPARAM)m_rtf.GetHwnd() && 0 != wParam) {
- CHARRANGE cr;
- m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&cr);
- if (cr.cpMax != cr.cpMin) {
- cr.cpMin = cr.cpMax;
- m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&cr);
- }
- }
- break;
-
- case WM_CHAR:
- m_pDlg.KbdState(isShift, isCtrl, isAlt);
- if (wParam == 0x03 && isCtrl) // Ctrl+C
- return m_pDlg.WMCopyHandler(msg, wParam, lParam);
- if (wParam == 0x11 && isCtrl) // Ctrl+Q
- m_pDlg.m_btnQuote.Click();
- break;
-
- case WM_LBUTTONUP:
- if (m_pDlg.isChat() && g_Settings.bClickableNicks) {
- POINT pt = { LOWORD(lParam), HIWORD(lParam) };
- CheckCustomLink(m_rtf.GetHwnd(), &pt, msg, wParam, lParam, TRUE);
- }
-
- if (g_plugin.bAutoCopy) {
- CHARRANGE sel;
- SendMessage(m_rtf.GetHwnd(), EM_EXGETSEL, 0, (LPARAM)&sel);
- if (sel.cpMin != sel.cpMax) {
- SendMessage(m_rtf.GetHwnd(), WM_COPY, 0, 0);
- sel.cpMin = sel.cpMax;
- SendMessage(m_rtf.GetHwnd(), EM_EXSETSEL, 0, (LPARAM)&sel);
- SetFocus(m_pDlg.m_message.GetHwnd());
- }
- }
- break;
-
- case WM_LBUTTONDOWN:
- case WM_LBUTTONDBLCLK:
- case WM_RBUTTONUP:
- case WM_RBUTTONDOWN:
- case WM_RBUTTONDBLCLK:
- if (m_pDlg.isChat() && g_Settings.bClickableNicks) {
- POINT pt = { LOWORD(lParam), HIWORD(lParam) };
- CheckCustomLink(m_rtf.GetHwnd(), &pt, msg, wParam, lParam, TRUE);
- }
- break;
-
- case WM_SETCURSOR:
- if (g_Settings.bClickableNicks && m_pDlg.isChat() && (LOWORD(lParam) == HTCLIENT)) {
- POINT pt;
- GetCursorPos(&pt);
- ScreenToClient(m_rtf.GetHwnd(), &pt);
- if (CheckCustomLink(m_rtf.GetHwnd(), &pt, msg, wParam, lParam, FALSE))
- return TRUE;
- }
- break;
-
- case WM_SYSKEYUP:
- if (wParam == VK_MENU) {
- m_pDlg.ProcessHotkeysByMsgFilter(m_rtf, msg, wParam, lParam);
- return 0;
- }
- break;
-
- case WM_SYSKEYDOWN:
- m_pDlg.m_bkeyProcessed = false;
- if (m_pDlg.ProcessHotkeysByMsgFilter(m_rtf, msg, wParam, lParam)) {
- m_pDlg.m_bkeyProcessed = true;
- return 0;
- }
- break;
-
- case WM_SYSCHAR:
- if (m_pDlg.m_bkeyProcessed) {
- m_pDlg.m_bkeyProcessed = false;
- return 0;
- }
- break;
-
- case WM_KEYDOWN:
- m_pDlg.KbdState(isShift, isCtrl, isAlt);
- if (wParam == VK_INSERT && isCtrl)
- return m_pDlg.WMCopyHandler(msg, wParam, lParam);
-
- if (wParam == 0x57 && isCtrl) { // ctrl-w (close window)
- PostMessage(m_pDlg.m_hwnd, WM_CLOSE, 0, 1);
- return TRUE;
- }
-
- break;
-
- case WM_COPY:
- return m_pDlg.WMCopyHandler(msg, wParam, lParam);
-
- case WM_NCCALCSIZE:
- return CSkin::NcCalcRichEditFrame(m_rtf.GetHwnd(), &m_pDlg, ID_EXTBKHISTORY, msg, wParam, lParam, stubLogProc);
-
- case WM_NCPAINT:
- return CSkin::DrawRichEditFrame(m_rtf.GetHwnd(), &m_pDlg, ID_EXTBKHISTORY, msg, wParam, lParam, stubLogProc);
-
- case WM_CONTEXTMENU:
- if (!m_pDlg.isChat()) {
- POINT pt;
- if (lParam == 0xFFFFFFFF) {
- CHARRANGE sel;
- m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel);
- m_rtf.SendMsg(EM_POSFROMCHAR, (WPARAM)&pt, (LPARAM)sel.cpMax);
- ClientToScreen(m_rtf.GetHwnd(), &pt);
- }
- else {
- pt.x = GET_X_LPARAM(lParam);
- pt.y = GET_Y_LPARAM(lParam);
- }
-
- m_pDlg.ShowPopupMenu(m_rtf, pt);
- return TRUE;
- }
- }
-
- return CSuper::WndProc(msg, wParam, lParam);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-void CLogWindow::Attach()
-{
- CSuper::Attach();
-
- m_rtf.SendMsg(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0, 0));
- m_rtf.SendMsg(EM_AUTOURLDETECT, TRUE, 0);
- m_rtf.SendMsg(EM_EXLIMITTEXT, 0, 0x7FFFFFFF);
- m_rtf.SendMsg(EM_SETUNDOLIMIT, 0, 0);
- m_rtf.SendMsg(EM_HIDESELECTION, TRUE, 0);
- m_rtf.SendMsg(EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_KEYEVENTS | ENM_LINK);
- m_rtf.SendMsg(EM_SETEDITSTYLE, SES_EXTENDBACKCOLOR, SES_EXTENDBACKCOLOR);
- m_rtf.SendMsg(EM_SETLANGOPTIONS, 0, m_rtf.SendMsg(EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOFONTSIZEADJUST);
- m_rtf.SendMsg(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3));
-}
-
void CLogWindow::LogEvents(MEVENT hDbEventFirst, int count, bool fAppend)
{
LogEvents(hDbEventFirst, count, fAppend, nullptr);
@@ -1228,7 +1237,7 @@ void CLogWindow::LogEvents(MEVENT hDbEventFirst, int count, bool fAppend, DBEVEN
LogStreamData streamData = { 0 };
streamData.hContact = m_pDlg.m_hContact;
streamData.hDbEvent = hDbEventFirst;
- streamData.dlgDat = &m_pDlg;
+ streamData.pLog = this;
streamData.eventsToInsert = count;
streamData.isEmpty = fAppend ? GetWindowTextLength(m_rtf.GetHwnd()) == 0 : 1;
streamData.dbei = dbei_s;
@@ -1306,6 +1315,8 @@ void CLogWindow::LogEvents(MEVENT hDbEventFirst, int count, bool fAppend, DBEVEN
mir_free(streamData.buffer);
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
void CLogWindow::LogEvents(LOGINFO *lin, bool bRedraw)
{
auto *si = m_pDlg.m_si;
@@ -1460,6 +1471,8 @@ void CLogWindow::LogEvents(LOGINFO *lin, bool bRedraw)
}
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
void CLogWindow::ReplaceIcons(LONG startAt, int fAppend, BOOL isSent)
{
wchar_t trbuffer[40];
@@ -1582,6 +1595,8 @@ void CLogWindow::ReplaceIcons(LONG startAt, int fAppend, BOOL isSent)
}
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
void CLogWindow::ScrollToBottom()
{
ScrollToBottom(false, false);
@@ -1606,6 +1621,8 @@ void CLogWindow::ScrollToBottom(bool bImmediate, bool bRedraw)
InvalidateRect(m_rtf.GetHwnd(), nullptr, FALSE);
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
void CLogWindow::UpdateOptions()
{
COLORREF colour = m_pDlg.isChat() ? g_Settings.crLogBackground : db_get_dw(0, FONTMODULE, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR);
@@ -1633,6 +1650,9 @@ void CLogWindow::UpdateOptions()
}
}
+/////////////////////////////////////////////////////////////////////////////////////////
+// Module entry point
+
CSrmmLogWindow *logBuilder(CMsgDialog &pDlg)
{
return new CLogWindow(pDlg);
diff --git a/plugins/TabSRMM/src/msgs.h b/plugins/TabSRMM/src/msgs.h
index 6d05b1a25f..d3bdec4c3d 100644
--- a/plugins/TabSRMM/src/msgs.h
+++ b/plugins/TabSRMM/src/msgs.h
@@ -371,42 +371,6 @@ struct TContainerData : public MZeroedObject
};
/////////////////////////////////////////////////////////////////////////////////////////
-// CLogWindow - built-in log window
-
-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 ScrollToBottom() override;
- void UpdateOptions() override;
-
- void DisableStaticEdge()
- {
- SetWindowLongPtr(m_rtf.GetHwnd(), GWL_EXSTYLE, GetWindowLongPtr(m_rtf.GetHwnd(), GWL_EXSTYLE) & ~WS_EX_STATICEDGE);
- }
-
- char* GetRichTextRtf(bool bText, bool bSelection)
- {
- return m_rtf.GetRichTextRtf(bText, bSelection);
- }
-
- void LogEvents(MEVENT hDbEventFirst, int count, bool bAppend, DBEVENTINFO *dbei);
- void ReplaceIcons(LONG startAt, int fAppend, BOOL isSent);
- void ScrollToBottom(bool, bool);
-
- INT_PTR WndProc(UINT msg, WPARAM wParam, LPARAM lParam) override;
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
// CMsgDialog - SRMM window class
class CMsgDialog : public CSrmmBaseDialog
@@ -711,6 +675,44 @@ public:
extern LIST<void> g_arUnreadWindows;
+/////////////////////////////////////////////////////////////////////////////////////////
+// CLogWindow - built-in log window
+
+class CLogWindow : public CRtfLogWindow
+{
+ typedef CRtfLogWindow CSuper;
+
+public:
+ CLogWindow(CMsgDialog &pDlg) :
+ CSuper(pDlg)
+ {}
+
+ char *CreateRTFFromDbEvent(struct LogStreamData *streamData);
+
+ 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 ScrollToBottom() override;
+ void UpdateOptions() override;
+
+ void DisableStaticEdge()
+ {
+ SetWindowLongPtr(m_rtf.GetHwnd(), GWL_EXSTYLE, GetWindowLongPtr(m_rtf.GetHwnd(), GWL_EXSTYLE) & ~WS_EX_STATICEDGE);
+ }
+
+ char *GetRichTextRtf(bool bText, bool bSelection)
+ {
+ return m_rtf.GetRichTextRtf(bText, bSelection);
+ }
+
+ void LogEvents(MEVENT hDbEventFirst, int count, bool bAppend, DBEVENTINFO *dbei);
+ void ReplaceIcons(LONG startAt, int fAppend, BOOL isSent);
+ void ScrollToBottom(bool, bool);
+
+ INT_PTR WndProc(UINT msg, WPARAM wParam, LPARAM lParam) override;
+};
+
#define MESSAGE_WINDOW_DATA_SIZE offsetof(_MessageWindowData, hdbEventFirst);
/*