summaryrefslogtreecommitdiff
path: root/src/mir_app
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/mir_app
parent9fe4e9044069e70b3f0e1df0e187f5ea43805ea1 (diff)
merge with SrmmLogContainer
Diffstat (limited to 'src/mir_app')
-rw-r--r--src/mir_app/mir_app.vcxproj2
-rw-r--r--src/mir_app/res/resource.rc27
-rw-r--r--src/mir_app/src/chat.h6
-rw-r--r--src/mir_app/src/mir_app.def26
-rw-r--r--src/mir_app/src/mir_app64.def26
-rw-r--r--src/mir_app/src/resource.h2
-rw-r--r--src/mir_app/src/srmm_base.cpp277
-rw-r--r--src/mir_app/src/srmm_log.cpp141
-rw-r--r--src/mir_app/src/srmm_log_hpp.cpp259
-rw-r--r--src/mir_app/src/srmm_log_rtf.cpp375
-rw-r--r--src/mir_app/src/srmm_toolbar.cpp4
-rw-r--r--src/mir_app/src/stdafx.h2
12 files changed, 881 insertions, 266 deletions
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>