diff options
author | George Hazan <ghazan@miranda.im> | 2019-10-02 20:42:44 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2019-10-02 20:42:44 +0300 |
commit | 7a948f1ef804ecd9971b0869e0591c22944fa6da (patch) | |
tree | cdc2df2e2d5f186da4b8778b4e1c9e79013ff921 /src | |
parent | 9fe4e9044069e70b3f0e1df0e187f5ea43805ea1 (diff) |
merge with SrmmLogContainer
Diffstat (limited to 'src')
-rw-r--r-- | src/core/stdmsg/src/chat_window.cpp | 51 | ||||
-rw-r--r-- | src/core/stdmsg/src/msgdialog.cpp | 170 | ||||
-rw-r--r-- | src/core/stdmsg/src/msglog.cpp | 253 | ||||
-rw-r--r-- | src/core/stdmsg/src/msgs.h | 34 | ||||
-rw-r--r-- | src/core/stdmsg/src/srmm.cpp | 3 | ||||
-rw-r--r-- | src/core/stdmsg/src/stdafx.h | 3 | ||||
-rw-r--r-- | src/core/stdmsg/src/tabs.cpp | 2 | ||||
-rw-r--r-- | src/mir_app/mir_app.vcxproj | 2 | ||||
-rw-r--r-- | src/mir_app/res/resource.rc | 27 | ||||
-rw-r--r-- | src/mir_app/src/chat.h | 6 | ||||
-rw-r--r-- | src/mir_app/src/mir_app.def | 26 | ||||
-rw-r--r-- | src/mir_app/src/mir_app64.def | 26 | ||||
-rw-r--r-- | src/mir_app/src/resource.h | 2 | ||||
-rw-r--r-- | src/mir_app/src/srmm_base.cpp | 277 | ||||
-rw-r--r-- | src/mir_app/src/srmm_log.cpp | 141 | ||||
-rw-r--r-- | src/mir_app/src/srmm_log_hpp.cpp | 259 | ||||
-rw-r--r-- | src/mir_app/src/srmm_log_rtf.cpp | 375 | ||||
-rw-r--r-- | src/mir_app/src/srmm_toolbar.cpp | 4 | ||||
-rw-r--r-- | src/mir_app/src/stdafx.h | 2 | ||||
-rw-r--r-- | src/mir_core/src/CDlgBase.cpp | 5 | ||||
-rw-r--r-- | src/mir_core/src/mir_core.def | 1 | ||||
-rw-r--r-- | src/mir_core/src/mir_core64.def | 1 |
22 files changed, 1157 insertions, 513 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)>xl, 0);
+ fi.chrg.cpMin = m_rtf.SendMsg(EM_GETTEXTLENGTHEX, (WPARAM)>xl, 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(); } } diff --git a/src/mir_app/mir_app.vcxproj b/src/mir_app/mir_app.vcxproj index 9f608d1f60..f06c30786a 100644 --- a/src/mir_app/mir_app.vcxproj +++ b/src/mir_app/mir_app.vcxproj @@ -35,7 +35,7 @@ <ModuleDefinitionFile Condition="'$(Platform)'=='x64'">src/mir_app64.def</ModuleDefinitionFile>
<AdditionalOptions>/ignore:4197 %(AdditionalOptions)</AdditionalOptions>
<AdditionalManifestDependencies>type=%27win32%27 name=%27Microsoft.Windows.Common-Controls%27 version=%276.0.0.0%27 processorArchitecture=%27*%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;type=%27win32%27 name=%27Microsoft.Windows.Gdiplus%27 version=%271.0.0.0%27 processorArchitecture=%27amd64%27 publicKeyToken=%276595b64144ccf1df%27 language=%27*%27;%(AdditionalManifestDependencies)</AdditionalManifestDependencies>
- <AdditionalDependencies>libeay32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>libeay32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Manifest>
<AdditionalManifestFiles>res/miranda32.exe.manifest</AdditionalManifestFiles>
diff --git a/src/mir_app/res/resource.rc b/src/mir_app/res/resource.rc index 50c4de9fbf..d8671c3df3 100644 --- a/src/mir_app/res/resource.rc +++ b/src/mir_app/res/resource.rc @@ -672,6 +672,17 @@ BEGIN CONTROL "Lock name to first contact",IDC_CHK_LOCKHANDLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,151,278,10
END
+IDD_OPT_SRMMLOG DIALOGEX 0, 0, 306, 226
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "Choose needed logger from listed below:",IDC_STATIC,2,3,299,8
+ LISTBOX IDC_LIST,0,16,305,189,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ CONTROL "Enable custom log controls in group chats",IDC_ENABLE_CUSTOM,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,5,210,297,12
+END
+
IDD_OPT_LANGUAGES DIALOGEX 0, 0, 301, 191
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
EXSTYLE WS_EX_CONTROLPARENT
@@ -1018,6 +1029,10 @@ BEGIN BOTTOMMARGIN, 164
END
+ IDD_OPT_SRMMLOG, DIALOG
+ BEGIN
+ END
+
IDD_OPT_LANGUAGES, DIALOG
BEGIN
VERTGUIDE, 5
@@ -1063,7 +1078,8 @@ END 1 TEXTINCLUDE
BEGIN
- "resource.h\0"
+ "#include ""../src/resource.h""\r\n"
+ "\0"
END
2 TEXTINCLUDE
@@ -1320,6 +1336,15 @@ BEGIN END
END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// AFX_DIALOG_LAYOUT
+//
+
+IDD_OPT_SRMMLOG AFX_DIALOG_LAYOUT
+BEGIN
+ 0
END
#endif // English (United States) resources
diff --git a/src/mir_app/src/chat.h b/src/mir_app/src/chat.h index ee0cecafa6..3cc64078fe 100644 --- a/src/mir_app/src/chat.h +++ b/src/mir_app/src/chat.h @@ -28,8 +28,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. void Srmm_CreateToolbarIcons(HWND hwndDlg, int flags);
void Srmm_ProcessToolbarHotkey(MCONTACT hContact, INT_PTR iButtonFrom, HWND hwndDlg);
+class CLogWindow : public CSrmmLogWindow {};
+
class CMsgDialog : public CSrmmBaseDialog
{
+ friend void RedrawLog2(SESSION_INFO *si);
+
CMsgDialog(); // just to suppress compiler's warnings, never implemented
};
@@ -124,6 +128,8 @@ BOOL DoTrayIcon(SESSION_INFO *si, GCEVENT *gce); BOOL DoPopup(SESSION_INFO *si, GCEVENT *gce);
int ShowPopup(MCONTACT hContact, SESSION_INFO *si, HICON hIcon, char* pszProtoName, wchar_t* pszRoomName, COLORREF crBkg, const wchar_t* fmt, ...);
+CSrmmLogWindow *Srmm_GetLogWindow(CMsgDialog *pDlg);
+
const wchar_t* my_strstri(const wchar_t* s1, const wchar_t* s2);
#pragma comment(lib,"comctl32.lib")
diff --git a/src/mir_app/src/mir_app.def b/src/mir_app/src/mir_app.def index 5bfcbfed5a..35f48d6460 100644 --- a/src/mir_app/src/mir_app.def +++ b/src/mir_app/src/mir_app.def @@ -348,9 +348,7 @@ Chat_UpdateOptions @418 NONAME ?ShowColorChooser@CSrmmBaseDialog@@QAEXH@Z @421 NONAME
?ShowFilterMenu@CSrmmBaseDialog@@UAEXXZ @422 NONAME
?OnInitDialog@CSrmmBaseDialog@@MAE_NXZ @423 NONAME
-?StreamInEvents@CSrmmBaseDialog@@UAEXPAULOGINFO@@_N@Z @424 NONAME
?AddLog@CSrmmBaseDialog@@UAEXXZ @425 NONAME
-?ScrollToBottom@CSrmmBaseDialog@@UAEXXZ @427 NONAME
?UpdateNickList@CSrmmBaseDialog@@UAEXXZ @428 NONAME
?onClick_BIU@CSrmmBaseDialog@@IAEXPAVCCtrlButton@@@Z @430 NONAME
?onClick_BkColor@CSrmmBaseDialog@@IAEXPAVCCtrlButton@@@Z @431 NONAME
@@ -359,7 +357,6 @@ Chat_UpdateOptions @418 NONAME ?ProcessHotkeys@CSrmmBaseDialog@@IAE_NH_N00@Z @434 NONAME
?onClick_History@CSrmmBaseDialog@@IAEXPAVCCtrlButton@@@Z @435 NONAME
?onClick_ChanMgr@CSrmmBaseDialog@@IAEXPAVCCtrlButton@@@Z @436 NONAME
-?WndProc_Log@CSrmmBaseDialog@@UAEJIIJ@Z @437 NONAME
?WndProc_Message@CSrmmBaseDialog@@UAEJIIJ@Z @438 NONAME
?WndProc_Nicklist@CSrmmBaseDialog@@UAEJIIJ@Z @439 NONAME
?onDblClick_List@CSrmmBaseDialog@@IAEXPAVCCtrlListBox@@@Z @440 NONAME
@@ -696,3 +693,26 @@ Ignore_IsIgnored @781 Contact_OnList @782
Contact_PutOnList @783
Contact_RemoveFromList @784
+RegisterHppLogger @785
+UnregisterHppLogger @786
+??0CRtfLogWindow@@QAE@AAVCMsgDialog@@@Z @787 NONAME
+??0CSrmmLogWindow@@IAE@AAVCMsgDialog@@@Z @788 NONAME
+??1CRtfLogWindow@@UAE@XZ @789 NONAME
+??1CSrmmLogWindow@@UAE@XZ @790 NONAME
+??_7CRtfLogWindow@@6B@ @791 NONAME
+??_7CSrmmLogWindow@@6B@ @792 NONAME
+?AtBottom@CRtfLogWindow@@UAE_NXZ @793 NONAME
+?Attach@CRtfLogWindow@@UAEXXZ @794 NONAME
+?Clear@CRtfLogWindow@@UAEXXZ @795 NONAME
+?Detach@CRtfLogWindow@@UAEXXZ @796 NONAME
+?GetHwnd@CRtfLogWindow@@UAEPAUHWND__@@XZ @797 NONAME
+?GetSelection@CRtfLogWindow@@UAEPA_WXZ @798 NONAME
+?Notify@CRtfLogWindow@@UAEHIJ@Z @799 NONAME
+?Notify@CSrmmLogWindow@@UAEHIJ@Z @800 NONAME
+?Resize@CRtfLogWindow@@UAEXXZ @801 NONAME
+?ScrollToBottom@CRtfLogWindow@@UAEXXZ @802 NONAME
+?UpdateOptions@CSrmmLogWindow@@UAEXXZ @803 NONAME
+?WndProc@CRtfLogWindow@@UAEHIIJ@Z @804 NONAME
+_RegisterSrmmLog@12 @805 NONAME
+_UnregisterSrmmLog@4 @806 NONAME
+?GetType@CRtfLogWindow@@UAEHXZ @807 NONAME
diff --git a/src/mir_app/src/mir_app64.def b/src/mir_app/src/mir_app64.def index 3a5645f024..95a66ca811 100644 --- a/src/mir_app/src/mir_app64.def +++ b/src/mir_app/src/mir_app64.def @@ -348,9 +348,7 @@ Chat_UpdateOptions @418 NONAME ?ShowColorChooser@CSrmmBaseDialog@@QEAAXH@Z @421 NONAME
?ShowFilterMenu@CSrmmBaseDialog@@UEAAXXZ @422 NONAME
?OnInitDialog@CSrmmBaseDialog@@MEAA_NXZ @423 NONAME
-?StreamInEvents@CSrmmBaseDialog@@UEAAXPEAULOGINFO@@_N@Z @424 NONAME
?AddLog@CSrmmBaseDialog@@UEAAXXZ @425 NONAME
-?ScrollToBottom@CSrmmBaseDialog@@UEAAXXZ @427 NONAME
?UpdateNickList@CSrmmBaseDialog@@UEAAXXZ @428 NONAME
?onClick_BIU@CSrmmBaseDialog@@IEAAXPEAVCCtrlButton@@@Z @430 NONAME
?onClick_BkColor@CSrmmBaseDialog@@IEAAXPEAVCCtrlButton@@@Z @431 NONAME
@@ -359,7 +357,6 @@ Chat_UpdateOptions @418 NONAME ?ProcessHotkeys@CSrmmBaseDialog@@IEAA_NH_N00@Z @434 NONAME
?onClick_History@CSrmmBaseDialog@@IEAAXPEAVCCtrlButton@@@Z @435 NONAME
?onClick_ChanMgr@CSrmmBaseDialog@@IEAAXPEAVCCtrlButton@@@Z @436 NONAME
-?WndProc_Log@CSrmmBaseDialog@@UEAA_JI_K_J@Z @437 NONAME
?WndProc_Message@CSrmmBaseDialog@@UEAA_JI_K_J@Z @438 NONAME
?WndProc_Nicklist@CSrmmBaseDialog@@UEAA_JI_K_J@Z @439 NONAME
?onDblClick_List@CSrmmBaseDialog@@IEAAXPEAVCCtrlListBox@@@Z @440 NONAME
@@ -696,3 +693,26 @@ Ignore_IsIgnored @781 Contact_OnList @782
Contact_PutOnList @783
Contact_RemoveFromList @784
+RegisterHppLogger @785
+UnregisterHppLogger @786
+??0CRtfLogWindow@@QEAA@AEAVCMsgDialog@@@Z @787 NONAME
+??0CSrmmLogWindow@@IEAA@AEAVCMsgDialog@@@Z @788 NONAME
+??1CRtfLogWindow@@UEAA@XZ @789 NONAME
+??1CSrmmLogWindow@@UEAA@XZ @790 NONAME
+??_7CRtfLogWindow@@6B@ @791 NONAME
+??_7CSrmmLogWindow@@6B@ @792 NONAME
+?AtBottom@CRtfLogWindow@@UEAA_NXZ @793 NONAME
+?Attach@CRtfLogWindow@@UEAAXXZ @794 NONAME
+?Clear@CRtfLogWindow@@UEAAXXZ @795 NONAME
+?Detach@CRtfLogWindow@@UEAAXXZ @796 NONAME
+?GetHwnd@CRtfLogWindow@@UEAAPEAUHWND__@@XZ @797 NONAME
+?GetSelection@CRtfLogWindow@@UEAAPEA_WXZ @798 NONAME
+?Notify@CRtfLogWindow@@UEAA_J_K_J@Z @799 NONAME
+?Notify@CSrmmLogWindow@@UEAA_J_K_J@Z @800 NONAME
+?Resize@CRtfLogWindow@@UEAAXXZ @801 NONAME
+?ScrollToBottom@CRtfLogWindow@@UEAAXXZ @802 NONAME
+?UpdateOptions@CSrmmLogWindow@@UEAAXXZ @803 NONAME
+?WndProc@CRtfLogWindow@@UEAA_JI_K_J@Z @804 NONAME
+RegisterSrmmLog @805 NONAME
+UnregisterSrmmLog @806 NONAME
+?GetType@CRtfLogWindow@@UEAAHXZ @807 NONAME
diff --git a/src/mir_app/src/resource.h b/src/mir_app/src/resource.h index fbf6d7920e..0d8e754683 100644 --- a/src/mir_app/src/resource.h +++ b/src/mir_app/src/resource.h @@ -18,6 +18,7 @@ #define IDD_OPT_PROTOCOLORDER 109
#define IDD_OPT_ICOLIB 110
#define IDD_ICOLIB_IMPORT 111
+#define IDD_OPT_SRMMLOG 112
#define IDI_LOADED_GRAY 113
#define IDI_NOTLOADED_GRAY 114
#define IDD_ADDED 115
@@ -540,6 +541,7 @@ #define IDC_RADIO1 1740
#define IDC_RADIO2 1741
#define IDC_ADDCHECK 1742
+#define IDC_ENABLE_CUSTOM 1743
#define IDC_GETMOREPLUGINS 1744
#define IDC_DISABLEMENUICONS 1745
#define IDC_SM_ENABLED 1746
diff --git a/src/mir_app/src/srmm_base.cpp b/src/mir_app/src/srmm_base.cpp index cf4685ef6b..11b955dda5 100644 --- a/src/mir_app/src/srmm_base.cpp +++ b/src/mir_app/src/srmm_base.cpp @@ -30,7 +30,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. CSrmmBaseDialog::CSrmmBaseDialog(CMPluginBase &pPlugin, int idDialog, SESSION_INFO *si) : CDlgBase(pPlugin, idDialog), - m_log(this, IDC_SRMM_LOG), m_message(this, IDC_SRMM_MESSAGE), m_nickList(this, IDC_SRMM_NICKLIST), @@ -134,193 +133,6 @@ static LRESULT CALLBACK Srmm_ButtonSubclassProc(HWND hwnd, UINT msg, WPARAM wPar ///////////////////////////////////////////////////////////////////////////////////////// -static wchar_t szTrimString[] = L":;,.!?\'\"><()[]- \r\n"; - -EXTERN_C MIR_APP_DLL(LRESULT) CALLBACK stubLogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - CSrmmBaseDialog *pDlg = (CSrmmBaseDialog*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); - if (pDlg != nullptr) - return pDlg->WndProc_Log(msg, wParam, lParam); - - return mir_callNextSubclass(hwnd, stubLogProc, msg, wParam, lParam); -} - -LRESULT CSrmmBaseDialog::WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam) -{ - CHARRANGE sel; - - switch (msg) { - case WM_ACTIVATE: - if (LOWORD(wParam) == WA_INACTIVE) { - m_log.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel); - if (sel.cpMin != sel.cpMax) { - sel.cpMin = sel.cpMax; - m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel); - } - } - break; - - case WM_SETCURSOR: - if (m_bInMenu) { - SetCursor(LoadCursor(nullptr, IDC_ARROW)); - return TRUE; - } - break; - - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - if (!(GetKeyState(VK_RMENU) & 0x8000)) { - MSG message = { m_hwnd, msg, wParam, lParam }; - LRESULT iButtonFrom = Hotkey_Check(&message, BB_HK_SECTION); - if (iButtonFrom) { - Srmm_ProcessToolbarHotkey(m_hContact, iButtonFrom, m_hwnd); - return TRUE; - } - } - break; - - case WM_CHAR: - if (wParam >= ' ') { - SetFocus(m_message.GetHwnd()); - m_message.SendMsg(WM_CHAR, wParam, lParam); - } - else if (wParam == '\t') - SetFocus(m_message.GetHwnd()); - break; - - case WM_CONTEXTMENU: - POINT pt, ptl; - m_log.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel); - if (lParam == 0xFFFFFFFF) { - m_log.SendMsg(EM_POSFROMCHAR, (WPARAM)&pt, (LPARAM)sel.cpMax); - ClientToScreen(m_log.GetHwnd(), &pt); - } - else { - pt.x = GET_X_LPARAM(lParam); - pt.y = GET_Y_LPARAM(lParam); - } - ptl = pt; - ScreenToClient(m_log.GetHwnd(), (LPPOINT)&ptl); - { - wchar_t *pszWord = (wchar_t*)_alloca(8192); - pszWord[0] = '\0'; - - // get a word under cursor - if (sel.cpMin == sel.cpMax) { - int iCharIndex = m_log.SendMsg(EM_CHARFROMPOS, 0, (LPARAM)&ptl); - if (iCharIndex < 0) - break; - - sel.cpMin = m_log.SendMsg(EM_FINDWORDBREAK, WB_LEFT, iCharIndex); - sel.cpMax = m_log.SendMsg(EM_FINDWORDBREAK, WB_RIGHT, iCharIndex); - } - - if (sel.cpMax > sel.cpMin) { - TEXTRANGE tr = { 0 }; - tr.chrg = sel; - tr.lpstrText = pszWord; - int iRes = m_log.SendMsg(EM_GETTEXTRANGE, 0, (LPARAM)&tr); - if (iRes > 0) { - wchar_t *p = wcschr(pszWord, '\r'); - if (p) *p = 0; - - size_t iLen = mir_wstrlen(pszWord) - 1; - while (wcschr(szTrimString, pszWord[iLen])) { - pszWord[iLen] = '\0'; - iLen--; - } - } - } - - CHARRANGE all = { 0, -1 }; - HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_LOGMENU)); - HMENU hSubMenu = GetSubMenu(hMenu, 0); - TranslateMenu(hSubMenu); - m_bInMenu = true; - UINT uID = CreateGCMenu(m_log.GetHwnd(), hSubMenu, pt, m_si, nullptr, pszWord); - m_bInMenu = false; - switch (uID) { - case 0: - PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); - break; - - case IDM_COPYALL: - m_log.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel); - m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)&all); - m_log.SendMsg(WM_COPY, 0, 0); - m_log.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel); - PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); - break; - - case IDM_CLEAR: - m_log.SetText(L""); - if (m_si) { - g_chatApi.LM_RemoveAll(&m_si->pLog, &m_si->pLogEnd); - m_si->iEventCount = 0; - m_si->LastTime = 0; - } - PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); - break; - - case IDM_SEARCH_GOOGLE: - case IDM_SEARCH_BING: - case IDM_SEARCH_YANDEX: - case IDM_SEARCH_YAHOO: - case IDM_SEARCH_WIKIPEDIA: - case IDM_SEARCH_FOODNETWORK: - case IDM_SEARCH_GOOGLE_MAPS: - case IDM_SEARCH_GOOGLE_TRANSLATE: - { - CMStringW szURL; - switch (uID) { - case IDM_SEARCH_WIKIPEDIA: - szURL.Format(L"http://en.wikipedia.org/wiki/%s", pszWord); - break; - case IDM_SEARCH_YAHOO: - szURL.Format(L"http://search.yahoo.com/search?p=%s&ei=UTF-8", pszWord); - break; - case IDM_SEARCH_FOODNETWORK: - szURL.Format(L"http://search.foodnetwork.com/search/delegate.do?fnSearchString=%s", pszWord); - break; - case IDM_SEARCH_BING: - szURL.Format(L"http://www.bing.com/search?q=%s&form=OSDSRC", pszWord); - break; - case IDM_SEARCH_GOOGLE_MAPS: - szURL.Format(L"http://maps.google.com/maps?q=%s&ie=utf-8&oe=utf-8", pszWord); - break; - case IDM_SEARCH_GOOGLE_TRANSLATE: - szURL.Format(L"http://translate.google.com/?q=%s&ie=utf-8&oe=utf-8", pszWord); - break; - case IDM_SEARCH_YANDEX: - szURL.Format(L"http://yandex.ru/yandsearch?text=%s", pszWord); - break; - case IDM_SEARCH_GOOGLE: - szURL.Format(L"http://www.google.com/search?q=%s&ie=utf-8&oe=utf-8", pszWord); - break; - } - Utils_OpenUrlW(szURL); - } - PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); - break; - - default: - PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); - Chat_DoEventHook(m_si, GC_USER_LOGMENU, nullptr, nullptr, uID); - break; - } - DestroyMenu(hMenu); - } - break; - } - - LRESULT res = mir_callNextSubclass(m_log.GetHwnd(), stubLogProc, msg, wParam, lParam); - if (msg == WM_GETDLGCODE) - return res & ~DLGC_HASSETSEL; - return res; -} - -///////////////////////////////////////////////////////////////////////////////////////// - EXTERN_C MIR_APP_DLL(LRESULT) CALLBACK stubMessageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { CSrmmBaseDialog *pDlg = (CSrmmBaseDialog*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); @@ -636,9 +448,13 @@ bool CSrmmBaseDialog::OnInitDialog() WindowList_Add(g_hWindowList, m_hwnd, m_hContact); SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)this); - SetWindowLongPtr(m_log.GetHwnd(), GWLP_USERDATA, LPARAM(this)); - mir_subclassWindow(m_log.GetHwnd(), stubLogProc); - m_log.SetReadOnly(true); + m_pLog = Srmm_GetLogWindow((CMsgDialog*)this); + if (m_pLog->GetType() != 0) { // custom log type + HWND hwndLog = GetDlgItem(m_hwnd, IDC_SRMM_LOG); + EnableWindow(hwndLog, FALSE); + ShowWindow(hwndLog, SW_HIDE); + } + m_pLog->Attach(); SetWindowLongPtr(m_message.GetHwnd(), GWLP_USERDATA, LPARAM(this)); mir_subclassWindow(m_message.GetHwnd(), stubMessageProc); @@ -661,10 +477,12 @@ bool CSrmmBaseDialog::OnInitDialog() void CSrmmBaseDialog::OnDestroy() { + m_pLog->Detach(); + delete m_pLog; + WindowList_Remove(g_hWindowList, m_hwnd); SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0); - mir_unsubclassWindow(m_log.GetHwnd(), stubLogProc); mir_unsubclassWindow(m_message.GetHwnd(), stubMessageProc); mir_unsubclassWindow(m_nickList.GetHwnd(), stubNicklistProc); } @@ -697,65 +515,8 @@ INT_PTR CSrmmBaseDialog::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) case WM_NOTIFY: LPNMHDR hdr = (LPNMHDR)lParam; - if (hdr->hwndFrom == m_log.GetHwnd() && hdr->code == EN_LINK) { - ENLINK *pLink = (ENLINK*)lParam; - switch (pLink->msg) { - case WM_SETCURSOR: - SetCursor(g_hCurHyperlinkHand); - SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, TRUE); - return TRUE; - - case WM_RBUTTONDOWN: - case WM_LBUTTONUP: - case WM_LBUTTONDBLCLK: - CHARRANGE sel; - m_log.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel); - if (sel.cpMin != sel.cpMax) - break; - - CMStringW wszText(' ', pLink->chrg.cpMax - pLink->chrg.cpMin + 1); - - TEXTRANGE tr; - tr.chrg = pLink->chrg; - tr.lpstrText = wszText.GetBuffer(); - m_log.SendMsg(EM_GETTEXTRANGE, 0, (LPARAM)&tr); - if (wcschr(tr.lpstrText, '@') != nullptr && wcschr(tr.lpstrText, ':') == nullptr && wcschr(tr.lpstrText, '/') == nullptr) - wszText.Insert(0, L"mailto:"); - - if (pLink->msg == WM_RBUTTONDOWN) { - HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_CONTEXT)); - HMENU hSubMenu = GetSubMenu(hMenu, 6); - TranslateMenu(hSubMenu); - - POINT pt = { GET_X_LPARAM(pLink->lParam), GET_Y_LPARAM(pLink->lParam) }; - ClientToScreen(((NMHDR *)lParam)->hwndFrom, &pt); - - switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, m_hwnd, nullptr)) { - case IDM_OPENLINK: - Utils_OpenUrlW(wszText); - break; - - case IDM_COPYLINK: - if (OpenClipboard(m_hwnd)) { - EmptyClipboard(); - HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE, (wszText.GetLength() + 1) * sizeof(wchar_t)); - mir_wstrcpy((wchar_t*)GlobalLock(hData), wszText); - GlobalUnlock(hData); - SetClipboardData(CF_UNICODETEXT, hData); - CloseClipboard(); - } - break; - } - - DestroyMenu(hMenu); - SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, TRUE); - return TRUE; - } - - Utils_OpenUrlW(wszText); - SetFocus(m_message.GetHwnd()); - } - } + if (hdr->hwndFrom == m_pLog->GetHwnd()) + m_pLog->Notify(wParam, lParam); break; } @@ -765,14 +526,14 @@ INT_PTR CSrmmBaseDialog::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) void CSrmmBaseDialog::AddLog() { if (m_si->pLogEnd) - StreamInEvents(m_si->pLog, false); + m_pLog->LogEvents(m_si->pLog, false); else - ClearLog(); + m_pLog->Clear(); } void CSrmmBaseDialog::ClearLog() { - m_log.SetText(L""); + m_pLog->Clear(); } void CSrmmBaseDialog::UpdateOptions() @@ -796,7 +557,7 @@ void RedrawLog2(SESSION_INFO *si) { si->LastTime = 0; if (si->pLog) - si->pDlg->StreamInEvents(si->pLogEnd, TRUE); + si->pDlg->m_pLog->LogEvents(si->pLogEnd, TRUE); } static void __cdecl phase2(SESSION_INFO *si) @@ -821,10 +582,10 @@ void CSrmmBaseDialog::RedrawLog() if (m_si->iType != GCW_CHATROOM || !m_bFilterEnabled || (m_iLogFilterFlags & pLog->iType) != 0) index++; } - StreamInEvents(pLog, true); + m_pLog->LogEvents(pLog, true); mir_forkThread<SESSION_INFO>(phase2, m_si); } - else StreamInEvents(m_si->pLogEnd, true); + else m_pLog->LogEvents(m_si->pLogEnd, true); } else ClearLog(); } @@ -955,7 +716,7 @@ int CSrmmBaseDialog::NotifyEvent(int code) mwe.uType = code; mwe.uFlags = MSG_WINDOW_UFLAG_MSG_BOTH; mwe.hwndInput = m_message.GetHwnd(); - mwe.hwndLog = m_log.GetHwnd(); + mwe.hwndLog = m_pLog->GetHwnd(); return ::NotifyEventHooks(hHookSrmmEvent, 0, (LPARAM)&mwe); } diff --git a/src/mir_app/src/srmm_log.cpp b/src/mir_app/src/srmm_log.cpp new file mode 100644 index 0000000000..27bf946237 --- /dev/null +++ b/src/mir_app/src/srmm_log.cpp @@ -0,0 +1,141 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-19 Miranda NG team, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +///////////////////////////////////////////////////////////////////////////////////////// +// SRMM log container + +#include "stdafx.h" +#include "chat.h" + +struct LoggerClass +{ + LoggerClass(const char *p1, const wchar_t *p2, pfnSrmmLogCreator p3) : + szShortName(mir_strdup(p1)), + wszScreenName(mir_wstrdup(p2)), + pfnBuilder(p3) + {} + + ptrA szShortName; + ptrW wszScreenName; + pfnSrmmLogCreator pfnBuilder; +}; + +static OBJLIST<LoggerClass> g_arLogClasses(1, PtrKeySortT); + +static CMOption<BYTE> g_bEnableCustomLogs("SRMM", "EnableCustomLogs", 0); + +///////////////////////////////////////////////////////////////////////////////////////// + +MIR_APP_DLL(HANDLE) RegisterSrmmLog(const char *pszShortName, const wchar_t *pwszScreenName, pfnSrmmLogCreator fnBuilder) +{ + if (!pszShortName || !pwszScreenName || !fnBuilder) + return nullptr; + + auto *p = new LoggerClass(pszShortName, pwszScreenName, fnBuilder); + g_arLogClasses.insert(p); + return p; +} + +MIR_APP_DLL(void) UnregisterSrmmLog(HANDLE pLogger) +{ + g_arLogClasses.remove((LoggerClass *)pLogger); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +CSrmmLogWindow* Srmm_GetLogWindow(CMsgDialog *pDlg) +{ + if (!pDlg->isChat() || g_bEnableCustomLogs) { + ptrA szCurr(db_get_sa(0, "SRMM", "Logger", "built-in")); + + for (auto &it : g_arLogClasses) + if (!mir_strcmp(szCurr, it->szShortName)) + return it->pfnBuilder(*pDlg); + } + + for (auto &it : g_arLogClasses) + if (!mir_strcmp(it->szShortName, "built-in")) + return it->pfnBuilder(*pDlg); + + return nullptr; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// options dialog + +class CSrmmLogOptionsDlg : public CDlgBase +{ + CCtrlListBox m_list; + CCtrlCheck chkCustomLogs; + +public: + CSrmmLogOptionsDlg() : + CDlgBase(g_plugin, IDD_OPT_SRMMLOG), + m_list(this, IDC_LIST), + chkCustomLogs(this, IDC_ENABLE_CUSTOM) + { + CreateLink(chkCustomLogs, g_bEnableCustomLogs); + + m_list.OnSelChange = Callback(this, &CSrmmLogOptionsDlg::onChange_List); + } + + bool OnInitDialog() override + { + ptrA szCurr(db_get_sa(0, "SRMM", "Logger", "built-in")); + + for (auto &it : g_arLogClasses) { + int idx = m_list.AddString(it->wszScreenName, LPARAM(it)); + if (!mir_strcmp(szCurr, it->szShortName)) + m_list.SetCurSel(idx); + } + + return true; + } + + bool OnApply() override + { + int idx = m_list.GetCurSel(); + if (idx == -1) + return false; + + auto *pLogger = (LoggerClass *)m_list.GetItemData(idx); + db_set_s(0, "SRMM", "Logger", pLogger->szShortName); + return true; + } + + void onChange_List(CCtrlListBox *) + { + NotifyChange(); + } +}; + +void SrmmLogOptionsInit(WPARAM wParam) +{ + OPTIONSDIALOGPAGE odp = {}; + odp.position = 910000000; + odp.szGroup.a = LPGEN("Message sessions"); + odp.szTitle.a = LPGEN("Log viewer"); + odp.flags = ODPF_BOLDGROUPS; + odp.pDialog = new CSrmmLogOptionsDlg(); + g_plugin.addOptions(wParam, &odp); +} diff --git a/src/mir_app/src/srmm_log_hpp.cpp b/src/mir_app/src/srmm_log_hpp.cpp new file mode 100644 index 0000000000..de829ebe3b --- /dev/null +++ b/src/mir_app/src/srmm_log_hpp.cpp @@ -0,0 +1,259 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-19 Miranda NG team, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +///////////////////////////////////////////////////////////////////////////////////////// +// CHppLogWindow class + +#include "stdafx.h" +#include "chat.h" + +#define EVENTTYPE_STATUSCHANGE 25368 +#define EVENTTYPE_ERRMSG 25366 + +class CHppLogWindow : public CSrmmLogWindow +{ + HWND m_hwnd = nullptr; + +public: + CHppLogWindow(CMsgDialog &pDlg) : + CSrmmLogWindow(pDlg) + { + } + + void Attach() override + { + IEVIEWWINDOW ieWindow = {}; + ieWindow.iType = IEW_CREATE; + ieWindow.dwMode = IEWM_TABSRMM; + ieWindow.parent = m_pDlg.GetHwnd(); + ieWindow.cx = 10; + ieWindow.cy = 10; + CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow); + m_hwnd = ieWindow.hwnd; + } + + void Detach() override + { + IEVIEWWINDOW ieWindow = {}; + ieWindow.iType = IEW_DESTROY; + ieWindow.hwnd = m_hwnd; + CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow); + } + + ////////////////////////////////////////////////////////////////////////////////////// + + bool AtBottom() override + { + return false; + } + + void Clear() override + { + IEVIEWEVENT event = {}; + event.iType = IEE_CLEAR_LOG; + event.hwnd = m_hwnd; + CallService(MS_HPP_EG_EVENT, 0, (LPARAM)&event); + } + + HWND GetHwnd() override + { + return m_hwnd; + } + + int GetType() override + { + return 2; + } + + wchar_t* GetSelection() override + { + IEVIEWEVENT event = {}; + event.hwnd = m_hwnd; + event.iType = IEE_GET_SELECTION; + event.hContact = m_pDlg.m_hContact; + event.dwFlags = 0; + return (wchar_t *)CallService(MS_HPP_EG_EVENT, 0, (LPARAM)&event); + } + + void LogEvents(MEVENT hDbEventFirst, int count, bool bAppend) override + { + if (!bAppend) + Clear(); + + IEVIEWEVENT event = {}; + event.hwnd = m_hwnd; + event.iType = IEE_LOG_DB_EVENTS; + event.hDbEventFirst = hDbEventFirst; + event.hContact = m_pDlg.m_hContact; + event.count = count; + CallService(MS_HPP_EG_EVENT, 0, (LPARAM)&event); + } + + void LogEvents(DBEVENTINFO *dbei, bool bAppend) override + { + if (!bAppend) + Clear(); + + IEVIEWEVENT event = {}; + event.hwnd = m_hwnd; + event.iType = IEE_LOG_MEM_EVENTS; + + IEVIEWEVENTDATA evData = {}; + if (dbei->flags & DBEF_SENT) { + evData.dwFlags = IEEDF_SENT; + evData.bIsMe = true; + } + else { + evData.dwFlags = IEEDF_UNICODE_NICK; + evData.szNick.w = Clist_GetContactDisplayName(m_pDlg.m_hContact); + } + switch (dbei->eventType) { + case EVENTTYPE_STATUSCHANGE: evData.iType = IEED_EVENT_STATUSCHANGE; break; + case EVENTTYPE_FILE: evData.iType = IEED_EVENT_FILE; break; + case EVENTTYPE_ERRMSG: evData.iType = IEED_EVENT_ERRMSG; break; + default: evData.iType = IEED_EVENT_MESSAGE; break; + } + evData.szText.a = (char *)dbei->pBlob; + evData.time = dbei->timestamp; + event.eventData = &evData; + event.codepage = CP_UTF8; + event.count = 1; + CallService(MS_HPP_EG_EVENT, 0, (LPARAM)&event); + } + + void CHppLogWindow::LogEvents(LOGINFO *pLog, bool) + { + IEVIEWEVENTDATA ied = {}; + ied.dwFlags = IEEDF_UNICODE_NICK | IEEDF_UNICODE_TEXT; + + IEVIEWEVENT event = {}; + event.hwnd = m_hwnd; + event.hContact = m_pDlg.m_hContact; + event.codepage = CP_ACP; + event.iType = IEE_LOG_MEM_EVENTS; + event.eventData = &ied; + event.count = 1; + + while (pLog) { + if (pLog->ptszText) { + ied.szNick.w = pLog->ptszNick; + ied.szText.w = pLog->ptszText; + ied.time = pLog->time; + ied.bIsMe = pLog->bIsMe; + + switch (pLog->iType) { + case GC_EVENT_MESSAGE: + ied.iType = IEED_GC_EVENT_MESSAGE; + ied.dwData = IEEDD_GC_SHOW_NICK; + break; + case GC_EVENT_ACTION: + ied.iType = IEED_GC_EVENT_ACTION; + break; + case GC_EVENT_JOIN: + ied.iType = IEED_GC_EVENT_JOIN; + break; + case GC_EVENT_PART: + ied.iType = IEED_GC_EVENT_PART; + break; + case GC_EVENT_QUIT: + ied.iType = IEED_GC_EVENT_QUIT; + break; + case GC_EVENT_NICK: + ied.iType = IEED_GC_EVENT_NICK; + break; + case GC_EVENT_KICK: + ied.iType = IEED_GC_EVENT_KICK; + break; + case GC_EVENT_NOTICE: + ied.iType = IEED_GC_EVENT_NOTICE; + break; + case GC_EVENT_TOPIC: + ied.iType = IEED_GC_EVENT_TOPIC; + break; + case GC_EVENT_INFORMATION: + ied.iType = IEED_GC_EVENT_INFORMATION; + break; + case GC_EVENT_ADDSTATUS: + ied.iType = IEED_GC_EVENT_ADDSTATUS; + break; + case GC_EVENT_REMOVESTATUS: + ied.iType = IEED_GC_EVENT_REMOVESTATUS; + break; + } + ied.dwData |= g_Settings->bShowTime ? IEEDD_GC_SHOW_TIME : 0; + ied.dwData |= IEEDD_GC_SHOW_ICON; + ied.dwFlags = IEEDF_UNICODE_TEXT | IEEDF_UNICODE_NICK | IEEDF_UNICODE_TEXT2; + CallService(MS_HPP_EG_EVENT, 0, (LPARAM) & event); + } + + pLog = pLog->prev; + } + } + + void Resize() override + { + RECT rcRichEdit; + GetWindowRect(GetDlgItem(m_pDlg.GetHwnd(), IDC_SRMM_LOG), &rcRichEdit); + + POINT pt = { rcRichEdit.left, rcRichEdit.top }; + ScreenToClient(GetParent(m_hwnd), &pt); + + IEVIEWWINDOW ieWindow = { sizeof(ieWindow) }; + ieWindow.iType = IEW_SETPOS; + ieWindow.parent = m_hwnd; + ieWindow.hwnd = m_hwnd; + ieWindow.x = pt.x; + ieWindow.y = pt.y; + ieWindow.cx = rcRichEdit.right - rcRichEdit.left; + ieWindow.cy = rcRichEdit.bottom - rcRichEdit.top; + if (ieWindow.cx != 0 && ieWindow.cy != 0) + CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow); + } + + void ScrollToBottom() override + { + IEVIEWWINDOW iew = { sizeof(iew) }; + iew.iType = IEW_SCROLLBOTTOM; + iew.hwnd = m_hwnd; + CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)&iew); + } +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +static HANDLE hLogger; + +static CSrmmLogWindow *logBuilder(CMsgDialog &pDlg) +{ + return new CHppLogWindow(pDlg); +} + +MIR_APP_DLL(void) RegisterHppLogger() +{ + hLogger = RegisterSrmmLog("hpp", L"History++ log", &logBuilder); +} + +MIR_APP_DLL(void) UnregisterHppLogger() +{ + UnregisterSrmmLog(hLogger); +} diff --git a/src/mir_app/src/srmm_log_rtf.cpp b/src/mir_app/src/srmm_log_rtf.cpp new file mode 100644 index 0000000000..f13cfbff43 --- /dev/null +++ b/src/mir_app/src/srmm_log_rtf.cpp @@ -0,0 +1,375 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-19 Miranda NG team, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +///////////////////////////////////////////////////////////////////////////////////////// +// SRMM log container + +#include "stdafx.h" +#include "chat.h" + +#define EVENTTYPE_STATUSCHANGE 25368 +#define EVENTTYPE_ERRMSG 25366 + +CRtfLogWindow::CRtfLogWindow(CMsgDialog &pDlg) : + CSrmmLogWindow(pDlg), + m_rtf(*(CCtrlRichEdit*)pDlg.FindControl(IDC_SRMM_LOG)) +{ +} + +CRtfLogWindow::~CRtfLogWindow() +{ +} + +///////////////////////////////////////////////////////////////////////////////////////// + +EXTERN_C MIR_APP_DLL(LRESULT) CALLBACK stubLogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + CRtfLogWindow *pLog = (CRtfLogWindow *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + if (pLog != nullptr) + return pLog->WndProc(msg, wParam, lParam); + + return mir_callNextSubclass(hwnd, stubLogProc, msg, wParam, lParam); +} + +void CRtfLogWindow::Attach() +{ + SetWindowLongPtr(m_rtf.GetHwnd(), GWLP_USERDATA, LPARAM(this)); + m_rtf.SetReadOnly(true); + + mir_subclassWindow(m_rtf.GetHwnd(), stubLogProc); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CRtfLogWindow::Detach() +{ + mir_unsubclassWindow(m_rtf.GetHwnd(), stubLogProc); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +bool CRtfLogWindow::AtBottom() +{ + if (!(GetWindowLongPtr(m_rtf.GetHwnd(), GWL_STYLE) & WS_VSCROLL)) + return true; + + SCROLLINFO si = {}; + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; + GetScrollInfo(m_rtf.GetHwnd(), SB_VERT, &si); + return (si.nPos + (int)si.nPage + 5) >= si.nMax; +} + +void CRtfLogWindow::Clear() +{ + m_rtf.SetText(L""); +} + +HWND CRtfLogWindow::GetHwnd() +{ + return m_rtf.GetHwnd(); +} + +int CRtfLogWindow::GetType() +{ + return 0; +} + +wchar_t* CRtfLogWindow::GetSelection() +{ + return nullptr; +} + +INT_PTR CRtfLogWindow::Notify(WPARAM, LPARAM lParam) +{ + LPNMHDR hdr = (LPNMHDR)lParam; + if (hdr->code != EN_LINK) + return FALSE; + + ENLINK *pLink = (ENLINK *)lParam; + switch (pLink->msg) { + case WM_SETCURSOR: + SetCursor(g_hCurHyperlinkHand); + SetWindowLongPtr(m_pDlg.m_hwnd, DWLP_MSGRESULT, TRUE); + return TRUE; + + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + case WM_LBUTTONDBLCLK: + CHARRANGE sel; + m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin != sel.cpMax) + break; + + CMStringW wszText(' ', pLink->chrg.cpMax - pLink->chrg.cpMin + 1); + + TEXTRANGE tr; + tr.chrg = pLink->chrg; + tr.lpstrText = wszText.GetBuffer(); + m_rtf.SendMsg(EM_GETTEXTRANGE, 0, (LPARAM)&tr); + if (wcschr(tr.lpstrText, '@') != nullptr && wcschr(tr.lpstrText, ':') == nullptr && wcschr(tr.lpstrText, '/') == nullptr) + wszText.Insert(0, L"mailto:"); + + if (pLink->msg == WM_RBUTTONDOWN) { + HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_CONTEXT)); + HMENU hSubMenu = GetSubMenu(hMenu, 6); + TranslateMenu(hSubMenu); + + POINT pt = { GET_X_LPARAM(pLink->lParam), GET_Y_LPARAM(pLink->lParam) }; + ClientToScreen(((NMHDR *)lParam)->hwndFrom, &pt); + + switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, m_pDlg.m_hwnd, nullptr)) { + case IDM_OPENLINK: + Utils_OpenUrlW(wszText); + break; + + case IDM_COPYLINK: + if (OpenClipboard(m_pDlg.m_hwnd)) { + EmptyClipboard(); + HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE, (wszText.GetLength() + 1) * sizeof(wchar_t)); + mir_wstrcpy((wchar_t *)GlobalLock(hData), wszText); + GlobalUnlock(hData); + SetClipboardData(CF_UNICODETEXT, hData); + CloseClipboard(); + } + break; + } + + DestroyMenu(hMenu); + SetWindowLongPtr(m_pDlg.m_hwnd, DWLP_MSGRESULT, TRUE); + return TRUE; + } + + Utils_OpenUrlW(wszText); + SetFocus(m_pDlg.m_message.GetHwnd()); + } + + return FALSE; +} + +void CRtfLogWindow::Resize() +{ + bool bottomScroll = !m_pDlg.isChat(); + if (AtBottom()) + bottomScroll = true; + + // ::MoveWindow(m_rtf.GetHwnd(), x, y, cx, cy, true); + + if (bottomScroll) + ScrollToBottom(); +} + +void CRtfLogWindow::ScrollToBottom() +{ + if (!(GetWindowLongPtr(m_rtf.GetHwnd(), GWL_STYLE) & WS_VSCROLL)) + return; + + SCROLLINFO si = {}; + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_RANGE; + GetScrollInfo(m_rtf.GetHwnd(), SB_VERT, &si); + + si.fMask = SIF_POS; + si.nPos = si.nMax - si.nPage; + SetScrollInfo(m_rtf.GetHwnd(), SB_VERT, &si, TRUE); + m_rtf.SendMsg(WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, 0), 0); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static wchar_t szTrimString[] = L":;,.!?\'\"><()[]- \r\n"; + +INT_PTR CRtfLogWindow::WndProc(UINT msg, WPARAM wParam, LPARAM lParam) +{ + CHARRANGE sel; + + switch (msg) { + case WM_ACTIVATE: + if (LOWORD(wParam) == WA_INACTIVE) { + m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin != sel.cpMax) { + sel.cpMin = sel.cpMax; + m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel); + } + } + break; + + case WM_SETCURSOR: + if (m_pDlg.m_bInMenu) { + SetCursor(LoadCursor(nullptr, IDC_ARROW)); + return TRUE; + } + break; + + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + if (!(GetKeyState(VK_RMENU) & 0x8000)) { + MSG message = { m_pDlg.m_hwnd, msg, wParam, lParam }; + LRESULT iButtonFrom = Hotkey_Check(&message, BB_HK_SECTION); + if (iButtonFrom) { + Srmm_ProcessToolbarHotkey(m_pDlg.m_hContact, iButtonFrom, m_pDlg.m_hwnd); + return TRUE; + } + } + break; + + case WM_CHAR: + if (wParam >= ' ') { + SetFocus(m_pDlg.m_message.GetHwnd()); + m_pDlg.m_message.SendMsg(WM_CHAR, wParam, lParam); + } + else if (wParam == '\t') + SetFocus(m_pDlg.m_message.GetHwnd()); + break; + + case WM_CONTEXTMENU: + POINT pt, ptl; + m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel); + if (lParam == 0xFFFFFFFF) { + 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); + } + ptl = pt; + ScreenToClient(m_rtf.GetHwnd(), (LPPOINT)&ptl); + { + wchar_t *pszWord = (wchar_t *)_alloca(8192); + pszWord[0] = '\0'; + + // get a word under cursor + if (sel.cpMin == sel.cpMax) { + int iCharIndex = m_rtf.SendMsg(EM_CHARFROMPOS, 0, (LPARAM)&ptl); + if (iCharIndex < 0) + break; + + sel.cpMin = m_rtf.SendMsg(EM_FINDWORDBREAK, WB_LEFT, iCharIndex); + sel.cpMax = m_rtf.SendMsg(EM_FINDWORDBREAK, WB_RIGHT, iCharIndex); + } + + if (sel.cpMax > sel.cpMin) { + TEXTRANGE tr = { 0 }; + tr.chrg = sel; + tr.lpstrText = pszWord; + int iRes = m_rtf.SendMsg(EM_GETTEXTRANGE, 0, (LPARAM)&tr); + if (iRes > 0) { + wchar_t *p = wcschr(pszWord, '\r'); + if (p) + *p = 0; + + size_t iLen = mir_wstrlen(pszWord) - 1; + while (wcschr(szTrimString, pszWord[iLen])) { + pszWord[iLen] = '\0'; + iLen--; + } + } + } + + CHARRANGE all = { 0, -1 }; + HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_LOGMENU)); + HMENU hSubMenu = GetSubMenu(hMenu, 0); + TranslateMenu(hSubMenu); + m_pDlg.m_bInMenu = true; + UINT uID = CreateGCMenu(m_rtf.GetHwnd(), hSubMenu, pt, m_pDlg.m_si, nullptr, pszWord); + m_pDlg.m_bInMenu = false; + switch (uID) { + case 0: + PostMessage(m_pDlg.m_hwnd, WM_MOUSEACTIVATE, 0, 0); + break; + + case IDM_COPYALL: + m_rtf.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel); + m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&all); + m_rtf.SendMsg(WM_COPY, 0, 0); + m_rtf.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel); + PostMessage(m_pDlg.m_hwnd, WM_MOUSEACTIVATE, 0, 0); + break; + + case IDM_CLEAR: + m_rtf.SetText(L""); + if (auto *si = m_pDlg.m_si) { + g_chatApi.LM_RemoveAll(&si->pLog, &si->pLogEnd); + si->iEventCount = 0; + si->LastTime = 0; + } + PostMessage(m_pDlg.m_hwnd, WM_MOUSEACTIVATE, 0, 0); + break; + + case IDM_SEARCH_GOOGLE: + case IDM_SEARCH_BING: + case IDM_SEARCH_YANDEX: + case IDM_SEARCH_YAHOO: + case IDM_SEARCH_WIKIPEDIA: + case IDM_SEARCH_FOODNETWORK: + case IDM_SEARCH_GOOGLE_MAPS: + case IDM_SEARCH_GOOGLE_TRANSLATE: + { + CMStringW szURL; + switch (uID) { + case IDM_SEARCH_WIKIPEDIA: + szURL.Format(L"http://en.wikipedia.org/wiki/%s", pszWord); + break; + case IDM_SEARCH_YAHOO: + szURL.Format(L"http://search.yahoo.com/search?p=%s&ei=UTF-8", pszWord); + break; + case IDM_SEARCH_FOODNETWORK: + szURL.Format(L"http://search.foodnetwork.com/search/delegate.do?fnSearchString=%s", pszWord); + break; + case IDM_SEARCH_BING: + szURL.Format(L"http://www.bing.com/search?q=%s&form=OSDSRC", pszWord); + break; + case IDM_SEARCH_GOOGLE_MAPS: + szURL.Format(L"http://maps.google.com/maps?q=%s&ie=utf-8&oe=utf-8", pszWord); + break; + case IDM_SEARCH_GOOGLE_TRANSLATE: + szURL.Format(L"http://translate.google.com/?q=%s&ie=utf-8&oe=utf-8", pszWord); + break; + case IDM_SEARCH_YANDEX: + szURL.Format(L"http://yandex.ru/yandsearch?text=%s", pszWord); + break; + case IDM_SEARCH_GOOGLE: + szURL.Format(L"http://www.google.com/search?q=%s&ie=utf-8&oe=utf-8", pszWord); + break; + } + Utils_OpenUrlW(szURL); + } + PostMessage(m_pDlg.m_hwnd, WM_MOUSEACTIVATE, 0, 0); + break; + + default: + PostMessage(m_pDlg.m_hwnd, WM_MOUSEACTIVATE, 0, 0); + Chat_DoEventHook(m_pDlg.m_si, GC_USER_LOGMENU, nullptr, nullptr, uID); + break; + } + DestroyMenu(hMenu); + } + break; + } + + LRESULT res = mir_callNextSubclass(m_rtf.GetHwnd(), stubLogProc, msg, wParam, lParam); + if (msg == WM_GETDLGCODE) + return res & ~DLGC_HASSETSEL; + return res; +} diff --git a/src/mir_app/src/srmm_toolbar.cpp b/src/mir_app/src/srmm_toolbar.cpp index b3c1aba600..6f99996ca8 100644 --- a/src/mir_app/src/srmm_toolbar.cpp +++ b/src/mir_app/src/srmm_toolbar.cpp @@ -769,6 +769,8 @@ public: } }; +void SrmmLogOptionsInit(WPARAM wParam); + static int SrmmOptionsInit(WPARAM wParam, LPARAM) { OPTIONSDIALOGPAGE odp = {}; @@ -778,6 +780,8 @@ static int SrmmOptionsInit(WPARAM wParam, LPARAM) odp.flags = ODPF_BOLDGROUPS; odp.pDialog = new CSrmmToolbarOptions(); g_plugin.addOptions(wParam, &odp); + + SrmmLogOptionsInit(wParam); return 0; } diff --git a/src/mir_app/src/stdafx.h b/src/mir_app/src/stdafx.h index 9d369695a0..6f4d249864 100644 --- a/src/mir_app/src/stdafx.h +++ b/src/mir_app/src/stdafx.h @@ -74,8 +74,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include <m_file.h>
#include <m_findadd.h>
#include <m_gui.h>
+#include <m_hpp.h>
#include <m_icolib.h>
#include <m_idle.h>
+#include <m_ieview.h>
#include <m_ignore.h>
#include <m_imgsrvc.h>
#include <m_hotkeys.h>
diff --git a/src/mir_core/src/CDlgBase.cpp b/src/mir_core/src/CDlgBase.cpp index 2c91c6a742..5a19c58558 100644 --- a/src/mir_core/src/CDlgBase.cpp +++ b/src/mir_core/src/CDlgBase.cpp @@ -412,6 +412,11 @@ void CDlgBase::AddControl(CCtrlBase *ctrl) m_controls.insert(ctrl); } +void CDlgBase::RemoveControl(CCtrlBase *ctrl) +{ + m_controls.remove(ctrl); +} + void CDlgBase::NotifyControls(void (CCtrlBase::*fn)()) { for (auto &it : m_controls) diff --git a/src/mir_core/src/mir_core.def b/src/mir_core/src/mir_core.def index 4bcb6da163..7069b1e3f2 100644 --- a/src/mir_core/src/mir_core.def +++ b/src/mir_core/src/mir_core.def @@ -1449,3 +1449,4 @@ XmlGetChildText @1645 ?Unsigned64Attribute@XMLElement@tinyxml2@@QBE_KPBD_K@Z @1664 NONAME
?Unsigned64Text@XMLElement@tinyxml2@@QBE_K_K@Z @1665 NONAME
?Unsigned64Value@XMLAttribute@tinyxml2@@QBE_KXZ @1666 NONAME
+?RemoveControl@CDlgBase@@IAEXPAVCCtrlBase@@@Z @1667 NONAME
diff --git a/src/mir_core/src/mir_core64.def b/src/mir_core/src/mir_core64.def index 8f8d58de25..7cc4be7567 100644 --- a/src/mir_core/src/mir_core64.def +++ b/src/mir_core/src/mir_core64.def @@ -1449,3 +1449,4 @@ XmlGetChildText @1645 ?Unsigned64Attribute@XMLElement@tinyxml2@@QEBA_KPEBD_K@Z @1664 NONAME
?Unsigned64Text@XMLElement@tinyxml2@@QEBA_K_K@Z @1665 NONAME
?Unsigned64Value@XMLAttribute@tinyxml2@@QEBA_KXZ @1666 NONAME
+?RemoveControl@CDlgBase@@IEAAXPEAVCCtrlBase@@@Z @1667 NONAME
|