summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2019-10-02 20:42:44 +0300
committerGeorge Hazan <ghazan@miranda.im>2019-10-02 20:42:44 +0300
commit7a948f1ef804ecd9971b0869e0591c22944fa6da (patch)
treecdc2df2e2d5f186da4b8778b4e1c9e79013ff921 /src/core
parent9fe4e9044069e70b3f0e1df0e187f5ea43805ea1 (diff)
merge with SrmmLogContainer
Diffstat (limited to 'src/core')
-rw-r--r--src/core/stdmsg/src/chat_window.cpp51
-rw-r--r--src/core/stdmsg/src/msgdialog.cpp170
-rw-r--r--src/core/stdmsg/src/msglog.cpp253
-rw-r--r--src/core/stdmsg/src/msgs.h34
-rw-r--r--src/core/stdmsg/src/srmm.cpp3
-rw-r--r--src/core/stdmsg/src/stdafx.h3
-rw-r--r--src/core/stdmsg/src/tabs.cpp2
7 files changed, 269 insertions, 247 deletions
diff --git a/src/core/stdmsg/src/chat_window.cpp b/src/core/stdmsg/src/chat_window.cpp
index a33d411064..a2f9f2e364 100644
--- a/src/core/stdmsg/src/chat_window.cpp
+++ b/src/core/stdmsg/src/chat_window.cpp
@@ -62,7 +62,7 @@ void CMsgDialog::UpdateOptions()
Window_SetIcon_IcoLib(m_pOwner->GetHwnd(), g_plugin.getIconHandle(IDI_CHANMGR));
- m_log.SendMsg(EM_SETBKGNDCOLOR, 0, g_Settings.crLogBackground);
+ m_pLog->UpdateOptions();
CHARFORMAT2 cf;
cf.cbSize = sizeof(CHARFORMAT2);
@@ -111,18 +111,19 @@ void CMsgDialog::UpdateStatusBar()
/////////////////////////////////////////////////////////////////////////////////////////
-void CMsgDialog::StreamInEvents(LOGINFO *lin, bool bRedraw)
+void CLogWindow::LogEvents(LOGINFO *lin, bool bRedraw)
{
- if (m_hwnd == nullptr || lin == nullptr || m_si == nullptr)
+ auto *si = m_pDlg.m_si;
+ if (lin == nullptr || si == nullptr)
return;
- if (!bRedraw && m_si->iType == GCW_CHATROOM && m_bFilterEnabled && (m_iLogFilterFlags & lin->iType) == 0)
+ if (!bRedraw && si->iType == GCW_CHATROOM && m_pDlg.m_bFilterEnabled && (m_pDlg.m_iLogFilterFlags & lin->iType) == 0)
return;
LOGSTREAMDATA streamData;
memset(&streamData, 0, sizeof(streamData));
- streamData.hwnd = m_log.GetHwnd();
- streamData.si = m_si;
+ streamData.hwnd = m_rtf.GetHwnd();
+ streamData.si = si;
streamData.lin = lin;
streamData.bStripFormat = FALSE;
@@ -135,20 +136,20 @@ void CMsgDialog::StreamInEvents(LOGINFO *lin, bool bRedraw)
SCROLLINFO scroll;
scroll.cbSize = sizeof(SCROLLINFO);
scroll.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
- GetScrollInfo(m_log.GetHwnd(), SB_VERT, &scroll);
+ GetScrollInfo(m_rtf.GetHwnd(), SB_VERT, &scroll);
POINT point = {};
- m_log.SendMsg(EM_GETSCROLLPOS, 0, (LPARAM)&point);
+ m_rtf.SendMsg(EM_GETSCROLLPOS, 0, (LPARAM)&point);
// do not scroll to bottom if there is a selection
CHARRANGE oldsel, sel;
- m_log.SendMsg(EM_EXGETSEL, 0, (LPARAM)&oldsel);
+ m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&oldsel);
if (oldsel.cpMax != oldsel.cpMin)
- m_log.SendMsg(WM_SETREDRAW, FALSE, 0);
+ m_rtf.SendMsg(WM_SETREDRAW, FALSE, 0);
//set the insertion point at the bottom
- sel.cpMin = sel.cpMax = m_log.GetRichTextLength();
- m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+ 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)
@@ -163,14 +164,14 @@ void CMsgDialog::StreamInEvents(LOGINFO *lin, bool bRedraw)
g_chatApi.logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY);
g_chatApi.logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX);
ReleaseDC(nullptr, hdc);
- m_log.SendMsg(WM_SETREDRAW, FALSE, 0);
+ m_rtf.SendMsg(WM_SETREDRAW, FALSE, 0);
bFlag = true;
}
// stream in the event(s)
streamData.lin = lin;
streamData.bRedraw = bRedraw;
- m_log.SendMsg(EM_STREAMIN, wp, (LPARAM)&stream);
+ m_rtf.SendMsg(EM_STREAMIN, wp, (LPARAM)&stream);
// do smileys
if (g_dat.bSmileyInstalled && (bRedraw || (lin->ptszText && lin->iType != GC_EVENT_JOIN && lin->iType != GC_EVENT_NICK && lin->iType != GC_EVENT_ADDSTATUS && lin->iType != GC_EVENT_REMOVESTATUS))) {
@@ -182,11 +183,11 @@ void CMsgDialog::StreamInEvents(LOGINFO *lin, bool bRedraw)
SMADD_RICHEDIT3 sm = {};
sm.cbSize = sizeof(sm);
- sm.hwndRichEditControl = m_log.GetHwnd();
- sm.Protocolname = m_si->pszModule;
+ sm.hwndRichEditControl = m_rtf.GetHwnd();
+ sm.Protocolname = si->pszModule;
sm.rangeToReplace = bRedraw ? nullptr : &newsel;
sm.disableRedraw = TRUE;
- sm.hContact = m_si->hContact;
+ sm.hContact = si->hContact;
CallService(MS_SMILEYADD_REPLACESMILEYS, 0, (LPARAM)&sm);
}
@@ -194,21 +195,21 @@ void CMsgDialog::StreamInEvents(LOGINFO *lin, bool bRedraw)
if (bRedraw || (UINT)scroll.nPos >= (UINT)scroll.nMax - scroll.nPage - 5 || scroll.nMax - scroll.nMin - scroll.nPage < 50)
ScrollToBottom();
else
- m_log.SendMsg(EM_SETSCROLLPOS, 0, (LPARAM)&point);
+ m_rtf.SendMsg(EM_SETSCROLLPOS, 0, (LPARAM)&point);
// do we need to restore the selection
if (oldsel.cpMax != oldsel.cpMin) {
- m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)&oldsel);
- m_log.SendMsg(WM_SETREDRAW, TRUE, 0);
- InvalidateRect(m_log.GetHwnd(), nullptr, TRUE);
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&oldsel);
+ m_rtf.SendMsg(WM_SETREDRAW, TRUE, 0);
+ InvalidateRect(m_rtf.GetHwnd(), nullptr, TRUE);
}
// need to invalidate the window
if (bFlag) {
- sel.cpMin = sel.cpMax = m_log.GetRichTextLength();
- m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
- m_log.SendMsg(WM_SETREDRAW, TRUE, 0);
- InvalidateRect(m_log.GetHwnd(), nullptr, TRUE);
+ sel.cpMin = sel.cpMax = m_rtf.GetRichTextLength();
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+ m_rtf.SendMsg(WM_SETREDRAW, TRUE, 0);
+ InvalidateRect(m_rtf.GetHwnd(), nullptr, TRUE);
}
}
diff --git a/src/core/stdmsg/src/msgdialog.cpp b/src/core/stdmsg/src/msgdialog.cpp
index d1e6bfdb9c..7081150531 100644
--- a/src/core/stdmsg/src/msgdialog.cpp
+++ b/src/core/stdmsg/src/msgdialog.cpp
@@ -143,9 +143,6 @@ bool CMsgDialog::OnInitDialog()
int nMax = CallProtoService(m_szProto, PS_GETCAPS, PFLAG_MAXLENOFMESSAGE, m_hContact);
if (nMax)
m_message.SendMsg(EM_EXLIMITTEXT, 0, nMax);
-
- // get around a lame bug in the Windows template resource code where richedits are limited to 0x7FFF
- m_log.SendMsg(EM_LIMITTEXT, sizeof(wchar_t) * 0x7FFFFFFF, 0);
}
m_wOldStatus = m_wStatus;
@@ -157,9 +154,6 @@ bool CMsgDialog::OnInitDialog()
m_iSplitterY = g_plugin.getDword(g_dat.bSavePerContact ? m_hContact : 0, "splitterPos", m_minEditInit.bottom - m_minEditInit.top);
UpdateSizeBar();
- m_log.SendMsg(EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_LINK | ENM_SCROLL);
- m_log.SendMsg(EM_AUTOURLDETECT, TRUE, 0);
-
m_message.SendMsg(EM_SETEVENTMASK, 0, ENM_CHANGE);
if (isChat()) {
@@ -384,7 +378,7 @@ void CMsgDialog::onClick_NickList(CCtrlButton *pButton)
m_bNicklistEnabled = !m_bNicklistEnabled;
pButton->SendMsg(BM_SETIMAGE, IMAGE_ICON, (LPARAM)g_plugin.getIcon(m_bNicklistEnabled ? IDI_NICKLIST : IDI_NICKLIST2, FALSE));
- ScrollToBottom();
+ m_pLog->ScrollToBottom();
Resize();
}
@@ -479,17 +473,21 @@ int CMsgDialog::Resizer(UTILRESIZECONTROL *urc)
urc->rcItem.top = 2;
urc->rcItem.left = 0;
urc->rcItem.right = bNick ? urc->dlgNewSize.cx - m_iSplitterX : urc->dlgNewSize.cx;
- LBL_CalcBottom:
urc->rcItem.bottom = urc->dlgNewSize.cy - m_iSplitterY;
if (!bToolbar)
urc->rcItem.bottom += 20;
+ m_rcLog = urc->rcItem;
return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM;
case IDC_SRMM_NICKLIST:
urc->rcItem.top = 2;
urc->rcItem.right = urc->dlgNewSize.cx;
urc->rcItem.left = urc->dlgNewSize.cx - m_iSplitterX + 2;
- goto LBL_CalcBottom;
+LBL_CalcBottom:
+ urc->rcItem.bottom = urc->dlgNewSize.cy - m_iSplitterY;
+ if (!bToolbar)
+ urc->rcItem.bottom += 20;
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM;
case IDC_SPLITTERX:
urc->rcItem.top = 1;
@@ -517,6 +515,7 @@ int CMsgDialog::Resizer(UTILRESIZECONTROL *urc)
if (!g_dat.bShowButtons)
urc->rcItem.top = 2;
urc->rcItem.bottom = urc->dlgNewSize.cy - m_iSplitterY;
+ m_rcLog = urc->rcItem;
return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP;
case IDC_SPLITTERY:
@@ -605,10 +604,8 @@ INT_PTR CMsgDialog::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_SIZE:
if (!IsIconic(m_hwnd)) {
- bool bottomScroll;
if (isChat()) {
- bottomScroll = false;
bool bSend = g_dat.bSendButton;
bool bNick = m_si->iType != GCW_SERVER && m_bNicklistEnabled;
@@ -632,29 +629,18 @@ INT_PTR CMsgDialog::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
}
}
else {
- bottomScroll = true;
SetupStatusBar();
-
- if (GetWindowLongPtr(m_log.GetHwnd(), GWL_STYLE) & WS_VSCROLL) {
- SCROLLINFO si = {};
- si.cbSize = sizeof(si);
- si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
- GetScrollInfo(m_log.GetHwnd(), SB_VERT, &si);
- bottomScroll = (si.nPos + (int)si.nPage + 5) >= si.nMax;
- }
}
CSuper::DlgProc(uMsg, wParam, lParam); // call built-in resizer
SetButtonsPos(m_hwnd, isChat());
+ m_pLog->Resize();
InvalidateRect(m_pOwner->m_hwndStatus, nullptr, true);
RedrawWindow(m_message.GetHwnd(), nullptr, nullptr, RDW_INVALIDATE);
RedrawWindow(m_btnOk.GetHwnd(), nullptr, nullptr, RDW_INVALIDATE);
if (g_dat.bShowAvatar && m_avatarPic)
RedrawWindow(m_avatar.GetHwnd(), nullptr, nullptr, RDW_INVALIDATE);
-
- if (bottomScroll)
- ScrollToBottom();
}
return TRUE;
@@ -682,21 +668,15 @@ INT_PTR CMsgDialog::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
}
if (hDbEvent != m_hDbEventFirst && db_event_next(m_hContact, hDbEvent) == 0)
- StreamInEvents(hDbEvent, 1, 1);
+ m_pLog->LogEvents(hDbEvent, 1, 1);
else
RemakeLog();
// Flash window *only* for messages, not for custom events
if (isMessage && !isSent) {
if (isActive) {
- if (GetWindowLongPtr(m_log.GetHwnd(), GWL_STYLE) & WS_VSCROLL) {
- SCROLLINFO si = {};
- si.cbSize = sizeof(si);
- si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
- GetScrollInfo(m_log.GetHwnd(), SB_VERT, &si);
- if ((si.nPos + (int)si.nPage + 5) < si.nMax)
- StartFlash();
- }
+ if (m_pLog->AtBottom())
+ StartFlash();
}
else StartFlash();
}
@@ -928,11 +908,11 @@ INT_PTR CMsgDialog::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
case DM_UPDATETITLE:
if (lParam != 0) {
if (isChat()) {
- if (lParam != m_hContact)
+ if ((MCONTACT)lParam != m_hContact)
break;
}
else {
- bool bIsMe = (lParam == m_hContact) || (m_bIsMeta && db_mc_getMeta(lParam) == m_hContact);
+ bool bIsMe = ((MCONTACT)lParam == m_hContact) || (m_bIsMeta && db_mc_getMeta(lParam) == m_hContact);
if (!bIsMe)
break;
}
@@ -951,7 +931,7 @@ INT_PTR CMsgDialog::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_LBUTTONDBLCLK:
if (LOWORD(lParam) < 30)
- ScrollToBottom();
+ m_pLog->ScrollToBottom();
break;
case WM_ACTIVATE:
@@ -971,84 +951,6 @@ INT_PTR CMsgDialog::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
/////////////////////////////////////////////////////////////////////////////////////////
-static const CHARRANGE rangeAll = { 0, -1 };
-
-LRESULT CMsgDialog::WndProc_Log(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 (!isChat()) {
- POINT pt;
- GetCursorPos(&pt);
-
- SetFocus(m_log.GetHwnd());
-
- HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_CONTEXT));
- HMENU hSubMenu = GetSubMenu(hMenu, 0);
- TranslateMenu(hSubMenu);
-
- CHARRANGE all = { 0, -1 };
- m_log.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_hwnd, nullptr)) {
- case IDM_COPY:
- m_log.SendMsg(WM_COPY, 0, 0);
- break;
- case IDM_COPYALL:
- m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)&all);
- m_log.SendMsg(WM_COPY, 0, 0);
- m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
- break;
- case IDM_SELECTALL:
- m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)&all);
- break;
- case IDM_CLEAR:
- ClearLog();
- m_hDbEventFirst = 0;
- break;
- }
- DestroyMenu(hSubMenu);
- DestroyMenu(hMenu);
- return TRUE;
- }
- break;
-
- case WM_LBUTTONUP:
- if (isChat()) {
- m_log.SendMsg(EM_EXGETSEL, 0, (LPARAM)& sel);
- if (sel.cpMin != sel.cpMax) {
- m_log.SendMsg(WM_COPY, 0, 0);
- sel.cpMin = sel.cpMax;
- m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)& sel);
- }
- SetFocus(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)
- CloseTab();
- return TRUE;
- }
-
- if (ProcessHotkeys(wParam, isShift, isCtrl, isAlt))
- return FALSE;
- }
-
- return CSuper::WndProc_Log(msg, wParam, lParam);
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
LRESULT CMsgDialog::WndProc_Nicklist(UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
@@ -1065,11 +967,13 @@ LRESULT CMsgDialog::WndProc_Nicklist(UINT msg, WPARAM wParam, LPARAM lParam)
/////////////////////////////////////////////////////////////////////////////////////////
+static const CHARRANGE rangeAll = { 0, -1 };
+
LRESULT CMsgDialog::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_MOUSEWHEEL:
- m_log.SendMsg(WM_MOUSEWHEEL, wParam, lParam);
+ LOG()->WndProc(msg, wParam, lParam);
m_iLastEnterTime = 0;
return TRUE;
@@ -1302,7 +1206,7 @@ LRESULT CMsgDialog::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam)
}
if (wParam == VK_NEXT || wParam == VK_PRIOR) {
- m_log.SendMsg(msg, wParam, lParam);
+ ((CLogWindow *)m_pLog)->WndProc(msg, wParam, lParam);
m_iLastEnterTime = 0;
return TRUE;
}
@@ -1375,21 +1279,6 @@ bool CMsgDialog::IsActive() const
return bRes;
}
-void CMsgDialog::ScrollToBottom()
-{
- if (GetWindowLongPtr(m_log.GetHwnd(), GWL_STYLE) & WS_VSCROLL) {
- SCROLLINFO si = {};
- si.cbSize = sizeof(si);
- si.fMask = SIF_PAGE | SIF_RANGE;
- GetScrollInfo(m_log.GetHwnd(), SB_VERT, &si);
-
- si.fMask = SIF_POS;
- si.nPos = si.nMax - si.nPage;
- SetScrollInfo(m_log.GetHwnd(), SB_VERT, &si, TRUE);
- m_log.SendMsg(WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, 0), 0);
- }
-}
-
void CMsgDialog::StartFlash()
{
::SetTimer(m_hwnd, TIMERID_FLASHWND, 900, nullptr);
@@ -1493,9 +1382,8 @@ void CMsgDialog::OnOptionsApplied(bool bUpdateAvatar)
UpdateTitle();
Resize();
- COLORREF colour = g_plugin.getDword(SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR);
- m_log.SendMsg(EM_SETBKGNDCOLOR, 0, colour);
- m_message.SendMsg(EM_SETBKGNDCOLOR, 0, colour);
+ m_pLog->UpdateOptions();
+ m_message.SendMsg(EM_SETBKGNDCOLOR, 0, g_plugin.getDword(SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR));
// avatar stuff
m_avatarPic = nullptr;
@@ -1520,19 +1408,7 @@ void CMsgDialog::OnOptionsApplied(bool bUpdateAvatar)
cf.dwMask = CFM_COLOR;
m_message.SendMsg(EM_SETCHARFORMAT, SCF_ALL, (WPARAM)&cf);
- // 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;
- ClearLog();
- m_log.SendMsg(EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
- pf2.wEffects = 0;
- m_log.SendMsg(EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
- m_log.SendMsg(EM_SETLANGOPTIONS, 0, m_log.SendMsg(EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD);
-
+ m_pLog->Clear();
RemakeLog();
FixTabIcons();
}
@@ -1621,7 +1497,7 @@ void CMsgDialog::NotifyTyping(int mode)
void CMsgDialog::RemakeLog()
{
- StreamInEvents(m_hDbEventFirst, -1, 0);
+ m_pLog->LogEvents(m_hDbEventFirst, -1, 0);
}
void CMsgDialog::ProcessFileDrop(HDROP hDrop)
diff --git a/src/core/stdmsg/src/msglog.cpp b/src/core/stdmsg/src/msglog.cpp
index b48c2365cd..bb21d6c782 100644
--- a/src/core/stdmsg/src/msglog.cpp
+++ b/src/core/stdmsg/src/msglog.cpp
@@ -393,75 +393,141 @@ static DWORD CALLBACK LogStreamInEvents(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG
return 0;
}
-void CMsgDialog::StreamInEvents(MEVENT hDbEventFirst, int count, bool bAppend)
+#define RTFPICTHEADERMAXSIZE 78
+void LoadMsgLogIcons(void)
+{
+ HBRUSH hBkgBrush = CreateSolidBrush(g_plugin.getDword(SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR));
+
+ BITMAPINFOHEADER bih = { sizeof(bih) };
+ bih.biBitCount = 24;
+ bih.biCompression = BI_RGB;
+ bih.biHeight = 10;
+ bih.biPlanes = 1;
+ bih.biWidth = 10;
+ int widthBytes = ((bih.biWidth * bih.biBitCount + 31) >> 5) * 4;
+
+ RECT rc;
+ rc.top = rc.left = 0;
+ rc.right = bih.biWidth;
+ rc.bottom = bih.biHeight;
+
+ HDC hdc = GetDC(nullptr);
+ HBITMAP hBmp = CreateCompatibleBitmap(hdc, bih.biWidth, bih.biHeight);
+ HDC hdcMem = CreateCompatibleDC(hdc);
+ PBYTE pBmpBits = (PBYTE)mir_alloc(widthBytes * bih.biHeight);
+
+ for (int i = 0; i < _countof(pLogIconBmpBits); i++) {
+ HICON hIcon = IcoLib_GetIconByHandle(iconList[i].hIcolib);
+ size_t size = RTFPICTHEADERMAXSIZE + (bih.biSize + widthBytes * bih.biHeight) * 2;
+ pLogIconBmpBits[i] = (char*)mir_alloc(size);
+ size_t rtfHeaderSize = mir_snprintf(pLogIconBmpBits[i], size, "{\\pict\\dibitmap0\\wbmbitspixel%u\\wbmplanes1\\wbmwidthbytes%u\\picw%u\\pich%u ", bih.biBitCount, widthBytes, bih.biWidth, bih.biHeight);
+ HBITMAP hoBmp = (HBITMAP)SelectObject(hdcMem, hBmp);
+ FillRect(hdcMem, &rc, hBkgBrush);
+ DrawIconEx(hdcMem, 0, 0, hIcon, bih.biWidth, bih.biHeight, 0, nullptr, DI_NORMAL);
+ IcoLib_ReleaseIcon(hIcon);
+
+ SelectObject(hdcMem, hoBmp);
+ GetDIBits(hdc, hBmp, 0, bih.biHeight, pBmpBits, (BITMAPINFO*)&bih, DIB_RGB_COLORS);
+
+ char *szDest = pLogIconBmpBits[i] + rtfHeaderSize;
+ bin2hex(&bih, sizeof(bih), szDest); szDest += sizeof(bih) * 2;
+ bin2hex(pBmpBits, widthBytes * bih.biHeight, szDest); szDest += widthBytes * bih.biHeight * 2;
+ mir_strcpy(szDest, "}");
+ }
+ mir_free(pBmpBits);
+ DeleteDC(hdcMem);
+ DeleteObject(hBmp);
+ ReleaseDC(nullptr, hdc);
+ DeleteObject(hBkgBrush);
+}
+
+void FreeMsgLogIcons(void)
+{
+ for (auto &it : pLogIconBmpBits)
+ mir_free(it);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void CLogWindow::Attach()
+{
+ CSuper::Attach();
+
+ // 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_AUTOURLDETECT, TRUE, 0);
+}
+
+void CLogWindow::LogEvents(MEVENT hDbEventFirst, int count, bool bAppend)
{
CHARRANGE oldSel, sel;
BOOL bottomScroll = TRUE;
POINT scrollPos;
- m_log.SendMsg(WM_SETREDRAW, FALSE, 0);
- m_log.SendMsg(EM_EXGETSEL, 0, (LPARAM)&oldSel);
+ m_rtf.SendMsg(WM_SETREDRAW, FALSE, 0);
+ m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&oldSel);
LogStreamData streamData = {};
- streamData.hContact = m_hContact;
+ streamData.hContact = m_pDlg.m_hContact;
streamData.hDbEvent = hDbEventFirst;
- streamData.dlgDat = this;
+ streamData.dlgDat = &m_pDlg;
streamData.eventsToInsert = count;
- streamData.isEmpty = !bAppend || GetWindowTextLength(m_log.GetHwnd()) == 0;
+ streamData.isEmpty = !bAppend || GetWindowTextLength(m_rtf.GetHwnd()) == 0;
EDITSTREAM stream = {};
stream.pfnCallback = LogStreamInEvents;
stream.dwCookie = (DWORD_PTR)&streamData;
if (!streamData.isEmpty) {
- bottomScroll = (GetFocus() != m_log.GetHwnd());
- if (bottomScroll && (GetWindowLongPtr(m_log.GetHwnd(), GWL_STYLE) & WS_VSCROLL)) {
+ bottomScroll = (GetFocus() != m_rtf.GetHwnd());
+ if (bottomScroll && (GetWindowLongPtr(m_rtf.GetHwnd(), GWL_STYLE) & WS_VSCROLL)) {
SCROLLINFO si = {};
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
- GetScrollInfo(m_log.GetHwnd(), SB_VERT, &si);
+ GetScrollInfo(m_rtf.GetHwnd(), SB_VERT, &si);
bottomScroll = (si.nPos + (int)si.nPage) >= si.nMax;
}
if (!bottomScroll)
- m_log.SendMsg(EM_GETSCROLLPOS, 0, (LPARAM)&scrollPos);
+ m_rtf.SendMsg(EM_GETSCROLLPOS, 0, (LPARAM)&scrollPos);
}
FINDTEXTEXA fi;
if (bAppend) {
sel.cpMin = sel.cpMax = -1;
- m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+ 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_log.SendMsg(EM_GETTEXTLENGTHEX, (WPARAM)&gtxl, 0);
+ fi.chrg.cpMin = m_rtf.SendMsg(EM_GETTEXTLENGTHEX, (WPARAM)&gtxl, 0);
- sel.cpMin = sel.cpMax = m_log.GetRichTextLength();
- m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+ 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_log.SendMsg(EM_STREAMIN, bAppend ? SFF_SELECTION | SF_RTF : SF_RTF, (LPARAM)&stream);
+ m_rtf.SendMsg(EM_STREAMIN, bAppend ? SFF_SELECTION | SF_RTF : SF_RTF, (LPARAM)&stream);
if (bottomScroll) {
sel.cpMin = sel.cpMax = -1;
- m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel);
}
else {
- m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)&oldSel);
- m_log.SendMsg(EM_SETSCROLLPOS, 0, (LPARAM)&scrollPos);
+ m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&oldSel);
+ m_rtf.SendMsg(EM_SETSCROLLPOS, 0, (LPARAM)&scrollPos);
}
if (g_dat.bSmileyInstalled) {
SMADD_RICHEDIT3 smre;
smre.cbSize = sizeof(SMADD_RICHEDIT3);
- smre.hwndRichEditControl = m_log.GetHwnd();
+ smre.hwndRichEditControl = m_rtf.GetHwnd();
- MCONTACT hContact = db_mc_getSrmmSub(m_hContact);
- smre.Protocolname = (hContact != 0) ? GetContactProto(hContact) : m_szProto;
+ MCONTACT hContact = db_mc_getSrmmSub(m_pDlg.m_hContact);
+ smre.Protocolname = (hContact != 0) ? GetContactProto(hContact) : m_pDlg.m_szProto;
if (fi.chrg.cpMin > 0) {
sel.cpMin = fi.chrg.cpMin;
@@ -471,70 +537,125 @@ void CMsgDialog::StreamInEvents(MEVENT hDbEventFirst, int count, bool bAppend)
else smre.rangeToReplace = nullptr;
smre.disableRedraw = TRUE;
- smre.hContact = m_hContact;
+ smre.hContact = m_pDlg.m_hContact;
smre.flags = 0;
CallService(MS_SMILEYADD_REPLACESMILEYS, 0, (LPARAM)&smre);
}
- m_log.SendMsg(WM_SETREDRAW, TRUE, 0);
+ m_rtf.SendMsg(WM_SETREDRAW, TRUE, 0);
if (bottomScroll) {
ScrollToBottom();
- RedrawWindow(m_log.GetHwnd(), nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
+ RedrawWindow(m_rtf.GetHwnd(), nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW);
}
- m_hDbEventLast = streamData.hDbEventLast;
+ m_pDlg.m_hDbEventLast = streamData.hDbEventLast;
}
-#define RTFPICTHEADERMAXSIZE 78
-void LoadMsgLogIcons(void)
+void CLogWindow::LogEvents(DBEVENTINFO*, bool)
{
- HBRUSH hBkgBrush = CreateSolidBrush(g_plugin.getDword(SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR));
+}
- BITMAPINFOHEADER bih = { sizeof(bih) };
- bih.biBitCount = 24;
- bih.biCompression = BI_RGB;
- bih.biHeight = 10;
- bih.biPlanes = 1;
- bih.biWidth = 10;
- int widthBytes = ((bih.biWidth * bih.biBitCount + 31) >> 5) * 4;
+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);
- RECT rc;
- rc.top = rc.left = 0;
- rc.right = bih.biWidth;
- rc.bottom = bih.biHeight;
+ pf2.wEffects = PFE_RTLPARA;
+ pf2.dwMask = PFM_RTLPARA;
+ m_rtf.SendMsg(EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
- HDC hdc = GetDC(nullptr);
- HBITMAP hBmp = CreateCompatibleBitmap(hdc, bih.biWidth, bih.biHeight);
- HDC hdcMem = CreateCompatibleDC(hdc);
- PBYTE pBmpBits = (PBYTE)mir_alloc(widthBytes * bih.biHeight);
+ pf2.wEffects = 0;
+ m_rtf.SendMsg(EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
- for (int i = 0; i < _countof(pLogIconBmpBits); i++) {
- HICON hIcon = IcoLib_GetIconByHandle(iconList[i].hIcolib);
- size_t size = RTFPICTHEADERMAXSIZE + (bih.biSize + widthBytes * bih.biHeight) * 2;
- pLogIconBmpBits[i] = (char*)mir_alloc(size);
- size_t rtfHeaderSize = mir_snprintf(pLogIconBmpBits[i], size, "{\\pict\\dibitmap0\\wbmbitspixel%u\\wbmplanes1\\wbmwidthbytes%u\\picw%u\\pich%u ", bih.biBitCount, widthBytes, bih.biWidth, bih.biHeight);
- HBITMAP hoBmp = (HBITMAP)SelectObject(hdcMem, hBmp);
- FillRect(hdcMem, &rc, hBkgBrush);
- DrawIconEx(hdcMem, 0, 0, hIcon, bih.biWidth, bih.biHeight, 0, nullptr, DI_NORMAL);
- IcoLib_ReleaseIcon(hIcon);
+ 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));
+ }
+}
- SelectObject(hdcMem, hoBmp);
- GetDIBits(hdc, hBmp, 0, bih.biHeight, pBmpBits, (BITMAPINFO*)&bih, DIB_RGB_COLORS);
+/////////////////////////////////////////////////////////////////////////////////////////
- char *szDest = pLogIconBmpBits[i] + rtfHeaderSize;
- bin2hex(&bih, sizeof(bih), szDest); szDest += sizeof(bih) * 2;
- bin2hex(pBmpBits, widthBytes * bih.biHeight, szDest); szDest += widthBytes * bih.biHeight * 2;
- mir_strcpy(szDest, "}");
+static const CHARRANGE rangeAll = { 0, -1 };
+
+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;
+ }
+ DestroyMenu(hSubMenu);
+ DestroyMenu(hMenu);
+ return TRUE;
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ if (m_pDlg.isChat()) {
+ 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());
+ }
+ 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;
}
- mir_free(pBmpBits);
- DeleteDC(hdcMem);
- DeleteObject(hBmp);
- ReleaseDC(nullptr, hdc);
- DeleteObject(hBkgBrush);
+
+ return CSuper::WndProc(msg, wParam, lParam);
}
-void FreeMsgLogIcons(void)
+CSrmmLogWindow *logBuilder(CMsgDialog &pDlg)
{
- for (auto &it : pLogIconBmpBits)
- mir_free(it);
+ return new CLogWindow(pDlg);
}
diff --git a/src/core/stdmsg/src/msgs.h b/src/core/stdmsg/src/msgs.h
index 5a876ac547..ed2a647fe8 100644
--- a/src/core/stdmsg/src/msgs.h
+++ b/src/core/stdmsg/src/msgs.h
@@ -32,10 +32,29 @@ 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(DBEVENTINFO *dbei, bool bAppend);
+ void LogEvents(struct LOGINFO *, bool) override;
+ void UpdateOptions() override;
+
+ INT_PTR WndProc(UINT msg, WPARAM wParam, LPARAM lParam) override;
+};
+
class CMsgDialog : public CSrmmBaseDialog
{
- typedef CSrmmBaseDialog CSuper;
+ friend class CLogWindow;
friend class CTabbedWindow;
+ typedef CSrmmBaseDialog CSuper;
void Init(void);
void NotifyTyping(int mode);
@@ -43,14 +62,12 @@ class CMsgDialog : public CSrmmBaseDialog
void ShowAvatar(void);
void ShowTime(bool bForce);
void SetupStatusBar(void);
- void StreamInEvents(MEVENT hDbEventFirst, int count, bool bAppend);
void UpdateIcon(WPARAM wParam);
void UpdateLastMessage(void);
void UpdateSizeBar(void);
static INT_PTR CALLBACK FilterWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
-protected:
CCtrlBase m_avatar;
CCtrlButton m_btnOk;
@@ -63,6 +80,7 @@ protected:
int m_iSplitterX, m_iSplitterY;
SIZE m_minEditBoxSize;
RECT m_minEditInit;
+ RECT m_rcLog;
// tab autocomplete
int m_iTabStart = 0;
@@ -93,7 +111,6 @@ public:
int Resizer(UTILRESIZECONTROL *urc) override;
INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override;
- LRESULT WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam) override;
LRESULT WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) override;
LRESULT WndProc_Nicklist(UINT msg, WPARAM wParam, LPARAM lParam) override;
@@ -115,11 +132,14 @@ public:
void UpdateReadChars(void);
- __forceinline MCONTACT getActiveContact() const
- {
+ __forceinline MCONTACT getActiveContact() const {
return (m_bIsMeta) ? db_mc_getSrmmSub(m_hContact) : m_hContact;
}
+ __forceinline CLogWindow* LOG() {
+ return ((CLogWindow *)m_pLog);
+ }
+
MEVENT m_hDbEventFirst, m_hDbEventLast;
int m_avatarWidth = 0, m_avatarHeight = 0;
@@ -137,9 +157,7 @@ public:
void CloseTab() override;
bool IsActive() const override;
void LoadSettings() override;
- void ScrollToBottom() override;
void SetStatusText(const wchar_t *, HICON) override;
- void StreamInEvents(LOGINFO *lin, bool bRedraw) override;
void ShowFilterMenu() override;
void UpdateNickList() override;
void UpdateOptions() override;
diff --git a/src/core/stdmsg/src/srmm.cpp b/src/core/stdmsg/src/srmm.cpp
index ebd0e2519d..6dad345b8d 100644
--- a/src/core/stdmsg/src/srmm.cpp
+++ b/src/core/stdmsg/src/srmm.cpp
@@ -52,6 +52,8 @@ extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_SRMM,
int CMPlugin::Load()
{
+ hLogger = RegisterSrmmLog("built-in", L"StdMsg internal log", &logBuilder);
+
Load_ChatModule();
return LoadSendRecvMessageModule();
}
@@ -60,6 +62,7 @@ int CMPlugin::Load()
int CMPlugin::Unload()
{
+ UnregisterSrmmLog(hLogger);
SplitmsgShutdown();
Unload_ChatModule();
return 0;
diff --git a/src/core/stdmsg/src/stdafx.h b/src/core/stdmsg/src/stdafx.h
index 918f63a017..ea7ed72a3e 100644
--- a/src/core/stdmsg/src/stdafx.h
+++ b/src/core/stdmsg/src/stdafx.h
@@ -155,6 +155,8 @@ struct CMPlugin : public PLUGIN<CMPlugin>
{
CMPlugin();
+ HANDLE hLogger;
+
int Load() override;
int Unload() override;
};
@@ -171,6 +173,7 @@ void Load_ChatModule(void);
// log.cpp
char* Log_CreateRtfHeader(void);
+CSrmmLogWindow *logBuilder(CMsgDialog &pDlg);
// window.cpp
SESSION_INFO* SM_GetPrevWindow(SESSION_INFO *si);
diff --git a/src/core/stdmsg/src/tabs.cpp b/src/core/stdmsg/src/tabs.cpp
index 8366c2d441..e9ae93b50e 100644
--- a/src/core/stdmsg/src/tabs.cpp
+++ b/src/core/stdmsg/src/tabs.cpp
@@ -515,7 +515,7 @@ INT_PTR CTabbedWindow::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam)
if (!((rc.right - rc.left) == oldSizeX && (rc.bottom - rc.top) == oldSizeY)) {
CMsgDialog *pDlg = (g_Settings.bTabsEnable) ? (CMsgDialog*)m_tab.GetActivePage() : m_pEmbed;
if (pDlg != nullptr) {
- pDlg->ScrollToBottom();
+ pDlg->m_pLog->ScrollToBottom();
pDlg->Resize();
}
}