From 7b64f8c1aac010e8d2bf865bb649df56388a51b3 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Thu, 12 Sep 2019 21:33:28 +0300 Subject: tabSRMM: single window --- plugins/TabSRMM/src/TSButton.cpp | 2 +- plugins/TabSRMM/src/buttonsbar.cpp | 14 +- plugins/TabSRMM/src/chat_tools.cpp | 6 +- plugins/TabSRMM/src/chat_window.cpp | 1880 +------------------------ plugins/TabSRMM/src/contactcache.cpp | 4 +- plugins/TabSRMM/src/contactcache.h | 6 +- plugins/TabSRMM/src/container.cpp | 36 +- plugins/TabSRMM/src/controls.cpp | 18 +- plugins/TabSRMM/src/eventpopups.cpp | 4 +- plugins/TabSRMM/src/functions.h | 8 +- plugins/TabSRMM/src/generic_msghandlers.cpp | 66 +- plugins/TabSRMM/src/globals.cpp | 8 +- plugins/TabSRMM/src/globals.h | 2 +- plugins/TabSRMM/src/hotkeyhandler.cpp | 4 +- plugins/TabSRMM/src/infopanel.cpp | 4 +- plugins/TabSRMM/src/infopanel.h | 8 +- plugins/TabSRMM/src/mim.cpp | 2 +- plugins/TabSRMM/src/msgdialog.cpp | 1585 ++++++++++++++------- plugins/TabSRMM/src/msgdlgother.cpp | 1986 +++++++++++++++++++++++++++ plugins/TabSRMM/src/msgdlgutils.cpp | 1514 ++------------------ plugins/TabSRMM/src/msgdlgutils.h | 5 +- plugins/TabSRMM/src/msglog.cpp | 14 +- plugins/TabSRMM/src/msgs.cpp | 235 +--- plugins/TabSRMM/src/msgs.h | 207 +-- plugins/TabSRMM/src/selectcontainer.cpp | 2 +- plugins/TabSRMM/src/sendqueue.cpp | 24 +- plugins/TabSRMM/src/sendqueue.h | 22 +- plugins/TabSRMM/src/sidebar.cpp | 20 +- plugins/TabSRMM/src/sidebar.h | 20 +- plugins/TabSRMM/src/stdafx.h | 2 +- plugins/TabSRMM/src/tabctrl.cpp | 30 +- plugins/TabSRMM/src/taskbar.cpp | 6 +- plugins/TabSRMM/src/taskbar.h | 8 +- plugins/TabSRMM/src/themeio.cpp | 2 +- plugins/TabSRMM/src/themes.cpp | 8 +- plugins/TabSRMM/src/themes.h | 14 +- plugins/TabSRMM/src/userprefs.cpp | 12 +- plugins/TabSRMM/src/utils.cpp | 10 +- plugins/TabSRMM/src/version.h | 4 +- 39 files changed, 3477 insertions(+), 4325 deletions(-) create mode 100644 plugins/TabSRMM/src/msgdlgother.cpp (limited to 'plugins') diff --git a/plugins/TabSRMM/src/TSButton.cpp b/plugins/TabSRMM/src/TSButton.cpp index dbb373f302..1a01eaed14 100644 --- a/plugins/TabSRMM/src/TSButton.cpp +++ b/plugins/TabSRMM/src/TSButton.cpp @@ -97,7 +97,7 @@ static void PaintWorker(TSButtonCtrl *ctl, HDC hdcPaint) if (ctl == nullptr || hdcPaint == nullptr) return; - CSrmmWindow *dat = (CSrmmWindow*)GetWindowLongPtr(GetParent(ctl->hwnd), GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr(GetParent(ctl->hwnd), GWLP_USERDATA); if (dat == nullptr) return; diff --git a/plugins/TabSRMM/src/buttonsbar.cpp b/plugins/TabSRMM/src/buttonsbar.cpp index be042cfd6b..9406bca6c6 100644 --- a/plugins/TabSRMM/src/buttonsbar.cpp +++ b/plugins/TabSRMM/src/buttonsbar.cpp @@ -139,7 +139,7 @@ static int CB_InitDefaultButtons(WPARAM, LPARAM) return 0; } -void CTabBaseDlg::BB_InitDlgButtons() +void CMsgDialog::BB_InitDlgButtons() { BYTE gap = DPISCALEX_S(g_plugin.getByte("ButtonsBarGap", 1)); @@ -182,7 +182,7 @@ void CTabBaseDlg::BB_InitDlgButtons() } } -void CTabBaseDlg::BB_RedrawButtons() +void CMsgDialog::BB_RedrawButtons() { Srmm_RedrawToolbarIcons(m_hwnd); @@ -191,14 +191,14 @@ void CTabBaseDlg::BB_RedrawButtons() InvalidateRect(hwndToggleSideBar, nullptr, TRUE); } -void CTabBaseDlg::BB_RefreshTheme() +void CMsgDialog::BB_RefreshTheme() { CustomButtonData *cbd; for (int i = 0; cbd = Srmm_GetNthButton(i); i++) SendDlgItemMessage(m_hwnd, cbd->m_dwButtonCID, WM_THEMECHANGED, 0, 0); } -BOOL CTabBaseDlg::BB_SetButtonsPos() +BOOL CMsgDialog::BB_SetButtonsPos() { if (!m_hwnd || !IsWindowVisible(m_hwnd)) return 0; @@ -333,7 +333,7 @@ BOOL CTabBaseDlg::BB_SetButtonsPos() return EndDeferWindowPos(hdwp); } -void CTabBaseDlg::CB_DestroyAllButtons() +void CMsgDialog::CB_DestroyAllButtons() { CustomButtonData *cbd; for (int i = 0; cbd = Srmm_GetNthButton(i); i++) { @@ -343,7 +343,7 @@ void CTabBaseDlg::CB_DestroyAllButtons() } } -void CTabBaseDlg::CB_DestroyButton(DWORD dwButtonCID, DWORD dwFlags) +void CMsgDialog::CB_DestroyButton(DWORD dwButtonCID, DWORD dwFlags) { HWND hwndButton = GetDlgItem(m_hwnd, dwButtonCID); if (hwndButton == nullptr) @@ -360,7 +360,7 @@ void CTabBaseDlg::CB_DestroyButton(DWORD dwButtonCID, DWORD dwFlags) BB_SetButtonsPos(); } -void CTabBaseDlg::CB_ChangeButton(CustomButtonData *cbd) +void CMsgDialog::CB_ChangeButton(CustomButtonData *cbd) { HWND hwndButton = GetDlgItem(m_hwnd, cbd->m_dwButtonCID); if (hwndButton == nullptr) diff --git a/plugins/TabSRMM/src/chat_tools.cpp b/plugins/TabSRMM/src/chat_tools.cpp index 61b2438e16..eb929bd437 100644 --- a/plugins/TabSRMM/src/chat_tools.cpp +++ b/plugins/TabSRMM/src/chat_tools.cpp @@ -133,7 +133,7 @@ BOOL DoPopup(SESSION_INFO *si, GCEVENT *gce) if (si == nullptr || !(iEvent & si->iLogPopupFlags)) return true; - CTabBaseDlg *dat = si->pDlg; + CMsgDialog *dat = si->pDlg; TContainerData *pContainer = dat ? dat->m_pContainer : nullptr; wchar_t *bbStart, *bbEnd; @@ -206,7 +206,7 @@ void DoFlashAndSoundWorker(FLASH_PARAMS *p) if (si == nullptr) return; - CTabBaseDlg *dat = nullptr; + CMsgDialog *dat = nullptr; if (si->pDlg) { dat = si->pDlg; if (dat) { @@ -290,7 +290,7 @@ BOOL DoSoundsFlashPopupTrayStuff(SESSION_INFO *si, GCEVENT *gce, BOOL bHighlight if (gce == nullptr || si == nullptr || gce->bIsMe || si->iType == GCW_SERVER) return FALSE; - CTabBaseDlg *dat = nullptr; + CMsgDialog *dat = nullptr; FLASH_PARAMS *params = (FLASH_PARAMS*)mir_calloc(sizeof(FLASH_PARAMS)); params->hContact = si->hContact; params->bInactive = TRUE; diff --git a/plugins/TabSRMM/src/chat_window.cpp b/plugins/TabSRMM/src/chat_window.cpp index 1372ac2ff8..1b2c830b33 100644 --- a/plugins/TabSRMM/src/chat_window.cpp +++ b/plugins/TabSRMM/src/chat_window.cpp @@ -40,84 +40,6 @@ char szIndicators[] = { 0, '+', '%', '@', '!', '*' }; const CLSID IID_ITextDocument = { 0x8CC497C0, 0xA1DF, 0x11CE, { 0x80, 0x98, 0x00, 0xAA, 0x00, 0x47, 0xBE, 0x5D } }; -///////////////////////////////////////////////////////////////////////////////////////// -// checking if theres's protected text at the point -// emulates EN_LINK WM_NOTIFY to parent to process links - -static BOOL CheckCustomLink(HWND hwndRich, POINT *ptClient, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL bUrlNeeded) -{ - long res = 0, cnt = 0; - long cpMin = 0, cpMax = 0; - POINT ptEnd = { 0 }; - IRichEditOle *RichEditOle = nullptr; - ITextDocument *TextDocument = nullptr; - ITextRange *TextRange = nullptr; - ITextFont *TextFont = nullptr; - BOOL bIsCustomLink = FALSE; - - POINT pt = *ptClient; - ClientToScreen(hwndRich, &pt); - - do { - if (!SendMessage(hwndRich, EM_GETOLEINTERFACE, 0, (LPARAM)&RichEditOle)) break; - if (RichEditOle->QueryInterface(IID_ITextDocument, (void**)&TextDocument) != S_OK) break; - if (TextDocument->RangeFromPoint(pt.x, pt.y, &TextRange) != S_OK) break; - - TextRange->GetStart(&cpMin); - cpMax = cpMin + 1; - TextRange->SetEnd(cpMax); - - if (TextRange->GetFont(&TextFont) != S_OK) - break; - - TextFont->GetProtected(&res); - if (res != tomTrue) - break; - - TextRange->GetPoint(tomEnd + TA_BOTTOM + TA_RIGHT, &ptEnd.x, &ptEnd.y); - if (pt.x > ptEnd.x || pt.y > ptEnd.y) - break; - - if (bUrlNeeded) { - TextRange->GetStoryLength(&cnt); - for (; cpMin > 0; cpMin--) { - res = tomTrue; - TextRange->SetIndex(tomCharacter, cpMin + 1, tomTrue); - TextFont->GetProtected(&res); - if (res != tomTrue) { cpMin++; break; } - } - for (cpMax--; cpMax < cnt; cpMax++) { - res = tomTrue; - TextRange->SetIndex(tomCharacter, cpMax + 1, tomTrue); - TextFont->GetProtected(&res); - if (res != tomTrue) - break; - } - } - - bIsCustomLink = (cpMin < cpMax); - } while (FALSE); - - if (TextFont) TextFont->Release(); - if (TextRange) TextRange->Release(); - if (TextDocument) TextDocument->Release(); - if (RichEditOle) RichEditOle->Release(); - - if (bIsCustomLink) { - ENLINK enlink = {}; - enlink.nmhdr.hwndFrom = hwndRich; - enlink.nmhdr.idFrom = IDC_SRMM_LOG; - enlink.nmhdr.code = EN_LINK; - enlink.msg = uMsg; - enlink.wParam = wParam; - enlink.lParam = lParam; - enlink.chrg.cpMin = cpMin; - enlink.chrg.cpMax = cpMax; - SendMessage(GetParent(hwndRich), WM_NOTIFY, IDC_SRMM_LOG, (LPARAM)&enlink); - } - return bIsCustomLink; -} - bool IsStringValidLink(wchar_t *pszText) { if (pszText == nullptr) @@ -230,564 +152,6 @@ void CMsgDialog::UpdateWindowState(UINT msg) } ///////////////////////////////////////////////////////////////////////////////////////// -// resizer callback for the group chat session window.Called from Mirandas dialog -// resizing service - -int CMsgDialog::Resizer(UTILRESIZECONTROL *urc) -{ - bool bToolbar = !(m_pContainer->m_dwFlags & CNT_HIDETOOLBAR); - bool bBottomToolbar = (m_pContainer->m_dwFlags & CNT_BOTTOMTOOLBAR) != 0; - bool bNick = m_si->iType != GCW_SERVER && m_bNicklistEnabled; - bool bInfoPanel = m_pPanel.isActive(); - int panelHeight = m_pPanel.getHeight() + 1; - int iSplitterX = m_pContainer->m_pSettings->iSplitterX; - - RECT rcTabs; - GetClientRect(m_hwnd, &rcTabs); - - if (m_bIsAutosizingInput) - Utils::showDlgControl(m_hwnd, IDC_SPLITTERY, SW_HIDE); - - if (m_si->iType != GCW_SERVER) { - m_nickList.Show(m_bNicklistEnabled); - Utils::showDlgControl(m_hwnd, IDC_SPLITTERX, m_bNicklistEnabled ? SW_SHOW : SW_HIDE); - - m_btnNickList.Enable(true); - m_btnFilter.Enable(true); - if (m_si->iType == GCW_CHATROOM) - m_btnChannelMgr.Enable(m_si->pMI->bChanMgr); - } - else { - m_nickList.Hide(); - Utils::showDlgControl(m_hwnd, IDC_SPLITTERX, SW_HIDE); - } - - if (m_si->iType == GCW_SERVER) { - m_btnNickList.Enable(false); - m_btnFilter.Enable(false); - m_btnChannelMgr.Enable(false); - } - - switch (urc->wId) { - case IDC_PANELSPLITTER: - urc->rcItem.bottom = panelHeight; - urc->rcItem.top = panelHeight - 2; - return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP; - - case IDC_SRMM_LOG: - urc->rcItem.top = 0; - urc->rcItem.left = 0; - urc->rcItem.right = bNick ? urc->dlgNewSize.cx - iSplitterX : urc->dlgNewSize.cx; - urc->rcItem.bottom = urc->dlgNewSize.cy - m_iSplitterY; - if (!bToolbar || bBottomToolbar) - urc->rcItem.bottom += DPISCALEY_S(21); - if (bInfoPanel) - urc->rcItem.top += panelHeight; - if (CSkin::m_skinEnabled) { - CSkinItem *item = &SkinItems[ID_EXTBKHISTORY]; - if (!item->IGNORED) { - urc->rcItem.left += item->MARGIN_LEFT; - urc->rcItem.right -= item->MARGIN_RIGHT; - urc->rcItem.top += item->MARGIN_TOP; - urc->rcItem.bottom -= item->MARGIN_BOTTOM; - } - } - return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; - - case IDC_SRMM_NICKLIST: - urc->rcItem.top = 0; - urc->rcItem.right = urc->dlgNewSize.cx; - urc->rcItem.left = urc->dlgNewSize.cx - iSplitterX + 2; - urc->rcItem.bottom = urc->dlgNewSize.cy - m_iSplitterY; - if (!bToolbar || bBottomToolbar) - urc->rcItem.bottom += DPISCALEY_S(21); - if (bInfoPanel) - urc->rcItem.top += panelHeight; - if (CSkin::m_skinEnabled) { - CSkinItem *item = &SkinItems[ID_EXTBKUSERLIST]; - if (!item->IGNORED) { - urc->rcItem.left += item->MARGIN_LEFT; - urc->rcItem.right -= item->MARGIN_RIGHT; - urc->rcItem.top += item->MARGIN_TOP; - urc->rcItem.bottom -= item->MARGIN_BOTTOM; - } - } - return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; - - case IDC_SPLITTERX: - urc->rcItem.right = urc->dlgNewSize.cx - iSplitterX + 2; - urc->rcItem.left = urc->dlgNewSize.cx - iSplitterX; - urc->rcItem.bottom = urc->dlgNewSize.cy - m_iSplitterY; - if (!bToolbar || bBottomToolbar) - urc->rcItem.bottom += DPISCALEY_S(21); - urc->rcItem.top = 0; - if (bInfoPanel) - urc->rcItem.top += panelHeight; - return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; - - case IDC_SPLITTERY: - urc->rcItem.right = urc->dlgNewSize.cx; - urc->rcItem.top = urc->dlgNewSize.cy - m_iSplitterY + DPISCALEY_S(23); - urc->rcItem.bottom = urc->rcItem.top + DPISCALEY_S(2); - urc->rcItem.left = 0; - urc->rcItem.bottom++; - urc->rcItem.top++; - return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; - - case IDC_SRMM_MESSAGE: - urc->rcItem.right = urc->dlgNewSize.cx; - urc->rcItem.top = urc->dlgNewSize.cy - m_iSplitterY + 3 + DPISCALEY_S(23); - urc->rcItem.bottom = urc->dlgNewSize.cy; - if (bBottomToolbar && bToolbar) - urc->rcItem.bottom -= DPISCALEY_S(22); - - if (m_bIsAutosizingInput) - urc->rcItem.top -= DPISCALEY_S(1); - - if (CSkin::m_skinEnabled) { - CSkinItem *item = &SkinItems[ID_EXTBKINPUTAREA]; - if (!item->IGNORED) { - urc->rcItem.left += item->MARGIN_LEFT; - urc->rcItem.right -= item->MARGIN_RIGHT; - urc->rcItem.top += item->MARGIN_TOP; - urc->rcItem.bottom -= item->MARGIN_BOTTOM; - } - } - return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; - } - return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; -} - -bool CMsgDialog::TabAutoComplete() -{ - LRESULT lResult = m_message.SendMsg(EM_GETSEL, 0, 0); - int start = LOWORD(lResult), end = HIWORD(lResult); - m_message.SendMsg(EM_SETSEL, end, end); - - GETTEXTEX gt = { 0 }; - gt.codepage = 1200; - gt.flags = GTL_DEFAULT | GTL_PRECISE; - int iLen = m_message.SendMsg(EM_GETTEXTLENGTHEX, (WPARAM)>, 0); - if (iLen <= 0) - return false; - - bool isTopic = false, isRoom = false; - wchar_t *pszName = nullptr; - wchar_t *pszText = (wchar_t*)mir_calloc((iLen + 10) * sizeof(wchar_t)); - - gt.flags = GT_DEFAULT; - gt.cb = (iLen + 9) * sizeof(wchar_t); - m_message.SendMsg(EM_GETTEXTEX, (WPARAM)>, (LPARAM)pszText); - - if (start > 1 && pszText[start - 1] == ' ' && pszText[start - 2] == ':') - start -= 2; - - if (m_wszSearchResult != nullptr) { - int cbResult = (int)mir_wstrlen(m_wszSearchResult); - if (start >= cbResult && !wcsnicmp(m_wszSearchResult, pszText + start - cbResult, cbResult)) { - start -= cbResult; - goto LBL_SkipEnd; - } - } - - while (start > 0 && pszText[start - 1] != ' ' && pszText[start - 1] != 13 && pszText[start - 1] != VK_TAB) - start--; - -LBL_SkipEnd: - while (end < iLen && pszText[end] != ' ' && pszText[end] != 13 && pszText[end - 1] != VK_TAB) - end++; - - if (pszText[start] == '#') - isRoom = true; - else { - int topicStart = start; - while (topicStart > 0 && (pszText[topicStart - 1] == ' ' || pszText[topicStart - 1] == 13 || pszText[topicStart - 1] == VK_TAB)) - topicStart--; - if (topicStart > 5 && wcsstr(&pszText[topicStart - 6], L"/topic") == &pszText[topicStart - 6]) - isTopic = true; - } - if (m_wszSearchQuery == nullptr) { - m_wszSearchQuery = mir_wstrndup(pszText + start, end - start); - m_wszSearchResult = mir_wstrdup(m_wszSearchQuery); - m_pLastSession = nullptr; - } - if (isTopic) - pszName = m_si->ptszTopic; - else if (isRoom) { - m_pLastSession = SM_FindSessionAutoComplete(m_si->pszModule, m_si, m_pLastSession, m_wszSearchQuery, m_wszSearchResult); - if (m_pLastSession != nullptr) - pszName = m_pLastSession->ptszName; - } - else pszName = g_chatApi.UM_FindUserAutoComplete(m_si, m_wszSearchQuery, m_wszSearchResult); - - replaceStrW(m_wszSearchResult, nullptr); - - if (pszName != nullptr) { - m_wszSearchResult = mir_wstrdup(pszName); - if (end != start) { - ptrW szReplace; - if (!isRoom && !isTopic && g_Settings.bAddColonToAutoComplete && start == 0) { - szReplace = (wchar_t*)mir_alloc((mir_wstrlen(pszName) + 4) * sizeof(wchar_t)); - mir_wstrcpy(szReplace, pszName); - mir_wstrcat(szReplace, g_Settings.bUseCommaAsColon ? L", " : L": "); - pszName = szReplace; - } - m_message.SendMsg(EM_SETSEL, start, end); - m_message.SendMsg(EM_REPLACESEL, TRUE, (LPARAM)pszName); - } - return true; - } - - if (end != start) { - m_message.SendMsg(EM_SETSEL, start, end); - m_message.SendMsg(EM_REPLACESEL, TRUE, (LPARAM)m_wszSearchQuery); - } - replaceStrW(m_wszSearchQuery, nullptr); - return false; -} - -static void __cdecl phase2(SESSION_INFO *si) -{ - Thread_SetName("TabSRMM: phase2"); - - Sleep(30); - if (si && si->pDlg) - si->pDlg->RedrawLog2(); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// the actual group chat session window procedure.Handles the entire chat session window -// which is usually a (tabbed) child of a container class window. - -CMsgDialog::CMsgDialog(SESSION_INFO *si) - : CSuper(IDD_CHANNEL, si), - m_btnOk(this, IDOK) -{ - m_szProto = GetContactProto(m_hContact); - m_bFilterEnabled = db_get_b(m_hContact, CHAT_MODULE, "FilterEnabled", m_bFilterEnabled) != 0; - - m_btnOk.OnClick = Callback(this, &CMsgDialog::onClick_OK); - m_btnFilter.OnClick = Callback(this, &CMsgDialog::onClick_Filter); - m_btnNickList.OnClick = Callback(this, &CMsgDialog::onClick_ShowNickList); - - m_nickList.OnDblClick = Callback(this, &CMsgDialog::onDblClick_List); - - m_message.OnChange = Callback(this, &CMsgDialog::onChange_Message); -} - -CThumbBase* CMsgDialog::tabCreateThumb(CProxyWindow *pProxy) const -{ - return new CThumbMUC(pProxy, m_si); -} - -void CMsgDialog::tabClearLog() -{ - SESSION_INFO *s = g_chatApi.SM_FindSession(m_si->ptszID, m_si->pszModule); - if (s) { - ClearLog(); - g_chatApi.LM_RemoveAll(&s->pLog, &s->pLogEnd); - s->iEventCount = 0; - s->LastTime = 0; - m_si->iEventCount = 0; - m_si->LastTime = 0; - m_si->pLog = s->pLog; - m_si->pLogEnd = s->pLogEnd; - PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); - } -} - -bool CMsgDialog::OnInitDialog() -{ - CSuper::OnInitDialog(); - - m_si->pDlg = this; - - Chat_SetFilters(m_si); - - m_iSplitterY = m_pContainer->m_pSettings->iSplitterY; - if (m_bIsAutosizingInput) - m_iSplitterY = GetDefaultMinimumInputHeight(); - - // Typing support for GCW_PRIVMESS sessions - if (m_si->iType == GCW_PRIVMESS) { - m_nTypeMode = PROTOTYPE_SELFTYPING_OFF; - SetTimer(m_hwnd, TIMERID_TYPE, 1000, nullptr); - } - - m_pPanel.getVisibility(); - m_pPanel.Configure(); - - SetWindowLongPtr(GetDlgItem(m_hwnd, IDC_PANELSPLITTER), GWLP_WNDPROC, (LONG_PTR)SplitterSubclassProc); - NotifyEvent(MSG_WINDOW_EVT_OPENING); - - m_log.SendMsg(EM_AUTOURLDETECT, 1, 0); - m_log.SendMsg(EM_SETEVENTMASK, 0, m_log.SendMsg(EM_GETEVENTMASK, 0, 0) | ENM_LINK | ENM_MOUSEEVENTS | ENM_KEYEVENTS); - m_log.SendMsg(EM_LIMITTEXT, 0x7FFFFFFF, 0); - m_log.SendMsg(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3)); - - m_message.SendMsg(EM_SETEVENTMASK, 0, ENM_REQUESTRESIZE | ENM_MOUSEEVENTS | ENM_SCROLL | ENM_KEYEVENTS | ENM_CHANGE); - m_message.SendMsg(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3)); - - m_pPanel.loadHeight(); - - if (PluginConfig.g_hMenuTrayUnread != nullptr && m_hContact != 0 && m_szProto != nullptr) - UpdateTrayMenu(nullptr, m_wStatus, m_szProto, m_wszStatus, m_hContact, 0); - - m_log.SendMsg(EM_HIDESELECTION, TRUE, 0); - - GetMYUIN(); - GetMyNick(); - - HWND hwndBtn = CreateWindowEx(0, L"MButtonClass", L"", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 0, 6, DPISCALEY_S(20), m_hwnd, (HMENU)IDC_TOGGLESIDEBAR, g_plugin.getInst(), nullptr); - CustomizeButton(hwndBtn); - SendMessage(hwndBtn, BUTTONSETASTHEMEDBTN, 1, 0); - SendMessage(hwndBtn, BUTTONSETCONTAINER, (LPARAM)m_pContainer, 0); - SendMessage(hwndBtn, BUTTONSETASFLATBTN, FALSE, 0); - SendMessage(hwndBtn, BUTTONSETASTOOLBARBUTTON, TRUE, 0); - SendMessage(hwndBtn, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Expand or collapse the side bar"), BATF_UNICODE); - - DM_InitTip(); - BB_InitDlgButtons(); - SendMessage(m_hwnd, WM_CBD_LOADICONS, 0, 0); - - mir_subclassWindow(GetDlgItem(m_hwnd, IDC_SPLITTERX), SplitterSubclassProc); - mir_subclassWindow(GetDlgItem(m_hwnd, IDC_SPLITTERY), SplitterSubclassProc); - - UpdateOptions(); - UpdateStatusBar(); - UpdateTitle(); - m_hTabIcon = m_hTabStatusIcon; - - RECT rc; - SendMessage(m_pContainer->m_hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)&rc); - SetWindowPos(m_hwnd, HWND_TOP, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), 0); - ShowWindow(m_hwnd, SW_SHOW); - UpdateNickList(); - m_pContainer->m_hwndActive = m_hwnd; - NotifyEvent(MSG_WINDOW_EVT_OPEN); - return true; -} - -void CMsgDialog::OnDestroy() -{ - // Typing support for GCW_PRIVMESS sessions - if (m_si->iType == GCW_PRIVMESS) - if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) - DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); - - if (g_clistApi.pfnGetEvent(m_si->hContact, 0)) - g_clistApi.pfnRemoveEvent(m_si->hContact, GC_FAKE_EVENT); - m_si->wState &= ~STATE_TALK; - m_si->pDlg = nullptr; - m_si = nullptr; - - NotifyEvent(MSG_WINDOW_EVT_CLOSING); - - DM_FreeTheme(); - - UpdateTrayMenuState(this, FALSE); // remove me from the tray menu (if still there) - if (PluginConfig.g_hMenuTrayUnread) - DeleteMenu(PluginConfig.g_hMenuTrayUnread, (UINT_PTR)m_hContact, MF_BYCOMMAND); - - if (m_hwndTip) - DestroyWindow(m_hwndTip); - - int i = GetTabIndexFromHWND(m_hwndParent, m_hwnd); - if (i >= 0) { - SendMessage(m_hwndParent, WM_USER + 100, 0, 0); // clean up tooltip - TabCtrl_DeleteItem(m_hwndParent, i); - m_pContainer->UpdateTabs(); - m_iTabID = -1; - } - - if (m_pWnd) { - delete m_pWnd; - m_pWnd = nullptr; - } - - NotifyEvent(MSG_WINDOW_EVT_CLOSE); - - m_pContainer->ClearMargins(); - PostMessage(m_pContainer->m_hwnd, WM_SIZE, 0, 1); - - if (m_pContainer->m_dwFlags & CNT_SIDEBAR) - m_pContainer->m_pSideBar->removeSession(this); - - CSuper::OnDestroy(); -} - -void CMsgDialog::onClick_OK(CCtrlButton*) -{ - if (GetSendButtonState(m_hwnd) == PBS_DISABLED) - return; - - ptrA pszRtf(m_message.GetRichTextRtf()); - if (pszRtf == nullptr) - return; - - CMStringW ptszText(ptrW(mir_utf8decodeW(pszRtf))); - if (ptszText.IsEmpty()) - return; - - m_cache->saveHistory(); - DoRtfToTags(ptszText); - ptszText.Trim(); - - if (m_si->pMI->bAckMsg) { - m_message.Enable(false); - m_message.SendMsg(EM_SETREADONLY, TRUE, 0); - } - else m_message.SetText(L""); - - Utils::enableDlgControl(m_hwnd, IDOK, false); - - // Typing support for GCW_PRIVMESS sessions - if (m_si->iType == GCW_PRIVMESS) - if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) - DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); - - bool fSound = true; - if (ptszText[0] == '/' || m_si->iType == GCW_SERVER) - fSound = false; - Chat_DoEventHook(m_si, GC_USER_MESSAGE, nullptr, ptszText, 0); - m_si->pMI->idleTimeStamp = time(0); - UpdateStatusBar(); - if (m_pContainer) - if (fSound && !nen_options.iNoSounds && !(m_pContainer->m_dwFlags & CNT_NOSOUND)) - Skin_PlaySound("ChatSent"); - - SetFocus(m_message.GetHwnd()); -} - -void CMsgDialog::onClick_Filter(CCtrlButton *pButton) -{ - if (!pButton->Enabled()) - return; - - if (m_iLogFilterFlags == 0 && !m_bFilterEnabled) { - MessageBox(nullptr, TranslateT("The filter cannot be enabled, because there are no event types selected either global or for this chat room"), TranslateT("Event filter error"), MB_OK); - m_bFilterEnabled = false; - } - else m_bFilterEnabled = !m_bFilterEnabled; - - m_btnFilter.SendMsg(BUTTONSETOVERLAYICON, (LPARAM)(m_bFilterEnabled ? PluginConfig.g_iconOverlayEnabled : PluginConfig.g_iconOverlayDisabled), 0); - - if (m_bFilterEnabled && db_get_b(0, CHAT_MODULE, "RightClickFilter", 1) == 0) { - ShowFilterMenu(); - return; - } - RedrawLog(); - UpdateTitle(); - db_set_b(m_si->hContact, CHAT_MODULE, "FilterEnabled", m_bFilterEnabled); -} - -void CMsgDialog::onClick_ShowNickList(CCtrlButton *pButton) -{ - if (!pButton->Enabled() || m_si->iType == GCW_SERVER) - return; - - m_bNicklistEnabled = !m_bNicklistEnabled; - - Resize(); - if (CSkin::m_skinEnabled) - InvalidateRect(m_hwnd, nullptr, TRUE); - ScrollToBottom(); -} - -void CMsgDialog::onChange_Message(CCtrlEdit*) -{ - if (m_pContainer->m_hwndActive == m_hwnd) - UpdateReadChars(); - m_dwLastActivity = GetTickCount(); - m_pContainer->m_dwLastActivity = m_dwLastActivity; - m_btnOk.SendMsg(BUTTONSETASNORMAL, m_message.GetRichTextLength() != 0, 0); - m_btnOk.Enable(m_message.GetRichTextLength() != 0); - - // Typing support for GCW_PRIVMESS sessions - if (m_si->iType == GCW_PRIVMESS) { - if (!(GetKeyState(VK_CONTROL) & 0x8000)) { - m_nLastTyping = GetTickCount(); - if (GetWindowTextLength(m_message.GetHwnd())) { - if (m_nTypeMode == PROTOTYPE_SELFTYPING_OFF) { - if (!(m_dwFlags & MWF_INITMODE)) - DM_NotifyTyping(PROTOTYPE_SELFTYPING_ON); - } - } - else if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) - DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); - } - } -} - -void CMsgDialog::onDblClick_List(CCtrlListBox *pList) -{ - TVHITTESTINFO hti; - hti.pt.x = (short)LOWORD(GetMessagePos()); - hti.pt.y = (short)HIWORD(GetMessagePos()); - ScreenToClient(pList->GetHwnd(), &hti.pt); - - int item = LOWORD(pList->SendMsg(LB_ITEMFROMPOINT, 0, MAKELPARAM(hti.pt.x, hti.pt.y))); - USERINFO *ui = g_chatApi.UM_FindUserFromIndex(m_si, item); - if (ui == nullptr) - return; - - bool bShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0; - if (g_Settings.bDoubleClick4Privat ? bShift : !bShift) { - int selStart = LOWORD(m_message.SendMsg(EM_GETSEL, 0, 0)); - CMStringW tszName(ui->pszNick); - if (selStart == 0) - tszName.AppendChar(g_Settings.bUseCommaAsColon ? ',' : ':'); - tszName.AppendChar(' '); - - m_message.SendMsg(EM_REPLACESEL, FALSE, (LPARAM)tszName.GetString()); - PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); - SetFocus(m_message.GetHwnd()); - } - else Chat_DoEventHook(m_si, GC_USER_PRIVMESS, ui, nullptr, 0); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void CMsgDialog::AddLog() -{ - if (PluginConfig.m_bUseDividers) { - if (PluginConfig.m_bDividersUsePopupConfig) { - if (!MessageWindowOpened(0, m_hwnd)) - DM_AddDivider(); - } - else { - bool bInactive = !IsActive(); - if (bInactive) - DM_AddDivider(); - else if (m_pContainer->m_hwndActive != m_hwnd) - DM_AddDivider(); - } - } - - CSrmmBaseDialog::AddLog(); -} - -void CMsgDialog::RedrawLog() -{ - m_si->LastTime = 0; - if (m_si->pLog) { - LOGINFO *pLog = m_si->pLog; - if (m_si->iEventCount > 60) { - int index = 0; - while (index < 59) { - if (pLog->next == nullptr) - break; - pLog = pLog->next; - if ((m_si->iType != GCW_CHATROOM && m_si->iType != GCW_PRIVMESS) || !m_bFilterEnabled || (m_iLogFilterFlags & pLog->iType) != 0) - index++; - } - StreamInEvents(pLog, TRUE); - mir_forkThread(phase2, m_si); - } - else StreamInEvents(m_si->pLogEnd, TRUE); - } - else ClearLog(); -} void CMsgDialog::ScrollToBottom() { @@ -836,487 +200,60 @@ void CMsgDialog::UpdateOptions() DM_InitRichEdit(); m_btnOk.SendMsg(BUTTONSETASNORMAL, TRUE, 0); - m_nickList.SetItemHeight(0, g_Settings.iNickListFontHeight); - InvalidateRect(m_nickList.GetHwnd(), nullptr, TRUE); - - m_btnFilter.SendMsg(BUTTONSETOVERLAYICON, (LPARAM)(m_bFilterEnabled ? PluginConfig.g_iconOverlayEnabled : PluginConfig.g_iconOverlayDisabled), 0); - Resize(); - RedrawLog2(); -} - -void CMsgDialog::UpdateStatusBar() -{ - if (m_pContainer->m_hwndActive != m_hwnd || m_pContainer->m_hwndStatus == nullptr || CMimAPI::m_shutDown || m_wszStatusBar[0]) - return; - - if (m_si->pszModule == nullptr) - return; - - //Mad: strange rare crash here... - MODULEINFO *mi = m_si->pMI; - if (!mi->ptszModDispName) - return; - - int x = 12; - x += Chat_GetTextPixelSize(mi->ptszModDispName, (HFONT)SendMessage(m_pContainer->m_hwndStatus, WM_GETFONT, 0, 0), true); - x += GetSystemMetrics(SM_CXSMICON); - - wchar_t szFinalStatusBarText[512]; - if (m_pPanel.isActive()) { - time_t now = time(0); - DWORD diff = (now - mi->idleTimeStamp) / 60; - if (diff >= 1) { - if (diff > 59) { - DWORD hours = diff / 60; - DWORD minutes = diff % 60; - mir_snwprintf(mi->tszIdleMsg, TranslateT(", %d %s, %d %s idle"), - hours, hours > 1 ? TranslateT("hours") : TranslateT("hour"), - minutes, minutes > 1 ? TranslateT("minutes") : TranslateT("minute")); - } - else mir_snwprintf(mi->tszIdleMsg, TranslateT(", %d %s idle"), diff, diff > 1 ? TranslateT("minutes") : TranslateT("minute")); - } - else mi->tszIdleMsg[0] = 0; - - mir_snwprintf(szFinalStatusBarText, TranslateT("%s on %s%s"), m_wszMyNickname, mi->ptszModDispName, mi->tszIdleMsg); - } - else { - if (m_si->ptszStatusbarText) - mir_snwprintf(szFinalStatusBarText, L"%s %s", mi->ptszModDispName, m_si->ptszStatusbarText); - else - wcsncpy_s(szFinalStatusBarText, mi->ptszModDispName, _TRUNCATE); - } - SendMessage(m_pContainer->m_hwndStatus, SB_SETTEXT, 0, (LPARAM)szFinalStatusBarText); - tabUpdateStatusBar(); - m_pPanel.Invalidate(); - if (m_pWnd) - m_pWnd->Invalidate(); -} - -void CMsgDialog::UpdateTitle() -{ - m_wStatus = m_si->wStatus; - - const wchar_t *szNick = m_cache->getNick(); - if (mir_wstrlen(szNick) > 0) { - if (M.GetByte("cuttitle", 0)) - CutContactName(szNick, m_wszTitle, _countof(m_wszTitle)); - else - wcsncpy_s(m_wszTitle, szNick, _TRUNCATE); - } - - CMStringW wszTitle; - HICON hIcon = nullptr; - int nUsers = m_si->getUserList().getCount(); - - switch (m_si->iType) { - case GCW_CHATROOM: - hIcon = Skin_LoadProtoIcon(m_si->pszModule, (m_wStatus <= ID_STATUS_OFFLINE) ? ID_STATUS_OFFLINE : m_wStatus); - wszTitle.Format((nUsers == 1) ? TranslateT("%s: chat room (%u user%s)") : TranslateT("%s: chat room (%u users%s)"), - szNick, nUsers, m_bFilterEnabled ? TranslateT(", event filter active") : L""); - break; - - case GCW_PRIVMESS: - hIcon = Skin_LoadProtoIcon(m_si->pszModule, (m_wStatus <= ID_STATUS_OFFLINE) ? ID_STATUS_OFFLINE : m_wStatus); - if (nUsers == 1) - wszTitle.Format(TranslateT("%s: message session"), szNick); - else - wszTitle.Format(TranslateT("%s: message session (%u users)"), szNick, nUsers); - break; - - case GCW_SERVER: - wszTitle.Format(L"%s: Server", szNick); - hIcon = LoadIconEx("window"); - break; - - default: - return; - } - - if (m_pWnd) { - m_pWnd->updateTitle(m_wszTitle); - m_pWnd->updateIcon(hIcon); - } - m_hTabStatusIcon = hIcon; - - if (m_cache->getStatus() != m_cache->getOldStatus()) { - wcsncpy_s(m_wszStatus, Clist_GetStatusModeDescription(m_wStatus, 0), _TRUNCATE); - - TCITEM item = {}; - item.mask = TCIF_TEXT; - item.pszText = m_wszTitle; - TabCtrl_SetItem(m_hwndParent, m_iTabID, &item); - } - SetWindowText(m_hwnd, wszTitle); - if (m_pContainer->m_hwndActive == m_hwnd) { - m_pContainer->UpdateTitle(0, this); - UpdateStatusBar(); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -// subclassing for the message history display(rich edit control in which the chat history appears) - -LRESULT CMsgDialog::WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_NCCALCSIZE: - return CSkin::NcCalcRichEditFrame(m_log.GetHwnd(), this, ID_EXTBKHISTORY, msg, wParam, lParam, stubLogProc); - - case WM_NCPAINT: - return CSkin::DrawRichEditFrame(m_log.GetHwnd(), this, ID_EXTBKHISTORY, msg, wParam, lParam, stubLogProc); - - case WM_COPY: - return WMCopyHandler(msg, wParam, lParam); - - case WM_SETCURSOR: - if (g_Settings.bClickableNicks && (LOWORD(lParam) == HTCLIENT)) { - POINT pt; - GetCursorPos(&pt); - ScreenToClient(m_log.GetHwnd(), &pt); - if (CheckCustomLink(m_log.GetHwnd(), &pt, msg, wParam, lParam, FALSE)) return TRUE; - } - break; - - case WM_LBUTTONDOWN: - case WM_LBUTTONDBLCLK: - case WM_RBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONDBLCLK: - if (g_Settings.bClickableNicks) { - POINT pt = { LOWORD(lParam), HIWORD(lParam) }; - CheckCustomLink(m_log.GetHwnd(), &pt, msg, wParam, lParam, TRUE); - } - break; - - case WM_LBUTTONUP: - if (g_Settings.bClickableNicks) { - POINT pt = { LOWORD(lParam), HIWORD(lParam) }; - CheckCustomLink(m_log.GetHwnd(), &pt, msg, wParam, lParam, TRUE); - } - if (M.GetByte("autocopy", 1)) { - CHARRANGE sel; - SendMessage(m_log.GetHwnd(), EM_EXGETSEL, 0, (LPARAM)&sel); - if (sel.cpMin != sel.cpMax) { - SendMessage(m_log.GetHwnd(), WM_COPY, 0, 0); - sel.cpMin = sel.cpMax; - SendMessage(m_log.GetHwnd(), EM_EXSETSEL, 0, (LPARAM)&sel); - SetFocus(m_message.GetHwnd()); - } - } - break; - - case WM_KEYDOWN: - if (wParam == 0x57 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w (close window) - PostMessage(m_hwnd, WM_CLOSE, 0, 1); - return TRUE; - } - if (wParam == VK_INSERT && GetKeyState(VK_CONTROL) & 0x8000) - return WMCopyHandler(msg, wParam, lParam); - break; - - case WM_SYSKEYUP: - if (wParam == VK_MENU) { - ProcessHotkeysByMsgFilter(m_log, msg, wParam, lParam); - return 0; - } - break; - - case WM_SYSKEYDOWN: - m_bkeyProcessed = false; - if (ProcessHotkeysByMsgFilter(m_log, msg, wParam, lParam)) { - m_bkeyProcessed = true; - return 0; - } - break; - - case WM_SYSCHAR: - if (m_bkeyProcessed) { - m_bkeyProcessed = false; - return 0; - } - break; - - case WM_CHAR: - bool isCtrl, isShift, isAlt; - KbdState(isShift, isCtrl, isAlt); - if (wParam == 0x03 && isCtrl) // Ctrl+C - return WMCopyHandler(msg, wParam, lParam); - break; - } - - return CSuper::WndProc_Log(msg, wParam, lParam); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// subclassing for the message input control(a richedit text control) - -LRESULT CMsgDialog::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (m_bkeyProcessed && (msg == WM_KEYUP)) { - GetKeyboardState(kstate); - if (!(kstate[VK_CONTROL] & 0x80) && !(kstate[VK_SHIFT] & 0x80)) - m_bkeyProcessed = false; - return 0; - } - - switch (msg) { - case WM_NCCALCSIZE: - return CSkin::NcCalcRichEditFrame(m_message.GetHwnd(), this, ID_EXTBKINPUTAREA, msg, wParam, lParam, stubMessageProc); - - case WM_NCPAINT: - return CSkin::DrawRichEditFrame(m_message.GetHwnd(), this, ID_EXTBKINPUTAREA, msg, wParam, lParam, stubMessageProc); - - case WM_CONTEXTMENU: - POINT pt; - GetCursorPos(&pt); - { - HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_CONTEXT)); - HMENU hSubMenu = GetSubMenu(hMenu, 2); - RemoveMenu(hSubMenu, 9, MF_BYPOSITION); - RemoveMenu(hSubMenu, 8, MF_BYPOSITION); - RemoveMenu(hSubMenu, 4, MF_BYPOSITION); - - EnableMenuItem(hSubMenu, IDM_PASTEFORMATTED, MF_BYCOMMAND | (m_si->pMI->bBold ? MF_ENABLED : MF_GRAYED)); - TranslateMenu(hSubMenu); - - CHARRANGE sel, all = { 0, -1 }; - m_message.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel); - if (sel.cpMin == sel.cpMax) { - EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(hSubMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED); - } - - MessageWindowPopupData mwpd = { sizeof(mwpd) }; - mwpd.uType = MSG_WINDOWPOPUP_SHOWING; - mwpd.uFlags = MSG_WINDOWPOPUP_INPUT; - mwpd.hContact = m_hContact; - mwpd.hwnd = m_message.GetHwnd(); - mwpd.hMenu = hSubMenu; - mwpd.pt = pt; - NotifyEventHooks(g_chatApi.hevWinPopup, 0, (LPARAM)&mwpd); - - int iSelection = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, m_hwnd, nullptr); - - mwpd.selection = iSelection; - mwpd.uType = MSG_WINDOWPOPUP_SELECTED; - NotifyEventHooks(g_chatApi.hevWinPopup, 0, (LPARAM)&mwpd); - - switch (iSelection) { - case IDM_COPY: - m_message.SendMsg(WM_COPY, 0, 0); - break; - case IDM_CUT: - m_message.SendMsg(WM_CUT, 0, 0); - break; - case IDM_PASTE: - case IDM_PASTEFORMATTED: - m_message.SendMsg(EM_PASTESPECIAL, (iSelection == IDM_PASTE) ? CF_UNICODETEXT : 0, 0); - break; - case IDM_COPYALL: - m_message.SendMsg(EM_EXSETSEL, 0, (LPARAM)&all); - m_message.SendMsg(WM_COPY, 0, 0); - m_message.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel); - break; - case IDM_SELECTALL: - m_message.SendMsg(EM_EXSETSEL, 0, (LPARAM)&all); - break; - } - DestroyMenu(hMenu); - } - return TRUE; - - case WM_MOUSEWHEEL: - if (DM_MouseWheelHandler(wParam, lParam) == 0) - return 0; - - m_iLastEnterTime = 0; - break; - - case WM_SYSKEYUP: - if (wParam == VK_MENU) { - ProcessHotkeysByMsgFilter(m_message, msg, wParam, lParam); - return 0; - } - break; - - case WM_SYSKEYDOWN: - m_bkeyProcessed = false; - if (ProcessHotkeysByMsgFilter(m_message, msg, wParam, lParam)) { - m_bkeyProcessed = true; - return 0; - } - break; - - case WM_SYSCHAR: - if (m_bkeyProcessed) { - m_bkeyProcessed = false; // preceeding key event has been processed by miranda hotkey service - return 0; - } - - if ((wParam >= '0' && wParam <= '9') && (GetKeyState(VK_MENU) & 0x8000)) { // ALT-1 -> ALT-0 direct tab selection - BYTE bChar = (BYTE)wParam; - int iIndex = (bChar == '0') ? 10 : bChar - (BYTE)'0'; - SendMessage(m_pContainer->m_hwnd, DM_SELECTTAB, DM_SELECT_BY_INDEX, (LPARAM)iIndex); - return 0; - } - break; - - case WM_CHAR: - bool isShift, isAlt, isCtrl; - KbdState(isShift, isCtrl, isAlt); - - if (!isAlt && !isCtrl && !(m_pContainer->m_dwFlags & CNT_NOSOUND) && wParam != VK_ESCAPE && !(wParam == VK_TAB && PluginConfig.m_bAllowTab)) - Skin_PlaySound("SoundOnTyping"); - - if (isCtrl && !isAlt && !isShift) - switch (wParam) { - case 0x17: - PostMessage(m_hwnd, WM_CLOSE, 0, 1); - return 0; - } - - break; - - case WM_KEYDOWN: - KbdState(isShift, isCtrl, isAlt); - - // sound on typing.. - if (!isAlt && wParam == VK_DELETE) - Skin_PlaySound("SoundOnTyping"); - - if (wParam != VK_ESCAPE) - if (ProcessHotkeys(wParam, isShift, isCtrl, isAlt)) - return true; - - if (wParam == VK_INSERT && !isShift && !isCtrl && !isAlt) { - m_bInsertMode = !m_bInsertMode; - m_message.OnChange(&m_message); - } - if (wParam == VK_CAPITAL || wParam == VK_NUMLOCK) - m_message.OnChange(&m_message); - - if (isCtrl && isAlt && !isShift) { - switch (wParam) { - case VK_UP: - case VK_DOWN: - case VK_PRIOR: - case VK_NEXT: - case VK_HOME: - case VK_END: - WPARAM wp = 0; - - if (wParam == VK_UP) - wp = MAKEWPARAM(SB_LINEUP, 0); - else if (wParam == VK_PRIOR) - wp = MAKEWPARAM(SB_PAGEUP, 0); - else if (wParam == VK_NEXT) - wp = MAKEWPARAM(SB_PAGEDOWN, 0); - else if (wParam == VK_HOME) - wp = MAKEWPARAM(SB_TOP, 0); - else if (wParam == VK_END) { - DM_ScrollToBottom(0, 0); - return 0; - } - else if (wParam == VK_DOWN) - wp = MAKEWPARAM(SB_LINEDOWN, 0); - - m_log.SendMsg(WM_VSCROLL, wp, 0); - return 0; - } - } - - if (wParam == VK_RETURN) { - if (isShift) { - if (PluginConfig.m_bSendOnShiftEnter) { - PostMessage(m_hwnd, WM_COMMAND, IDOK, 0); - return 0; - } - break; - } - if ((isCtrl && !isShift) ^ (0 != PluginConfig.m_bSendOnEnter)) { - PostMessage(m_hwnd, WM_COMMAND, IDOK, 0); - return 0; - } - if (!PluginConfig.m_bSendOnEnter && !PluginConfig.m_bSendOnDblEnter) - break; - if (isCtrl) - break; - - if (PluginConfig.m_bSendOnDblEnter) { - if (m_iLastEnterTime + 2 < time(0)) { - m_iLastEnterTime = time(0); - break; - } - - m_message.SendMsg(WM_KEYDOWN, VK_BACK, 0); - m_message.SendMsg(WM_KEYUP, VK_BACK, 0); - PostMessage(m_hwnd, WM_COMMAND, IDOK, 0); - return 0; - } - PostMessage(m_hwnd, WM_COMMAND, IDOK, 0); - return 0; - } - else m_iLastEnterTime = 0; - - if ((wParam == VK_NEXT && isCtrl && !isShift) || (wParam == VK_TAB && isCtrl && !isShift)) { // CTRL-TAB (switch tab/window) - SendMessage(m_pContainer->m_hwnd, DM_SELECTTAB, DM_SELECT_NEXT, 0); - return TRUE; - } - - if ((wParam == VK_PRIOR && isCtrl && !isShift) || (wParam == VK_TAB && isCtrl && isShift)) { // CTRL_SHIFT-TAB (switch tab/window) - SendMessage(m_pContainer->m_hwnd, DM_SELECTTAB, DM_SELECT_PREV, 0); - return TRUE; - } - if (wParam == VK_TAB && !isCtrl && !isShift) { // tab-autocomplete - m_message.SendMsg(WM_SETREDRAW, FALSE, 0); - bool fCompleted = TabAutoComplete(); - m_message.SendMsg(WM_SETREDRAW, TRUE, 0); - RedrawWindow(m_message.GetHwnd(), nullptr, nullptr, RDW_INVALIDATE); - if (!fCompleted && !PluginConfig.m_bAllowTab) { - if ((GetSendButtonState(GetHwnd()) != PBS_DISABLED)) - SetFocus(m_btnOk.GetHwnd()); - else - SetFocus(m_log.GetHwnd()); - } - return 0; - } - - if (wParam != VK_RIGHT && wParam != VK_LEFT) { - replaceStrW(m_wszSearchQuery, nullptr); - replaceStrW(m_wszSearchResult, nullptr); - } + m_nickList.SetItemHeight(0, g_Settings.iNickListFontHeight); + InvalidateRect(m_nickList.GetHwnd(), nullptr, TRUE); - if (wParam == VK_F4 && isCtrl && !isAlt) { // ctrl-F4 (close tab) - CloseTab(); - return 0; - } + m_btnFilter.SendMsg(BUTTONSETOVERLAYICON, (LPARAM)(m_bFilterEnabled ? PluginConfig.g_iconOverlayEnabled : PluginConfig.g_iconOverlayDisabled), 0); + Resize(); + RedrawLog2(); +} - if (wParam == VK_NEXT || wParam == VK_PRIOR) { - m_log.SendMsg(msg, wParam, lParam); - m_iLastEnterTime = 0; - return 0; - } +void CMsgDialog::UpdateStatusBar() +{ + if (m_pContainer->m_hwndActive != m_hwnd || m_pContainer->m_hwndStatus == nullptr || CMimAPI::m_shutDown || m_wszStatusBar[0]) + return; - // input history scrolling (ctrl-up / down) - if (isCtrl && !isAlt && !isShift && (wParam == VK_UP || wParam == VK_DOWN)) { - m_iLastEnterTime = 0; - m_cache->inputHistoryEvent(wParam); - return 0; - } + if (m_si->pszModule == nullptr) + return; - __fallthrough; + //Mad: strange rare crash here... + MODULEINFO *mi = m_si->pMI; + if (!mi->ptszModDispName) + return; - case WM_LBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_KILLFOCUS: - m_iLastEnterTime = 0; - break; + int x = 12; + x += Chat_GetTextPixelSize(mi->ptszModDispName, (HFONT)SendMessage(m_pContainer->m_hwndStatus, WM_GETFONT, 0, 0), true); + x += GetSystemMetrics(SM_CXSMICON); - case WM_ERASEBKGND: - return !CSkin::m_skinEnabled; - } + wchar_t szFinalStatusBarText[512]; + if (m_pPanel.isActive()) { + time_t now = time(0); + DWORD diff = (now - mi->idleTimeStamp) / 60; + if (diff >= 1) { + if (diff > 59) { + DWORD hours = diff / 60; + DWORD minutes = diff % 60; + mir_snwprintf(mi->tszIdleMsg, TranslateT(", %d %s, %d %s idle"), + hours, hours > 1 ? TranslateT("hours") : TranslateT("hour"), + minutes, minutes > 1 ? TranslateT("minutes") : TranslateT("minute")); + } + else mir_snwprintf(mi->tszIdleMsg, TranslateT(", %d %s idle"), diff, diff > 1 ? TranslateT("minutes") : TranslateT("minute")); + } + else mi->tszIdleMsg[0] = 0; - return CSuper::WndProc_Message(msg, wParam, lParam); + mir_snwprintf(szFinalStatusBarText, TranslateT("%s on %s%s"), m_wszMyNickname, mi->ptszModDispName, mi->tszIdleMsg); + } + else { + if (m_si->ptszStatusbarText) + mir_snwprintf(szFinalStatusBarText, L"%s %s", mi->ptszModDispName, m_si->ptszStatusbarText); + else + wcsncpy_s(szFinalStatusBarText, mi->ptszModDispName, _TRUNCATE); + } + SendMessage(m_pContainer->m_hwndStatus, SB_SETTEXT, 0, (LPARAM)szFinalStatusBarText); + tabUpdateStatusBar(); + m_pPanel.Invalidate(); + if (m_pWnd) + m_pWnd->Invalidate(); } ///////////////////////////////////////////////////////////////////////////////////////// @@ -1576,725 +513,6 @@ INT_PTR CALLBACK CMsgDialog::FilterWndProc(HWND hwndDlg, UINT uMsg, WPARAM wPara return FALSE; } -///////////////////////////////////////////////////////////////////////////////////////// - -INT_PTR CMsgDialog::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - POINT pt, tmp, cur; - RECT rc; - - switch (uMsg) { - case WM_SETFOCUS: - if (CMimAPI::m_shutDown) - break; - - UpdateWindowState(WM_SETFOCUS); - SetFocus(m_message.GetHwnd()); - return 1; - - case WM_TIMECHANGE: - RedrawLog(); - break; - - case WM_CBD_LOADICONS: - Srmm_UpdateToolbarIcons(m_hwnd); - return 0; - - case WM_SIZE: - if (m_ipFieldHeight == 0) - m_ipFieldHeight = CInfoPanel::m_ipConfig.height1; - - if (wParam == SIZE_MAXIMIZED) - ScrollToBottom(); - - if (!IsIconic(m_hwnd)) { - int panelHeight = m_pPanel.getHeight() + 1; - - GetClientRect(m_hwnd, &rc); - int cx = rc.right; - - CSuper::DlgProc(uMsg, 0, 0); // call basic window resizer - - BB_SetButtonsPos(); - - rc.left = panelHeight <= CInfoPanel::LEFT_OFFSET_LOGO ? panelHeight : CInfoPanel::LEFT_OFFSET_LOGO; - rc.right = cx; - rc.top = 1; - rc.bottom = (panelHeight > CInfoPanel::DEGRADE_THRESHOLD ? rc.top + m_ipFieldHeight - 2 : panelHeight - 1); - m_rcNick = rc; - - rc.left = panelHeight <= CInfoPanel::LEFT_OFFSET_LOGO ? panelHeight : CInfoPanel::LEFT_OFFSET_LOGO; - rc.right = cx; - rc.bottom = panelHeight - 2; - rc.top = m_rcNick.bottom + 1; - m_rcUIN = rc; - - if (m_hwndIEView || m_hwndHPP) - ResizeIeView(); - DetermineMinHeight(); - } - return 0; - - case DM_TYPING: - // Typing support for GCW_PRIVMESS sessions - if (m_si->iType == GCW_PRIVMESS) { - int preTyping = m_nTypeSecs != 0; - m_nTypeSecs = (int)lParam > 0 ? (int)lParam : 0; - - if (m_nTypeSecs) - m_bShowTyping = 0; - - SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, preTyping); - } - return TRUE; - - case WM_CTLCOLORLISTBOX: - SetBkColor((HDC)wParam, g_Settings.crUserListBGColor); - return (INT_PTR)g_chatApi.hListBkgBrush; - - case WM_MEASUREITEM: - { - MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam; - if (mis->CtlType == ODT_MENU) { - if (m_pPanel.isHovered()) { - mis->itemHeight = 0; - mis->itemWidth = 6; - return TRUE; - } - return Menu_MeasureItem(lParam); - } - mis->itemHeight = g_Settings.iNickListFontHeight; - } - return TRUE; - - case WM_DRAWITEM: - { - DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam; - if (dis->CtlType == ODT_MENU) { - if (m_pPanel.isHovered()) { - DrawMenuItem(dis, (HICON)dis->itemData, 0); - return TRUE; - } - return Menu_DrawItem(lParam); - } - - if (dis->CtlID == IDC_SRMM_NICKLIST) { - int x_offset = 0; - int index = dis->itemID; - - USERINFO *ui = g_chatApi.UM_FindUserFromIndex(m_si, index); - if (ui == nullptr) - return TRUE; - - int height = dis->rcItem.bottom - dis->rcItem.top; - if (height & 1) - height++; - int offset = (height == 10) ? 0 : height / 2; - - HICON hIcon = g_chatApi.SM_GetStatusIcon(m_si, ui); - HFONT hFont = g_Settings.UserListFonts[ui->iStatusEx]; - HFONT hOldFont = (HFONT)SelectObject(dis->hDC, hFont); - SetBkMode(dis->hDC, TRANSPARENT); - - int nickIndex = 0; - for (int i = 0; i < STATUSICONCOUNT; i++) { - if (hIcon == g_chatApi.hIcons[ICON_STATUS0 + i]) { - nickIndex = i; - break; - } - } - - if (dis->itemState & ODS_SELECTED) { - FillRect(dis->hDC, &dis->rcItem, g_Settings.SelectionBGBrush); - SetTextColor(dis->hDC, g_Settings.nickColors[6]); - } - else { - FillRect(dis->hDC, &dis->rcItem, g_chatApi.hListBkgBrush); - if (g_Settings.bColorizeNicks && nickIndex != 0) - SetTextColor(dis->hDC, g_Settings.nickColors[nickIndex - 1]); - else - SetTextColor(dis->hDC, g_Settings.UserListColors[ui->iStatusEx]); - } - x_offset = 2; - - if (g_Settings.bShowContactStatus && g_Settings.bContactStatusFirst && ui->ContactStatus) { - HICON icon = Skin_LoadProtoIcon(m_si->pszModule, ui->ContactStatus); - DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 8, icon, 16, 16, 0, nullptr, DI_NORMAL); - IcoLib_ReleaseIcon(icon); - x_offset += 18; - } - - if (g_Settings.bClassicIndicators) { - char szTemp[3]; - szTemp[1] = 0; - szTemp[0] = szIndicators[nickIndex]; - if (szTemp[0]) { - SIZE szUmode; - GetTextExtentPoint32A(dis->hDC, szTemp, 1, &szUmode); - TextOutA(dis->hDC, x_offset, dis->rcItem.top, szTemp, 1); - x_offset += szUmode.cx + 2; - } - else x_offset += 8; - } - else { - DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 5, hIcon, 10, 10, 0, nullptr, DI_NORMAL); - x_offset += 12; - } - - if (g_Settings.bShowContactStatus && !g_Settings.bContactStatusFirst && ui->ContactStatus) { - HICON icon = Skin_LoadProtoIcon(m_si->pszModule, ui->ContactStatus); - DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 8, icon, 16, 16, 0, nullptr, DI_NORMAL); - IcoLib_ReleaseIcon(icon); - x_offset += 18; - } - - SIZE sz; - if (m_iSearchItem != -1 && m_iSearchItem == index && m_wszSearch[0]) { - COLORREF clr_orig = GetTextColor(dis->hDC); - GetTextExtentPoint32(dis->hDC, ui->pszNick, (int)mir_wstrlen(m_wszSearch), &sz); - SetTextColor(dis->hDC, RGB(250, 250, 0)); - TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick, (int)mir_wstrlen(m_wszSearch)); - SetTextColor(dis->hDC, clr_orig); - x_offset += sz.cx; - TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick + mir_wstrlen(m_wszSearch), int(mir_wstrlen(ui->pszNick) - mir_wstrlen(m_wszSearch))); - } - else { - GetTextExtentPoint32(dis->hDC, ui->pszNick, (int)mir_wstrlen(ui->pszNick), &sz); - TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick, (int)mir_wstrlen(ui->pszNick)); - SelectObject(dis->hDC, hOldFont); - } - return TRUE; - } - } - break; - - case WM_CONTEXTMENU: - { - DWORD idFrom = GetDlgCtrlID((HWND)wParam); - if (idFrom >= MIN_CBUTTONID && idFrom <= MAX_CBUTTONID) - Srmm_ClickToolbarIcon(m_hContact, idFrom, m_hwnd, 1); - } - break; - - case DM_SPLITTERMOVED: - RECT rcLog; - GetWindowRect(m_log.GetHwnd(), &rcLog); - - if ((HWND)lParam == GetDlgItem(m_hwnd, IDC_SPLITTERX)) { - GetClientRect(m_hwnd, &rc); - pt.x = wParam, pt.y = 0; - ScreenToClient(m_hwnd, &pt); - - int iSplitterX = rc.right - pt.x + 1; - if (iSplitterX < 35) - iSplitterX = 35; - if (iSplitterX > rc.right - rc.left - 35) - iSplitterX = rc.right - rc.left - 35; - m_pContainer->m_pSettings->iSplitterX = iSplitterX; - Resize(); - } - else if ((HWND)lParam == GetDlgItem(m_hwnd, IDC_SPLITTERY) || lParam == -1) { - GetClientRect(m_hwnd, &rc); - rc.top += (m_pPanel.isActive() ? m_pPanel.getHeight() + 40 : 30); - pt.x = 0, pt.y = wParam; - ScreenToClient(m_hwnd, &pt); - - m_iSplitterY = rc.bottom - pt.y + 3 + DPISCALEY_S(23); - int iMinHeight = DPISCALEY_S(23) + ((m_pContainer->m_dwFlags & CNT_BOTTOMTOOLBAR) ? 21 : 0); - if (m_iSplitterY < iMinHeight) - m_iSplitterY = iMinHeight; - if (m_iSplitterY > rc.bottom - rc.top - DPISCALEY_S(40)) - m_iSplitterY = rc.bottom - rc.top - DPISCALEY_S(40); - m_pContainer->m_pSettings->iSplitterY = m_iSplitterY; - UpdateToolbarBG(); - Resize(); - } - else if ((HWND)lParam == GetDlgItem(m_hwnd, IDC_PANELSPLITTER)) { - pt.x = 0, pt.y = wParam; - ScreenToClient(m_hwnd, &pt); - GetClientRect(m_log.GetHwnd(), &rc); - if ((pt.y + 2 >= MIN_PANELHEIGHT + 2) && (pt.y + 2 < 100) && (pt.y + 2 < rc.bottom - 30)) - m_pPanel.setHeight(pt.y + 2); - RedrawWindow(m_hwnd, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); - if (M.isAero()) - InvalidateRect(m_hwndParent, nullptr, FALSE); - SendMessage(m_hwnd, WM_SIZE, DM_SPLITTERMOVED, 0); - break; - } - break; - - case WM_TIMER: - if (wParam == TIMERID_FLASHWND) - if (m_bCanFlashTab) - FlashTab(true); - - // Typing support for GCW_PRIVMESS sessions - if (m_si->iType == GCW_PRIVMESS && wParam == TIMERID_TYPE) - DM_Typing(false); - break; - - case WM_ACTIVATE: - case WM_MOUSEACTIVATE: - if (LOWORD(wParam) != WA_ACTIVE) { - m_pContainer->m_hwndSaved = nullptr; - break; - } - - UpdateWindowState(WM_ACTIVATE); - return 1; - - case WM_NOTIFY: - switch (((LPNMHDR)lParam)->code) { - case EN_MSGFILTER: - bool isShift, isCtrl, isMenu; - { - UINT msg = ((MSGFILTER *)lParam)->msg; - WPARAM wp = ((MSGFILTER *)lParam)->wParam; - LPARAM lp = ((MSGFILTER *)lParam)->lParam; - - KbdState(isShift, isCtrl, isMenu); - - MSG message; - message.hwnd = m_hwnd; - message.message = msg; - message.lParam = lp; - message.wParam = wp; - - if (msg == WM_SYSKEYUP) { - if (wp == VK_MENU) - if (!m_bkeyProcessed && !(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000) && !(lp & (1 << 24))) - m_pContainer->m_pMenuBar->autoShow(); - - return _dlgReturn(m_hwnd, 0); - } - - if (msg == WM_MOUSEMOVE) { - GetCursorPos(&pt); - DM_DismissTip(pt); - m_pPanel.trackMouse(pt); - break; - } - if (msg == WM_KEYDOWN) { - if ((wp == VK_INSERT && isShift && !isCtrl && !isMenu) || (wp == 'V' && !isShift && !isMenu && isCtrl)) { - m_message.SendMsg(EM_PASTESPECIAL, CF_UNICODETEXT, 0); - ((MSGFILTER*)lParam)->msg = WM_NULL; - ((MSGFILTER*)lParam)->wParam = 0; - ((MSGFILTER*)lParam)->lParam = 0; - return _dlgReturn(m_hwnd, 1); - } - } - - if (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN || msg == WM_MBUTTONDOWN) - m_pContainer->m_pMenuBar->Cancel(); - - if ((msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) && !(GetKeyState(VK_RMENU) & 0x8000)) { - if (DM_GenericHotkeysCheck(&message)) { - m_bkeyProcessed = true; - return _dlgReturn(m_hwnd, 1); - } - - LRESULT mim_hotkey_check = Hotkey_Check(&message, TABSRMM_HK_SECTION_GC); - if (mim_hotkey_check) - m_bkeyProcessed = true; - - switch (mim_hotkey_check) { - case TABSRMM_HK_CHANNELMGR: - onClick_ChanMgr(&m_btnChannelMgr); - return _dlgReturn(m_hwnd, 1); - case TABSRMM_HK_FILTERTOGGLE: - onClick_Filter(&m_btnFilter); - InvalidateRect(m_btnFilter.GetHwnd(), nullptr, TRUE); - return _dlgReturn(m_hwnd, 1); - case TABSRMM_HK_LISTTOGGLE: - onClick_ShowNickList(&m_btnNickList); - return _dlgReturn(m_hwnd, 1); - case TABSRMM_HK_MUC_SHOWSERVER: - if (m_si->iType != GCW_SERVER) - Chat_DoEventHook(m_si, GC_USER_MESSAGE, nullptr, L"/servershow", 0); - return _dlgReturn(m_hwnd, 1); - } - } - - if (msg == WM_KEYDOWN && ((NMHDR*)lParam)->idFrom != IDC_SRMM_MESSAGE) { - if ((wp == VK_NEXT && isCtrl && !isShift) || (wp == VK_TAB && isCtrl && !isShift)) // CTRL-TAB (switch tab/window) - SendMessage(m_pContainer->m_hwnd, DM_SELECTTAB, DM_SELECT_NEXT, 0); - else if ((wp == VK_PRIOR && isCtrl && !isShift) || (wp == VK_TAB && isCtrl && isShift)) // CTRL_SHIFT-TAB (switch tab/window) - SendMessage(m_pContainer->m_hwnd, DM_SELECTTAB, DM_SELECT_PREV, 0); - } - - if (msg == WM_KEYDOWN && wp == VK_TAB) { - if (((NMHDR*)lParam)->idFrom == IDC_SRMM_LOG) { - SetFocus(m_message.GetHwnd()); - return _dlgReturn(m_hwnd, 1); - } - } - - if (((LPNMHDR)lParam)->idFrom == IDC_SRMM_LOG && ((MSGFILTER *)lParam)->msg == WM_RBUTTONUP) - return _dlgReturn(m_hwnd, 1); - } - break; - - case EN_REQUESTRESIZE: - if (((LPNMHDR)lParam)->idFrom == IDC_SRMM_MESSAGE) - DM_HandleAutoSizeRequest((REQRESIZE *)lParam); - break; - - case EN_LINK: - if (((LPNMHDR)lParam)->idFrom == IDC_SRMM_LOG) { - switch (((ENLINK*)lParam)->msg) { - case WM_RBUTTONDOWN: - case WM_LBUTTONUP: - case WM_LBUTTONDBLCLK: - CHARRANGE sel; - SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_EXGETSEL, 0, (LPARAM)&sel); - if (sel.cpMin == sel.cpMax) { - UINT msg = ((ENLINK*)lParam)->msg; - m_pContainer->m_pMenuBar->Cancel(); - - TEXTRANGE tr; - tr.lpstrText = nullptr; - tr.chrg = ((ENLINK*)lParam)->chrg; - tr.lpstrText = (wchar_t*)mir_alloc(sizeof(wchar_t) * (tr.chrg.cpMax - tr.chrg.cpMin + 2)); - SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&tr); - - BOOL isLink = IsStringValidLink(tr.lpstrText); - if (isLink) // handled by core - break; - - // clicked a nick name - if (g_Settings.bClickableNicks) { - if (msg == WM_RBUTTONDOWN) { - for (auto &ui : m_si->getUserList()) { - if (mir_wstrcmp(ui->pszNick, tr.lpstrText)) - continue; - - pt.x = (short)LOWORD(((ENLINK*)lParam)->lParam); - pt.y = (short)HIWORD(((ENLINK*)lParam)->lParam); - ClientToScreen(((NMHDR*)lParam)->hwndFrom, &pt); - RunUserMenu(m_hwnd, ui, pt); - break; - } - return TRUE; - } - - if (msg == WM_LBUTTONUP) { - CHARRANGE chr; - m_message.SendMsg(EM_EXGETSEL, 0, (LPARAM)&chr); - - wchar_t tszAplTmpl[] = L"%s:"; - size_t bufSize = mir_wstrlen(tr.lpstrText) + mir_wstrlen(tszAplTmpl) + 3; - wchar_t *tszTmp = (wchar_t*)mir_alloc(bufSize * sizeof(wchar_t)), *tszAppeal = tszTmp; - - TEXTRANGE tr2; - tr2.lpstrText = (LPTSTR)mir_alloc(sizeof(wchar_t) * 2); - if (chr.cpMin) { - // prepend nick with space if needed - tr2.chrg.cpMin = chr.cpMin - 1; - tr2.chrg.cpMax = chr.cpMin; - m_message.SendMsg(EM_GETTEXTRANGE, 0, (LPARAM)&tr2); - if (!iswspace(*tr2.lpstrText)) - *tszTmp++ = ' '; - mir_wstrcpy(tszTmp, tr.lpstrText); - } - else // in the beginning of the message window - mir_snwprintf(tszAppeal, bufSize, tszAplTmpl, tr.lpstrText); - - size_t st = mir_wstrlen(tszAppeal); - if (chr.cpMax != -1) { - tr2.chrg.cpMin = chr.cpMax; - tr2.chrg.cpMax = chr.cpMax + 1; - // if there is no space after selection, - // or there is nothing after selection at all... - if (!m_message.SendMsg(EM_GETTEXTRANGE, 0, (LPARAM)&tr2) || !iswspace(*tr2.lpstrText)) { - tszAppeal[st++] = ' '; - tszAppeal[st++] = '\0'; - } - } - else { - tszAppeal[st++] = ' '; - tszAppeal[st++] = '\0'; - } - m_message.SendMsg(EM_REPLACESEL, FALSE, (LPARAM)tszAppeal); - mir_free((void*)tr2.lpstrText); - mir_free((void*)tszAppeal); - } - } - SetFocus(m_message.GetHwnd()); - mir_free(tr.lpstrText); - return TRUE; - } - } - break; - } - break; - } - break; - - case WM_LBUTTONDOWN: - GetCursorPos(&tmp); - if (!m_pPanel.isHovered()) { - cur.x = (SHORT)tmp.x; - cur.y = (SHORT)tmp.y; - SendMessage(m_pContainer->m_hwnd, WM_NCLBUTTONDOWN, HTCAPTION, *((LPARAM*)(&cur))); - } - break; - - case WM_LBUTTONUP: - GetCursorPos(&tmp); - if (m_pPanel.isHovered()) - m_pPanel.handleClick(tmp); - else { - cur.x = (SHORT)tmp.x; - cur.y = (SHORT)tmp.y; - SendMessage(m_pContainer->m_hwnd, WM_NCLBUTTONUP, HTCAPTION, *((LPARAM*)(&cur))); - } - break; - - case WM_MOUSEMOVE: - GetCursorPos(&pt); - DM_DismissTip(pt); - m_pPanel.trackMouse(pt); - break; - - case WM_APPCOMMAND: - { - DWORD cmd = GET_APPCOMMAND_LPARAM(lParam); - if (cmd == APPCOMMAND_BROWSER_BACKWARD || cmd == APPCOMMAND_BROWSER_FORWARD) { - SendMessage(m_pContainer->m_hwnd, DM_SELECTTAB, cmd == APPCOMMAND_BROWSER_BACKWARD ? DM_SELECT_PREV : DM_SELECT_NEXT, 0); - return 1; - } - } - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_TOGGLESIDEBAR: - SendMessage(m_pContainer->m_hwnd, WM_COMMAND, IDC_TOGGLESIDEBAR, 0); - break; - - case IDCANCEL: - ShowWindow(m_pContainer->m_hwnd, SW_MINIMIZE); - return FALSE; - - case IDC_CLOSE: - CloseTab(); - break; - - case IDC_SELFTYPING: - // Typing support for GCW_PRIVMESS sessions - if (m_si->iType == GCW_PRIVMESS) { - if (m_hContact) { - int iCurrentTypingMode = g_plugin.getByte(m_hContact, SRMSGSET_TYPING, g_plugin.getByte(SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW)); - - if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON && iCurrentTypingMode) { - DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); - m_nTypeMode = PROTOTYPE_SELFTYPING_OFF; - } - g_plugin.setByte(m_hContact, SRMSGSET_TYPING, (BYTE)!iCurrentTypingMode); - } - } - break; - } - break; - - case WM_KEYDOWN: - SetFocus(m_message.GetHwnd()); - break; - - case WM_ERASEBKGND: - RECT rcClient, rcWindow; - { - HDC hdc = (HDC)wParam; - UINT item_ids[3] = { ID_EXTBKUSERLIST, ID_EXTBKHISTORY, ID_EXTBKINPUTAREA }; - UINT ctl_ids[3] = { IDC_SRMM_NICKLIST, IDC_SRMM_LOG, IDC_SRMM_MESSAGE }; - HANDLE hbp = nullptr; - HDC hdcMem = nullptr; - HBITMAP hbm, hbmOld; - - GetClientRect(m_hwnd, &rcClient); - LONG cx = rcClient.right - rcClient.left; - LONG cy = rcClient.bottom - rcClient.top; - - if (CMimAPI::m_haveBufferedPaint) { - hbp = CSkin::InitiateBufferedPaint(hdc, rcClient, hdcMem); - hbm = hbmOld = nullptr; - } - else { - hdcMem = CreateCompatibleDC(hdc); - hbm = CSkin::CreateAeroCompatibleBitmap(rcClient, hdc); - hbmOld = (HBITMAP)SelectObject(hdcMem, hbm); - } - - if (CSkin::m_skinEnabled && !M.isAero()) { - CSkin::SkinDrawBG(m_hwnd, m_pContainer->m_hwnd, m_pContainer, &rcClient, hdcMem); - for (int i = 0; i < 3; i++) { - CSkinItem *item = &SkinItems[item_ids[i]]; - if (!item->IGNORED) { - GetWindowRect(GetDlgItem(m_hwnd, ctl_ids[i]), &rcWindow); - pt.x = rcWindow.left; - pt.y = rcWindow.top; - ScreenToClient(m_hwnd, &pt); - rc.left = pt.x - item->MARGIN_LEFT; - rc.top = pt.y - item->MARGIN_TOP; - rc.right = rc.left + item->MARGIN_RIGHT + (rcWindow.right - rcWindow.left) + item->MARGIN_LEFT; - rc.bottom = rc.top + item->MARGIN_BOTTOM + (rcWindow.bottom - rcWindow.top) + item->MARGIN_TOP; - CSkin::DrawItem(hdcMem, &rc, item); - } - } - } - else { - CSkin::FillBack(hdcMem, &rcClient); - - if (M.isAero()) { - LONG temp = rcClient.bottom; - rcClient.bottom = m_pPanel.isActive() ? m_pPanel.getHeight() + 5 : 5; - FillRect(hdcMem, &rcClient, (HBRUSH)GetStockObject(BLACK_BRUSH)); - rcClient.bottom = temp; - } - } - - GetClientRect(m_hwnd, &rc); - m_pPanel.renderBG(hdcMem, rc, &SkinItems[ID_EXTBKINFOPANELBG], M.isAero()); - m_pPanel.renderContent(hdcMem); - - if (!CSkin::m_skinEnabled) - RenderToolbarBG(hdcMem, rcClient); - - if (hbp) - CSkin::FinalizeBufferedPaint(hbp, &rcClient); - else { - BitBlt(hdc, 0, 0, cx, cy, hdcMem, 0, 0, SRCCOPY); - SelectObject(hdcMem, hbmOld); - DeleteObject(hbm); - DeleteDC(hdcMem); - } - if (!m_fLimitedUpdate) - SetAeroMargins(m_pContainer); - } - return TRUE; - - case WM_NCPAINT: - if (CSkin::m_skinEnabled) - return 0; - break; - - case WM_PAINT: - PAINTSTRUCT ps; - BeginPaint(m_hwnd, &ps); - EndPaint(m_hwnd, &ps); - return 0; - - case WM_RBUTTONUP: - GetCursorPos(&pt); - if (!m_pPanel.invokeConfigDialog(pt)) { - HMENU subMenu = GetSubMenu(PluginConfig.g_hMenuContext, 0); - - MsgWindowUpdateMenu(subMenu, MENU_TABCONTEXT); - - int iSelection = TrackPopupMenu(subMenu, TPM_RETURNCMD, pt.x, pt.y, 0, m_hwnd, nullptr); - if (iSelection >= IDM_CONTAINERMENU) { - char szIndex[10]; - _itoa_s(iSelection - IDM_CONTAINERMENU, szIndex, 10); - ptrW wszContainer(db_get_wsa(0, "TAB_ContainersW", szIndex)); - if (wszContainer != nullptr) - SendMessage(m_hwnd, DM_CONTAINERSELECTED, 0, wszContainer); - break; - } - MsgWindowMenuHandler(iSelection, MENU_TABCONTEXT); - } - break; - - case WM_LBUTTONDBLCLK: - if (LOWORD(lParam) < 30) - ScrollToBottom(); - break; - - case WM_CLOSE: - if (wParam == 0 && lParam == 0) { - switch (PluginConfig.m_EscapeCloses) { - case 1: // minimize container - SendMessage(m_pContainer->m_hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); - return TRUE; - - case 2: // close or hide, optionally - if (PluginConfig.m_bHideOnClose) { - ShowWindow(m_pContainer->m_hwnd, SW_HIDE); - return TRUE; - } - break; - - case 3: // does nothing - _dlgReturn(m_hwnd, FALSE); - return TRUE; - } - _dlgReturn(m_hwnd, TRUE); - } - CloseTab(); - return 0; - - case DM_SAVESIZE: - if (m_dwFlags & MWF_NEEDCHECKSIZE) - lParam = 0; - - m_dwFlags &= ~MWF_NEEDCHECKSIZE; - if (m_dwFlags & MWF_WASBACKGROUNDCREATE) - m_dwFlags &= ~MWF_INITMODE; - - SendMessage(m_pContainer->m_hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)&rcClient); - MoveWindow(m_hwnd, rcClient.left, rcClient.top, (rcClient.right - rcClient.left), (rcClient.bottom - rcClient.top), TRUE); - - if (m_dwFlags & MWF_WASBACKGROUNDCREATE) { - m_dwFlags &= ~MWF_WASBACKGROUNDCREATE; - Resize(); - - pt.x = pt.y = 0; - m_log.SendMsg(EM_SETSCROLLPOS, 0, (LPARAM)&pt); - } - else { - Resize(); - if (lParam == 0) - DM_ScrollToBottom(1, 1); - } - return 0; - - case WM_CBD_UPDATED: - if (lParam) - CB_ChangeButton((CustomButtonData*)lParam); - else - BB_InitDlgButtons(); - - BB_SetButtonsPos(); - return 0; - - case WM_CBD_REMOVED: - if (lParam) - CB_DestroyButton((DWORD)wParam, (DWORD)lParam); - else - CB_DestroyAllButtons(); - break; - - case DM_CONFIGURETOOLBAR: - Resize(); - break; - - case DM_SMILEYOPTIONSCHANGED: - RedrawLog(); - break; - - case EM_THEMECHANGED: - DM_FreeTheme(); - DM_ThemeChanged(); - return 0; - - case WM_DWMCOMPOSITIONCHANGED: - BB_RefreshTheme(); - m_pContainer->ClearMargins(); - VerifyProxy(); - break; - } - return CSuper::DlgProc(uMsg, wParam, lParam); -} - ///////////////////////////////////////////////////////////////////////////////////////// // chat session creator @@ -2361,7 +579,7 @@ void ShowRoom(TContainerData *pContainer, SESSION_INFO *si) if (iCount > 0) { for (int i = iCount - 1; i >= 0; i--) { HWND hwnd = GetTabWindow(hwndTab, i); - CSrmmWindow *dat = (CSrmmWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if (dat) { int relPos = M.GetDword(dat->m_hContact, "tabindex", i * 100); if (iTabIndex_wanted <= relPos) @@ -2379,7 +597,7 @@ void ShowRoom(TContainerData *pContainer, SESSION_INFO *si) TabCtrl_SetCurSel(hwndTab, iTabId); pContainer->m_iChilds++; - CMsgDialog *pDlg = new CMsgDialog(si); + CMsgDialog *pDlg = new CMsgDialog(IDD_CHANNEL, si); pDlg->m_iTabID = iTabId; pDlg->m_pContainer = pContainer; pDlg->SetParent(hwndTab); diff --git a/plugins/TabSRMM/src/contactcache.cpp b/plugins/TabSRMM/src/contactcache.cpp index 790f7c197b..ed30fba4b9 100644 --- a/plugins/TabSRMM/src/contactcache.cpp +++ b/plugins/TabSRMM/src/contactcache.cpp @@ -198,9 +198,9 @@ void CContactCache::updateStats(int iType, size_t value) // dialog will use this in WM_INITDIALOG and WM_DESTROY to tell the cache // that a message window is open for this contact. // -// @param dat: CSrmmWindow* - window data structure +// @param dat: CMsgDialog* - window data structure -void CContactCache::setWindowData(CTabBaseDlg *dat) +void CContactCache::setWindowData(CMsgDialog *dat) { m_dat = dat; diff --git a/plugins/TabSRMM/src/contactcache.h b/plugins/TabSRMM/src/contactcache.h index aeafd8f1e2..afd5aca0d4 100644 --- a/plugins/TabSRMM/src/contactcache.h +++ b/plugins/TabSRMM/src/contactcache.h @@ -65,7 +65,7 @@ class CContactCache : public MZeroedObject bool m_isValid; int m_nMax; - CTabBaseDlg *m_dat; + CMsgDialog *m_dat; TSessionStats *m_stats; DBCachedContact *cc; @@ -106,7 +106,7 @@ public: __forceinline DWORD getSessionStart() const { return m_stats->started; } __forceinline int getSessionMsgCount() const { return (int)m_stats->messageCount; } - __forceinline CTabBaseDlg* getDat() const { return m_dat; } + __forceinline CMsgDialog* getDat() const { return m_dat; } size_t getMaxMessageLength(); void updateStats(int iType, size_t value = 0); @@ -118,7 +118,7 @@ public: void updateMeta(); bool updateUIN(); void updateStatusMsg(const char *szKey = nullptr); - void setWindowData(CTabBaseDlg *dat = nullptr); + void setWindowData(CMsgDialog *dat = nullptr); void resetMeta(); void closeWindow(); void deletedHandler(); diff --git a/plugins/TabSRMM/src/container.cpp b/plugins/TabSRMM/src/container.cpp index f4ecb7ac67..1b8bfd118b 100644 --- a/plugins/TabSRMM/src/container.cpp +++ b/plugins/TabSRMM/src/container.cpp @@ -57,7 +57,7 @@ void TContainerData::InitRedraw() ::SetTimer(m_hwnd, (UINT_PTR)this, 100, nullptr); } -void TContainerData::SetIcon(CTabBaseDlg *pDlg, HICON hIcon) +void TContainerData::SetIcon(CMsgDialog *pDlg, HICON hIcon) { HICON hIconMsg = PluginConfig.g_IconMsgEvent; HICON hIconBig = (pDlg && pDlg->m_cache) ? Skin_LoadProtoIcon(pDlg->m_cache->getProto(), pDlg->m_cache->getStatus(), true) : nullptr; @@ -130,13 +130,13 @@ void TContainerData::UpdateTabs() if (!hDlg) continue; - CTabBaseDlg *dat = (CTabBaseDlg*)GetWindowLongPtr(hDlg, GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr(hDlg, GWLP_USERDATA); if (dat) dat->m_iTabID = i; } } -void TContainerData::UpdateTitle(MCONTACT hContact, CTabBaseDlg *pDlg) +void TContainerData::UpdateTitle(MCONTACT hContact, CMsgDialog *pDlg) { // pDlg != 0 means sent by a chat window if (pDlg) { @@ -151,12 +151,12 @@ void TContainerData::UpdateTitle(MCONTACT hContact, CTabBaseDlg *pDlg) // no hContact given - obtain the hContact for the active tab if (hContact == 0) { if (m_hwndActive && IsWindow(m_hwndActive)) - pDlg = (CTabBaseDlg*)GetWindowLongPtr(m_hwndActive, GWLP_USERDATA); + pDlg = (CMsgDialog*)GetWindowLongPtr(m_hwndActive, GWLP_USERDATA); } else { HWND hwnd = Srmm_FindWindow(hContact); if (hwnd != nullptr) - pDlg = (CTabBaseDlg*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + pDlg = (CMsgDialog*)GetWindowLongPtr(hwnd, GWLP_USERDATA); } if (pDlg) { @@ -181,7 +181,7 @@ void TSAPI SetAeroMargins(TContainerData *pContainer) return; } - CTabBaseDlg *dat = (CTabBaseDlg*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); if (!dat) return; @@ -573,7 +573,7 @@ static INT_PTR CALLBACK DlgProcContainer(HWND hwndDlg, UINT msg, WPARAM wParam, RECT rc; POINT pt; MCONTACT hContact; - CTabBaseDlg *dat; + CMsgDialog *dat; TContainerData *pContainer = (TContainerData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); BOOL bSkinned = CSkin::m_skinEnabled ? TRUE : FALSE; @@ -738,7 +738,7 @@ static INT_PTR CALLBACK DlgProcContainer(HWND hwndDlg, UINT msg, WPARAM wParam, pContainer->m_pMenuBar->getClientRect(); if (pContainer->m_hwndStatus) { - dat = (CTabBaseDlg*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); SendMessage(pContainer->m_hwndStatus, WM_USER + 101, 0, (LPARAM)dat); RECT rcs; @@ -788,7 +788,7 @@ static INT_PTR CALLBACK DlgProcContainer(HWND hwndDlg, UINT msg, WPARAM wParam, SetWindowPos(hDlg, nullptr, rcClient.left, rcClient.top, (rcClient.right - rcClient.left), (rcClient.bottom - rcClient.top), SWP_NOSENDCHANGING | SWP_NOACTIVATE/*|SWP_NOCOPYBITS*/); if (!pContainer->m_bSizingLoop && sizeChanged) { - dat = (CTabBaseDlg*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); if (dat) dat->DM_ScrollToBottom(0, 1); } @@ -853,7 +853,7 @@ static INT_PTR CALLBACK DlgProcContainer(HWND hwndDlg, UINT msg, WPARAM wParam, else nPanel = nm->dwItemSpec; panel_found: if (nPanel == 2) { - dat = (CTabBaseDlg*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); SendMessage(pContainer->m_hwndStatus, SB_GETRECT, nPanel, (LPARAM)&rc); if (dat) dat->CheckStatusIconClick(nm->pt, rc, 2, ((LPNMHDR)lParam)->code); @@ -904,7 +904,7 @@ panel_found: if (((LPNMHDR)lParam)->idFrom == IDC_MSGTABS) { hDlg = GetTabWindow(hwndTab, GetTabItemFromMouse(hwndTab, &pt)); if (hDlg && IsWindow(hDlg)) - dat = (CTabBaseDlg*)GetWindowLongPtr(hDlg, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(hDlg, GWLP_USERDATA); } // sent from a sidebar button (RMB click) instead of the tab control else if (((LPNMHDR)lParam)->idFrom == 5000) { @@ -978,7 +978,7 @@ panel_found: bool fProcessMainMenu = pContainer->m_pMenuBar->isMainMenu(); pContainer->m_pMenuBar->Cancel(); - dat = (CTabBaseDlg*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); DWORD dwOldFlags = pContainer->m_dwFlags; if (dat) { @@ -1181,7 +1181,7 @@ panel_found: case WM_EXITSIZEMOVE: GetClientRect(hwndTab, &rc); if (!((rc.right - rc.left) == pContainer->m_oldSize.cx && (rc.bottom - rc.top) == pContainer->m_oldSize.cy)) { - dat = (CTabBaseDlg*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); if (dat) dat->DM_ScrollToBottom(0, 0); SendMessage(pContainer->m_hwndActive, WM_SIZE, 0, 0); @@ -1261,7 +1261,7 @@ panel_found: PostMessage(hwndDlg, WM_CLOSE, 1, 0); } - dat = (CTabBaseDlg*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); if (dat && !dat->isChat()) { if (dat->m_idle && pContainer->m_hwndActive && IsWindow(pContainer->m_hwndActive)) dat->m_pPanel.Invalidate(TRUE); @@ -1299,7 +1299,7 @@ panel_found: pContainer->ClearMargins(); break; case SC_MINIMIZE: - dat = (CTabBaseDlg*)(GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA)); + dat = (CMsgDialog*)(GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA)); if (dat) { GetWindowRect(pContainer->m_hwndActive, &pContainer->m_rcLogSaved); pContainer->m_ptLogSaved.x = pContainer->m_rcLogSaved.left; @@ -1594,7 +1594,7 @@ panel_found: SetWindowPos(hwndDlg, nullptr, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOCOPYBITS); RedrawWindow(hwndDlg, nullptr, nullptr, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW); if (pContainer->m_hwndActive != nullptr) { - dat = (CTabBaseDlg*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); dat->DM_ScrollToBottom(0, 0); } } @@ -1694,7 +1694,7 @@ panel_found: { DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam; if (dis->hwndItem == pContainer->m_hwndStatus && !(pContainer->m_dwFlags & CNT_NOSTATUSBAR)) { - dat = (CTabBaseDlg*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); if (dat) dat->DrawStatusIcons(dis->hDC, dis->rcItem, 2); return TRUE; @@ -1964,7 +1964,7 @@ int TSAPI ActivateTabFromHWND(HWND hwndTab, HWND hwnd) } // enumerates tabs and closes all of them, but the one in dat -void TSAPI CloseOtherTabs(HWND hwndTab, CTabBaseDlg &dat) +void TSAPI CloseOtherTabs(HWND hwndTab, CMsgDialog &dat) { for (int idxt = 0; idxt < dat.m_pContainer->m_iChilds;) { HWND otherTab = GetTabWindow(hwndTab, idxt); diff --git a/plugins/TabSRMM/src/controls.cpp b/plugins/TabSRMM/src/controls.cpp index 5d0a735fd5..8dd9fb01e8 100644 --- a/plugins/TabSRMM/src/controls.cpp +++ b/plugins/TabSRMM/src/controls.cpp @@ -384,7 +384,7 @@ void CMenuBar::invoke(const int id) m_isContactMenu = m_isMainMenu = false; - CSrmmWindow *dat = (CSrmmWindow*)GetWindowLongPtr(m_pContainer->m_hwndActive, GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr(m_pContainer->m_hwndActive, GWLP_USERDATA); MCONTACT hContact = dat ? dat->m_hContact : 0; @@ -438,7 +438,7 @@ void CMenuBar::Cancel(void) void CMenuBar::updateState(const HMENU hMenu) const { - CSrmmWindow *dat = (CSrmmWindow*)GetWindowLongPtr(m_pContainer->m_hwndActive, GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr(m_pContainer->m_hwndActive, GWLP_USERDATA); if (dat) { ::CheckMenuItem(hMenu, ID_VIEW_SHOWMENUBAR, MF_BYCOMMAND | m_pContainer->m_dwFlags & CNT_NOMENUBAR ? MF_UNCHECKED : MF_CHECKED); ::CheckMenuItem(hMenu, ID_VIEW_SHOWSTATUSBAR, MF_BYCOMMAND | m_pContainer->m_dwFlags & CNT_NOSTATUSBAR ? MF_UNCHECKED : MF_CHECKED); @@ -477,7 +477,7 @@ void CMenuBar::updateState(const HMENU hMenu) const void CMenuBar::configureMenu() const { - CSrmmWindow *dat = (CSrmmWindow*)::GetWindowLongPtr(m_pContainer->m_hwndActive, GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)::GetWindowLongPtr(m_pContainer->m_hwndActive, GWLP_USERDATA); if (dat) { bool fChat = dat->isChat(); @@ -663,10 +663,10 @@ static int tooltip_active = FALSE; static POINT ptMouse = { 0 }; RECT rcLastStatusBarClick; // remembers click (down event) point for status bar clicks -LONG_PTR CALLBACK CTabBaseDlg::StatusBarSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +LONG_PTR CALLBACK CMsgDialog::StatusBarSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { TContainerData *pContainer = (TContainerData*)GetWindowLongPtr(GetParent(hWnd), GWLP_USERDATA); - CTabBaseDlg *dat = nullptr; + CMsgDialog *dat = nullptr; POINT pt; if (OldStatusBarproc == nullptr) { @@ -725,7 +725,7 @@ LONG_PTR CALLBACK CTabBaseDlg::StatusBarSubclassProc(HWND hWnd, UINT msg, WPARAM HANDLE hTheme = bAero ? OpenThemeData(hWnd, L"ButtonStyle") : nullptr; if (pContainer) - dat = (CTabBaseDlg*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); RECT rcClient; GetClientRect(hWnd, &rcClient); @@ -830,7 +830,7 @@ LONG_PTR CALLBACK CTabBaseDlg::StatusBarSubclassProc(HWND hWnd, UINT msg, WPARAM wchar_t szText[1024]; szText[0] = 0; LRESULT result = SendMessage(hWnd, SB_GETTEXT, i, (LPARAM)szText); if (i == 2 && pContainer) { - CSrmmWindow *pDat = (CSrmmWindow*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); + CMsgDialog *pDat = (CMsgDialog*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); if (pDat) pDat->DrawStatusIcons(hdcMem, itemRect, 2); } @@ -878,7 +878,7 @@ LONG_PTR CALLBACK CTabBaseDlg::StatusBarSubclassProc(HWND hWnd, UINT msg, WPARAM // needed when an icon is added to or removed from the icon area { int list_icons = 0; - dat = (CTabBaseDlg*)lParam; + dat = (CMsgDialog*)lParam; if (dat) while (Srmm_GetNthIcon(dat->m_hContact, list_icons)) list_icons++; @@ -941,7 +941,7 @@ LONG_PTR CALLBACK CTabBaseDlg::StatusBarSubclassProc(HWND hWnd, UINT msg, WPARAM GetCursorPos(&pt); if (pt.x != ptMouse.x || pt.y != ptMouse.y) break; - dat = (CTabBaseDlg*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(pContainer->m_hwndActive, GWLP_USERDATA); if (dat != nullptr) { RECT rc; SIZE size; diff --git a/plugins/TabSRMM/src/eventpopups.cpp b/plugins/TabSRMM/src/eventpopups.cpp index 548bd5653a..9f0c80364e 100644 --- a/plugins/TabSRMM/src/eventpopups.cpp +++ b/plugins/TabSRMM/src/eventpopups.cpp @@ -664,7 +664,7 @@ void Popup_Options(WPARAM wParam) // updates the menu entry... // bForced is used to only update the status, nickname etc. and does NOT update the unread count -void TSAPI UpdateTrayMenuState(CTabBaseDlg *dat, BOOL bForced) +void TSAPI UpdateTrayMenuState(CMsgDialog *dat, BOOL bForced) { if (PluginConfig.g_hMenuTrayUnread == nullptr || dat->m_hContact == 0) return; @@ -694,7 +694,7 @@ void TSAPI UpdateTrayMenuState(CTabBaseDlg *dat, BOOL bForced) } // if we want tray support, add the contact to the list of unread sessions in the tray menu -int TSAPI UpdateTrayMenu(const CTabBaseDlg *dat, WORD wStatus, const char *szProto, const wchar_t *szStatus, MCONTACT hContact, DWORD fromEvent) +int TSAPI UpdateTrayMenu(const CMsgDialog *dat, WORD wStatus, const char *szProto, const wchar_t *szStatus, MCONTACT hContact, DWORD fromEvent) { if (!PluginConfig.g_hMenuTrayUnread || hContact == 0 || szProto == nullptr) return 0; diff --git a/plugins/TabSRMM/src/functions.h b/plugins/TabSRMM/src/functions.h index 2de544eb2b..bac6bf1110 100644 --- a/plugins/TabSRMM/src/functions.h +++ b/plugins/TabSRMM/src/functions.h @@ -50,7 +50,7 @@ LONG_PTR CALLBACK HotkeyHandlerDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LP int TSAPI NEN_ReadOptions(NEN_OPTIONS *options); int TSAPI NEN_WriteOptions(NEN_OPTIONS *options); -int TSAPI UpdateTrayMenu(const CTabBaseDlg *dat, WORD wStatus, const char *szProto, const wchar_t *szStatus, MCONTACT hContact, DWORD fromEvent); +int TSAPI UpdateTrayMenu(const CMsgDialog *dat, WORD wStatus, const char *szProto, const wchar_t *szStatus, MCONTACT hContact, DWORD fromEvent); void TSAPI DeletePopupsForContact(MCONTACT hContact, DWORD dwMask); /* @@ -59,7 +59,7 @@ void TSAPI DeletePopupsForContact(MCONTACT hContact, DWORD dwMask); void TSAPI CreateSystrayIcon(int create); void TSAPI FlashTrayIcon(HICON hIcon); -void TSAPI UpdateTrayMenuState(CTabBaseDlg *dat, BOOL bForced); +void TSAPI UpdateTrayMenuState(CMsgDialog *dat, BOOL bForced); void TSAPI LoadFavoritesAndRecent(); void TSAPI AddContactToFavorites(MCONTACT hContact, const wchar_t *szNickname, const char *szProto, wchar_t *szStatus, WORD wStatus, HICON hIcon, BOOL mode, HMENU hMenu); @@ -82,7 +82,7 @@ TContainerData* TSAPI FindContainerByName(const wchar_t *name); int TSAPI GetTabIndexFromHWND(HWND hwndTab, HWND hwnd); HWND TSAPI GetTabWindow(HWND hwndTab, int idx); int TSAPI GetTabItemFromMouse(HWND hwndTab, POINT *pt); -void TSAPI CloseOtherTabs(HWND hwndTab, CTabBaseDlg &dat); +void TSAPI CloseOtherTabs(HWND hwndTab, CMsgDialog &dat); int TSAPI ActivateTabFromHWND(HWND hwndTab, HWND hwnd); void TSAPI AdjustTabClientRect(TContainerData *pContainer, RECT *rc); void TSAPI ReflashContainer(TContainerData *pContainer); @@ -135,7 +135,7 @@ int _DebugPopup(MCONTACT hContact, const wchar_t *fmt, ...); const wchar_t* TSAPI GetThemeFileName(int iMode); int TSAPI CheckThemeVersion(const wchar_t *szIniFilename); -void TSAPI WriteThemeToINI(const wchar_t *szIniFilename, CSrmmWindow *dat); +void TSAPI WriteThemeToINI(const wchar_t *szIniFilename, CMsgDialog *dat); void TSAPI ReadThemeFromINI(const wchar_t *szIniFilename, TContainerData *dat, int noAdvanced, DWORD dwFlags); // TypingNotify diff --git a/plugins/TabSRMM/src/generic_msghandlers.cpp b/plugins/TabSRMM/src/generic_msghandlers.cpp index c825414a33..7b2f90c0e9 100644 --- a/plugins/TabSRMM/src/generic_msghandlers.cpp +++ b/plugins/TabSRMM/src/generic_msghandlers.cpp @@ -33,7 +33,7 @@ ///////////////////////////////////////////////////////////////////////////////////////// // Save message log for given session as RTF document -void CTabBaseDlg::DM_SaveLogAsRTF() const +void CMsgDialog::DM_SaveLogAsRTF() const { if (m_hwndIEView != nullptr) { IEVIEWEVENT event = { sizeof(event) }; @@ -75,7 +75,7 @@ void CTabBaseDlg::DM_SaveLogAsRTF() const ///////////////////////////////////////////////////////////////////////////////////////// // checks if the balloon tooltip can be dismissed (usually called by WM_MOUSEMOVE events) -void CTabBaseDlg::DM_DismissTip(const POINT& pt) +void CMsgDialog::DM_DismissTip(const POINT& pt) { if (!IsWindowVisible(m_hwndTip)) return; @@ -94,7 +94,7 @@ void CTabBaseDlg::DM_DismissTip(const POINT& pt) ///////////////////////////////////////////////////////////////////////////////////////// // initialize the balloon tooltip for message window notifications -void CTabBaseDlg::DM_InitTip() +void CMsgDialog::DM_InitTip() { m_hwndTip = CreateWindowEx(0, TOOLTIPS_CLASS, nullptr, WS_POPUP | TTS_NOPREFIX | TTS_BALLOON, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, m_hwnd, nullptr, g_plugin.getInst(), (LPVOID)nullptr); @@ -116,7 +116,7 @@ void CTabBaseDlg::DM_InitTip() // // returns 1 for handled hotkeys, 0 otherwise. -bool CTabBaseDlg::DM_GenericHotkeysCheck(MSG *message) +bool CMsgDialog::DM_GenericHotkeysCheck(MSG *message) { LRESULT mim_hotkey_check = Hotkey_Check(message, TABSRMM_HK_SECTION_GENERIC); @@ -166,7 +166,7 @@ bool CTabBaseDlg::DM_GenericHotkeysCheck(MSG *message) return false; } -LRESULT CTabBaseDlg::DM_MsgWindowCmdHandler(UINT cmd, WPARAM wParam, LPARAM lParam) +LRESULT CMsgDialog::DM_MsgWindowCmdHandler(UINT cmd, WPARAM wParam, LPARAM lParam) { RECT rc; int iSelection; @@ -499,14 +499,16 @@ LRESULT CTabBaseDlg::DM_MsgWindowCmdHandler(UINT cmd, WPARAM wParam, LPARAM lPar break; case IDC_SELFTYPING: - if (m_hContact) { - int iCurrentTypingMode = g_plugin.getByte(m_hContact, SRMSGSET_TYPING, g_plugin.getByte(SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW)); + if (m_si == nullptr || m_si->iType == GCW_PRIVMESS) { + if (m_hContact) { + int iCurrentTypingMode = g_plugin.getByte(m_hContact, SRMSGSET_TYPING, g_plugin.getByte(SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW)); - if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON && iCurrentTypingMode) { - DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); - m_nTypeMode = PROTOTYPE_SELFTYPING_OFF; + if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON && iCurrentTypingMode) { + DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); + m_nTypeMode = PROTOTYPE_SELFTYPING_OFF; + } + g_plugin.setByte(m_hContact, SRMSGSET_TYPING, (BYTE)!iCurrentTypingMode); } - g_plugin.setByte(m_hContact, SRMSGSET_TYPING, (BYTE)!iCurrentTypingMode); } break; @@ -520,7 +522,7 @@ LRESULT CTabBaseDlg::DM_MsgWindowCmdHandler(UINT cmd, WPARAM wParam, LPARAM lPar // initialize rich edit control (log and edit control) for both MUC and // standard IM session windows. -void CTabBaseDlg::DM_InitRichEdit() +void CMsgDialog::DM_InitRichEdit() { bool fIsChat = isChat(); @@ -623,7 +625,7 @@ void CTabBaseDlg::DM_InitRichEdit() ///////////////////////////////////////////////////////////////////////////////////////// // set the states of defined database action buttons(only if button is a toggle) -void CTabBaseDlg::DM_SetDBButtonStates() +void CMsgDialog::DM_SetDBButtonStates() { ButtonItem *buttonItem = m_pContainer->m_buttonItems; MCONTACT hFinalContact = 0; @@ -676,7 +678,7 @@ void CTabBaseDlg::DM_SetDBButtonStates() } } -void CTabBaseDlg::DM_ScrollToBottom(WPARAM wParam, LPARAM lParam) +void CMsgDialog::DM_ScrollToBottom(WPARAM wParam, LPARAM lParam) { if (m_dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED) return; @@ -710,7 +712,7 @@ void CTabBaseDlg::DM_ScrollToBottom(WPARAM wParam, LPARAM lParam) InvalidateRect(m_log.GetHwnd(), nullptr, FALSE); } -void CTabBaseDlg::DM_RecalcPictureSize() +void CMsgDialog::DM_RecalcPictureSize() { HBITMAP hbm = ((m_pPanel.isActive()) && m_pContainer->m_avatarMode != 3) ? m_hOwnPic : (m_ace ? m_ace->hbmPic : PluginConfig.g_hbmUnknown); if (hbm) { @@ -722,7 +724,7 @@ void CTabBaseDlg::DM_RecalcPictureSize() else m_pic.cy = m_pic.cx = 60; } -void CTabBaseDlg::DM_UpdateLastMessage() const +void CMsgDialog::DM_UpdateLastMessage() const { if (m_pContainer->m_hwndStatus == nullptr || m_pContainer->m_hwndActive != m_hwnd) return; @@ -759,7 +761,7 @@ void CTabBaseDlg::DM_UpdateLastMessage() const ///////////////////////////////////////////////////////////////////////////////////////// // create embedded contact list control -HWND CTabBaseDlg::DM_CreateClist() +HWND CMsgDialog::DM_CreateClist() { if (!sendLater->isAvail()) { CWarning::show(CWarning::WARN_NO_SENDLATER, MB_OK | MB_ICONINFORMATION); @@ -789,7 +791,7 @@ HWND CTabBaseDlg::DM_CreateClist() return hwndClist; } -LRESULT CTabBaseDlg::DM_MouseWheelHandler(WPARAM wParam, LPARAM lParam) +LRESULT CMsgDialog::DM_MouseWheelHandler(WPARAM wParam, LPARAM lParam) { POINT pt; GetCursorPos(&pt); @@ -848,7 +850,7 @@ LRESULT CTabBaseDlg::DM_MouseWheelHandler(WPARAM wParam, LPARAM lParam) return 1; } -void CTabBaseDlg::DM_FreeTheme() +void CMsgDialog::DM_FreeTheme() { if (m_hTheme) { CloseThemeData(m_hTheme); @@ -864,7 +866,7 @@ void CTabBaseDlg::DM_FreeTheme() } } -void CTabBaseDlg::DM_ThemeChanged() +void CMsgDialog::DM_ThemeChanged() { CSkinItem *item_log = &SkinItems[ID_EXTBKHISTORY]; CSkinItem *item_msg = &SkinItems[ID_EXTBKINPUTAREA]; @@ -888,7 +890,7 @@ void CTabBaseDlg::DM_ThemeChanged() // send out message typing notifications (MTN) when the // user is typing/editing text in the message input area. -void CTabBaseDlg::DM_NotifyTyping(int mode) +void CMsgDialog::DM_NotifyTyping(int mode) { if (!m_hContact) return; @@ -937,7 +939,7 @@ void CTabBaseDlg::DM_NotifyTyping(int mode) CallService(MS_PROTO_SELFISTYPING, hContact, m_nTypeMode); } -void CSrmmWindow::DM_OptionsApplied(WPARAM, LPARAM lParam) +void CMsgDialog::DM_OptionsApplied(WPARAM, LPARAM lParam) { m_szMicroLf[0] = 0; if (!(m_pContainer->m_theme.isPrivate)) { @@ -978,7 +980,7 @@ void CSrmmWindow::DM_OptionsApplied(WPARAM, LPARAM lParam) SendMessage(m_hwnd, DM_UPDATEWINICON, 0, 0); } -void CTabBaseDlg::DM_Typing(bool fForceOff) +void CMsgDialog::DM_Typing(bool fForceOff) { HWND hwndContainer = m_pContainer->m_hwnd; HWND hwndStatus = m_pContainer->m_hwndStatus; @@ -1003,7 +1005,7 @@ void CTabBaseDlg::DM_Typing(bool fForceOff) } SendMessage(m_hwnd, DM_UPDATEWINICON, 0, 0); HandleIconFeedback(this, (HICON)-1); - CTabBaseDlg *dat_active = (CTabBaseDlg*)GetWindowLongPtr(m_pContainer->m_hwndActive, GWLP_USERDATA); + CMsgDialog *dat_active = (CMsgDialog*)GetWindowLongPtr(m_pContainer->m_hwndActive, GWLP_USERDATA); if (dat_active && !dat_active->isChat()) m_pContainer->UpdateTitle(0); else @@ -1059,9 +1061,9 @@ void CTabBaseDlg::DM_Typing(bool fForceOff) // This cares about private / per container / MUC <> IM splitter syncing and everything. // called from IM and MUC windows via DM_SPLITTERGLOBALEVENT -int CTabBaseDlg::DM_SplitterGlobalEvent(WPARAM wParam, LPARAM lParam) +int CMsgDialog::DM_SplitterGlobalEvent(WPARAM wParam, LPARAM lParam) { - CTabBaseDlg *srcDat = PluginConfig.lastSPlitterPos.pSrcDat; + CMsgDialog *srcDat = PluginConfig.lastSPlitterPos.pSrcDat; TContainerData *srcCnt = PluginConfig.lastSPlitterPos.pSrcContainer; bool fCntGlobal = (!m_pContainer->m_pSettings->fPrivate ? true : false); @@ -1118,7 +1120,7 @@ int CTabBaseDlg::DM_SplitterGlobalEvent(WPARAM wParam, LPARAM lParam) return 0; } -void CTabBaseDlg::DM_AddDivider() +void CMsgDialog::DM_AddDivider() { if (!(m_dwFlags & MWF_DIVIDERSET) && PluginConfig.m_bUseDividers) { if (GetWindowTextLength(m_log.GetHwnd()) > 0) @@ -1129,7 +1131,7 @@ void CTabBaseDlg::DM_AddDivider() ///////////////////////////////////////////////////////////////////////////////////////// // incoming event handler -void CTabBaseDlg::DM_EventAdded(WPARAM hContact, LPARAM lParam) +void CMsgDialog::DM_EventAdded(WPARAM hContact, LPARAM lParam) { MEVENT hDbEvent = (MEVENT)lParam; @@ -1251,7 +1253,7 @@ void CTabBaseDlg::DM_EventAdded(WPARAM hContact, LPARAM lParam) m_pWnd->Invalidate(); } -void CTabBaseDlg::DM_HandleAutoSizeRequest(REQRESIZE* rr) +void CMsgDialog::DM_HandleAutoSizeRequest(REQRESIZE* rr) { if (rr == nullptr || GetForegroundWindow() != m_pContainer->m_hwnd) return; @@ -1307,7 +1309,7 @@ static int OnSrmmIconChanged(WPARAM hContact, LPARAM) return 0; } -void CTabBaseDlg::DrawStatusIcons(HDC hDC, const RECT &rc, int gap) +void CMsgDialog::DrawStatusIcons(HDC hDC, const RECT &rc, int gap) { int x = rc.left; int y = (rc.top + rc.bottom - PluginConfig.m_smcxicon) >> 1; @@ -1355,7 +1357,7 @@ void CTabBaseDlg::DrawStatusIcons(HDC hDC, const RECT &rc, int gap) } } -void CTabBaseDlg::CheckStatusIconClick(POINT pt, const RECT &rc, int gap, int code) +void CMsgDialog::CheckStatusIconClick(POINT pt, const RECT &rc, int gap, int code) { if (code == NM_CLICK || code == NM_RCLICK) { POINT ptScreen; @@ -1405,7 +1407,7 @@ void CTabBaseDlg::CheckStatusIconClick(POINT pt, const RECT &rc, int gap, int co } } -void CTabBaseDlg::DM_ErrorDetected(int type, int flag) +void CMsgDialog::DM_ErrorDetected(int type, int flag) { switch (type) { case MSGERROR_CANCEL: diff --git a/plugins/TabSRMM/src/globals.cpp b/plugins/TabSRMM/src/globals.cpp index 60d681e88d..59fb381a43 100644 --- a/plugins/TabSRMM/src/globals.cpp +++ b/plugins/TabSRMM/src/globals.cpp @@ -380,12 +380,12 @@ int CGlobals::DBSettingChanged(WPARAM hContact, LPARAM lParam) } if (hwnd != nullptr) { - CTabBaseDlg *dat = c->getDat(); + CMsgDialog *dat = c->getDat(); if (!strcmp(setting, "MirVer")) PostMessage(hwnd, DM_CLIENTCHANGED, 0, 0); if (dat && !strcmp(setting, "NotOnList") && (cws->value.type == DBVT_DELETED || cws->value.bVal == 0)) - ((CSrmmWindow*)dat)->onClick_CancelAdd(0); + ((CMsgDialog*)dat)->onClick_CancelAdd(0); if (dat && (fChanged || fExtendedStatusChange)) dat->UpdateTitle(); @@ -429,7 +429,7 @@ int CGlobals::MetaContactEvent(WPARAM hContact, LPARAM) if (hContact) { CContactCache *c = CContactCache::getContactCache(hContact); c->updateMeta(); - CTabBaseDlg *pDlg = c->getDat(); + CMsgDialog *pDlg = c->getDat(); if (pDlg) { pDlg->UpdateTitle(); pDlg->GetClientIcon(); @@ -530,7 +530,7 @@ void CGlobals::logStatusChange(WPARAM wParam, const CContactCache *c) if (c == nullptr) return; - CTabBaseDlg *dat = c->getDat(); + CMsgDialog *dat = c->getDat(); if (dat == nullptr || !c->isValid()) return; diff --git a/plugins/TabSRMM/src/globals.h b/plugins/TabSRMM/src/globals.h index bb8f583bd9..ae2e6bdd7b 100644 --- a/plugins/TabSRMM/src/globals.h +++ b/plugins/TabSRMM/src/globals.h @@ -32,7 +32,7 @@ struct TSplitterBroadCast { TContainerData *pSrcContainer; - CTabBaseDlg *pSrcDat; + CMsgDialog *pSrcDat; LONG pos, pos_chat; LONG off_chat, off_im; LPARAM lParam; diff --git a/plugins/TabSRMM/src/hotkeyhandler.cpp b/plugins/TabSRMM/src/hotkeyhandler.cpp index f6e53d3a23..b32cf7abea 100644 --- a/plugins/TabSRMM/src/hotkeyhandler.cpp +++ b/plugins/TabSRMM/src/hotkeyhandler.cpp @@ -183,9 +183,9 @@ LONG_PTR CALLBACK HotkeyHandlerDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LP hWnd = si ? si->pDlg->GetHwnd() : nullptr; } - CSrmmWindow *dat = nullptr; + CMsgDialog *dat = nullptr; if (hWnd) - dat = (CSrmmWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(hWnd, GWLP_USERDATA); { HICON hIcon; diff --git a/plugins/TabSRMM/src/infopanel.cpp b/plugins/TabSRMM/src/infopanel.cpp index 3c3684dc8b..434b097b2a 100644 --- a/plugins/TabSRMM/src/infopanel.cpp +++ b/plugins/TabSRMM/src/infopanel.cpp @@ -42,7 +42,7 @@ TInfoPanelConfig CInfoPanel::m_ipConfig = {}; ///////////////////////////////////////////////////////////////////////////////////////// -CInfoPanel::CInfoPanel(CTabBaseDlg *dat) +CInfoPanel::CInfoPanel(CMsgDialog *dat) { if (dat) { m_dat = dat; @@ -962,7 +962,7 @@ LRESULT CALLBACK CInfoPanel::avatarParentSubclass(HWND hwnd, UINT msg, WPARAM wP case WM_ERASEBKGND: // parent window of the infopanel ACC control RECT rc, rcItem; - CSrmmWindow *dat = (CSrmmWindow*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); if (dat == nullptr) break; diff --git a/plugins/TabSRMM/src/infopanel.h b/plugins/TabSRMM/src/infopanel.h index a4a2a04819..9e925ba511 100644 --- a/plugins/TabSRMM/src/infopanel.h +++ b/plugins/TabSRMM/src/infopanel.h @@ -30,7 +30,7 @@ #define __INFOPANEL_H class CInfoPanel; -class CTabBaseDlg; +class CMsgDialog; struct CSkinItem; /* @@ -129,14 +129,14 @@ public: HTNIRVANA = 0 }; - CInfoPanel(CTabBaseDlg *dat); + CInfoPanel(CMsgDialog *dat); ~CInfoPanel(); __forceinline const LONG getHeight() const { return m_height; } __forceinline bool isActive() const { return m_active; } __forceinline bool isPrivateHeight() const { return m_fPrivateHeight; } __forceinline DWORD isHovered() const { return m_active ? m_hoverFlags : 0; } - __forceinline const CTabBaseDlg* getDat() const { return m_dat; } + __forceinline const CMsgDialog* getDat() const { return m_dat; } void setHeight(LONG newHeight, bool fBroadcast = false); void setActive(const int newActive); @@ -180,7 +180,7 @@ private: bool m_active; // panel active and visible bool m_fPrivateHeight; bool m_fDialogCreated; - CTabBaseDlg *m_dat; // this one OWNS us... + CMsgDialog *m_dat; // this one OWNS us... LONG m_height; // height (determined by position of IDC_PANELSPLITTER) LONG m_defaultHeight, m_defaultMUCHeight; // global values for the info bar height diff --git a/plugins/TabSRMM/src/mim.cpp b/plugins/TabSRMM/src/mim.cpp index 9ce2123785..5b3258ea7d 100644 --- a/plugins/TabSRMM/src/mim.cpp +++ b/plugins/TabSRMM/src/mim.cpp @@ -306,7 +306,7 @@ int CMimAPI::ProtoAck(WPARAM, LPARAM lParam) for (int j = 0; j < SendQueue::NR_SENDJOBS; j++) { SendJob &p = jobs[j]; if (pAck->hProcess == (HANDLE)p.iSendId && pAck->hContact == p.hContact) { - CSrmmWindow *dat = p.hOwnerWnd ? (CSrmmWindow*)GetWindowLongPtr(p.hOwnerWnd, GWLP_USERDATA) : nullptr; + CMsgDialog *dat = p.hOwnerWnd ? (CMsgDialog*)GetWindowLongPtr(p.hOwnerWnd, GWLP_USERDATA) : nullptr; if (dat == nullptr) { sendQueue->ackMessage(nullptr, (WPARAM)MAKELONG(j, i), lParam); return 0; diff --git a/plugins/TabSRMM/src/msgdialog.cpp b/plugins/TabSRMM/src/msgdialog.cpp index 5f57d9b34e..84c7db6689 100644 --- a/plugins/TabSRMM/src/msgdialog.cpp +++ b/plugins/TabSRMM/src/msgdialog.cpp @@ -69,124 +69,11 @@ static void _clrMsgFilter(MSGFILTER *m) } ///////////////////////////////////////////////////////////////////////////////////////// -// show a modified context menu for the richedit control(s) - -void CTabBaseDlg::ShowPopupMenu(const CCtrlBase &pCtrl, POINT pt) -{ - CHARRANGE sel, all = { 0, -1 }; - - HMENU hSubMenu, hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_CONTEXT)); - if (pCtrl.GetCtrlId() == IDC_SRMM_LOG) - hSubMenu = GetSubMenu(hMenu, 0); - else { - hSubMenu = GetSubMenu(hMenu, 2); - EnableMenuItem(hSubMenu, IDM_PASTEFORMATTED, MF_BYCOMMAND | (m_SendFormat != 0 ? MF_ENABLED : MF_GRAYED)); - EnableMenuItem(hSubMenu, ID_EDITOR_PASTEANDSENDIMMEDIATELY, MF_BYCOMMAND | (PluginConfig.m_PasteAndSend ? MF_ENABLED : MF_GRAYED)); - CheckMenuItem(hSubMenu, ID_EDITOR_SHOWMESSAGELENGTHINDICATOR, MF_BYCOMMAND | (PluginConfig.m_visualMessageSizeIndicator ? MF_CHECKED : MF_UNCHECKED)); - EnableMenuItem(hSubMenu, ID_EDITOR_SHOWMESSAGELENGTHINDICATOR, MF_BYCOMMAND | (m_pContainer->m_hwndStatus ? MF_ENABLED : MF_GRAYED)); - } - TranslateMenu(hSubMenu); - pCtrl.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel); - if (sel.cpMin == sel.cpMax) { - EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(hSubMenu, IDM_QUOTE, MF_BYCOMMAND | MF_GRAYED); - if (pCtrl.GetCtrlId() == IDC_SRMM_MESSAGE) - EnableMenuItem(hSubMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED); - } - - if (pCtrl.GetCtrlId() == IDC_SRMM_LOG) { - InsertMenuA(hSubMenu, 6, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); - CheckMenuItem(hSubMenu, ID_LOG_FREEZELOG, MF_BYCOMMAND | (m_dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED ? MF_CHECKED : MF_UNCHECKED)); - } - - MessageWindowPopupData mwpd; - // First notification - mwpd.uType = MSG_WINDOWPOPUP_SHOWING; - mwpd.uFlags = (pCtrl.GetCtrlId() == IDC_SRMM_LOG ? MSG_WINDOWPOPUP_LOG : MSG_WINDOWPOPUP_INPUT); - mwpd.hContact = m_hContact; - mwpd.hwnd = pCtrl.GetHwnd(); - mwpd.hMenu = hSubMenu; - mwpd.selection = 0; - mwpd.pt = pt; - NotifyEventHooks(g_chatApi.hevWinPopup, 0, (LPARAM)&mwpd); - - int iSelection = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, m_hwnd, nullptr); - - // Second notification - mwpd.selection = iSelection; - mwpd.uType = MSG_WINDOWPOPUP_SELECTED; - NotifyEventHooks(g_chatApi.hevWinPopup, 0, (LPARAM)&mwpd); - - switch (iSelection) { - case IDM_COPY: - pCtrl.SendMsg(WM_COPY, 0, 0); - break; - case IDM_CUT: - pCtrl.SendMsg(WM_CUT, 0, 0); - break; - case IDM_PASTE: - case IDM_PASTEFORMATTED: - if (pCtrl.GetCtrlId() == IDC_SRMM_MESSAGE) - pCtrl.SendMsg(EM_PASTESPECIAL, (iSelection == IDM_PASTE) ? CF_UNICODETEXT : 0, 0); - break; - case IDM_COPYALL: - pCtrl.SendMsg(EM_EXSETSEL, 0, (LPARAM)&all); - pCtrl.SendMsg(WM_COPY, 0, 0); - pCtrl.SendMsg(EM_EXSETSEL, 0, (LPARAM)&sel); - break; - case IDM_QUOTE: - SendMessage(m_hwnd, WM_COMMAND, IDC_QUOTE, 0); - break; - case IDM_SELECTALL: - pCtrl.SendMsg(EM_EXSETSEL, 0, (LPARAM)&all); - break; - case IDM_CLEAR: - tabClearLog(); - break; - case ID_LOG_FREEZELOG: - SendDlgItemMessage(m_hwnd, IDC_SRMM_LOG, WM_KEYDOWN, VK_F12, 0); - break; - case ID_EDITOR_SHOWMESSAGELENGTHINDICATOR: - PluginConfig.m_visualMessageSizeIndicator = !PluginConfig.m_visualMessageSizeIndicator; - db_set_b(0, SRMSGMOD_T, "msgsizebar", (BYTE)PluginConfig.m_visualMessageSizeIndicator); - Srmm_Broadcast(DM_CONFIGURETOOLBAR, 0, 0); - Resize(); - if (m_pContainer->m_hwndStatus) - RedrawWindow(m_pContainer->m_hwndStatus, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW); - break; - case ID_EDITOR_PASTEANDSENDIMMEDIATELY: - HandlePasteAndSend(); - break; - } - - if (pCtrl.GetCtrlId() == IDC_SRMM_LOG) - RemoveMenu(hSubMenu, 7, MF_BYPOSITION); - DestroyMenu(hMenu); -} - -void CTabBaseDlg::ResizeIeView() -{ - RECT rcRichEdit; - GetWindowRect(m_log.GetHwnd(), &rcRichEdit); - - POINT pt = { rcRichEdit.left, rcRichEdit.top }; - ScreenToClient(m_hwnd, &pt); - - IEVIEWWINDOW ieWindow = { sizeof(ieWindow) }; - ieWindow.iType = IEW_SETPOS; - ieWindow.parent = m_hwnd; - ieWindow.hwnd = m_hwndIEView ? m_hwndIEView : m_hwndHPP; - 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(m_hwndIEView ? MS_IEVIEW_WINDOW : MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow); -} +// sublassing procedure for the h++ based message log viewer LRESULT CALLBACK IEViewSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - CSrmmWindow *mwdat = (CSrmmWindow*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); + CMsgDialog *mwdat = (CMsgDialog*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); switch (msg) { case WM_NCCALCSIZE: @@ -197,12 +84,9 @@ LRESULT CALLBACK IEViewSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM l return mir_callNextSubclass(hwnd, IEViewSubclassProc, msg, wParam, lParam); } -///////////////////////////////////////////////////////////////////////////////////////// -// sublassing procedure for the h++ based message log viewer - LRESULT CALLBACK HPPKFSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - CSrmmWindow *mwdat = (CSrmmWindow*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); + CMsgDialog *mwdat = (CMsgDialog*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); if (mwdat) { bool isCtrl, isShift, isAlt; mwdat->KbdState(isShift, isCtrl, isAlt); @@ -230,134 +114,13 @@ LRESULT CALLBACK HPPKFSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP return mir_callNextSubclass(hwnd, HPPKFSubclassProc, msg, wParam, lParam); } -///////////////////////////////////////////////////////////////////////////////////////// -// update state of the container - this is called whenever a tab becomes active, no matter how and -// deals with various things like updating the title bar, removing flashing icons, updating the -// session list, switching the keyboard layout (autolocale active) and the general container status. -// -// it protects itself from being called more than once per session activation and is valid for -// normal IM sessions *only*. Group chat sessions have their own activation handler (see chat/window.c) - -void CSrmmWindow::MsgWindowUpdateState(UINT msg) -{ - if (m_iTabID < 0) - return; - - if (msg == WM_ACTIVATE) { - if (m_pContainer->m_dwFlags & CNT_TRANSPARENCY) { - DWORD trans = LOWORD(m_pContainer->m_pSettings->dwTransparency); - SetLayeredWindowAttributes(m_pContainer->m_hwnd, 0, (BYTE)trans, (m_pContainer->m_dwFlags & CNT_TRANSPARENCY ? LWA_ALPHA : 0)); - } - } - - if (m_bIsAutosizingInput && m_iInputAreaHeight == -1) { - m_iInputAreaHeight = 0; - m_message.SendMsg(EM_REQUESTRESIZE, 0, 0); - } - - if (m_pWnd) - m_pWnd->activateTab(); - m_pPanel.dismissConfig(); - m_dwUnread = 0; - if (m_pContainer->m_hwndSaved == m_hwnd) - return; - - m_pContainer->m_hwndSaved = m_hwnd; - - m_dwTickLastEvent = 0; - m_dwFlags &= ~MWF_DIVIDERSET; - if (KillTimer(m_hwnd, TIMERID_FLASHWND)) { - FlashTab(false); - m_bCanFlashTab = false; - } - if (m_pContainer->m_dwFlashingStarted != 0) { - FlashContainer(m_pContainer, 0, 0); - m_pContainer->m_dwFlashingStarted = 0; - } - if (m_dwFlagsEx & MWF_SHOW_FLASHCLIST) { - m_dwFlagsEx &= ~MWF_SHOW_FLASHCLIST; - if (m_hFlashingEvent != 0) - g_clistApi.pfnRemoveEvent(m_hContact, m_hFlashingEvent); - m_hFlashingEvent = 0; - } - m_pContainer->m_dwFlags &= ~CNT_NEED_UPDATETITLE; - - if ((m_dwFlags & MWF_DEFERREDREMAKELOG) && !IsIconic(m_pContainer->m_hwnd)) { - SendMessage(m_hwnd, DM_REMAKELOG, 0, 0); - m_dwFlags &= ~MWF_DEFERREDREMAKELOG; - } - - if (m_dwFlags & MWF_NEEDCHECKSIZE) - PostMessage(m_hwnd, DM_SAVESIZE, 0, 0); - - m_pContainer->m_hIconTaskbarOverlay = nullptr; - m_pContainer->UpdateTitle(m_hContact); - - tabUpdateStatusBar(); - m_dwLastActivity = GetTickCount(); - m_pContainer->m_dwLastActivity = m_dwLastActivity; - - m_pContainer->m_pMenuBar->configureMenu(); - UpdateTrayMenuState(this, FALSE); - - if (m_pContainer->m_hwndActive == m_hwnd) - DeletePopupsForContact(m_hContact, PU_REMOVE_ON_FOCUS); - - m_pPanel.Invalidate(); - - if (m_dwFlags & MWF_DEFERREDSCROLL && m_hwndIEView == nullptr && m_hwndHPP == nullptr) { - m_dwFlags &= ~MWF_DEFERREDSCROLL; - DM_ScrollToBottom(0, 1); - } - - DM_SetDBButtonStates(); - - if (m_hwndIEView) { - RECT rcRTF; - POINT pt; - - GetWindowRect(m_log.GetHwnd(), &rcRTF); - rcRTF.left += 20; - rcRTF.top += 20; - pt.x = rcRTF.left; - pt.y = rcRTF.top; - if (m_hwndIEView) { - if (M.GetByte("subclassIEView", 0)) { - mir_subclassWindow(m_hwndIEView, IEViewSubclassProc); - SetWindowPos(m_hwndIEView, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_DRAWFRAME); - RedrawWindow(m_hwndIEView, nullptr, nullptr, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW); - } - } - m_hwndIWebBrowserControl = WindowFromPoint(pt); - } - - if (m_dwFlagsEx & MWF_EX_DELAYEDSPLITTER) { - m_dwFlagsEx &= ~MWF_EX_DELAYEDSPLITTER; - ShowWindow(m_pContainer->m_hwnd, SW_RESTORE); - PostMessage(m_hwnd, DM_SPLITTERGLOBALEVENT, m_wParam, m_lParam); - m_wParam = m_lParam = 0; - } - if (m_dwFlagsEx & MWF_EX_AVATARCHANGED) { - m_dwFlagsEx &= ~MWF_EX_AVATARCHANGED; - PostMessage(m_hwnd, DM_UPDATEPICLAYOUT, 0, 0); - } - BB_SetButtonsPos(); - if (M.isAero()) - InvalidateRect(m_hwndParent, nullptr, FALSE); - if (m_pContainer->m_dwFlags & CNT_SIDEBAR) - m_pContainer->m_pSideBar->setActiveItem(this); - - if (m_pWnd) - m_pWnd->Invalidate(); -} - static void ShowMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state) { for (int i = 0; i < cControls; i++) Utils::showDlgControl(hwndDlg, controls[i], state); } -void CTabBaseDlg::SetDialogToType() +void CMsgDialog::SetDialogToType() { if (m_hContact) { if (db_get_b(m_hContact, "CList", "NotOnList", 0)) { @@ -432,7 +195,7 @@ LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM { RECT rc; HWND hwndParent = GetParent(hwnd); - CTabBaseDlg *dat = (CTabBaseDlg*)GetWindowLongPtr(hwndParent, GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr(hwndParent, GWLP_USERDATA); switch (msg) { case WM_NCHITTEST: @@ -562,56 +325,99 @@ LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM ///////////////////////////////////////////////////////////////////////////////////////// -CSrmmWindow::CSrmmWindow() - : CSuper(IDD_MSGSPLITNEW), +CMsgDialog::CMsgDialog(int iDlgId, SESSION_INFO *si) : + CSuper(g_plugin, iDlgId, si), + m_pPanel(this), + m_dwFlags(MWF_INITMODE), m_btnOk(this, IDOK), m_btnAdd(this, IDC_ADD), m_btnQuote(this, IDC_QUOTE), m_btnCancelAdd(this, IDC_CANCELADD) { - m_btnOk.OnClick = Callback(this, &CSrmmWindow::onClick_Ok); - m_btnAdd.OnClick = Callback(this, &CSrmmWindow::onClick_Add); - m_btnQuote.OnClick = Callback(this, &CSrmmWindow::onClick_Quote); - m_btnCancelAdd.OnClick = Callback(this, &CSrmmWindow::onClick_CancelAdd); + m_autoClose = CLOSE_ON_CANCEL; + m_forceResizable = true; - m_message.OnChange = Callback(this, &CSrmmWindow::onChange_Message); -} + m_szProto = GetContactProto(m_hContact); + m_bFilterEnabled = db_get_b(m_hContact, CHAT_MODULE, "FilterEnabled", m_bFilterEnabled) != 0; -void CSrmmWindow::tabClearLog() -{ - if (m_hwndIEView || m_hwndHPP) { - IEVIEWEVENT event; - event.cbSize = sizeof(IEVIEWEVENT); - event.iType = IEE_CLEAR_LOG; - event.dwFlags = (m_dwFlags & MWF_LOG_RTL) ? IEEF_RTL : 0; - event.hContact = m_hContact; - if (m_hwndIEView) { - event.hwnd = m_hwndIEView; - CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&event); - } - else { - event.hwnd = m_hwndHPP; - CallService(MS_HPP_EG_EVENT, 0, (LPARAM)&event); - } - } - m_log.SetText(L""); - m_hDbEventFirst = 0; + m_btnOk.OnClick = Callback(this, &CMsgDialog::onClick_Ok); + m_btnAdd.OnClick = Callback(this, &CMsgDialog::onClick_Add); + m_btnQuote.OnClick = Callback(this, &CMsgDialog::onClick_Quote); + m_btnFilter.OnClick = Callback(this, &CMsgDialog::onClick_Filter); + m_btnNickList.OnClick = Callback(this, &CMsgDialog::onClick_ShowNickList); + m_btnCancelAdd.OnClick = Callback(this, &CMsgDialog::onClick_CancelAdd); + + m_nickList.OnDblClick = Callback(this, &CMsgDialog::onDblClick_List); + + m_message.OnChange = Callback(this, &CMsgDialog::onChange_Message); } -CThumbBase* CSrmmWindow::tabCreateThumb(CProxyWindow *pProxy) const +CMsgDialog::~CMsgDialog() { - return new CThumbIM(pProxy); + delete m_pWnd; + + mir_free(m_sendBuffer); + mir_free(m_hHistoryEvents); + mir_free(m_hQueuedEvents); + + if (m_hClientIcon) DestroyIcon(m_hClientIcon); + if (m_hSmileyIcon) DestroyIcon(m_hSmileyIcon); + if (m_hXStatusIcon) DestroyIcon(m_hXStatusIcon); + if (m_hTaskbarIcon) DestroyIcon(m_hTaskbarIcon); } -bool CSrmmWindow::OnInitDialog() +bool CMsgDialog::OnInitDialog() { CSuper::OnInitDialog(); + // m_hwnd is valid, pass it to the tab control + TCITEM tci; + tci.mask = TCIF_PARAM; + tci.lParam = (LPARAM)m_hwnd; + TabCtrl_SetItem(m_hwndParent, m_iTabID, &tci); + + // update another tab ids + m_pContainer->UpdateTabs(); + + // add this window to window list & proxy + if (IsWinVer7Plus() && PluginConfig.m_useAeroPeek) + m_pWnd = new CProxyWindow(this); + else + m_pWnd = nullptr; + + // set up Windows themes + DM_ThemeChanged(); + + // refresh cache data for this contact + m_cache = CContactCache::getContactCache(m_hContact); + m_cache->updateNick(); + m_cache->updateUIN(); + m_cache->setWindowData(this); + + m_bIsAutosizingInput = IsAutoSplitEnabled(); m_szProto = const_cast(m_cache->getProto()); m_bIsMeta = m_cache->isMeta(); if (m_bIsMeta) m_cache->updateMeta(); + if (m_si) { + m_si->pDlg = this; + Chat_SetFilters(m_si); + + m_pPanel.getVisibility(); + m_pPanel.Configure(); + + for (auto &it : btnControls) + ShowWindow(GetDlgItem(m_hwnd,it), SW_HIDE); + } + else { + ShowWindow(GetDlgItem(m_hwnd, IDC_SPLITTERX), SW_HIDE); + m_nickList.Hide(); + + for (auto &it : btnControls) + CustomizeButton(GetDlgItem(m_hwnd, it)); + } + // show a popup if wanted... if (m_bWantPopup) { DBEVENTINFO dbei = {}; @@ -627,14 +433,17 @@ bool CSrmmWindow::OnInitDialog() } else m_wStatus = ID_STATUS_OFFLINE; - for (auto &it : btnControls) - CustomizeButton(GetDlgItem(m_hwnd, it)); - GetMYUIN(); GetClientIcon(); - CustomizeButton(CreateWindowEx(0, L"MButtonClass", L"", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 0, 6, DPISCALEY_S(20), - m_hwnd, (HMENU)IDC_TOGGLESIDEBAR, g_plugin.getInst(), nullptr)); + HWND hwndBtn = CreateWindowEx(0, L"MButtonClass", L"", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 0, 6, DPISCALEY_S(20), m_hwnd, (HMENU)IDC_TOGGLESIDEBAR, g_plugin.getInst(), nullptr); + CustomizeButton(hwndBtn); + SendMessage(hwndBtn, BUTTONSETASTHEMEDBTN, 1, 0); + SendMessage(hwndBtn, BUTTONSETCONTAINER, (LPARAM)m_pContainer, 0); + SendMessage(hwndBtn, BUTTONSETASFLATBTN, FALSE, 0); + SendMessage(hwndBtn, BUTTONSETASTOOLBARBUTTON, TRUE, 0); + SendMessage(hwndBtn, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Expand or collapse the side bar"), BATF_UNICODE); + m_hwndPanelPicParent = CreateWindowEx(WS_EX_TOPMOST, L"Static", L"", SS_OWNERDRAW | WS_VISIBLE | WS_CHILD, 1, 1, 1, 1, m_hwnd, (HMENU)6000, nullptr, nullptr); mir_subclassWindow(m_hwndPanelPicParent, CInfoPanel::avatarParentSubclass); @@ -661,8 +470,10 @@ bool CSrmmWindow::OnInitDialog() GetMyNick(); m_iMultiSplit = g_plugin.getDword("multisplit", 150); - m_nTypeMode = PROTOTYPE_SELFTYPING_OFF; - SetTimer(m_hwnd, TIMERID_TYPE, 1000, nullptr); + if (m_si == nullptr || m_si->iType == GCW_PRIVMESS) { + m_nTypeMode = PROTOTYPE_SELFTYPING_OFF; + SetTimer(m_hwnd, TIMERID_TYPE, 1000, nullptr); + } m_iLastEventType = 0xffffffff; // load log option flags... @@ -734,68 +545,81 @@ bool CSrmmWindow::OnInitDialog() SetDlgItemText(m_hwnd, IDC_CANCELSEND, TranslateT("Cancel")); SetDlgItemText(m_hwnd, IDC_MSGSENDLATER, TranslateT("Send later")); + m_log.SendMsg(EM_AUTOURLDETECT, TRUE, 0); + m_log.SendMsg(EM_EXLIMITTEXT, 0, 0x7FFFFFFF); m_log.SendMsg(EM_SETUNDOLIMIT, 0, 0); + m_log.SendMsg(EM_HIDESELECTION, TRUE, 0); m_log.SendMsg(EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_KEYEVENTS | ENM_LINK); + m_log.SendMsg(EM_SETEDITSTYLE, SES_EXTENDBACKCOLOR, SES_EXTENDBACKCOLOR); + m_log.SendMsg(EM_SETLANGOPTIONS, 0, m_log.SendMsg(EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOFONTSIZEADJUST); + m_log.SendMsg(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3)); m_message.SendMsg(EM_SETEVENTMASK, 0, ENM_REQUESTRESIZE | ENM_MOUSEEVENTS | ENM_SCROLL | ENM_KEYEVENTS | ENM_CHANGE); + m_message.SendMsg(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3)); m_message.SetReadOnly(false); m_bActualHistory = M.GetByte(m_hContact, "ActualHistory", 0) != 0; - /* OnO: higligh lines to their end */ - m_log.SendMsg(EM_SETEDITSTYLE, SES_EXTENDBACKCOLOR, SES_EXTENDBACKCOLOR); - - m_log.SendMsg(EM_SETLANGOPTIONS, 0, m_log.SendMsg(EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOFONTSIZEADJUST); - // add us to the tray list (if it exists) UpdateTrayMenu(nullptr, m_wStatus, m_szProto, m_wszStatus, m_hContact, 0); - m_log.SendMsg(EM_AUTOURLDETECT, TRUE, 0); - m_log.SendMsg(EM_EXLIMITTEXT, 0, 0x80000000); - // subclassing stuff mir_subclassWindow(GetDlgItem(m_hwnd, IDC_CONTACTPIC), AvatarSubclassProc); + mir_subclassWindow(GetDlgItem(m_hwnd, IDC_SPLITTERX), SplitterSubclassProc); mir_subclassWindow(GetDlgItem(m_hwnd, IDC_SPLITTERY), SplitterSubclassProc); mir_subclassWindow(GetDlgItem(m_hwnd, IDC_MULTISPLITTER), SplitterSubclassProc); mir_subclassWindow(GetDlgItem(m_hwnd, IDC_PANELSPLITTER), SplitterSubclassProc); // load old messages from history (if wanted...) + m_cache->updateStats(TSessionStats::INIT_TIMER); - if (m_hContact) { - FindFirstEvent(); - m_nMax = (int)m_cache->getMaxMessageLength(); - } + LoadContactAvatar(); - DM_OptionsApplied(0, 0); LoadOwnAvatar(); - // restore saved msg if any... - if (m_hContact) { - ptrW tszSavedMsg(g_plugin.getWStringA(m_hContact, "SavedMsg")); - if (tszSavedMsg != 0) { - SETTEXTEX stx = { ST_DEFAULT, 1200 }; - m_message.SendMsg(EM_SETTEXTEX, (WPARAM)&stx, tszSavedMsg); - UpdateSaveAndSendButton(); - if (m_pContainer->m_hwndActive == m_hwnd) - UpdateReadChars(); - } - } - if (wszInitialText) { - m_message.SetText(wszInitialText); - int len = GetWindowTextLength(m_message.GetHwnd()); - PostMessage(m_message.GetHwnd(), EM_SETSEL, len, len); - if (len) - EnableSendButton(true); - mir_free(wszInitialText); + if (isChat()) { + UpdateOptions(); + UpdateStatusBar(); + UpdateTitle(); + m_hTabIcon = m_hTabStatusIcon; + + UpdateNickList(); } + else { + if (m_hContact) { + FindFirstEvent(); + m_nMax = (int)m_cache->getMaxMessageLength(); + } + DM_OptionsApplied(0, 0); - for (MEVENT hdbEvent = db_event_last(m_hContact); hdbEvent; hdbEvent = db_event_prev(m_hContact, hdbEvent)) { - DBEVENTINFO dbei = {}; - db_event_get(hdbEvent, &dbei); - if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) { - m_lastMessage = dbei.timestamp; - DM_UpdateLastMessage(); - break; + // restore saved msg if any... + if (m_hContact) { + ptrW tszSavedMsg(g_plugin.getWStringA(m_hContact, "SavedMsg")); + if (tszSavedMsg != 0) { + SETTEXTEX stx = { ST_DEFAULT, 1200 }; + m_message.SendMsg(EM_SETTEXTEX, (WPARAM)& stx, tszSavedMsg); + UpdateSaveAndSendButton(); + if (m_pContainer->m_hwndActive == m_hwnd) + UpdateReadChars(); + } + } + if (wszInitialText) { + m_message.SetText(wszInitialText); + int len = GetWindowTextLength(m_message.GetHwnd()); + PostMessage(m_message.GetHwnd(), EM_SETSEL, len, len); + if (len) + EnableSendButton(true); + mir_free(wszInitialText); + } + + for (MEVENT hdbEvent = db_event_last(m_hContact); hdbEvent; hdbEvent = db_event_prev(m_hContact, hdbEvent)) { + DBEVENTINFO dbei = {}; + db_event_get(hdbEvent, &dbei); + if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) { + m_lastMessage = dbei.timestamp; + DM_UpdateLastMessage(); + break; + } } } @@ -819,7 +643,11 @@ bool CSrmmWindow::OnInitDialog() m_dwFlags |= MWF_NEEDCHECKSIZE | MWF_WASBACKGROUNDCREATE | MWF_DEFERREDSCROLL; } - if (m_bActivate) { + if (isChat()) { + m_pContainer->m_hwndActive = m_hwnd; + ShowWindow(m_hwnd, SW_SHOW); + } + else if (m_bActivate) { m_pContainer->m_hwndActive = m_hwnd; ShowWindow(m_hwnd, SW_SHOW); SetActiveWindow(m_hwnd); @@ -850,8 +678,11 @@ bool CSrmmWindow::OnInitDialog() return true; } -void CSrmmWindow::OnDestroy() +void CMsgDialog::OnDestroy() { + NotifyEvent(MSG_WINDOW_EVT_CLOSING); + + m_cache->setWindowData(); m_pContainer->ClearMargins(); PostMessage(m_pContainer->m_hwnd, WM_SIZE, 0, 1); if (m_pContainer->m_dwFlags & CNT_SIDEBAR) @@ -870,8 +701,15 @@ void CSrmmWindow::OnDestroy() if (m_hwndPanelPicParent) DestroyWindow(m_hwndPanelPicParent); + if (m_si) { + if (g_clistApi.pfnGetEvent(m_si->hContact, 0)) + g_clistApi.pfnRemoveEvent(m_si->hContact, GC_FAKE_EVENT); + m_si->wState &= ~STATE_TALK; + m_si->pDlg = nullptr; + m_si = nullptr; + } + if (m_cache->isValid()) { // not valid means the contact was deleted - NotifyEvent(MSG_WINDOW_EVT_CLOSING); AddContactToFavorites(m_hContact, m_cache->getNick(), m_cache->getActiveProto(), m_wszStatus, m_wStatus, Skin_LoadProtoIcon(m_cache->getActiveProto(), m_cache->getActiveStatus()), 1, PluginConfig.g_hMenuRecent); if (m_hContact) { @@ -887,8 +725,9 @@ void CSrmmWindow::OnDestroy() } } - if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) - DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); + if (m_si == nullptr || m_si->iType == GCW_PRIVMESS) + if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) + DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); DM_FreeTheme(); @@ -911,6 +750,11 @@ void CSrmmWindow::OnDestroy() } } + if (m_pWnd) { + delete m_pWnd; + m_pWnd = nullptr; + } + if (m_hwndTip) DestroyWindow(m_hwndTip); @@ -950,7 +794,7 @@ void CSrmmWindow::OnDestroy() CSuper::OnDestroy(); } -void CSrmmWindow::ReplayQueue() +void CMsgDialog::ReplayQueue() { for (int i = 0; i < m_iNextQueuedEvent; i++) if (m_hQueuedEvents[i] != 0) @@ -961,107 +805,168 @@ void CSrmmWindow::ReplayQueue() TranslateT("Auto scrolling is disabled (press F12 to enable it)")); } -void CSrmmWindow::UpdateTitle() +void CMsgDialog::UpdateTitle() { - DWORD dwOldIdle = m_idle; - const char *szActProto = nullptr; + if (isChat()) { + m_wStatus = m_si->wStatus; - m_wszStatus[0] = 0; + const wchar_t *szNick = m_cache->getNick(); + if (mir_wstrlen(szNick) > 0) { + if (M.GetByte("cuttitle", 0)) + CutContactName(szNick, m_wszTitle, _countof(m_wszTitle)); + else + wcsncpy_s(m_wszTitle, szNick, _TRUNCATE); + } - if (m_iTabID == -1) - return; + CMStringW wszTitle; + HICON hIcon = nullptr; + int nUsers = m_si->getUserList().getCount(); - TCITEM item = {}; + switch (m_si->iType) { + case GCW_CHATROOM: + hIcon = Skin_LoadProtoIcon(m_si->pszModule, (m_wStatus <= ID_STATUS_OFFLINE) ? ID_STATUS_OFFLINE : m_wStatus); + wszTitle.Format((nUsers == 1) ? TranslateT("%s: chat room (%u user%s)") : TranslateT("%s: chat room (%u users%s)"), + szNick, nUsers, m_bFilterEnabled ? TranslateT(", event filter active") : L""); + break; - bool bChanged = false; - wchar_t newtitle[128]; - if (m_hContact) { - if (m_szProto) { - szActProto = m_cache->getProto(); + case GCW_PRIVMESS: + hIcon = Skin_LoadProtoIcon(m_si->pszModule, (m_wStatus <= ID_STATUS_OFFLINE) ? ID_STATUS_OFFLINE : m_wStatus); + if (nUsers == 1) + wszTitle.Format(TranslateT("%s: message session"), szNick); + else + wszTitle.Format(TranslateT("%s: message session (%u users)"), szNick, nUsers); + break; - bool bHasName = (m_cache->getUIN()[0] != 0); - m_idle = m_cache->getIdleTS(); - m_dwFlagsEx = m_idle ? m_dwFlagsEx | MWF_SHOW_ISIDLE : m_dwFlagsEx & ~MWF_SHOW_ISIDLE; + case GCW_SERVER: + wszTitle.Format(L"%s: Server", szNick); + hIcon = LoadIconEx("window"); + break; - m_wStatus = m_cache->getStatus(); - wcsncpy_s(m_wszStatus, Clist_GetStatusModeDescription(m_szProto == nullptr ? ID_STATUS_OFFLINE : m_wStatus, 0), _TRUNCATE); + default: + return; + } - wchar_t newcontactname[128]; newcontactname[0] = 0; - if (PluginConfig.m_bCutContactNameOnTabs) - CutContactName(m_cache->getNick(), newcontactname, _countof(newcontactname)); - else - wcsncpy_s(newcontactname, m_cache->getNick(), _TRUNCATE); + if (m_pWnd) { + m_pWnd->updateTitle(m_wszTitle); + m_pWnd->updateIcon(hIcon); + } + m_hTabStatusIcon = hIcon; + + if (m_cache->getStatus() != m_cache->getOldStatus()) { + wcsncpy_s(m_wszStatus, Clist_GetStatusModeDescription(m_wStatus, 0), _TRUNCATE); + + TCITEM item = {}; + item.mask = TCIF_TEXT; + item.pszText = m_wszTitle; + TabCtrl_SetItem(m_hwndParent, m_iTabID, &item); + } + SetWindowText(m_hwnd, wszTitle); + if (m_pContainer->m_hwndActive == m_hwnd) { + m_pContainer->UpdateTitle(0, this); + UpdateStatusBar(); + } + } + else { + DWORD dwOldIdle = m_idle; + const char *szActProto = nullptr; - Utils::DoubleAmpersands(newcontactname, _countof(newcontactname)); + m_wszStatus[0] = 0; - if (newcontactname[0] != 0) { - if (PluginConfig.m_bStatusOnTabs) - mir_snwprintf(newtitle, L"%s (%s)", newcontactname, m_wszStatus); + if (m_iTabID == -1) + return; + + TCITEM item = {}; + + bool bChanged = false; + wchar_t newtitle[128]; + if (m_hContact) { + if (m_szProto) { + szActProto = m_cache->getProto(); + + bool bHasName = (m_cache->getUIN()[0] != 0); + m_idle = m_cache->getIdleTS(); + m_dwFlagsEx = m_idle ? m_dwFlagsEx | MWF_SHOW_ISIDLE : m_dwFlagsEx & ~MWF_SHOW_ISIDLE; + + m_wStatus = m_cache->getStatus(); + wcsncpy_s(m_wszStatus, Clist_GetStatusModeDescription(m_szProto == nullptr ? ID_STATUS_OFFLINE : m_wStatus, 0), _TRUNCATE); + + wchar_t newcontactname[128]; newcontactname[0] = 0; + if (PluginConfig.m_bCutContactNameOnTabs) + CutContactName(m_cache->getNick(), newcontactname, _countof(newcontactname)); else - wcsncpy_s(newtitle, newcontactname, _TRUNCATE); - } - else wcsncpy_s(newtitle, L"Forward", _TRUNCATE); + wcsncpy_s(newcontactname, m_cache->getNick(), _TRUNCATE); + + Utils::DoubleAmpersands(newcontactname, _countof(newcontactname)); + + if (newcontactname[0] != 0) { + if (PluginConfig.m_bStatusOnTabs) + mir_snwprintf(newtitle, L"%s (%s)", newcontactname, m_wszStatus); + else + wcsncpy_s(newtitle, newcontactname, _TRUNCATE); + } + else wcsncpy_s(newtitle, L"Forward", _TRUNCATE); - if (mir_wstrcmp(newtitle, m_wszTitle)) - bChanged = true; - else if (m_wStatus != m_wOldStatus) - bChanged = true; + if (mir_wstrcmp(newtitle, m_wszTitle)) + bChanged = true; + else if (m_wStatus != m_wOldStatus) + bChanged = true; - SendMessage(m_hwnd, DM_UPDATEWINICON, 0, 0); + SendMessage(m_hwnd, DM_UPDATEWINICON, 0, 0); - wchar_t fulluin[256]; - if (m_bIsMeta) - mir_snwprintf(fulluin, + wchar_t fulluin[256]; + if (m_bIsMeta) + mir_snwprintf(fulluin, TranslateT("UID: %s (Shift+click -> copy to clipboard)\nClick for user's details\nRight click for metacontact control\nClick dropdown to add or remove user from your favorites."), bHasName ? m_cache->getUIN() : TranslateT("No UID")); - else - mir_snwprintf(fulluin, + else + mir_snwprintf(fulluin, TranslateT("UID: %s (Shift+click -> copy to clipboard)\nClick for user's details\nClick dropdown to change this contact's favorite status."), bHasName ? m_cache->getUIN() : TranslateT("No UID")); - SendDlgItemMessage(m_hwnd, IDC_NAME, BUTTONADDTOOLTIP, (WPARAM)fulluin, BATF_UNICODE); + SendDlgItemMessage(m_hwnd, IDC_NAME, BUTTONADDTOOLTIP, (WPARAM)fulluin, BATF_UNICODE); + } } - } - else wcsncpy_s(newtitle, L"Message Session", _TRUNCATE); + else wcsncpy_s(newtitle, L"Message Session", _TRUNCATE); - m_wOldStatus = m_wStatus; - if (m_idle != dwOldIdle || bChanged) { - if (bChanged) { - item.mask |= TCIF_TEXT; - item.pszText = m_wszTitle; - wcsncpy_s(m_wszTitle, newtitle, _TRUNCATE); - if (m_pWnd) - m_pWnd->updateTitle(m_cache->getNick()); - } - if (m_iTabID >= 0) { - TabCtrl_SetItem(m_hwndParent, m_iTabID, &item); - if (m_pContainer->m_dwFlags & CNT_SIDEBAR) - m_pContainer->m_pSideBar->updateSession(this); - } - if (m_pContainer->m_hwndActive == m_hwnd && bChanged) - m_pContainer->UpdateTitle(m_hContact); + m_wOldStatus = m_wStatus; + if (m_idle != dwOldIdle || bChanged) { + if (bChanged) { + item.mask |= TCIF_TEXT; + item.pszText = m_wszTitle; + wcsncpy_s(m_wszTitle, newtitle, _TRUNCATE); + if (m_pWnd) + m_pWnd->updateTitle(m_cache->getNick()); + } + if (m_iTabID >= 0) { + TabCtrl_SetItem(m_hwndParent, m_iTabID, &item); + if (m_pContainer->m_dwFlags & CNT_SIDEBAR) + m_pContainer->m_pSideBar->updateSession(this); + } + if (m_pContainer->m_hwndActive == m_hwnd && bChanged) + m_pContainer->UpdateTitle(m_hContact); - UpdateTrayMenuState(this, TRUE); - if (M.IsFavorite(m_hContact)) - AddContactToFavorites(m_hContact, m_cache->getNick(), szActProto, m_wszStatus, m_wStatus, Skin_LoadProtoIcon(m_cache->getProto(), m_cache->getStatus()), 0, PluginConfig.g_hMenuFavorites); + UpdateTrayMenuState(this, TRUE); + if (M.IsFavorite(m_hContact)) + AddContactToFavorites(m_hContact, m_cache->getNick(), szActProto, m_wszStatus, m_wStatus, Skin_LoadProtoIcon(m_cache->getProto(), m_cache->getStatus()), 0, PluginConfig.g_hMenuFavorites); - if (M.IsRecent(m_hContact)) - AddContactToFavorites(m_hContact, m_cache->getNick(), szActProto, m_wszStatus, m_wStatus, Skin_LoadProtoIcon(m_cache->getProto(), m_cache->getStatus()), 0, PluginConfig.g_hMenuRecent); + if (M.IsRecent(m_hContact)) + AddContactToFavorites(m_hContact, m_cache->getNick(), szActProto, m_wszStatus, m_wStatus, Skin_LoadProtoIcon(m_cache->getProto(), m_cache->getStatus()), 0, PluginConfig.g_hMenuRecent); - m_pPanel.Invalidate(); - if (m_pWnd) - m_pWnd->Invalidate(); - } + m_pPanel.Invalidate(); + if (m_pWnd) + m_pWnd->Invalidate(); + } - // care about MetaContacts and update the statusbar icon with the currently "most online" contact... - if (m_bIsMeta) { - PostMessage(m_hwnd, DM_OWNNICKCHANGED, 0, 0); - if (m_pContainer->m_dwFlags & CNT_UINSTATUSBAR) - DM_UpdateLastMessage(); + // care about MetaContacts and update the statusbar icon with the currently "most online" contact... + if (m_bIsMeta) { + PostMessage(m_hwnd, DM_OWNNICKCHANGED, 0, 0); + if (m_pContainer->m_dwFlags & CNT_UINSTATUSBAR) + DM_UpdateLastMessage(); + } } } -void CSrmmWindow::onClick_Ok(CCtrlButton*) +void CMsgDialog::onClick_Ok(CCtrlButton *) { if (m_bEditNotesActive) { SendMessage(m_hwnd, DM_ACTIVATETOOLTIP, IDC_PIC, (LPARAM)TranslateT("You are editing the user notes. Click the button again or use the hotkey (default: Alt+N) to save the notes and return to normal messaging mode")); @@ -1074,9 +979,9 @@ void CSrmmWindow::onClick_Ok(CCtrlButton*) fi.chrg.cpMin = 0; fi.chrg.cpMax = -1; fi.lpstrText = L"{"; - int final_sendformat = m_message.SendMsg(EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi) == -1 ? m_SendFormat : 0; + int final_sendformat = m_message.SendMsg(EM_FINDTEXTEX, FR_DOWN, (LPARAM)& fi) == -1 ? m_SendFormat : 0; fi.lpstrText = L"}"; - final_sendformat = m_message.SendMsg(EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi) == -1 ? final_sendformat : 0; + final_sendformat = m_message.SendMsg(EM_FINDTEXTEX, FR_DOWN, (LPARAM)& fi) == -1 ? final_sendformat : 0; if (GetSendButtonState(m_hwnd) == PBS_DISABLED) return; @@ -1089,70 +994,102 @@ void CSrmmWindow::onClick_Ok(CCtrlButton*) if (decoded.IsEmpty()) return; - if (final_sendformat) + if (isChat()) { + m_cache->saveHistory(); DoRtfToTags(decoded); - decoded.TrimRight(); - - T2Utf utfResult(decoded); - size_t memRequired = mir_strlen(utfResult) + 1; - - // try to detect RTL - HWND hwndEdit = m_message.GetHwnd(); - SendMessage(hwndEdit, WM_SETREDRAW, FALSE, 0); - - PARAFORMAT2 pf2; - memset(&pf2, 0, sizeof(PARAFORMAT2)); - pf2.cbSize = sizeof(pf2); - pf2.dwMask = PFM_RTLPARA; - SendMessage(hwndEdit, EM_SETSEL, 0, -1); - SendMessage(hwndEdit, EM_GETPARAFORMAT, 0, (LPARAM)&pf2); - - int flags = 0; - if (pf2.wEffects & PFE_RTLPARA) - if (Utils_IsRtl(decoded)) - flags |= PREF_RTL; - - SendMessage(hwndEdit, WM_SETREDRAW, TRUE, 0); - SendMessage(hwndEdit, EM_SETSEL, -1, -1); - InvalidateRect(hwndEdit, nullptr, FALSE); - - if (memRequired > m_iSendBufferSize) { - m_sendBuffer = (char *)mir_realloc(m_sendBuffer, memRequired); - m_iSendBufferSize = memRequired; + decoded.Trim(); + + if (m_si->pMI->bAckMsg) { + m_message.Enable(false); + m_message.SendMsg(EM_SETREADONLY, TRUE, 0); + } + else m_message.SetText(L""); + + Utils::enableDlgControl(m_hwnd, IDOK, false); + + // Typing support for GCW_PRIVMESS sessions + if (m_si->iType == GCW_PRIVMESS) + if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) + DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); + + bool fSound = true; + if (decoded[0] == '/' || m_si->iType == GCW_SERVER) + fSound = false; + Chat_DoEventHook(m_si, GC_USER_MESSAGE, nullptr, decoded, 0); + m_si->pMI->idleTimeStamp = time(0); + UpdateStatusBar(); + if (m_pContainer) + if (fSound && !nen_options.iNoSounds && !(m_pContainer->m_dwFlags & CNT_NOSOUND)) + Skin_PlaySound("ChatSent"); } + else { + if (final_sendformat) + DoRtfToTags(decoded); + decoded.TrimRight(); - memcpy(m_sendBuffer, (char*)utfResult, memRequired); + T2Utf utfResult(decoded); + size_t memRequired = mir_strlen(utfResult) + 1; - if (memRequired == 0 || m_sendBuffer[0] == 0) - return; + // try to detect RTL + HWND hwndEdit = m_message.GetHwnd(); + SendMessage(hwndEdit, WM_SETREDRAW, FALSE, 0); + + PARAFORMAT2 pf2; + memset(&pf2, 0, sizeof(PARAFORMAT2)); + pf2.cbSize = sizeof(pf2); + pf2.dwMask = PFM_RTLPARA; + SendMessage(hwndEdit, EM_SETSEL, 0, -1); + SendMessage(hwndEdit, EM_GETPARAFORMAT, 0, (LPARAM)& pf2); + + int flags = 0; + if (pf2.wEffects & PFE_RTLPARA) + if (Utils_IsRtl(decoded)) + flags |= PREF_RTL; - if (m_sendMode & SMODE_CONTAINER && m_pContainer->m_hwndActive == m_hwnd && GetForegroundWindow() == m_pContainer->m_hwnd) { - int tabCount = TabCtrl_GetItemCount(m_hwndParent); - ptrA szFromStream(m_message.GetRichTextRtf(!m_SendFormat)); - - for (int i = 0; i < tabCount; i++) { - // get the contact from the tabs lparam which hopefully is the tabs hwnd so we can get its userdata.... hopefully - HWND contacthwnd = GetTabWindow(m_hwndParent, i); - if (IsWindow(contacthwnd)) { - // if the contact hwnd is the current contact then ignore it and let the normal code deal with the msg - if (contacthwnd != m_hwnd) { - SETTEXTEX stx = { ST_DEFAULT, CP_UTF8 }; - // send the buffer to the contacts msg typing area - SendDlgItemMessage(contacthwnd, IDC_SRMM_MESSAGE, EM_SETTEXTEX, (WPARAM)&stx, (LPARAM)szFromStream); - SendMessage(contacthwnd, WM_COMMAND, IDOK, 0); + SendMessage(hwndEdit, WM_SETREDRAW, TRUE, 0); + SendMessage(hwndEdit, EM_SETSEL, -1, -1); + InvalidateRect(hwndEdit, nullptr, FALSE); + + if (memRequired > m_iSendBufferSize) { + m_sendBuffer = (char *)mir_realloc(m_sendBuffer, memRequired); + m_iSendBufferSize = memRequired; + } + + memcpy(m_sendBuffer, (char *)utfResult, memRequired); + + if (memRequired == 0 || m_sendBuffer[0] == 0) + return; + + if (m_sendMode & SMODE_CONTAINER && m_pContainer->m_hwndActive == m_hwnd && GetForegroundWindow() == m_pContainer->m_hwnd) { + int tabCount = TabCtrl_GetItemCount(m_hwndParent); + ptrA szFromStream(m_message.GetRichTextRtf(!m_SendFormat)); + + for (int i = 0; i < tabCount; i++) { + // get the contact from the tabs lparam which hopefully is the tabs hwnd so we can get its userdata.... hopefully + HWND contacthwnd = GetTabWindow(m_hwndParent, i); + if (IsWindow(contacthwnd)) { + // if the contact hwnd is the current contact then ignore it and let the normal code deal with the msg + if (contacthwnd != m_hwnd) { + SETTEXTEX stx = { ST_DEFAULT, CP_UTF8 }; + // send the buffer to the contacts msg typing area + SendDlgItemMessage(contacthwnd, IDC_SRMM_MESSAGE, EM_SETTEXTEX, (WPARAM)& stx, (LPARAM)szFromStream); + SendMessage(contacthwnd, WM_COMMAND, IDOK, 0); + } } } } + // END /all /MOD + if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) + DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); + + DeletePopupsForContact(m_hContact, PU_REMOVE_ON_SEND); + sendQueue->addTo(this, memRequired, flags); } - // END /all /MOD - if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) - DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); - DeletePopupsForContact(m_hContact, PU_REMOVE_ON_SEND); - sendQueue->addTo(this, memRequired, flags); + SetFocus(m_message.GetHwnd()); } -void CSrmmWindow::onClick_Add(CCtrlButton*) +void CMsgDialog::onClick_Add(CCtrlButton*) { Contact_Add(m_hContact, m_hwnd); @@ -1165,7 +1102,7 @@ void CSrmmWindow::onClick_Add(CCtrlButton*) } } -void CSrmmWindow::onClick_Quote(CCtrlButton*) +void CMsgDialog::onClick_Quote(CCtrlButton*) { CHARRANGE sel; SETTEXTEX stx = { ST_SELECTION, 1200 }; @@ -1253,7 +1190,7 @@ void CSrmmWindow::onClick_Quote(CCtrlButton*) SetFocus(m_message.GetHwnd()); } -void CSrmmWindow::onClick_CancelAdd(CCtrlButton*) +void CMsgDialog::onClick_CancelAdd(CCtrlButton*) { m_bNotOnList = false; ShowMultipleControls(m_hwnd, addControls, _countof(addControls), SW_HIDE); @@ -1262,7 +1199,69 @@ void CSrmmWindow::onClick_CancelAdd(CCtrlButton*) Resize(); } -void CSrmmWindow::onChange_Message(CCtrlEdit*) +void CMsgDialog::onClick_Filter(CCtrlButton *pButton) +{ + if (!pButton->Enabled()) + return; + + if (m_iLogFilterFlags == 0 && !m_bFilterEnabled) { + MessageBox(nullptr, TranslateT("The filter cannot be enabled, because there are no event types selected either global or for this chat room"), TranslateT("Event filter error"), MB_OK); + m_bFilterEnabled = false; + } + else m_bFilterEnabled = !m_bFilterEnabled; + + m_btnFilter.SendMsg(BUTTONSETOVERLAYICON, (LPARAM)(m_bFilterEnabled ? PluginConfig.g_iconOverlayEnabled : PluginConfig.g_iconOverlayDisabled), 0); + + if (m_bFilterEnabled && db_get_b(0, CHAT_MODULE, "RightClickFilter", 1) == 0) { + ShowFilterMenu(); + return; + } + RedrawLog(); + UpdateTitle(); + db_set_b(m_si->hContact, CHAT_MODULE, "FilterEnabled", m_bFilterEnabled); +} + +void CMsgDialog::onClick_ShowNickList(CCtrlButton *pButton) +{ + if (!pButton->Enabled() || m_si->iType == GCW_SERVER) + return; + + m_bNicklistEnabled = !m_bNicklistEnabled; + + Resize(); + if (CSkin::m_skinEnabled) + InvalidateRect(m_hwnd, nullptr, TRUE); + ScrollToBottom(); +} + +void CMsgDialog::onDblClick_List(CCtrlListBox *pList) +{ + TVHITTESTINFO hti; + hti.pt.x = (short)LOWORD(GetMessagePos()); + hti.pt.y = (short)HIWORD(GetMessagePos()); + ScreenToClient(pList->GetHwnd(), &hti.pt); + + int item = LOWORD(pList->SendMsg(LB_ITEMFROMPOINT, 0, MAKELPARAM(hti.pt.x, hti.pt.y))); + USERINFO *ui = g_chatApi.UM_FindUserFromIndex(m_si, item); + if (ui == nullptr) + return; + + bool bShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0; + if (g_Settings.bDoubleClick4Privat ? bShift : !bShift) { + int selStart = LOWORD(m_message.SendMsg(EM_GETSEL, 0, 0)); + CMStringW tszName(ui->pszNick); + if (selStart == 0) + tszName.AppendChar(g_Settings.bUseCommaAsColon ? ',' : ':'); + tszName.AppendChar(' '); + + m_message.SendMsg(EM_REPLACESEL, FALSE, (LPARAM)tszName.GetString()); + PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); + SetFocus(m_message.GetHwnd()); + } + else Chat_DoEventHook(m_si, GC_USER_PRIVMESS, ui, nullptr, 0); +} + +void CMsgDialog::onChange_Message(CCtrlEdit*) { if (m_pContainer->m_hwndActive == m_hwnd) UpdateReadChars(); @@ -1270,38 +1269,75 @@ void CSrmmWindow::onChange_Message(CCtrlEdit*) m_dwLastActivity = GetTickCount(); m_pContainer->m_dwLastActivity = m_dwLastActivity; UpdateSaveAndSendButton(); - if (!(GetKeyState(VK_CONTROL) & 0x8000)) { - m_nLastTyping = GetTickCount(); - if (GetWindowTextLength(m_message.GetHwnd())) { - if (m_nTypeMode == PROTOTYPE_SELFTYPING_OFF) { - if (!(m_dwFlags & MWF_INITMODE)) - DM_NotifyTyping(PROTOTYPE_SELFTYPING_ON); + + m_btnOk.SendMsg(BUTTONSETASNORMAL, m_message.GetRichTextLength() != 0, 0); + m_btnOk.Enable(m_message.GetRichTextLength() != 0); + + // Typing support for GCW_PRIVMESS sessions + if (m_si == nullptr || m_si->iType == GCW_PRIVMESS) { + if (!(GetKeyState(VK_CONTROL) & 0x8000)) { + m_nLastTyping = GetTickCount(); + if (GetWindowTextLength(m_message.GetHwnd())) { + if (m_nTypeMode == PROTOTYPE_SELFTYPING_OFF) { + if (!(m_dwFlags & MWF_INITMODE)) + DM_NotifyTyping(PROTOTYPE_SELFTYPING_ON); + } } + else if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) + DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); } - else if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) - DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); } } ///////////////////////////////////////////////////////////////////////////////////////// // resizer proc for the "new" layout. -int CSrmmWindow::Resizer(UTILRESIZECONTROL *urc) +int CMsgDialog::Resizer(UTILRESIZECONTROL *urc) { int panelHeight = m_pPanel.getHeight() + 1; - + + bool bNick = false; bool bInfoPanel = m_pPanel.isActive(); bool bErrorState = (m_dwFlags & MWF_ERRORSTATE) != 0; bool bShowToolbar = (m_pContainer->m_dwFlags & CNT_HIDETOOLBAR) == 0; bool bBottomToolbar = (m_pContainer->m_dwFlags & CNT_BOTTOMTOOLBAR) != 0; + int iSplitterX = m_pContainer->m_pSettings->iSplitterX; + RECT rc, rcButton; GetClientRect(m_log.GetHwnd(), &rc); GetClientRect(GetDlgItem(m_hwnd, IDC_PROTOCOL), &rcButton); + if (m_bIsAutosizingInput) + Utils::showDlgControl(m_hwnd, IDC_SPLITTERY, SW_HIDE); + if (m_panelStatusCX == 0) m_panelStatusCX = 80; + if (m_si) { + if (m_si->iType != GCW_SERVER) { + m_nickList.Show(m_bNicklistEnabled); + Utils::showDlgControl(m_hwnd, IDC_SPLITTERX, m_bNicklistEnabled ? SW_SHOW : SW_HIDE); + + m_btnNickList.Enable(true); + m_btnFilter.Enable(true); + if (m_si->iType == GCW_CHATROOM) + m_btnChannelMgr.Enable(m_si->pMI->bChanMgr); + } + else { + m_nickList.Hide(); + Utils::showDlgControl(m_hwnd, IDC_SPLITTERX, SW_HIDE); + } + + if (m_si->iType == GCW_SERVER) { + m_btnNickList.Enable(false); + m_btnFilter.Enable(false); + m_btnChannelMgr.Enable(false); + } + + bNick = m_si->iType != GCW_SERVER && m_bNicklistEnabled; + } + switch (urc->wId) { case IDC_PANELSPLITTER: urc->rcItem.bottom = panelHeight; @@ -1309,6 +1345,27 @@ int CSrmmWindow::Resizer(UTILRESIZECONTROL *urc) return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP; case IDC_SRMM_LOG: + if (isChat()) { + urc->rcItem.top = 0; + urc->rcItem.left = 0; + urc->rcItem.right = bNick ? urc->dlgNewSize.cx - iSplitterX : urc->dlgNewSize.cx; + urc->rcItem.bottom = urc->dlgNewSize.cy - m_iSplitterY; + if (!bShowToolbar || bBottomToolbar) + urc->rcItem.bottom += DPISCALEY_S(21); + if (bInfoPanel) + urc->rcItem.top += panelHeight; + if (CSkin::m_skinEnabled) { + CSkinItem *item = &SkinItems[ID_EXTBKHISTORY]; + if (!item->IGNORED) { + urc->rcItem.left += item->MARGIN_LEFT; + urc->rcItem.right -= item->MARGIN_RIGHT; + urc->rcItem.top += item->MARGIN_TOP; + urc->rcItem.bottom -= item->MARGIN_BOTTOM; + } + } + return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; + } + if (m_dwFlags & MWF_ERRORSTATE) urc->rcItem.bottom -= ERRORPANEL_HEIGHT; if (m_dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED || m_bNotOnList) @@ -1333,6 +1390,26 @@ int CSrmmWindow::Resizer(UTILRESIZECONTROL *urc) rcLogBottom = urc->rcItem.bottom; return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; + case IDC_SRMM_NICKLIST: + urc->rcItem.top = 0; + urc->rcItem.right = urc->dlgNewSize.cx; + urc->rcItem.left = urc->dlgNewSize.cx - iSplitterX + 2; + urc->rcItem.bottom = urc->dlgNewSize.cy - m_iSplitterY; + if (!bShowToolbar || bBottomToolbar) + urc->rcItem.bottom += DPISCALEY_S(21); + if (bInfoPanel) + urc->rcItem.top += panelHeight; + if (CSkin::m_skinEnabled) { + CSkinItem *item = &SkinItems[ID_EXTBKUSERLIST]; + if (!item->IGNORED) { + urc->rcItem.left += item->MARGIN_LEFT; + urc->rcItem.right -= item->MARGIN_RIGHT; + urc->rcItem.top += item->MARGIN_TOP; + urc->rcItem.bottom -= item->MARGIN_BOTTOM; + } + } + return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; + case IDC_CONTACTPIC: GetClientRect(m_message.GetHwnd(), &rc); urc->rcItem.top -= m_iSplitterY - m_originalSplitterY; @@ -1357,10 +1434,28 @@ int CSrmmWindow::Resizer(UTILRESIZECONTROL *urc) return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; + case IDC_SPLITTERX: + urc->rcItem.right = urc->dlgNewSize.cx - iSplitterX + 2; + urc->rcItem.left = urc->dlgNewSize.cx - iSplitterX; + urc->rcItem.bottom = urc->dlgNewSize.cy - m_iSplitterY; + if (!bShowToolbar || bBottomToolbar) + urc->rcItem.bottom += DPISCALEY_S(21); + urc->rcItem.top = 0; + if (bInfoPanel) + urc->rcItem.top += panelHeight; + return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; + case IDC_SPLITTERY: urc->rcItem.right = urc->dlgNewSize.cx; + urc->rcItem.bottom = urc->rcItem.top + DPISCALEY_S(2); + if (isChat()) { + urc->rcItem.top = urc->dlgNewSize.cy - m_iSplitterY + DPISCALEY_S(23); + urc->rcItem.left = 0; + urc->rcItem.bottom++; + urc->rcItem.top++; + return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; + } urc->rcItem.top -= m_iSplitterY - m_originalSplitterY; - urc->rcItem.bottom = urc->rcItem.top + 2; OffsetRect(&urc->rcItem, 0, 1); urc->rcItem.left = 0; @@ -1372,7 +1467,14 @@ int CSrmmWindow::Resizer(UTILRESIZECONTROL *urc) urc->rcItem.right = urc->dlgNewSize.cx; if (m_bShowAvatar) urc->rcItem.right -= m_pic.cx + 2; - urc->rcItem.top -= m_iSplitterY - m_originalSplitterY; + if (isChat()) { + urc->rcItem.bottom = urc->dlgNewSize.cy; + urc->rcItem.top = urc->dlgNewSize.cy - m_iSplitterY + 3 + DPISCALEY_S(23); + } + else { + urc->rcItem.top -= m_iSplitterY - m_originalSplitterY; + } + if (bBottomToolbar && bShowToolbar) urc->rcItem.bottom -= DPISCALEY_S(22); @@ -1389,6 +1491,8 @@ int CSrmmWindow::Resizer(UTILRESIZECONTROL *urc) urc->rcItem.bottom -= item->MARGIN_BOTTOM; } } + if (isChat()) + return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; return RD_ANCHORX_CUSTOM | RD_ANCHORY_BOTTOM; case IDC_MULTISPLITTER: @@ -1465,7 +1569,7 @@ int CSrmmWindow::Resizer(UTILRESIZECONTROL *urc) ///////////////////////////////////////////////////////////////////////////////////////// // message filter -int CSrmmWindow::OnFilter(MSGFILTER *pFilter) +int CMsgDialog::OnFilter(MSGFILTER *pFilter) { RECT rc; POINT pt; @@ -1486,11 +1590,25 @@ int CSrmmWindow::OnFilter(MSGFILTER *pFilter) if ((msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) && !(GetKeyState(VK_RMENU) & 0x8000)) { MSG message = { m_hwnd, msg, wp, lp }; - LRESULT mim_hotkey_check = Hotkey_Check(&message, TABSRMM_HK_SECTION_IM); + LRESULT mim_hotkey_check = Hotkey_Check(&message, isChat() ? TABSRMM_HK_SECTION_GC : TABSRMM_HK_SECTION_IM); if (mim_hotkey_check) m_bkeyProcessed = true; switch (mim_hotkey_check) { + case TABSRMM_HK_CHANNELMGR: + onClick_ChanMgr(&m_btnChannelMgr); + return _dlgReturn(m_hwnd, 1); + case TABSRMM_HK_FILTERTOGGLE: + onClick_Filter(&m_btnFilter); + InvalidateRect(m_btnFilter.GetHwnd(), nullptr, TRUE); + return _dlgReturn(m_hwnd, 1); + case TABSRMM_HK_LISTTOGGLE: + onClick_ShowNickList(&m_btnNickList); + return _dlgReturn(m_hwnd, 1); + case TABSRMM_HK_MUC_SHOWSERVER: + if (m_si->iType != GCW_SERVER) + Chat_DoEventHook(m_si, GC_USER_MESSAGE, nullptr, L"/servershow", 0); + return _dlgReturn(m_hwnd, 1); case TABSRMM_HK_SETUSERPREFS: CallService(MS_TABMSG_SETUSERPREFS, m_hContact, 0); return _dlgReturn(m_hwnd, 1); @@ -1817,7 +1935,7 @@ int CSrmmWindow::OnFilter(MSGFILTER *pFilter) ///////////////////////////////////////////////////////////////////////////////////////// -LRESULT CSrmmWindow::WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam) +LRESULT CMsgDialog::WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam) { bool isCtrl, isShift, isAlt; @@ -1841,6 +1959,44 @@ LRESULT CSrmmWindow::WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam) m_btnQuote.Click(); break; + case WM_LBUTTONUP: + if (isChat() && g_Settings.bClickableNicks) { + POINT pt = { LOWORD(lParam), HIWORD(lParam) }; + CheckCustomLink(m_log.GetHwnd(), &pt, msg, wParam, lParam, TRUE); + } + if (M.GetByte("autocopy", 1)) { + CHARRANGE sel; + SendMessage(m_log.GetHwnd(), EM_EXGETSEL, 0, (LPARAM)& sel); + if (sel.cpMin != sel.cpMax) { + SendMessage(m_log.GetHwnd(), WM_COPY, 0, 0); + sel.cpMin = sel.cpMax; + SendMessage(m_log.GetHwnd(), EM_EXSETSEL, 0, (LPARAM)& sel); + SetFocus(m_message.GetHwnd()); + } + } + break; + + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + case WM_RBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONDBLCLK: + if (isChat() && g_Settings.bClickableNicks) { + POINT pt = { LOWORD(lParam), HIWORD(lParam) }; + CheckCustomLink(m_log.GetHwnd(), &pt, msg, wParam, lParam, TRUE); + } + break; + + case WM_SETCURSOR: + if (g_Settings.bClickableNicks && isChat() && (LOWORD(lParam) == HTCLIENT)) { + POINT pt; + GetCursorPos(&pt); + ScreenToClient(m_log.GetHwnd(), &pt); + if (CheckCustomLink(m_log.GetHwnd(), &pt, msg, wParam, lParam, FALSE)) + return TRUE; + } + break; + case WM_SYSKEYUP: if (wParam == VK_MENU) { ProcessHotkeysByMsgFilter(m_log, msg, wParam, lParam); @@ -1867,6 +2023,12 @@ LRESULT CSrmmWindow::WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam) KbdState(isShift, isCtrl, isAlt); if (wParam == VK_INSERT && isCtrl) return WMCopyHandler(msg, wParam, lParam); + + if (wParam == 0x57 && isCtrl) { // ctrl-w (close window) + PostMessage(m_hwnd, WM_CLOSE, 0, 1); + return TRUE; + } + break; case WM_COPY: @@ -1901,7 +2063,7 @@ LRESULT CSrmmWindow::WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam) ///////////////////////////////////////////////////////////////////////////////////////// -LRESULT CSrmmWindow::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) +LRESULT CMsgDialog::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) { bool isCtrl, isShift, isAlt; @@ -1957,6 +2119,8 @@ LRESULT CSrmmWindow::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) case WM_MOUSEWHEEL: if (DM_MouseWheelHandler(wParam, lParam) == 0) return 0; + + m_iLastEnterTime = 0; break; case EM_PASTESPECIAL: @@ -1993,6 +2157,11 @@ LRESULT CSrmmWindow::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) if (wParam == VK_CAPITAL || wParam == VK_NUMLOCK) m_message.OnChange(&m_message); + if (wParam != VK_RIGHT && wParam != VK_LEFT) { + replaceStrW(m_wszSearchQuery, nullptr); + replaceStrW(m_wszSearchResult, nullptr); + } + if (wParam == VK_RETURN) { if (m_bEditNotesActive) break; @@ -2108,7 +2277,7 @@ LRESULT CSrmmWindow::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) break; case WM_ERASEBKGND: - return(CSkin::m_skinEnabled ? 0 : 1); + return !CSkin::m_skinEnabled; // sent by smileyadd when the smiley selection window dies // just grab the focus :) @@ -2118,18 +2287,76 @@ LRESULT CSrmmWindow::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) case WM_CONTEXTMENU: POINT pt; - if (lParam == 0xFFFFFFFF) { - CHARRANGE sel; - m_message.SendMsg(EM_EXGETSEL, 0, (LPARAM)&sel); - m_message.SendMsg(EM_POSFROMCHAR, (WPARAM)&pt, (LPARAM)sel.cpMax); - ClientToScreen(m_message.GetHwnd(), &pt); + if (isChat()) { + GetCursorPos(&pt); + + HMENU hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_CONTEXT)); + HMENU hSubMenu = GetSubMenu(hMenu, 2); + RemoveMenu(hSubMenu, 9, MF_BYPOSITION); + RemoveMenu(hSubMenu, 8, MF_BYPOSITION); + RemoveMenu(hSubMenu, 4, MF_BYPOSITION); + + EnableMenuItem(hSubMenu, IDM_PASTEFORMATTED, MF_BYCOMMAND | (m_si->pMI->bBold ? MF_ENABLED : MF_GRAYED)); + TranslateMenu(hSubMenu); + + CHARRANGE sel, all = { 0, -1 }; + m_message.SendMsg(EM_EXGETSEL, 0, (LPARAM)& sel); + if (sel.cpMin == sel.cpMax) { + EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(hSubMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED); + } + + MessageWindowPopupData mwpd = { sizeof(mwpd) }; + mwpd.uType = MSG_WINDOWPOPUP_SHOWING; + mwpd.uFlags = MSG_WINDOWPOPUP_INPUT; + mwpd.hContact = m_hContact; + mwpd.hwnd = m_message.GetHwnd(); + mwpd.hMenu = hSubMenu; + mwpd.pt = pt; + NotifyEventHooks(g_chatApi.hevWinPopup, 0, (LPARAM)& mwpd); + + int iSelection = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, m_hwnd, nullptr); + + mwpd.selection = iSelection; + mwpd.uType = MSG_WINDOWPOPUP_SELECTED; + NotifyEventHooks(g_chatApi.hevWinPopup, 0, (LPARAM)& mwpd); + + switch (iSelection) { + case IDM_COPY: + m_message.SendMsg(WM_COPY, 0, 0); + break; + case IDM_CUT: + m_message.SendMsg(WM_CUT, 0, 0); + break; + case IDM_PASTE: + case IDM_PASTEFORMATTED: + m_message.SendMsg(EM_PASTESPECIAL, (iSelection == IDM_PASTE) ? CF_UNICODETEXT : 0, 0); + break; + case IDM_COPYALL: + m_message.SendMsg(EM_EXSETSEL, 0, (LPARAM)& all); + m_message.SendMsg(WM_COPY, 0, 0); + m_message.SendMsg(EM_EXSETSEL, 0, (LPARAM)& sel); + break; + case IDM_SELECTALL: + m_message.SendMsg(EM_EXSETSEL, 0, (LPARAM)& all); + break; + } + DestroyMenu(hMenu); } else { - pt.x = GET_X_LPARAM(lParam); - pt.y = GET_Y_LPARAM(lParam); - } + if (lParam == 0xFFFFFFFF) { + CHARRANGE sel; + m_message.SendMsg(EM_EXGETSEL, 0, (LPARAM)& sel); + m_message.SendMsg(EM_POSFROMCHAR, (WPARAM)& pt, (LPARAM)sel.cpMax); + ClientToScreen(m_message.GetHwnd(), &pt); + } + else { + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + } - ShowPopupMenu(m_message, pt); + ShowPopupMenu(m_message, pt); + } return TRUE; } @@ -2139,7 +2366,7 @@ LRESULT CSrmmWindow::WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) ///////////////////////////////////////////////////////////////////////////////////////// // dialog procedure -INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +INT_PTR CMsgDialog::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) { POINT pt, tmp, cur; RECT rc; @@ -2170,15 +2397,15 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) bool bAero = M.isAero(); if (CSkin::m_skinEnabled) { - UINT item_ids[2] = { ID_EXTBKHISTORY, ID_EXTBKINPUTAREA }; - UINT ctl_ids[2] = { IDC_SRMM_LOG, IDC_SRMM_MESSAGE }; + UINT item_ids[] = { ID_EXTBKUSERLIST, ID_EXTBKHISTORY, ID_EXTBKINPUTAREA }; + UINT ctl_ids[] = { IDC_SRMM_NICKLIST, IDC_SRMM_LOG, IDC_SRMM_MESSAGE }; BOOL isEditNotesReason = m_bEditNotesActive; BOOL isSendLaterReason = (m_sendMode & SMODE_SENDLATER); BOOL isMultipleReason = (m_sendMode & SMODE_MULTIPLE || m_sendMode & SMODE_CONTAINER); CSkin::SkinDrawBG(m_hwnd, m_pContainer->m_hwnd, m_pContainer, &rcClient, hdcMem); - for (int i = 0; i < 2; i++) { + for (int i = 0; i < _countof(item_ids); i++) { CSkinItem *item = &SkinItems[item_ids[i]]; if (!item->IGNORED) { GetWindowRect(GetDlgItem(m_hwnd, ctl_ids[i]), &rcWindow); @@ -2245,6 +2472,9 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) return 0; case WM_SIZE: + if (wParam == SIZE_MAXIMIZED) + ScrollToBottom(); + if (!IsIconic(m_hwnd)) { if (m_ipFieldHeight == 0) m_ipFieldHeight = CInfoPanel::m_ipConfig.height2; @@ -2259,11 +2489,13 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) LoadSplitter(); } - HBITMAP hbm = ((m_pPanel.isActive()) && m_pContainer->m_avatarMode != 3) ? m_hOwnPic : (m_ace ? m_ace->hbmPic : PluginConfig.g_hbmUnknown); - if (hbm != nullptr) { - BITMAP bminfo; - GetObject(hbm, sizeof(bminfo), &bminfo); - CalcDynamicAvatarSize(&bminfo); + if (m_si == nullptr) { + HBITMAP hbm = ((m_pPanel.isActive()) && m_pContainer->m_avatarMode != 3) ? m_hOwnPic : (m_ace ? m_ace->hbmPic : PluginConfig.g_hbmUnknown); + if (hbm != nullptr) { + BITMAP bminfo; + GetObject(hbm, sizeof(bminfo), &bminfo); + CalcDynamicAvatarSize(&bminfo); + } } GetClientRect(m_hwnd, &rc); @@ -2277,7 +2509,7 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) LONG cx = rc.right; LONG panelHeight = m_pPanel.getHeight(); - hbm = (m_pContainer->m_avatarMode == 3) ? m_hOwnPic : (m_ace ? m_ace->hbmPic : PluginConfig.g_hbmUnknown); + HBITMAP hbm = (m_pContainer->m_avatarMode == 3) ? m_hOwnPic : (m_ace ? m_ace->hbmPic : PluginConfig.g_hbmUnknown); double dHeight = 0, dWidth = 0; Utils::scaleAvatarHeightLimited(hbm, dWidth, dHeight, panelHeight - 2); m_iPanelAvatarX = (int)dWidth; @@ -2340,7 +2572,10 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) return 0; case WM_TIMECHANGE: - DM_OptionsApplied(0, 0); + if (isChat()) + RedrawLog(); + else + DM_OptionsApplied(0, 0); break; case WM_NOTIFY: @@ -2362,12 +2597,105 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) case EN_REQUESTRESIZE: DM_HandleAutoSizeRequest((REQRESIZE *)lParam); break; + + case EN_LINK: + if (((LPNMHDR)lParam)->idFrom == IDC_SRMM_LOG) { + switch (((ENLINK *)lParam)->msg) { + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + case WM_LBUTTONDBLCLK: + CHARRANGE sel; + SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_EXGETSEL, 0, (LPARAM)& sel); + if (sel.cpMin == sel.cpMax) { + UINT msg = ((ENLINK *)lParam)->msg; + m_pContainer->m_pMenuBar->Cancel(); + + TEXTRANGE tr; + tr.lpstrText = nullptr; + tr.chrg = ((ENLINK *)lParam)->chrg; + tr.lpstrText = (wchar_t *)mir_alloc(sizeof(wchar_t) * (tr.chrg.cpMax - tr.chrg.cpMin + 2)); + SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)& tr); + + BOOL isLink = IsStringValidLink(tr.lpstrText); + if (isLink) // handled by core + break; + + // clicked a nick name + if (g_Settings.bClickableNicks) { + if (msg == WM_RBUTTONDOWN) { + for (auto &ui : m_si->getUserList()) { + if (mir_wstrcmp(ui->pszNick, tr.lpstrText)) + continue; + + pt.x = (short)LOWORD(((ENLINK *)lParam)->lParam); + pt.y = (short)HIWORD(((ENLINK *)lParam)->lParam); + ClientToScreen(((NMHDR *)lParam)->hwndFrom, &pt); + RunUserMenu(m_hwnd, ui, pt); + break; + } + return TRUE; + } + + if (msg == WM_LBUTTONUP) { + CHARRANGE chr; + m_message.SendMsg(EM_EXGETSEL, 0, (LPARAM)& chr); + + wchar_t tszAplTmpl[] = L"%s:"; + size_t bufSize = mir_wstrlen(tr.lpstrText) + mir_wstrlen(tszAplTmpl) + 3; + wchar_t *tszTmp = (wchar_t *)mir_alloc(bufSize * sizeof(wchar_t)), *tszAppeal = tszTmp; + + TEXTRANGE tr2; + tr2.lpstrText = (LPTSTR)mir_alloc(sizeof(wchar_t) * 2); + if (chr.cpMin) { + // prepend nick with space if needed + tr2.chrg.cpMin = chr.cpMin - 1; + tr2.chrg.cpMax = chr.cpMin; + m_message.SendMsg(EM_GETTEXTRANGE, 0, (LPARAM)& tr2); + if (!iswspace(*tr2.lpstrText)) + *tszTmp++ = ' '; + mir_wstrcpy(tszTmp, tr.lpstrText); + } + else // in the beginning of the message window + mir_snwprintf(tszAppeal, bufSize, tszAplTmpl, tr.lpstrText); + + size_t st = mir_wstrlen(tszAppeal); + if (chr.cpMax != -1) { + tr2.chrg.cpMin = chr.cpMax; + tr2.chrg.cpMax = chr.cpMax + 1; + // if there is no space after selection, + // or there is nothing after selection at all... + if (!m_message.SendMsg(EM_GETTEXTRANGE, 0, (LPARAM)& tr2) || !iswspace(*tr2.lpstrText)) { + tszAppeal[st++] = ' '; + tszAppeal[st++] = '\0'; + } + } + else { + tszAppeal[st++] = ' '; + tszAppeal[st++] = '\0'; + } + m_message.SendMsg(EM_REPLACESEL, FALSE, (LPARAM)tszAppeal); + mir_free((void *)tr2.lpstrText); + mir_free((void *)tszAppeal); + } + } + SetFocus(m_message.GetHwnd()); + mir_free(tr.lpstrText); + return TRUE; + } + } + break; + } + break; } } break; + case WM_CTLCOLORLISTBOX: + SetBkColor((HDC)wParam, g_Settings.crUserListBGColor); + return (INT_PTR)g_chatApi.hListBkgBrush; + case DM_TYPING: - { + if (m_si == nullptr || m_si->iType == GCW_PRIVMESS) { int preTyping = m_nTypeSecs != 0; m_nTypeSecs = (int)lParam > 0 ? (int)lParam : 0; @@ -2438,18 +2766,33 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) GetMyNick(); return 0; + case WM_KEYDOWN: + SetFocus(m_message.GetHwnd()); + break; + case WM_SETFOCUS: - MsgWindowUpdateState(WM_SETFOCUS); + if (CMimAPI::m_shutDown) + break; + + if (isChat()) + UpdateWindowState(WM_SETFOCUS); + else + MsgWindowUpdateState(WM_SETFOCUS); SetFocus(m_message.GetHwnd()); return 1; case WM_ACTIVATE: - if (LOWORD(wParam) != WA_ACTIVE) + if (LOWORD(wParam) != WA_ACTIVE) { + m_pContainer->m_hwndSaved = nullptr; break; + } __fallthrough; case WM_MOUSEACTIVATE: - MsgWindowUpdateState(WM_ACTIVATE); + if (isChat()) + UpdateWindowState(WM_ACTIVATE); + else + MsgWindowUpdateState(WM_ACTIVATE); return 1; case DM_UPDATEPICLAYOUT: @@ -2474,7 +2817,20 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) m_iMultiSplit = oldSplitterX; Resize(); } - else if ((HWND)lParam == GetDlgItem(m_hwnd, IDC_SPLITTERY)) { + else if ((HWND)lParam == GetDlgItem(m_hwnd, IDC_SPLITTERX)) { + GetClientRect(m_hwnd, &rc); + pt.x = wParam, pt.y = 0; + ScreenToClient(m_hwnd, &pt); + + int iSplitterX = rc.right - pt.x + 1; + if (iSplitterX < 35) + iSplitterX = 35; + if (iSplitterX > rc.right - rc.left - 35) + iSplitterX = rc.right - rc.left - 35; + m_pContainer->m_pSettings->iSplitterX = iSplitterX; + Resize(); + } + else if ((HWND)lParam == GetDlgItem(m_hwnd, IDC_SPLITTERY) || lParam == -1) { GetClientRect(m_hwnd, &rc); rc.top += (m_pPanel.isActive() ? m_pPanel.getHeight() + 40 : 30); pt.x = 0; @@ -2622,7 +2978,8 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) break; } else if (wParam == TIMERID_TYPE) { - DM_Typing(false); + if (m_si == nullptr || m_si->iType == GCW_PRIVMESS) + DM_Typing(false); break; } break; @@ -2752,22 +3109,124 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_MEASUREITEM: { - LPMEASUREITEMSTRUCT lpmi = (LPMEASUREITEMSTRUCT)lParam; - if (m_pPanel.isHovered()) { - lpmi->itemHeight = 0; - lpmi->itemWidth = 6; + MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam; + if (mis->CtlType == ODT_MENU) { + if (m_pPanel.isHovered()) { + mis->itemHeight = 0; + mis->itemWidth = 6; + return TRUE; + } + return Menu_MeasureItem(lParam); + } + mis->itemHeight = g_Settings.iNickListFontHeight; + } + return TRUE; + + case WM_DRAWITEM: + { + DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam; + if (dis->CtlType == ODT_MENU) { + if (m_pPanel.isHovered()) { + DrawMenuItem(dis, (HICON)dis->itemData, 0); + return TRUE; + } + return Menu_DrawItem(lParam); + } + + if (dis->CtlID == IDC_SRMM_NICKLIST) { + int x_offset = 0; + int index = dis->itemID; + + USERINFO *ui = g_chatApi.UM_FindUserFromIndex(m_si, index); + if (ui == nullptr) + return TRUE; + + int height = dis->rcItem.bottom - dis->rcItem.top; + if (height & 1) + height++; + int offset = (height == 10) ? 0 : height / 2; + + HICON hIcon = g_chatApi.SM_GetStatusIcon(m_si, ui); + HFONT hFont = g_Settings.UserListFonts[ui->iStatusEx]; + HFONT hOldFont = (HFONT)SelectObject(dis->hDC, hFont); + SetBkMode(dis->hDC, TRANSPARENT); + + int nickIndex = 0; + for (int i = 0; i < STATUSICONCOUNT; i++) { + if (hIcon == g_chatApi.hIcons[ICON_STATUS0 + i]) { + nickIndex = i; + break; + } + } + + if (dis->itemState & ODS_SELECTED) { + FillRect(dis->hDC, &dis->rcItem, g_Settings.SelectionBGBrush); + SetTextColor(dis->hDC, g_Settings.nickColors[6]); + } + else { + FillRect(dis->hDC, &dis->rcItem, g_chatApi.hListBkgBrush); + if (g_Settings.bColorizeNicks && nickIndex != 0) + SetTextColor(dis->hDC, g_Settings.nickColors[nickIndex - 1]); + else + SetTextColor(dis->hDC, g_Settings.UserListColors[ui->iStatusEx]); + } + x_offset = 2; + + if (g_Settings.bShowContactStatus && g_Settings.bContactStatusFirst && ui->ContactStatus) { + HICON icon = Skin_LoadProtoIcon(m_si->pszModule, ui->ContactStatus); + DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 8, icon, 16, 16, 0, nullptr, DI_NORMAL); + IcoLib_ReleaseIcon(icon); + x_offset += 18; + } + + if (g_Settings.bClassicIndicators) { + char szTemp[3]; + szTemp[1] = 0; + szTemp[0] = szIndicators[nickIndex]; + if (szTemp[0]) { + SIZE szUmode; + GetTextExtentPoint32A(dis->hDC, szTemp, 1, &szUmode); + TextOutA(dis->hDC, x_offset, dis->rcItem.top, szTemp, 1); + x_offset += szUmode.cx + 2; + } + else x_offset += 8; + } + else { + DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 5, hIcon, 10, 10, 0, nullptr, DI_NORMAL); + x_offset += 12; + } + + if (g_Settings.bShowContactStatus && !g_Settings.bContactStatusFirst && ui->ContactStatus) { + HICON icon = Skin_LoadProtoIcon(m_si->pszModule, ui->ContactStatus); + DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 8, icon, 16, 16, 0, nullptr, DI_NORMAL); + IcoLib_ReleaseIcon(icon); + x_offset += 18; + } + + SIZE sz; + if (m_iSearchItem != -1 && m_iSearchItem == index && m_wszSearch[0]) { + COLORREF clr_orig = GetTextColor(dis->hDC); + GetTextExtentPoint32(dis->hDC, ui->pszNick, (int)mir_wstrlen(m_wszSearch), &sz); + SetTextColor(dis->hDC, RGB(250, 250, 0)); + TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick, (int)mir_wstrlen(m_wszSearch)); + SetTextColor(dis->hDC, clr_orig); + x_offset += sz.cx; + TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick + mir_wstrlen(m_wszSearch), int(mir_wstrlen(ui->pszNick) - mir_wstrlen(m_wszSearch))); + } + else { + GetTextExtentPoint32(dis->hDC, ui->pszNick, (int)mir_wstrlen(ui->pszNick), &sz); + TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick, (int)mir_wstrlen(ui->pszNick)); + SelectObject(dis->hDC, hOldFont); + } return TRUE; } } - return Menu_MeasureItem(lParam); + break; case WM_NCHITTEST: SendMessage(m_pContainer->m_hwnd, WM_NCHITTEST, wParam, lParam); break; - case WM_DRAWITEM: - return MsgWindowDrawHandler((DRAWITEMSTRUCT*)lParam); - case WM_APPCOMMAND: { DWORD cmd = GET_APPCOMMAND_LPARAM(lParam); @@ -2819,7 +3278,10 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) break; case DM_SMILEYOPTIONSCHANGED: - SendMessage(m_hwnd, DM_REMAKELOG, 0, 0); + if (isChat()) + RedrawLog(); + else + SendMessage(m_hwnd, DM_REMAKELOG, 0, 0); break; case DM_MYAVATARCHANGED: @@ -2982,6 +3444,119 @@ INT_PTR CSrmmWindow::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) case DM_CHECKINFOTIP: m_pPanel.hideTip(reinterpret_cast(lParam)); return 0; + + case DM_SETINFOPANEL: // broadcasted when global info panel setting changes + if (wParam == 0 && lParam == 0) { + m_pPanel.getVisibility(); + m_pPanel.loadHeight(); + m_pPanel.showHide(); + } + else { + CMsgDialog *srcDat = (CMsgDialog *)wParam; + if (lParam == 0) + m_pPanel.loadHeight(); + else { + if (srcDat && lParam && this != srcDat && !m_pPanel.isPrivateHeight()) { + if (srcDat->isChat() != isChat() && M.GetByte("syncAllPanels", 0) == 0) + return 0; + + if (m_pContainer->m_pSettings->fPrivate && srcDat->m_pContainer != m_pContainer) + return 0; + + m_pPanel.setHeight((LONG)lParam); + } + } + Resize(); + } + return 0; + + case DM_STATUSICONCHANGE: + m_pContainer->InitRedraw(); + return 0; + + case DM_ACTIVATEME: // the child window will activate itself + ActivateExistingTab(m_pContainer, m_hwnd); + return 0; + + case DM_QUERYCONTAINER: // container API support functions + if (lParam) + *(TContainerData **)lParam = m_pContainer; + return 0; + + case DM_QUERYHCONTACT: + if (lParam) + *(MCONTACT *)lParam = m_hContact; + return 0; + + case DM_CHECKSIZE: + m_dwFlags |= MWF_NEEDCHECKSIZE; + return 0; + + case DM_CONTAINERSELECTED: + // sent by the select container dialog box when a container was selected... + // lParam = (wchar_t*)selected name... + { + wchar_t *szNewName = (wchar_t *)lParam; + if (!mir_wstrcmp(szNewName, TranslateT("Default container"))) + szNewName = CGlobals::m_default_container_name; + + int iOldItems = TabCtrl_GetItemCount(m_hwndParent); + if (!wcsncmp(m_pContainer->m_wszName, szNewName, CONTAINER_NAMELEN)) + break; + + TContainerData *pNewContainer = FindContainerByName(szNewName); + if (pNewContainer == nullptr) + if ((pNewContainer = CreateContainer(szNewName, FALSE, m_hContact)) == nullptr) + break; + + db_set_ws(m_hContact, SRMSGMOD_T, "containerW", szNewName); + PostMessage(PluginConfig.g_hwndHotkeyHandler, DM_DOCREATETAB, (WPARAM)pNewContainer, m_hContact); + if (iOldItems > 1) // there were more than 1 tab, container is still valid + SendMessage(m_pContainer->m_hwndActive, WM_SIZE, 0, 0); + SetForegroundWindow(pNewContainer->m_hwnd); + SetActiveWindow(pNewContainer->m_hwnd); + } + return 0; + + case DM_ACTIVATETOOLTIP: + // show the balloon tooltip control. + // wParam == id of the "anchor" element, defaults to the panel status field (for away msg retrieval) + // lParam == new text to show + if (!IsIconic(m_pContainer->m_hwnd) && m_pContainer->m_hwndActive == m_hwnd) + m_pPanel.showTip(wParam, lParam); + return 0; + + case DM_STATUSBARCHANGED: + tabUpdateStatusBar(); + break; + + case DM_CHECKAUTOHIDE: + // This is broadcasted by the container to all child windows to check if the + // container can be autohidden or -closed. + // + // wParam is the autohide timeout (in seconds) + // lParam points to a BOOL and a session which wants to prevent auto-hiding + // the container must set it to FALSE. + // + // If no session in the container disagrees, the container will be hidden. + + if (lParam) { + BOOL *fResult = (BOOL *)lParam; + // text entered in the input area -> prevent autohide/cose + if (GetWindowTextLength(m_message.GetHwnd()) > 0) + *fResult = FALSE; + // unread events, do not hide or close the container + else if (m_dwUnread) + *fResult = FALSE; + // time since last activity did not yet reach the threshold. + else if (((GetTickCount() - m_dwLastActivity) / 1000) <= wParam) + *fResult = FALSE; + } + return 0; + + case DM_SPLITTERGLOBALEVENT: + DM_SplitterGlobalEvent(wParam, lParam); + return 0; } return CSuper::DlgProc(uMsg, wParam, lParam); diff --git a/plugins/TabSRMM/src/msgdlgother.cpp b/plugins/TabSRMM/src/msgdlgother.cpp new file mode 100644 index 0000000000..7a24071d4d --- /dev/null +++ b/plugins/TabSRMM/src/msgdlgother.cpp @@ -0,0 +1,1986 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Miranda NG: the free IM client for Microsoft* Windows* +// +// Copyright (C) 2012-19 Miranda NG team, +// Copyright (c) 2000-09 Miranda ICQ/IM project, +// 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. +// +// part of tabSRMM messaging plugin for Miranda. +// +// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors +// +// Helper functions for the message dialog. + +#include "stdafx.h" + +UINT_PTR CALLBACK OpenFileSubclass(HWND hwnd, UINT msg, WPARAM, LPARAM lParam); + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::AddLog() +{ + if (PluginConfig.m_bUseDividers) { + if (PluginConfig.m_bDividersUsePopupConfig) { + if (!MessageWindowOpened(0, m_hwnd)) + DM_AddDivider(); + } + else { + bool bInactive = !IsActive(); + if (bInactive) + DM_AddDivider(); + else if (m_pContainer->m_hwndActive != m_hwnd) + DM_AddDivider(); + } + } + + CSrmmBaseDialog::AddLog(); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::AdjustBottomAvatarDisplay() +{ + GetAvatarVisibility(); + + bool bInfoPanel = m_pPanel.isActive(); + HBITMAP hbm = (bInfoPanel && m_pContainer->m_avatarMode != 3) ? m_hOwnPic : (m_ace ? m_ace->hbmPic : PluginConfig.g_hbmUnknown); + if (hbm) { + if (m_dynaSplitter == 0 || m_iSplitterY == 0) + LoadSplitter(); + m_dynaSplitter = m_iSplitterY - DPISCALEY_S(34); + DM_RecalcPictureSize(); + Utils::showDlgControl(m_hwnd, IDC_CONTACTPIC, m_bShowAvatar ? SW_SHOW : SW_HIDE); + InvalidateRect(GetDlgItem(m_hwnd, IDC_CONTACTPIC), nullptr, TRUE); + } + else { + Utils::showDlgControl(m_hwnd, IDC_CONTACTPIC, m_bShowAvatar ? SW_SHOW : SW_HIDE); + m_pic.cy = m_pic.cx = DPISCALEY_S(60); + InvalidateRect(GetDlgItem(m_hwnd, IDC_CONTACTPIC), nullptr, TRUE); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// calculates avatar layouting, based on splitter position to find the optimal size +// for the avatar w/o disturbing the toolbar too much. + +void CMsgDialog::CalcDynamicAvatarSize(BITMAP *bminfo) +{ + if (m_dwFlags & MWF_WASBACKGROUNDCREATE || m_pContainer->m_dwFlags & CNT_DEFERREDCONFIGURE || m_pContainer->m_dwFlags & CNT_CREATE_MINIMIZED || IsIconic(m_pContainer->m_hwnd)) + return; // at this stage, the layout is not yet ready... + + RECT rc; + GetClientRect(m_hwnd, &rc); + + BOOL bBottomToolBar = m_pContainer->m_dwFlags & CNT_BOTTOMTOOLBAR; + BOOL bToolBar = m_pContainer->m_dwFlags & CNT_HIDETOOLBAR ? 0 : 1; + int iSplitOffset = m_bIsAutosizingInput ? 1 : 0; + + double picAspect = (bminfo->bmWidth == 0 || bminfo->bmHeight == 0) ? 1.0 : (double)(bminfo->bmWidth / (double)bminfo->bmHeight); + double picProjectedWidth = (double)((m_dynaSplitter - ((bBottomToolBar && bToolBar) ? DPISCALEX_S(24) : 0) + ((m_bShowUIElements) ? DPISCALEX_S(28) : DPISCALEX_S(2)))) * picAspect; + + if ((rc.right - (int)picProjectedWidth) > (m_iButtonBarReallyNeeds) && !PluginConfig.m_bAlwaysFullToolbarWidth && bToolBar) + m_iRealAvatarHeight = m_dynaSplitter + 3 + (m_bShowUIElements ? DPISCALEY_S(28) : DPISCALEY_S(2)); + else + m_iRealAvatarHeight = m_dynaSplitter + DPISCALEY_S(6) + DPISCALEY_S(iSplitOffset); + + m_iRealAvatarHeight -= ((bBottomToolBar && bToolBar) ? DPISCALEY_S(22) : 0); + + if (PluginConfig.m_LimitStaticAvatarHeight > 0) + m_iRealAvatarHeight = min(m_iRealAvatarHeight, PluginConfig.m_LimitStaticAvatarHeight); + + if (M.GetByte(m_hContact, "dontscaleavatars", M.GetByte("dontscaleavatars", 0))) + m_iRealAvatarHeight = min(bminfo->bmHeight, m_iRealAvatarHeight); + + double aspect = (bminfo->bmHeight != 0) ? (double)m_iRealAvatarHeight / (double)bminfo->bmHeight : 1.0; + double newWidth = (double)bminfo->bmWidth * aspect; + if (newWidth > (double)(rc.right) * 0.8) + newWidth = (double)(rc.right) * 0.8; + m_pic.cy = m_iRealAvatarHeight + 2; + m_pic.cx = (int)newWidth + 2; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::CloseTab() +{ + int iTabs = TabCtrl_GetItemCount(m_hwndParent); + if (iTabs == 1) { + SendMessage(m_pContainer->m_hwnd, WM_CLOSE, 0, 1); + return; + } + + m_pContainer->m_iChilds--; + int i = GetTabIndexFromHWND(m_hwndParent, m_hwnd); + + // after closing a tab, we need to activate the tab to the left side of + // the previously open tab. + // normally, this tab has the same index after the deletion of the formerly active tab + // unless, of course, we closed the last (rightmost) tab. + if (!m_pContainer->m_bDontSmartClose && iTabs > 1) { + if (i == iTabs - 1) + i--; + else + i++; + TabCtrl_SetCurSel(m_hwndParent, i); + + m_pContainer->m_hwndActive = GetTabWindow(m_hwndParent, i); + + RECT rc; + SendMessage(m_pContainer->m_hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)& rc); + SetWindowPos(m_pContainer->m_hwndActive, HWND_TOP, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), SWP_SHOWWINDOW); + ShowWindow(m_pContainer->m_hwndActive, SW_SHOW); + SetForegroundWindow(m_pContainer->m_hwndActive); + SetFocus(m_pContainer->m_hwndActive); + } + + SendMessage(m_pContainer->m_hwnd, WM_SIZE, 0, 0); + DestroyWindow(m_hwnd); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// calculate the minimum required client height for the given message +// window layout +// +// the container will use this in its WM_GETMINMAXINFO handler to set +// minimum tracking height. + +void CMsgDialog::DetermineMinHeight() +{ + RECT rc; + LONG height = (m_pPanel.isActive() ? m_pPanel.getHeight() + 2 : 0); + if (!(m_pContainer->m_dwFlags & CNT_HIDETOOLBAR)) + height += DPISCALEY_S(24); // toolbar + GetClientRect(m_message.GetHwnd(), &rc); + height += rc.bottom; // input area + height += 40; // min space for log area and some padding + + m_pContainer->m_uChildMinHeight = height; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// convert rich edit code to bbcode (if wanted). Otherwise, strip all RTF formatting +// tags and return plain text + +static wchar_t tszRtfBreaks[] = L" \\\n\r"; + +static void CreateColorMap(CMStringW &Text, int iCount, COLORREF *pSrc, int *pDst) +{ + const wchar_t *pszText = Text; + int iIndex = 1; + + static const wchar_t *lpszFmt = L"\\red%[^ \x5b\\]\\green%[^ \x5b\\]\\blue%[^ \x5b;];"; + wchar_t szRed[10], szGreen[10], szBlue[10]; + + const wchar_t *p1 = wcsstr(pszText, L"\\colortbl"); + if (!p1) + return; + + const wchar_t *pEnd = wcschr(p1, '}'); + + const wchar_t *p2 = wcsstr(p1, L"\\red"); + + for (int i = 0; i < iCount; i++) + pDst[i] = -1; + + while (p2 && p2 < pEnd) { + if (swscanf(p2, lpszFmt, &szRed, &szGreen, &szBlue) > 0) { + for (int i = 0; i < iCount; i++) { + if (pSrc[i] == RGB(_wtoi(szRed), _wtoi(szGreen), _wtoi(szBlue))) + pDst[i] = iIndex; + } + } + iIndex++; + p1 = p2; + p1++; + + p2 = wcsstr(p1, L"\\red"); + } +} + +static int RtfColorToIndex(int iNumColors, int *pIndex, int iCol) +{ + for (int i = 0; i < iNumColors; i++) + if (pIndex[i] == iCol) + return i; + + return -1; +} + +BOOL CMsgDialog::DoRtfToTags(CMStringW &pszText) const +{ + if (pszText.IsEmpty()) + return FALSE; + + // used to filter out attributes which are already set for the default message input area font + LOGFONTA lf = m_pContainer->m_theme.logFonts[MSGFONTID_MESSAGEAREA]; + + // create an index of colors in the module and map them to + // corresponding colors in the RTF color table + int iNumColors = Utils::rtf_clrs.getCount(); + int *pIndex = (int *)_alloca(iNumColors * sizeof(int)); + COLORREF *pColors = (COLORREF *)_alloca(iNumColors * sizeof(COLORREF)); + for (int i = 0; i < iNumColors; i++) + pColors[i] = Utils::rtf_clrs[i].clr; + CreateColorMap(pszText, iNumColors, pColors, pIndex); + + // scan the file for rtf commands and remove or parse them + int idx = pszText.Find(L"\\pard"); + if (idx == -1) { + if ((idx = pszText.Find(L"\\ltrpar")) == -1) + return FALSE; + idx += 7; + } + else idx += 5; + + MODULEINFO *mi = (isChat()) ? m_si->pMI : nullptr; + + bool bInsideColor = false, bInsideUl = false; + CMStringW res; + + // iterate through all characters, if rtf control character found then take action + for (const wchar_t *p = pszText.GetString() + idx; *p;) { + switch (*p) { + case '\\': + if (p[1] == '\\' || p[1] == '{' || p[1] == '}') { // escaped characters + res.AppendChar(p[1]); + p += 2; break; + } + if (p[1] == '~') { // non-breaking space + res.AppendChar(0xA0); + p += 2; break; + } + + if (!wcsncmp(p, L"\\cf", 3)) { // foreground color + int iCol = _wtoi(p + 3); + int iInd = RtfColorToIndex(iNumColors, pIndex, iCol); + + if (iCol > 0) { + if (isChat()) { + if (mi && mi->bColor) { + if (iInd >= 0) { + if (!(res.IsEmpty() && m_pContainer->m_theme.fontColors[MSGFONTID_MESSAGEAREA] == pColors[iInd])) + res.AppendFormat(L"%%c%u", iInd); + } + else if (!res.IsEmpty()) + res.Append(L"%%C"); + } + } + else res.AppendFormat((iInd >= 0) ? (bInsideColor ? L"[/color][color=%s]" : L"[color=%s]") : (bInsideColor ? L"[/color]" : L""), Utils::rtf_clrs[iInd].szName); + } + + bInsideColor = iInd >= 0; + } + else if (!wcsncmp(p, L"\\highlight", 10)) { // background color + if (isChat()) { + if (mi && mi->bBkgColor) { + int iInd = RtfColorToIndex(iNumColors, pIndex, _wtoi(p + 10)); + if (iInd >= 0) { + // if the entry field is empty & the color passed is the back color, skip it + if (!(res.IsEmpty() && m_pContainer->m_theme.inputbg == pColors[iInd])) + res.AppendFormat(L"%%f%u", iInd); + } + else if (!res.IsEmpty()) + res.AppendFormat(L"%%F"); + } + } + } + else if (!wcsncmp(p, L"\\line", 5)) { // soft line break; + res.AppendChar('\n'); + } + else if (!wcsncmp(p, L"\\endash", 7)) { + res.AppendChar(0x2013); + } + else if (!wcsncmp(p, L"\\emdash", 7)) { + res.AppendChar(0x2014); + } + else if (!wcsncmp(p, L"\\bullet", 7)) { + res.AppendChar(0x2022); + } + else if (!wcsncmp(p, L"\\ldblquote", 10)) { + res.AppendChar(0x201C); + } + else if (!wcsncmp(p, L"\\rdblquote", 10)) { + res.AppendChar(0x201D); + } + else if (!wcsncmp(p, L"\\lquote", 7)) { + res.AppendChar(0x2018); + } + else if (!wcsncmp(p, L"\\rquote", 7)) { + res.AppendChar(0x2019); + } + else if (!wcsncmp(p, L"\\b", 2)) { //bold + if (isChat()) { + if (mi && mi->bBold) + res.Append((p[2] != '0') ? L"%b" : L"%B"); + } + else { + if (!(lf.lfWeight == FW_BOLD)) // only allow bold if the font itself isn't a bold one, otherwise just strip it.. + if (m_SendFormat) + res.Append((p[2] != '0') ? L"[b]" : L"[/b]"); + } + } + else if (!wcsncmp(p, L"\\i", 2)) { // italics + if (isChat()) { + if (mi && mi->bItalics) + res.Append((p[2] != '0') ? L"%i" : L"%I"); + } + else { + if (!lf.lfItalic && m_SendFormat) + res.Append((p[2] != '0') ? L"[i]" : L"[/i]"); + } + } + else if (!wcsncmp(p, L"\\strike", 7)) { // strike-out + if (!lf.lfStrikeOut && m_SendFormat) + res.Append((p[7] != '0') ? L"[s]" : L"[/s]"); + } + else if (!wcsncmp(p, L"\\ul", 3)) { // underlined + if (isChat()) { + if (mi && mi->bUnderline) + res.Append((p[3] != '0') ? L"%u" : L"%U"); + } + else { + if (!lf.lfUnderline && m_SendFormat) { + if (p[3] == 0 || wcschr(tszRtfBreaks, p[3])) { + res.Append(L"[u]"); + bInsideUl = true; + } + else if (!wcsncmp(p + 3, L"none", 4)) { + if (bInsideUl) + res.Append(L"[/u]"); + bInsideUl = false; + } + } + } + } + else if (!wcsncmp(p, L"\\tab", 4)) { // tab + res.AppendChar('\t'); + } + else if (p[1] == '\'') { // special character + if (p[2] != ' ' && p[2] != '\\') { + wchar_t tmp[10]; + + if (p[3] != ' ' && p[3] != '\\') { + wcsncpy(tmp, p + 2, 3); + tmp[3] = 0; + } + else { + wcsncpy(tmp, p + 2, 2); + tmp[2] = 0; + } + + // convert string containing char in hex format to int. + wchar_t *stoppedHere; + res.AppendChar(wcstol(tmp, &stoppedHere, 16)); + } + } + + p++; // skip initial slash + p += wcscspn(p, tszRtfBreaks); + if (*p == ' ') + p++; + break; + + case '{': // other RTF control characters + case '}': + p++; + break; + + case '%': // double % for stupid chat engine + if (isChat()) + res.Append(L"%%"); + else + res.AppendChar(*p); + p++; + break; + + default: // other text that should not be touched + res.AppendChar(*p++); + break; + } + } + + if (bInsideColor && !isChat()) + res.Append(L"[/color]"); + if (bInsideUl) + res.Append(L"[/u]"); + + pszText = res; + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::EnableSendButton(bool bMode) const +{ + SendDlgItemMessage(m_hwnd, IDOK, BUTTONSETASNORMAL, bMode, 0); + SendDlgItemMessage(m_hwnd, IDC_PIC, BUTTONSETASNORMAL, m_bEditNotesActive ? TRUE : (!bMode && m_iOpenJobs == 0) ? TRUE : FALSE, 0); + + HWND hwndOK = GetDlgItem(GetParent(GetParent(m_hwnd)), IDOK); + if (IsWindow(hwndOK)) + SendMessage(hwndOK, BUTTONSETASNORMAL, bMode, 0); +} + +void CMsgDialog::EnableSending(bool bMode) const +{ + m_message.SendMsg(EM_SETREADONLY, !bMode, 0); + Utils::enableDlgControl(m_hwnd, IDC_CLIST, bMode); + EnableSendButton(bMode); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::FindFirstEvent() +{ + int historyMode = g_plugin.getByte(m_hContact, SRMSGSET_LOADHISTORY, -1); + if (historyMode == -1) + historyMode = (int)g_plugin.getByte(SRMSGSET_LOADHISTORY, SRMSGDEFSET_LOADHISTORY); + + m_hDbEventFirst = db_event_firstUnread(m_hContact); + + if (m_bActualHistory) + historyMode = LOADHISTORY_COUNT; + + switch (historyMode) { + case LOADHISTORY_COUNT: + int i; + MEVENT hPrevEvent; + { + DBEVENTINFO dbei = {}; + // ability to load only current session's history + if (m_bActualHistory) + i = m_cache->getSessionMsgCount(); + else + i = g_plugin.getWord(SRMSGSET_LOADCOUNT, SRMSGDEFSET_LOADCOUNT); + + for (; i > 0; i--) { + if (m_hDbEventFirst == 0) + hPrevEvent = db_event_last(m_hContact); + else + hPrevEvent = db_event_prev(m_hContact, m_hDbEventFirst); + if (hPrevEvent == 0) + break; + dbei.cbBlob = 0; + m_hDbEventFirst = hPrevEvent; + db_event_get(m_hDbEventFirst, &dbei); + if (!DbEventIsShown(&dbei)) + i++; + } + } + break; + + case LOADHISTORY_TIME: + DBEVENTINFO dbei = {}; + if (m_hDbEventFirst == 0) + dbei.timestamp = time(0); + else + db_event_get(m_hDbEventFirst, &dbei); + + DWORD firstTime = dbei.timestamp - 60 * g_plugin.getWord(SRMSGSET_LOADTIME, SRMSGDEFSET_LOADTIME); + for (;;) { + if (m_hDbEventFirst == 0) + hPrevEvent = db_event_last(m_hContact); + else + hPrevEvent = db_event_prev(m_hContact, m_hDbEventFirst); + if (hPrevEvent == 0) + break; + dbei.cbBlob = 0; + db_event_get(hPrevEvent, &dbei); + if (dbei.timestamp < firstTime) + break; + m_hDbEventFirst = hPrevEvent; + } + break; + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::FlashOnClist(MEVENT hEvent, DBEVENTINFO *dbei) +{ + m_dwTickLastEvent = GetTickCount(); + + if ((GetForegroundWindow() != m_pContainer->m_hwnd || m_pContainer->m_hwndActive != m_hwnd) && !(dbei->flags & DBEF_SENT) && dbei->eventType == EVENTTYPE_MESSAGE) { + m_dwUnread++; + UpdateTrayMenu(this, (WORD)(m_cache->getActiveStatus()), m_cache->getActiveProto(), m_wszStatus, m_hContact, 0); + if (nen_options.bTraySupport) + return; + } + if (hEvent == 0) + return; + + if (!PluginConfig.m_bFlashOnClist) + return; + + if ((GetForegroundWindow() != m_pContainer->m_hwnd || m_pContainer->m_hwndActive != m_hwnd) && !(dbei->flags & DBEF_SENT) && dbei->eventType == EVENTTYPE_MESSAGE && !(m_dwFlagsEx & MWF_SHOW_FLASHCLIST)) { + CLISTEVENT cle = {}; + cle.hContact = m_hContact; + cle.hDbEvent = hEvent; + cle.hIcon = Skin_LoadIcon(SKINICON_EVENT_MESSAGE); + cle.pszService = MS_MSG_READMESSAGE; + g_clistApi.pfnAddEvent(&cle); + + m_dwFlagsEx |= MWF_SHOW_FLASHCLIST; + m_hFlashingEvent = hEvent; + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// flash a tab icon if mode = true, otherwise restore default icon +// store flashing state into bState + +void CMsgDialog::FlashTab(bool bInvertMode) +{ + if (bInvertMode) + m_bTabFlash = !m_bTabFlash; + + TCITEM item = {}; + item.mask = TCIF_IMAGE; + TabCtrl_SetItem(m_hwndParent, m_iTabID, &item); + if (m_pContainer->m_dwFlags & CNT_SIDEBAR) + m_pContainer->m_pSideBar->updateSession(this); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// retrieve the visiblity of the avatar window, depending on the global setting +// and local mode + +bool CMsgDialog::GetAvatarVisibility() +{ + BYTE bAvatarMode = m_pContainer->m_avatarMode; + BYTE bOwnAvatarMode = m_pContainer->m_ownAvatarMode; + char hideOverride = (char)M.GetByte(m_hContact, "hideavatar", -1); + + // infopanel visible, consider own avatar display + m_bShowAvatar = false; + if (m_si) + return false; + + if (m_pPanel.isActive() && bAvatarMode != 3) { + if (!bOwnAvatarMode) { + m_bShowAvatar = (m_hOwnPic && m_hOwnPic != PluginConfig.g_hbmUnknown); + if (!m_hwndContactPic) + m_hwndContactPic = CreateWindowEx(WS_EX_TOPMOST, AVATAR_CONTROL_CLASS, L"", WS_VISIBLE | WS_CHILD, 1, 1, 1, 1, GetDlgItem(m_hwnd, IDC_CONTACTPIC), (HMENU)nullptr, nullptr, nullptr); + } + + switch (bAvatarMode) { + case 2: + m_bShowInfoAvatar = false; + break; + case 0: + m_bShowInfoAvatar = true; + case 1: + HBITMAP hbm = ((m_ace && !(m_ace->dwFlags & AVS_HIDEONCLIST)) ? m_ace->hbmPic : nullptr); + if (hbm == nullptr && !bAvatarMode) { + m_bShowInfoAvatar = false; + break; + } + + if (!m_hwndPanelPic) { + m_hwndPanelPic = CreateWindowEx(WS_EX_TOPMOST, AVATAR_CONTROL_CLASS, L"", WS_VISIBLE | WS_CHILD, 1, 1, 1, 1, m_hwndPanelPicParent, (HMENU)7000, nullptr, nullptr); + if (m_hwndPanelPic) + SendMessage(m_hwndPanelPic, AVATAR_SETAEROCOMPATDRAWING, 0, TRUE); + } + + if (bAvatarMode != 0) + m_bShowInfoAvatar = (hbm && hbm != PluginConfig.g_hbmUnknown); + break; + } + + if (m_bShowInfoAvatar) + m_bShowInfoAvatar = hideOverride == 0 ? false : m_bShowInfoAvatar; + else + m_bShowInfoAvatar = hideOverride == 1 ? true : m_bShowInfoAvatar; + + Utils::setAvatarContact(m_hwndPanelPic, m_hContact); + SendMessage(m_hwndContactPic, AVATAR_SETPROTOCOL, 0, (LPARAM)m_cache->getActiveProto()); + } + else { + m_bShowInfoAvatar = false; + + switch (bAvatarMode) { + case 0: // globally on + m_bShowAvatar = true; + LBL_Check: + if (!m_hwndContactPic) + m_hwndContactPic = CreateWindowEx(WS_EX_TOPMOST, AVATAR_CONTROL_CLASS, L"", WS_VISIBLE | WS_CHILD, 1, 1, 1, 1, GetDlgItem(m_hwnd, IDC_CONTACTPIC), (HMENU)nullptr, nullptr, nullptr); + break; + case 2: // globally OFF + m_bShowAvatar = false; + break; + case 3: // on, if present + case 1: + HBITMAP hbm = (m_ace && !(m_ace->dwFlags & AVS_HIDEONCLIST)) ? m_ace->hbmPic : nullptr; + m_bShowAvatar = (hbm && hbm != PluginConfig.g_hbmUnknown); + goto LBL_Check; + } + + if (m_bShowAvatar) + m_bShowAvatar = hideOverride == 0 ? 0 : m_bShowAvatar; + else + m_bShowAvatar = hideOverride == 1 ? 1 : m_bShowAvatar; + + // reloads avatars + if (m_hwndPanelPic) { // shows contact or user picture, depending on panel visibility + SendMessage(m_hwndContactPic, AVATAR_SETPROTOCOL, 0, (LPARAM)m_cache->getActiveProto()); + Utils::setAvatarContact(m_hwndPanelPic, m_hContact); + } + else Utils::setAvatarContact(m_hwndContactPic, m_hContact); + } + return m_bShowAvatar; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::GetClientIcon() +{ + if (m_hClientIcon) + DestroyIcon(m_hClientIcon); + + m_hClientIcon = nullptr; + if (ServiceExists(MS_FP_GETCLIENTICONT)) { + ptrW tszMirver(db_get_wsa(m_cache->getActiveContact(), m_cache->getActiveProto(), "MirVer")); + if (tszMirver) + m_hClientIcon = Finger_GetClientIcon(tszMirver, 1); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +LONG CMsgDialog::GetDefaultMinimumInputHeight() const +{ + LONG height = (m_pContainer->m_dwFlags & CNT_BOTTOMTOOLBAR) ? DPISCALEY_S(46 + 22) : DPISCALEY_S(46); + + if (CSkin::m_skinEnabled && !SkinItems[ID_EXTBKINPUTAREA].IGNORED) + height += (SkinItems[ID_EXTBKINPUTAREA].MARGIN_BOTTOM + SkinItems[ID_EXTBKINPUTAREA].MARGIN_TOP - 2); + + return height; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +HICON CMsgDialog::GetMyContactIcon(LPCSTR szSetting) +{ + int bUseMeta = (szSetting == nullptr) ? false : M.GetByte(szSetting, mir_strcmp(szSetting, "MetaiconTab") == 0); + if (bUseMeta) + return Skin_LoadProtoIcon(m_cache->getProto(), m_cache->getStatus()); + return Skin_LoadProtoIcon(m_cache->getActiveProto(), m_cache->getActiveStatus()); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::GetMyNick() +{ + ptrW tszNick(Contact_GetInfo(CNF_CUSTOMNICK, 0, m_cache->getActiveProto())); + if (tszNick == nullptr) + tszNick = Contact_GetInfo(CNF_NICK, 0, m_cache->getActiveProto()); + if (tszNick != nullptr) { + if (mir_wstrlen(tszNick) == 0 || !mir_wstrcmp(tszNick, TranslateT("'(Unknown contact)'"))) + wcsncpy_s(m_wszMyNickname, (m_myUin[0] ? m_myUin : TranslateT("'(Unknown contact)'")), _TRUNCATE); + else + wcsncpy_s(m_wszMyNickname, tszNick, _TRUNCATE); + } + else wcsncpy_s(m_wszMyNickname, L"", _TRUNCATE); // same here +} + +///////////////////////////////////////////////////////////////////////////////////////// +// retrieve both buddys and my own UIN for a message session and store them in the message window *dat +// respects metacontacts and uses the current protocol if the contact is a MC + +void CMsgDialog::GetMYUIN() +{ + ptrW uid(Contact_GetInfo(CNF_DISPLAYUID, 0, m_cache->getActiveProto())); + if (uid != nullptr) + wcsncpy_s(m_myUin, uid, _TRUNCATE); + else + m_myUin[0] = 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// reads send format and configures the toolbar buttons +// if mode == 0, int only configures the buttons and does not change send format + +void CMsgDialog::GetSendFormat() +{ + m_SendFormat = M.GetDword(m_hContact, "sendformat", PluginConfig.m_SendFormat); + if (m_SendFormat == -1) // per contact override to disable it.. + m_SendFormat = 0; + else if (m_SendFormat == 0) + m_SendFormat = PluginConfig.m_SendFormat ? 1 : 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +HICON CMsgDialog::GetXStatusIcon() const +{ + BYTE xStatus = m_cache->getXStatusId(); + if (xStatus == 0) + return nullptr; + + if (!ProtoServiceExists(m_cache->getActiveProto(), PS_GETCUSTOMSTATUSICON)) + return nullptr; + + return (HICON)(CallProtoService(m_cache->getActiveProto(), PS_GETCUSTOMSTATUSICON, xStatus, 0)); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// paste contents of the clipboard into the message input area and send it immediately + +void CMsgDialog::HandlePasteAndSend() +{ + // is feature disabled? + if (!PluginConfig.m_PasteAndSend) { + SendMessage(m_hwnd, DM_ACTIVATETOOLTIP, IDC_SRMM_MESSAGE, (LPARAM)TranslateT("The 'paste and send' feature is disabled. You can enable it on the 'General' options page in the 'Sending messages' section")); + return; + } + + m_message.SendMsg(EM_PASTESPECIAL, CF_UNICODETEXT, 0); + if (GetWindowTextLength(m_message.GetHwnd()) > 0) + SendMessage(m_hwnd, WM_COMMAND, IDOK, 0); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +bool CMsgDialog::IsAutoSplitEnabled() const +{ + return (m_pContainer->m_dwFlags & CNT_AUTOSPLITTER) && !(m_dwFlagsEx & MWF_SHOW_SPLITTEROVERRIDE); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// read keyboard state and return the state of the modifier keys + +void CMsgDialog::KbdState(bool &isShift, bool &isControl, bool &isAlt) +{ + GetKeyboardState(kstate); + isShift = (kstate[VK_SHIFT] & 0x80) != 0; + isControl = (kstate[VK_CONTROL] & 0x80) != 0; + isAlt = (kstate[VK_MENU] & 0x80) != 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::LimitMessageText(int iLen) +{ + if (this != nullptr) + m_message.SendMsg(EM_EXLIMITTEXT, 0, iLen); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::LoadContactAvatar() +{ + m_ace = Utils::loadAvatarFromAVS(m_bIsMeta ? db_mc_getSrmmSub(m_hContact) : m_hContact); + + BITMAP bm; + if (m_ace && m_ace->hbmPic) + GetObject(m_ace->hbmPic, sizeof(bm), &bm); + else if (m_ace == nullptr) + GetObject(PluginConfig.g_hbmUnknown, sizeof(bm), &bm); + else + return; + + AdjustBottomAvatarDisplay(); + CalcDynamicAvatarSize(&bm); + + if (!m_pPanel.isActive() || m_pContainer->m_avatarMode == 3) { + m_iRealAvatarHeight = 0; + PostMessage(m_hwnd, WM_SIZE, 0, 0); + } + else if (m_pPanel.isActive()) + GetAvatarVisibility(); + + if (m_pWnd != nullptr) + m_pWnd->verifyDwmState(); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::LoadOwnAvatar() +{ + if (ServiceExists(MS_AV_GETMYAVATAR)) + m_ownAce = (AVATARCACHEENTRY *)CallService(MS_AV_GETMYAVATAR, 0, (LPARAM)(m_cache->getActiveProto())); + else + m_ownAce = nullptr; + + if (m_ownAce) + m_hOwnPic = m_ownAce->hbmPic; + else + m_hOwnPic = PluginConfig.g_hbmUnknown; + + if (m_pPanel.isActive() && m_pContainer->m_avatarMode != 3) { + BITMAP bm; + + m_iRealAvatarHeight = 0; + AdjustBottomAvatarDisplay(); + GetObject(m_hOwnPic, sizeof(bm), &bm); + CalcDynamicAvatarSize(&bm); + Resize(); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::LoadSettings() +{ + m_clrInputBG = m_pContainer->m_theme.inputbg; + LoadLogfont(FONTSECTION_IM, MSGFONTID_MESSAGEAREA, nullptr, &m_clrInputFG, FONTMODULE); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::LoadSplitter() +{ + if (m_bIsAutosizingInput) { + m_iSplitterY = GetDefaultMinimumInputHeight(); + return; + } + + if (!(m_dwFlagsEx & MWF_SHOW_SPLITTEROVERRIDE)) { + if (!m_pContainer->m_pSettings->fPrivate) + m_iSplitterY = (int)M.GetDword("splitsplity", 60); + else + m_iSplitterY = m_pContainer->m_pSettings->iSplitterY; + } + else m_iSplitterY = (int)M.GetDword(m_hContact, "splitsplity", M.GetDword("splitsplity", 60)); + + if (m_iSplitterY < MINSPLITTERY) + m_iSplitterY = 150; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// draw various elements of the message window, like avatar(s), info panel fields +// and the color formatting menu + +int CMsgDialog::MsgWindowDrawHandler(DRAWITEMSTRUCT *dis) +{ + HBITMAP hbmAvatar = m_ace ? m_ace->hbmPic : PluginConfig.g_hbmUnknown; + if ((dis->hwndItem == GetDlgItem(m_hwnd, IDC_CONTACTPIC) && m_bShowAvatar) || (dis->hwndItem == m_hwnd && m_pPanel.isActive())) { + if (hbmAvatar == nullptr) + return TRUE; + + int top, cx, cy; + RECT rcClient, rcFrame; + bool bPanelPic = (dis->hwndItem == m_hwnd); + if (bPanelPic && !m_bShowInfoAvatar) + return TRUE; + + RECT rc; + GetClientRect(m_hwnd, &rc); + if (bPanelPic) { + rcClient = dis->rcItem; + cx = (rcClient.right - rcClient.left); + cy = (rcClient.bottom - rcClient.top) + 1; + } + else { + GetClientRect(dis->hwndItem, &rcClient); + cx = rcClient.right; + cy = rcClient.bottom; + } + + if (cx < 5 || cy < 5) + return TRUE; + + HDC hdcDraw = CreateCompatibleDC(dis->hDC); + HBITMAP hbmDraw = CreateCompatibleBitmap(dis->hDC, cx, cy); + HBITMAP hbmOld = (HBITMAP)SelectObject(hdcDraw, hbmDraw); + + bool bAero = M.isAero(); + + HRGN clipRgn = nullptr; + HBRUSH hOldBrush = (HBRUSH)SelectObject(hdcDraw, bAero ? (HBRUSH)GetStockObject(HOLLOW_BRUSH) : GetSysColorBrush(COLOR_3DFACE)); + rcFrame = rcClient; + + if (!bPanelPic) { + top = (cy - m_pic.cy) / 2; + RECT rcEdge = { 0, top, m_pic.cx, top + m_pic.cy }; + if (CSkin::m_skinEnabled) + CSkin::SkinDrawBG(dis->hwndItem, m_pContainer->m_hwnd, m_pContainer, &dis->rcItem, hdcDraw); + else if (PluginConfig.m_fillColor) { + HBRUSH br = CreateSolidBrush(PluginConfig.m_fillColor); + FillRect(hdcDraw, &rcFrame, br); + DeleteObject(br); + } + else if (bAero && CSkin::m_pCurrentAeroEffect) { + COLORREF clr = PluginConfig.m_tbBackgroundHigh ? PluginConfig.m_tbBackgroundHigh : + (CSkin::m_pCurrentAeroEffect ? CSkin::m_pCurrentAeroEffect->m_clrToolbar : 0xf0f0f0); + + HBRUSH br = CreateSolidBrush(clr); + FillRect(hdcDraw, &rcFrame, br); + DeleteObject(br); + } + else FillRect(hdcDraw, &rcFrame, GetSysColorBrush(COLOR_3DFACE)); + + HPEN hPenBorder = CreatePen(PS_SOLID, 1, CSkin::m_avatarBorderClr); + HPEN hPenOld = (HPEN)SelectObject(hdcDraw, hPenBorder); + + if (CSkin::m_bAvatarBorderType == 1) + Rectangle(hdcDraw, rcEdge.left, rcEdge.top, rcEdge.right, rcEdge.bottom); + else if (CSkin::m_bAvatarBorderType == 2) { + clipRgn = CreateRoundRectRgn(rcEdge.left, rcEdge.top, rcEdge.right + 1, rcEdge.bottom + 1, 6, 6); + SelectClipRgn(hdcDraw, clipRgn); + + HBRUSH hbr = CreateSolidBrush(CSkin::m_avatarBorderClr); + FrameRgn(hdcDraw, clipRgn, hbr, 1, 1); + DeleteObject(hbr); + DeleteObject(clipRgn); + } + + SelectObject(hdcDraw, hPenOld); + DeleteObject(hPenBorder); + } + + if (bPanelPic) { + bool bBorder = (CSkin::m_bAvatarBorderType ? true : false); + + int border_off = bBorder ? 1 : 0; + int iMaxHeight = m_iPanelAvatarY - (bBorder ? 2 : 0); + int iMaxWidth = m_iPanelAvatarX - (bBorder ? 2 : 0); + + rcFrame.left = rcFrame.top = 0; + rcFrame.right = (rcClient.right - rcClient.left); + rcFrame.bottom = (rcClient.bottom - rcClient.top); + + rcFrame.left = rcFrame.right - (LONG)m_iPanelAvatarX; + rcFrame.bottom = (LONG)m_iPanelAvatarY; + + int height_off = (cy - iMaxHeight - (bBorder ? 2 : 0)) / 2; + rcFrame.top += height_off; + rcFrame.bottom += height_off; + + SendMessage(m_hwndPanelPic, AVATAR_SETAEROCOMPATDRAWING, 0, bAero ? TRUE : FALSE); + SetWindowPos(m_hwndPanelPic, HWND_TOP, rcFrame.left + border_off, rcFrame.top + border_off, + iMaxWidth, iMaxHeight, SWP_SHOWWINDOW | SWP_ASYNCWINDOWPOS | SWP_DEFERERASE | SWP_NOSENDCHANGING); + } + + SelectObject(hdcDraw, hOldBrush); + if (!bPanelPic) + BitBlt(dis->hDC, 0, 0, cx, cy, hdcDraw, 0, 0, SRCCOPY); + SelectObject(hdcDraw, hbmOld); + DeleteObject(hbmDraw); + DeleteDC(hdcDraw); + return TRUE; + } + + if (dis->hwndItem == GetDlgItem(m_hwnd, IDC_STATICTEXT) || dis->hwndItem == GetDlgItem(m_hwnd, IDC_LOGFROZENTEXT)) { + wchar_t szWindowText[256]; + if (CSkin::m_skinEnabled) { + SetTextColor(dis->hDC, CSkin::m_DefaultFontColor); + CSkin::SkinDrawBG(dis->hwndItem, m_pContainer->m_hwnd, m_pContainer, &dis->rcItem, dis->hDC); + } + else { + SetTextColor(dis->hDC, GetSysColor(COLOR_BTNTEXT)); + CSkin::FillBack(dis->hDC, &dis->rcItem); + } + GetWindowText(dis->hwndItem, szWindowText, _countof(szWindowText)); + szWindowText[255] = 0; + SetBkMode(dis->hDC, TRANSPARENT); + DrawText(dis->hDC, szWindowText, -1, &dis->rcItem, DT_SINGLELINE | DT_VCENTER | DT_NOCLIP | DT_END_ELLIPSIS); + return TRUE; + } + + if (dis->hwndItem == GetDlgItem(m_hwnd, IDC_STATICERRORICON)) { + if (CSkin::m_skinEnabled) + CSkin::SkinDrawBG(dis->hwndItem, m_pContainer->m_hwnd, m_pContainer, &dis->rcItem, dis->hDC); + else + CSkin::FillBack(dis->hDC, &dis->rcItem); + DrawIconEx(dis->hDC, (dis->rcItem.right - dis->rcItem.left) / 2 - 8, (dis->rcItem.bottom - dis->rcItem.top) / 2 - 8, + PluginConfig.g_iconErr, 16, 16, 0, nullptr, DI_NORMAL); + return TRUE; + } + + if (dis->CtlType == ODT_MENU && m_pPanel.isHovered()) { + DrawMenuItem(dis, (HICON)dis->itemData, 0); + return TRUE; + } + + return Menu_DrawItem((LPARAM)dis); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int CMsgDialog::MsgWindowUpdateMenu(HMENU submenu, int menuID) +{ + bool bInfoPanel = m_pPanel.isActive(); + + if (menuID == MENU_TABCONTEXT) { + EnableMenuItem(submenu, ID_TABMENU_LEAVECHATROOM, (isChat() && ProtoServiceExists(m_szProto, PS_LEAVECHAT)) ? MF_ENABLED : MF_DISABLED); + EnableMenuItem(submenu, ID_TABMENU_ATTACHTOCONTAINER, (M.GetByte("useclistgroups", 0) || M.GetByte("singlewinmode", 0)) ? MF_GRAYED : MF_ENABLED); + EnableMenuItem(submenu, ID_TABMENU_CLEARSAVEDTABPOSITION, (M.GetDword(m_hContact, "tabindex", -1) != -1) ? MF_ENABLED : MF_GRAYED); + } + else if (menuID == MENU_PICMENU) { + wchar_t *szText = nullptr; + char avOverride = (char)M.GetByte(m_hContact, "hideavatar", -1); + HMENU visMenu = GetSubMenu(submenu, 0); + BOOL picValid = bInfoPanel ? (m_hOwnPic != nullptr) : (m_ace && m_ace->hbmPic && m_ace->hbmPic != PluginConfig.g_hbmUnknown); + + MENUITEMINFO mii = { 0 }; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING; + + EnableMenuItem(submenu, ID_PICMENU_SAVETHISPICTUREAS, MF_BYCOMMAND | (picValid ? MF_ENABLED : MF_GRAYED)); + + CheckMenuItem(visMenu, ID_VISIBILITY_DEFAULT, MF_BYCOMMAND | (avOverride == -1 ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(visMenu, ID_VISIBILITY_HIDDENFORTHISCONTACT, MF_BYCOMMAND | (avOverride == 0 ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(visMenu, ID_VISIBILITY_VISIBLEFORTHISCONTACT, MF_BYCOMMAND | (avOverride == 1 ? MF_CHECKED : MF_UNCHECKED)); + + CheckMenuItem(submenu, ID_PICMENU_ALWAYSKEEPTHEBUTTONBARATFULLWIDTH, MF_BYCOMMAND | (PluginConfig.m_bAlwaysFullToolbarWidth ? MF_CHECKED : MF_UNCHECKED)); + if (!bInfoPanel) { + EnableMenuItem(submenu, ID_PICMENU_SETTINGS, MF_BYCOMMAND | (ServiceExists(MS_AV_GETAVATARBITMAP) ? MF_ENABLED : MF_GRAYED)); + szText = TranslateT("Contact picture settings..."); + EnableMenuItem(submenu, 0, MF_BYPOSITION | MF_ENABLED); + } + else { + EnableMenuItem(submenu, 0, MF_BYPOSITION | MF_GRAYED); + EnableMenuItem(submenu, ID_PICMENU_SETTINGS, MF_BYCOMMAND | ((ServiceExists(MS_AV_SETMYAVATARW) && CallService(MS_AV_CANSETMYAVATAR, (WPARAM)(m_cache->getActiveProto()), 0)) ? MF_ENABLED : MF_GRAYED)); + szText = TranslateT("Set your avatar..."); + } + mii.dwTypeData = szText; + mii.cch = (int)mir_wstrlen(szText) + 1; + SetMenuItemInfo(submenu, ID_PICMENU_SETTINGS, FALSE, &mii); + } + else if (menuID == MENU_PANELPICMENU) { + HMENU visMenu = GetSubMenu(submenu, 0); + char avOverride = (char)M.GetByte(m_hContact, "hideavatar", -1); + + CheckMenuItem(visMenu, ID_VISIBILITY_DEFAULT, MF_BYCOMMAND | (avOverride == -1 ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(visMenu, ID_VISIBILITY_HIDDENFORTHISCONTACT, MF_BYCOMMAND | (avOverride == 0 ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(visMenu, ID_VISIBILITY_VISIBLEFORTHISCONTACT, MF_BYCOMMAND | (avOverride == 1 ? MF_CHECKED : MF_UNCHECKED)); + + EnableMenuItem(submenu, ID_PICMENU_SETTINGS, MF_BYCOMMAND | (ServiceExists(MS_AV_GETAVATARBITMAP) ? MF_ENABLED : MF_GRAYED)); + EnableMenuItem(submenu, ID_PANELPICMENU_SAVETHISPICTUREAS, MF_BYCOMMAND | ((m_ace && m_ace->hbmPic && m_ace->hbmPic != PluginConfig.g_hbmUnknown) ? MF_ENABLED : MF_GRAYED)); + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// update state of the container - this is called whenever a tab becomes active, no matter how and +// deals with various things like updating the title bar, removing flashing icons, updating the +// session list, switching the keyboard layout (autolocale active) and the general container status. +// +// it protects itself from being called more than once per session activation and is valid for +// normal IM sessions *only*. Group chat sessions have their own activation handler (see chat/window.c) + +void CMsgDialog::MsgWindowUpdateState(UINT msg) +{ + if (m_iTabID < 0) + return; + + if (msg == WM_ACTIVATE) { + if (m_pContainer->m_dwFlags & CNT_TRANSPARENCY) { + DWORD trans = LOWORD(m_pContainer->m_pSettings->dwTransparency); + SetLayeredWindowAttributes(m_pContainer->m_hwnd, 0, (BYTE)trans, (m_pContainer->m_dwFlags & CNT_TRANSPARENCY ? LWA_ALPHA : 0)); + } + } + + if (m_bIsAutosizingInput && m_iInputAreaHeight == -1) { + m_iInputAreaHeight = 0; + m_message.SendMsg(EM_REQUESTRESIZE, 0, 0); + } + + if (m_pWnd) + m_pWnd->activateTab(); + m_pPanel.dismissConfig(); + m_dwUnread = 0; + if (m_pContainer->m_hwndSaved == m_hwnd) + return; + + m_pContainer->m_hwndSaved = m_hwnd; + + m_dwTickLastEvent = 0; + m_dwFlags &= ~MWF_DIVIDERSET; + if (KillTimer(m_hwnd, TIMERID_FLASHWND)) { + FlashTab(false); + m_bCanFlashTab = false; + } + if (m_pContainer->m_dwFlashingStarted != 0) { + FlashContainer(m_pContainer, 0, 0); + m_pContainer->m_dwFlashingStarted = 0; + } + if (m_dwFlagsEx & MWF_SHOW_FLASHCLIST) { + m_dwFlagsEx &= ~MWF_SHOW_FLASHCLIST; + if (m_hFlashingEvent != 0) + g_clistApi.pfnRemoveEvent(m_hContact, m_hFlashingEvent); + m_hFlashingEvent = 0; + } + m_pContainer->m_dwFlags &= ~CNT_NEED_UPDATETITLE; + + if ((m_dwFlags & MWF_DEFERREDREMAKELOG) && !IsIconic(m_pContainer->m_hwnd)) { + SendMessage(m_hwnd, DM_REMAKELOG, 0, 0); + m_dwFlags &= ~MWF_DEFERREDREMAKELOG; + } + + if (m_dwFlags & MWF_NEEDCHECKSIZE) + PostMessage(m_hwnd, DM_SAVESIZE, 0, 0); + + m_pContainer->m_hIconTaskbarOverlay = nullptr; + m_pContainer->UpdateTitle(m_hContact); + + tabUpdateStatusBar(); + m_dwLastActivity = GetTickCount(); + m_pContainer->m_dwLastActivity = m_dwLastActivity; + + m_pContainer->m_pMenuBar->configureMenu(); + UpdateTrayMenuState(this, FALSE); + + if (m_pContainer->m_hwndActive == m_hwnd) + DeletePopupsForContact(m_hContact, PU_REMOVE_ON_FOCUS); + + m_pPanel.Invalidate(); + + if (m_dwFlags & MWF_DEFERREDSCROLL && m_hwndIEView == nullptr && m_hwndHPP == nullptr) { + m_dwFlags &= ~MWF_DEFERREDSCROLL; + DM_ScrollToBottom(0, 1); + } + + DM_SetDBButtonStates(); + + if (m_hwndIEView) { + RECT rcRTF; + POINT pt; + + GetWindowRect(m_log.GetHwnd(), &rcRTF); + rcRTF.left += 20; + rcRTF.top += 20; + pt.x = rcRTF.left; + pt.y = rcRTF.top; + if (m_hwndIEView) { + if (M.GetByte("subclassIEView", 0)) { + mir_subclassWindow(m_hwndIEView, IEViewSubclassProc); + SetWindowPos(m_hwndIEView, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_DRAWFRAME); + RedrawWindow(m_hwndIEView, nullptr, nullptr, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW); + } + } + m_hwndIWebBrowserControl = WindowFromPoint(pt); + } + + if (m_dwFlagsEx & MWF_EX_DELAYEDSPLITTER) { + m_dwFlagsEx &= ~MWF_EX_DELAYEDSPLITTER; + ShowWindow(m_pContainer->m_hwnd, SW_RESTORE); + PostMessage(m_hwnd, DM_SPLITTERGLOBALEVENT, m_wParam, m_lParam); + m_wParam = m_lParam = 0; + } + if (m_dwFlagsEx & MWF_EX_AVATARCHANGED) { + m_dwFlagsEx &= ~MWF_EX_AVATARCHANGED; + PostMessage(m_hwnd, DM_UPDATEPICLAYOUT, 0, 0); + } + BB_SetButtonsPos(); + if (M.isAero()) + InvalidateRect(m_hwndParent, nullptr, FALSE); + if (m_pContainer->m_dwFlags & CNT_SIDEBAR) + m_pContainer->m_pSideBar->setActiveItem(this); + + if (m_pWnd) + m_pWnd->Invalidate(); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int CMsgDialog::MsgWindowMenuHandler(int selection, int menuId) +{ + if (menuId == MENU_PICMENU || menuId == MENU_PANELPICMENU || menuId == MENU_TABCONTEXT) { + switch (selection) { + case ID_TABMENU_ATTACHTOCONTAINER: + CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_SELECTCONTAINER), m_hwnd, SelectContainerDlgProc, (LPARAM)m_hwnd); + return 1; + case ID_TABMENU_CONTAINEROPTIONS: + if (m_pContainer->m_hWndOptions == nullptr) + CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_CONTAINEROPTIONS), m_hwnd, DlgProcContainerOptions, (LPARAM)m_pContainer); + return 1; + case ID_TABMENU_CLOSECONTAINER: + SendMessage(m_pContainer->m_hwnd, WM_CLOSE, 0, 0); + return 1; + case ID_TABMENU_CLOSETAB: + PostMessage(m_hwnd, WM_CLOSE, 1, 0); + return 1; + case ID_TABMENU_SAVETABPOSITION: + db_set_dw(m_hContact, SRMSGMOD_T, "tabindex", m_iTabID * 100); + break; + case ID_TABMENU_CLEARSAVEDTABPOSITION: + db_unset(m_hContact, SRMSGMOD_T, "tabindex"); + break; + case ID_TABMENU_LEAVECHATROOM: + if (isChat() && m_hContact != 0) { + char *szProto = GetContactProto(m_hContact); + if (szProto) + CallProtoService(szProto, PS_LEAVECHAT, m_hContact, 0); + } + return 1; + + case ID_VISIBILITY_DEFAULT: + case ID_VISIBILITY_HIDDENFORTHISCONTACT: + case ID_VISIBILITY_VISIBLEFORTHISCONTACT: + { + BYTE avOverrideMode; + if (selection == ID_VISIBILITY_DEFAULT) + avOverrideMode = -1; + else if (selection == ID_VISIBILITY_VISIBLEFORTHISCONTACT) + avOverrideMode = 1; + else + avOverrideMode = 0; + db_set_b(m_hContact, SRMSGMOD_T, "hideavatar", avOverrideMode); + } + + ShowPicture(false); + Resize(); + DM_ScrollToBottom(0, 1); + return 1; + + case ID_PICMENU_ALWAYSKEEPTHEBUTTONBARATFULLWIDTH: + PluginConfig.m_bAlwaysFullToolbarWidth = !PluginConfig.m_bAlwaysFullToolbarWidth; + db_set_b(0, SRMSGMOD_T, "alwaysfulltoolbar", (BYTE)PluginConfig.m_bAlwaysFullToolbarWidth); + Srmm_Broadcast(DM_CONFIGURETOOLBAR, 0, 1); + break; + + case ID_PICMENU_SAVETHISPICTUREAS: + if (m_pPanel.isActive()) + SaveAvatarToFile(m_hOwnPic, 1); + else if (m_ace) + SaveAvatarToFile(m_ace->hbmPic, 0); + break; + + case ID_PANELPICMENU_SAVETHISPICTUREAS: + if (m_ace) + SaveAvatarToFile(m_ace->hbmPic, 0); + break; + + case ID_PICMENU_SETTINGS: + if (menuId == MENU_PANELPICMENU) + CallService(MS_AV_CONTACTOPTIONS, m_hContact, 0); + else if (menuId == MENU_PICMENU) { + if (m_pPanel.isActive()) { + if (ServiceExists(MS_AV_SETMYAVATARW) && CallService(MS_AV_CANSETMYAVATAR, (WPARAM)(m_cache->getActiveProto()), 0)) + CallService(MS_AV_SETMYAVATARW, (WPARAM)(m_cache->getActiveProto()), 0); + } + else + CallService(MS_AV_CONTACTOPTIONS, m_hContact, 0); + } + return 1; + } + } + else if (menuId == MENU_LOGMENU) { + switch (selection) { + case ID_MESSAGELOGSETTINGS_GLOBAL: + g_plugin.openOptions(nullptr, L"Message sessions", L"Message log"); + return 1; + + case ID_MESSAGELOGSETTINGS_FORTHISCONTACT: + CallService(MS_TABMSG_SETUSERPREFS, m_hContact, 0); + return 1; + } + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::PlayIncomingSound() const +{ + int iPlay = MustPlaySound(); + if (iPlay) { + if (GetForegroundWindow() == m_pContainer->m_hwnd && m_pContainer->m_hwndActive == m_hwnd) + Skin_PlaySound("RecvMsgActive"); + else + Skin_PlaySound("RecvMsgInactive"); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static void __cdecl phase2(SESSION_INFO *si) +{ + Thread_SetName("TabSRMM: phase2"); + + Sleep(30); + if (si && si->pDlg) + si->pDlg->RedrawLog2(); +} + +void CMsgDialog::RedrawLog() +{ + m_si->LastTime = 0; + if (m_si->pLog) { + LOGINFO *pLog = m_si->pLog; + if (m_si->iEventCount > 60) { + int index = 0; + while (index < 59) { + if (pLog->next == nullptr) + break; + pLog = pLog->next; + if ((m_si->iType != GCW_CHATROOM && m_si->iType != GCW_PRIVMESS) || !m_bFilterEnabled || (m_iLogFilterFlags & pLog->iType) != 0) + index++; + } + StreamInEvents(pLog, TRUE); + mir_forkThread(phase2, m_si); + } + else StreamInEvents(m_si->pLogEnd, TRUE); + } + else ClearLog(); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::ResizeIeView() +{ + RECT rcRichEdit; + GetWindowRect(m_log.GetHwnd(), &rcRichEdit); + + POINT pt = { rcRichEdit.left, rcRichEdit.top }; + ScreenToClient(m_hwnd, &pt); + + IEVIEWWINDOW ieWindow = { sizeof(ieWindow) }; + ieWindow.iType = IEW_SETPOS; + ieWindow.parent = m_hwnd; + ieWindow.hwnd = m_hwndIEView ? m_hwndIEView : m_hwndHPP; + 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(m_hwndIEView ? MS_IEVIEW_WINDOW : MS_HPP_EG_WINDOW, 0, (LPARAM)& ieWindow); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// saves a contact picture to disk +// takes hbm (bitmap handle) and bool isOwnPic (1 == save the picture as your own avatar) +// requires AVS service (Miranda 0.7+) + +void CMsgDialog::SaveAvatarToFile(HBITMAP hbm, int isOwnPic) +{ + wchar_t szFinalFilename[MAX_PATH]; + time_t t = time(0); + struct tm *lt = localtime(&t); + DWORD setView = 1; + + wchar_t szTimestamp[100]; + mir_snwprintf(szTimestamp, L"%04u %02u %02u_%02u%02u", lt->tm_year + 1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min); + + wchar_t *szProto = mir_a2u(m_cache->getActiveProto()); + + wchar_t szFinalPath[MAX_PATH]; + mir_snwprintf(szFinalPath, L"%s\\%s", M.getSavedAvatarPath(), szProto); + mir_free(szProto); + + if (CreateDirectory(szFinalPath, nullptr) == 0) { + if (GetLastError() != ERROR_ALREADY_EXISTS) { + MessageBox(nullptr, TranslateT("Error creating destination directory"), + TranslateT("Save contact picture"), MB_OK | MB_ICONSTOP); + return; + } + } + + wchar_t szBaseName[MAX_PATH]; + if (isOwnPic) + mir_snwprintf(szBaseName, L"My Avatar_%s", szTimestamp); + else + mir_snwprintf(szBaseName, L"%s_%s", m_cache->getNick(), szTimestamp); + + mir_snwprintf(szFinalFilename, L"%s.png", szBaseName); + + // do not allow / or \ or % in the filename + Utils::sanitizeFilename(szFinalFilename); + + wchar_t filter[MAX_PATH]; + mir_snwprintf(filter, L"%s%c*.bmp;*.png;*.jpg;*.gif%c%c", TranslateT("Image files"), 0, 0, 0); + + OPENFILENAME ofn = { 0 }; + ofn.lpstrDefExt = L"png"; + ofn.lpstrFilter = filter; + ofn.Flags = OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ENABLESIZING | OFN_ENABLEHOOK; + ofn.lpfnHook = OpenFileSubclass; + ofn.lStructSize = sizeof(ofn); + ofn.lpstrFile = szFinalFilename; + ofn.lpstrInitialDir = szFinalPath; + ofn.nMaxFile = MAX_PATH; + ofn.nMaxFileTitle = MAX_PATH; + ofn.lCustData = (LPARAM)& setView; + if (GetSaveFileName(&ofn)) { + if (PathFileExists(szFinalFilename)) + if (MessageBox(nullptr, TranslateT("The file exists. Do you want to overwrite it?"), TranslateT("Save contact picture"), MB_YESNO | MB_ICONQUESTION) == IDNO) + return; + + IMGSRVC_INFO ii; + ii.cbSize = sizeof(ii); + ii.pwszName = szFinalFilename; + ii.hbm = hbm; + ii.dwMask = IMGI_HBITMAP; + ii.fif = FIF_UNKNOWN; // get the format from the filename extension. png is default. + Image_Save(&ii); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::SaveSplitter() +{ + if (m_bIsAutosizingInput) + return; + + if (m_iSplitterY < DPISCALEY_S(MINSPLITTERY) || m_iSplitterY < 0) + m_iSplitterY = DPISCALEY_S(MINSPLITTERY); + + if (m_dwFlagsEx & MWF_SHOW_SPLITTEROVERRIDE) + db_set_dw(m_hContact, SRMSGMOD_T, "splitsplity", m_iSplitterY); + else { + if (m_pContainer->m_pSettings->fPrivate) + m_pContainer->m_pSettings->iSplitterY = m_iSplitterY; + else + db_set_dw(0, SRMSGMOD_T, "splitsplity", m_iSplitterY); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// send a pasted bitmap by file transfer. + +static LIST vTempFilenames(5); + +void CMsgDialog::SendHBitmapAsFile(HBITMAP hbmp) const +{ + const wchar_t *mirandatempdir = L"Miranda"; + const wchar_t *filenametemplate = L"\\clp-%Y%m%d-%H%M%S0.jpg"; + wchar_t filename[MAX_PATH]; + size_t tempdirlen = GetTempPath(MAX_PATH, filename); + bool fSend = true; + + const char *szProto = m_cache->getActiveProto(); + int wMyStatus = Proto_GetStatus(szProto); + + DWORD protoCaps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0); + DWORD typeCaps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0); + + // check protocol capabilities, status modes and visibility lists (privacy) + // to determine whether the file can be sent. Throw a warning if any of + // these checks fails. + if (!(protoCaps & PF1_FILESEND)) + fSend = false; + + if ((ID_STATUS_OFFLINE == wMyStatus) || (ID_STATUS_OFFLINE == m_cache->getActiveStatus() && !(typeCaps & PF4_OFFLINEFILES))) + fSend = false; + + if (protoCaps & PF1_VISLIST && db_get_w(m_cache->getActiveContact(), szProto, "ApparentMode", 0) == ID_STATUS_OFFLINE) + fSend = false; + + if (protoCaps & PF1_INVISLIST && wMyStatus == ID_STATUS_INVISIBLE && db_get_w(m_cache->getActiveContact(), szProto, "ApparentMode", 0) != ID_STATUS_ONLINE) + fSend = false; + + if (!fSend) { + CWarning::show(CWarning::WARN_SENDFILE, MB_OK | MB_ICONEXCLAMATION | CWarning::CWF_NOALLOWHIDE); + return; + } + + if (tempdirlen <= 0 || tempdirlen >= MAX_PATH - mir_wstrlen(mirandatempdir) - mir_wstrlen(filenametemplate) - 2) // -2 is because %Y takes 4 symbols + filename[0] = 0; // prompt for a new name + else { + mir_wstrcpy(filename + tempdirlen, mirandatempdir); + if ((GetFileAttributes(filename) == INVALID_FILE_ATTRIBUTES || ((GetFileAttributes(filename) & FILE_ATTRIBUTE_DIRECTORY) == 0)) && CreateDirectory(filename, nullptr) == 0) + filename[0] = 0; + else { + tempdirlen = mir_wstrlen(filename); + + time_t rawtime; + time(&rawtime); + const tm *timeinfo; + timeinfo = _localtime32((__time32_t *)& rawtime); + wcsftime(filename + tempdirlen, MAX_PATH - tempdirlen, filenametemplate, timeinfo); + size_t firstnumberpos = tempdirlen + 14; + size_t lastnumberpos = tempdirlen + 20; + while (GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES) { // while it exists + for (size_t pos = lastnumberpos; pos >= firstnumberpos; pos--) + if (filename[pos]++ != '9') + break; + else + if (pos == firstnumberpos) + filename[0] = 0; // all filenames exist => prompt for a new name + else + filename[pos] = '0'; + } + } + } + + if (filename[0] == 0) { // prompting to save + wchar_t filter[MAX_PATH]; + mir_snwprintf(filter, L"%s%c*.jpg%c%c", TranslateT("JPEG-compressed images"), 0, 0, 0); + + OPENFILENAME dlg; + dlg.lStructSize = sizeof(dlg); + dlg.lpstrFilter = filter; + dlg.nFilterIndex = 1; + dlg.lpstrFile = filename; + dlg.nMaxFile = MAX_PATH; + dlg.Flags = OFN_NOREADONLYRETURN | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; + dlg.lpstrDefExt = L"jpg"; + if (!GetSaveFileName(&dlg)) + return; + } + + IMGSRVC_INFO ii; + ii.cbSize = sizeof(ii); + ii.hbm = hbmp; + ii.pwszName = filename; + ii.dwMask = IMGI_HBITMAP; + ii.fif = FIF_JPEG; + Image_Save(&ii); + + int totalCount = 0; + wchar_t **ppFiles = nullptr; + Utils::AddToFileList(&ppFiles, &totalCount, filename); + + wchar_t *_t = mir_wstrdup(filename); + vTempFilenames.insert(_t); + + CallService(MS_FILE_SENDSPECIFICFILEST, m_cache->getActiveContact(), (LPARAM)ppFiles); + + mir_free(ppFiles[0]); + mir_free(ppFiles); +} + +// remove all temporary files created by the "send clipboard as file" feature. +void TSAPI CleanTempFiles() +{ + for (auto &it : vTempFilenames) { + DeleteFileW(it); + mir_free(it); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::SetMessageLog() +{ + if (isChat()) + return; + + unsigned int iLogMode = GetIEViewMode(m_hContact); + + if (iLogMode == WANT_IEVIEW_LOG && m_hwndIEView == nullptr) { + IEVIEWWINDOW ieWindow = {}; + ieWindow.cbSize = sizeof(IEVIEWWINDOW); + ieWindow.iType = IEW_CREATE; + ieWindow.dwMode = IEWM_TABSRMM; + ieWindow.parent = m_hwnd; + ieWindow.cx = 200; + ieWindow.cy = 200; + CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)& ieWindow); + m_hwndIEView = ieWindow.hwnd; + m_log.Hide(); + m_log.Enable(false); + } + else if (iLogMode == WANT_HPP_LOG && m_hwndHPP == nullptr) { + IEVIEWWINDOW ieWindow = {}; + ieWindow.cbSize = sizeof(IEVIEWWINDOW); + ieWindow.iType = IEW_CREATE; + ieWindow.dwMode = IEWM_TABSRMM; + ieWindow.parent = m_hwnd; + ieWindow.cx = 10; + ieWindow.cy = 10; + CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)& ieWindow); + m_hwndHPP = ieWindow.hwnd; + m_log.Hide(); + m_log.Enable(false); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::ShowPicture(bool showNewPic) +{ + if (!m_pPanel.isActive()) + m_pic.cy = m_pic.cx = DPISCALEY_S(60); + + if (showNewPic) { + if (m_pPanel.isActive() && m_pContainer->m_avatarMode != 3) { + if (!m_hwndPanelPic) { + InvalidateRect(m_hwnd, nullptr, TRUE); + UpdateWindow(m_hwnd); + Resize(); + } + return; + } + AdjustBottomAvatarDisplay(); + } + else { + m_bShowAvatar = !m_bShowAvatar; + db_set_b(m_hContact, SRMSGMOD_T, "MOD_ShowPic", m_bShowAvatar); + } + + RECT rc; + GetWindowRect(GetDlgItem(m_hwnd, IDC_CONTACTPIC), &rc); + if (m_minEditBoxSize.cy + DPISCALEY_S(3) > m_iSplitterY) + SendMessage(m_hwnd, DM_SPLITTERMOVED, (WPARAM)rc.bottom - m_minEditBoxSize.cy, (LPARAM)GetDlgItem(m_hwnd, IDC_SPLITTERY)); + if (!showNewPic) + SetDialogToType(); + else + Resize(); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// show a modified context menu for the richedit control(s) + +void CMsgDialog::ShowPopupMenu(const CCtrlBase &pCtrl, POINT pt) +{ + CHARRANGE sel, all = { 0, -1 }; + + HMENU hSubMenu, hMenu = LoadMenu(g_plugin.getInst(), MAKEINTRESOURCE(IDR_CONTEXT)); + if (pCtrl.GetCtrlId() == IDC_SRMM_LOG) + hSubMenu = GetSubMenu(hMenu, 0); + else { + hSubMenu = GetSubMenu(hMenu, 2); + EnableMenuItem(hSubMenu, IDM_PASTEFORMATTED, MF_BYCOMMAND | (m_SendFormat != 0 ? MF_ENABLED : MF_GRAYED)); + EnableMenuItem(hSubMenu, ID_EDITOR_PASTEANDSENDIMMEDIATELY, MF_BYCOMMAND | (PluginConfig.m_PasteAndSend ? MF_ENABLED : MF_GRAYED)); + CheckMenuItem(hSubMenu, ID_EDITOR_SHOWMESSAGELENGTHINDICATOR, MF_BYCOMMAND | (PluginConfig.m_visualMessageSizeIndicator ? MF_CHECKED : MF_UNCHECKED)); + EnableMenuItem(hSubMenu, ID_EDITOR_SHOWMESSAGELENGTHINDICATOR, MF_BYCOMMAND | (m_pContainer->m_hwndStatus ? MF_ENABLED : MF_GRAYED)); + } + TranslateMenu(hSubMenu); + pCtrl.SendMsg(EM_EXGETSEL, 0, (LPARAM)& sel); + if (sel.cpMin == sel.cpMax) { + EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(hSubMenu, IDM_QUOTE, MF_BYCOMMAND | MF_GRAYED); + if (pCtrl.GetCtrlId() == IDC_SRMM_MESSAGE) + EnableMenuItem(hSubMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED); + } + + if (pCtrl.GetCtrlId() == IDC_SRMM_LOG) { + InsertMenuA(hSubMenu, 6, MF_BYPOSITION | MF_SEPARATOR, 0, nullptr); + CheckMenuItem(hSubMenu, ID_LOG_FREEZELOG, MF_BYCOMMAND | (m_dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED ? MF_CHECKED : MF_UNCHECKED)); + } + + MessageWindowPopupData mwpd; + // First notification + mwpd.uType = MSG_WINDOWPOPUP_SHOWING; + mwpd.uFlags = (pCtrl.GetCtrlId() == IDC_SRMM_LOG ? MSG_WINDOWPOPUP_LOG : MSG_WINDOWPOPUP_INPUT); + mwpd.hContact = m_hContact; + mwpd.hwnd = pCtrl.GetHwnd(); + mwpd.hMenu = hSubMenu; + mwpd.selection = 0; + mwpd.pt = pt; + NotifyEventHooks(g_chatApi.hevWinPopup, 0, (LPARAM)& mwpd); + + int iSelection = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, m_hwnd, nullptr); + + // Second notification + mwpd.selection = iSelection; + mwpd.uType = MSG_WINDOWPOPUP_SELECTED; + NotifyEventHooks(g_chatApi.hevWinPopup, 0, (LPARAM)& mwpd); + + switch (iSelection) { + case IDM_COPY: + pCtrl.SendMsg(WM_COPY, 0, 0); + break; + case IDM_CUT: + pCtrl.SendMsg(WM_CUT, 0, 0); + break; + case IDM_PASTE: + case IDM_PASTEFORMATTED: + if (pCtrl.GetCtrlId() == IDC_SRMM_MESSAGE) + pCtrl.SendMsg(EM_PASTESPECIAL, (iSelection == IDM_PASTE) ? CF_UNICODETEXT : 0, 0); + break; + case IDM_COPYALL: + pCtrl.SendMsg(EM_EXSETSEL, 0, (LPARAM)& all); + pCtrl.SendMsg(WM_COPY, 0, 0); + pCtrl.SendMsg(EM_EXSETSEL, 0, (LPARAM)& sel); + break; + case IDM_QUOTE: + SendMessage(m_hwnd, WM_COMMAND, IDC_QUOTE, 0); + break; + case IDM_SELECTALL: + pCtrl.SendMsg(EM_EXSETSEL, 0, (LPARAM)& all); + break; + case IDM_CLEAR: + tabClearLog(); + break; + case ID_LOG_FREEZELOG: + SendDlgItemMessage(m_hwnd, IDC_SRMM_LOG, WM_KEYDOWN, VK_F12, 0); + break; + case ID_EDITOR_SHOWMESSAGELENGTHINDICATOR: + PluginConfig.m_visualMessageSizeIndicator = !PluginConfig.m_visualMessageSizeIndicator; + db_set_b(0, SRMSGMOD_T, "msgsizebar", (BYTE)PluginConfig.m_visualMessageSizeIndicator); + Srmm_Broadcast(DM_CONFIGURETOOLBAR, 0, 0); + Resize(); + if (m_pContainer->m_hwndStatus) + RedrawWindow(m_pContainer->m_hwndStatus, nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW); + break; + case ID_EDITOR_PASTEANDSENDIMMEDIATELY: + HandlePasteAndSend(); + break; + } + + if (pCtrl.GetCtrlId() == IDC_SRMM_LOG) + RemoveMenu(hSubMenu, 7, MF_BYPOSITION); + DestroyMenu(hMenu); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +bool CMsgDialog::TabAutoComplete() +{ + LRESULT lResult = m_message.SendMsg(EM_GETSEL, 0, 0); + int start = LOWORD(lResult), end = HIWORD(lResult); + m_message.SendMsg(EM_SETSEL, end, end); + + GETTEXTEX gt = { 0 }; + gt.codepage = 1200; + gt.flags = GTL_DEFAULT | GTL_PRECISE; + int iLen = m_message.SendMsg(EM_GETTEXTLENGTHEX, (WPARAM)& gt, 0); + if (iLen <= 0) + return false; + + bool isTopic = false, isRoom = false; + wchar_t *pszName = nullptr; + wchar_t *pszText = (wchar_t *)mir_calloc((iLen + 10) * sizeof(wchar_t)); + + gt.flags = GT_DEFAULT; + gt.cb = (iLen + 9) * sizeof(wchar_t); + m_message.SendMsg(EM_GETTEXTEX, (WPARAM)& gt, (LPARAM)pszText); + + if (start > 1 && pszText[start - 1] == ' ' && pszText[start - 2] == ':') + start -= 2; + + if (m_wszSearchResult != nullptr) { + int cbResult = (int)mir_wstrlen(m_wszSearchResult); + if (start >= cbResult && !wcsnicmp(m_wszSearchResult, pszText + start - cbResult, cbResult)) { + start -= cbResult; + goto LBL_SkipEnd; + } + } + + while (start > 0 && pszText[start - 1] != ' ' && pszText[start - 1] != 13 && pszText[start - 1] != VK_TAB) + start--; + +LBL_SkipEnd: + while (end < iLen && pszText[end] != ' ' && pszText[end] != 13 && pszText[end - 1] != VK_TAB) + end++; + + if (pszText[start] == '#') + isRoom = true; + else { + int topicStart = start; + while (topicStart > 0 && (pszText[topicStart - 1] == ' ' || pszText[topicStart - 1] == 13 || pszText[topicStart - 1] == VK_TAB)) + topicStart--; + if (topicStart > 5 && wcsstr(&pszText[topicStart - 6], L"/topic") == &pszText[topicStart - 6]) + isTopic = true; + } + if (m_wszSearchQuery == nullptr) { + m_wszSearchQuery = mir_wstrndup(pszText + start, end - start); + m_wszSearchResult = mir_wstrdup(m_wszSearchQuery); + m_pLastSession = nullptr; + } + if (isTopic) + pszName = m_si->ptszTopic; + else if (isRoom) { + m_pLastSession = SM_FindSessionAutoComplete(m_si->pszModule, m_si, m_pLastSession, m_wszSearchQuery, m_wszSearchResult); + if (m_pLastSession != nullptr) + pszName = m_pLastSession->ptszName; + } + else pszName = g_chatApi.UM_FindUserAutoComplete(m_si, m_wszSearchQuery, m_wszSearchResult); + + replaceStrW(m_wszSearchResult, nullptr); + + if (pszName != nullptr) { + m_wszSearchResult = mir_wstrdup(pszName); + if (end != start) { + ptrW szReplace; + if (!isRoom && !isTopic && g_Settings.bAddColonToAutoComplete && start == 0) { + szReplace = (wchar_t *)mir_alloc((mir_wstrlen(pszName) + 4) * sizeof(wchar_t)); + mir_wstrcpy(szReplace, pszName); + mir_wstrcat(szReplace, g_Settings.bUseCommaAsColon ? L", " : L": "); + pszName = szReplace; + } + m_message.SendMsg(EM_SETSEL, start, end); + m_message.SendMsg(EM_REPLACESEL, TRUE, (LPARAM)pszName); + } + return true; + } + + if (end != start) { + m_message.SendMsg(EM_SETSEL, start, end); + m_message.SendMsg(EM_REPLACESEL, TRUE, (LPARAM)m_wszSearchQuery); + } + replaceStrW(m_wszSearchQuery, nullptr); + return false; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::tabClearLog() +{ + if (isChat()) { + SESSION_INFO *s = g_chatApi.SM_FindSession(m_si->ptszID, m_si->pszModule); + if (s) { + ClearLog(); + g_chatApi.LM_RemoveAll(&s->pLog, &s->pLogEnd); + s->iEventCount = 0; + s->LastTime = 0; + m_si->iEventCount = 0; + m_si->LastTime = 0; + m_si->pLog = s->pLog; + m_si->pLogEnd = s->pLogEnd; + PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); + } + } + else { + if (m_hwndIEView || m_hwndHPP) { + IEVIEWEVENT event; + event.cbSize = sizeof(IEVIEWEVENT); + event.iType = IEE_CLEAR_LOG; + event.dwFlags = (m_dwFlags & MWF_LOG_RTL) ? IEEF_RTL : 0; + event.hContact = m_hContact; + if (m_hwndIEView) { + event.hwnd = m_hwndIEView; + CallService(MS_IEVIEW_EVENT, 0, (LPARAM) & event); + } + else { + event.hwnd = m_hwndHPP; + CallService(MS_HPP_EG_EVENT, 0, (LPARAM) & event); + } + } + m_log.SetText(L""); + m_hDbEventFirst = 0; + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +CThumbBase *CMsgDialog::tabCreateThumb(CProxyWindow *pProxy) const +{ + if (isChat()) + return new CThumbMUC(pProxy, m_si); + + return new CThumbIM(pProxy); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// update all status bar fields and force a redraw of the status bar. + +void CMsgDialog::tabUpdateStatusBar() const +{ + if (m_pContainer->m_hwndStatus && m_pContainer->m_hwndActive == m_hwnd) { + if (!isChat()) { + if (m_wszStatusBar[0]) { + SendMessage(m_pContainer->m_hwndStatus, SB_SETICON, 0, (LPARAM)PluginConfig.g_buttonBarIcons[ICON_DEFAULT_TYPING]); + SendMessage(m_pContainer->m_hwndStatus, SB_SETTEXT, 0, (LPARAM)m_wszStatusBar); + } + else if (m_bStatusSet) { + SendMessage(m_pContainer->m_hwndStatus, SB_SETICON, 0, (LPARAM)m_szStatusIcon); + SendMessage(m_pContainer->m_hwndStatus, SB_SETTEXT, 0, (LPARAM)m_szStatusText.c_str()); + } + else { + SendMessage(m_pContainer->m_hwndStatus, SB_SETICON, 0, 0); + DM_UpdateLastMessage(); + } + } + else { + if (m_bStatusSet) { + SendMessage(m_pContainer->m_hwndStatus, SB_SETICON, 0, (LPARAM)m_szStatusIcon); + SendMessage(m_pContainer->m_hwndStatus, SB_SETTEXT, 0, (LPARAM)m_szStatusText.c_str()); + } + else SendMessage(m_pContainer->m_hwndStatus, SB_SETICON, 0, 0); + } + UpdateReadChars(); + InvalidateRect(m_pContainer->m_hwndStatus, nullptr, TRUE); + SendMessage(m_pContainer->m_hwndStatus, WM_USER + 101, 0, (LPARAM)this); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// update the status bar field which displays the number of characters in the input area +// and various indicators (caps lock, num lock, insert mode). + +void CMsgDialog::UpdateReadChars() const +{ + if (!m_pContainer->m_hwndStatus || m_pContainer->m_hwndActive != m_hwnd) + return; + + int len; + if (isChat()) + len = GetWindowTextLength(m_message.GetHwnd()); + else { + // retrieve text length in UTF8 bytes, because this is the relevant length for most protocols + GETTEXTLENGTHEX gtxl = { 0 }; + gtxl.codepage = CP_UTF8; + gtxl.flags = GTL_DEFAULT | GTL_PRECISE | GTL_NUMBYTES; + + len = m_message.SendMsg(EM_GETTEXTLENGTHEX, (WPARAM)>xl, 0); + } + + BOOL fCaps = (GetKeyState(VK_CAPITAL) & 1); + BOOL fNum = (GetKeyState(VK_NUMLOCK) & 1); + + wchar_t szBuf[20]; szBuf[0] = 0; + if (m_bInsertMode) + mir_wstrcat(szBuf, L"O"); + if (fCaps) + mir_wstrcat(szBuf, L"C"); + if (fNum) + mir_wstrcat(szBuf, L"N"); + if (m_bInsertMode || fCaps || fNum) + mir_wstrcat(szBuf, L" | "); + + wchar_t buf[128]; + mir_snwprintf(buf, L"%s%s %d/%d", szBuf, m_lcID, m_iOpenJobs, len); + SendMessage(m_pContainer->m_hwndStatus, SB_SETTEXT, 1, (LPARAM)buf); + if (PluginConfig.m_visualMessageSizeIndicator) + InvalidateRect(m_pContainer->m_hwndStatus, nullptr, FALSE); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void CMsgDialog::UpdateSaveAndSendButton() +{ + GETTEXTLENGTHEX gtxl = { 0 }; + gtxl.codepage = CP_UTF8; + gtxl.flags = GTL_DEFAULT | GTL_PRECISE | GTL_NUMBYTES; + + int len = SendDlgItemMessage(m_hwnd, IDC_SRMM_MESSAGE, EM_GETTEXTLENGTHEX, (WPARAM)>xl, 0); + if (len && GetSendButtonState(m_hwnd) == PBS_DISABLED) + EnableSendButton(true); + else if (len == 0 && GetSendButtonState(m_hwnd) != PBS_DISABLED) + EnableSendButton(false); + + if (len) { // looks complex but avoids flickering on the button while typing. + if (!(m_dwFlags & MWF_SAVEBTN_SAV)) { + SendDlgItemMessage(m_hwnd, IDC_CLOSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)PluginConfig.g_buttonBarIcons[ICON_BUTTON_SAVE]); + SendDlgItemMessage(m_hwnd, IDC_CLOSE, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Save and close session"), BATF_UNICODE); + m_dwFlags |= MWF_SAVEBTN_SAV; + } + } + else { + SendDlgItemMessage(m_hwnd, IDC_CLOSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)PluginConfig.g_buttonBarIcons[ICON_BUTTON_CANCEL]); + SendDlgItemMessage(m_hwnd, IDC_CLOSE, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Close session"), BATF_UNICODE); + m_dwFlags &= ~MWF_SAVEBTN_SAV; + } + m_textLen = len; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// generic handler for the WM_COPY message in message log/chat history richedit control(s). +// it filters out the invisible event boundary markers from the text copied to the clipboard. +// WINE Fix: overwrite clippboad data from original control data + +LRESULT CMsgDialog::WMCopyHandler(UINT msg, WPARAM wParam, LPARAM lParam) +{ + LRESULT result = mir_callNextSubclass(m_log.GetHwnd(), stubLogProc, msg, wParam, lParam); + + ptrA szFromStream(m_log.GetRichTextRtf(true, true)); + if (szFromStream != nullptr) { + ptrW converted(mir_utf8decodeW(szFromStream)); + if (converted != nullptr) { + Utils::FilterEventMarkers(converted); + Utils::CopyToClipBoard(converted, m_log.GetHwnd()); + } + } + + return result; +} diff --git a/plugins/TabSRMM/src/msgdlgutils.cpp b/plugins/TabSRMM/src/msgdlgutils.cpp index 02a7fdeb0f..17ff931222 100644 --- a/plugins/TabSRMM/src/msgdlgutils.cpp +++ b/plugins/TabSRMM/src/msgdlgutils.cpp @@ -65,12 +65,90 @@ bool TSAPI IsCustomEvent(int eventType) return true; } +///////////////////////////////////////////////////////////////////////////////////////// +// checking if theres's protected text at the point +// emulates EN_LINK WM_NOTIFY to parent to process links + +BOOL TSAPI CheckCustomLink(HWND hwndRich, POINT *ptClient, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL bUrlNeeded) +{ + long res = 0, cnt = 0; + long cpMin = 0, cpMax = 0; + POINT ptEnd = { 0 }; + IRichEditOle *RichEditOle = nullptr; + ITextDocument *TextDocument = nullptr; + ITextRange *TextRange = nullptr; + ITextFont *TextFont = nullptr; + BOOL bIsCustomLink = FALSE; + + POINT pt = *ptClient; + ClientToScreen(hwndRich, &pt); + + do { + if (!SendMessage(hwndRich, EM_GETOLEINTERFACE, 0, (LPARAM)& RichEditOle)) break; + if (RichEditOle->QueryInterface(IID_ITextDocument, (void **)& TextDocument) != S_OK) break; + if (TextDocument->RangeFromPoint(pt.x, pt.y, &TextRange) != S_OK) break; + + TextRange->GetStart(&cpMin); + cpMax = cpMin + 1; + TextRange->SetEnd(cpMax); + + if (TextRange->GetFont(&TextFont) != S_OK) + break; + + TextFont->GetProtected(&res); + if (res != tomTrue) + break; + + TextRange->GetPoint(tomEnd + TA_BOTTOM + TA_RIGHT, &ptEnd.x, &ptEnd.y); + if (pt.x > ptEnd.x || pt.y > ptEnd.y) + break; + + if (bUrlNeeded) { + TextRange->GetStoryLength(&cnt); + for (; cpMin > 0; cpMin--) { + res = tomTrue; + TextRange->SetIndex(tomCharacter, cpMin + 1, tomTrue); + TextFont->GetProtected(&res); + if (res != tomTrue) { cpMin++; break; } + } + for (cpMax--; cpMax < cnt; cpMax++) { + res = tomTrue; + TextRange->SetIndex(tomCharacter, cpMax + 1, tomTrue); + TextFont->GetProtected(&res); + if (res != tomTrue) + break; + } + } + + bIsCustomLink = (cpMin < cpMax); + } while (FALSE); + + if (TextFont) TextFont->Release(); + if (TextRange) TextRange->Release(); + if (TextDocument) TextDocument->Release(); + if (RichEditOle) RichEditOle->Release(); + + if (bIsCustomLink) { + ENLINK enlink = {}; + enlink.nmhdr.hwndFrom = hwndRich; + enlink.nmhdr.idFrom = IDC_SRMM_LOG; + enlink.nmhdr.code = EN_LINK; + enlink.msg = uMsg; + enlink.wParam = wParam; + enlink.lParam = lParam; + enlink.chrg.cpMin = cpMin; + enlink.chrg.cpMax = cpMax; + SendMessage(GetParent(hwndRich), WM_NOTIFY, IDC_SRMM_LOG, (LPARAM)& enlink); + } + return bIsCustomLink; +} + ///////////////////////////////////////////////////////////////////////////////////////// // reorder tabs within a container. bSavePos indicates whether the new position should // be saved to the contacts db record (if so, the container will try to open the tab // at the saved position later) -void TSAPI RearrangeTab(HWND hwndDlg, const CTabBaseDlg *dat, int iMode, BOOL bSavePos) +void TSAPI RearrangeTab(HWND hwndDlg, const CMsgDialog *dat, int iMode, BOOL bSavePos) { if (dat == nullptr || !IsWindow(hwndDlg)) return; @@ -100,7 +178,7 @@ void TSAPI RearrangeTab(HWND hwndDlg, const CTabBaseDlg *dat, int iMode, BOOL bS // subclassing for the save as file dialog (needed to set it to thumbnail view on Windows 2000 // or later -static UINT_PTR CALLBACK OpenFileSubclass(HWND hwnd, UINT msg, WPARAM, LPARAM lParam) +UINT_PTR CALLBACK OpenFileSubclass(HWND hwnd, UINT msg, WPARAM, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: @@ -121,382 +199,6 @@ static UINT_PTR CALLBACK OpenFileSubclass(HWND hwnd, UINT msg, WPARAM, LPARAM lP return FALSE; } -///////////////////////////////////////////////////////////////////////////////////////// -// saves a contact picture to disk -// takes hbm (bitmap handle) and bool isOwnPic (1 == save the picture as your own avatar) -// requires AVS service (Miranda 0.7+) - -static void SaveAvatarToFile(CTabBaseDlg *dat, HBITMAP hbm, int isOwnPic) -{ - wchar_t szFinalFilename[MAX_PATH]; - time_t t = time(0); - struct tm *lt = localtime(&t); - DWORD setView = 1; - - wchar_t szTimestamp[100]; - mir_snwprintf(szTimestamp, L"%04u %02u %02u_%02u%02u", lt->tm_year + 1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min); - - wchar_t *szProto = mir_a2u(dat->m_cache->getActiveProto()); - - wchar_t szFinalPath[MAX_PATH]; - mir_snwprintf(szFinalPath, L"%s\\%s", M.getSavedAvatarPath(), szProto); - mir_free(szProto); - - if (CreateDirectory(szFinalPath, nullptr) == 0) { - if (GetLastError() != ERROR_ALREADY_EXISTS) { - MessageBox(nullptr, TranslateT("Error creating destination directory"), - TranslateT("Save contact picture"), MB_OK | MB_ICONSTOP); - return; - } - } - - wchar_t szBaseName[MAX_PATH]; - if (isOwnPic) - mir_snwprintf(szBaseName, L"My Avatar_%s", szTimestamp); - else - mir_snwprintf(szBaseName, L"%s_%s", dat->m_cache->getNick(), szTimestamp); - - mir_snwprintf(szFinalFilename, L"%s.png", szBaseName); - - // do not allow / or \ or % in the filename - Utils::sanitizeFilename(szFinalFilename); - - wchar_t filter[MAX_PATH]; - mir_snwprintf(filter, L"%s%c*.bmp;*.png;*.jpg;*.gif%c%c", TranslateT("Image files"), 0, 0, 0); - - OPENFILENAME ofn = { 0 }; - ofn.lpstrDefExt = L"png"; - ofn.lpstrFilter = filter; - ofn.Flags = OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ENABLESIZING | OFN_ENABLEHOOK; - ofn.lpfnHook = OpenFileSubclass; - ofn.lStructSize = sizeof(ofn); - ofn.lpstrFile = szFinalFilename; - ofn.lpstrInitialDir = szFinalPath; - ofn.nMaxFile = MAX_PATH; - ofn.nMaxFileTitle = MAX_PATH; - ofn.lCustData = (LPARAM)&setView; - if (GetSaveFileName(&ofn)) { - if (PathFileExists(szFinalFilename)) - if (MessageBox(nullptr, TranslateT("The file exists. Do you want to overwrite it?"), TranslateT("Save contact picture"), MB_YESNO | MB_ICONQUESTION) == IDNO) - return; - - IMGSRVC_INFO ii; - ii.cbSize = sizeof(ii); - ii.pwszName = szFinalFilename; - ii.hbm = hbm; - ii.dwMask = IMGI_HBITMAP; - ii.fif = FIF_UNKNOWN; // get the format from the filename extension. png is default. - Image_Save(&ii); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -// flash a tab icon if mode = true, otherwise restore default icon -// store flashing state into bState - -void CTabBaseDlg::FlashTab(bool bInvertMode) -{ - if (bInvertMode) - m_bTabFlash = !m_bTabFlash; - - TCITEM item = {}; - item.mask = TCIF_IMAGE; - TabCtrl_SetItem(m_hwndParent, m_iTabID, &item); - if (m_pContainer->m_dwFlags & CNT_SIDEBAR) - m_pContainer->m_pSideBar->updateSession(this); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// calculates avatar layouting, based on splitter position to find the optimal size -// for the avatar w/o disturbing the toolbar too much. - -void CTabBaseDlg::CalcDynamicAvatarSize(BITMAP *bminfo) -{ - if (m_dwFlags & MWF_WASBACKGROUNDCREATE || m_pContainer->m_dwFlags & CNT_DEFERREDCONFIGURE || m_pContainer->m_dwFlags & CNT_CREATE_MINIMIZED || IsIconic(m_pContainer->m_hwnd)) - return; // at this stage, the layout is not yet ready... - - RECT rc; - GetClientRect(m_hwnd, &rc); - - BOOL bBottomToolBar = m_pContainer->m_dwFlags & CNT_BOTTOMTOOLBAR; - BOOL bToolBar = m_pContainer->m_dwFlags & CNT_HIDETOOLBAR ? 0 : 1; - int iSplitOffset = m_bIsAutosizingInput ? 1 : 0; - - double picAspect = (bminfo->bmWidth == 0 || bminfo->bmHeight == 0) ? 1.0 : (double)(bminfo->bmWidth / (double)bminfo->bmHeight); - double picProjectedWidth = (double)((m_dynaSplitter - ((bBottomToolBar && bToolBar) ? DPISCALEX_S(24) : 0) + ((m_bShowUIElements) ? DPISCALEX_S(28) : DPISCALEX_S(2)))) * picAspect; - - if ((rc.right - (int)picProjectedWidth) > (m_iButtonBarReallyNeeds) && !PluginConfig.m_bAlwaysFullToolbarWidth && bToolBar) - m_iRealAvatarHeight = m_dynaSplitter + 3 + (m_bShowUIElements ? DPISCALEY_S(28) : DPISCALEY_S(2)); - else - m_iRealAvatarHeight = m_dynaSplitter + DPISCALEY_S(6) + DPISCALEY_S(iSplitOffset); - - m_iRealAvatarHeight -= ((bBottomToolBar&&bToolBar) ? DPISCALEY_S(22) : 0); - - if (PluginConfig.m_LimitStaticAvatarHeight > 0) - m_iRealAvatarHeight = min(m_iRealAvatarHeight, PluginConfig.m_LimitStaticAvatarHeight); - - if (M.GetByte(m_hContact, "dontscaleavatars", M.GetByte("dontscaleavatars", 0))) - m_iRealAvatarHeight = min(bminfo->bmHeight, m_iRealAvatarHeight); - - double aspect = (bminfo->bmHeight != 0) ? (double)m_iRealAvatarHeight / (double)bminfo->bmHeight : 1.0; - double newWidth = (double)bminfo->bmWidth * aspect; - if (newWidth > (double)(rc.right) * 0.8) - newWidth = (double)(rc.right) * 0.8; - m_pic.cy = m_iRealAvatarHeight + 2; - m_pic.cx = (int)newWidth + 2; -} - -int CTabBaseDlg::MsgWindowUpdateMenu(HMENU submenu, int menuID) -{ - bool bInfoPanel = m_pPanel.isActive(); - - if (menuID == MENU_TABCONTEXT) { - EnableMenuItem(submenu, ID_TABMENU_LEAVECHATROOM, (isChat() && ProtoServiceExists(m_szProto, PS_LEAVECHAT)) ? MF_ENABLED : MF_DISABLED); - EnableMenuItem(submenu, ID_TABMENU_ATTACHTOCONTAINER, (M.GetByte("useclistgroups", 0) || M.GetByte("singlewinmode", 0)) ? MF_GRAYED : MF_ENABLED); - EnableMenuItem(submenu, ID_TABMENU_CLEARSAVEDTABPOSITION, (M.GetDword(m_hContact, "tabindex", -1) != -1) ? MF_ENABLED : MF_GRAYED); - } - else if (menuID == MENU_PICMENU) { - wchar_t *szText = nullptr; - char avOverride = (char)M.GetByte(m_hContact, "hideavatar", -1); - HMENU visMenu = GetSubMenu(submenu, 0); - BOOL picValid = bInfoPanel ? (m_hOwnPic != nullptr) : (m_ace && m_ace->hbmPic && m_ace->hbmPic != PluginConfig.g_hbmUnknown); - - MENUITEMINFO mii = { 0 }; - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_STRING; - - EnableMenuItem(submenu, ID_PICMENU_SAVETHISPICTUREAS, MF_BYCOMMAND | (picValid ? MF_ENABLED : MF_GRAYED)); - - CheckMenuItem(visMenu, ID_VISIBILITY_DEFAULT, MF_BYCOMMAND | (avOverride == -1 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(visMenu, ID_VISIBILITY_HIDDENFORTHISCONTACT, MF_BYCOMMAND | (avOverride == 0 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(visMenu, ID_VISIBILITY_VISIBLEFORTHISCONTACT, MF_BYCOMMAND | (avOverride == 1 ? MF_CHECKED : MF_UNCHECKED)); - - CheckMenuItem(submenu, ID_PICMENU_ALWAYSKEEPTHEBUTTONBARATFULLWIDTH, MF_BYCOMMAND | (PluginConfig.m_bAlwaysFullToolbarWidth ? MF_CHECKED : MF_UNCHECKED)); - if (!bInfoPanel) { - EnableMenuItem(submenu, ID_PICMENU_SETTINGS, MF_BYCOMMAND | (ServiceExists(MS_AV_GETAVATARBITMAP) ? MF_ENABLED : MF_GRAYED)); - szText = TranslateT("Contact picture settings..."); - EnableMenuItem(submenu, 0, MF_BYPOSITION | MF_ENABLED); - } - else { - EnableMenuItem(submenu, 0, MF_BYPOSITION | MF_GRAYED); - EnableMenuItem(submenu, ID_PICMENU_SETTINGS, MF_BYCOMMAND | ((ServiceExists(MS_AV_SETMYAVATARW) && CallService(MS_AV_CANSETMYAVATAR, (WPARAM)(m_cache->getActiveProto()), 0)) ? MF_ENABLED : MF_GRAYED)); - szText = TranslateT("Set your avatar..."); - } - mii.dwTypeData = szText; - mii.cch = (int)mir_wstrlen(szText) + 1; - SetMenuItemInfo(submenu, ID_PICMENU_SETTINGS, FALSE, &mii); - } - else if (menuID == MENU_PANELPICMENU) { - HMENU visMenu = GetSubMenu(submenu, 0); - char avOverride = (char)M.GetByte(m_hContact, "hideavatar", -1); - - CheckMenuItem(visMenu, ID_VISIBILITY_DEFAULT, MF_BYCOMMAND | (avOverride == -1 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(visMenu, ID_VISIBILITY_HIDDENFORTHISCONTACT, MF_BYCOMMAND | (avOverride == 0 ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(visMenu, ID_VISIBILITY_VISIBLEFORTHISCONTACT, MF_BYCOMMAND | (avOverride == 1 ? MF_CHECKED : MF_UNCHECKED)); - - EnableMenuItem(submenu, ID_PICMENU_SETTINGS, MF_BYCOMMAND | (ServiceExists(MS_AV_GETAVATARBITMAP) ? MF_ENABLED : MF_GRAYED)); - EnableMenuItem(submenu, ID_PANELPICMENU_SAVETHISPICTUREAS, MF_BYCOMMAND | ((m_ace && m_ace->hbmPic && m_ace->hbmPic != PluginConfig.g_hbmUnknown) ? MF_ENABLED : MF_GRAYED)); - } - return 0; -} - -int CTabBaseDlg::MsgWindowMenuHandler(int selection, int menuId) -{ - if (menuId == MENU_PICMENU || menuId == MENU_PANELPICMENU || menuId == MENU_TABCONTEXT) { - switch (selection) { - case ID_TABMENU_ATTACHTOCONTAINER: - CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_SELECTCONTAINER), m_hwnd, SelectContainerDlgProc, (LPARAM)m_hwnd); - return 1; - case ID_TABMENU_CONTAINEROPTIONS: - if (m_pContainer->m_hWndOptions == nullptr) - CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_CONTAINEROPTIONS), m_hwnd, DlgProcContainerOptions, (LPARAM)m_pContainer); - return 1; - case ID_TABMENU_CLOSECONTAINER: - SendMessage(m_pContainer->m_hwnd, WM_CLOSE, 0, 0); - return 1; - case ID_TABMENU_CLOSETAB: - PostMessage(m_hwnd, WM_CLOSE, 1, 0); - return 1; - case ID_TABMENU_SAVETABPOSITION: - db_set_dw(m_hContact, SRMSGMOD_T, "tabindex", m_iTabID * 100); - break; - case ID_TABMENU_CLEARSAVEDTABPOSITION: - db_unset(m_hContact, SRMSGMOD_T, "tabindex"); - break; - case ID_TABMENU_LEAVECHATROOM: - if (isChat() && m_hContact != 0) { - char *szProto = GetContactProto(m_hContact); - if (szProto) - CallProtoService(szProto, PS_LEAVECHAT, m_hContact, 0); - } - return 1; - - case ID_VISIBILITY_DEFAULT: - case ID_VISIBILITY_HIDDENFORTHISCONTACT: - case ID_VISIBILITY_VISIBLEFORTHISCONTACT: - { - BYTE avOverrideMode; - if (selection == ID_VISIBILITY_DEFAULT) - avOverrideMode = -1; - else if (selection == ID_VISIBILITY_VISIBLEFORTHISCONTACT) - avOverrideMode = 1; - else - avOverrideMode = 0; - db_set_b(m_hContact, SRMSGMOD_T, "hideavatar", avOverrideMode); - } - - ShowPicture(false); - Resize(); - DM_ScrollToBottom(0, 1); - return 1; - - case ID_PICMENU_ALWAYSKEEPTHEBUTTONBARATFULLWIDTH: - PluginConfig.m_bAlwaysFullToolbarWidth = !PluginConfig.m_bAlwaysFullToolbarWidth; - db_set_b(0, SRMSGMOD_T, "alwaysfulltoolbar", (BYTE)PluginConfig.m_bAlwaysFullToolbarWidth); - Srmm_Broadcast(DM_CONFIGURETOOLBAR, 0, 1); - break; - - case ID_PICMENU_SAVETHISPICTUREAS: - if (m_pPanel.isActive()) - SaveAvatarToFile(this, m_hOwnPic, 1); - else if (m_ace) - SaveAvatarToFile(this, m_ace->hbmPic, 0); - break; - - case ID_PANELPICMENU_SAVETHISPICTUREAS: - if (m_ace) - SaveAvatarToFile(this, m_ace->hbmPic, 0); - break; - - case ID_PICMENU_SETTINGS: - if (menuId == MENU_PANELPICMENU) - CallService(MS_AV_CONTACTOPTIONS, m_hContact, 0); - else if (menuId == MENU_PICMENU) { - if (m_pPanel.isActive()) { - if (ServiceExists(MS_AV_SETMYAVATARW) && CallService(MS_AV_CANSETMYAVATAR, (WPARAM)(m_cache->getActiveProto()), 0)) - CallService(MS_AV_SETMYAVATARW, (WPARAM)(m_cache->getActiveProto()), 0); - } - else - CallService(MS_AV_CONTACTOPTIONS, m_hContact, 0); - } - return 1; - } - } - else if (menuId == MENU_LOGMENU) { - switch (selection) { - case ID_MESSAGELOGSETTINGS_GLOBAL: - g_plugin.openOptions(nullptr, L"Message sessions", L"Message log"); - return 1; - - case ID_MESSAGELOGSETTINGS_FORTHISCONTACT: - CallService(MS_TABMSG_SETUSERPREFS, m_hContact, 0); - return 1; - } - } - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// update the status bar field which displays the number of characters in the input area -// and various indicators (caps lock, num lock, insert mode). - -void CTabBaseDlg::UpdateReadChars() const -{ - if (!m_pContainer->m_hwndStatus || m_pContainer->m_hwndActive != m_hwnd) - return; - - int len; - if (isChat()) - len = GetWindowTextLength(m_message.GetHwnd()); - else { - // retrieve text length in UTF8 bytes, because this is the relevant length for most protocols - GETTEXTLENGTHEX gtxl = { 0 }; - gtxl.codepage = CP_UTF8; - gtxl.flags = GTL_DEFAULT | GTL_PRECISE | GTL_NUMBYTES; - - len = m_message.SendMsg(EM_GETTEXTLENGTHEX, (WPARAM)>xl, 0); - } - - BOOL fCaps = (GetKeyState(VK_CAPITAL) & 1); - BOOL fNum = (GetKeyState(VK_NUMLOCK) & 1); - - wchar_t szBuf[20]; szBuf[0] = 0; - if (m_bInsertMode) - mir_wstrcat(szBuf, L"O"); - if (fCaps) - mir_wstrcat(szBuf, L"C"); - if (fNum) - mir_wstrcat(szBuf, L"N"); - if (m_bInsertMode || fCaps || fNum) - mir_wstrcat(szBuf, L" | "); - - wchar_t buf[128]; - mir_snwprintf(buf, L"%s%s %d/%d", szBuf, m_lcID, m_iOpenJobs, len); - SendMessage(m_pContainer->m_hwndStatus, SB_SETTEXT, 1, (LPARAM)buf); - if (PluginConfig.m_visualMessageSizeIndicator) - InvalidateRect(m_pContainer->m_hwndStatus, nullptr, FALSE); -} - -void CTabBaseDlg::UpdateSaveAndSendButton() -{ - GETTEXTLENGTHEX gtxl = { 0 }; - gtxl.codepage = CP_UTF8; - gtxl.flags = GTL_DEFAULT | GTL_PRECISE | GTL_NUMBYTES; - - int len = SendDlgItemMessage(m_hwnd, IDC_SRMM_MESSAGE, EM_GETTEXTLENGTHEX, (WPARAM)>xl, 0); - if (len && GetSendButtonState(m_hwnd) == PBS_DISABLED) - EnableSendButton(true); - else if (len == 0 && GetSendButtonState(m_hwnd) != PBS_DISABLED) - EnableSendButton(false); - - if (len) { // looks complex but avoids flickering on the button while typing. - if (!(m_dwFlags & MWF_SAVEBTN_SAV)) { - SendDlgItemMessage(m_hwnd, IDC_CLOSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)PluginConfig.g_buttonBarIcons[ICON_BUTTON_SAVE]); - SendDlgItemMessage(m_hwnd, IDC_CLOSE, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Save and close session"), BATF_UNICODE); - m_dwFlags |= MWF_SAVEBTN_SAV; - } - } - else { - SendDlgItemMessage(m_hwnd, IDC_CLOSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)PluginConfig.g_buttonBarIcons[ICON_BUTTON_CANCEL]); - SendDlgItemMessage(m_hwnd, IDC_CLOSE, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Close session"), BATF_UNICODE); - m_dwFlags &= ~MWF_SAVEBTN_SAV; - } - m_textLen = len; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// update all status bar fields and force a redraw of the status bar. - -void CTabBaseDlg::tabUpdateStatusBar() const -{ - if (m_pContainer->m_hwndStatus && m_pContainer->m_hwndActive == m_hwnd) { - if (!isChat()) { - if (m_wszStatusBar[0]) { - SendMessage(m_pContainer->m_hwndStatus, SB_SETICON, 0, (LPARAM)PluginConfig.g_buttonBarIcons[ICON_DEFAULT_TYPING]); - SendMessage(m_pContainer->m_hwndStatus, SB_SETTEXT, 0, (LPARAM)m_wszStatusBar); - } - else if (m_bStatusSet) { - SendMessage(m_pContainer->m_hwndStatus, SB_SETICON, 0, (LPARAM)m_szStatusIcon); - SendMessage(m_pContainer->m_hwndStatus, SB_SETTEXT, 0, (LPARAM)m_szStatusText.c_str()); - } - else { - SendMessage(m_pContainer->m_hwndStatus, SB_SETICON, 0, 0); - DM_UpdateLastMessage(); - } - } - else { - if (m_bStatusSet) { - SendMessage(m_pContainer->m_hwndStatus, SB_SETICON, 0, (LPARAM)m_szStatusIcon); - SendMessage(m_pContainer->m_hwndStatus, SB_SETTEXT, 0, (LPARAM)m_szStatusText.c_str()); - } - else SendMessage(m_pContainer->m_hwndStatus, SB_SETICON, 0, 0); - } - UpdateReadChars(); - InvalidateRect(m_pContainer->m_hwndStatus, nullptr, TRUE); - SendMessage(m_pContainer->m_hwndStatus, WM_USER + 101, 0, (LPARAM)this); - } -} - ///////////////////////////////////////////////////////////////////////////////////////// // provide user feedback via icons on tabs.Used to indicate "send in progress" or // any error state. @@ -504,7 +206,7 @@ void CTabBaseDlg::tabUpdateStatusBar() const // NOT used for typing notification feedback as this is handled directly from the // MTN handler. -void TSAPI HandleIconFeedback(CTabBaseDlg *dat, HICON iIcon) +void TSAPI HandleIconFeedback(CMsgDialog *dat, HICON iIcon) { TCITEM item = {}; @@ -531,7 +233,7 @@ void TSAPI ProcessAvatarChange(HWND hwnd, LPARAM lParam) { if (((LPNMHDR)lParam)->code == NM_AVATAR_CHANGED) { HWND hwndDlg = GetParent(hwnd); - CTabBaseDlg *dat = (CTabBaseDlg*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); if (!dat) return; @@ -544,93 +246,6 @@ void TSAPI ProcessAvatarChange(HWND hwnd, LPARAM lParam) } } -///////////////////////////////////////////////////////////////////////////////////////// -// retrieve the visiblity of the avatar window, depending on the global setting -// and local mode - -bool CTabBaseDlg::GetAvatarVisibility() -{ - BYTE bAvatarMode = m_pContainer->m_avatarMode; - BYTE bOwnAvatarMode = m_pContainer->m_ownAvatarMode; - char hideOverride = (char)M.GetByte(m_hContact, "hideavatar", -1); - - // infopanel visible, consider own avatar display - m_bShowAvatar = false; - - if (m_pPanel.isActive() && bAvatarMode != 3) { - if (!bOwnAvatarMode) { - m_bShowAvatar = (m_hOwnPic && m_hOwnPic != PluginConfig.g_hbmUnknown); - if (!m_hwndContactPic) - m_hwndContactPic = CreateWindowEx(WS_EX_TOPMOST, AVATAR_CONTROL_CLASS, L"", WS_VISIBLE | WS_CHILD, 1, 1, 1, 1, GetDlgItem(m_hwnd, IDC_CONTACTPIC), (HMENU)nullptr, nullptr, nullptr); - } - - switch (bAvatarMode) { - case 2: - m_bShowInfoAvatar = false; - break; - case 0: - m_bShowInfoAvatar = true; - case 1: - HBITMAP hbm = ((m_ace && !(m_ace->dwFlags & AVS_HIDEONCLIST)) ? m_ace->hbmPic : nullptr); - if (hbm == nullptr && !bAvatarMode) { - m_bShowInfoAvatar = false; - break; - } - - if (!m_hwndPanelPic) { - m_hwndPanelPic = CreateWindowEx(WS_EX_TOPMOST, AVATAR_CONTROL_CLASS, L"", WS_VISIBLE | WS_CHILD, 1, 1, 1, 1, m_hwndPanelPicParent, (HMENU)7000, nullptr, nullptr); - if (m_hwndPanelPic) - SendMessage(m_hwndPanelPic, AVATAR_SETAEROCOMPATDRAWING, 0, TRUE); - } - - if (bAvatarMode != 0) - m_bShowInfoAvatar = (hbm && hbm != PluginConfig.g_hbmUnknown); - break; - } - - if (m_bShowInfoAvatar) - m_bShowInfoAvatar = hideOverride == 0 ? false : m_bShowInfoAvatar; - else - m_bShowInfoAvatar = hideOverride == 1 ? true : m_bShowInfoAvatar; - - Utils::setAvatarContact(m_hwndPanelPic, m_hContact); - SendMessage(m_hwndContactPic, AVATAR_SETPROTOCOL, 0, (LPARAM)m_cache->getActiveProto()); - } - else { - m_bShowInfoAvatar = false; - - switch (bAvatarMode) { - case 0: // globally on - m_bShowAvatar = true; -LBL_Check: - if (!m_hwndContactPic) - m_hwndContactPic = CreateWindowEx(WS_EX_TOPMOST, AVATAR_CONTROL_CLASS, L"", WS_VISIBLE | WS_CHILD, 1, 1, 1, 1, GetDlgItem(m_hwnd, IDC_CONTACTPIC), (HMENU)nullptr, nullptr, nullptr); - break; - case 2: // globally OFF - m_bShowAvatar = false; - break; - case 3: // on, if present - case 1: - HBITMAP hbm = (m_ace && !(m_ace->dwFlags & AVS_HIDEONCLIST)) ? m_ace->hbmPic : nullptr; - m_bShowAvatar = (hbm && hbm != PluginConfig.g_hbmUnknown); - goto LBL_Check; - } - - if (m_bShowAvatar) - m_bShowAvatar = hideOverride == 0 ? 0 : m_bShowAvatar; - else - m_bShowAvatar = hideOverride == 1 ? 1 : m_bShowAvatar; - - // reloads avatars - if (m_hwndPanelPic) { // shows contact or user picture, depending on panel visibility - SendMessage(m_hwndContactPic, AVATAR_SETPROTOCOL, 0, (LPARAM)m_cache->getActiveProto()); - Utils::setAvatarContact(m_hwndPanelPic, m_hContact); - } - else Utils::setAvatarContact(m_hwndContactPic, m_hContact); - } - return m_bShowAvatar; -} - ///////////////////////////////////////////////////////////////////////////////////////// // checks, if there is a valid smileypack installed for the given protocol @@ -703,353 +318,6 @@ wchar_t* TSAPI QuoteText(const wchar_t *text) return strout; } -void CTabBaseDlg::AdjustBottomAvatarDisplay() -{ - GetAvatarVisibility(); - - bool bInfoPanel = m_pPanel.isActive(); - HBITMAP hbm = (bInfoPanel && m_pContainer->m_avatarMode != 3) ? m_hOwnPic : (m_ace ? m_ace->hbmPic : PluginConfig.g_hbmUnknown); - if (hbm) { - if (m_dynaSplitter == 0 || m_iSplitterY == 0) - LoadSplitter(); - m_dynaSplitter = m_iSplitterY - DPISCALEY_S(34); - DM_RecalcPictureSize(); - Utils::showDlgControl(m_hwnd, IDC_CONTACTPIC, m_bShowAvatar ? SW_SHOW : SW_HIDE); - InvalidateRect(GetDlgItem(m_hwnd, IDC_CONTACTPIC), nullptr, TRUE); - } - else { - Utils::showDlgControl(m_hwnd, IDC_CONTACTPIC, m_bShowAvatar ? SW_SHOW : SW_HIDE); - m_pic.cy = m_pic.cx = DPISCALEY_S(60); - InvalidateRect(GetDlgItem(m_hwnd, IDC_CONTACTPIC), nullptr, TRUE); - } -} - -void CTabBaseDlg::ShowPicture(bool showNewPic) -{ - if (!m_pPanel.isActive()) - m_pic.cy = m_pic.cx = DPISCALEY_S(60); - - if (showNewPic) { - if (m_pPanel.isActive() && m_pContainer->m_avatarMode != 3) { - if (!m_hwndPanelPic) { - InvalidateRect(m_hwnd, nullptr, TRUE); - UpdateWindow(m_hwnd); - Resize(); - } - return; - } - AdjustBottomAvatarDisplay(); - } - else { - m_bShowAvatar = !m_bShowAvatar; - db_set_b(m_hContact, SRMSGMOD_T, "MOD_ShowPic", m_bShowAvatar); - } - - RECT rc; - GetWindowRect(GetDlgItem(m_hwnd, IDC_CONTACTPIC), &rc); - if (m_minEditBoxSize.cy + DPISCALEY_S(3) > m_iSplitterY) - SendMessage(m_hwnd, DM_SPLITTERMOVED, (WPARAM)rc.bottom - m_minEditBoxSize.cy, (LPARAM)GetDlgItem(m_hwnd, IDC_SPLITTERY)); - if (!showNewPic) - SetDialogToType(); - else - Resize(); -} - -void CTabBaseDlg::FlashOnClist(MEVENT hEvent, DBEVENTINFO *dbei) -{ - m_dwTickLastEvent = GetTickCount(); - - if ((GetForegroundWindow() != m_pContainer->m_hwnd || m_pContainer->m_hwndActive != m_hwnd) && !(dbei->flags & DBEF_SENT) && dbei->eventType == EVENTTYPE_MESSAGE) { - m_dwUnread++; - UpdateTrayMenu(this, (WORD)(m_cache->getActiveStatus()), m_cache->getActiveProto(), m_wszStatus, m_hContact, 0); - if (nen_options.bTraySupport) - return; - } - if (hEvent == 0) - return; - - if (!PluginConfig.m_bFlashOnClist) - return; - - if ((GetForegroundWindow() != m_pContainer->m_hwnd || m_pContainer->m_hwndActive != m_hwnd) && !(dbei->flags & DBEF_SENT) && dbei->eventType == EVENTTYPE_MESSAGE && !(m_dwFlagsEx & MWF_SHOW_FLASHCLIST)) { - CLISTEVENT cle = {}; - cle.hContact = m_hContact; - cle.hDbEvent = hEvent; - cle.hIcon = Skin_LoadIcon(SKINICON_EVENT_MESSAGE); - cle.pszService = MS_MSG_READMESSAGE; - g_clistApi.pfnAddEvent(&cle); - - m_dwFlagsEx |= MWF_SHOW_FLASHCLIST; - m_hFlashingEvent = hEvent; - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -static wchar_t tszRtfBreaks[] = L" \\\n\r"; - -static void CreateColorMap(CMStringW &Text, int iCount, COLORREF *pSrc, int *pDst) -{ - const wchar_t *pszText = Text; - int iIndex = 1; - - static const wchar_t *lpszFmt = L"\\red%[^ \x5b\\]\\green%[^ \x5b\\]\\blue%[^ \x5b;];"; - wchar_t szRed[10], szGreen[10], szBlue[10]; - - const wchar_t *p1 = wcsstr(pszText, L"\\colortbl"); - if (!p1) - return; - - const wchar_t *pEnd = wcschr(p1, '}'); - - const wchar_t *p2 = wcsstr(p1, L"\\red"); - - for (int i = 0; i < iCount; i++) - pDst[i] = -1; - - while (p2 && p2 < pEnd) { - if (swscanf(p2, lpszFmt, &szRed, &szGreen, &szBlue) > 0) { - for (int i = 0; i < iCount; i++) { - if (pSrc[i] == RGB(_wtoi(szRed), _wtoi(szGreen), _wtoi(szBlue))) - pDst[i] = iIndex; - } - } - iIndex++; - p1 = p2; - p1++; - - p2 = wcsstr(p1, L"\\red"); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -// convert rich edit code to bbcode (if wanted). Otherwise, strip all RTF formatting -// tags and return plain text - -static int RtfColorToIndex(int iNumColors, int *pIndex, int iCol) -{ - for (int i = 0; i < iNumColors; i++) - if (pIndex[i] == iCol) - return i; - - return -1; -} - -BOOL CTabBaseDlg::DoRtfToTags(CMStringW &pszText) const -{ - if (pszText.IsEmpty()) - return FALSE; - - // used to filter out attributes which are already set for the default message input area font - LOGFONTA lf = m_pContainer->m_theme.logFonts[MSGFONTID_MESSAGEAREA]; - - // create an index of colors in the module and map them to - // corresponding colors in the RTF color table - int iNumColors = Utils::rtf_clrs.getCount(); - int *pIndex = (int*)_alloca(iNumColors * sizeof(int)); - COLORREF *pColors = (COLORREF*)_alloca(iNumColors * sizeof(COLORREF)); - for (int i = 0; i < iNumColors; i++) - pColors[i] = Utils::rtf_clrs[i].clr; - CreateColorMap(pszText, iNumColors, pColors, pIndex); - - // scan the file for rtf commands and remove or parse them - int idx = pszText.Find(L"\\pard"); - if (idx == -1) { - if ((idx = pszText.Find(L"\\ltrpar")) == -1) - return FALSE; - idx += 7; - } - else idx += 5; - - MODULEINFO *mi = (isChat()) ? m_si->pMI : nullptr; - - bool bInsideColor = false, bInsideUl = false; - CMStringW res; - - // iterate through all characters, if rtf control character found then take action - for (const wchar_t *p = pszText.GetString() + idx; *p;) { - switch (*p) { - case '\\': - if (p[1] == '\\' || p[1] == '{' || p[1] == '}') { // escaped characters - res.AppendChar(p[1]); - p += 2; break; - } - if (p[1] == '~') { // non-breaking space - res.AppendChar(0xA0); - p += 2; break; - } - - if (!wcsncmp(p, L"\\cf", 3)) { // foreground color - int iCol = _wtoi(p + 3); - int iInd = RtfColorToIndex(iNumColors, pIndex, iCol); - - if (iCol > 0) { - if (isChat()) { - if (mi && mi->bColor) { - if (iInd >= 0) { - if (!(res.IsEmpty() && m_pContainer->m_theme.fontColors[MSGFONTID_MESSAGEAREA] == pColors[iInd])) - res.AppendFormat(L"%%c%u", iInd); - } - else if (!res.IsEmpty()) - res.Append(L"%%C"); - } - } - else res.AppendFormat((iInd >= 0) ? (bInsideColor ? L"[/color][color=%s]" : L"[color=%s]") : (bInsideColor ? L"[/color]" : L""), Utils::rtf_clrs[iInd].szName); - } - - bInsideColor = iInd >= 0; - } - else if (!wcsncmp(p, L"\\highlight", 10)) { // background color - if (isChat()) { - if (mi && mi->bBkgColor) { - int iInd = RtfColorToIndex(iNumColors, pIndex, _wtoi(p + 10)); - if (iInd >= 0) { - // if the entry field is empty & the color passed is the back color, skip it - if (!(res.IsEmpty() && m_pContainer->m_theme.inputbg == pColors[iInd])) - res.AppendFormat(L"%%f%u", iInd); - } - else if (!res.IsEmpty()) - res.AppendFormat(L"%%F"); - } - } - } - else if (!wcsncmp(p, L"\\line", 5)) { // soft line break; - res.AppendChar('\n'); - } - else if (!wcsncmp(p, L"\\endash", 7)) { - res.AppendChar(0x2013); - } - else if (!wcsncmp(p, L"\\emdash", 7)) { - res.AppendChar(0x2014); - } - else if (!wcsncmp(p, L"\\bullet", 7)) { - res.AppendChar(0x2022); - } - else if (!wcsncmp(p, L"\\ldblquote", 10)) { - res.AppendChar(0x201C); - } - else if (!wcsncmp(p, L"\\rdblquote", 10)) { - res.AppendChar(0x201D); - } - else if (!wcsncmp(p, L"\\lquote", 7)) { - res.AppendChar(0x2018); - } - else if (!wcsncmp(p, L"\\rquote", 7)) { - res.AppendChar(0x2019); - } - else if (!wcsncmp(p, L"\\b", 2)) { //bold - if (isChat()) { - if (mi && mi->bBold) - res.Append((p[2] != '0') ? L"%b" : L"%B"); - } - else { - if (!(lf.lfWeight == FW_BOLD)) // only allow bold if the font itself isn't a bold one, otherwise just strip it.. - if (m_SendFormat) - res.Append((p[2] != '0') ? L"[b]" : L"[/b]"); - } - } - else if (!wcsncmp(p, L"\\i", 2)) { // italics - if (isChat()) { - if (mi && mi->bItalics) - res.Append((p[2] != '0') ? L"%i" : L"%I"); - } - else { - if (!lf.lfItalic && m_SendFormat) - res.Append((p[2] != '0') ? L"[i]" : L"[/i]"); - } - } - else if (!wcsncmp(p, L"\\strike", 7)) { // strike-out - if (!lf.lfStrikeOut && m_SendFormat) - res.Append((p[7] != '0') ? L"[s]" : L"[/s]"); - } - else if (!wcsncmp(p, L"\\ul", 3)) { // underlined - if (isChat()) { - if (mi && mi->bUnderline) - res.Append((p[3] != '0') ? L"%u" : L"%U"); - } - else { - if (!lf.lfUnderline && m_SendFormat) { - if (p[3] == 0 || wcschr(tszRtfBreaks, p[3])) { - res.Append(L"[u]"); - bInsideUl = true; - } - else if (!wcsncmp(p + 3, L"none", 4)) { - if (bInsideUl) - res.Append(L"[/u]"); - bInsideUl = false; - } - } - } - } - else if (!wcsncmp(p, L"\\tab", 4)) { // tab - res.AppendChar('\t'); - } - else if (p[1] == '\'') { // special character - if (p[2] != ' ' && p[2] != '\\') { - wchar_t tmp[10]; - - if (p[3] != ' ' && p[3] != '\\') { - wcsncpy(tmp, p + 2, 3); - tmp[3] = 0; - } - else { - wcsncpy(tmp, p + 2, 2); - tmp[2] = 0; - } - - // convert string containing char in hex format to int. - wchar_t *stoppedHere; - res.AppendChar(wcstol(tmp, &stoppedHere, 16)); - } - } - - p++; // skip initial slash - p += wcscspn(p, tszRtfBreaks); - if (*p == ' ') - p++; - break; - - case '{': // other RTF control characters - case '}': - p++; - break; - - case '%': // double % for stupid chat engine - if (isChat()) - res.Append(L"%%"); - else - res.AppendChar(*p); - p++; - break; - - default: // other text that should not be touched - res.AppendChar(*p++); - break; - } - } - - if (bInsideColor && !isChat()) - res.Append(L"[/color]"); - if (bInsideUl) - res.Append(L"[/u]"); - - pszText = res; - return TRUE; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// retrieve both buddys and my own UIN for a message session and store them in the message window *dat -// respects metacontacts and uses the current protocol if the contact is a MC - -void CTabBaseDlg::GetMYUIN() -{ - ptrW uid(Contact_GetInfo(CNF_DISPLAYUID, 0, m_cache->getActiveProto())); - if (uid != nullptr) - wcsncpy_s(m_myUin, uid, _TRUNCATE); - else - m_myUin[0] = 0; -} - ///////////////////////////////////////////////////////////////////////////////////////// static int g_IEViewAvail = -1; @@ -1079,375 +347,6 @@ UINT TSAPI GetIEViewMode(MCONTACT hContact) ///////////////////////////////////////////////////////////////////////////////////////// -void CTabBaseDlg::SetMessageLog() -{ - unsigned int iLogMode = GetIEViewMode(m_hContact); - - if (iLogMode == WANT_IEVIEW_LOG && m_hwndIEView == nullptr) { - IEVIEWWINDOW ieWindow = {}; - ieWindow.cbSize = sizeof(IEVIEWWINDOW); - ieWindow.iType = IEW_CREATE; - ieWindow.dwMode = IEWM_TABSRMM; - ieWindow.parent = m_hwnd; - ieWindow.cx = 200; - ieWindow.cy = 200; - CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow); - m_hwndIEView = ieWindow.hwnd; - m_log.Hide(); - m_log.Enable(false); - } - else if (iLogMode == WANT_HPP_LOG && m_hwndHPP == nullptr) { - IEVIEWWINDOW ieWindow = {}; - ieWindow.cbSize = sizeof(IEVIEWWINDOW); - ieWindow.iType = IEW_CREATE; - ieWindow.dwMode = IEWM_TABSRMM; - ieWindow.parent = m_hwnd; - ieWindow.cx = 10; - ieWindow.cy = 10; - CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow); - m_hwndHPP = ieWindow.hwnd; - m_log.Hide(); - m_log.Enable(false); - } -} - -void CTabBaseDlg::FindFirstEvent() -{ - int historyMode = g_plugin.getByte(m_hContact, SRMSGSET_LOADHISTORY, -1); - if (historyMode == -1) - historyMode = (int)g_plugin.getByte(SRMSGSET_LOADHISTORY, SRMSGDEFSET_LOADHISTORY); - - m_hDbEventFirst = db_event_firstUnread(m_hContact); - - if (m_bActualHistory) - historyMode = LOADHISTORY_COUNT; - - switch (historyMode) { - case LOADHISTORY_COUNT: - int i; - MEVENT hPrevEvent; - { - DBEVENTINFO dbei = {}; - // ability to load only current session's history - if (m_bActualHistory) - i = m_cache->getSessionMsgCount(); - else - i = g_plugin.getWord(SRMSGSET_LOADCOUNT, SRMSGDEFSET_LOADCOUNT); - - for (; i > 0; i--) { - if (m_hDbEventFirst == 0) - hPrevEvent = db_event_last(m_hContact); - else - hPrevEvent = db_event_prev(m_hContact, m_hDbEventFirst); - if (hPrevEvent == 0) - break; - dbei.cbBlob = 0; - m_hDbEventFirst = hPrevEvent; - db_event_get(m_hDbEventFirst, &dbei); - if (!DbEventIsShown(&dbei)) - i++; - } - } - break; - - case LOADHISTORY_TIME: - DBEVENTINFO dbei = {}; - if (m_hDbEventFirst == 0) - dbei.timestamp = time(0); - else - db_event_get(m_hDbEventFirst, &dbei); - - DWORD firstTime = dbei.timestamp - 60 * g_plugin.getWord(SRMSGSET_LOADTIME, SRMSGDEFSET_LOADTIME); - for (;;) { - if (m_hDbEventFirst == 0) - hPrevEvent = db_event_last(m_hContact); - else - hPrevEvent = db_event_prev(m_hContact, m_hDbEventFirst); - if (hPrevEvent == 0) - break; - dbei.cbBlob = 0; - db_event_get(hPrevEvent, &dbei); - if (dbei.timestamp < firstTime) - break; - m_hDbEventFirst = hPrevEvent; - } - break; - } -} - -void CTabBaseDlg::SaveSplitter() -{ - if (m_bIsAutosizingInput) - return; - - if (m_iSplitterY < DPISCALEY_S(MINSPLITTERY) || m_iSplitterY < 0) - m_iSplitterY = DPISCALEY_S(MINSPLITTERY); - - if (m_dwFlagsEx & MWF_SHOW_SPLITTEROVERRIDE) - db_set_dw(m_hContact, SRMSGMOD_T, "splitsplity", m_iSplitterY); - else { - if (m_pContainer->m_pSettings->fPrivate) - m_pContainer->m_pSettings->iSplitterY = m_iSplitterY; - else - db_set_dw(0, SRMSGMOD_T, "splitsplity", m_iSplitterY); - } -} - -void CTabBaseDlg::LoadSplitter() -{ - if (m_bIsAutosizingInput) { - m_iSplitterY = GetDefaultMinimumInputHeight(); - return; - } - - if (!(m_dwFlagsEx & MWF_SHOW_SPLITTEROVERRIDE)) { - if (!m_pContainer->m_pSettings->fPrivate) - m_iSplitterY = (int)M.GetDword("splitsplity", 60); - else - m_iSplitterY = m_pContainer->m_pSettings->iSplitterY; - } - else m_iSplitterY = (int)M.GetDword(m_hContact, "splitsplity", M.GetDword("splitsplity", 60)); - - if (m_iSplitterY < MINSPLITTERY) - m_iSplitterY = 150; -} - -void CTabBaseDlg::PlayIncomingSound() const -{ - int iPlay = MustPlaySound(); - if (iPlay) { - if (GetForegroundWindow() == m_pContainer->m_hwnd && m_pContainer->m_hwndActive == m_hwnd) - Skin_PlaySound("RecvMsgActive"); - else - Skin_PlaySound("RecvMsgInactive"); - } -} - -///////////////////////////////////////////////////////////////////////////////////////// -// reads send format and configures the toolbar buttons -// if mode == 0, int only configures the buttons and does not change send format - -void CTabBaseDlg::GetSendFormat() -{ - m_SendFormat = M.GetDword(m_hContact, "sendformat", PluginConfig.m_SendFormat); - if (m_SendFormat == -1) // per contact override to disable it.. - m_SendFormat = 0; - else if (m_SendFormat == 0) - m_SendFormat = PluginConfig.m_SendFormat ? 1 : 0; -} - -void CSrmmWindow::LoadContactAvatar() -{ - m_ace = Utils::loadAvatarFromAVS(m_bIsMeta ? db_mc_getSrmmSub(m_hContact) : m_hContact); - - BITMAP bm; - if (m_ace && m_ace->hbmPic) - GetObject(m_ace->hbmPic, sizeof(bm), &bm); - else if (m_ace == nullptr) - GetObject(PluginConfig.g_hbmUnknown, sizeof(bm), &bm); - else - return; - - AdjustBottomAvatarDisplay(); - CalcDynamicAvatarSize(&bm); - - if (!m_pPanel.isActive() || m_pContainer->m_avatarMode == 3) { - m_iRealAvatarHeight = 0; - PostMessage(m_hwnd, WM_SIZE, 0, 0); - } - else if (m_pPanel.isActive()) - GetAvatarVisibility(); - - if (m_pWnd != nullptr) - m_pWnd->verifyDwmState(); -} - -void CSrmmWindow::LoadOwnAvatar() -{ - if (ServiceExists(MS_AV_GETMYAVATAR)) - m_ownAce = (AVATARCACHEENTRY *)CallService(MS_AV_GETMYAVATAR, 0, (LPARAM)(m_cache->getActiveProto())); - else - m_ownAce = nullptr; - - if (m_ownAce) - m_hOwnPic = m_ownAce->hbmPic; - else - m_hOwnPic = PluginConfig.g_hbmUnknown; - - if (m_pPanel.isActive() && m_pContainer->m_avatarMode != 3) { - BITMAP bm; - - m_iRealAvatarHeight = 0; - AdjustBottomAvatarDisplay(); - GetObject(m_hOwnPic, sizeof(bm), &bm); - CalcDynamicAvatarSize(&bm); - Resize(); - } -} - -// paste contents of the clipboard into the message input area and send it immediately -void CTabBaseDlg::HandlePasteAndSend() -{ - // is feature disabled? - if (!PluginConfig.m_PasteAndSend) { - SendMessage(m_hwnd, DM_ACTIVATETOOLTIP, IDC_SRMM_MESSAGE, (LPARAM)TranslateT("The 'paste and send' feature is disabled. You can enable it on the 'General' options page in the 'Sending messages' section")); - return; - } - - m_message.SendMsg(EM_PASTESPECIAL, CF_UNICODETEXT, 0); - if (GetWindowTextLength(m_message.GetHwnd()) > 0) - SendMessage(m_hwnd, WM_COMMAND, IDOK, 0); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// draw various elements of the message window, like avatar(s), info panel fields -// and the color formatting menu - -int CTabBaseDlg::MsgWindowDrawHandler(DRAWITEMSTRUCT *dis) -{ - HBITMAP hbmAvatar = m_ace ? m_ace->hbmPic : PluginConfig.g_hbmUnknown; - if ((dis->hwndItem == GetDlgItem(m_hwnd, IDC_CONTACTPIC) && m_bShowAvatar) || (dis->hwndItem == m_hwnd && m_pPanel.isActive())) { - if (hbmAvatar == nullptr) - return TRUE; - - int top, cx, cy; - RECT rcClient, rcFrame; - bool bPanelPic = (dis->hwndItem == m_hwnd); - if (bPanelPic && !m_bShowInfoAvatar) - return TRUE; - - RECT rc; - GetClientRect(m_hwnd, &rc); - if (bPanelPic) { - rcClient = dis->rcItem; - cx = (rcClient.right - rcClient.left); - cy = (rcClient.bottom - rcClient.top) + 1; - } - else { - GetClientRect(dis->hwndItem, &rcClient); - cx = rcClient.right; - cy = rcClient.bottom; - } - - if (cx < 5 || cy < 5) - return TRUE; - - HDC hdcDraw = CreateCompatibleDC(dis->hDC); - HBITMAP hbmDraw = CreateCompatibleBitmap(dis->hDC, cx, cy); - HBITMAP hbmOld = (HBITMAP)SelectObject(hdcDraw, hbmDraw); - - bool bAero = M.isAero(); - - HRGN clipRgn = nullptr; - HBRUSH hOldBrush = (HBRUSH)SelectObject(hdcDraw, bAero ? (HBRUSH)GetStockObject(HOLLOW_BRUSH) : GetSysColorBrush(COLOR_3DFACE)); - rcFrame = rcClient; - - if (!bPanelPic) { - top = (cy - m_pic.cy) / 2; - RECT rcEdge = { 0, top, m_pic.cx, top + m_pic.cy }; - if (CSkin::m_skinEnabled) - CSkin::SkinDrawBG(dis->hwndItem, m_pContainer->m_hwnd, m_pContainer, &dis->rcItem, hdcDraw); - else if (PluginConfig.m_fillColor) { - HBRUSH br = CreateSolidBrush(PluginConfig.m_fillColor); - FillRect(hdcDraw, &rcFrame, br); - DeleteObject(br); - } - else if (bAero && CSkin::m_pCurrentAeroEffect) { - COLORREF clr = PluginConfig.m_tbBackgroundHigh ? PluginConfig.m_tbBackgroundHigh : - (CSkin::m_pCurrentAeroEffect ? CSkin::m_pCurrentAeroEffect->m_clrToolbar : 0xf0f0f0); - - HBRUSH br = CreateSolidBrush(clr); - FillRect(hdcDraw, &rcFrame, br); - DeleteObject(br); - } - else FillRect(hdcDraw, &rcFrame, GetSysColorBrush(COLOR_3DFACE)); - - HPEN hPenBorder = CreatePen(PS_SOLID, 1, CSkin::m_avatarBorderClr); - HPEN hPenOld = (HPEN)SelectObject(hdcDraw, hPenBorder); - - if (CSkin::m_bAvatarBorderType == 1) - Rectangle(hdcDraw, rcEdge.left, rcEdge.top, rcEdge.right, rcEdge.bottom); - else if (CSkin::m_bAvatarBorderType == 2) { - clipRgn = CreateRoundRectRgn(rcEdge.left, rcEdge.top, rcEdge.right + 1, rcEdge.bottom + 1, 6, 6); - SelectClipRgn(hdcDraw, clipRgn); - - HBRUSH hbr = CreateSolidBrush(CSkin::m_avatarBorderClr); - FrameRgn(hdcDraw, clipRgn, hbr, 1, 1); - DeleteObject(hbr); - DeleteObject(clipRgn); - } - - SelectObject(hdcDraw, hPenOld); - DeleteObject(hPenBorder); - } - - if (bPanelPic) { - bool bBorder = (CSkin::m_bAvatarBorderType ? true : false); - - int border_off = bBorder ? 1 : 0; - int iMaxHeight = m_iPanelAvatarY - (bBorder ? 2 : 0); - int iMaxWidth = m_iPanelAvatarX - (bBorder ? 2 : 0); - - rcFrame.left = rcFrame.top = 0; - rcFrame.right = (rcClient.right - rcClient.left); - rcFrame.bottom = (rcClient.bottom - rcClient.top); - - rcFrame.left = rcFrame.right - (LONG)m_iPanelAvatarX; - rcFrame.bottom = (LONG)m_iPanelAvatarY; - - int height_off = (cy - iMaxHeight - (bBorder ? 2 : 0)) / 2; - rcFrame.top += height_off; - rcFrame.bottom += height_off; - - SendMessage(m_hwndPanelPic, AVATAR_SETAEROCOMPATDRAWING, 0, bAero ? TRUE : FALSE); - SetWindowPos(m_hwndPanelPic, HWND_TOP, rcFrame.left + border_off, rcFrame.top + border_off, - iMaxWidth, iMaxHeight, SWP_SHOWWINDOW | SWP_ASYNCWINDOWPOS | SWP_DEFERERASE | SWP_NOSENDCHANGING); - } - - SelectObject(hdcDraw, hOldBrush); - if (!bPanelPic) - BitBlt(dis->hDC, 0, 0, cx, cy, hdcDraw, 0, 0, SRCCOPY); - SelectObject(hdcDraw, hbmOld); - DeleteObject(hbmDraw); - DeleteDC(hdcDraw); - return TRUE; - } - - if (dis->hwndItem == GetDlgItem(m_hwnd, IDC_STATICTEXT) || dis->hwndItem == GetDlgItem(m_hwnd, IDC_LOGFROZENTEXT)) { - wchar_t szWindowText[256]; - if (CSkin::m_skinEnabled) { - SetTextColor(dis->hDC, CSkin::m_DefaultFontColor); - CSkin::SkinDrawBG(dis->hwndItem, m_pContainer->m_hwnd, m_pContainer, &dis->rcItem, dis->hDC); - } - else { - SetTextColor(dis->hDC, GetSysColor(COLOR_BTNTEXT)); - CSkin::FillBack(dis->hDC, &dis->rcItem); - } - GetWindowText(dis->hwndItem, szWindowText, _countof(szWindowText)); - szWindowText[255] = 0; - SetBkMode(dis->hDC, TRANSPARENT); - DrawText(dis->hDC, szWindowText, -1, &dis->rcItem, DT_SINGLELINE | DT_VCENTER | DT_NOCLIP | DT_END_ELLIPSIS); - return TRUE; - } - - if (dis->hwndItem == GetDlgItem(m_hwnd, IDC_STATICERRORICON)) { - if (CSkin::m_skinEnabled) - CSkin::SkinDrawBG(dis->hwndItem, m_pContainer->m_hwnd, m_pContainer, &dis->rcItem, dis->hDC); - else - CSkin::FillBack(dis->hDC, &dis->rcItem); - DrawIconEx(dis->hDC, (dis->rcItem.right - dis->rcItem.left) / 2 - 8, (dis->rcItem.bottom - dis->rcItem.top) / 2 - 8, - PluginConfig.g_iconErr, 16, 16, 0, nullptr, DI_NORMAL); - return TRUE; - } - - if (dis->CtlType == ODT_MENU && m_pPanel.isHovered()) { - DrawMenuItem(dis, (HICON)dis->itemData, 0); - return TRUE; - } - - return Menu_DrawItem((LPARAM)dis); -} - void TSAPI LoadThemeDefaults(TContainerData *pContainer) { memset(&pContainer->m_theme, 0, sizeof(TLogTheme)); @@ -1515,18 +414,6 @@ void TSAPI LoadOverrideTheme(TContainerData *pContainer) LoadThemeDefaults(pContainer); } -HICON CTabBaseDlg::GetXStatusIcon() const -{ - BYTE xStatus = m_cache->getXStatusId(); - if (xStatus == 0) - return nullptr; - - if (!ProtoServiceExists(m_cache->getActiveProto(), PS_GETCUSTOMSTATUSICON)) - return nullptr; - - return (HICON)(CallProtoService(m_cache->getActiveProto(), PS_GETCUSTOMSTATUSICON, xStatus, 0)); -} - LRESULT TSAPI GetSendButtonState(HWND hwnd) { HWND hwndIDok = GetDlgItem(hwnd, IDOK); @@ -1534,240 +421,3 @@ LRESULT TSAPI GetSendButtonState(HWND hwnd) return SendMessage(hwndIDok, BUTTONGETSTATEID, TRUE, 0); return 0; } - -void CTabBaseDlg::EnableSendButton(bool bMode) const -{ - SendDlgItemMessage(m_hwnd, IDOK, BUTTONSETASNORMAL, bMode, 0); - SendDlgItemMessage(m_hwnd, IDC_PIC, BUTTONSETASNORMAL, m_bEditNotesActive ? TRUE : (!bMode && m_iOpenJobs == 0) ? TRUE : FALSE, 0); - - HWND hwndOK = GetDlgItem(GetParent(GetParent(m_hwnd)), IDOK); - if (IsWindow(hwndOK)) - SendMessage(hwndOK, BUTTONSETASNORMAL, bMode, 0); -} - -void CTabBaseDlg::EnableSending(bool bMode) const -{ - m_message.SendMsg(EM_SETREADONLY, !bMode, 0); - Utils::enableDlgControl(m_hwnd, IDC_CLIST, bMode); - EnableSendButton(bMode); -} - -void CTabBaseDlg::GetClientIcon() -{ - if (m_hClientIcon) - DestroyIcon(m_hClientIcon); - - m_hClientIcon = nullptr; - if (ServiceExists(MS_FP_GETCLIENTICONT)) { - ptrW tszMirver(db_get_wsa(m_cache->getActiveContact(), m_cache->getActiveProto(), "MirVer")); - if (tszMirver) - m_hClientIcon = Finger_GetClientIcon(tszMirver, 1); - } -} - -void CTabBaseDlg::GetMyNick() -{ - ptrW tszNick(Contact_GetInfo(CNF_CUSTOMNICK, 0, m_cache->getActiveProto())); - if (tszNick == nullptr) - tszNick = Contact_GetInfo(CNF_NICK, 0, m_cache->getActiveProto()); - if (tszNick != nullptr) { - if (mir_wstrlen(tszNick) == 0 || !mir_wstrcmp(tszNick, TranslateT("'(Unknown contact)'"))) - wcsncpy_s(m_wszMyNickname, (m_myUin[0] ? m_myUin : TranslateT("'(Unknown contact)'")), _TRUNCATE); - else - wcsncpy_s(m_wszMyNickname, tszNick, _TRUNCATE); - } - else wcsncpy_s(m_wszMyNickname, L"", _TRUNCATE); // same here -} - -HICON CTabBaseDlg::GetMyContactIcon(LPCSTR szSetting) -{ - int bUseMeta = (szSetting == nullptr) ? false : M.GetByte(szSetting, mir_strcmp(szSetting, "MetaiconTab") == 0); - if (bUseMeta) - return Skin_LoadProtoIcon(m_cache->getProto(), m_cache->getStatus()); - return Skin_LoadProtoIcon(m_cache->getActiveProto(), m_cache->getActiveStatus()); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// read keyboard state and return the state of the modifier keys - -void CTabBaseDlg::KbdState(bool &isShift, bool &isControl, bool &isAlt) -{ - GetKeyboardState(kstate); - isShift = (kstate[VK_SHIFT] & 0x80) != 0; - isControl = (kstate[VK_CONTROL] & 0x80) != 0; - isAlt = (kstate[VK_MENU] & 0x80) != 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// generic handler for the WM_COPY message in message log/chat history richedit control(s). -// it filters out the invisible event boundary markers from the text copied to the clipboard. -// WINE Fix: overwrite clippboad data from original control data - -LRESULT CTabBaseDlg::WMCopyHandler(UINT msg, WPARAM wParam, LPARAM lParam) -{ - LRESULT result = mir_callNextSubclass(m_log.GetHwnd(), stubLogProc, msg, wParam, lParam); - - ptrA szFromStream(m_log.GetRichTextRtf(true, true)); - if (szFromStream != nullptr) { - ptrW converted(mir_utf8decodeW(szFromStream)); - if (converted != nullptr) { - Utils::FilterEventMarkers(converted); - Utils::CopyToClipBoard(converted, m_log.GetHwnd()); - } - } - - return result; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// calculate the minimum required client height for the given message -// window layout -// -// the container will use this in its WM_GETMINMAXINFO handler to set -// minimum tracking height. - -void CTabBaseDlg::DetermineMinHeight() -{ - RECT rc; - LONG height = (m_pPanel.isActive() ? m_pPanel.getHeight() + 2 : 0); - if (!(m_pContainer->m_dwFlags & CNT_HIDETOOLBAR)) - height += DPISCALEY_S(24); // toolbar - GetClientRect(m_message.GetHwnd(), &rc); - height += rc.bottom; // input area - height += 40; // min space for log area and some padding - - m_pContainer->m_uChildMinHeight = height; -} - -LONG CTabBaseDlg::GetDefaultMinimumInputHeight() const -{ - LONG height = (m_pContainer->m_dwFlags & CNT_BOTTOMTOOLBAR) ? DPISCALEY_S(46 + 22) : DPISCALEY_S(46); - - if (CSkin::m_skinEnabled && !SkinItems[ID_EXTBKINPUTAREA].IGNORED) - height += (SkinItems[ID_EXTBKINPUTAREA].MARGIN_BOTTOM + SkinItems[ID_EXTBKINPUTAREA].MARGIN_TOP - 2); - - return height; -} - -bool CTabBaseDlg::IsAutoSplitEnabled() const -{ - return (m_pContainer->m_dwFlags & CNT_AUTOSPLITTER) && !(m_dwFlagsEx & MWF_SHOW_SPLITTEROVERRIDE); -} - -void CTabBaseDlg::LimitMessageText(int iLen) -{ - if (this != nullptr) - m_message.SendMsg(EM_EXLIMITTEXT, 0, iLen); -} - -static LIST vTempFilenames(5); - -// send a pasted bitmap by file transfer. -void CTabBaseDlg::SendHBitmapAsFile(HBITMAP hbmp) const -{ - const wchar_t *mirandatempdir = L"Miranda"; - const wchar_t *filenametemplate = L"\\clp-%Y%m%d-%H%M%S0.jpg"; - wchar_t filename[MAX_PATH]; - size_t tempdirlen = GetTempPath(MAX_PATH, filename); - bool fSend = true; - - const char *szProto = m_cache->getActiveProto(); - int wMyStatus = Proto_GetStatus(szProto); - - DWORD protoCaps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0); - DWORD typeCaps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0); - - // check protocol capabilities, status modes and visibility lists (privacy) - // to determine whether the file can be sent. Throw a warning if any of - // these checks fails. - if (!(protoCaps & PF1_FILESEND)) - fSend = false; - - if ((ID_STATUS_OFFLINE == wMyStatus) || (ID_STATUS_OFFLINE == m_cache->getActiveStatus() && !(typeCaps & PF4_OFFLINEFILES))) - fSend = false; - - if (protoCaps & PF1_VISLIST && db_get_w(m_cache->getActiveContact(), szProto, "ApparentMode", 0) == ID_STATUS_OFFLINE) - fSend = false; - - if (protoCaps & PF1_INVISLIST && wMyStatus == ID_STATUS_INVISIBLE && db_get_w(m_cache->getActiveContact(), szProto, "ApparentMode", 0) != ID_STATUS_ONLINE) - fSend = false; - - if (!fSend) { - CWarning::show(CWarning::WARN_SENDFILE, MB_OK | MB_ICONEXCLAMATION | CWarning::CWF_NOALLOWHIDE); - return; - } - - if (tempdirlen <= 0 || tempdirlen >= MAX_PATH - mir_wstrlen(mirandatempdir) - mir_wstrlen(filenametemplate) - 2) // -2 is because %Y takes 4 symbols - filename[0] = 0; // prompt for a new name - else { - mir_wstrcpy(filename + tempdirlen, mirandatempdir); - if ((GetFileAttributes(filename) == INVALID_FILE_ATTRIBUTES || ((GetFileAttributes(filename) & FILE_ATTRIBUTE_DIRECTORY) == 0)) && CreateDirectory(filename, nullptr) == 0) - filename[0] = 0; - else { - tempdirlen = mir_wstrlen(filename); - - time_t rawtime; - time(&rawtime); - const tm* timeinfo; - timeinfo = _localtime32((__time32_t *)&rawtime); - wcsftime(filename + tempdirlen, MAX_PATH - tempdirlen, filenametemplate, timeinfo); - size_t firstnumberpos = tempdirlen + 14; - size_t lastnumberpos = tempdirlen + 20; - while (GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES) { // while it exists - for (size_t pos = lastnumberpos; pos >= firstnumberpos; pos--) - if (filename[pos]++ != '9') - break; - else - if (pos == firstnumberpos) - filename[0] = 0; // all filenames exist => prompt for a new name - else - filename[pos] = '0'; - } - } - } - - if (filename[0] == 0) { // prompting to save - wchar_t filter[MAX_PATH]; - mir_snwprintf(filter, L"%s%c*.jpg%c%c", TranslateT("JPEG-compressed images"), 0, 0, 0); - - OPENFILENAME dlg; - dlg.lStructSize = sizeof(dlg); - dlg.lpstrFilter = filter; - dlg.nFilterIndex = 1; - dlg.lpstrFile = filename; - dlg.nMaxFile = MAX_PATH; - dlg.Flags = OFN_NOREADONLYRETURN | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; - dlg.lpstrDefExt = L"jpg"; - if (!GetSaveFileName(&dlg)) - return; - } - - IMGSRVC_INFO ii; - ii.cbSize = sizeof(ii); - ii.hbm = hbmp; - ii.pwszName = filename; - ii.dwMask = IMGI_HBITMAP; - ii.fif = FIF_JPEG; - Image_Save(&ii); - - int totalCount = 0; - wchar_t **ppFiles = nullptr; - Utils::AddToFileList(&ppFiles, &totalCount, filename); - - wchar_t* _t = mir_wstrdup(filename); - vTempFilenames.insert(_t); - - CallService(MS_FILE_SENDSPECIFICFILEST, m_cache->getActiveContact(), (LPARAM)ppFiles); - - mir_free(ppFiles[0]); - mir_free(ppFiles); -} - -// remove all temporary files created by the "send clipboard as file" feature. -void TSAPI CleanTempFiles() -{ - for (auto &it : vTempFilenames) { - DeleteFileW(it); - mir_free(it); - } -} diff --git a/plugins/TabSRMM/src/msgdlgutils.h b/plugins/TabSRMM/src/msgdlgutils.h index 3b71b5acb9..1766826cfe 100644 --- a/plugins/TabSRMM/src/msgdlgutils.h +++ b/plugins/TabSRMM/src/msgdlgutils.h @@ -31,6 +31,7 @@ #define WANT_HPP_LOG 2 void TSAPI ProcessAvatarChange(HWND hwnd, LPARAM lParam); +BOOL TSAPI CheckCustomLink(HWND hwndRich, POINT *ptClient, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL bUrlNeeded); int TSAPI CheckValidSmileyPack(const char *szProto, MCONTACT hContact); wchar_t* TSAPI QuoteText(const wchar_t *text); UINT TSAPI GetIEViewMode(MCONTACT hContact); @@ -38,10 +39,10 @@ void TSAPI LoadOverrideTheme(TContainerData *pContainer); void TSAPI LoadThemeDefaults(TContainerData *pContainer); int TSAPI CutContactName(const wchar_t *szold, wchar_t *sznew, size_t size); LRESULT TSAPI GetSendButtonState(HWND hwnd); -void TSAPI RearrangeTab(HWND hwndDlg, const CTabBaseDlg *dat, int iMode, BOOL bSavePos); +void TSAPI RearrangeTab(HWND hwndDlg, const CMsgDialog *dat, int iMode, BOOL bSavePos); bool TSAPI IsStatusEvent(int eventType); bool TSAPI IsCustomEvent(int eventType); - + void TSAPI CleanTempFiles(); extern INT_PTR CALLBACK SelectContainerDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); diff --git a/plugins/TabSRMM/src/msglog.cpp b/plugins/TabSRMM/src/msglog.cpp index e8a22c1536..dfbf83e653 100644 --- a/plugins/TabSRMM/src/msglog.cpp +++ b/plugins/TabSRMM/src/msglog.cpp @@ -93,7 +93,7 @@ struct LogStreamData { int eventsToInsert; int isEmpty; int isAppend; - CTabBaseDlg *dlgDat; + CMsgDialog *dlgDat; DBEVENTINFO *dbei; }; @@ -306,7 +306,7 @@ static int AppendUnicodeToBuffer(CMStringA &str, const wchar_t *line, int mode) ///////////////////////////////////////////////////////////////////////////////////////// -static void Build_RTF_Header(CMStringA &str, CTabBaseDlg *dat) +static void Build_RTF_Header(CMStringA &str, CMsgDialog *dat) { int i; LOGFONTA *logFonts = dat->m_pContainer->m_theme.logFonts; @@ -364,14 +364,14 @@ static void Build_RTF_Header(CMStringA &str, CTabBaseDlg *dat) } // mir_free() the return value -static char* CreateRTFHeader(CTabBaseDlg *dat) +static char* CreateRTFHeader(CMsgDialog *dat) { CMStringA str; Build_RTF_Header(str, dat); return str.Detach(); } -static void AppendTimeStamp(wchar_t *szFinalTimestamp, int isSent, CMStringA &str, int skipFont, CTabBaseDlg *dat, int iFontIDOffset) +static void AppendTimeStamp(wchar_t *szFinalTimestamp, int isSent, CMStringA &str, int skipFont, CMsgDialog *dat, int iFontIDOffset) { if (skipFont) AppendUnicodeToBuffer(str, szFinalTimestamp, MAKELONG(isSent, dat->m_bIsHistory)); @@ -426,7 +426,7 @@ int DbEventIsForMsgWindow(DBEVENTINFO *dbei) return et && (et->flags & DETF_MSGWINDOW); } -static char* Template_CreateRTFFromDbEvent(CTabBaseDlg *dat, MCONTACT hContact, MEVENT hDbEvent, LogStreamData *streamData) +static char* Template_CreateRTFFromDbEvent(CMsgDialog *dat, MCONTACT hContact, MEVENT hDbEvent, LogStreamData *streamData) { HANDLE hTimeZone = nullptr; BOOL skipToNext = FALSE, skipFont = FALSE; @@ -1054,7 +1054,7 @@ static DWORD CALLBACK LogStreamInEvents(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG return 0; } -void CTabBaseDlg::ReplaceIcons(LONG startAt, int fAppend, BOOL isSent) +void CMsgDialog::ReplaceIcons(LONG startAt, int fAppend, BOOL isSent) { wchar_t trbuffer[40]; TEXTRANGE tr; @@ -1176,7 +1176,7 @@ void CTabBaseDlg::ReplaceIcons(LONG startAt, int fAppend, BOOL isSent) } } -void CTabBaseDlg::StreamInEvents(MEVENT hDbEventFirst, int count, int fAppend, DBEVENTINFO *dbei_s) +void CMsgDialog::StreamInEvents(MEVENT hDbEventFirst, int count, int fAppend, DBEVENTINFO *dbei_s) { CHARRANGE oldSel, sel; diff --git a/plugins/TabSRMM/src/msgs.cpp b/plugins/TabSRMM/src/msgs.cpp index e3f1619744..565b0bbfa7 100644 --- a/plugins/TabSRMM/src/msgs.cpp +++ b/plugins/TabSRMM/src/msgs.cpp @@ -62,232 +62,7 @@ int SmileyAddOptionsChanged(WPARAM, LPARAM) ///////////////////////////////////////////////////////////////////////////////////////// // basic window class -CTabBaseDlg::CTabBaseDlg(int iResource, SESSION_INFO *si) - : CSrmmBaseDialog(g_plugin, iResource, si), - m_pPanel(this), - m_dwFlags(MWF_INITMODE), - m_iInputAreaHeight(-1) -{ - m_autoClose = CLOSE_ON_CANCEL; - m_forceResizable = true; -} - -CTabBaseDlg::~CTabBaseDlg() -{ - delete m_pWnd; - - mir_free(m_sendBuffer); - mir_free(m_hHistoryEvents); - mir_free(m_hQueuedEvents); - - if (m_hClientIcon) DestroyIcon(m_hClientIcon); - if (m_hSmileyIcon) DestroyIcon(m_hSmileyIcon); - if (m_hXStatusIcon) DestroyIcon(m_hXStatusIcon); - if (m_hTaskbarIcon) DestroyIcon(m_hTaskbarIcon); -} - -void CTabBaseDlg::CloseTab() -{ - int iTabs = TabCtrl_GetItemCount(m_hwndParent); - if (iTabs == 1) { - SendMessage(m_pContainer->m_hwnd, WM_CLOSE, 0, 1); - return; - } - - m_pContainer->m_iChilds--; - int i = GetTabIndexFromHWND(m_hwndParent, m_hwnd); - - // after closing a tab, we need to activate the tab to the left side of - // the previously open tab. - // normally, this tab has the same index after the deletion of the formerly active tab - // unless, of course, we closed the last (rightmost) tab. - if (!m_pContainer->m_bDontSmartClose && iTabs > 1) { - if (i == iTabs - 1) - i--; - else - i++; - TabCtrl_SetCurSel(m_hwndParent, i); - - m_pContainer->m_hwndActive = GetTabWindow(m_hwndParent, i); - - RECT rc; - SendMessage(m_pContainer->m_hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)& rc); - SetWindowPos(m_pContainer->m_hwndActive, HWND_TOP, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), SWP_SHOWWINDOW); - ShowWindow(m_pContainer->m_hwndActive, SW_SHOW); - SetForegroundWindow(m_pContainer->m_hwndActive); - SetFocus(m_pContainer->m_hwndActive); - } - - SendMessage(m_pContainer->m_hwnd, WM_SIZE, 0, 0); - DestroyWindow(m_hwnd); -} - -void CTabBaseDlg::LoadSettings() -{ - m_clrInputBG = m_pContainer->m_theme.inputbg; - LoadLogfont(FONTSECTION_IM, MSGFONTID_MESSAGEAREA, nullptr, &m_clrInputFG, FONTMODULE); -} - -bool CTabBaseDlg::OnInitDialog() -{ - CSrmmBaseDialog::OnInitDialog(); - - // m_hwnd is valid, pass it to the tab control - TCITEM tci; - tci.mask = TCIF_PARAM; - tci.lParam = (LPARAM)m_hwnd; - TabCtrl_SetItem(m_hwndParent, m_iTabID, &tci); - - // update another tab ids - m_pContainer->UpdateTabs(); - - // add this window to window list & proxy - if (IsWinVer7Plus() && PluginConfig.m_useAeroPeek) - m_pWnd = new CProxyWindow(this); - else - m_pWnd = nullptr; - - // set up Windows themes - DM_ThemeChanged(); - - // refresh cache data for this contact - m_cache = CContactCache::getContactCache(m_hContact); - m_cache->updateNick(); - m_cache->updateUIN(); - m_cache->setWindowData(this); - - m_bIsAutosizingInput = IsAutoSplitEnabled(); - return true; -} - -void CTabBaseDlg::OnDestroy() -{ - m_cache->setWindowData(); - - CSuper::OnDestroy(); -} - -INT_PTR CTabBaseDlg::DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case DM_SETINFOPANEL: // broadcasted when global info panel setting changes - if (wParam == 0 && lParam == 0) { - m_pPanel.getVisibility(); - m_pPanel.loadHeight(); - m_pPanel.showHide(); - } - else { - CTabBaseDlg *srcDat = (CTabBaseDlg*)wParam; - if (lParam == 0) - m_pPanel.loadHeight(); - else { - if (srcDat && lParam && this != srcDat && !m_pPanel.isPrivateHeight()) { - if (srcDat->isChat() != isChat() && M.GetByte("syncAllPanels", 0) == 0) - return 0; - - if (m_pContainer->m_pSettings->fPrivate && srcDat->m_pContainer != m_pContainer) - return 0; - - m_pPanel.setHeight((LONG)lParam); - } - } - Resize(); - } - return 0; - - case DM_STATUSICONCHANGE: - m_pContainer->InitRedraw(); - return 0; - - case DM_ACTIVATEME: // the child window will activate itself - ActivateExistingTab(m_pContainer, m_hwnd); - return 0; - - case DM_QUERYCONTAINER: // container API support functions - if (lParam) - *(TContainerData**)lParam = m_pContainer; - return 0; - - case DM_QUERYHCONTACT: - if (lParam) - *(MCONTACT*)lParam = m_hContact; - return 0; - - case DM_CHECKSIZE: - m_dwFlags |= MWF_NEEDCHECKSIZE; - return 0; - - case DM_CONTAINERSELECTED: - // sent by the select container dialog box when a container was selected... - // lParam = (wchar_t*)selected name... - { - wchar_t *szNewName = (wchar_t*)lParam; - if (!mir_wstrcmp(szNewName, TranslateT("Default container"))) - szNewName = CGlobals::m_default_container_name; - - int iOldItems = TabCtrl_GetItemCount(m_hwndParent); - if (!wcsncmp(m_pContainer->m_wszName, szNewName, CONTAINER_NAMELEN)) - break; - - TContainerData *pNewContainer = FindContainerByName(szNewName); - if (pNewContainer == nullptr) - if ((pNewContainer = CreateContainer(szNewName, FALSE, m_hContact)) == nullptr) - break; - - db_set_ws(m_hContact, SRMSGMOD_T, "containerW", szNewName); - PostMessage(PluginConfig.g_hwndHotkeyHandler, DM_DOCREATETAB, (WPARAM)pNewContainer, m_hContact); - if (iOldItems > 1) // there were more than 1 tab, container is still valid - SendMessage(m_pContainer->m_hwndActive, WM_SIZE, 0, 0); - SetForegroundWindow(pNewContainer->m_hwnd); - SetActiveWindow(pNewContainer->m_hwnd); - } - return 0; - - case DM_ACTIVATETOOLTIP: - // show the balloon tooltip control. - // wParam == id of the "anchor" element, defaults to the panel status field (for away msg retrieval) - // lParam == new text to show - if (!IsIconic(m_pContainer->m_hwnd) && m_pContainer->m_hwndActive == m_hwnd) - m_pPanel.showTip(wParam, lParam); - return 0; - - case DM_STATUSBARCHANGED: - tabUpdateStatusBar(); - break; - - case DM_CHECKAUTOHIDE: - // This is broadcasted by the container to all child windows to check if the - // container can be autohidden or -closed. - // - // wParam is the autohide timeout (in seconds) - // lParam points to a BOOL and a session which wants to prevent auto-hiding - // the container must set it to FALSE. - // - // If no session in the container disagrees, the container will be hidden. - - if (lParam) { - BOOL *fResult = (BOOL*)lParam; - // text entered in the input area -> prevent autohide/cose - if (GetWindowTextLength(m_message.GetHwnd()) > 0) - *fResult = FALSE; - // unread events, do not hide or close the container - else if (m_dwUnread) - *fResult = FALSE; - // time since last activity did not yet reach the threshold. - else if (((GetTickCount() - m_dwLastActivity) / 1000) <= wParam) - *fResult = FALSE; - } - return 0; - - case DM_SPLITTERGLOBALEVENT: - DM_SplitterGlobalEvent(wParam, lParam); - return 0; - } - - return CSrmmBaseDialog::DlgProc(msg, wParam, lParam); -} - -void CTabBaseDlg::NotifyDeliveryFailure() const +void CMsgDialog::NotifyDeliveryFailure() const { if (M.GetByte("adv_noErrorPopups", 0)) return; @@ -316,7 +91,7 @@ void CTabBaseDlg::NotifyDeliveryFailure() const ///////////////////////////////////////////////////////////////////////////////////////// // Sets a status bar text for a contact -void CTabBaseDlg::SetStatusText(const wchar_t *wszText, HICON hIcon) +void CMsgDialog::SetStatusText(const wchar_t *wszText, HICON hIcon) { if (wszText != nullptr) { m_bStatusSet = true; @@ -538,7 +313,7 @@ int MyAvatarChanged(WPARAM wParam, LPARAM lParam) int TSAPI ActivateExistingTab(TContainerData *pContainer, HWND hwndChild) { - CSrmmWindow *dat = (CSrmmWindow*)GetWindowLongPtr(hwndChild, GWLP_USERDATA); // needed to obtain the hContact for the message window + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr(hwndChild, GWLP_USERDATA); // needed to obtain the hContact for the message window if (!dat || !pContainer) return FALSE; @@ -634,7 +409,7 @@ HWND TSAPI CreateNewTabForContact(TContainerData *pContainer, MCONTACT hContact, if (iCount > 0) { for (int i = iCount - 1; i >= 0; i--) { HWND hwnd = GetTabWindow(hwndTab, i); - CSrmmWindow *dat = (CSrmmWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if (dat) { int relPos = M.GetDword(dat->m_hContact, "tabindex", i * 100); if (iTabIndex_wanted <= relPos) @@ -654,7 +429,7 @@ HWND TSAPI CreateNewTabForContact(TContainerData *pContainer, MCONTACT hContact, if (bActivateTab) TabCtrl_SetCurSel(hwndTab, iTabId); - CSrmmWindow *pWindow = new CSrmmWindow(); + CMsgDialog *pWindow = new CMsgDialog(IDD_MSGSPLITNEW); pWindow->m_hContact = hContact; pWindow->m_iTabID = iTabId; pWindow->m_pContainer = pContainer; diff --git a/plugins/TabSRMM/src/msgs.h b/plugins/TabSRMM/src/msgs.h index 1604b40ec6..27e7ba9d38 100644 --- a/plugins/TabSRMM/src/msgs.h +++ b/plugins/TabSRMM/src/msgs.h @@ -226,9 +226,9 @@ struct TContainerData CSideBar *m_pSideBar; void InitRedraw(); - void SetIcon(CTabBaseDlg *pDlg, HICON hIcon); + void SetIcon(CMsgDialog *pDlg, HICON hIcon); void UpdateTabs(); - void UpdateTitle(MCONTACT, class CTabBaseDlg* = nullptr); + void UpdateTitle(MCONTACT, class CMsgDialog* = nullptr); void ClearMargins() { memset(&m_mOld, 0xfe, sizeof(m_mOld)); @@ -239,30 +239,30 @@ struct TContainerData } }; -class CTabBaseDlg : public CSrmmBaseDialog +class CMsgDialog : public CSrmmBaseDialog { typedef CSrmmBaseDialog CSuper; friend class CInfoPanel; -protected: - void CloseTab() override; - void LoadSettings() override; - void SetStatusText(const wchar_t*, HICON) override; - void DM_AddDivider(); void DM_DismissTip(const POINT& pt); void DM_ErrorDetected(int type, int flag); bool DM_GenericHotkeysCheck(MSG *message); int DM_SplitterGlobalEvent(WPARAM wParam, LPARAM lParam); void DM_UpdateLastMessage() const; - + void DetermineMinHeight(); void FindFirstEvent(); int FindRTLLocale(); void GetSendFormat(); bool IsAutoSplitEnabled() const; + void LoadContactAvatar(); + void LoadOwnAvatar(); + void MsgWindowUpdateState(UINT msg); void ReplaceIcons(LONG startAt, int fAppend, BOOL isSent); + void ReplayQueue(); void ResizeIeView(); + void SaveAvatarToFile(HBITMAP hbm, int isOwnPic); void ShowPopupMenu(const CCtrlBase&, POINT pt); void VerifyProxy(); LRESULT WMCopyHandler(UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -346,7 +346,7 @@ public: int m_iLastEventType; int m_nTypeSecs; int m_iOpenJobs; - int m_iInputAreaHeight; + int m_iInputAreaHeight = -1; int m_maxHistory, m_curHistory; int m_iCurrentQueueError; int m_iSplitterY, m_dynaSplitter; @@ -361,23 +361,72 @@ public: wchar_t m_wszStatusBar[100]; char m_szMicroLf[128]; + int m_iMultiSplit; + int msgTop, rcLogBottom; + wchar_t *wszInitialText; + bool m_bActivate, m_bWantPopup, m_bIsMeta; + CInfoPanel m_pPanel; + CProxyWindow *m_pWnd; // proxy window object (win7+, for taskbar support). CContactCache *m_cache; TContainerData *m_pContainer; // parent container description structure AVATARCACHEENTRY *m_ace, *m_ownAce; - CProxyWindow *m_pWnd; // proxy window object (win7+, for taskbar support). - // ALWAYS check this pointer before using it, it is not guaranteed to exist. + + static INT_PTR CALLBACK FilterWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + bool TabAutoComplete(); + + HWND m_hwndFilter; + int m_iSearchItem; + BOOL m_iSavedSpaces; + wchar_t m_wszSearch[255]; + wchar_t *m_wszSearchQuery, *m_wszSearchResult; + SESSION_INFO *m_pLastSession; + + CCtrlButton m_btnOk, m_btnAdd, m_btnQuote, m_btnCancelAdd; public: - CTabBaseDlg(int iDialogId, SESSION_INFO* = nullptr); - virtual ~CTabBaseDlg(); + CMsgDialog(int dlgId, SESSION_INFO* = nullptr); + ~CMsgDialog(); + + void onClick_Ok(CCtrlButton *); + void onClick_Add(CCtrlButton *); + void onClick_Quote(CCtrlButton *); + void onClick_Filter(CCtrlButton *); + void onClick_CancelAdd(CCtrlButton *); + void onClick_ShowNickList(CCtrlButton *); + + void onChange_Message(CCtrlEdit *); + + void onDblClick_List(CCtrlListBox *); + + int OnFilter(MSGFILTER *); bool OnInitDialog() override; void OnDestroy() override; - INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override; + int Resizer(UTILRESIZECONTROL *urc) override; + + void UpdateWindowState(UINT msg); + + LRESULT 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; + + void AddLog() override; + void CloseTab() override; + void LoadSettings() override; + void RedrawLog() override; + void ScrollToBottom() override; + void SetStatusText(const wchar_t *, HICON) override; + void ShowFilterMenu() override; + void StreamInEvents(LOGINFO *lin, bool bRedraw) override; + void UpdateNickList() override; + void UpdateOptions() override; + void UpdateStatusBar() override; + void UpdateTitle() override; - virtual CThumbBase* tabCreateThumb(CProxyWindow*) const = 0; - virtual void tabClearLog() = 0; + CThumbBase* tabCreateThumb(CProxyWindow*) const; + void tabClearLog(); void tabUpdateStatusBar() const; static LONG_PTR CALLBACK StatusBarSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); @@ -394,6 +443,7 @@ public: void DM_InitRichEdit(); void DM_InitTip(); void DM_NotifyTyping(int mode); + void DM_OptionsApplied(WPARAM wParam, LPARAM lParam); void DM_RecalcPictureSize(); void DM_SaveLogAsRTF() const; void DM_ScrollToBottom(WPARAM wParam, LPARAM lParam); @@ -461,111 +511,9 @@ public: void UpdateToolbarBG(); }; -class CSrmmWindow : public CTabBaseDlg +class CTemplateEditDlg : public CMsgDialog { - typedef CTabBaseDlg CSuper; - - virtual CThumbBase* tabCreateThumb(CProxyWindow *pProxy) const override; - virtual void tabClearLog() override; - - CCtrlButton m_btnOk, m_btnAdd, m_btnQuote, m_btnCancelAdd; - - virtual LRESULT WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam) override; - virtual LRESULT WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) override; - - void LoadContactAvatar(); - void LoadOwnAvatar(); - void MsgWindowUpdateState(UINT msg); - void ReplayQueue(); - -public: - int m_iMultiSplit; - int msgTop, rcLogBottom; - wchar_t *wszInitialText; - bool m_bActivate, m_bWantPopup, m_bIsMeta; - -public: - CSrmmWindow(); - - bool OnInitDialog() override; - void OnDestroy() override; - - int Resizer(UTILRESIZECONTROL *urc) override; - - void UpdateTitle() override; - - INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override; - - void onClick_Ok(CCtrlButton*); - void onClick_Add(CCtrlButton*); - void onClick_Quote(CCtrlButton*); - void onClick_CancelAdd(CCtrlButton*); - - void onChange_Message(CCtrlEdit*); - - int OnFilter(MSGFILTER*); - - void DM_OptionsApplied(WPARAM wParam, LPARAM lParam); -}; - -class CMsgDialog : public CTabBaseDlg -{ - typedef CTabBaseDlg CSuper; - - HWND m_hwndFilter; - CCtrlButton m_btnOk; - - virtual LRESULT WndProc_Log(UINT msg, WPARAM wParam, LPARAM lParam) override; - virtual LRESULT WndProc_Message(UINT msg, WPARAM wParam, LPARAM lParam) override; - virtual LRESULT WndProc_Nicklist(UINT msg, WPARAM wParam, LPARAM lParam) override; - - static INT_PTR CALLBACK FilterWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); - - virtual CThumbBase* tabCreateThumb(CProxyWindow *pProxy) const override; - virtual void tabClearLog() override; - - bool TabAutoComplete(); - - int m_iSearchItem; - BOOL m_iSavedSpaces; - wchar_t m_wszSearch[255]; - wchar_t *m_wszSearchQuery, *m_wszSearchResult; - SESSION_INFO *m_pLastSession; - -public: - CMsgDialog(SESSION_INFO*); - - bool OnInitDialog() override; - void OnDestroy() override; - - int Resizer(UTILRESIZECONTROL *urc) override; - - void AddLog() override; - void RedrawLog() override; - void ScrollToBottom() override; - void ShowFilterMenu() override; - void StreamInEvents(LOGINFO* lin, bool bRedraw) override; - void UpdateNickList() override; - void UpdateOptions() override; - void UpdateStatusBar() override; - void UpdateTitle() override; - - INT_PTR DlgProc(UINT msg, WPARAM wParam, LPARAM lParam) override; - - void onClick_OK(CCtrlButton*); - void onClick_Filter(CCtrlButton*); - void onClick_ShowNickList(CCtrlButton*); - - void onDblClick_List(CCtrlListBox*); - - void onChange_Message(CCtrlEdit*); - - void UpdateWindowState(UINT msg); -}; - -class CTemplateEditDlg : public CTabBaseDlg -{ - typedef CTabBaseDlg CSuper; + typedef CMsgDialog CSuper; BOOL rtl; BOOL changed; // template in edit field is changed @@ -580,10 +528,6 @@ class CTemplateEditDlg : public CTabBaseDlg CCtrlListBox listTemplates; CCtrlHyperlink urlHelp; - virtual CThumbBase* tabCreateThumb(CProxyWindow*) const override { return nullptr; } - virtual void tabClearLog() override {} - virtual void UpdateTitle() override {}; - public: CTemplateEditDlg(BOOL rtl, HWND hwndParent); @@ -977,14 +921,15 @@ struct TOptionListItem #define IDC_SBAR_TOGGLEFORMAT 1117 #define IDC_SBAR_CANCEL 1118 -struct SIDEBARITEM { +struct SIDEBARITEM +{ UINT uId; DWORD dwFlags; - HICON *hIcon, *hIconPressed, *hIconHover; - wchar_t *szName; - void(*pfnAction)(ButtonItem *item, HWND hwndDlg, CSrmmWindow *dat, HWND hwndItem); - void(*pfnCallback)(ButtonItem *item, HWND hwndDlg, CSrmmWindow *dat, HWND hwndItem); - wchar_t *tszTip; + HICON *hIcon, *hIconPressed, *hIconHover; + wchar_t *szName; + void (*pfnAction)(ButtonItem *item, HWND hwndDlg, CMsgDialog *dat, HWND hwndItem); + void (*pfnCallback)(ButtonItem *item, HWND hwndDlg, CMsgDialog *dat, HWND hwndItem); + wchar_t *tszTip; }; #define FONTF_BOLD 1 diff --git a/plugins/TabSRMM/src/selectcontainer.cpp b/plugins/TabSRMM/src/selectcontainer.cpp index 04e5685b2c..b925a97dc5 100644 --- a/plugins/TabSRMM/src/selectcontainer.cpp +++ b/plugins/TabSRMM/src/selectcontainer.cpp @@ -45,7 +45,7 @@ INT_PTR CALLBACK SelectContainerDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, L TranslateDialogDefault(hwndDlg); if (lParam) { - CSrmmWindow *dat = (CSrmmWindow*)GetWindowLongPtr((HWND)lParam, GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr((HWND)lParam, GWLP_USERDATA); if (dat) { mir_snwprintf(szNewTitle, TranslateT("Select container for %s"), dat->m_cache->getNick()); SetWindowText(hwndDlg, szNewTitle); diff --git a/plugins/TabSRMM/src/sendqueue.cpp b/plugins/TabSRMM/src/sendqueue.cpp index b43c0b1c8a..c09dbcff03 100644 --- a/plugins/TabSRMM/src/sendqueue.cpp +++ b/plugins/TabSRMM/src/sendqueue.cpp @@ -35,7 +35,7 @@ SendQueue *sendQueue = nullptr; // as "failed" by either the ACKRESULT_FAILED or a timeout handler // returns: zero-based queue index or -1 if none was found -int SendQueue::findNextFailed(const CTabBaseDlg *dat) const +int SendQueue::findNextFailed(const CMsgDialog *dat) const { if (dat) for (int i = 0; i < NR_SENDJOBS; i++) @@ -45,7 +45,7 @@ int SendQueue::findNextFailed(const CTabBaseDlg *dat) const return -1; } -void SendQueue::handleError(CTabBaseDlg *dat, const int iEntry) const +void SendQueue::handleError(CMsgDialog *dat, const int iEntry) const { if (!dat) return; @@ -63,7 +63,7 @@ void SendQueue::handleError(CTabBaseDlg *dat, const int iEntry) const //add a message to the sending queue. // iLen = required size of the memory block to hold the message -int SendQueue::addTo(CTabBaseDlg *dat, size_t iLen, int dwFlags) +int SendQueue::addTo(CMsgDialog *dat, size_t iLen, int dwFlags) { int i; int iFound = NR_SENDJOBS; @@ -190,7 +190,7 @@ size_t SendQueue::getSendLength(const int iEntry) return p.iSendLength; } -int SendQueue::sendQueued(CTabBaseDlg *dat, const int iEntry) +int SendQueue::sendQueued(CMsgDialog *dat, const int iEntry) { HWND hwndDlg = dat->GetHwnd(); CContactCache *ccActive = CContactCache::getContactCache(dat->m_hContact); @@ -321,15 +321,15 @@ void SendQueue::clearJob(const int iIndex) // ) user decided to cancel a failed send // it removes the completed / canceled send job from the queue and schedules the next job to send (if any) -void SendQueue::checkQueue(const CTabBaseDlg *dat) const +void SendQueue::checkQueue(const CMsgDialog *dat) const { if (dat) { HWND hwndDlg = dat->GetHwnd(); if (dat->m_iOpenJobs == 0) - ::HandleIconFeedback(const_cast(dat), (HICON)INVALID_HANDLE_VALUE); + ::HandleIconFeedback(const_cast(dat), (HICON)INVALID_HANDLE_VALUE); else if (!(dat->m_sendMode & SMODE_NOACK)) - ::HandleIconFeedback(const_cast(dat), PluginConfig.g_IconSend); + ::HandleIconFeedback(const_cast(dat), PluginConfig.g_IconSend); if (dat->m_pContainer->m_hwndActive == hwndDlg) dat->UpdateReadChars(); @@ -340,7 +340,7 @@ void SendQueue::checkQueue(const CTabBaseDlg *dat) const // logs an error message to the message window.Optionally, appends the original message // from the given sendJob (queue index) -void SendQueue::logError(CTabBaseDlg *dat, int iSendJobIndex, const wchar_t *szErrMsg) const +void SendQueue::logError(CMsgDialog *dat, int iSendJobIndex, const wchar_t *szErrMsg) const { if (dat == nullptr) return; @@ -367,7 +367,7 @@ void SendQueue::logError(CTabBaseDlg *dat, int iSendJobIndex, const wchar_t *szE ///////////////////////////////////////////////////////////////////////////////////////// // show or hide the error control button bar on top of the window -void SendQueue::showErrorControls(CTabBaseDlg *dat, const int showCmd) const +void SendQueue::showErrorControls(CMsgDialog *dat, const int showCmd) const { UINT myerrorControls[] = { IDC_STATICERRORICON, IDC_STATICTEXT, IDC_RETRY, IDC_CANCELSEND, IDC_MSGSENDLATER }; HWND hwndDlg = dat->GetHwnd(); @@ -395,7 +395,7 @@ void SendQueue::showErrorControls(CTabBaseDlg *dat, const int showCmd) const dat->EnableSending(TRUE); } -void SendQueue::recallFailed(CTabBaseDlg *dat, int iEntry) const +void SendQueue::recallFailed(CMsgDialog *dat, int iEntry) const { if (dat == nullptr) return; @@ -412,7 +412,7 @@ void SendQueue::recallFailed(CTabBaseDlg *dat, int iEntry) const SendDlgItemMessage(dat->GetHwnd(), IDC_SRMM_MESSAGE, EM_SETSEL, -1, -1); } -int SendQueue::ackMessage(CTabBaseDlg *dat, WPARAM wParam, LPARAM lParam) +int SendQueue::ackMessage(CMsgDialog *dat, WPARAM wParam, LPARAM lParam) { ACKDATA *ack = (ACKDATA *)lParam; @@ -537,7 +537,7 @@ LRESULT SendQueue::WarnPendingJobs(unsigned int) // // @return the index on success, -1 on failure -int SendQueue::doSendLater(int iJobIndex, CTabBaseDlg *dat, MCONTACT hContact, bool fIsSendLater) +int SendQueue::doSendLater(int iJobIndex, CMsgDialog *dat, MCONTACT hContact, bool fIsSendLater) { bool fAvail = sendLater->isAvail(); diff --git a/plugins/TabSRMM/src/sendqueue.h b/plugins/TabSRMM/src/sendqueue.h index 2235168ba4..d7c797c5f9 100644 --- a/plugins/TabSRMM/src/sendqueue.h +++ b/plugins/TabSRMM/src/sendqueue.h @@ -85,17 +85,17 @@ public: SendJob *getJobByIndex(const int index) { return(&m_jobs[index]); } void clearJob(const int index); - int findNextFailed(const CTabBaseDlg *dat) const; - void handleError(CTabBaseDlg *dat, const int iEntry) const; - int addTo(CTabBaseDlg *dat, size_t iLen, int dwFlags); - int sendQueued(CTabBaseDlg *dat, const int iEntry); + int findNextFailed(const CMsgDialog *dat) const; + void handleError(CMsgDialog *dat, const int iEntry) const; + int addTo(CMsgDialog *dat, size_t iLen, int dwFlags); + int sendQueued(CMsgDialog *dat, const int iEntry); size_t getSendLength(const int iEntry); - void checkQueue(const CTabBaseDlg *dat) const; - void logError(CTabBaseDlg *dat, int iSendJobIndex, const wchar_t *szErrMsg) const; - void recallFailed(CTabBaseDlg *dat, int iEntry) const; - void showErrorControls(CTabBaseDlg *dat, const int showCmd) const; - int ackMessage(CTabBaseDlg *dat, WPARAM wParam, LPARAM lParam); - int doSendLater(int iIndex, CTabBaseDlg *dat, MCONTACT hContact = 0, bool fIsSendLater = true); + void checkQueue(const CMsgDialog *dat) const; + void logError(CMsgDialog *dat, int iSendJobIndex, const wchar_t *szErrMsg) const; + void recallFailed(CMsgDialog *dat, int iEntry) const; + void showErrorControls(CMsgDialog *dat, const int showCmd) const; + int ackMessage(CMsgDialog *dat, WPARAM wParam, LPARAM lParam); + int doSendLater(int iIndex, CMsgDialog *dat, MCONTACT hContact = 0, bool fIsSendLater = true); // static members static LRESULT TSAPI WarnPendingJobs(unsigned int uNrMessages); @@ -108,6 +108,6 @@ private: extern SendQueue *sendQueue; int TSAPI ActivateExistingTab(TContainerData *pContainer, HWND hwndChild); -void TSAPI HandleIconFeedback(CTabBaseDlg *dat, HICON iIcon); +void TSAPI HandleIconFeedback(CMsgDialog *dat, HICON iIcon); #endif /* __SENDQUEUE_H */ diff --git a/plugins/TabSRMM/src/sidebar.cpp b/plugins/TabSRMM/src/sidebar.cpp index 5f43e104c4..6b77165c6f 100644 --- a/plugins/TabSRMM/src/sidebar.cpp +++ b/plugins/TabSRMM/src/sidebar.cpp @@ -71,7 +71,7 @@ TSideBarLayout CSideBar::m_layouts[CSideBar::NR_LAYOUTS] = { } }; -CSideBarButton::CSideBarButton(CTabBaseDlg *dat, CSideBar *sideBar) +CSideBarButton::CSideBarButton(CMsgDialog *dat, CSideBar *sideBar) { m_dat = dat; m_id = UINT(dat->m_hContact); // set the control id @@ -503,7 +503,7 @@ void CSideBar::populateAll() if (hDlg == 0 || !IsWindow(hDlg)) continue; - CSrmmWindow *dat = (CSrmmWindow*)::GetWindowLongPtr(hDlg, GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)::GetWindowLongPtr(hDlg, GWLP_USERDATA); if (dat == nullptr) continue; @@ -528,7 +528,7 @@ void CSideBar::populateAll() * (that is, it can only be used after WM_INITIALOG completed). *position: -1 = append, otherwise insert it at the given position */ -void CSideBar::addSession(CTabBaseDlg *dat, int position) +void CSideBar::addSession(CMsgDialog *dat, int position) { if (!m_isActive) return; @@ -561,7 +561,7 @@ void CSideBar::addSession(CTabBaseDlg *dat, int position) * * @param dat _MessageWindowData *: session data for a client session. */ -HRESULT CSideBar::removeSession(CTabBaseDlg *dat) +HRESULT CSideBar::removeSession(CMsgDialog *dat) { if (dat) { CSideBarButton *item = findSession(dat); @@ -638,7 +638,7 @@ void CSideBar::scrollIntoView(const CSideBarButton *item) * * @param dat _MessageWindowData*: Session data */ -void CSideBar::updateSession(CTabBaseDlg *dat) +void CSideBar::updateSession(CMsgDialog *dat) { if (!m_isVisible || !m_isActive) return; @@ -670,7 +670,7 @@ void CSideBar::updateSession(CTabBaseDlg *dat) * * @return The previously active item (that can be zero) */ -const CSideBarButton* CSideBar::setActiveItem(const CTabBaseDlg *dat) +const CSideBarButton* CSideBar::setActiveItem(const CMsgDialog *dat) { CSideBarButton *item = findSession(dat); if (item != nullptr) @@ -789,7 +789,7 @@ void CSideBar::showAll(int showCmd) * @return CSideBarButtonItem*: pointer to the found item. Zero, if none was found */ -CSideBarButton* CSideBar::findSession(const CTabBaseDlg *dat) +CSideBarButton* CSideBar::findSession(const CMsgDialog *dat) { if (dat == nullptr) return nullptr; @@ -845,7 +845,7 @@ void CSideBar::resizeScrollWnd(LONG x, LONG y, LONG, LONG height) const SWP_NOCOPYBITS | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOSENDCHANGING | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS); } -void CSideBar::invalidateButton(CTabBaseDlg *dat) +void CSideBar::invalidateButton(CMsgDialog *dat) { if (m_isActive && m_isVisible) { CSideBarButton *item = findSession(dat); @@ -1041,7 +1041,7 @@ void __fastcall CSideBar::m_DefaultContentRenderer(const HDC hdc, const RECT *rc void __fastcall CSideBar::m_AdvancedContentRenderer(const HDC hdc, const RECT *rcBox, const CSideBarButton *item) { - const CTabBaseDlg *dat = item->getDat(); + const CMsgDialog *dat = item->getDat(); UINT id = item->getID(); LONG cx = rcBox->right - rcBox->left; @@ -1119,7 +1119,7 @@ const SIZE& __fastcall CSideBar::m_measureAdvancedVertical(CSideBarButton* item) { SIZE sz = { 0 }; - const CTabBaseDlg *dat = item->getDat(); + const CMsgDialog *dat = item->getDat(); if (dat) { SIZE szFirstLine, szSecondLine; diff --git a/plugins/TabSRMM/src/sidebar.h b/plugins/TabSRMM/src/sidebar.h index 424cfd0269..c8fa3e472f 100644 --- a/plugins/TabSRMM/src/sidebar.h +++ b/plugins/TabSRMM/src/sidebar.h @@ -32,7 +32,7 @@ struct TSideBarNotify { NMHDR nmHdr; - CTabBaseDlg *dat; + CMsgDialog *dat; }; /* layout description structure */ @@ -61,7 +61,7 @@ class CSideBarButton { public: CSideBarButton(const UINT id, CSideBar *sideBar); - CSideBarButton(CTabBaseDlg *dat, CSideBar *sideBar); + CSideBarButton(CMsgDialog *dat, CSideBar *sideBar); ~CSideBarButton(); LONG getHeight() const { return(m_sz.cy); } @@ -71,7 +71,7 @@ public: const HWND getHwnd() const { return(m_hwnd); } const UINT getID() const { return(m_id); } const MCONTACT getContactHandle() const { return(m_dat->m_hContact); } - const CTabBaseDlg* getDat() const { return(m_dat); } + const CMsgDialog* getDat() const { return(m_dat); } const TSideBarLayout* getLayout() const { return(m_sideBarLayout); } void RenderThis(const HDC hdc) const; @@ -91,7 +91,7 @@ private: private: const TSideBarLayout* m_sideBarLayout; HWND m_hwnd; // window handle for the TSButton object - CTabBaseDlg *m_dat; // session data + CMsgDialog *m_dat; // session data UINT m_id; // control id bool m_isTopAligned; SIZE m_sz; @@ -130,9 +130,9 @@ public: ~CSideBar(); void Init(); - void addSession(CTabBaseDlg *dat, int position); - HRESULT removeSession(CTabBaseDlg *dat); - void updateSession(CTabBaseDlg *dat); + void addSession(CMsgDialog *dat, int position); + HRESULT removeSession(CMsgDialog *dat); + void updateSession(CMsgDialog *dat); void processScrollerButtons(UINT cmd); void Layout(); @@ -149,7 +149,7 @@ public: const CSideBarButton* getScrollDown() const { return(m_down); } bool isSkinnedContainer() const { return(CSkin::m_skinEnabled ? true : false); } const UINT getLayoutId() const { return(m_uLayout); } - void invalidateButton(CTabBaseDlg *dat); + void invalidateButton(CMsgDialog *dat); const CSideBarButton* setActiveItem(const CSideBarButton *newItem) { @@ -171,7 +171,7 @@ public: } HWND getScrollWnd() const { return(m_hwndScrollWnd); } const CSideBarButton* getHoveredClose() const { return(m_hoveredClose); } - const CSideBarButton* setActiveItem(const CTabBaseDlg *dat); + const CSideBarButton* setActiveItem(const CMsgDialog *dat); static LRESULT CALLBACK wndProcStub(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); @@ -189,7 +189,7 @@ private: void populateAll(); void removeAll(); void Invalidate(); - CSideBarButton* findSession(const CTabBaseDlg *dat); + CSideBarButton* findSession(const CMsgDialog *dat); CSideBarButton* findSession(const MCONTACT hContact); LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); diff --git a/plugins/TabSRMM/src/stdafx.h b/plugins/TabSRMM/src/stdafx.h index 551630bf7f..8aef3fe071 100644 --- a/plugins/TabSRMM/src/stdafx.h +++ b/plugins/TabSRMM/src/stdafx.h @@ -248,6 +248,6 @@ INT_PTR CALLBACK DlgProcSetupStatusModes(HWND hwndDlg, UINT msg, WPARAM wParam, int TSAPI TBStateConvert2Flat(int state); int TSAPI RBStateConvert2Flat(int state); -void TSAPI FillTabBackground(const HDC hdc, int iStateId, const CTabBaseDlg *dat, RECT* rc); +void TSAPI FillTabBackground(const HDC hdc, int iStateId, const CMsgDialog *dat, RECT* rc); #define IS_EXTKEY(a) (a & (1 << 24)) diff --git a/plugins/TabSRMM/src/tabctrl.cpp b/plugins/TabSRMM/src/tabctrl.cpp index 5a89e6031d..ca32820cb6 100644 --- a/plugins/TabSRMM/src/tabctrl.cpp +++ b/plugins/TabSRMM/src/tabctrl.cpp @@ -139,7 +139,7 @@ static void TSAPI DrawCustomTabPage(HDC hdc, RECT& rcClient) ::DeleteObject(hPen); } -void TSAPI FillTabBackground(const HDC hdc, int iStateId, const CTabBaseDlg *dat, RECT* rc) +void TSAPI FillTabBackground(const HDC hdc, int iStateId, const CMsgDialog *dat, RECT* rc) { unsigned clrIndex; @@ -160,7 +160,7 @@ void TSAPI FillTabBackground(const HDC hdc, int iStateId, const CTabBaseDlg *dat // no image list is used and necessary, the message window dialog procedure has to provide a valid // icon handle in dat->hTabIcon -static void DrawItem(TabControlData *tabdat, HDC dc, RECT *rcItem, int nHint, int nItem, CSrmmWindow *dat) +static void DrawItem(TabControlData *tabdat, HDC dc, RECT *rcItem, int nHint, int nItem, CMsgDialog *dat) { if (dat == nullptr) return; @@ -235,7 +235,7 @@ static void DrawItem(TabControlData *tabdat, HDC dc, RECT *rcItem, int nHint, in static RECT rcTabPage = { 0 }; -static void DrawItemRect(TabControlData *tabdat, HDC dc, RECT *rcItem, int nHint, const CSrmmWindow *dat) +static void DrawItemRect(TabControlData *tabdat, HDC dc, RECT *rcItem, int nHint, const CMsgDialog *dat) { POINT pt; DWORD dwStyle = tabdat->dwStyle; @@ -393,7 +393,7 @@ static int DWordAlign(int n) return n; } -static HRESULT DrawThemesPartWithAero(const TabControlData *tabdat, HDC hDC, int iPartId, int iStateId, LPRECT prcBox, CSrmmWindow *dat) +static HRESULT DrawThemesPartWithAero(const TabControlData *tabdat, HDC hDC, int iPartId, int iStateId, LPRECT prcBox, CMsgDialog *dat) { HRESULT hResult = 0; bool bAero = M.isAero(); @@ -440,7 +440,7 @@ static HRESULT DrawThemesPart(const TabControlData *tabdat, HDC hDC, int iPartId // draw a themed tab item. either a tab or the body pane // handles image mirroring for tabs at the bottom -static void DrawThemesXpTabItem(HDC pDC, RECT *rcItem, UINT uiFlag, TabControlData *tabdat, CSrmmWindow *dat) +static void DrawThemesXpTabItem(HDC pDC, RECT *rcItem, UINT uiFlag, TabControlData *tabdat, CMsgDialog *dat) { BOOL bBody = (uiFlag & 1) ? TRUE : FALSE; BOOL bSel = (uiFlag & 2) ? TRUE : FALSE; @@ -614,7 +614,7 @@ static void PaintWorker(HWND hwnd, TabControlData *tabdat) tabdat->helperDat = nullptr; if (tabdat->bAeroTabs) { - CSrmmWindow *dat = (CSrmmWindow*)GetWindowLongPtr(tabdat->pContainer->m_hwndActive, GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr(tabdat->pContainer->m_hwndActive, GWLP_USERDATA); if (dat) tabdat->helperDat = dat; else @@ -841,9 +841,9 @@ page_done: if (i == iActive) continue; - CSrmmWindow *dat = nullptr; + CMsgDialog *dat = nullptr; if (HWND hDlg = GetTabWindow(hwnd, i)) - dat = (CSrmmWindow*)GetWindowLongPtr(hDlg, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(hDlg, GWLP_USERDATA); TabCtrl_GetItemRect(hwnd, i, &rcItem); if (!bClassicDraw && uiBottom) { rcItem.top -= PluginConfig.tabConfig.m_bottomAdjust; @@ -871,12 +871,12 @@ page_done: rctActive.bottom -= PluginConfig.tabConfig.m_bottomAdjust; } if (rctActive.left >= 0) { - CSrmmWindow *dat = nullptr; + CMsgDialog *dat = nullptr; int nHint = 0; rcItem = rctActive; if (HWND hDlg = GetTabWindow(hwnd, iActive)) - dat = (CSrmmWindow*)GetWindowLongPtr(hDlg, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(hDlg, GWLP_USERDATA); if (!bClassicDraw && !(dwStyle & TCS_BUTTONS)) { InflateRect(&rcItem, 2, 2); @@ -1104,7 +1104,7 @@ static LRESULT CALLBACK TabControlSubclassProc(HWND hwnd, UINT msg, WPARAM wPara int i = GetTabItemFromMouse(hwnd, &pt); if (i != -1) { HWND hDlg = GetTabWindow(hwnd, i); - CSrmmWindow *dat = (CSrmmWindow*)GetWindowLongPtr(hDlg, GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr(hDlg, GWLP_USERDATA); if (dat) { tabdat->bDragging = true; tabdat->iBeginIndex = i; @@ -1129,7 +1129,7 @@ static LRESULT CALLBACK TabControlSubclassProc(HWND hwnd, UINT msg, WPARAM wPara int i = GetTabItemFromMouse(hwnd, &pt); if (i != -1) { HWND hDlg = GetTabWindow(hwnd, i); - CSrmmWindow *dat = (CSrmmWindow*)GetWindowLongPtr(hDlg, GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr(hDlg, GWLP_USERDATA); if (dat) { tabdat->bDragging = true; tabdat->iBeginIndex = i; @@ -1249,9 +1249,9 @@ static LRESULT CALLBACK TabControlSubclassProc(HWND hwnd, UINT msg, WPARAM wPara if (nItem >= 0 && nItem < TabCtrl_GetItemCount(hwnd)) { // get the message window data for the session to which this tab item belongs HWND hDlg = GetTabWindow(hwnd, nItem); - CSrmmWindow *dat = nullptr; + CMsgDialog *dat = nullptr; if (IsWindow(hDlg) && hDlg != 0) - dat = (CSrmmWindow*)GetWindowLongPtr(hDlg, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(hDlg, GWLP_USERDATA); if (dat) { tabdat->bTipActive = true; ti.isGroup = 0; @@ -1351,7 +1351,7 @@ int TSAPI RegisterTabCtrlClass(void) RegisterClassEx(&wc); wc.lpszClassName = L"TSStatusBarClass"; - wc.lpfnWndProc = &CTabBaseDlg::StatusBarSubclassProc; + wc.lpfnWndProc = &CMsgDialog::StatusBarSubclassProc; wc.hCursor = LoadCursor(nullptr, IDC_ARROW); wc.cbWndExtra = sizeof(void*); wc.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_PARENTDC; diff --git a/plugins/TabSRMM/src/taskbar.cpp b/plugins/TabSRMM/src/taskbar.cpp index 1fe035bc38..7f8d9ab86c 100644 --- a/plugins/TabSRMM/src/taskbar.cpp +++ b/plugins/TabSRMM/src/taskbar.cpp @@ -179,7 +179,7 @@ void CTaskbarInteract::SetTabActive(const HWND hwndTab, const HWND hwndGroup) co * * static member function */ -void CTabBaseDlg::VerifyProxy() +void CMsgDialog::VerifyProxy() { if (IsWinVer7Plus() && PluginConfig.m_useAeroPeek) { if (nullptr == m_pWnd) { @@ -207,7 +207,7 @@ void CTabBaseDlg::VerifyProxy() * and previews for a message session. * each tab has one invisible proxy window */ -CProxyWindow::CProxyWindow(CTabBaseDlg *dat) : +CProxyWindow::CProxyWindow(CMsgDialog *dat) : m_dat(dat) { m_hwndProxy = ::CreateWindowEx(/*WS_EX_TOOLWINDOW | */WS_EX_NOACTIVATE, PROXYCLASSNAME, L"", @@ -288,7 +288,7 @@ void CProxyWindow::sendPreview() if (m_dat->m_pContainer == nullptr) return; - CSrmmWindow *dat_active = reinterpret_cast(::GetWindowLongPtr(m_dat->m_pContainer->m_hwndActive, GWLP_USERDATA)); + CMsgDialog *dat_active = reinterpret_cast(::GetWindowLongPtr(m_dat->m_pContainer->m_hwndActive, GWLP_USERDATA)); if (!m_thumb || !dat_active) return; diff --git a/plugins/TabSRMM/src/taskbar.h b/plugins/TabSRMM/src/taskbar.h index 9da6ab0d0d..622ec3cff9 100644 --- a/plugins/TabSRMM/src/taskbar.h +++ b/plugins/TabSRMM/src/taskbar.h @@ -49,7 +49,7 @@ public: virtual void update() = 0; protected: - const CTabBaseDlg *m_dat; + const CMsgDialog *m_dat; const CProxyWindow *m_pWnd; HBITMAP m_hbmThumb, m_hbmOld; @@ -98,7 +98,7 @@ private: class CProxyWindow { public: - CProxyWindow(CTabBaseDlg *dat); + CProxyWindow(CMsgDialog *dat); ~CProxyWindow(); void updateIcon(const HICON hIcon) const; @@ -109,7 +109,7 @@ public: void Invalidate() const; void verifyDwmState(); - __inline const CTabBaseDlg* getDat() const { return m_dat; } + __inline const CMsgDialog* getDat() const { return m_dat; } __inline const LONG getWidth() const { return m_width; } __inline const LONG getHeight() const { return m_height; } __inline const HWND getHwnd() const { return m_hwndProxy; } @@ -119,7 +119,7 @@ public: static LRESULT CALLBACK stubWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); private: - CTabBaseDlg *m_dat; + CMsgDialog *m_dat; HWND m_hwndProxy = nullptr; LONG m_width, m_height; diff --git a/plugins/TabSRMM/src/themeio.cpp b/plugins/TabSRMM/src/themeio.cpp index 5b0bf7c027..abf9af9021 100644 --- a/plugins/TabSRMM/src/themeio.cpp +++ b/plugins/TabSRMM/src/themeio.cpp @@ -176,7 +176,7 @@ int TSAPI CheckThemeVersion(const wchar_t *szIniFilename) return 0; } -void TSAPI WriteThemeToINI(const wchar_t *szIniFilenameT, CSrmmWindow *dat) +void TSAPI WriteThemeToINI(const wchar_t *szIniFilenameT, CMsgDialog *dat) { int i, n = 0; DBVARIANT dbv; diff --git a/plugins/TabSRMM/src/themes.cpp b/plugins/TabSRMM/src/themes.cpp index 48584e43e0..a1b2368a04 100644 --- a/plugins/TabSRMM/src/themes.cpp +++ b/plugins/TabSRMM/src/themes.cpp @@ -1911,7 +1911,7 @@ void CSkin::DrawDimmedIcon(HDC hdc, LONG left, LONG top, LONG dx, LONG dy, HICON DeleteDC(dcMem); } -UINT CSkin::NcCalcRichEditFrame(HWND hwnd, const CTabBaseDlg *mwdat, UINT skinID, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC MyWndProc) +UINT CSkin::NcCalcRichEditFrame(HWND hwnd, const CMsgDialog *mwdat, UINT skinID, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC MyWndProc) { NCCALCSIZE_PARAMS *nccp = (NCCALCSIZE_PARAMS *)lParam; BOOL bReturn = FALSE; @@ -1956,7 +1956,7 @@ UINT CSkin::NcCalcRichEditFrame(HWND hwnd, const CTabBaseDlg *mwdat, UINT skinID // process WM_NCPAINT for the rich edit control. Draws a visual style border and avoid // classic static edge / client edge may also draw a colorized border around the control -UINT CSkin::DrawRichEditFrame(HWND hwnd, const CTabBaseDlg *mwdat, UINT skinID, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC OldWndProc) +UINT CSkin::DrawRichEditFrame(HWND hwnd, const CMsgDialog *mwdat, UINT skinID, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC OldWndProc) { // do default processing (otherwise, NO scrollbar as it is painted in NC_PAINT) LRESULT result = (OldWndProc == nullptr) ? 0 : mir_callNextSubclass(hwnd, OldWndProc, msg, wParam, lParam); @@ -2142,7 +2142,7 @@ void CSkin::MapClientToParent(HWND hwndClient, HWND hwndParent, RECT &rc) // @param hdc HDC: handle to the device context in which painting should occur. // @param rcWindow RECT &: The window rectangle of the message dialog window -void CTabBaseDlg::RenderToolbarBG(HDC hdc, const RECT &rcWindow) const +void CMsgDialog::RenderToolbarBG(HDC hdc, const RECT &rcWindow) const { if (m_pContainer->m_dwFlags & CNT_HIDETOOLBAR) return; @@ -2401,7 +2401,7 @@ void CSkin::extractSkinsAndLogo(bool fForceOverwrite) const ///////////////////////////////////////////////////////////////////////////////////////// // redraw the splitter area between the message input and message log area only -void CTabBaseDlg::UpdateToolbarBG() +void CMsgDialog::UpdateToolbarBG() { RECT rcUpdate, rcTmp; ::GetWindowRect(m_log.GetHwnd(), &rcTmp); diff --git a/plugins/TabSRMM/src/themes.h b/plugins/TabSRMM/src/themes.h index 96233533a4..1f11390521 100644 --- a/plugins/TabSRMM/src/themes.h +++ b/plugins/TabSRMM/src/themes.h @@ -370,8 +370,8 @@ public: static void TSAPI SkinDrawBG(HWND hwndClient, HWND hwnd, TContainerData *pContainer, RECT *rcClient, HDC hdcTarget); static void TSAPI DrawDimmedIcon(HDC hdc, LONG left, LONG top, LONG dx, LONG dy, HICON hIcon, BYTE alpha); static DWORD TSAPI HexStringToLong(const wchar_t *szSource); - static UINT TSAPI DrawRichEditFrame(HWND hwnd, const CTabBaseDlg *mwdat, UINT skinID, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC OldWndProc); - static UINT TSAPI NcCalcRichEditFrame(HWND hwnd, const CTabBaseDlg *mwdat, UINT skinID, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC OldWndProc); + static UINT TSAPI DrawRichEditFrame(HWND hwnd, const CMsgDialog *mwdat, UINT skinID, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC OldWndProc); + static UINT TSAPI NcCalcRichEditFrame(HWND hwnd, const CMsgDialog *mwdat, UINT skinID, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC OldWndProc); static HBITMAP TSAPI CreateAeroCompatibleBitmap(const RECT &rc, HDC dc); static int TSAPI RenderText(HDC hdc, HANDLE hTheme, const wchar_t *szText, RECT *rc, DWORD dtFlags, const int iGlowSize = DEFAULT_GLOW_SIZE, COLORREF clr = 0, bool fForceAero = false); static void TSAPI MapClientToParent(HWND hwndClient, HWND hwndParent, RECT &rc); @@ -470,8 +470,8 @@ struct TabControlData HIMAGELIST himlDrag; TContainerData *pContainer; - CSrmmWindow *dragDat; - CSrmmWindow *helperDat; // points to the client data of the active tab + CMsgDialog *dragDat; + CMsgDialog *helperDat; // points to the client data of the active tab CImageItem *helperItem, *helperGlowItem; // aero ui, holding the skin image for the tabs }; @@ -497,12 +497,12 @@ struct ButtonItem { char szModule[256], szSetting[256]; BYTE bValuePush[256], bValueRelease[256]; DWORD type; - void(*pfnAction)(ButtonItem *item, HWND hwndDlg, CTabBaseDlg *dat, HWND hwndItem); - void(*pfnCallback)(ButtonItem *item, HWND hwndDlg, CTabBaseDlg *dat, HWND hwndItem); + void(*pfnAction)(ButtonItem *item, HWND hwndDlg, CMsgDialog *dat, HWND hwndItem); + void(*pfnCallback)(ButtonItem *item, HWND hwndDlg, CMsgDialog *dat, HWND hwndItem); wchar_t tszLabel[40]; ButtonItem* nextItem; HANDLE hContact; - CSrmmWindow *dat; + CMsgDialog *dat; }; typedef struct _tagButtonSet { diff --git a/plugins/TabSRMM/src/userprefs.cpp b/plugins/TabSRMM/src/userprefs.cpp index d8c947e8f8..71603c5833 100644 --- a/plugins/TabSRMM/src/userprefs.cpp +++ b/plugins/TabSRMM/src/userprefs.cpp @@ -132,14 +132,14 @@ static INT_PTR CALLBACK DlgProcUserPrefs(HWND hwndDlg, UINT msg, WPARAM wParam, break; case WM_USER + 100: - CSrmmWindow *dat = nullptr; + CMsgDialog *dat = nullptr; DWORD *pdwActionToTake = (DWORD *)lParam; unsigned int iOldIEView = 0; HWND hWnd = Srmm_FindWindow(hContact); BYTE bOldInfoPanel = M.GetByte(hContact, "infopanel", 0); if (hWnd) { - dat = (CSrmmWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(hWnd, GWLP_USERDATA); if (dat) iOldIEView = GetIEViewMode(dat->m_hContact); } @@ -274,7 +274,7 @@ checkboxes[] = { 0, 0 }; -int CTabBaseDlg::LoadLocalFlags() +int CMsgDialog::LoadLocalFlags() { DWORD dwMask = M.GetDword(m_hContact, "mwmask", 0); DWORD dwLocal = M.GetDword(m_hContact, "mwflags", 0); @@ -343,9 +343,9 @@ static INT_PTR CALLBACK DlgProcUserPrefsLogOptions(HWND hwndDlg, UINT msg, WPARA HWND hwnd = Srmm_FindWindow(hContact); DWORD *dwActionToTake = (DWORD *)lParam, dwMask = 0, dwFlags = 0, maskval; - CSrmmWindow *dat = nullptr; + CMsgDialog *dat = nullptr; if (hwnd) - dat = (CSrmmWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + dat = (CMsgDialog*)GetWindowLongPtr(hwnd, GWLP_USERDATA); while (checkboxes[i].uId) { maskval = checkboxes[i].uFlag; @@ -469,7 +469,7 @@ static INT_PTR CALLBACK DlgProcUserPrefsFrame(HWND hwndDlg, UINT msg, WPARAM wPa SendMessage(GetTabWindow(hwndTab, i), WM_COMMAND, WM_USER + 100, (LPARAM)&dwActionToTake); if (hwnd) { - CSrmmWindow *dat = (CSrmmWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + CMsgDialog *dat = (CMsgDialog*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if (dat) { DWORD dwOldFlags = (dat->m_dwFlags & MWF_LOG_ALL); dat->SetDialogToType(); diff --git a/plugins/TabSRMM/src/utils.cpp b/plugins/TabSRMM/src/utils.cpp index eb39976b8f..a3f75b02a4 100644 --- a/plugins/TabSRMM/src/utils.cpp +++ b/plugins/TabSRMM/src/utils.cpp @@ -49,7 +49,7 @@ static wchar_t *formatting_strings_end[] = { L"b0 ", L"i0 ", L"u0 ", L"s0 ", // flags: loword = words only for simple * /_ formatting // hiword = bbcode support (strip bbcodes if 0) -void CTabBaseDlg::FormatRaw(CMStringW &msg, int flags, bool isSent) +void CMsgDialog::FormatRaw(CMStringW &msg, int flags, bool isSent) { bool clr_was_added = false, was_added; int beginmark = 0, endmark = 0, tempmark = 0, index; @@ -221,7 +221,7 @@ static wchar_t* Trunc500(wchar_t *str) return str; } -bool CTabBaseDlg::FormatTitleBar(const wchar_t *szFormat, CMStringW &dest) +bool CMsgDialog::FormatTitleBar(const wchar_t *szFormat, CMStringW &dest) { for (const wchar_t *src = szFormat; *src; src++) { if (*src != '%') { @@ -388,7 +388,7 @@ wchar_t* Utils::GetPreviewWithEllipsis(wchar_t *szText, size_t iMaxLen) // returns != 0 when one of the installed keyboard layouts belongs to an rtl language // used to find out whether we need to configure the message input box for bidirectional mode -int CTabBaseDlg::FindRTLLocale() +int CMsgDialog::FindRTLLocale() { HKL layouts[20]; int i, result = 0; @@ -639,7 +639,7 @@ void Utils::scaleAvatarHeightLimited(const HBITMAP hBm, double& dNewWidth, doubl // @param dat: _MessageWindowData* pointer to the window data // @return HICON: the icon handle -HICON CTabBaseDlg::IconFromAvatar() const +HICON CMsgDialog::IconFromAvatar() const { if (!ServiceExists(MS_AV_GETAVATARBITMAP)) return nullptr; @@ -741,7 +741,7 @@ void Utils::addMenuItem(const HMENU& m, MENUITEMINFO &mii, HICON hIcon, const wc // return != 0 when the sound effect must be played for the given // session. Uses container sound settings -int CTabBaseDlg::MustPlaySound() const +int CMsgDialog::MustPlaySound() const { if (m_pContainer->m_bHidden) // hidden container is treated as closed, so play the sound return 1; diff --git a/plugins/TabSRMM/src/version.h b/plugins/TabSRMM/src/version.h index 30740a8842..c77447f4ae 100644 --- a/plugins/TabSRMM/src/version.h +++ b/plugins/TabSRMM/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 3 -#define __MINOR_VERSION 5 +#define __MINOR_VERSION 6 #define __RELEASE_NUM 0 -#define __BUILD_NUM 14 +#define __BUILD_NUM 1 #include -- cgit v1.2.3