diff options
Diffstat (limited to 'plugins/TabSRMM/src/msgdialog.cpp')
-rw-r--r-- | plugins/TabSRMM/src/msgdialog.cpp | 6781 |
1 files changed, 3391 insertions, 3390 deletions
diff --git a/plugins/TabSRMM/src/msgdialog.cpp b/plugins/TabSRMM/src/msgdialog.cpp index 717cfc28a8..8945853bd9 100644 --- a/plugins/TabSRMM/src/msgdialog.cpp +++ b/plugins/TabSRMM/src/msgdialog.cpp @@ -1,3396 +1,3397 @@ -///////////////////////////////////////////////////////////////////////////////////////// -// Miranda NG: the free IM client for Microsoft* Windows* -// -// Copyright (ñ) 2012-15 Miranda NG project, -// 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 -// -// implements the message dialog window. - -#include "commonheaders.h" - -#define MS_HTTPSERVER_ADDFILENAME "HTTPServer/AddFileName" - -bool IsStringValidLink(TCHAR* pszText); - -const TCHAR *pszIDCSAVE_close = 0, *pszIDCSAVE_save = 0; - -static const UINT sendControls[] = { IDC_MESSAGE, IDC_LOG }; -static const UINT formatControls[] = { IDC_SMILEYBTN, IDC_FONTBOLD, IDC_FONTITALIC, IDC_FONTUNDERLINE, IDC_FONTFACE,IDC_FONTSTRIKEOUT }; -static const UINT addControls[] = { IDC_ADD, IDC_CANCELADD }; -static const UINT btnControls[] = { IDC_RETRY, IDC_CANCELSEND, IDC_MSGSENDLATER, IDC_ADD, IDC_CANCELADD }; -static const UINT errorControls[] = { IDC_STATICERRORICON, IDC_STATICTEXT, IDC_RETRY, IDC_CANCELSEND, IDC_MSGSENDLATER}; - +/////////////////////////////////////////////////////////////////////////////////////////
+// Miranda NG: the free IM client for Microsoft* Windows*
+//
+// Copyright (ñ) 2012-15 Miranda NG project,
+// 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
+//
+// implements the message dialog window.
+
+#include "commonheaders.h"
+
+#define MS_HTTPSERVER_ADDFILENAME "HTTPServer/AddFileName"
+
+bool IsStringValidLink(TCHAR* pszText);
+
+const TCHAR *pszIDCSAVE_close = 0, *pszIDCSAVE_save = 0;
+
+static const UINT sendControls[] = { IDC_MESSAGE, IDC_LOG };
+static const UINT formatControls[] = { IDC_SMILEYBTN, IDC_FONTBOLD, IDC_FONTITALIC, IDC_FONTUNDERLINE, IDC_FONTFACE, IDC_FONTSTRIKEOUT };
+static const UINT addControls[] = { IDC_ADD, IDC_CANCELADD };
+static const UINT btnControls[] = { IDC_RETRY, IDC_CANCELSEND, IDC_MSGSENDLATER, IDC_ADD, IDC_CANCELADD };
+static const UINT errorControls[] = { IDC_STATICERRORICON, IDC_STATICTEXT, IDC_RETRY, IDC_CANCELSEND, IDC_MSGSENDLATER };
+
static COLORREF rtfDefColors[] = { RGB(255, 0, 0), RGB(0, 0, 255), RGB(0, 255, 0), RGB(255, 0, 255), RGB(255, 255, 0), RGB(0, 255, 255), 0, RGB(255, 255, 255) };
- -static struct { - int id; - const TCHAR* text; -} -tooltips[] = -{ - { IDC_ADD, LPGENT("Add this contact permanently to your contact list") }, - { IDC_CANCELADD, LPGENT("Do not add this contact permanently") }, - { IDC_TOGGLESIDEBAR, LPGENT("Expand or collapse the side bar") } -}; - -static struct -{ - int id; - HICON *pIcon; -} -buttonicons[] = -{ - { IDC_ADD, &PluginConfig.g_buttonBarIcons[ICON_BUTTON_ADD] }, - { IDC_CANCELADD, &PluginConfig.g_buttonBarIcons[ICON_BUTTON_CANCEL] } -}; - -static void _clrMsgFilter(LPARAM lParam) -{ - MSGFILTER *m = reinterpret_cast<MSGFILTER *>(lParam); - m->msg = 0; - m->lParam = 0; - m->wParam = 0; -} - -BOOL TSAPI IsUtfSendAvailable(MCONTACT hContact) -{ - char *szProto = GetContactProto(hContact); - if (szProto == NULL) - return FALSE; - - return (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_IMSENDUTF) ? TRUE : FALSE; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// show a modified context menu for the richedit control(s) -// @param dat message window data -// @param idFrom dlg ctrl id -// @param hwndFrom src window handle -// @param pt mouse pointer position - -static void ShowPopupMenu(TWindowData *dat, int idFrom, HWND hwndFrom, POINT pt) -{ - CHARRANGE sel, all = { 0, -1}; - int oldCodepage = dat->codePage; - HWND hwndDlg = dat->hwnd; - - HMENU hSubMenu, hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)); - if (idFrom == IDC_LOG) - hSubMenu = GetSubMenu(hMenu, 0); - else { - hSubMenu = GetSubMenu(hMenu, 2); - EnableMenuItem(hSubMenu, IDM_PASTEFORMATTED, MF_BYCOMMAND | (dat->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 | (dat->pContainer->hwndStatus ? MF_ENABLED : MF_GRAYED)); - } - TranslateMenu(hSubMenu); - SendMessage(hwndFrom, 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 (idFrom == IDC_MESSAGE) - EnableMenuItem(hSubMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED); - } - - if (idFrom == IDC_LOG) { - InsertMenuA(hSubMenu, 6/*5*/, MF_BYPOSITION | MF_SEPARATOR, 0, 0); - InsertMenu(hSubMenu, 7/*6*/, MF_BYPOSITION | MF_POPUP, (UINT_PTR) PluginConfig.g_hMenuEncoding, TranslateT("Character encoding")); - for (int i=0; i < GetMenuItemCount(PluginConfig.g_hMenuEncoding); i++) - CheckMenuItem(PluginConfig.g_hMenuEncoding, i, MF_BYPOSITION | MF_UNCHECKED); - - if (dat->codePage == CP_ACP) - CheckMenuItem(PluginConfig.g_hMenuEncoding, 0, MF_BYPOSITION | MF_CHECKED); - else - CheckMenuItem(PluginConfig.g_hMenuEncoding, dat->codePage, MF_BYCOMMAND | MF_CHECKED); - - CheckMenuItem(hSubMenu, ID_LOG_FREEZELOG, MF_BYCOMMAND | (dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED ? MF_CHECKED : MF_UNCHECKED)); - } - - MessageWindowPopupData mwpd; - if (idFrom == IDC_LOG || idFrom == IDC_MESSAGE) { - // First notification - mwpd.cbSize = sizeof(mwpd); - mwpd.uType = MSG_WINDOWPOPUP_SHOWING; - mwpd.uFlags = (idFrom == IDC_LOG ? MSG_WINDOWPOPUP_LOG : MSG_WINDOWPOPUP_INPUT); - mwpd.hContact = dat->hContact; - mwpd.hwnd = hwndFrom; - mwpd.hMenu = hSubMenu; - mwpd.selection = 0; - mwpd.pt = pt; - NotifyEventHooks(PluginConfig.m_event_MsgPopup, 0, (LPARAM)&mwpd); - } - - int iSelection = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL); - - if (idFrom == IDC_LOG || idFrom == IDC_MESSAGE) { - // Second notification - mwpd.selection = iSelection; - mwpd.uType = MSG_WINDOWPOPUP_SELECTED; - NotifyEventHooks(PluginConfig.m_event_MsgPopup, 0, (LPARAM)&mwpd); - } - - if (((iSelection > 800 && iSelection < 1400) || iSelection == 20866) && idFrom == IDC_LOG) { - dat->codePage = iSelection; - db_set_dw(dat->hContact, SRMSGMOD_T, "ANSIcodepage", dat->codePage); - } - else if (iSelection == 500 && idFrom == IDC_LOG) { - dat->codePage = CP_ACP; - db_unset(dat->hContact, SRMSGMOD_T, "ANSIcodepage"); - } - else { - switch (iSelection) { - case IDM_COPY: - SendMessage(hwndFrom, WM_COPY, 0, 0); - break; - case IDM_CUT: - SendMessage(hwndFrom, WM_CUT, 0, 0); - break; - case IDM_PASTE: - case IDM_PASTEFORMATTED: - if (idFrom == IDC_MESSAGE) - SendMessage(hwndFrom, EM_PASTESPECIAL, (iSelection == IDM_PASTE) ? CF_UNICODETEXT : 0, 0); - break; - case IDM_COPYALL: - SendMessage(hwndFrom, EM_EXSETSEL, 0, (LPARAM)&all); - SendMessage(hwndFrom, WM_COPY, 0, 0); - SendMessage(hwndFrom, EM_EXSETSEL, 0, (LPARAM)&sel); - break; - case IDM_QUOTE: - SendMessage(hwndDlg, WM_COMMAND, IDC_QUOTE, 0); - break; - case IDM_SELECTALL: - SendMessage(hwndFrom, EM_EXSETSEL, 0, (LPARAM)&all); - break; - case IDM_CLEAR: - ClearLog(dat); - break; - case ID_LOG_FREEZELOG: - SendDlgItemMessage(hwndDlg, IDC_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); - M.BroadcastMessage(DM_CONFIGURETOOLBAR, 0, 0); - SendMessage(hwndDlg, WM_SIZE, 0, 0); - if (dat->pContainer->hwndStatus) - RedrawWindow(dat->pContainer->hwndStatus, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW); - break; - case ID_EDITOR_PASTEANDSENDIMMEDIATELY: - HandlePasteAndSend(dat); - break; - } - } - if (idFrom == IDC_LOG) - RemoveMenu(hSubMenu, 7, MF_BYPOSITION); - DestroyMenu(hMenu); - if (dat->codePage != (UINT)oldCodepage) { - SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); - SendMessage(hwndDlg, DM_UPDATETITLE, 0, 1); - } -} - -static void ResizeIeView(const TWindowData *dat) -{ - RECT rcRichEdit; - GetWindowRect(GetDlgItem(dat->hwnd, IDC_LOG), &rcRichEdit); - - POINT pt = { rcRichEdit.left, rcRichEdit.top }; - ScreenToClient(dat->hwnd, &pt); - - IEVIEWWINDOW ieWindow = { sizeof(ieWindow) }; - ieWindow.iType = IEW_SETPOS; - ieWindow.parent = dat->hwnd; - ieWindow.hwnd = dat->hwndIEView ? dat->hwndIEView : dat->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(dat->hwndIEView ? MS_IEVIEW_WINDOW : MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow); -} - -LRESULT CALLBACK IEViewSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - TWindowData *mwdat = (TWindowData*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); - - switch (msg) { - case WM_NCCALCSIZE: - return CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, IEViewSubclassProc); - case WM_NCPAINT: - return CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, IEViewSubclassProc); - } - 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) -{ - TWindowData *mwdat = (TWindowData*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); - if (mwdat) { - BOOL isCtrl, isShift, isAlt; - KbdState(mwdat, isShift, isCtrl, isAlt); - - switch (msg) { - case WM_NCCALCSIZE: - return CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, HPPKFSubclassProc); - case WM_NCPAINT: - return CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, HPPKFSubclassProc); - - case WM_KEYDOWN: - if (!isCtrl && !isAlt && !isShift) { - if (wParam != VK_PRIOR && wParam != VK_NEXT && wParam != VK_DELETE && - wParam != VK_MENU && wParam != VK_END && wParam != VK_HOME && - wParam != VK_UP && wParam != VK_DOWN && wParam != VK_LEFT && - wParam != VK_RIGHT && wParam != VK_TAB && wParam != VK_SPACE) - { - SetFocus(GetDlgItem(mwdat->hwnd, IDC_MESSAGE)); - keybd_event((BYTE)wParam, (BYTE)MapVirtualKey(wParam, 0), KEYEVENTF_EXTENDEDKEY | 0, 0); - return 0; - } - break; - } - } - } - 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) - -static void MsgWindowUpdateState(TWindowData *dat, UINT msg) -{ - if (dat == NULL || dat->iTabID < 0) - return; - - HWND hwndDlg = dat->hwnd; - HWND hwndTab = GetParent(hwndDlg); - - if (msg == WM_ACTIVATE) { - if (dat->pContainer->dwFlags & CNT_TRANSPARENCY) { - DWORD trans = LOWORD(dat->pContainer->settings->dwTransparency); - SetLayeredWindowAttributes(dat->pContainer->hwnd, 0, (BYTE)trans, (dat->pContainer->dwFlags & CNT_TRANSPARENCY ? LWA_ALPHA : 0)); - } - } - - if (dat->bIsAutosizingInput && dat->iInputAreaHeight == -1) { - dat->iInputAreaHeight = 0; - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_REQUESTRESIZE, 0, 0); - } - - if (dat->pWnd) - dat->pWnd->activateTab(); - dat->Panel->dismissConfig(); - dat->dwUnread = 0; - if (dat->pContainer->hwndSaved == hwndDlg) - return; - - dat->pContainer->hwndSaved = hwndDlg; - - dat->dwTickLastEvent = 0; - dat->dwFlags &= ~MWF_DIVIDERSET; - if (KillTimer(hwndDlg, TIMERID_FLASHWND)) { - FlashTab(dat, hwndTab, dat->iTabID, &dat->bTabFlash, FALSE, dat->hTabIcon); - dat->mayFlashTab = FALSE; - } - if (dat->pContainer->dwFlashingStarted != 0) { - FlashContainer(dat->pContainer, 0, 0); - dat->pContainer->dwFlashingStarted = 0; - } - if (dat->dwFlagsEx & MWF_SHOW_FLASHCLIST) { - dat->dwFlagsEx &= ~MWF_SHOW_FLASHCLIST; - if (dat->hFlashingEvent != 0) - CallService(MS_CLIST_REMOVEEVENT, dat->hContact, (LPARAM)dat->hFlashingEvent); - dat->hFlashingEvent = 0; - } - dat->pContainer->dwFlags &= ~CNT_NEED_UPDATETITLE; - - if ((dat->dwFlags & MWF_DEFERREDREMAKELOG) && !IsIconic(dat->pContainer->hwnd)) { - SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); - dat->dwFlags &= ~MWF_DEFERREDREMAKELOG; - } - - if (dat->dwFlags & MWF_NEEDCHECKSIZE) - PostMessage(hwndDlg, DM_SAVESIZE, 0, 0); - - if (PluginConfig.m_bAutoLocaleSupport) { - if (dat->hkl == 0) - DM_LoadLocale(dat); - else - SendMessage(hwndDlg, DM_SETLOCALE, 0, 0); - } - - dat->pContainer->hIconTaskbarOverlay = 0; - SendMessage(dat->pContainer->hwnd, DM_UPDATETITLE, dat->hContact, 0); - - UpdateStatusBar(dat); - dat->dwLastActivity = GetTickCount(); - dat->pContainer->dwLastActivity = dat->dwLastActivity; - - dat->pContainer->MenuBar->configureMenu(); - UpdateTrayMenuState(dat, FALSE); - - if (dat->pContainer->hwndActive == hwndDlg) - PostMessage(hwndDlg, DM_REMOVEPOPUPS, PU_REMOVE_ON_FOCUS, 0); - - dat->Panel->Invalidate(); - +
+static struct {
+ int id;
+ const TCHAR* text;
+}
+tooltips[] =
+{
+ { IDC_ADD, LPGENT("Add this contact permanently to your contact list") },
+ { IDC_CANCELADD, LPGENT("Do not add this contact permanently") },
+ { IDC_TOGGLESIDEBAR, LPGENT("Expand or collapse the side bar") }
+};
+
+static struct
+{
+ int id;
+ HICON *pIcon;
+}
+buttonicons[] =
+{
+ { IDC_ADD, &PluginConfig.g_buttonBarIcons[ICON_BUTTON_ADD] },
+ { IDC_CANCELADD, &PluginConfig.g_buttonBarIcons[ICON_BUTTON_CANCEL] }
+};
+
+static void _clrMsgFilter(LPARAM lParam)
+{
+ MSGFILTER *m = reinterpret_cast<MSGFILTER *>(lParam);
+ m->msg = 0;
+ m->lParam = 0;
+ m->wParam = 0;
+}
+
+BOOL TSAPI IsUtfSendAvailable(MCONTACT hContact)
+{
+ char *szProto = GetContactProto(hContact);
+ if (szProto == NULL)
+ return FALSE;
+
+ return (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_IMSENDUTF) ? TRUE : FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// show a modified context menu for the richedit control(s)
+// @param dat message window data
+// @param idFrom dlg ctrl id
+// @param hwndFrom src window handle
+// @param pt mouse pointer position
+
+static void ShowPopupMenu(TWindowData *dat, int idFrom, HWND hwndFrom, POINT pt)
+{
+ CHARRANGE sel, all = { 0, -1 };
+ int oldCodepage = dat->codePage;
+ HWND hwndDlg = dat->hwnd;
+
+ HMENU hSubMenu, hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT));
+ if (idFrom == IDC_LOG)
+ hSubMenu = GetSubMenu(hMenu, 0);
+ else {
+ hSubMenu = GetSubMenu(hMenu, 2);
+ EnableMenuItem(hSubMenu, IDM_PASTEFORMATTED, MF_BYCOMMAND | (dat->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 | (dat->pContainer->hwndStatus ? MF_ENABLED : MF_GRAYED));
+ }
+ TranslateMenu(hSubMenu);
+ SendMessage(hwndFrom, 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 (idFrom == IDC_MESSAGE)
+ EnableMenuItem(hSubMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED);
+ }
+
+ if (idFrom == IDC_LOG) {
+ InsertMenuA(hSubMenu, 6/*5*/, MF_BYPOSITION | MF_SEPARATOR, 0, 0);
+ InsertMenu(hSubMenu, 7/*6*/, MF_BYPOSITION | MF_POPUP, (UINT_PTR)PluginConfig.g_hMenuEncoding, TranslateT("Character encoding"));
+ for (int i = 0; i < GetMenuItemCount(PluginConfig.g_hMenuEncoding); i++)
+ CheckMenuItem(PluginConfig.g_hMenuEncoding, i, MF_BYPOSITION | MF_UNCHECKED);
+
+ if (dat->codePage == CP_ACP)
+ CheckMenuItem(PluginConfig.g_hMenuEncoding, 0, MF_BYPOSITION | MF_CHECKED);
+ else
+ CheckMenuItem(PluginConfig.g_hMenuEncoding, dat->codePage, MF_BYCOMMAND | MF_CHECKED);
+
+ CheckMenuItem(hSubMenu, ID_LOG_FREEZELOG, MF_BYCOMMAND | (dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED ? MF_CHECKED : MF_UNCHECKED));
+ }
+
+ MessageWindowPopupData mwpd;
+ if (idFrom == IDC_LOG || idFrom == IDC_MESSAGE) {
+ // First notification
+ mwpd.cbSize = sizeof(mwpd);
+ mwpd.uType = MSG_WINDOWPOPUP_SHOWING;
+ mwpd.uFlags = (idFrom == IDC_LOG ? MSG_WINDOWPOPUP_LOG : MSG_WINDOWPOPUP_INPUT);
+ mwpd.hContact = dat->hContact;
+ mwpd.hwnd = hwndFrom;
+ mwpd.hMenu = hSubMenu;
+ mwpd.selection = 0;
+ mwpd.pt = pt;
+ NotifyEventHooks(PluginConfig.m_event_MsgPopup, 0, (LPARAM)&mwpd);
+ }
+
+ int iSelection = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL);
+
+ if (idFrom == IDC_LOG || idFrom == IDC_MESSAGE) {
+ // Second notification
+ mwpd.selection = iSelection;
+ mwpd.uType = MSG_WINDOWPOPUP_SELECTED;
+ NotifyEventHooks(PluginConfig.m_event_MsgPopup, 0, (LPARAM)&mwpd);
+ }
+
+ if (((iSelection > 800 && iSelection < 1400) || iSelection == 20866) && idFrom == IDC_LOG) {
+ dat->codePage = iSelection;
+ db_set_dw(dat->hContact, SRMSGMOD_T, "ANSIcodepage", dat->codePage);
+ }
+ else if (iSelection == 500 && idFrom == IDC_LOG) {
+ dat->codePage = CP_ACP;
+ db_unset(dat->hContact, SRMSGMOD_T, "ANSIcodepage");
+ }
+ else {
+ switch (iSelection) {
+ case IDM_COPY:
+ SendMessage(hwndFrom, WM_COPY, 0, 0);
+ break;
+ case IDM_CUT:
+ SendMessage(hwndFrom, WM_CUT, 0, 0);
+ break;
+ case IDM_PASTE:
+ case IDM_PASTEFORMATTED:
+ if (idFrom == IDC_MESSAGE)
+ SendMessage(hwndFrom, EM_PASTESPECIAL, (iSelection == IDM_PASTE) ? CF_UNICODETEXT : 0, 0);
+ break;
+ case IDM_COPYALL:
+ SendMessage(hwndFrom, EM_EXSETSEL, 0, (LPARAM)&all);
+ SendMessage(hwndFrom, WM_COPY, 0, 0);
+ SendMessage(hwndFrom, EM_EXSETSEL, 0, (LPARAM)&sel);
+ break;
+ case IDM_QUOTE:
+ SendMessage(hwndDlg, WM_COMMAND, IDC_QUOTE, 0);
+ break;
+ case IDM_SELECTALL:
+ SendMessage(hwndFrom, EM_EXSETSEL, 0, (LPARAM)&all);
+ break;
+ case IDM_CLEAR:
+ ClearLog(dat);
+ break;
+ case ID_LOG_FREEZELOG:
+ SendDlgItemMessage(hwndDlg, IDC_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);
+ M.BroadcastMessage(DM_CONFIGURETOOLBAR, 0, 0);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ if (dat->pContainer->hwndStatus)
+ RedrawWindow(dat->pContainer->hwndStatus, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW);
+ break;
+ case ID_EDITOR_PASTEANDSENDIMMEDIATELY:
+ HandlePasteAndSend(dat);
+ break;
+ }
+ }
+ if (idFrom == IDC_LOG)
+ RemoveMenu(hSubMenu, 7, MF_BYPOSITION);
+ DestroyMenu(hMenu);
+ if (dat->codePage != (UINT)oldCodepage) {
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+ SendMessage(hwndDlg, DM_UPDATETITLE, 0, 1);
+ }
+}
+
+static void ResizeIeView(const TWindowData *dat)
+{
+ RECT rcRichEdit;
+ GetWindowRect(GetDlgItem(dat->hwnd, IDC_LOG), &rcRichEdit);
+
+ POINT pt = { rcRichEdit.left, rcRichEdit.top };
+ ScreenToClient(dat->hwnd, &pt);
+
+ IEVIEWWINDOW ieWindow = { sizeof(ieWindow) };
+ ieWindow.iType = IEW_SETPOS;
+ ieWindow.parent = dat->hwnd;
+ ieWindow.hwnd = dat->hwndIEView ? dat->hwndIEView : dat->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(dat->hwndIEView ? MS_IEVIEW_WINDOW : MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow);
+}
+
+LRESULT CALLBACK IEViewSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TWindowData *mwdat = (TWindowData*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA);
+
+ switch (msg) {
+ case WM_NCCALCSIZE:
+ return CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, IEViewSubclassProc);
+ case WM_NCPAINT:
+ return CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, IEViewSubclassProc);
+ }
+ 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)
+{
+ TWindowData *mwdat = (TWindowData*)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA);
+ if (mwdat) {
+ BOOL isCtrl, isShift, isAlt;
+ KbdState(mwdat, isShift, isCtrl, isAlt);
+
+ switch (msg) {
+ case WM_NCCALCSIZE:
+ return CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, HPPKFSubclassProc);
+ case WM_NCPAINT:
+ return CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, HPPKFSubclassProc);
+
+ case WM_KEYDOWN:
+ if (!isCtrl && !isAlt && !isShift) {
+ if (wParam != VK_PRIOR && wParam != VK_NEXT && wParam != VK_DELETE &&
+ wParam != VK_MENU && wParam != VK_END && wParam != VK_HOME &&
+ wParam != VK_UP && wParam != VK_DOWN && wParam != VK_LEFT &&
+ wParam != VK_RIGHT && wParam != VK_TAB && wParam != VK_SPACE)
+ {
+ SetFocus(GetDlgItem(mwdat->hwnd, IDC_MESSAGE));
+ keybd_event((BYTE)wParam, (BYTE)MapVirtualKey(wParam, 0), KEYEVENTF_EXTENDEDKEY | 0, 0);
+ return 0;
+ }
+ break;
+ }
+ }
+ }
+ 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)
+
+static void MsgWindowUpdateState(TWindowData *dat, UINT msg)
+{
+ if (dat == NULL || dat->iTabID < 0)
+ return;
+
+ HWND hwndDlg = dat->hwnd;
+ HWND hwndTab = GetParent(hwndDlg);
+
+ if (msg == WM_ACTIVATE) {
+ if (dat->pContainer->dwFlags & CNT_TRANSPARENCY) {
+ DWORD trans = LOWORD(dat->pContainer->settings->dwTransparency);
+ SetLayeredWindowAttributes(dat->pContainer->hwnd, 0, (BYTE)trans, (dat->pContainer->dwFlags & CNT_TRANSPARENCY ? LWA_ALPHA : 0));
+ }
+ }
+
+ if (dat->bIsAutosizingInput && dat->iInputAreaHeight == -1) {
+ dat->iInputAreaHeight = 0;
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_REQUESTRESIZE, 0, 0);
+ }
+
+ if (dat->pWnd)
+ dat->pWnd->activateTab();
+ dat->Panel->dismissConfig();
+ dat->dwUnread = 0;
+ if (dat->pContainer->hwndSaved == hwndDlg)
+ return;
+
+ dat->pContainer->hwndSaved = hwndDlg;
+
+ dat->dwTickLastEvent = 0;
+ dat->dwFlags &= ~MWF_DIVIDERSET;
+ if (KillTimer(hwndDlg, TIMERID_FLASHWND)) {
+ FlashTab(dat, hwndTab, dat->iTabID, &dat->bTabFlash, FALSE, dat->hTabIcon);
+ dat->mayFlashTab = FALSE;
+ }
+ if (dat->pContainer->dwFlashingStarted != 0) {
+ FlashContainer(dat->pContainer, 0, 0);
+ dat->pContainer->dwFlashingStarted = 0;
+ }
+ if (dat->dwFlagsEx & MWF_SHOW_FLASHCLIST) {
+ dat->dwFlagsEx &= ~MWF_SHOW_FLASHCLIST;
+ if (dat->hFlashingEvent != 0)
+ CallService(MS_CLIST_REMOVEEVENT, dat->hContact, (LPARAM)dat->hFlashingEvent);
+ dat->hFlashingEvent = 0;
+ }
+ dat->pContainer->dwFlags &= ~CNT_NEED_UPDATETITLE;
+
+ if ((dat->dwFlags & MWF_DEFERREDREMAKELOG) && !IsIconic(dat->pContainer->hwnd)) {
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+ dat->dwFlags &= ~MWF_DEFERREDREMAKELOG;
+ }
+
+ if (dat->dwFlags & MWF_NEEDCHECKSIZE)
+ PostMessage(hwndDlg, DM_SAVESIZE, 0, 0);
+
+ if (PluginConfig.m_bAutoLocaleSupport) {
+ if (dat->hkl == 0)
+ DM_LoadLocale(dat);
+ else
+ SendMessage(hwndDlg, DM_SETLOCALE, 0, 0);
+ }
+
+ dat->pContainer->hIconTaskbarOverlay = 0;
+ SendMessage(dat->pContainer->hwnd, DM_UPDATETITLE, dat->hContact, 0);
+
+ UpdateStatusBar(dat);
+ dat->dwLastActivity = GetTickCount();
+ dat->pContainer->dwLastActivity = dat->dwLastActivity;
+
+ dat->pContainer->MenuBar->configureMenu();
+ UpdateTrayMenuState(dat, FALSE);
+
+ if (dat->pContainer->hwndActive == hwndDlg)
+ PostMessage(hwndDlg, DM_REMOVEPOPUPS, PU_REMOVE_ON_FOCUS, 0);
+
+ dat->Panel->Invalidate();
+
if (dat->dwFlags & MWF_DEFERREDSCROLL && dat->hwndIEView == 0 && dat->hwndHPP == 0) {
dat->dwFlags &= ~MWF_DEFERREDSCROLL;
DM_ScrollToBottom(dat, 0, 1);
}
- - DM_SetDBButtonStates(hwndDlg, dat); - - if (dat->hwndIEView) { - RECT rcRTF; - POINT pt; - - GetWindowRect(GetDlgItem(hwndDlg, IDC_LOG), &rcRTF); - rcRTF.left += 20; - rcRTF.top += 20; - pt.x = rcRTF.left; - pt.y = rcRTF.top; - if (dat->hwndIEView) { - if (M.GetByte("subclassIEView", 0)) { - mir_subclassWindow(dat->hwndIEView, IEViewSubclassProc); - SetWindowPos(dat->hwndIEView, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_DRAWFRAME); - RedrawWindow(dat->hwndIEView, 0, 0, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW); - } - } - dat->hwndIWebBrowserControl = WindowFromPoint(pt); - } - - if (dat->dwFlagsEx & MWF_EX_DELAYEDSPLITTER) { - dat->dwFlagsEx &= ~MWF_EX_DELAYEDSPLITTER; - ShowWindow(dat->pContainer->hwnd, SW_RESTORE); - PostMessage(hwndDlg, DM_SPLITTERGLOBALEVENT, dat->wParam, dat->lParam); - dat->wParam = dat->lParam = 0; - } - if (dat->dwFlagsEx & MWF_EX_AVATARCHANGED) { - dat->dwFlagsEx &= ~MWF_EX_AVATARCHANGED; - PostMessage(hwndDlg, DM_UPDATEPICLAYOUT, 0, 0); - } - BB_SetButtonsPos(dat); - if (M.isAero()) - InvalidateRect(hwndTab, NULL, FALSE); - if (dat->pContainer->dwFlags & CNT_SIDEBAR) - dat->pContainer->SideBar->setActiveItem(dat); - - if (dat->pWnd) - dat->pWnd->Invalidate(); -} - -void TSAPI ShowMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state) -{ - for (int i = 0; i < cControls; i++) - Utils::showDlgControl(hwndDlg, controls[i], state); -} - -void TSAPI SetDialogToType(HWND hwndDlg) -{ - TWindowData *dat = (TWindowData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - if (dat->hContact) { - if (db_get_b(dat->hContact, "CList", "NotOnList", 0)) { - dat->bNotOnList = TRUE; - ShowMultipleControls(hwndDlg, addControls, 2, SW_SHOW); - Utils::showDlgControl(hwndDlg, IDC_LOGFROZENTEXT, SW_SHOW); - SetDlgItemText(hwndDlg, IDC_LOGFROZENTEXT, TranslateT("Contact not on list. You may add it...")); - } - else { - ShowMultipleControls(hwndDlg, addControls, 2, SW_HIDE); - dat->bNotOnList = FALSE; - Utils::showDlgControl(hwndDlg, IDC_LOGFROZENTEXT, SW_HIDE); - } - } - - Utils::enableDlgControl(hwndDlg, IDC_TIME, true); - - if (dat->hwndIEView || dat->hwndHPP) { - Utils::showDlgControl(hwndDlg, IDC_LOG, SW_HIDE); - Utils::enableDlgControl(hwndDlg, IDC_LOG, false); - Utils::showDlgControl(hwndDlg, IDC_MESSAGE, SW_SHOW); - } - else ShowMultipleControls(hwndDlg, sendControls, sizeof(sendControls) / sizeof(sendControls[0]), SW_SHOW); - - ShowMultipleControls(hwndDlg, errorControls, sizeof(errorControls) / sizeof(errorControls[0]), dat->dwFlags & MWF_ERRORSTATE ? SW_SHOW : SW_HIDE); - - if (!dat->SendFormat) - ShowMultipleControls(hwndDlg, &formatControls[1], 5, SW_HIDE); - - ConfigureSmileyButton(dat); - - if (dat->pContainer->hwndActive == hwndDlg) - UpdateReadChars(dat); - - SetDlgItemText(hwndDlg, IDC_STATICTEXT, TranslateT("A message failed to send successfully.")); - - DM_RecalcPictureSize(dat); - GetAvatarVisibility(hwndDlg, dat); - - Utils::showDlgControl(hwndDlg, IDC_CONTACTPIC, dat->bShowAvatar ? SW_SHOW : SW_HIDE); - Utils::showDlgControl(hwndDlg, IDC_SPLITTER, dat->bIsAutosizingInput ? SW_HIDE : SW_SHOW); - Utils::showDlgControl(hwndDlg, IDC_MULTISPLITTER, (dat->sendMode & SMODE_MULTIPLE) ? SW_SHOW : SW_HIDE); - - EnableSendButton(dat, GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)) != 0); - SendMessage(hwndDlg, DM_UPDATETITLE, 0, 1); - SendMessage(hwndDlg, WM_SIZE, 0, 0); - - Utils::enableDlgControl(hwndDlg, IDC_CONTACTPIC, false); - - dat->Panel->Configure(); -} - -static LRESULT CALLBACK MessageLogSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HWND hwndParent = GetParent(hwnd); - TWindowData *mwdat = (TWindowData*)GetWindowLongPtr(hwndParent, GWLP_USERDATA); - BOOL isCtrl, isShift, isAlt; - KbdState(mwdat, isShift, isCtrl, isAlt); - - switch (msg) { - case WM_KILLFOCUS: - if (wParam != (WPARAM)hwnd && 0 != wParam) { - CHARRANGE cr; - SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&cr); - if (cr.cpMax != cr.cpMin) { - cr.cpMin = cr.cpMax; - SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&cr); - } - } - break; - - case WM_CHAR: - if (wParam == 0x03 && isCtrl) // Ctrl+C - return DM_WMCopyHandler(hwnd, MessageLogSubclassProc, msg, wParam, lParam); - if (wParam == 0x11 && isCtrl) - SendMessage(mwdat->hwnd, WM_COMMAND, IDC_QUOTE, 0); - break; - - case WM_SYSKEYUP: - if (wParam == VK_MENU) { - ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_LOG); - return 0; - } - break; - - case WM_SYSKEYDOWN: - mwdat->fkeyProcessed = false; - if (ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_LOG)) { - mwdat->fkeyProcessed = true; - return 0; - } - break; - - case WM_SYSCHAR: - if (mwdat->fkeyProcessed) { - mwdat->fkeyProcessed = false; - return 0; - } - break; - - case WM_KEYDOWN: - if (wParam == VK_INSERT && isCtrl) - return DM_WMCopyHandler(hwnd, MessageLogSubclassProc, msg, wParam, lParam); - break; - - case WM_COPY: - return DM_WMCopyHandler(hwnd, MessageLogSubclassProc, msg, wParam, lParam); - - case WM_NCCALCSIZE: - return CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, MessageLogSubclassProc); - - case WM_NCPAINT: - return CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, MessageLogSubclassProc); - - case WM_CONTEXTMENU: - POINT pt; - - if (lParam == 0xFFFFFFFF) { - CHARRANGE sel; - SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); - SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&pt, (LPARAM)sel.cpMax); - ClientToScreen(hwnd, &pt); - } - else { - pt.x = (short)LOWORD(lParam); - pt.y = (short)HIWORD(lParam); - } - - ShowPopupMenu(mwdat, IDC_LOG, hwnd, pt); - return TRUE; - } - - return mir_callNextSubclass(hwnd, MessageLogSubclassProc, msg, wParam, lParam); -} - -static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - BOOL isCtrl, isShift, isAlt; - HWND hwndParent = GetParent(hwnd); - TWindowData *mwdat = (TWindowData*)GetWindowLongPtr(hwndParent, GWLP_USERDATA); - if (mwdat == NULL) - return 0; - - // prevent the rich edit from switching text direction or keyboard layout when - // using hotkeys with ctrl-shift or alt-shift modifiers - if (mwdat->fkeyProcessed && (msg == WM_KEYUP)) { - GetKeyboardState(mwdat->kstate); - if (mwdat->kstate[VK_CONTROL] & 0x80 || mwdat->kstate[VK_SHIFT] & 0x80) - return 0; - - mwdat->fkeyProcessed = false; - return 0; - } - - switch (msg) { - case WM_NCCALCSIZE: - return CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKINPUTAREA, msg, wParam, lParam, MessageEditSubclassProc); - - case WM_NCPAINT: - return CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKINPUTAREA, msg, wParam, lParam, MessageEditSubclassProc); - - case WM_DROPFILES: - SendMessage(hwndParent, WM_DROPFILES, (WPARAM)wParam, (LPARAM)lParam); - return 0; - - case WM_CHAR: - KbdState(mwdat, isShift, isCtrl, isAlt); - - if (PluginConfig.m_bSoundOnTyping && !isAlt && !isCtrl && !(mwdat->pContainer->dwFlags & CNT_NOSOUND) && wParam != VK_ESCAPE && !(wParam == VK_TAB && PluginConfig.m_bAllowTab)) - SkinPlaySound("SoundOnTyping"); - - if (isCtrl && !isAlt) { - switch (wParam) { - case 0x02: // bold - if (mwdat->SendFormat) - SendMessage(hwndParent, WM_COMMAND, MAKELONG(IDC_FONTBOLD, IDC_MESSAGE), 0); - return 0; - case 0x09: - if (mwdat->SendFormat) - SendMessage(hwndParent, WM_COMMAND, MAKELONG(IDC_FONTITALIC, IDC_MESSAGE), 0); - return 0; - case 21: - if (mwdat->SendFormat) - SendMessage(hwndParent, WM_COMMAND, MAKELONG(IDC_FONTUNDERLINE, IDC_MESSAGE), 0); - return 0; - case 0x0b: - SetWindowText(hwnd, _T("")); - return 0; - } - } - break; - - case WM_MOUSEWHEEL: - if (DM_MouseWheelHandler(hwnd, hwndParent, mwdat, wParam, lParam) == 0) - return 0; - break; - - case EM_PASTESPECIAL: - case WM_PASTE: - if (OpenClipboard(hwnd)) { - HANDLE hClip = GetClipboardData(CF_TEXT); - if (hClip) { - if (mir_strlen((char*)hClip) > mwdat->nMax) { - TCHAR szBuffer[512]; - if (M.GetByte("autosplit", 0)) - mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("WARNING: The message you are trying to paste exceeds the message size limit for the active protocol. It will be sent in chunks of max %d characters"), mwdat->nMax - 10); - else - mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("The message you are trying to paste exceeds the message size limit for the active protocol. Only the first %d characters will be sent."), mwdat->nMax); - SendMessage(hwndParent, DM_ACTIVATETOOLTIP, IDC_MESSAGE, (LPARAM)szBuffer); - } - } - else if (hClip = GetClipboardData(CF_BITMAP)) - SendHBitmapAsFile(mwdat, (HBITMAP)hClip); - - CloseClipboard(); - } - break; - - case WM_KEYDOWN: - KbdState(mwdat, isShift, isCtrl, isAlt); - - if (PluginConfig.m_bSoundOnTyping && !isAlt && !(mwdat->pContainer->dwFlags & CNT_NOSOUND) && wParam == VK_DELETE) - SkinPlaySound("SoundOnTyping"); - - if (wParam == VK_INSERT && !isShift && !isCtrl && !isAlt) { - mwdat->fInsertMode = !mwdat->fInsertMode; - SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM)hwnd); - } - if (wParam == VK_CAPITAL || wParam == VK_NUMLOCK) - SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM)hwnd); - - if (wParam == VK_RETURN) { - if (mwdat->fEditNotesActive) - break; - - if (isShift) { - if (PluginConfig.m_bSendOnShiftEnter) { - PostMessage(hwndParent, WM_COMMAND, IDOK, 0); - return 0; - } - else break; - } - if ((isCtrl && !isShift) ^ (0 != PluginConfig.m_bSendOnEnter)) { - PostMessage(hwndParent, WM_COMMAND, IDOK, 0); - return 0; - } - if (PluginConfig.m_bSendOnEnter || PluginConfig.m_bSendOnDblEnter) { - if (isCtrl) - break; - - if (PluginConfig.m_bSendOnDblEnter) { - LONG_PTR lastEnterTime = GetWindowLongPtr(hwnd, GWLP_USERDATA); - if (lastEnterTime + 2 < time(NULL)) { - lastEnterTime = time(NULL); - SetWindowLongPtr(hwnd, GWLP_USERDATA, lastEnterTime); - break; - } - else { - SendMessage(hwnd, WM_KEYDOWN, VK_BACK, 0); - SendMessage(hwnd, WM_KEYUP, VK_BACK, 0); - PostMessage(hwndParent, WM_COMMAND, IDOK, 0); - return 0; - } - } - PostMessage(hwndParent, WM_COMMAND, IDOK, 0); - return 0; - } - else break; - } - else SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); - - if (isCtrl && !isAlt && !isShift) { - if (!isShift && (wParam == VK_UP || wParam == VK_DOWN)) { // input history scrolling (ctrl-up / down) - SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); - if (mwdat) - mwdat->cache->inputHistoryEvent(wParam); - return 0; - } - } - 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; - - SetWindowLongPtr(hwnd, GWLP_USERDATA, 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(mwdat, 0, 0); - return 0; - } - else if (wParam == VK_DOWN) - wp = MAKEWPARAM(SB_LINEDOWN, 0); - - if (mwdat->hwndIEView == 0 && mwdat->hwndHPP == 0) - SendDlgItemMessage(hwndParent, IDC_LOG, WM_VSCROLL, wp, 0); - else - SendMessage(mwdat->hwndIWebBrowserControl, WM_VSCROLL, wp, 0); - return 0; - } - } - if (wParam == VK_RETURN) - break; - - case WM_SYSKEYDOWN: - mwdat->fkeyProcessed = false; - if (ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_MESSAGE)) { - mwdat->fkeyProcessed = true; - return 0; - } - break; - - case WM_SYSKEYUP: - if (wParam == VK_MENU) { - ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_MESSAGE); - return 0; - } - break; - - case WM_SYSCHAR: - if (mwdat->fkeyProcessed) { - mwdat->fkeyProcessed = false; - return 0; - } - - KbdState(mwdat, isShift, isCtrl, isAlt); - if ((wParam >= '0' && wParam <= '9') && isAlt) { // ALT-1 -> ALT-0 direct tab selection - BYTE bChar = (BYTE)wParam; - int iIndex; - - if (bChar == '0') - iIndex = 10; - else - iIndex = bChar - (BYTE)'0'; - SendMessage(mwdat->pContainer->hwnd, DM_SELECTTAB, DM_SELECT_BY_INDEX, (LPARAM)iIndex); - return 0; - } - break; - - case WM_INPUTLANGCHANGE: - if (PluginConfig.m_bAutoLocaleSupport && GetFocus() == hwnd && mwdat->pContainer->hwndActive == hwndParent && GetForegroundWindow() == mwdat->pContainer->hwnd && GetActiveWindow() == mwdat->pContainer->hwnd) { - DM_SaveLocale(mwdat, wParam, lParam); - SendMessage(hwnd, EM_SETLANGOPTIONS, 0, (LPARAM)SendMessage(hwnd, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD); - return 1; - } - break; - - case WM_ERASEBKGND: - return(CSkin::m_skinEnabled ? 0 : 1); - - // sent by smileyadd when the smiley selection window dies - // just grab the focus :) - case WM_USER + 100: - SetFocus(hwnd); - break; - - case WM_CONTEXTMENU: - POINT pt; - if (lParam == 0xFFFFFFFF) { - CHARRANGE sel; - SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); - SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&pt, (LPARAM)sel.cpMax); - ClientToScreen(hwnd, &pt); - } - else { - pt.x = (short)LOWORD(lParam); - pt.y = (short)HIWORD(lParam); - } - - ShowPopupMenu(mwdat, IDC_MESSAGE, hwnd, pt); - return TRUE; - } - return mir_callNextSubclass(hwnd, MessageEditSubclassProc, msg, wParam, lParam); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// subclasses the avatar display controls, needed for skinning and to prevent -// it from flickering during resize/move operations. - -static LRESULT CALLBACK AvatarSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_ERASEBKGND: - return TRUE; - - case WM_UPDATEUISTATE: - return TRUE; - - case WM_NOTIFY: - ProcessAvatarChange(hwnd, lParam); - break; - } - return mir_callNextSubclass(hwnd, AvatarSubclassProc, msg, wParam, lParam); -} - -LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - RECT rc; - HWND hwndParent = GetParent(hwnd); - TWindowData *dat = (TWindowData*)GetWindowLongPtr(hwndParent, GWLP_USERDATA); - - switch (msg) { - case WM_NCHITTEST: - return HTCLIENT; - - case WM_SETCURSOR: - GetClientRect(hwnd, &rc); - SetCursor(rc.right > rc.bottom ? PluginConfig.hCurSplitNS : PluginConfig.hCurSplitWE); - return TRUE; - - case WM_LBUTTONDOWN: - if (hwnd == GetDlgItem(hwndParent, IDC_SPLITTER) || hwnd == GetDlgItem(hwndParent, IDC_SPLITTERY)) { - if (dat) { - GetClientRect(hwnd, &rc); - dat->savedSplitter = rc.right > rc.bottom ? (short)HIWORD(GetMessagePos()) + rc.bottom / 2 : (short)LOWORD(GetMessagePos()) + rc.right / 2; - if (dat->bType == SESSIONTYPE_IM) - dat->savedSplitY = dat->splitterY; - else - dat->savedSplitY = dat->si->iSplitterY; - - dat->savedDynaSplit = dat->dynaSplitter; - } - } - SetCapture(hwnd); - return 0; - - case WM_MOUSEMOVE: - if (GetCapture() == hwnd) { - GetClientRect(hwnd, &rc); - SendMessage(hwndParent, DM_SPLITTERMOVED, rc.right > rc.bottom ? (short)HIWORD(GetMessagePos()) + rc.bottom / 2 : (short)LOWORD(GetMessagePos()) + rc.right / 2, (LPARAM)hwnd); - } - return 0; - - case WM_ERASEBKGND: - return 1; - - case WM_PAINT: - GetClientRect(hwnd, &rc); - { - PAINTSTRUCT ps; - HDC dc = BeginPaint(hwnd, &ps); - - if (dat && CSkin::m_skinEnabled) - CSkin::SkinDrawBG(hwnd, dat->pContainer->hwnd, dat->pContainer, &rc, dc); - else if (M.isAero() || M.isVSThemed()) { - if (GetDlgCtrlID(hwnd) == IDC_PANELSPLITTER) { - EndPaint(hwnd, &ps); - return 0; - } - CSkin::FillBack(dc, &rc); - } - else CSkin::FillBack(dc, &rc); - - EndPaint(hwnd, &ps); - } - return 0; - - case WM_LBUTTONUP: - HWND hwndCapture = GetCapture(); - - ReleaseCapture(); - DM_ScrollToBottom(dat, 0, 1); - if (dat && dat->bType == SESSIONTYPE_IM && hwnd == GetDlgItem(hwndParent, IDC_PANELSPLITTER)) { - SendMessage(hwndParent, WM_SIZE, 0, 0); - RedrawWindow(hwndParent, NULL, NULL, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW); - } - else if ((dat && dat->bType == SESSIONTYPE_IM && hwnd == GetDlgItem(hwndParent, IDC_SPLITTER)) || - (dat && dat->bType == SESSIONTYPE_CHAT && hwnd == GetDlgItem(hwndParent, IDC_SPLITTERY))) { - POINT pt; - int selection; - HMENU hMenu = GetSubMenu(dat->pContainer->hMenuContext, 12); - LONG messagePos = GetMessagePos(); - - GetClientRect(hwnd, &rc); - if (hwndCapture != hwnd || dat->savedSplitter == (rc.right > rc.bottom ? (short) HIWORD(messagePos) + rc.bottom / 2 : (short) LOWORD(messagePos) + rc.right / 2)) - break; - GetCursorPos(&pt); - - if (dat->bIsAutosizingInput) - selection = ID_SPLITTERCONTEXT_SETPOSITIONFORTHISSESSION; - else - selection = TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndParent, NULL); - - switch (selection) { - case ID_SPLITTERCONTEXT_SAVEFORTHISCONTACTONLY: - dat->dwFlagsEx |= MWF_SHOW_SPLITTEROVERRIDE; - db_set_b(dat->hContact, SRMSGMOD_T, "splitoverride", 1); - if (dat->bType == SESSIONTYPE_IM) - SaveSplitter(dat); - break; - - case ID_SPLITTERCONTEXT_SETPOSITIONFORTHISSESSION: - if (dat->bIsAutosizingInput) { - GetWindowRect(GetDlgItem(dat->hwnd, IDC_MESSAGE), &rc); - dat->iInputAreaHeight = 0; - } - break; - - case ID_SPLITTERCONTEXT_SAVEGLOBALFORALLSESSIONS: - { - BYTE bSync = M.GetByte(CHAT_MODULE, "SyncSplitter", 0); - DWORD dwOff_IM = 0, dwOff_CHAT = 0; - - dwOff_CHAT = -(2 + (PluginConfig.m_DPIscaleY > 1.0 ? 1 : 0)); - dwOff_IM = 2 + (PluginConfig.m_DPIscaleY > 1.0 ? 1 : 0); - - RECT rcWin; - GetWindowRect(hwndParent, &rcWin); - - PluginConfig.lastSPlitterPos.pSrcDat = dat; - PluginConfig.lastSPlitterPos.pSrcContainer = dat->pContainer; - PluginConfig.lastSPlitterPos.lParam = rc.bottom; - PluginConfig.lastSPlitterPos.pos = rcWin.bottom - HIWORD(messagePos); - PluginConfig.lastSPlitterPos.pos_chat = rcWin.bottom - (short)HIWORD(messagePos) + rc.bottom / 2; - PluginConfig.lastSPlitterPos.off_chat = dwOff_CHAT; - PluginConfig.lastSPlitterPos.off_im = dwOff_IM; - PluginConfig.lastSPlitterPos.bSync = bSync; - SendMessage(dat->hwnd, DM_SPLITTERGLOBALEVENT, 0, 0); - M.BroadcastMessage(DM_SPLITTERGLOBALEVENT, 0, 0); - } - break; - - default: - dat->splitterY = dat->savedSplitY; - dat->dynaSplitter = dat->savedDynaSplit; - DM_RecalcPictureSize(dat); - if (dat->bType == SESSIONTYPE_CHAT) { - SESSION_INFO *si = dat->si; - si->iSplitterY = dat->savedSplitY; - dat->splitterY = si->iSplitterY + DPISCALEY_S(22); - } - CSkin::UpdateToolbarBG(dat); - SendMessage(hwndParent, WM_SIZE, 0, 0); - DM_ScrollToBottom(dat, 0, 1); - break; - } - } - return 0; - } - return mir_callNextSubclass(hwnd, SplitterSubclassProc, msg, wParam, lParam); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// resizer proc for the "new" layout. - -static int MessageDialogResize(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL * urc) -{ - TWindowData *dat = (TWindowData*)lParam; - RECT rc, rcButton; - static int uinWidth, msgTop = 0, msgBottom = 0; - - int showToolbar = dat->pContainer->dwFlags & CNT_HIDETOOLBAR ? 0 : 1; - BOOL bBottomToolbar = dat->pContainer->dwFlags & CNT_BOTTOMTOOLBAR ? 1 : 0; - static LONG rcLogBottom; - - int panelHeight = dat->Panel->getHeight() + 1; - int s_offset = 0; - bool bInfoPanel = dat->Panel->isActive(); - bool fErrorState = (dat->dwFlags & MWF_ERRORSTATE) ? true : false; - - GetClientRect(GetDlgItem(hwndDlg, IDC_LOG), &rc); - GetClientRect(GetDlgItem(hwndDlg, IDC_PROTOCOL), &rcButton); - - if (dat->panelStatusCX == 0) - dat->panelStatusCX = 80; - - s_offset = 1; - - switch (urc->wId) { - case IDC_PANELSPLITTER: - urc->rcItem.bottom = panelHeight; - urc->rcItem.top = panelHeight - 2; - return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP; - - case IDC_LOG: - if (dat->dwFlags & MWF_ERRORSTATE) - urc->rcItem.bottom -= ERRORPANEL_HEIGHT; - if (dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED || dat->bNotOnList) - urc->rcItem.bottom -= 20; - if (dat->sendMode & SMODE_MULTIPLE) - urc->rcItem.right -= (dat->multiSplitterX + 3); - urc->rcItem.bottom -= dat->splitterY - dat->originalSplitterY; - if (!showToolbar||bBottomToolbar) - urc->rcItem.bottom += 21; - if (bInfoPanel) - urc->rcItem.top += panelHeight; - urc->rcItem.bottom += 3; - 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; - } - } - rcLogBottom = urc->rcItem.bottom; - return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; - - case IDC_CONTACTPIC: - GetClientRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &rc); - urc->rcItem.top -= dat->splitterY - dat->originalSplitterY; - urc->rcItem.left = urc->rcItem.right - (dat->pic.cx + 2); - if ((urc->rcItem.bottom - urc->rcItem.top) < (dat->pic.cy/* + 2*/) && dat->bShowAvatar) { - urc->rcItem.top = urc->rcItem.bottom - dat->pic.cy; - dat->bUseOffset = true; - } - else dat->bUseOffset = false; - - if (showToolbar && bBottomToolbar && (PluginConfig.m_bAlwaysFullToolbarWidth || ((dat->pic.cy - DPISCALEY_S(6)) < rc.bottom))) { - urc->rcItem.bottom -= DPISCALEY_S(22); - if (dat->bIsAutosizingInput) { - urc->rcItem.left--; - urc->rcItem.top--; - } - } - - if (dat->hwndContactPic) //if Panel control was created? - SetWindowPos(dat->hwndContactPic, HWND_TOP, 1, ((urc->rcItem.bottom - urc->rcItem.top) - (dat->pic.cy)) / 2 + 1, //resizes it - dat->pic.cx - 2, dat->pic.cy - 2, SWP_SHOWWINDOW); - - return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; - - case IDC_SPLITTER: - urc->rcItem.right = urc->dlgNewSize.cx; - urc->rcItem.top -= dat->splitterY - dat->originalSplitterY; - urc->rcItem.bottom = urc->rcItem.top + 2; - OffsetRect(&urc->rcItem, 0, 1); - urc->rcItem.left = 0; - - if (dat->bUseOffset) - urc->rcItem.right -= (dat->pic.cx); // + DPISCALEX(2)); - return RD_ANCHORX_CUSTOM | RD_ANCHORY_BOTTOM; - - case IDC_MESSAGE: - urc->rcItem.right = urc->dlgNewSize.cx; - if (dat->bShowAvatar) - urc->rcItem.right -= dat->pic.cx + 2; - urc->rcItem.top -= dat->splitterY - dat->originalSplitterY; - if (bBottomToolbar&&showToolbar) - urc->rcItem.bottom -= DPISCALEY_S(22); - - if (dat->bIsAutosizingInput) - urc->rcItem.top -= DPISCALEY_S(1); - - msgTop = urc->rcItem.top; - msgBottom = urc->rcItem.bottom; - 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_BOTTOM; - - case IDC_MULTISPLITTER: - if (bInfoPanel) - urc->rcItem.top += panelHeight; - urc->rcItem.left -= dat->multiSplitterX; - urc->rcItem.right -= dat->multiSplitterX; - urc->rcItem.bottom = rcLogBottom; - return RD_ANCHORX_RIGHT | RD_ANCHORY_HEIGHT; - - case IDC_LOGFROZENTEXT: - urc->rcItem.right = urc->dlgNewSize.cx - 50; - urc->rcItem.bottom = msgTop - (bBottomToolbar ? 0 : 28); - urc->rcItem.top = msgTop - 16 - (bBottomToolbar ? 0 : 28); - if (!showToolbar && !bBottomToolbar) { - urc->rcItem.bottom += 21; - urc->rcItem.top += 21; - } - return RD_ANCHORX_CUSTOM | RD_ANCHORY_BOTTOM; - - case IDC_ADD: - urc->rcItem.bottom = msgTop - (bBottomToolbar ? 0 : 28); - urc->rcItem.top = msgTop - 18 - (bBottomToolbar ? 0 : 28); - urc->rcItem.right = urc->dlgNewSize.cx - 28; - urc->rcItem.left = urc->rcItem.right - 20; - if (!showToolbar && !bBottomToolbar) { - urc->rcItem.bottom += 21; - urc->rcItem.top += 21; - } - return RD_ANCHORX_CUSTOM | RD_ANCHORY_BOTTOM; - - case IDC_CANCELADD: - urc->rcItem.bottom = msgTop - (bBottomToolbar ? 0 : 28); - urc->rcItem.top = msgTop - 18 - (bBottomToolbar ? 0 : 28); - urc->rcItem.right = urc->dlgNewSize.cx - 4; - urc->rcItem.left = urc->rcItem.right - 20; - if (!showToolbar && !bBottomToolbar) { - urc->rcItem.bottom += 21; - urc->rcItem.top += 21; - } - return RD_ANCHORX_CUSTOM | RD_ANCHORY_BOTTOM; - - case IDC_TOGGLESIDEBAR: - return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; - - case IDC_RETRY: - case IDC_CANCELSEND: - case IDC_MSGSENDLATER: - if (fErrorState) { - urc->rcItem.bottom = msgTop - 5 - (bBottomToolbar ? 0 : 28) - ((dat->bNotOnList || dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED) ? 20 : 0); - urc->rcItem.top = msgTop - 25 - (bBottomToolbar ? 0 : 28) - ((dat->bNotOnList || dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED) ? 20 : 0); - } - if (!showToolbar && !bBottomToolbar) { - urc->rcItem.bottom += 21; - urc->rcItem.top += 21; - } - return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM; - - case IDC_STATICTEXT: - case IDC_STATICERRORICON: - if (fErrorState) { - urc->rcItem.bottom = msgTop - 28 - (bBottomToolbar ? 0 : 28) - ((dat->bNotOnList || dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED) ? 20 : 0); - urc->rcItem.top = msgTop - 45 - (bBottomToolbar ? 0 : 28) - ((dat->bNotOnList || dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED) ? 20 : 0); - } - if (!showToolbar && !bBottomToolbar) { - urc->rcItem.bottom += 21; - urc->rcItem.top += 21; - } - return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM; - } - return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM; -} - -INT_PTR CALLBACK DlgProcMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - TContainerData *m_pContainer = 0; - TWindowData *dat = (TWindowData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - HWND hwndTab = GetParent(hwndDlg), hwndContainer; - POINT pt, tmp, cur; - RECT rc; - - if (dat == 0) { - if (msg == WM_ACTIVATE || msg == WM_SETFOCUS) - return 0; - hwndContainer = NULL; - } - else { - m_pContainer = dat->pContainer; - hwndContainer = m_pContainer->hwnd; - } - - switch (msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - { - TNewWindowData *newData = (TNewWindowData*)lParam; - - dat = (TWindowData*)mir_calloc(sizeof(TWindowData)); - if (newData->iTabID >= 0) { - dat->pContainer = newData->pContainer; - m_pContainer = dat->pContainer; - hwndContainer = m_pContainer->hwnd; - } - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); - - if (Utils::rtf_ctable == 0) - Utils::RTF_CTableInit(); - - dat->dwFlags |= MWF_INITMODE; - dat->bType = SESSIONTYPE_IM; - dat->fInsertMode = FALSE; - dat->fLimitedUpdate = false; - dat->Panel = new CInfoPanel(dat); - - newData->item.lParam = (LPARAM)hwndDlg; - TabCtrl_SetItem(hwndTab, newData->iTabID, &newData->item); - dat->iTabID = newData->iTabID; - dat->hwnd = hwndDlg; - - DM_ThemeChanged(dat); - - pszIDCSAVE_close = TranslateT("Close session"); - pszIDCSAVE_save = TranslateT("Save and close session"); - - dat->hContact = newData->hContact; - dat->cache = CContactCache::getContactCache(dat->hContact); - dat->cache->updateState(); - dat->cache->setWindowData(hwndDlg, dat); - M.AddWindow(hwndDlg, dat->hContact); - BroadCastContainer(m_pContainer, DM_REFRESHTABINDEX, 0, 0); - dat->pWnd = 0; - dat->sbCustom = 0; - CProxyWindow::add(dat); - dat->szProto = const_cast<char *>(dat->cache->getProto()); - dat->bIsMeta = dat->cache->isMeta(); - if (dat->bIsMeta) - dat->cache->updateMeta(); - - dat->cache->updateUIN(); - - if (dat->hContact && dat->szProto != NULL) { - dat->wStatus = db_get_w(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE); - _tcsncpy_s(dat->szStatus, pcli->pfnGetStatusModeDescription(dat->szProto == NULL ? ID_STATUS_OFFLINE : dat->wStatus, 0), _TRUNCATE); - } - else dat->wStatus = ID_STATUS_OFFLINE; - - for (int i = 0; i < SIZEOF(btnControls); i++) - CustomizeButton(GetDlgItem(hwndDlg, btnControls[i])); - - GetMYUIN(dat); - GetClientIcon(dat); - - CustomizeButton(CreateWindowEx(0, _T("MButtonClass"), _T(""), WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 0, 6, DPISCALEY_S(20), - hwndDlg, (HMENU)IDC_TOGGLESIDEBAR, g_hInst, NULL)); - dat->hwndPanelPicParent = CreateWindowEx(WS_EX_TOPMOST, _T("Static"), _T(""), SS_OWNERDRAW | WS_VISIBLE | WS_CHILD, 1, 1, 1, 1, hwndDlg, (HMENU)6000, NULL, NULL); - mir_subclassWindow(dat->hwndPanelPicParent, CInfoPanel::avatarParentSubclass); - - dat->bShowUIElements = (m_pContainer->dwFlags & CNT_HIDETOOLBAR) == 0; - dat->sendMode |= M.GetByte(dat->hContact, "forceansi", 0) ? SMODE_FORCEANSI : 0; - dat->sendMode |= dat->hContact == 0 ? SMODE_MULTIPLE : 0; - dat->sendMode |= M.GetByte(dat->hContact, "no_ack", 0) ? SMODE_NOACK : 0; - - dat->hQueuedEvents = (MEVENT*)mir_calloc(sizeof(MEVENT)* EVENT_QUEUE_SIZE); - dat->iEventQueueSize = EVENT_QUEUE_SIZE; - dat->iCurrentQueueError = -1; - - // message history limit - // hHistoryEvents holds up to n event handles - dat->maxHistory = M.GetDword(dat->hContact, "maxhist", M.GetDword("maxhist", 0)); - dat->curHistory = 0; - if (dat->maxHistory) - dat->hHistoryEvents = (MEVENT*)mir_alloc(dat->maxHistory * sizeof(MEVENT)); - else - dat->hHistoryEvents = NULL; - - if (dat->bIsMeta) - SendMessage(hwndDlg, DM_UPDATEMETACONTACTINFO, 0, 0); - else - SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0); - dat->bTabFlash = FALSE; - dat->mayFlashTab = FALSE; - GetMyNick(dat); - - dat->multiSplitterX = (int)M.GetDword(SRMSGMOD, "multisplit", 150); - dat->nTypeMode = PROTOTYPE_SELFTYPING_OFF; - SetTimer(hwndDlg, TIMERID_TYPE, 1000, NULL); - dat->iLastEventType = 0xffffffff; - - // load log option flags... - dat->dwFlags = dat->pContainer->theme.dwFlags; - - // consider per-contact message setting overrides - if (dat->hContact && M.GetDword(dat->hContact, "mwmask", 0)) - LoadLocalFlags(dat); - - DM_InitTip(dat); - dat->Panel->getVisibility(); - - dat->dwFlagsEx |= M.GetByte(dat->hContact, "splitoverride", 0) ? MWF_SHOW_SPLITTEROVERRIDE : 0; - dat->bIsAutosizingInput = IsAutoSplitEnabled(dat); - dat->iInputAreaHeight = -1; - SetMessageLog(dat); - if (dat->hContact) { - dat->codePage = M.GetDword(dat->hContact, "ANSIcodepage", CP_ACP); - dat->Panel->loadHeight(); - } - - dat->bShowAvatar = GetAvatarVisibility(hwndDlg, dat); - - Utils::showDlgControl(hwndDlg, IDC_MULTISPLITTER, SW_HIDE); - - GetWindowRect(GetDlgItem(hwndDlg, IDC_SPLITTER), &rc); - pt.y = (rc.top + rc.bottom) / 2; - pt.x = 0; - ScreenToClient(hwndDlg, &pt); - dat->originalSplitterY = pt.y; - if (dat->splitterY == -1) - dat->splitterY = dat->originalSplitterY + 60; - - GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &rc); - dat->minEditBoxSize.cx = rc.right - rc.left; - dat->minEditBoxSize.cy = rc.bottom - rc.top; - - BB_InitDlgButtons(dat); - SendMessage(hwndDlg, DM_LOADBUTTONBARICONS, 0, 0); - - BOOL isThemed = TRUE; - if (CSkin::m_skinEnabled && !SkinItems[ID_EXTBKBUTTONSNPRESSED].IGNORED && - !SkinItems[ID_EXTBKBUTTONSPRESSED].IGNORED && !SkinItems[ID_EXTBKBUTTONSMOUSEOVER].IGNORED) - isThemed = FALSE; - - SendDlgItemMessage(hwndDlg, IDC_ADD, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hwndDlg, IDC_CANCELADD, BUTTONSETASFLATBTN, TRUE, 0); - - SendDlgItemMessage(hwndDlg, IDC_TOGGLESIDEBAR, BUTTONSETASFLATBTN, TRUE, 0); - SendDlgItemMessage(hwndDlg, IDC_TOGGLESIDEBAR, BUTTONSETASTHEMEDBTN, isThemed, 0); - SendDlgItemMessage(hwndDlg, IDC_TOGGLESIDEBAR, BUTTONSETCONTAINER, (LPARAM)m_pContainer, 0); - SendDlgItemMessage(hwndDlg, IDC_TOGGLESIDEBAR, BUTTONSETASTOOLBARBUTTON, TRUE, 0); - - TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPENING, 0); - - for (int i = 0; i < SIZEOF(tooltips); i++) - SendDlgItemMessage(hwndDlg, tooltips[i].id, BUTTONADDTOOLTIP, (WPARAM)TranslateTS(tooltips[i].text), BATF_TCHAR); - - SetDlgItemText(hwndDlg, IDC_LOGFROZENTEXT, dat->bNotOnList ? TranslateT("Contact not on list. You may add it...") : - TranslateT("Auto scrolling is disabled (press F12 to enable it)")); - - SendDlgItemMessage(hwndDlg, IDC_SAVE, BUTTONADDTOOLTIP, (WPARAM)pszIDCSAVE_close, BATF_TCHAR); - SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Click for contact menu\nClick dropdown for window settings"), BATF_TCHAR); - - SetDlgItemText(hwndDlg, IDC_RETRY, TranslateT("Retry")); - - UINT _ctrls[] = { IDC_RETRY, IDC_CANCELSEND, IDC_MSGSENDLATER }; - for (int i = 0; i < SIZEOF(_ctrls); i++) { - SendDlgItemMessage(hwndDlg, _ctrls[i], BUTTONSETASPUSHBTN, TRUE, 0); - SendDlgItemMessage(hwndDlg, _ctrls[i], BUTTONSETASFLATBTN, FALSE, 0); - SendDlgItemMessage(hwndDlg, _ctrls[i], BUTTONSETASTHEMEDBTN, TRUE, 0); - } - - SetDlgItemText(hwndDlg, IDC_CANCELSEND, TranslateT("Cancel")); - SetDlgItemText(hwndDlg, IDC_MSGSENDLATER, TranslateT("Send later")); - - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETUNDOLIMIT, 0, 0); - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_KEYEVENTS | ENM_LINK); - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETOLECALLBACK, 0, (LPARAM)&reOleCallback); - - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETEVENTMASK, 0, ENM_REQUESTRESIZE | ENM_MOUSEEVENTS | ENM_SCROLL | ENM_KEYEVENTS | ENM_CHANGE); - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETOLECALLBACK, 0, (LPARAM)&reOleCallback2); - - dat->bActualHistory = M.GetByte(dat->hContact, "ActualHistory", 0); - - /* OnO: higligh lines to their end */ - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETEDITSTYLE, SES_EXTENDBACKCOLOR, SES_EXTENDBACKCOLOR); - - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETLANGOPTIONS, 0, SendDlgItemMessage(hwndDlg, IDC_LOG, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOFONTSIZEADJUST); - - // add us to the tray list (if it exists) - if (PluginConfig.g_hMenuTrayUnread != 0 && dat->hContact != 0 && dat->szProto != NULL) - UpdateTrayMenu(0, dat->wStatus, dat->szProto, dat->szStatus, dat->hContact, FALSE); - - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_AUTOURLDETECT, TRUE, 0); - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXLIMITTEXT, 0, 0x80000000); - - // subclassing stuff - mir_subclassWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), MessageEditSubclassProc); - mir_subclassWindow(GetDlgItem(hwndDlg, IDC_CONTACTPIC), AvatarSubclassProc); - mir_subclassWindow(GetDlgItem(hwndDlg, IDC_SPLITTER), SplitterSubclassProc); - mir_subclassWindow(GetDlgItem(hwndDlg, IDC_MULTISPLITTER), SplitterSubclassProc); - mir_subclassWindow(GetDlgItem(hwndDlg, IDC_PANELSPLITTER), SplitterSubclassProc); - - // load old messages from history (if wanted...) - dat->cache->updateStats(TSessionStats::INIT_TIMER); - if (dat->hContact) { - FindFirstEvent(dat); - dat->nMax = dat->cache->getMaxMessageLength(); - } - LoadContactAvatar(dat); - SendMessage(hwndDlg, DM_OPTIONSAPPLIED, 0, 0); - LoadOwnAvatar(dat); - - // restore saved msg if any... - if (dat->hContact) { - ptrT tszSavedMsg(db_get_tsa(dat->hContact, SRMSGMOD, "SavedMsg")); - if (tszSavedMsg != 0) { - SETTEXTEX stx = { ST_DEFAULT, 1200 }; - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETTEXTEX, (WPARAM)&stx, tszSavedMsg); - SendQueue::UpdateSaveAndSendButton(dat); - if (m_pContainer->hwndActive == hwndDlg) - UpdateReadChars(dat); - } - } - if (newData->szInitialText) { - if (newData->isWchar) - SetDlgItemTextW(hwndDlg, IDC_MESSAGE, (TCHAR*)newData->szInitialText); - else - SetDlgItemTextA(hwndDlg, IDC_MESSAGE, newData->szInitialText); - int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)); - PostMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), EM_SETSEL, len, len); - if (len) - EnableSendButton(dat, TRUE); - } - - for (MEVENT hdbEvent = db_event_last(dat->hContact); hdbEvent; hdbEvent = db_event_prev(dat->hContact, hdbEvent)) { - DBEVENTINFO dbei = { sizeof(dbei) }; - db_event_get(hdbEvent, &dbei); - if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) { - dat->lastMessage = dbei.timestamp; - DM_UpdateLastMessage(dat); - break; - } - } - - SendMessage(hwndContainer, DM_QUERYCLIENTAREA, 0, (LPARAM)&rc); - - WNDCLASS wndClass = { 0 }; - GetClassInfo(g_hInst, _T("RICHEDIT50W"), &wndClass); - mir_subclassWindowFull(GetDlgItem(hwndDlg, IDC_LOG), MessageLogSubclassProc, wndClass.lpfnWndProc); - - SetWindowPos(hwndDlg, 0, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), newData->iActivate ? 0 : SWP_NOZORDER | SWP_NOACTIVATE); - LoadSplitter(dat); - ShowPicture(dat, TRUE); - - if (m_pContainer->dwFlags & CNT_CREATE_MINIMIZED || !newData->iActivate || m_pContainer->dwFlags & CNT_DEFERREDTABSELECT) { - dat->iFlashIcon = PluginConfig.g_IconMsgEvent; - SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL); - dat->mayFlashTab = true; - - DBEVENTINFO dbei = { 0 }; - dbei.eventType = EVENTTYPE_MESSAGE; - FlashOnClist(hwndDlg, dat, dat->hDbEventFirst, &dbei); - - SendMessage(hwndContainer, DM_SETICON, (WPARAM)dat, (LPARAM)LoadSkinnedIcon(SKINICON_EVENT_MESSAGE)); - m_pContainer->dwFlags |= CNT_NEED_UPDATETITLE; - dat->dwFlags |= MWF_NEEDCHECKSIZE | MWF_WASBACKGROUNDCREATE | MWF_DEFERREDSCROLL; - } - - if (newData->iActivate) { - m_pContainer->hwndActive = hwndDlg; - ShowWindow(hwndDlg, SW_SHOW); - SetActiveWindow(hwndDlg); - SetForegroundWindow(hwndDlg); - } - else if (m_pContainer->dwFlags & CNT_CREATE_MINIMIZED) { - dat->dwFlags |= MWF_DEFERREDSCROLL; - ShowWindow(hwndDlg, SW_SHOWNOACTIVATE); - m_pContainer->hwndActive = hwndDlg; - m_pContainer->dwFlags |= CNT_DEFERREDCONFIGURE; - } - PostMessage(hwndContainer, DM_UPDATETITLE, dat->hContact, 0); - - DM_RecalcPictureSize(dat); - dat->dwLastActivity = GetTickCount() - 1000; - m_pContainer->dwLastActivity = dat->dwLastActivity; - - if (dat->hwndHPP) - mir_subclassWindow(dat->hwndHPP, HPPKFSubclassProc); - - dat->dwFlags &= ~MWF_INITMODE; - TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPEN, 0); - - // show a popup if wanted... - if (newData->bWantPopup) { - DBEVENTINFO dbei = { sizeof(dbei) }; - newData->bWantPopup = FALSE; - db_event_get(newData->hdbEvent, &dbei); - tabSRMM_ShowPopup(dat->hContact, newData->hdbEvent, dbei.eventType, 0, 0, hwndDlg, dat->cache->getActiveProto()); - } - if (m_pContainer->dwFlags & CNT_CREATE_MINIMIZED) { - m_pContainer->dwFlags &= ~CNT_CREATE_MINIMIZED; - m_pContainer->hwndActive = hwndDlg; - return FALSE; - } - return newData->iActivate != 0; - } - - case WM_ERASEBKGND: - RECT rcClient, rcWindow; - { - HDC hdc = (HDC)wParam; - HDC hdcMem = 0; - HBITMAP hbm, hbmOld; - HANDLE hpb = 0; - - GetClientRect(hwndDlg, &rcClient); - DWORD cx = rcClient.right - rcClient.left; - DWORD cy = rcClient.bottom - rcClient.top; - - if (CMimAPI::m_haveBufferedPaint) { - hpb = CMimAPI::m_pfnBeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB, 0, &hdcMem); - hbm = hbmOld = 0; - } - else { - hdcMem = CreateCompatibleDC(hdc); - hbm = CSkin::CreateAeroCompatibleBitmap(rcClient, hdc); - hbmOld = (HBITMAP)SelectObject(hdcMem, hbm); - } - - bool bAero = M.isAero(); - - if (CSkin::m_skinEnabled) { - UINT item_ids[2] = {ID_EXTBKHISTORY, ID_EXTBKINPUTAREA}; - UINT ctl_ids[2] = {IDC_LOG, IDC_MESSAGE}; - BOOL isEditNotesReason = dat->fEditNotesActive; - BOOL isSendLaterReason = (dat->sendMode & SMODE_SENDLATER); - BOOL isMultipleReason = (dat->sendMode & SMODE_MULTIPLE || dat->sendMode & SMODE_CONTAINER); - - CSkin::SkinDrawBG(hwndDlg, hwndContainer, m_pContainer, &rcClient, hdcMem); - - for (int i=0; i < 2; i++) { - CSkinItem *item = &SkinItems[item_ids[i]]; - if (!item->IGNORED) { - GetWindowRect(GetDlgItem(hwndDlg, ctl_ids[i]), &rcWindow); - pt.x = rcWindow.left; - pt.y = rcWindow.top; - ScreenToClient(hwndDlg, &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; - if (item_ids[i] == ID_EXTBKINPUTAREA && (isMultipleReason || isEditNotesReason || isSendLaterReason)) { - HBRUSH br = CreateSolidBrush(isMultipleReason ? RGB(255, 130, 130) : (isEditNotesReason ? RGB(80, 255, 80) : RGB(80, 80, 255))); - FillRect(hdcMem, &rc, br); - DeleteObject(br); - } - else CSkin::DrawItem(hdcMem, &rc, item); - } - } - } - else { - CSkin::FillBack(hdcMem, &rcClient); - - if (M.isAero()) { - LONG temp = rcClient.bottom; - rcClient.bottom = dat->Panel->isActive() ? dat->Panel->getHeight() + 5 : 5; - FillRect(hdcMem, &rcClient, (HBRUSH)GetStockObject(BLACK_BRUSH)); - rcClient.bottom = temp; - } - } - - // draw the (new) infopanel background. Use the gradient from the statusitem. - GetClientRect(hwndDlg, &rc); - dat->Panel->renderBG(hdcMem, rc, &SkinItems[ID_EXTBKINFOPANELBG], bAero); - - // draw aero related stuff - if (!CSkin::m_skinEnabled) - CSkin::RenderToolbarBG(dat, hdcMem, rcClient); - - // render info panel fields - dat->Panel->renderContent(hdcMem); - - if (hpb) - CSkin::FinalizeBufferedPaint(hpb, &rcClient); - else { - BitBlt(hdc, 0, 0, cx, cy, hdcMem, 0, 0, SRCCOPY); - SelectObject(hdcMem, hbmOld); - DeleteObject(hbm); - DeleteDC(hdcMem); - } - if (!dat->fLimitedUpdate) - SetAeroMargins(dat->pContainer); - } - return 1; - - case WM_NCPAINT: - return 0; - - case WM_PAINT: - // in skinned mode only, draw the background elements for the 2 richedit controls - // this allows border-less textboxes to appear "skinned" and blended with the background - { - PAINTSTRUCT ps; - BeginPaint(hwndDlg, &ps); - EndPaint(hwndDlg, &ps); - } - return 0; - - case WM_SIZE: - if (!IsIconic(hwndDlg)) { - if (dat->ipFieldHeight == 0) - dat->ipFieldHeight = CInfoPanel::m_ipConfig.height2; - - if (dat->pContainer->uChildMinHeight > 0 && HIWORD(lParam) >= dat->pContainer->uChildMinHeight) { - if (dat->splitterY > HIWORD(lParam) - DPISCALEY_S(MINLOGHEIGHT)) { - dat->splitterY = HIWORD(lParam) - DPISCALEY_S(MINLOGHEIGHT); - dat->dynaSplitter = dat->splitterY - DPISCALEY_S(34); - DM_RecalcPictureSize(dat); - } - if (dat->splitterY < DPISCALEY_S(MINSPLITTERY)) - LoadSplitter(dat); - } - - HBITMAP hbm = ((dat->Panel->isActive()) && m_pContainer->avatarMode != 3) ? dat->hOwnPic : (dat->ace ? dat->ace->hbmPic : PluginConfig.g_hbmUnknown); - if (hbm != 0) { - BITMAP bminfo; - GetObject(hbm, sizeof(bminfo), &bminfo); - CalcDynamicAvatarSize(dat, &bminfo); - } - - GetClientRect(hwndDlg, &rc); - - UTILRESIZEDIALOG urd = { sizeof(urd) }; - urd.hInstance = g_hInst; - urd.hwndDlg = hwndDlg; - urd.lParam = (LPARAM)dat; - urd.lpTemplate = MAKEINTRESOURCEA(IDD_MSGSPLITNEW); - urd.pfnResizer = MessageDialogResize; - CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd); - - BB_SetButtonsPos(dat); - - // size info panel fields - if (dat->Panel->isActive()) { - LONG cx = rc.right; - LONG panelHeight = dat->Panel->getHeight(); - - hbm = (m_pContainer->avatarMode == 3) ? dat->hOwnPic : (dat->ace ? dat->ace->hbmPic : PluginConfig.g_hbmUnknown); - double dHeight = 0, dWidth = 0; - Utils::scaleAvatarHeightLimited(hbm, dWidth, dHeight, panelHeight-2); - dat->iPanelAvatarX = (int)dWidth; - dat->iPanelAvatarY = (int)dHeight; - - rc.top = 1; - rc.left = cx - dat->iPanelAvatarX; - rc.bottom = panelHeight - (CSkin::m_bAvatarBorderType ? 2 : 0); - rc.right = cx; - dat->rcPic = rc; - - if (dat->bShowInfoAvatar) { - SetWindowPos(dat->hwndPanelPicParent, HWND_TOP, rc.left - 2, rc.top, rc.right - rc.left, rc.bottom - rc.top + 1, 0); - ShowWindow(dat->hwndPanelPicParent, (dat->iPanelAvatarX == 0) || !dat->Panel->isActive() ? SW_HIDE : SW_SHOW); - } - else { - ShowWindow(dat->hwndPanelPicParent, SW_HIDE); - dat->iPanelAvatarX = dat->iPanelAvatarY = 0; - } - - rc.right = cx - dat->iPanelAvatarX; - rc.left = rc.right - dat->panelStatusCX; - rc.bottom = panelHeight - 3; - rc.top = rc.bottom - dat->ipFieldHeight; - dat->rcStatus = rc; - - rc.left = CInfoPanel::LEFT_OFFSET_LOGO; - rc.right = cx - dat->iPanelAvatarX - (panelHeight < CInfoPanel::DEGRADE_THRESHOLD ? (dat->rcStatus.right - dat->rcStatus.left) + 3 : 0); - rc.bottom = panelHeight - (panelHeight >= CInfoPanel::DEGRADE_THRESHOLD ? dat->ipFieldHeight : 0) - 1; - rc.top = 1; - dat->rcNick = rc; - - rc.left = CInfoPanel::LEFT_OFFSET_LOGO; - rc.right = cx - (dat->iPanelAvatarX + 2) - dat->panelStatusCX; - rc.bottom = panelHeight - 3; - rc.top = rc.bottom - dat->ipFieldHeight; - dat->rcUIN = rc; - - dat->Panel->Invalidate(); - } - - if (GetDlgItem(hwndDlg, IDC_CLIST) != 0) { - RECT rcLog; - GetClientRect(hwndDlg, &rcClient); - GetClientRect(GetDlgItem(hwndDlg, IDC_LOG), &rcLog); - rc.top = 0; - rc.right = rcClient.right; - rc.left = rcClient.right - dat->multiSplitterX; - rc.bottom = rcLog.bottom; - if (dat->Panel->isActive()) - rc.top += (dat->Panel->getHeight() + 1); - MoveWindow(GetDlgItem(hwndDlg, IDC_CLIST), rc.left, rc.top, rc.right - rc.left, rcLog.bottom - rcLog.top, FALSE); - } - - if (dat->hwndIEView || dat->hwndHPP) - ResizeIeView(dat); - - DetermineMinHeight(dat); - } - break; - - case WM_TIMECHANGE: - PostMessage(hwndDlg, DM_OPTIONSAPPLIED, 0, 0); - break; - - case WM_NOTIFY: - if (dat != 0 && ((NMHDR*)lParam)->hwndFrom == dat->hwndTip) { - if (((NMHDR*)lParam)->code == NM_CLICK) - SendMessage(dat->hwndTip, TTM_TRACKACTIVATE, FALSE, 0); - break; - } - - switch (((NMHDR*)lParam)->idFrom) { - case IDC_LOG: - case IDC_MESSAGE: - switch (((NMHDR*)lParam)->code) { - case EN_MSGFILTER: - { - DWORD msg = ((MSGFILTER *) lParam)->msg; - WPARAM wp = ((MSGFILTER *) lParam)->wParam; - LPARAM lp = ((MSGFILTER *) lParam)->lParam; - CHARFORMAT2 cf2; - BOOL isCtrl, isShift, isAlt; - KbdState(dat, isShift, isCtrl, isAlt); - - MSG message; - message.hwnd = hwndDlg; - message.message = msg; - message.lParam = lp; - message.wParam = wp; - - if (msg == WM_SYSKEYUP) { - if (wp == VK_MENU) - if (!dat->fkeyProcessed && !(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000) && !(lp & (1 << 24))) - m_pContainer->MenuBar->autoShow(); - - return _dlgReturn(hwndDlg, 0); - } - - if ((msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) && !(GetKeyState(VK_RMENU) & 0x8000)) { - LRESULT mim_hotkey_check = CallService(MS_HOTKEY_CHECK, (WPARAM)&message, (LPARAM)(TABSRMM_HK_SECTION_IM)); - if (mim_hotkey_check) - dat->fkeyProcessed = true; - - switch (mim_hotkey_check) { - case TABSRMM_HK_SETUSERPREFS: - CallService(MS_TABMSG_SETUSERPREFS, dat->hContact, 0); - return _dlgReturn(hwndDlg, 1); - case TABSRMM_HK_NUDGE: - SendNudge(dat); - return _dlgReturn(hwndDlg, 1); - case TABSRMM_HK_SENDFILE: - CallService(MS_FILE_SENDFILE, dat->hContact, 0); - return _dlgReturn(hwndDlg, 1); - case TABSRMM_HK_QUOTEMSG: - SendMessage(hwndDlg, WM_COMMAND, IDC_QUOTE, 0); - return _dlgReturn(hwndDlg, 1); - case TABSRMM_HK_USERMENU: - SendMessage(hwndDlg, WM_COMMAND, IDC_PROTOCOL, 0); - return _dlgReturn(hwndDlg, 1); - case TABSRMM_HK_USERDETAILS: - SendMessage(hwndDlg, WM_COMMAND, MAKELONG(IDC_NAME, BN_CLICKED), 0); - return _dlgReturn(hwndDlg, 1); - case TABSRMM_HK_EDITNOTES: - PostMessage(hwndDlg, WM_COMMAND, MAKELONG(IDC_PIC, BN_CLICKED), 0); - return _dlgReturn(hwndDlg, 1); - case TABSRMM_HK_TOGGLESENDLATER: - if (sendLater->isAvail()) { - dat->sendMode ^= SMODE_SENDLATER; - SetWindowPos(GetDlgItem(hwndDlg, IDC_MESSAGE), 0, 0, 0, 0, 0, SWP_DRAWFRAME|SWP_FRAMECHANGED|SWP_NOZORDER| - SWP_NOMOVE|SWP_NOSIZE|SWP_NOCOPYBITS); - RedrawWindow(hwndDlg, 0, 0, RDW_INVALIDATE|RDW_ERASE|RDW_UPDATENOW|RDW_ALLCHILDREN); - } - else - CWarning::show(CWarning::WARN_NO_SENDLATER, MB_OK|MB_ICONINFORMATION, TranslateT("Configuration issue|The unattended send feature is disabled. The \\b1 send later\\b0 and \\b1 send to multiple contacts\\b0 features depend on it.\n\nYou must enable it under \\b1Options->Message sessions->Advanced tweaks\\b0. Changing this option requires a restart.")); - return _dlgReturn(hwndDlg, 1); - case TABSRMM_HK_TOGGLERTL: - { - DWORD dwGlobal = M.GetDword("mwflags", MWF_LOG_DEFAULT); - DWORD dwMask = M.GetDword(dat->hContact, "mwmask", 0); - DWORD dwFlags = M.GetDword(dat->hContact, "mwflags", 0); - - dat->dwFlags ^= MWF_LOG_RTL; - if ((dwGlobal & MWF_LOG_RTL) != (dat->dwFlags & MWF_LOG_RTL)) { - dwMask |= MWF_LOG_RTL; - dwFlags |= (dat->dwFlags & MWF_LOG_RTL); - } - else { - dwMask &= ~MWF_LOG_RTL; - dwFlags &= ~MWF_LOG_RTL; - } - if (dwMask) { - db_set_dw(dat->hContact, SRMSGMOD_T, "mwmask", dwMask); - db_set_dw(dat->hContact, SRMSGMOD_T, "mwflags", dwFlags); - } - else { - db_unset(dat->hContact, SRMSGMOD_T, "mwmask"); - db_unset(dat->hContact, SRMSGMOD_T, "mwflags"); - } - SendMessage(hwndDlg, DM_OPTIONSAPPLIED, 0, 0); - SendMessage(hwndDlg, DM_DEFERREDREMAKELOG, (WPARAM)hwndDlg, 0); - } - return _dlgReturn(hwndDlg, 1); - - case TABSRMM_HK_TOGGLEMULTISEND: - dat->sendMode ^= SMODE_MULTIPLE; - if (dat->sendMode & SMODE_MULTIPLE) - DM_CreateClist(dat); - else if (IsWindow(GetDlgItem(hwndDlg, IDC_CLIST))) - DestroyWindow(GetDlgItem(hwndDlg, IDC_CLIST)); - - HWND hwndEdit = GetDlgItem(hwndDlg, IDC_MESSAGE); - SetWindowPos(hwndEdit, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE); - SendMessage(hwndDlg, WM_SIZE, 0, 0); - RedrawWindow(hwndEdit, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW | RDW_ERASE); - DM_ScrollToBottom(dat, 0, 0); - Utils::showDlgControl(hwndDlg, IDC_MULTISPLITTER, (dat->sendMode & SMODE_MULTIPLE) ? SW_SHOW : SW_HIDE); - Utils::showDlgControl(hwndDlg, IDC_CLIST, (dat->sendMode & SMODE_MULTIPLE) ? SW_SHOW : SW_HIDE); - if (dat->sendMode & SMODE_MULTIPLE) - SetFocus(GetDlgItem(hwndDlg, IDC_CLIST)); - else - SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); - RedrawWindow(hwndDlg, 0, 0, RDW_INVALIDATE|RDW_ERASE|RDW_UPDATENOW|RDW_ALLCHILDREN); - return _dlgReturn(hwndDlg, 1); - } - if (DM_GenericHotkeysCheck(&message, dat)) { - dat->fkeyProcessed = true; - return _dlgReturn(hwndDlg, 1); - } - } - if (wp == VK_BROWSER_BACK || wp == VK_BROWSER_FORWARD) - return 1; - - if (msg == WM_CHAR) { - if (isCtrl && !isShift && !isAlt) { - switch (wp) { - case 23: // ctrl - w - PostMessage(hwndDlg, WM_CLOSE, 1, 0); - break; - case 19: - PostMessage(hwndDlg, WM_COMMAND, IDC_SENDMENU, IDC_SENDMENU); - break; - case 16: - PostMessage(hwndDlg, WM_COMMAND, IDC_PROTOMENU, IDC_PROTOMENU); - break; - case 20: - PostMessage(hwndDlg, WM_COMMAND, IDC_TOGGLETOOLBAR, 1); - break; - } - return 1; - } - } - if (msg == WM_KEYDOWN) { - if ((wp == VK_INSERT && isShift && !isCtrl) || (wp == 'V' && isCtrl && !isShift && !isAlt)) { - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_PASTESPECIAL, CF_UNICODETEXT, 0); - _clrMsgFilter(lParam); - return _dlgReturn(hwndDlg, 1); - } - if (isCtrl && isShift) { - if (wp == 0x9) { // ctrl-shift tab - SendMessage(hwndDlg, DM_SELECTTAB, DM_SELECT_PREV, 0); - _clrMsgFilter(lParam); - return _dlgReturn(hwndDlg, 1); - } - } - if (isCtrl && !isShift && !isAlt) { - if (wp == VK_TAB) { - SendMessage(hwndDlg, DM_SELECTTAB, DM_SELECT_NEXT, 0); - _clrMsgFilter(lParam); - return _dlgReturn(hwndDlg, 1); - } - if (wp == VK_F4) { - PostMessage(hwndDlg, WM_CLOSE, 1, 0); - return _dlgReturn(hwndDlg, 1); - } - if (wp == VK_PRIOR) { - SendMessage(hwndDlg, DM_SELECTTAB, DM_SELECT_PREV, 0); - return _dlgReturn(hwndDlg, 1); - } - if (wp == VK_NEXT) { - SendMessage(hwndDlg, DM_SELECTTAB, DM_SELECT_NEXT, 0); - return _dlgReturn(hwndDlg, 1); - } - } - } - if (msg == WM_SYSKEYDOWN && isAlt) { - if (wp == 0x52) { - SendMessage(hwndDlg, DM_QUERYPENDING, DM_QUERY_MOSTRECENT, 0); - return _dlgReturn(hwndDlg, 1); - } - if (wp == VK_MULTIPLY) { - SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); - return _dlgReturn(hwndDlg, 1); - } - if (wp == VK_DIVIDE) { - SetFocus(GetDlgItem(hwndDlg, IDC_LOG)); - return _dlgReturn(hwndDlg, 1); - } - if (wp == VK_ADD) { - SendMessage(hwndContainer, DM_SELECTTAB, DM_SELECT_NEXT, 0); - return _dlgReturn(hwndDlg, 1); - } - if (wp == VK_SUBTRACT) { - SendMessage(hwndContainer, DM_SELECTTAB, DM_SELECT_PREV, 0); - return _dlgReturn(hwndDlg, 1); - } - } - - if (msg == WM_KEYDOWN && wp == VK_F12) { - if (isShift || isCtrl || isAlt) - return _dlgReturn(hwndDlg, 1); - if (dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED) - SendMessage(hwndDlg, DM_REPLAYQUEUE, 0, 0); - dat->dwFlagsEx ^= MWF_SHOW_SCROLLINGDISABLED; - Utils::showDlgControl(hwndDlg, IDC_LOGFROZENTEXT, (dat->bNotOnList || dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED) ? SW_SHOW : SW_HIDE); - if (!(dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED)) - SetDlgItemText(hwndDlg, IDC_LOGFROZENTEXT, TranslateT("Contact not on list. You may add it...")); - else - SetDlgItemText(hwndDlg, IDC_LOGFROZENTEXT, TranslateT("Auto scrolling is disabled (press F12 to enable it)")); - SendMessage(hwndDlg, WM_SIZE, 0, 0); - DM_ScrollToBottom(dat, 1, 1); - return _dlgReturn(hwndDlg, 1); - } - - // tabulation mod - if (msg == WM_KEYDOWN && wp == VK_TAB) { - if (PluginConfig.m_bAllowTab) { - if (((NMHDR*)lParam)->idFrom == IDC_MESSAGE) - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_REPLACESEL, FALSE, (LPARAM)"\t"); - _clrMsgFilter(lParam); - if (((NMHDR*)lParam)->idFrom != IDC_MESSAGE) - SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); - return _dlgReturn(hwndDlg, 1); - } - else { - if (((NMHDR*)lParam)->idFrom == IDC_MESSAGE) { - if (GetSendButtonState(hwndDlg) != PBS_DISABLED && !(dat->pContainer->dwFlags & CNT_HIDETOOLBAR)) - SetFocus(GetDlgItem(hwndDlg, IDOK)); - else - SetFocus(GetDlgItem(hwndDlg, IDC_LOG)); - return _dlgReturn(hwndDlg, 1); - } - if (((NMHDR*)lParam)->idFrom == IDC_LOG) { - SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); - return _dlgReturn(hwndDlg, 1); - } - } - return _dlgReturn(hwndDlg, 0); - } - - if (msg == WM_MOUSEWHEEL && (((NMHDR*)lParam)->idFrom == IDC_LOG || ((NMHDR*)lParam)->idFrom == IDC_MESSAGE)) { - GetCursorPos(&pt); - GetWindowRect(GetDlgItem(hwndDlg, IDC_LOG), &rc); - if (PtInRect(&rc, pt)) { - short wDirection = (short)HIWORD(wp); - if (LOWORD(wp) & MK_SHIFT) { - if (wDirection < 0) - SendDlgItemMessage(hwndDlg, IDC_LOG, WM_VSCROLL, MAKEWPARAM(SB_PAGEDOWN, 0), 0); - else if (wDirection > 0) - SendDlgItemMessage(hwndDlg, IDC_LOG, WM_VSCROLL, MAKEWPARAM(SB_PAGEUP, 0), 0); - return 0; - } - return 0; - } - return 1; - } - - if (msg == WM_CHAR && wp == 'c') { - if (isCtrl) { - SendDlgItemMessage(hwndDlg, ((NMHDR*)lParam)->code, WM_COPY, 0, 0); - break; - } - } - if ((msg == WM_LBUTTONDOWN || msg == WM_KEYUP || msg == WM_LBUTTONUP) && ((NMHDR*)lParam)->idFrom == IDC_MESSAGE) { - int bBold = IsDlgButtonChecked(hwndDlg, IDC_FONTBOLD); - int bItalic = IsDlgButtonChecked(hwndDlg, IDC_FONTITALIC); - int bUnder = IsDlgButtonChecked(hwndDlg, IDC_FONTUNDERLINE); - int bStrikeout = IsDlgButtonChecked(hwndDlg, IDC_FONTSTRIKEOUT); - - cf2.cbSize = sizeof(CHARFORMAT2); - cf2.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_UNDERLINETYPE | CFM_STRIKEOUT; - cf2.dwEffects = 0; - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2); - if (cf2.dwEffects & CFE_BOLD) { - if (bBold == BST_UNCHECKED) - CheckDlgButton(hwndDlg, IDC_FONTBOLD, BST_CHECKED); - } - else if (bBold == BST_CHECKED) - CheckDlgButton(hwndDlg, IDC_FONTBOLD, BST_UNCHECKED); - - if (cf2.dwEffects & CFE_ITALIC) { - if (bItalic == BST_UNCHECKED) - CheckDlgButton(hwndDlg, IDC_FONTITALIC, BST_CHECKED); - } - else if (bItalic == BST_CHECKED) - CheckDlgButton(hwndDlg, IDC_FONTITALIC, BST_UNCHECKED); - - if (cf2.dwEffects & CFE_UNDERLINE && (cf2.bUnderlineType & CFU_UNDERLINE || cf2.bUnderlineType & CFU_UNDERLINEWORD)) { - if (bUnder == BST_UNCHECKED) - CheckDlgButton(hwndDlg, IDC_FONTUNDERLINE, BST_CHECKED); - } - else if (bUnder == BST_CHECKED) - CheckDlgButton(hwndDlg, IDC_FONTUNDERLINE, BST_UNCHECKED); - - if (cf2.dwEffects & CFE_STRIKEOUT) { - if (bStrikeout == BST_UNCHECKED) - CheckDlgButton(hwndDlg, IDC_FONTSTRIKEOUT, BST_CHECKED); - } - else if (bStrikeout == BST_CHECKED) - CheckDlgButton(hwndDlg, IDC_FONTSTRIKEOUT, BST_UNCHECKED); - } - switch (msg) { - case WM_LBUTTONDOWN: - { - HCURSOR hCur = GetCursor(); - m_pContainer->MenuBar->Cancel(); - if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE) - || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE)) { - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); - return TRUE; - } - break; - } - - // auto-select-and-copy handling... - // if enabled, releasing the lmb with an active selection automatically copies the selection - // to the clipboard. - // holding ctrl while releasing the button pastes the selection to the input area, using plain text - // holding ctrl-alt does the same, but pastes formatted text - case WM_LBUTTONUP: - if (((NMHDR*) lParam)->idFrom == IDC_LOG) { - CHARRANGE cr; - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXGETSEL, 0, (LPARAM)&cr); - if (cr.cpMax != cr.cpMin) { - cr.cpMin = cr.cpMax; - if (isCtrl && M.GetByte("autocopy", 1)) { - SETTEXTEX stx = {ST_KEEPUNDO | ST_SELECTION, CP_UTF8}; - char *streamOut = NULL; - if (isAlt) - streamOut = Message_GetFromStream(GetDlgItem(hwndDlg, IDC_LOG), SF_RTFNOOBJS | SFF_PLAINRTF | SFF_SELECTION); - else - streamOut = Message_GetFromStream(GetDlgItem(hwndDlg, IDC_LOG), SF_TEXT | SFF_SELECTION); - if (streamOut) { - Utils::FilterEventMarkers(streamOut); - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETTEXTEX, (WPARAM)&stx, (LPARAM)streamOut); - mir_free(streamOut); - } - SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); - } - else if (M.GetByte("autocopy", 1) && !isShift) { - SendDlgItemMessage(hwndDlg, IDC_LOG, WM_COPY, 0, 0); - SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); - if (m_pContainer->hwndStatus) - SendMessage(m_pContainer->hwndStatus, SB_SETTEXT, 0, (LPARAM)TranslateT("Selection copied to clipboard")); - } - } - } - break; - - case WM_RBUTTONUP: +
+ DM_SetDBButtonStates(hwndDlg, dat);
+
+ if (dat->hwndIEView) {
+ RECT rcRTF;
+ POINT pt;
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_LOG), &rcRTF);
+ rcRTF.left += 20;
+ rcRTF.top += 20;
+ pt.x = rcRTF.left;
+ pt.y = rcRTF.top;
+ if (dat->hwndIEView) {
+ if (M.GetByte("subclassIEView", 0)) {
+ mir_subclassWindow(dat->hwndIEView, IEViewSubclassProc);
+ SetWindowPos(dat->hwndIEView, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_DRAWFRAME);
+ RedrawWindow(dat->hwndIEView, 0, 0, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW);
+ }
+ }
+ dat->hwndIWebBrowserControl = WindowFromPoint(pt);
+ }
+
+ if (dat->dwFlagsEx & MWF_EX_DELAYEDSPLITTER) {
+ dat->dwFlagsEx &= ~MWF_EX_DELAYEDSPLITTER;
+ ShowWindow(dat->pContainer->hwnd, SW_RESTORE);
+ PostMessage(hwndDlg, DM_SPLITTERGLOBALEVENT, dat->wParam, dat->lParam);
+ dat->wParam = dat->lParam = 0;
+ }
+ if (dat->dwFlagsEx & MWF_EX_AVATARCHANGED) {
+ dat->dwFlagsEx &= ~MWF_EX_AVATARCHANGED;
+ PostMessage(hwndDlg, DM_UPDATEPICLAYOUT, 0, 0);
+ }
+ BB_SetButtonsPos(dat);
+ if (M.isAero())
+ InvalidateRect(hwndTab, NULL, FALSE);
+ if (dat->pContainer->dwFlags & CNT_SIDEBAR)
+ dat->pContainer->SideBar->setActiveItem(dat);
+
+ if (dat->pWnd)
+ dat->pWnd->Invalidate();
+}
+
+void TSAPI ShowMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state)
+{
+ for (int i = 0; i < cControls; i++)
+ Utils::showDlgControl(hwndDlg, controls[i], state);
+}
+
+void TSAPI SetDialogToType(HWND hwndDlg)
+{
+ TWindowData *dat = (TWindowData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ if (dat->hContact) {
+ if (db_get_b(dat->hContact, "CList", "NotOnList", 0)) {
+ dat->bNotOnList = TRUE;
+ ShowMultipleControls(hwndDlg, addControls, 2, SW_SHOW);
+ Utils::showDlgControl(hwndDlg, IDC_LOGFROZENTEXT, SW_SHOW);
+ SetDlgItemText(hwndDlg, IDC_LOGFROZENTEXT, TranslateT("Contact not on list. You may add it..."));
+ }
+ else {
+ ShowMultipleControls(hwndDlg, addControls, 2, SW_HIDE);
+ dat->bNotOnList = FALSE;
+ Utils::showDlgControl(hwndDlg, IDC_LOGFROZENTEXT, SW_HIDE);
+ }
+ }
+
+ Utils::enableDlgControl(hwndDlg, IDC_TIME, true);
+
+ if (dat->hwndIEView || dat->hwndHPP) {
+ Utils::showDlgControl(hwndDlg, IDC_LOG, SW_HIDE);
+ Utils::enableDlgControl(hwndDlg, IDC_LOG, false);
+ Utils::showDlgControl(hwndDlg, IDC_MESSAGE, SW_SHOW);
+ }
+ else ShowMultipleControls(hwndDlg, sendControls, sizeof(sendControls) / sizeof(sendControls[0]), SW_SHOW);
+
+ ShowMultipleControls(hwndDlg, errorControls, sizeof(errorControls) / sizeof(errorControls[0]), dat->dwFlags & MWF_ERRORSTATE ? SW_SHOW : SW_HIDE);
+
+ if (!dat->SendFormat)
+ ShowMultipleControls(hwndDlg, &formatControls[1], 5, SW_HIDE);
+
+ ConfigureSmileyButton(dat);
+
+ if (dat->pContainer->hwndActive == hwndDlg)
+ UpdateReadChars(dat);
+
+ SetDlgItemText(hwndDlg, IDC_STATICTEXT, TranslateT("A message failed to send successfully."));
+
+ DM_RecalcPictureSize(dat);
+ GetAvatarVisibility(hwndDlg, dat);
+
+ Utils::showDlgControl(hwndDlg, IDC_CONTACTPIC, dat->bShowAvatar ? SW_SHOW : SW_HIDE);
+ Utils::showDlgControl(hwndDlg, IDC_SPLITTER, dat->bIsAutosizingInput ? SW_HIDE : SW_SHOW);
+ Utils::showDlgControl(hwndDlg, IDC_MULTISPLITTER, (dat->sendMode & SMODE_MULTIPLE) ? SW_SHOW : SW_HIDE);
+
+ EnableSendButton(dat, GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)) != 0);
+ SendMessage(hwndDlg, DM_UPDATETITLE, 0, 1);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+
+ Utils::enableDlgControl(hwndDlg, IDC_CONTACTPIC, false);
+
+ dat->Panel->Configure();
+}
+
+static LRESULT CALLBACK MessageLogSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hwndParent = GetParent(hwnd);
+ TWindowData *mwdat = (TWindowData*)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+ BOOL isCtrl, isShift, isAlt;
+ KbdState(mwdat, isShift, isCtrl, isAlt);
+
+ switch (msg) {
+ case WM_KILLFOCUS:
+ if (wParam != (WPARAM)hwnd && 0 != wParam) {
+ CHARRANGE cr;
+ SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&cr);
+ if (cr.cpMax != cr.cpMin) {
+ cr.cpMin = cr.cpMax;
+ SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&cr);
+ }
+ }
+ break;
+
+ case WM_CHAR:
+ if (wParam == 0x03 && isCtrl) // Ctrl+C
+ return DM_WMCopyHandler(hwnd, MessageLogSubclassProc, msg, wParam, lParam);
+ if (wParam == 0x11 && isCtrl)
+ SendMessage(mwdat->hwnd, WM_COMMAND, IDC_QUOTE, 0);
+ break;
+
+ case WM_SYSKEYUP:
+ if (wParam == VK_MENU) {
+ ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_LOG);
+ return 0;
+ }
+ break;
+
+ case WM_SYSKEYDOWN:
+ mwdat->fkeyProcessed = false;
+ if (ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_LOG)) {
+ mwdat->fkeyProcessed = true;
+ return 0;
+ }
+ break;
+
+ case WM_SYSCHAR:
+ if (mwdat->fkeyProcessed) {
+ mwdat->fkeyProcessed = false;
+ return 0;
+ }
+ break;
+
+ case WM_KEYDOWN:
+ if (wParam == VK_INSERT && isCtrl)
+ return DM_WMCopyHandler(hwnd, MessageLogSubclassProc, msg, wParam, lParam);
+ break;
+
+ case WM_COPY:
+ return DM_WMCopyHandler(hwnd, MessageLogSubclassProc, msg, wParam, lParam);
+
+ case WM_NCCALCSIZE:
+ return CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, MessageLogSubclassProc);
+
+ case WM_NCPAINT:
+ return CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, MessageLogSubclassProc);
+
+ case WM_CONTEXTMENU:
+ POINT pt;
+
+ if (lParam == 0xFFFFFFFF) {
+ CHARRANGE sel;
+ SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel);
+ SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&pt, (LPARAM)sel.cpMax);
+ ClientToScreen(hwnd, &pt);
+ }
+ else {
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ }
+
+ ShowPopupMenu(mwdat, IDC_LOG, hwnd, pt);
+ return TRUE;
+ }
+
+ return mir_callNextSubclass(hwnd, MessageLogSubclassProc, msg, wParam, lParam);
+}
+
+static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ BOOL isCtrl, isShift, isAlt;
+ HWND hwndParent = GetParent(hwnd);
+ TWindowData *mwdat = (TWindowData*)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+ if (mwdat == NULL)
+ return 0;
+
+ // prevent the rich edit from switching text direction or keyboard layout when
+ // using hotkeys with ctrl-shift or alt-shift modifiers
+ if (mwdat->fkeyProcessed && (msg == WM_KEYUP)) {
+ GetKeyboardState(mwdat->kstate);
+ if (mwdat->kstate[VK_CONTROL] & 0x80 || mwdat->kstate[VK_SHIFT] & 0x80)
+ return 0;
+
+ mwdat->fkeyProcessed = false;
+ return 0;
+ }
+
+ switch (msg) {
+ case WM_NCCALCSIZE:
+ return CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKINPUTAREA, msg, wParam, lParam, MessageEditSubclassProc);
+
+ case WM_NCPAINT:
+ return CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKINPUTAREA, msg, wParam, lParam, MessageEditSubclassProc);
+
+ case WM_DROPFILES:
+ SendMessage(hwndParent, WM_DROPFILES, (WPARAM)wParam, (LPARAM)lParam);
+ return 0;
+
+ case WM_CHAR:
+ KbdState(mwdat, isShift, isCtrl, isAlt);
+
+ if (PluginConfig.m_bSoundOnTyping && !isAlt && !isCtrl && !(mwdat->pContainer->dwFlags & CNT_NOSOUND) && wParam != VK_ESCAPE && !(wParam == VK_TAB && PluginConfig.m_bAllowTab))
+ SkinPlaySound("SoundOnTyping");
+
+ if (isCtrl && !isAlt) {
+ switch (wParam) {
+ case 0x02: // bold
+ if (mwdat->SendFormat)
+ SendMessage(hwndParent, WM_COMMAND, MAKELONG(IDC_FONTBOLD, IDC_MESSAGE), 0);
+ return 0;
+ case 0x09:
+ if (mwdat->SendFormat)
+ SendMessage(hwndParent, WM_COMMAND, MAKELONG(IDC_FONTITALIC, IDC_MESSAGE), 0);
+ return 0;
+ case 21:
+ if (mwdat->SendFormat)
+ SendMessage(hwndParent, WM_COMMAND, MAKELONG(IDC_FONTUNDERLINE, IDC_MESSAGE), 0);
+ return 0;
+ case 0x0b:
+ SetWindowText(hwnd, _T(""));
+ return 0;
+ }
+ }
+ break;
+
+ case WM_MOUSEWHEEL:
+ if (DM_MouseWheelHandler(hwnd, hwndParent, mwdat, wParam, lParam) == 0)
+ return 0;
+ break;
+
+ case EM_PASTESPECIAL:
+ case WM_PASTE:
+ if (OpenClipboard(hwnd)) {
+ HANDLE hClip = GetClipboardData(CF_TEXT);
+ if (hClip) {
+ if (mir_strlen((char*)hClip) > mwdat->nMax) {
+ TCHAR szBuffer[512];
+ if (M.GetByte("autosplit", 0))
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("WARNING: The message you are trying to paste exceeds the message size limit for the active protocol. It will be sent in chunks of max %d characters"), mwdat->nMax - 10);
+ else
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("The message you are trying to paste exceeds the message size limit for the active protocol. Only the first %d characters will be sent."), mwdat->nMax);
+ SendMessage(hwndParent, DM_ACTIVATETOOLTIP, IDC_MESSAGE, (LPARAM)szBuffer);
+ }
+ }
+ else if (hClip = GetClipboardData(CF_BITMAP))
+ SendHBitmapAsFile(mwdat, (HBITMAP)hClip);
+
+ CloseClipboard();
+ }
+ break;
+
+ case WM_KEYDOWN:
+ KbdState(mwdat, isShift, isCtrl, isAlt);
+
+ if (PluginConfig.m_bSoundOnTyping && !isAlt && !(mwdat->pContainer->dwFlags & CNT_NOSOUND) && wParam == VK_DELETE)
+ SkinPlaySound("SoundOnTyping");
+
+ if (wParam == VK_INSERT && !isShift && !isCtrl && !isAlt) {
+ mwdat->fInsertMode = !mwdat->fInsertMode;
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM)hwnd);
+ }
+ if (wParam == VK_CAPITAL || wParam == VK_NUMLOCK)
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM)hwnd);
+
+ if (wParam == VK_RETURN) {
+ if (mwdat->fEditNotesActive)
+ break;
+
+ if (isShift) {
+ if (PluginConfig.m_bSendOnShiftEnter) {
+ PostMessage(hwndParent, WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ else break;
+ }
+ if ((isCtrl && !isShift) ^ (0 != PluginConfig.m_bSendOnEnter)) {
+ PostMessage(hwndParent, WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ if (PluginConfig.m_bSendOnEnter || PluginConfig.m_bSendOnDblEnter) {
+ if (isCtrl)
+ break;
+
+ if (PluginConfig.m_bSendOnDblEnter) {
+ LONG_PTR lastEnterTime = GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ if (lastEnterTime + 2 < time(NULL)) {
+ lastEnterTime = time(NULL);
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, lastEnterTime);
+ break;
+ }
+ else {
+ SendMessage(hwnd, WM_KEYDOWN, VK_BACK, 0);
+ SendMessage(hwnd, WM_KEYUP, VK_BACK, 0);
+ PostMessage(hwndParent, WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ }
+ PostMessage(hwndParent, WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ else break;
+ }
+ else SetWindowLongPtr(hwnd, GWLP_USERDATA, 0);
+
+ if (isCtrl && !isAlt && !isShift) {
+ if (!isShift && (wParam == VK_UP || wParam == VK_DOWN)) { // input history scrolling (ctrl-up / down)
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, 0);
+ if (mwdat)
+ mwdat->cache->inputHistoryEvent(wParam);
+ return 0;
+ }
+ }
+ 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;
+
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, 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(mwdat, 0, 0);
+ return 0;
+ }
+ else if (wParam == VK_DOWN)
+ wp = MAKEWPARAM(SB_LINEDOWN, 0);
+
+ if (mwdat->hwndIEView == 0 && mwdat->hwndHPP == 0)
+ SendDlgItemMessage(hwndParent, IDC_LOG, WM_VSCROLL, wp, 0);
+ else
+ SendMessage(mwdat->hwndIWebBrowserControl, WM_VSCROLL, wp, 0);
+ return 0;
+ }
+ }
+ if (wParam == VK_RETURN)
+ break;
+
+ case WM_SYSKEYDOWN:
+ mwdat->fkeyProcessed = false;
+ if (ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_MESSAGE)) {
+ mwdat->fkeyProcessed = true;
+ return 0;
+ }
+ break;
+
+ case WM_SYSKEYUP:
+ if (wParam == VK_MENU) {
+ ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_MESSAGE);
+ return 0;
+ }
+ break;
+
+ case WM_SYSCHAR:
+ if (mwdat->fkeyProcessed) {
+ mwdat->fkeyProcessed = false;
+ return 0;
+ }
+
+ KbdState(mwdat, isShift, isCtrl, isAlt);
+ if ((wParam >= '0' && wParam <= '9') && isAlt) { // ALT-1 -> ALT-0 direct tab selection
+ BYTE bChar = (BYTE)wParam;
+ int iIndex;
+
+ if (bChar == '0')
+ iIndex = 10;
+ else
+ iIndex = bChar - (BYTE)'0';
+ SendMessage(mwdat->pContainer->hwnd, DM_SELECTTAB, DM_SELECT_BY_INDEX, (LPARAM)iIndex);
+ return 0;
+ }
+ break;
+
+ case WM_INPUTLANGCHANGE:
+ if (PluginConfig.m_bAutoLocaleSupport && GetFocus() == hwnd && mwdat->pContainer->hwndActive == hwndParent && GetForegroundWindow() == mwdat->pContainer->hwnd && GetActiveWindow() == mwdat->pContainer->hwnd) {
+ DM_SaveLocale(mwdat, wParam, lParam);
+ SendMessage(hwnd, EM_SETLANGOPTIONS, 0, (LPARAM)SendMessage(hwnd, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD);
+ return 1;
+ }
+ break;
+
+ case WM_ERASEBKGND:
+ return(CSkin::m_skinEnabled ? 0 : 1);
+
+ // sent by smileyadd when the smiley selection window dies
+ // just grab the focus :)
+ case WM_USER + 100:
+ SetFocus(hwnd);
+ break;
+
+ case WM_CONTEXTMENU:
+ POINT pt;
+ if (lParam == 0xFFFFFFFF) {
+ CHARRANGE sel;
+ SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel);
+ SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&pt, (LPARAM)sel.cpMax);
+ ClientToScreen(hwnd, &pt);
+ }
+ else {
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ }
+
+ ShowPopupMenu(mwdat, IDC_MESSAGE, hwnd, pt);
+ return TRUE;
+ }
+ return mir_callNextSubclass(hwnd, MessageEditSubclassProc, msg, wParam, lParam);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// subclasses the avatar display controls, needed for skinning and to prevent
+// it from flickering during resize/move operations.
+
+static LRESULT CALLBACK AvatarSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_ERASEBKGND:
+ return TRUE;
+
+ case WM_UPDATEUISTATE:
+ return TRUE;
+
+ case WM_NOTIFY:
+ ProcessAvatarChange(hwnd, lParam);
+ break;
+ }
+ return mir_callNextSubclass(hwnd, AvatarSubclassProc, msg, wParam, lParam);
+}
+
+LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ RECT rc;
+ HWND hwndParent = GetParent(hwnd);
+ TWindowData *dat = (TWindowData*)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+
+ switch (msg) {
+ case WM_NCHITTEST:
+ return HTCLIENT;
+
+ case WM_SETCURSOR:
+ GetClientRect(hwnd, &rc);
+ SetCursor(rc.right > rc.bottom ? PluginConfig.hCurSplitNS : PluginConfig.hCurSplitWE);
+ return TRUE;
+
+ case WM_LBUTTONDOWN:
+ if (hwnd == GetDlgItem(hwndParent, IDC_SPLITTER) || hwnd == GetDlgItem(hwndParent, IDC_SPLITTERY)) {
+ if (dat) {
+ GetClientRect(hwnd, &rc);
+ dat->savedSplitter = rc.right > rc.bottom ? (short)HIWORD(GetMessagePos()) + rc.bottom / 2 : (short)LOWORD(GetMessagePos()) + rc.right / 2;
+ if (dat->bType == SESSIONTYPE_IM)
+ dat->savedSplitY = dat->splitterY;
+ else
+ dat->savedSplitY = dat->si->iSplitterY;
+
+ dat->savedDynaSplit = dat->dynaSplitter;
+ }
+ }
+ SetCapture(hwnd);
+ return 0;
+
+ case WM_MOUSEMOVE:
+ if (GetCapture() == hwnd) {
+ GetClientRect(hwnd, &rc);
+ SendMessage(hwndParent, DM_SPLITTERMOVED, rc.right > rc.bottom ? (short)HIWORD(GetMessagePos()) + rc.bottom / 2 : (short)LOWORD(GetMessagePos()) + rc.right / 2, (LPARAM)hwnd);
+ }
+ return 0;
+
+ case WM_ERASEBKGND:
+ return 1;
+
+ case WM_PAINT:
+ GetClientRect(hwnd, &rc);
+ {
+ PAINTSTRUCT ps;
+ HDC dc = BeginPaint(hwnd, &ps);
+
+ if (dat && CSkin::m_skinEnabled)
+ CSkin::SkinDrawBG(hwnd, dat->pContainer->hwnd, dat->pContainer, &rc, dc);
+ else if (M.isAero() || M.isVSThemed()) {
+ if (GetDlgCtrlID(hwnd) == IDC_PANELSPLITTER) {
+ EndPaint(hwnd, &ps);
+ return 0;
+ }
+ CSkin::FillBack(dc, &rc);
+ }
+ else CSkin::FillBack(dc, &rc);
+
+ EndPaint(hwnd, &ps);
+ }
+ return 0;
+
+ case WM_LBUTTONUP:
+ HWND hwndCapture = GetCapture();
+
+ ReleaseCapture();
+ DM_ScrollToBottom(dat, 0, 1);
+ if (dat && dat->bType == SESSIONTYPE_IM && hwnd == GetDlgItem(hwndParent, IDC_PANELSPLITTER)) {
+ SendMessage(hwndParent, WM_SIZE, 0, 0);
+ RedrawWindow(hwndParent, NULL, NULL, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW);
+ }
+ else if ((dat && dat->bType == SESSIONTYPE_IM && hwnd == GetDlgItem(hwndParent, IDC_SPLITTER)) ||
+ (dat && dat->bType == SESSIONTYPE_CHAT && hwnd == GetDlgItem(hwndParent, IDC_SPLITTERY))) {
+ POINT pt;
+ int selection;
+ HMENU hMenu = GetSubMenu(dat->pContainer->hMenuContext, 12);
+ LONG messagePos = GetMessagePos();
+
+ GetClientRect(hwnd, &rc);
+ if (hwndCapture != hwnd || dat->savedSplitter == (rc.right > rc.bottom ? (short)HIWORD(messagePos) + rc.bottom / 2 : (short)LOWORD(messagePos) + rc.right / 2))
+ break;
+ GetCursorPos(&pt);
+
+ if (dat->bIsAutosizingInput)
+ selection = ID_SPLITTERCONTEXT_SETPOSITIONFORTHISSESSION;
+ else
+ selection = TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndParent, NULL);
+
+ switch (selection) {
+ case ID_SPLITTERCONTEXT_SAVEFORTHISCONTACTONLY:
+ dat->dwFlagsEx |= MWF_SHOW_SPLITTEROVERRIDE;
+ db_set_b(dat->hContact, SRMSGMOD_T, "splitoverride", 1);
+ if (dat->bType == SESSIONTYPE_IM)
+ SaveSplitter(dat);
+ break;
+
+ case ID_SPLITTERCONTEXT_SETPOSITIONFORTHISSESSION:
+ if (dat->bIsAutosizingInput) {
+ GetWindowRect(GetDlgItem(dat->hwnd, IDC_MESSAGE), &rc);
+ dat->iInputAreaHeight = 0;
+ }
+ break;
+
+ case ID_SPLITTERCONTEXT_SAVEGLOBALFORALLSESSIONS:
+ {
+ BYTE bSync = M.GetByte(CHAT_MODULE, "SyncSplitter", 0);
+ DWORD dwOff_IM = 0, dwOff_CHAT = 0;
+
+ dwOff_CHAT = -(2 + (PluginConfig.m_DPIscaleY > 1.0 ? 1 : 0));
+ dwOff_IM = 2 + (PluginConfig.m_DPIscaleY > 1.0 ? 1 : 0);
+
+ RECT rcWin;
+ GetWindowRect(hwndParent, &rcWin);
+
+ PluginConfig.lastSPlitterPos.pSrcDat = dat;
+ PluginConfig.lastSPlitterPos.pSrcContainer = dat->pContainer;
+ PluginConfig.lastSPlitterPos.lParam = rc.bottom;
+ PluginConfig.lastSPlitterPos.pos = rcWin.bottom - HIWORD(messagePos);
+ PluginConfig.lastSPlitterPos.pos_chat = rcWin.bottom - (short)HIWORD(messagePos) + rc.bottom / 2;
+ PluginConfig.lastSPlitterPos.off_chat = dwOff_CHAT;
+ PluginConfig.lastSPlitterPos.off_im = dwOff_IM;
+ PluginConfig.lastSPlitterPos.bSync = bSync;
+ SendMessage(dat->hwnd, DM_SPLITTERGLOBALEVENT, 0, 0);
+ M.BroadcastMessage(DM_SPLITTERGLOBALEVENT, 0, 0);
+ }
+ break;
+
+ default:
+ dat->splitterY = dat->savedSplitY;
+ dat->dynaSplitter = dat->savedDynaSplit;
+ DM_RecalcPictureSize(dat);
+ if (dat->bType == SESSIONTYPE_CHAT) {
+ SESSION_INFO *si = dat->si;
+ si->iSplitterY = dat->savedSplitY;
+ dat->splitterY = si->iSplitterY + DPISCALEY_S(22);
+ }
+ CSkin::UpdateToolbarBG(dat);
+ SendMessage(hwndParent, WM_SIZE, 0, 0);
+ DM_ScrollToBottom(dat, 0, 1);
+ break;
+ }
+ }
+ return 0;
+ }
+ return mir_callNextSubclass(hwnd, SplitterSubclassProc, msg, wParam, lParam);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// resizer proc for the "new" layout.
+
+static int MessageDialogResize(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL * urc)
+{
+ TWindowData *dat = (TWindowData*)lParam;
+ RECT rc, rcButton;
+ static int uinWidth, msgTop = 0, msgBottom = 0;
+
+ int showToolbar = dat->pContainer->dwFlags & CNT_HIDETOOLBAR ? 0 : 1;
+ BOOL bBottomToolbar = dat->pContainer->dwFlags & CNT_BOTTOMTOOLBAR ? 1 : 0;
+ static LONG rcLogBottom;
+
+ int panelHeight = dat->Panel->getHeight() + 1;
+ int s_offset = 0;
+ bool bInfoPanel = dat->Panel->isActive();
+ bool fErrorState = (dat->dwFlags & MWF_ERRORSTATE) ? true : false;
+
+ GetClientRect(GetDlgItem(hwndDlg, IDC_LOG), &rc);
+ GetClientRect(GetDlgItem(hwndDlg, IDC_PROTOCOL), &rcButton);
+
+ if (dat->panelStatusCX == 0)
+ dat->panelStatusCX = 80;
+
+ s_offset = 1;
+
+ switch (urc->wId) {
+ case IDC_PANELSPLITTER:
+ urc->rcItem.bottom = panelHeight;
+ urc->rcItem.top = panelHeight - 2;
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP;
+
+ case IDC_LOG:
+ if (dat->dwFlags & MWF_ERRORSTATE)
+ urc->rcItem.bottom -= ERRORPANEL_HEIGHT;
+ if (dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED || dat->bNotOnList)
+ urc->rcItem.bottom -= 20;
+ if (dat->sendMode & SMODE_MULTIPLE)
+ urc->rcItem.right -= (dat->multiSplitterX + 3);
+ urc->rcItem.bottom -= dat->splitterY - dat->originalSplitterY;
+ if (!showToolbar || bBottomToolbar)
+ urc->rcItem.bottom += 21;
+ if (bInfoPanel)
+ urc->rcItem.top += panelHeight;
+ urc->rcItem.bottom += 3;
+ 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;
+ }
+ }
+ rcLogBottom = urc->rcItem.bottom;
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT;
+
+ case IDC_CONTACTPIC:
+ GetClientRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &rc);
+ urc->rcItem.top -= dat->splitterY - dat->originalSplitterY;
+ urc->rcItem.left = urc->rcItem.right - (dat->pic.cx + 2);
+ if ((urc->rcItem.bottom - urc->rcItem.top) < (dat->pic.cy/* + 2*/) && dat->bShowAvatar) {
+ urc->rcItem.top = urc->rcItem.bottom - dat->pic.cy;
+ dat->bUseOffset = true;
+ }
+ else dat->bUseOffset = false;
+
+ if (showToolbar && bBottomToolbar && (PluginConfig.m_bAlwaysFullToolbarWidth || ((dat->pic.cy - DPISCALEY_S(6)) < rc.bottom))) {
+ urc->rcItem.bottom -= DPISCALEY_S(22);
+ if (dat->bIsAutosizingInput) {
+ urc->rcItem.left--;
+ urc->rcItem.top--;
+ }
+ }
+
+ if (dat->hwndContactPic) //if Panel control was created?
+ SetWindowPos(dat->hwndContactPic, HWND_TOP, 1, ((urc->rcItem.bottom - urc->rcItem.top) - (dat->pic.cy)) / 2 + 1, //resizes it
+ dat->pic.cx - 2, dat->pic.cy - 2, SWP_SHOWWINDOW);
+
+ return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM;
+
+ case IDC_SPLITTER:
+ urc->rcItem.right = urc->dlgNewSize.cx;
+ urc->rcItem.top -= dat->splitterY - dat->originalSplitterY;
+ urc->rcItem.bottom = urc->rcItem.top + 2;
+ OffsetRect(&urc->rcItem, 0, 1);
+ urc->rcItem.left = 0;
+
+ if (dat->bUseOffset)
+ urc->rcItem.right -= (dat->pic.cx); // + DPISCALEX(2));
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_BOTTOM;
+
+ case IDC_MESSAGE:
+ urc->rcItem.right = urc->dlgNewSize.cx;
+ if (dat->bShowAvatar)
+ urc->rcItem.right -= dat->pic.cx + 2;
+ urc->rcItem.top -= dat->splitterY - dat->originalSplitterY;
+ if (bBottomToolbar&&showToolbar)
+ urc->rcItem.bottom -= DPISCALEY_S(22);
+
+ if (dat->bIsAutosizingInput)
+ urc->rcItem.top -= DPISCALEY_S(1);
+
+ msgTop = urc->rcItem.top;
+ msgBottom = urc->rcItem.bottom;
+ 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_BOTTOM;
+
+ case IDC_MULTISPLITTER:
+ if (bInfoPanel)
+ urc->rcItem.top += panelHeight;
+ urc->rcItem.left -= dat->multiSplitterX;
+ urc->rcItem.right -= dat->multiSplitterX;
+ urc->rcItem.bottom = rcLogBottom;
+ return RD_ANCHORX_RIGHT | RD_ANCHORY_HEIGHT;
+
+ case IDC_LOGFROZENTEXT:
+ urc->rcItem.right = urc->dlgNewSize.cx - 50;
+ urc->rcItem.bottom = msgTop - (bBottomToolbar ? 0 : 28);
+ urc->rcItem.top = msgTop - 16 - (bBottomToolbar ? 0 : 28);
+ if (!showToolbar && !bBottomToolbar) {
+ urc->rcItem.bottom += 21;
+ urc->rcItem.top += 21;
+ }
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_BOTTOM;
+
+ case IDC_ADD:
+ urc->rcItem.bottom = msgTop - (bBottomToolbar ? 0 : 28);
+ urc->rcItem.top = msgTop - 18 - (bBottomToolbar ? 0 : 28);
+ urc->rcItem.right = urc->dlgNewSize.cx - 28;
+ urc->rcItem.left = urc->rcItem.right - 20;
+ if (!showToolbar && !bBottomToolbar) {
+ urc->rcItem.bottom += 21;
+ urc->rcItem.top += 21;
+ }
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_BOTTOM;
+
+ case IDC_CANCELADD:
+ urc->rcItem.bottom = msgTop - (bBottomToolbar ? 0 : 28);
+ urc->rcItem.top = msgTop - 18 - (bBottomToolbar ? 0 : 28);
+ urc->rcItem.right = urc->dlgNewSize.cx - 4;
+ urc->rcItem.left = urc->rcItem.right - 20;
+ if (!showToolbar && !bBottomToolbar) {
+ urc->rcItem.bottom += 21;
+ urc->rcItem.top += 21;
+ }
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_BOTTOM;
+
+ case IDC_TOGGLESIDEBAR:
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM;
+
+ case IDC_RETRY:
+ case IDC_CANCELSEND:
+ case IDC_MSGSENDLATER:
+ if (fErrorState) {
+ urc->rcItem.bottom = msgTop - 5 - (bBottomToolbar ? 0 : 28) - ((dat->bNotOnList || dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED) ? 20 : 0);
+ urc->rcItem.top = msgTop - 25 - (bBottomToolbar ? 0 : 28) - ((dat->bNotOnList || dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED) ? 20 : 0);
+ }
+ if (!showToolbar && !bBottomToolbar) {
+ urc->rcItem.bottom += 21;
+ urc->rcItem.top += 21;
+ }
+ return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM;
+
+ case IDC_STATICTEXT:
+ case IDC_STATICERRORICON:
+ if (fErrorState) {
+ urc->rcItem.bottom = msgTop - 28 - (bBottomToolbar ? 0 : 28) - ((dat->bNotOnList || dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED) ? 20 : 0);
+ urc->rcItem.top = msgTop - 45 - (bBottomToolbar ? 0 : 28) - ((dat->bNotOnList || dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED) ? 20 : 0);
+ }
+ if (!showToolbar && !bBottomToolbar) {
+ urc->rcItem.bottom += 21;
+ urc->rcItem.top += 21;
+ }
+ return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM;
+ }
+ return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM;
+}
+
+INT_PTR CALLBACK DlgProcMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ TContainerData *m_pContainer = 0;
+ TWindowData *dat = (TWindowData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ HWND hwndTab = GetParent(hwndDlg), hwndContainer;
+ POINT pt, tmp, cur;
+ RECT rc;
+
+ if (dat == 0) {
+ if (msg == WM_ACTIVATE || msg == WM_SETFOCUS)
+ return 0;
+ hwndContainer = NULL;
+ }
+ else {
+ m_pContainer = dat->pContainer;
+ hwndContainer = m_pContainer->hwnd;
+ }
+
+ switch (msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ {
+ TNewWindowData *newData = (TNewWindowData*)lParam;
+
+ dat = (TWindowData*)mir_calloc(sizeof(TWindowData));
+ if (newData->iTabID >= 0) {
+ dat->pContainer = newData->pContainer;
+ m_pContainer = dat->pContainer;
+ hwndContainer = m_pContainer->hwnd;
+ }
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
+
+ if (Utils::rtf_ctable == 0)
+ Utils::RTF_CTableInit();
+
+ dat->dwFlags |= MWF_INITMODE;
+ dat->bType = SESSIONTYPE_IM;
+ dat->fInsertMode = FALSE;
+ dat->fLimitedUpdate = false;
+ dat->Panel = new CInfoPanel(dat);
+
+ newData->item.lParam = (LPARAM)hwndDlg;
+ TabCtrl_SetItem(hwndTab, newData->iTabID, &newData->item);
+ dat->iTabID = newData->iTabID;
+ dat->hwnd = hwndDlg;
+
+ DM_ThemeChanged(dat);
+
+ pszIDCSAVE_close = TranslateT("Close session");
+ pszIDCSAVE_save = TranslateT("Save and close session");
+
+ dat->hContact = newData->hContact;
+ dat->cache = CContactCache::getContactCache(dat->hContact);
+ dat->cache->updateState();
+ dat->cache->setWindowData(hwndDlg, dat);
+ M.AddWindow(hwndDlg, dat->hContact);
+ BroadCastContainer(m_pContainer, DM_REFRESHTABINDEX, 0, 0);
+ dat->pWnd = 0;
+ dat->sbCustom = 0;
+ CProxyWindow::add(dat);
+ dat->szProto = const_cast<char *>(dat->cache->getProto());
+ dat->bIsMeta = dat->cache->isMeta();
+ if (dat->bIsMeta)
+ dat->cache->updateMeta();
+
+ dat->cache->updateUIN();
+
+ if (dat->hContact && dat->szProto != NULL) {
+ dat->wStatus = db_get_w(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE);
+ _tcsncpy_s(dat->szStatus, pcli->pfnGetStatusModeDescription(dat->szProto == NULL ? ID_STATUS_OFFLINE : dat->wStatus, 0), _TRUNCATE);
+ }
+ else dat->wStatus = ID_STATUS_OFFLINE;
+
+ for (int i = 0; i < SIZEOF(btnControls); i++)
+ CustomizeButton(GetDlgItem(hwndDlg, btnControls[i]));
+
+ GetMYUIN(dat);
+ GetClientIcon(dat);
+
+ CustomizeButton(CreateWindowEx(0, _T("MButtonClass"), _T(""), WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 0, 6, DPISCALEY_S(20),
+ hwndDlg, (HMENU)IDC_TOGGLESIDEBAR, g_hInst, NULL));
+ dat->hwndPanelPicParent = CreateWindowEx(WS_EX_TOPMOST, _T("Static"), _T(""), SS_OWNERDRAW | WS_VISIBLE | WS_CHILD, 1, 1, 1, 1, hwndDlg, (HMENU)6000, NULL, NULL);
+ mir_subclassWindow(dat->hwndPanelPicParent, CInfoPanel::avatarParentSubclass);
+
+ dat->bShowUIElements = (m_pContainer->dwFlags & CNT_HIDETOOLBAR) == 0;
+ dat->sendMode |= M.GetByte(dat->hContact, "forceansi", 0) ? SMODE_FORCEANSI : 0;
+ dat->sendMode |= dat->hContact == 0 ? SMODE_MULTIPLE : 0;
+ dat->sendMode |= M.GetByte(dat->hContact, "no_ack", 0) ? SMODE_NOACK : 0;
+
+ dat->hQueuedEvents = (MEVENT*)mir_calloc(sizeof(MEVENT)* EVENT_QUEUE_SIZE);
+ dat->iEventQueueSize = EVENT_QUEUE_SIZE;
+ dat->iCurrentQueueError = -1;
+
+ // message history limit
+ // hHistoryEvents holds up to n event handles
+ dat->maxHistory = M.GetDword(dat->hContact, "maxhist", M.GetDword("maxhist", 0));
+ dat->curHistory = 0;
+ if (dat->maxHistory)
+ dat->hHistoryEvents = (MEVENT*)mir_alloc(dat->maxHistory * sizeof(MEVENT));
+ else
+ dat->hHistoryEvents = NULL;
+
+ if (dat->bIsMeta)
+ SendMessage(hwndDlg, DM_UPDATEMETACONTACTINFO, 0, 0);
+ else
+ SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0);
+ dat->bTabFlash = FALSE;
+ dat->mayFlashTab = FALSE;
+ GetMyNick(dat);
+
+ dat->multiSplitterX = (int)M.GetDword(SRMSGMOD, "multisplit", 150);
+ dat->nTypeMode = PROTOTYPE_SELFTYPING_OFF;
+ SetTimer(hwndDlg, TIMERID_TYPE, 1000, NULL);
+ dat->iLastEventType = 0xffffffff;
+
+ // load log option flags...
+ dat->dwFlags = dat->pContainer->theme.dwFlags;
+
+ // consider per-contact message setting overrides
+ if (dat->hContact && M.GetDword(dat->hContact, "mwmask", 0))
+ LoadLocalFlags(dat);
+
+ DM_InitTip(dat);
+ dat->Panel->getVisibility();
+
+ dat->dwFlagsEx |= M.GetByte(dat->hContact, "splitoverride", 0) ? MWF_SHOW_SPLITTEROVERRIDE : 0;
+ dat->bIsAutosizingInput = IsAutoSplitEnabled(dat);
+ dat->iInputAreaHeight = -1;
+ SetMessageLog(dat);
+ if (dat->hContact) {
+ dat->codePage = M.GetDword(dat->hContact, "ANSIcodepage", CP_ACP);
+ dat->Panel->loadHeight();
+ }
+
+ dat->bShowAvatar = GetAvatarVisibility(hwndDlg, dat);
+
+ Utils::showDlgControl(hwndDlg, IDC_MULTISPLITTER, SW_HIDE);
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_SPLITTER), &rc);
+ pt.y = (rc.top + rc.bottom) / 2;
+ pt.x = 0;
+ ScreenToClient(hwndDlg, &pt);
+ dat->originalSplitterY = pt.y;
+ if (dat->splitterY == -1)
+ dat->splitterY = dat->originalSplitterY + 60;
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &rc);
+ dat->minEditBoxSize.cx = rc.right - rc.left;
+ dat->minEditBoxSize.cy = rc.bottom - rc.top;
+
+ BB_InitDlgButtons(dat);
+ SendMessage(hwndDlg, DM_LOADBUTTONBARICONS, 0, 0);
+
+ BOOL isThemed = TRUE;
+ if (CSkin::m_skinEnabled && !SkinItems[ID_EXTBKBUTTONSNPRESSED].IGNORED &&
+ !SkinItems[ID_EXTBKBUTTONSPRESSED].IGNORED && !SkinItems[ID_EXTBKBUTTONSMOUSEOVER].IGNORED)
+ isThemed = FALSE;
+
+ SendDlgItemMessage(hwndDlg, IDC_ADD, BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CANCELADD, BUTTONSETASFLATBTN, TRUE, 0);
+
+ SendDlgItemMessage(hwndDlg, IDC_TOGGLESIDEBAR, BUTTONSETASFLATBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_TOGGLESIDEBAR, BUTTONSETASTHEMEDBTN, isThemed, 0);
+ SendDlgItemMessage(hwndDlg, IDC_TOGGLESIDEBAR, BUTTONSETCONTAINER, (LPARAM)m_pContainer, 0);
+ SendDlgItemMessage(hwndDlg, IDC_TOGGLESIDEBAR, BUTTONSETASTOOLBARBUTTON, TRUE, 0);
+
+ TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPENING, 0);
+
+ for (int i = 0; i < SIZEOF(tooltips); i++)
+ SendDlgItemMessage(hwndDlg, tooltips[i].id, BUTTONADDTOOLTIP, (WPARAM)TranslateTS(tooltips[i].text), BATF_TCHAR);
+
+ SetDlgItemText(hwndDlg, IDC_LOGFROZENTEXT, dat->bNotOnList ? TranslateT("Contact not on list. You may add it...") :
+ TranslateT("Auto scrolling is disabled (press F12 to enable it)"));
+
+ SendDlgItemMessage(hwndDlg, IDC_SAVE, BUTTONADDTOOLTIP, (WPARAM)pszIDCSAVE_close, BATF_TCHAR);
+ SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Click for contact menu\nClick dropdown for window settings"), BATF_TCHAR);
+
+ SetDlgItemText(hwndDlg, IDC_RETRY, TranslateT("Retry"));
+
+ UINT _ctrls[] = { IDC_RETRY, IDC_CANCELSEND, IDC_MSGSENDLATER };
+ for (int i = 0; i < SIZEOF(_ctrls); i++) {
+ SendDlgItemMessage(hwndDlg, _ctrls[i], BUTTONSETASPUSHBTN, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, _ctrls[i], BUTTONSETASFLATBTN, FALSE, 0);
+ SendDlgItemMessage(hwndDlg, _ctrls[i], BUTTONSETASTHEMEDBTN, TRUE, 0);
+ }
+
+ SetDlgItemText(hwndDlg, IDC_CANCELSEND, TranslateT("Cancel"));
+ SetDlgItemText(hwndDlg, IDC_MSGSENDLATER, TranslateT("Send later"));
+
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETUNDOLIMIT, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_KEYEVENTS | ENM_LINK);
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETOLECALLBACK, 0, (LPARAM)&reOleCallback);
+
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETEVENTMASK, 0, ENM_REQUESTRESIZE | ENM_MOUSEEVENTS | ENM_SCROLL | ENM_KEYEVENTS | ENM_CHANGE);
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETOLECALLBACK, 0, (LPARAM)&reOleCallback2);
+
+ dat->bActualHistory = M.GetByte(dat->hContact, "ActualHistory", 0);
+
+ /* OnO: higligh lines to their end */
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETEDITSTYLE, SES_EXTENDBACKCOLOR, SES_EXTENDBACKCOLOR);
+
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETLANGOPTIONS, 0, SendDlgItemMessage(hwndDlg, IDC_LOG, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOFONTSIZEADJUST);
+
+ // add us to the tray list (if it exists)
+ if (PluginConfig.g_hMenuTrayUnread != 0 && dat->hContact != 0 && dat->szProto != NULL)
+ UpdateTrayMenu(0, dat->wStatus, dat->szProto, dat->szStatus, dat->hContact, FALSE);
+
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_AUTOURLDETECT, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXLIMITTEXT, 0, 0x80000000);
+
+ // subclassing stuff
+ mir_subclassWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), MessageEditSubclassProc);
+ mir_subclassWindow(GetDlgItem(hwndDlg, IDC_CONTACTPIC), AvatarSubclassProc);
+ mir_subclassWindow(GetDlgItem(hwndDlg, IDC_SPLITTER), SplitterSubclassProc);
+ mir_subclassWindow(GetDlgItem(hwndDlg, IDC_MULTISPLITTER), SplitterSubclassProc);
+ mir_subclassWindow(GetDlgItem(hwndDlg, IDC_PANELSPLITTER), SplitterSubclassProc);
+
+ // load old messages from history (if wanted...)
+ dat->cache->updateStats(TSessionStats::INIT_TIMER);
+ if (dat->hContact) {
+ FindFirstEvent(dat);
+ dat->nMax = dat->cache->getMaxMessageLength();
+ }
+ LoadContactAvatar(dat);
+ SendMessage(hwndDlg, DM_OPTIONSAPPLIED, 0, 0);
+ LoadOwnAvatar(dat);
+
+ // restore saved msg if any...
+ if (dat->hContact) {
+ ptrT tszSavedMsg(db_get_tsa(dat->hContact, SRMSGMOD, "SavedMsg"));
+ if (tszSavedMsg != 0) {
+ SETTEXTEX stx = { ST_DEFAULT, 1200 };
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETTEXTEX, (WPARAM)&stx, tszSavedMsg);
+ SendQueue::UpdateSaveAndSendButton(dat);
+ if (m_pContainer->hwndActive == hwndDlg)
+ UpdateReadChars(dat);
+ }
+ }
+ if (newData->szInitialText) {
+ if (newData->isWchar)
+ SetDlgItemTextW(hwndDlg, IDC_MESSAGE, (TCHAR*)newData->szInitialText);
+ else
+ SetDlgItemTextA(hwndDlg, IDC_MESSAGE, newData->szInitialText);
+ int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ PostMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), EM_SETSEL, len, len);
+ if (len)
+ EnableSendButton(dat, TRUE);
+ }
+
+ for (MEVENT hdbEvent = db_event_last(dat->hContact); hdbEvent; hdbEvent = db_event_prev(dat->hContact, hdbEvent)) {
+ DBEVENTINFO dbei = { sizeof(dbei) };
+ db_event_get(hdbEvent, &dbei);
+ if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & DBEF_SENT)) {
+ dat->lastMessage = dbei.timestamp;
+ DM_UpdateLastMessage(dat);
+ break;
+ }
+ }
+
+ SendMessage(hwndContainer, DM_QUERYCLIENTAREA, 0, (LPARAM)&rc);
+
+ WNDCLASS wndClass = { 0 };
+ GetClassInfo(g_hInst, _T("RICHEDIT50W"), &wndClass);
+ mir_subclassWindowFull(GetDlgItem(hwndDlg, IDC_LOG), MessageLogSubclassProc, wndClass.lpfnWndProc);
+
+ SetWindowPos(hwndDlg, 0, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), newData->iActivate ? 0 : SWP_NOZORDER | SWP_NOACTIVATE);
+ LoadSplitter(dat);
+ ShowPicture(dat, TRUE);
+
+ if (m_pContainer->dwFlags & CNT_CREATE_MINIMIZED || !newData->iActivate || m_pContainer->dwFlags & CNT_DEFERREDTABSELECT) {
+ dat->iFlashIcon = PluginConfig.g_IconMsgEvent;
+ SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL);
+ dat->mayFlashTab = true;
+
+ DBEVENTINFO dbei = { 0 };
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ FlashOnClist(hwndDlg, dat, dat->hDbEventFirst, &dbei);
+
+ SendMessage(hwndContainer, DM_SETICON, (WPARAM)dat, (LPARAM)LoadSkinnedIcon(SKINICON_EVENT_MESSAGE));
+ m_pContainer->dwFlags |= CNT_NEED_UPDATETITLE;
+ dat->dwFlags |= MWF_NEEDCHECKSIZE | MWF_WASBACKGROUNDCREATE | MWF_DEFERREDSCROLL;
+ }
+
+ if (newData->iActivate) {
+ m_pContainer->hwndActive = hwndDlg;
+ ShowWindow(hwndDlg, SW_SHOW);
+ SetActiveWindow(hwndDlg);
+ SetForegroundWindow(hwndDlg);
+ }
+ else if (m_pContainer->dwFlags & CNT_CREATE_MINIMIZED) {
+ dat->dwFlags |= MWF_DEFERREDSCROLL;
+ ShowWindow(hwndDlg, SW_SHOWNOACTIVATE);
+ m_pContainer->hwndActive = hwndDlg;
+ m_pContainer->dwFlags |= CNT_DEFERREDCONFIGURE;
+ }
+ PostMessage(hwndContainer, DM_UPDATETITLE, dat->hContact, 0);
+
+ DM_RecalcPictureSize(dat);
+ dat->dwLastActivity = GetTickCount() - 1000;
+ m_pContainer->dwLastActivity = dat->dwLastActivity;
+
+ if (dat->hwndHPP)
+ mir_subclassWindow(dat->hwndHPP, HPPKFSubclassProc);
+
+ dat->dwFlags &= ~MWF_INITMODE;
+ TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPEN, 0);
+
+ // show a popup if wanted...
+ if (newData->bWantPopup) {
+ DBEVENTINFO dbei = { sizeof(dbei) };
+ newData->bWantPopup = FALSE;
+ db_event_get(newData->hdbEvent, &dbei);
+ tabSRMM_ShowPopup(dat->hContact, newData->hdbEvent, dbei.eventType, 0, 0, hwndDlg, dat->cache->getActiveProto());
+ }
+ if (m_pContainer->dwFlags & CNT_CREATE_MINIMIZED) {
+ m_pContainer->dwFlags &= ~CNT_CREATE_MINIMIZED;
+ m_pContainer->hwndActive = hwndDlg;
+ return FALSE;
+ }
+ return newData->iActivate != 0;
+ }
+
+ case WM_ERASEBKGND:
+ RECT rcClient, rcWindow;
+ {
+ HDC hdc = (HDC)wParam;
+ HDC hdcMem = 0;
+ HBITMAP hbm, hbmOld;
+ HANDLE hpb = 0;
+
+ GetClientRect(hwndDlg, &rcClient);
+ DWORD cx = rcClient.right - rcClient.left;
+ DWORD cy = rcClient.bottom - rcClient.top;
+
+ if (CMimAPI::m_haveBufferedPaint) {
+ hpb = CMimAPI::m_pfnBeginBufferedPaint(hdc, &rcClient, BPBF_TOPDOWNDIB, 0, &hdcMem);
+ hbm = hbmOld = 0;
+ }
+ else {
+ hdcMem = CreateCompatibleDC(hdc);
+ hbm = CSkin::CreateAeroCompatibleBitmap(rcClient, hdc);
+ hbmOld = (HBITMAP)SelectObject(hdcMem, hbm);
+ }
+
+ bool bAero = M.isAero();
+
+ if (CSkin::m_skinEnabled) {
+ UINT item_ids[2] = { ID_EXTBKHISTORY, ID_EXTBKINPUTAREA };
+ UINT ctl_ids[2] = { IDC_LOG, IDC_MESSAGE };
+ BOOL isEditNotesReason = dat->fEditNotesActive;
+ BOOL isSendLaterReason = (dat->sendMode & SMODE_SENDLATER);
+ BOOL isMultipleReason = (dat->sendMode & SMODE_MULTIPLE || dat->sendMode & SMODE_CONTAINER);
+
+ CSkin::SkinDrawBG(hwndDlg, hwndContainer, m_pContainer, &rcClient, hdcMem);
+
+ for (int i = 0; i < 2; i++) {
+ CSkinItem *item = &SkinItems[item_ids[i]];
+ if (!item->IGNORED) {
+ GetWindowRect(GetDlgItem(hwndDlg, ctl_ids[i]), &rcWindow);
+ pt.x = rcWindow.left;
+ pt.y = rcWindow.top;
+ ScreenToClient(hwndDlg, &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;
+ if (item_ids[i] == ID_EXTBKINPUTAREA && (isMultipleReason || isEditNotesReason || isSendLaterReason)) {
+ HBRUSH br = CreateSolidBrush(isMultipleReason ? RGB(255, 130, 130) : (isEditNotesReason ? RGB(80, 255, 80) : RGB(80, 80, 255)));
+ FillRect(hdcMem, &rc, br);
+ DeleteObject(br);
+ }
+ else CSkin::DrawItem(hdcMem, &rc, item);
+ }
+ }
+ }
+ else {
+ CSkin::FillBack(hdcMem, &rcClient);
+
+ if (M.isAero()) {
+ LONG temp = rcClient.bottom;
+ rcClient.bottom = dat->Panel->isActive() ? dat->Panel->getHeight() + 5 : 5;
+ FillRect(hdcMem, &rcClient, (HBRUSH)GetStockObject(BLACK_BRUSH));
+ rcClient.bottom = temp;
+ }
+ }
+
+ // draw the (new) infopanel background. Use the gradient from the statusitem.
+ GetClientRect(hwndDlg, &rc);
+ dat->Panel->renderBG(hdcMem, rc, &SkinItems[ID_EXTBKINFOPANELBG], bAero);
+
+ // draw aero related stuff
+ if (!CSkin::m_skinEnabled)
+ CSkin::RenderToolbarBG(dat, hdcMem, rcClient);
+
+ // render info panel fields
+ dat->Panel->renderContent(hdcMem);
+
+ if (hpb)
+ CSkin::FinalizeBufferedPaint(hpb, &rcClient);
+ else {
+ BitBlt(hdc, 0, 0, cx, cy, hdcMem, 0, 0, SRCCOPY);
+ SelectObject(hdcMem, hbmOld);
+ DeleteObject(hbm);
+ DeleteDC(hdcMem);
+ }
+ if (!dat->fLimitedUpdate)
+ SetAeroMargins(dat->pContainer);
+ }
+ return 1;
+
+ case WM_NCPAINT:
+ return 0;
+
+ case WM_PAINT:
+ // in skinned mode only, draw the background elements for the 2 richedit controls
+ // this allows border-less textboxes to appear "skinned" and blended with the background
+ {
+ PAINTSTRUCT ps;
+ BeginPaint(hwndDlg, &ps);
+ EndPaint(hwndDlg, &ps);
+ }
+ return 0;
+
+ case WM_SIZE:
+ if (!IsIconic(hwndDlg)) {
+ if (dat->ipFieldHeight == 0)
+ dat->ipFieldHeight = CInfoPanel::m_ipConfig.height2;
+
+ if (dat->pContainer->uChildMinHeight > 0 && HIWORD(lParam) >= dat->pContainer->uChildMinHeight) {
+ if (dat->splitterY > HIWORD(lParam) - DPISCALEY_S(MINLOGHEIGHT)) {
+ dat->splitterY = HIWORD(lParam) - DPISCALEY_S(MINLOGHEIGHT);
+ dat->dynaSplitter = dat->splitterY - DPISCALEY_S(34);
+ DM_RecalcPictureSize(dat);
+ }
+ if (dat->splitterY < DPISCALEY_S(MINSPLITTERY))
+ LoadSplitter(dat);
+ }
+
+ HBITMAP hbm = ((dat->Panel->isActive()) && m_pContainer->avatarMode != 3) ? dat->hOwnPic : (dat->ace ? dat->ace->hbmPic : PluginConfig.g_hbmUnknown);
+ if (hbm != 0) {
+ BITMAP bminfo;
+ GetObject(hbm, sizeof(bminfo), &bminfo);
+ CalcDynamicAvatarSize(dat, &bminfo);
+ }
+
+ GetClientRect(hwndDlg, &rc);
+
+ UTILRESIZEDIALOG urd = { sizeof(urd) };
+ urd.hInstance = g_hInst;
+ urd.hwndDlg = hwndDlg;
+ urd.lParam = (LPARAM)dat;
+ urd.lpTemplate = MAKEINTRESOURCEA(IDD_MSGSPLITNEW);
+ urd.pfnResizer = MessageDialogResize;
+ CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd);
+
+ BB_SetButtonsPos(dat);
+
+ // size info panel fields
+ if (dat->Panel->isActive()) {
+ LONG cx = rc.right;
+ LONG panelHeight = dat->Panel->getHeight();
+
+ hbm = (m_pContainer->avatarMode == 3) ? dat->hOwnPic : (dat->ace ? dat->ace->hbmPic : PluginConfig.g_hbmUnknown);
+ double dHeight = 0, dWidth = 0;
+ Utils::scaleAvatarHeightLimited(hbm, dWidth, dHeight, panelHeight - 2);
+ dat->iPanelAvatarX = (int)dWidth;
+ dat->iPanelAvatarY = (int)dHeight;
+
+ rc.top = 1;
+ rc.left = cx - dat->iPanelAvatarX;
+ rc.bottom = panelHeight - (CSkin::m_bAvatarBorderType ? 2 : 0);
+ rc.right = cx;
+ dat->rcPic = rc;
+
+ if (dat->bShowInfoAvatar) {
+ SetWindowPos(dat->hwndPanelPicParent, HWND_TOP, rc.left - 2, rc.top, rc.right - rc.left, rc.bottom - rc.top + 1, 0);
+ ShowWindow(dat->hwndPanelPicParent, (dat->iPanelAvatarX == 0) || !dat->Panel->isActive() ? SW_HIDE : SW_SHOW);
+ }
+ else {
+ ShowWindow(dat->hwndPanelPicParent, SW_HIDE);
+ dat->iPanelAvatarX = dat->iPanelAvatarY = 0;
+ }
+
+ rc.right = cx - dat->iPanelAvatarX;
+ rc.left = rc.right - dat->panelStatusCX;
+ rc.bottom = panelHeight - 3;
+ rc.top = rc.bottom - dat->ipFieldHeight;
+ dat->rcStatus = rc;
+
+ rc.left = CInfoPanel::LEFT_OFFSET_LOGO;
+ rc.right = cx - dat->iPanelAvatarX - (panelHeight < CInfoPanel::DEGRADE_THRESHOLD ? (dat->rcStatus.right - dat->rcStatus.left) + 3 : 0);
+ rc.bottom = panelHeight - (panelHeight >= CInfoPanel::DEGRADE_THRESHOLD ? dat->ipFieldHeight : 0) - 1;
+ rc.top = 1;
+ dat->rcNick = rc;
+
+ rc.left = CInfoPanel::LEFT_OFFSET_LOGO;
+ rc.right = cx - (dat->iPanelAvatarX + 2) - dat->panelStatusCX;
+ rc.bottom = panelHeight - 3;
+ rc.top = rc.bottom - dat->ipFieldHeight;
+ dat->rcUIN = rc;
+
+ dat->Panel->Invalidate();
+ }
+
+ if (GetDlgItem(hwndDlg, IDC_CLIST) != 0) {
+ RECT rcLog;
+ GetClientRect(hwndDlg, &rcClient);
+ GetClientRect(GetDlgItem(hwndDlg, IDC_LOG), &rcLog);
+ rc.top = 0;
+ rc.right = rcClient.right;
+ rc.left = rcClient.right - dat->multiSplitterX;
+ rc.bottom = rcLog.bottom;
+ if (dat->Panel->isActive())
+ rc.top += (dat->Panel->getHeight() + 1);
+ MoveWindow(GetDlgItem(hwndDlg, IDC_CLIST), rc.left, rc.top, rc.right - rc.left, rcLog.bottom - rcLog.top, FALSE);
+ }
+
+ if (dat->hwndIEView || dat->hwndHPP)
+ ResizeIeView(dat);
+
+ DetermineMinHeight(dat);
+ }
+ break;
+
+ case WM_TIMECHANGE:
+ PostMessage(hwndDlg, DM_OPTIONSAPPLIED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ if (dat != 0 && ((NMHDR*)lParam)->hwndFrom == dat->hwndTip) {
+ if (((NMHDR*)lParam)->code == NM_CLICK)
+ SendMessage(dat->hwndTip, TTM_TRACKACTIVATE, FALSE, 0);
+ break;
+ }
+
+ switch (((NMHDR*)lParam)->idFrom) {
+ case IDC_LOG:
+ case IDC_MESSAGE:
+ switch (((NMHDR*)lParam)->code) {
+ case EN_MSGFILTER:
+ {
+ DWORD msg = ((MSGFILTER *)lParam)->msg;
+ WPARAM wp = ((MSGFILTER *)lParam)->wParam;
+ LPARAM lp = ((MSGFILTER *)lParam)->lParam;
+ CHARFORMAT2 cf2;
+ BOOL isCtrl, isShift, isAlt;
+ KbdState(dat, isShift, isCtrl, isAlt);
+
+ MSG message;
+ message.hwnd = hwndDlg;
+ message.message = msg;
+ message.lParam = lp;
+ message.wParam = wp;
+
+ if (msg == WM_SYSKEYUP) {
+ if (wp == VK_MENU)
+ if (!dat->fkeyProcessed && !(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000) && !(lp & (1 << 24)))
+ m_pContainer->MenuBar->autoShow();
+
+ return _dlgReturn(hwndDlg, 0);
+ }
+
+ if ((msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) && !(GetKeyState(VK_RMENU) & 0x8000)) {
+ LRESULT mim_hotkey_check = CallService(MS_HOTKEY_CHECK, (WPARAM)&message, (LPARAM)(TABSRMM_HK_SECTION_IM));
+ if (mim_hotkey_check)
+ dat->fkeyProcessed = true;
+
+ switch (mim_hotkey_check) {
+ case TABSRMM_HK_SETUSERPREFS:
+ CallService(MS_TABMSG_SETUSERPREFS, dat->hContact, 0);
return _dlgReturn(hwndDlg, 1);
- - case WM_MOUSEMOVE: - GetCursorPos(&pt); - DM_DismissTip(dat, pt); - dat->Panel->trackMouse(pt); - - HCURSOR hCur = GetCursor(); - if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE) || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE)) - SetCursor(LoadCursor(NULL, IDC_ARROW)); - break; - } - } - break; - - case EN_REQUESTRESIZE: - DM_HandleAutoSizeRequest(dat, (REQRESIZE *)lParam); - break; - - case EN_LINK: - ENLINK *pLink = (ENLINK*)lParam; - switch (pLink->msg) { - case WM_SETCURSOR: - SetCursor(PluginConfig.hCurHyperlinkHand); - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); - return TRUE; - - case WM_RBUTTONDOWN: - case WM_LBUTTONUP: - ptrT tszUrl(Utils::extractURLFromRichEdit((ENLINK*)lParam, GetDlgItem(hwndDlg, IDC_LOG))); - if (!IsStringValidLink(tszUrl)) - break; - - if (pLink->msg != WM_RBUTTONDOWN) { - CallService(MS_UTILS_OPENURL, OUF_TCHAR, tszUrl); - SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); - break; - } - HMENU hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)); - HMENU hSubMenu = GetSubMenu(hMenu, 1); - TranslateMenu(hSubMenu); - pt.x = (short)LOWORD(pLink->lParam); - pt.y = (short)HIWORD(pLink->lParam); - ClientToScreen(((NMHDR*)lParam)->hwndFrom, &pt); - switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) { - case IDM_OPENNEW: - CallService(MS_UTILS_OPENURL, OUF_NEWWINDOW | OUF_TCHAR, tszUrl); - break; - - case IDM_OPENEXISTING: - CallService(MS_UTILS_OPENURL, OUF_TCHAR, tszUrl); - break; - - case IDM_COPYLINK: - if (!OpenClipboard(hwndDlg)) - break; - - EmptyClipboard(); - HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(TCHAR)*(mir_tstrlen(tszUrl) + 1)); - TCHAR *buf = (TCHAR*)GlobalLock(hData); - mir_tstrcpy(buf, tszUrl); - GlobalUnlock(hData); - SetClipboardData(CF_UNICODETEXT, hData); - CloseClipboard(); - break; - } - DestroyMenu(hMenu); - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); - return TRUE; - } - } - } - break; - - case DM_TYPING: - { - int preTyping = dat->nTypeSecs != 0; - dat->nTypeSecs = (int)lParam > 0 ? (int)lParam : 0; - - if (dat->nTypeSecs) - dat->bShowTyping = 0; - - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, preTyping); - } - return TRUE; - - case DM_UPDATEWINICON: - if (dat->hXStatusIcon) { - DestroyIcon(dat->hXStatusIcon); - dat->hXStatusIcon = 0; - } - - if (LPCSTR szProto = dat->cache->getProto()) { - dat->hTabIcon = dat->hTabStatusIcon = MY_GetContactIcon(dat, "MetaiconTab"); - if (M.GetByte("use_xicons", 1)) - dat->hXStatusIcon = GetXStatusIcon(dat); - - SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, BUTTONSETASDIMMED, (dat->dwFlagsEx & MWF_SHOW_ISIDLE) != 0, 0); - SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, BM_SETIMAGE, IMAGE_ICON, (LPARAM)(dat->hXStatusIcon ? dat->hXStatusIcon : MY_GetContactIcon(dat, "MetaiconBar"))); - - if (m_pContainer->hwndActive == hwndDlg) - SendMessage(m_pContainer->hwnd, DM_SETICON, (WPARAM)dat, (LPARAM)(dat->hXStatusIcon ? dat->hXStatusIcon : dat->hTabIcon)); - - if (dat->pWnd) - dat->pWnd->updateIcon(dat->hXStatusIcon ? dat->hXStatusIcon : dat->hTabIcon); - } - return 0; - - // configures the toolbar only... if lParam != 0, then it also calls - // SetDialogToType() to reconfigure the message window - case DM_CONFIGURETOOLBAR: - dat->bShowUIElements = m_pContainer->dwFlags & CNT_HIDETOOLBAR ? 0 : 1; - - SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTER), GWL_EXSTYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTER), GWL_EXSTYLE) & ~WS_EX_STATICEDGE); - - if (lParam == 1) { - GetSendFormat(dat); - SetDialogToType(hwndDlg); - } - - if (lParam == 1) { - DM_RecalcPictureSize(dat); - SendMessage(hwndDlg, WM_SIZE, 0, 0); - DM_ScrollToBottom(dat, 0, 1); - } - return 0; - - case DM_LOADBUTTONBARICONS: - for (int i=0; i < SIZEOF(buttonicons); i++) { - SendDlgItemMessage(hwndDlg, buttonicons[i].id, BM_SETIMAGE, IMAGE_ICON, (LPARAM)*buttonicons[i].pIcon); - SendDlgItemMessage(hwndDlg, buttonicons[i].id, BUTTONSETCONTAINER, (LPARAM)m_pContainer, 0); - } - - BB_UpdateIcons(hwndDlg); - SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0); - return 0; - - case DM_OPTIONSAPPLIED: - DM_OptionsApplied(dat, wParam, lParam); - return 0; - - case DM_UPDATETITLE: - DM_UpdateTitle(dat, wParam, lParam); - return 0; - - case DM_UPDATESTATUSMSG: - dat->Panel->Invalidate(); - return 0; - - case DM_OWNNICKCHANGED: - GetMyNick(dat); - return 0; - - case DM_ADDDIVIDER: - if (!(dat->dwFlags & MWF_DIVIDERSET) && PluginConfig.m_bUseDividers) { - if (GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOG)) > 0) { - dat->dwFlags |= MWF_DIVIDERWANTED; - dat->dwFlags |= MWF_DIVIDERSET; - } - } - return 0; - - case WM_SETFOCUS: - MsgWindowUpdateState(dat, WM_SETFOCUS); - SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); - return 1; - - case WM_ACTIVATE: - if (LOWORD(wParam) != WA_ACTIVE) - break; - - //fall through - case WM_MOUSEACTIVATE: - MsgWindowUpdateState(dat, WM_ACTIVATE); - return 1; - - case DM_UPDATEPICLAYOUT: - LoadContactAvatar(dat); - SendMessage(hwndDlg, WM_SIZE, 0, 0); - return 0; - - case DM_SPLITTERGLOBALEVENT: - DM_SplitterGlobalEvent(dat, wParam, lParam); - return 0; - - case DM_SPLITTERMOVED: - if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_MULTISPLITTER)) { - GetClientRect(hwndDlg, &rc); - pt.x = wParam; - pt.y = 0; - ScreenToClient(hwndDlg, &pt); - int oldSplitterX = dat->multiSplitterX; - dat->multiSplitterX = rc.right - pt.x; - if (dat->multiSplitterX < 25) - dat->multiSplitterX = 25; - - if (dat->multiSplitterX > ((rc.right - rc.left) - 80)) - dat->multiSplitterX = oldSplitterX; - SendMessage(dat->hwnd, WM_SIZE, 0, 0); - } - else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SPLITTER)) { - GetClientRect(hwndDlg, &rc); - rc.top += (dat->Panel->isActive() ? dat->Panel->getHeight() + 40 : 30); - pt.x = 0; - pt.y = wParam; - ScreenToClient(hwndDlg, &pt); - - int oldSplitterY = dat->splitterY; - int oldDynaSplitter = dat->dynaSplitter; - - dat->splitterY = rc.bottom - pt.y + DPISCALEY_S(23); - - // attempt to fix splitter troubles.. - // hardcoded limits... better solution is possible, but this works for now - int bottomtoolbarH = 0; - if (dat->pContainer->dwFlags & CNT_BOTTOMTOOLBAR) - bottomtoolbarH = 22; - - if (dat->splitterY < (DPISCALEY_S(MINSPLITTERY) + 5 + bottomtoolbarH)) { // min splitter size - dat->splitterY = (DPISCALEY_S(MINSPLITTERY) + 5 + bottomtoolbarH); - dat->dynaSplitter = dat->splitterY - DPISCALEY_S(34); - DM_RecalcPictureSize(dat); - } - else if (dat->splitterY > (rc.bottom - rc.top)) { - dat->splitterY = oldSplitterY; - dat->dynaSplitter = oldDynaSplitter; - DM_RecalcPictureSize(dat); - } - else { - dat->dynaSplitter = (rc.bottom - pt.y) - DPISCALEY_S(11); - DM_RecalcPictureSize(dat); - } - CSkin::UpdateToolbarBG(dat); - SendMessage(dat->hwnd, WM_SIZE, 0, 0); - } - else if ((HWND) lParam == GetDlgItem(hwndDlg, IDC_PANELSPLITTER)) { - GetClientRect(GetDlgItem(hwndDlg, IDC_LOG), &rc); - - POINT pt = { 0, wParam }; - ScreenToClient(hwndDlg, &pt); - if ((pt.y + 2 >= MIN_PANELHEIGHT + 2) && (pt.y + 2 < 100) && (pt.y + 2 < rc.bottom - 30)) - dat->Panel->setHeight(pt.y + 2, true); - - RedrawWindow(hwndDlg, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); - if (M.isAero()) - InvalidateRect(GetParent(hwndDlg), NULL, FALSE); - } - break; - - // queue a dm_remakelog - // wParam = hwnd of the sender, so we can directly do a DM_REMAKELOG if the msg came - // from ourself. otherwise, the dm_remakelog will be deferred until next window - // activation (focus) - case DM_DEFERREDREMAKELOG: - if ((HWND) wParam == hwndDlg) - SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); - else { - if (M.GetByte(dat->hContact, "mwoverride", 0) == 0) { - dat->dwFlags &= ~(MWF_LOG_ALL); - dat->dwFlags |= (lParam & MWF_LOG_ALL); - dat->dwFlags |= MWF_DEFERREDREMAKELOG; - } - } - return 0; - - case DM_FORCEDREMAKELOG: - if ((HWND) wParam == hwndDlg) - SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); - else { - dat->dwFlags &= ~(MWF_LOG_ALL); - dat->dwFlags |= (lParam & MWF_LOG_ALL); - dat->dwFlags |= MWF_DEFERREDREMAKELOG; - } - return 0; - - case DM_REMAKELOG: - dat->szMicroLf[0] = 0; - dat->lastEventTime = 0; - dat->iLastEventType = -1; - StreamInEvents(hwndDlg, dat->hDbEventFirst, -1, 0, NULL); - return 0; - - case DM_APPENDMCEVENT: - if (dat->hContact == db_mc_getMeta(wParam) && dat->hDbEventFirst == NULL) { - dat->hDbEventFirst = lParam; - SendMessage(dat->hwnd, DM_REMAKELOG, 0, 0); - } - else if (dat->hContact == wParam && db_mc_isSub(wParam) && db_event_getContact(lParam) != wParam) - StreamInEvents(hwndDlg, lParam, 1, 1, NULL); - return 0; - - case DM_APPENDTOLOG: - StreamInEvents(hwndDlg, wParam, 1, 1, NULL); - return 0; - - // replays queued events after the message log has been frozen for a while - case DM_REPLAYQUEUE: - for (int i=0; i < dat->iNextQueuedEvent; i++) - if (dat->hQueuedEvents[i] != 0) - StreamInEvents(hwndDlg, dat->hQueuedEvents[i], 1, 1, NULL); - - dat->iNextQueuedEvent = 0; - SetDlgItemText(hwndDlg, IDC_LOGFROZENTEXT, dat->bNotOnList ? TranslateT("Contact not on list. You may add it...") : - TranslateT("Auto scrolling is disabled (press F12 to enable it)")); - return 0; - - case DM_SCROLLIEVIEW: - { - IEVIEWWINDOW iew = { sizeof(iew) }; - iew.iType = IEW_SCROLLBOTTOM; - if (dat->hwndIEView) { - iew.hwnd = dat->hwndIEView; - CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&iew); - } - else if (dat->hwndHPP) { - iew.hwnd = dat->hwndHPP; - CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)&iew); - } - } - return 0; - - case HM_DBEVENTADDED: - // this is called whenever a new event has been added to the database. - // this CAN be posted (some sanity checks required). - if (dat && dat->hContact) - DM_EventAdded(dat, dat->hContact, lParam); - return 0; - - case WM_TIMER: - // timer to control info panel hovering - if (wParam == TIMERID_AWAYMSG) { - KillTimer(hwndDlg, wParam); - GetCursorPos(&pt); - - if (wParam == TIMERID_AWAYMSG && dat->Panel->hitTest(pt) != CInfoPanel::HTNIRVANA) - SendMessage(hwndDlg, DM_ACTIVATETOOLTIP, 0, 0); - else - dat->dwFlagsEx &= ~MWF_SHOW_AWAYMSGTIMER; - break; - } - - // timer id for message timeouts is composed like: - // for single message sends: basevalue (TIMERID_MSGSEND) + send queue index - if (wParam >= TIMERID_MSGSEND) { - int iIndex = wParam - TIMERID_MSGSEND; - if (iIndex < SendQueue::NR_SENDJOBS) { // single sendjob timer - SendJob *job = sendQueue->getJobByIndex(iIndex); - KillTimer(hwndDlg, wParam); - mir_sntprintf(job->szErrorMsg, SIZEOF(job->szErrorMsg), TranslateT("Delivery failure: %s"), - TranslateT("The message send timed out")); - job->iStatus = SendQueue::SQ_ERROR; - if (!nen_options.iNoSounds && !(m_pContainer->dwFlags & CNT_NOSOUND)) - SkinPlaySound("SendError"); - if (!(dat->dwFlags & MWF_ERRORSTATE)) - sendQueue->handleError(dat, iIndex); - break; - } - } - else if (wParam == TIMERID_FLASHWND) { - if (dat->mayFlashTab) - FlashTab(dat, hwndTab, dat->iTabID, &dat->bTabFlash, TRUE, dat->hTabIcon); - break; - } - else if (wParam == TIMERID_TYPE) { - DM_Typing(dat); - break; - } - break; - - case DM_ERRORDECIDED: - switch (wParam) { - case MSGERROR_CANCEL: - case MSGERROR_SENDLATER: - if (dat->dwFlags & MWF_ERRORSTATE) { - dat->cache->saveHistory(0, 0); - if (wParam == MSGERROR_SENDLATER) - sendQueue->doSendLater(dat->iCurrentQueueError, dat); // to be implemented at a later time - dat->iOpenJobs--; - sendQueue->dec(); - if (dat->iCurrentQueueError >= 0 && dat->iCurrentQueueError < SendQueue::NR_SENDJOBS) - sendQueue->clearJob(dat->iCurrentQueueError); - dat->iCurrentQueueError = -1; - sendQueue->showErrorControls(dat, FALSE); - if (wParam != MSGERROR_CANCEL || (wParam == MSGERROR_CANCEL && lParam == 0)) - SetDlgItemText(hwndDlg, IDC_MESSAGE, _T("")); - sendQueue->checkQueue(dat); - int iNextFailed = sendQueue->findNextFailed(dat); - if (iNextFailed >= 0) - sendQueue->handleError(dat, iNextFailed); - } - break; - - case MSGERROR_RETRY: - if (dat->dwFlags & MWF_ERRORSTATE) { - int resent = 0; - - dat->cache->saveHistory(0, 0); - if (dat->iCurrentQueueError >= 0 && dat->iCurrentQueueError < SendQueue::NR_SENDJOBS) { - SendJob *job = sendQueue->getJobByIndex(dat->iCurrentQueueError); - if (job->hSendId == 0 && job->hContact == 0) - break; - - job->hSendId = (HANDLE)CallContactService(job->hContact, PSS_MESSAGE, - (dat->sendMode & SMODE_FORCEANSI) ? (job->dwFlags & ~PREF_UNICODE) : job->dwFlags, (LPARAM)job->szSendBuffer); - resent++; - } - - if (resent) { - SendJob *job = sendQueue->getJobByIndex(dat->iCurrentQueueError); - - SetTimer(hwndDlg, TIMERID_MSGSEND + dat->iCurrentQueueError, PluginConfig.m_MsgTimeout, NULL); - job->iStatus = SendQueue::SQ_INPROGRESS; - dat->iCurrentQueueError = -1; - sendQueue->showErrorControls(dat, FALSE); - SetDlgItemText(hwndDlg, IDC_MESSAGE, _T("")); - sendQueue->checkQueue(dat); - - int iNextFailed = sendQueue->findNextFailed(dat); - if (iNextFailed >= 0) - sendQueue->handleError(dat, iNextFailed); - } - } - } - break; - - case DM_SELECTTAB: - SendMessage(hwndContainer, DM_SELECTTAB, wParam, lParam); // pass the msg to our container - return 0; - - case DM_SETLOCALE: - if (dat->dwFlags & MWF_WASBACKGROUNDCREATE) - break; - if (m_pContainer->hwndActive == hwndDlg && PluginConfig.m_bAutoLocaleSupport && hwndContainer == GetForegroundWindow() && hwndContainer == GetActiveWindow()) { - if (lParam) - dat->hkl = (HKL)lParam; - - if (dat->hkl) - ActivateKeyboardLayout(dat->hkl, 0); - } - return 0; - - // return timestamp (in ticks) of last recent message which has not been read yet. - // 0 if there is none - // lParam = pointer to a dword receiving the value. - case DM_QUERYLASTUNREAD: - { - DWORD *pdw = (DWORD *)lParam; - if (pdw) - *pdw = dat->dwTickLastEvent; - } - return 0; - - case DM_QUERYCONTAINER: - { - TContainerData **pc = (TContainerData **)lParam; - if (pc) - *pc = m_pContainer; - } - return 0; - - case DM_QUERYHCONTACT: - { - MCONTACT *phContact = (MCONTACT*)lParam; - if (phContact) - *phContact = dat->hContact; - } - return 0; - - case DM_UPDATELASTMESSAGE: - DM_UpdateLastMessage(dat); - return 0; - - case DM_SAVESIZE: - if (dat->dwFlags & MWF_NEEDCHECKSIZE) - lParam = 0; - - dat->dwFlags &= ~MWF_NEEDCHECKSIZE; - if (dat->dwFlags & MWF_WASBACKGROUNDCREATE) { - dat->dwFlags &= ~MWF_INITMODE; - if (dat->lastMessage) - DM_UpdateLastMessage(dat); - } - - SendMessage(hwndContainer, DM_QUERYCLIENTAREA, 0, (LPARAM)&rcClient); - MoveWindow(hwndDlg, rcClient.left, rcClient.top, (rcClient.right - rcClient.left), (rcClient.bottom - rcClient.top), TRUE); - if (dat->dwFlags & MWF_WASBACKGROUNDCREATE) { - dat->dwFlags &= ~MWF_WASBACKGROUNDCREATE; - SendMessage(hwndDlg, WM_SIZE, 0, 0); - PostMessage(hwndDlg, DM_UPDATEPICLAYOUT, 0, 0); - if (PluginConfig.m_bAutoLocaleSupport) { - if (dat->hkl == 0) - DM_LoadLocale(dat); - else - PostMessage(hwndDlg, DM_SETLOCALE, 0, 0); - } - if (dat->hwndIEView != 0) - SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); - if (dat->pContainer->dwFlags & CNT_SIDEBAR) - dat->pContainer->SideBar->Layout(); - } - else { - SendMessage(hwndDlg, WM_SIZE, 0, 0); - if (lParam == 0) - DM_ScrollToBottom(dat, 0, 1); - } - return 0; - - case DM_CHECKSIZE: - dat->dwFlags |= MWF_NEEDCHECKSIZE; - return 0; - - // sent by the message input area hotkeys. just pass it to our container - case DM_QUERYPENDING: - SendMessage(hwndContainer, DM_QUERYPENDING, wParam, lParam); - return 0; - - case WM_LBUTTONDOWN: - GetCursorPos(&tmp); - cur.x = (SHORT)tmp.x; - cur.y = (SHORT)tmp.y; - if (!dat->Panel->isHovered()) - SendMessage(hwndContainer, WM_NCLBUTTONDOWN, HTCAPTION, *((LPARAM*)(&cur))); - break; - - case WM_LBUTTONUP: - GetCursorPos(&tmp); - if (dat->Panel->isHovered()) - dat->Panel->handleClick(tmp); - else { - cur.x = (SHORT)tmp.x; - cur.y = (SHORT)tmp.y; - SendMessage(hwndContainer, WM_NCLBUTTONUP, HTCAPTION, *((LPARAM*)(&cur))); - } - break; - - case WM_RBUTTONUP: - { - RECT rcPicture, rcPanelNick = { 0 }; - int menuID = 0; - - GetWindowRect(GetDlgItem(hwndDlg, IDC_CONTACTPIC), &rcPicture); - rcPanelNick.left = rcPanelNick.right - 30; - GetCursorPos(&pt); - - if (dat->Panel->invokeConfigDialog(pt)) - break; - - if (PtInRect(&rcPicture, pt)) - menuID = MENU_PICMENU; - - if ((menuID == MENU_PICMENU && ((dat->ace ? dat->ace->hbmPic : PluginConfig.g_hbmUnknown) || dat->hOwnPic) && dat->bShowAvatar != 0)) { - HMENU submenu = GetSubMenu(m_pContainer->hMenuContext, menuID == MENU_PICMENU ? 1 : 11); - GetCursorPos(&pt); - MsgWindowUpdateMenu(dat, submenu, menuID); - int iSelection = TrackPopupMenu(submenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL); - MsgWindowMenuHandler(dat, iSelection, menuID); - break; - } - - HMENU subMenu = GetSubMenu(m_pContainer->hMenuContext, 0); - MsgWindowUpdateMenu(dat, subMenu, MENU_TABCONTEXT); - - int iSelection = TrackPopupMenu(subMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL); - if (iSelection >= IDM_CONTAINERMENU) { - char szIndex[10]; - char *szKey = "TAB_ContainersW"; - - mir_snprintf(szIndex, SIZEOF(szIndex), "%d", iSelection - IDM_CONTAINERMENU); - if (iSelection - IDM_CONTAINERMENU >= 0) { - ptrT val(db_get_tsa(NULL, szKey, szIndex)); - if (val) - SendMessage(hwndDlg, DM_CONTAINERSELECTED, 0, (LPARAM)val); - } - break; - } - MsgWindowMenuHandler(dat, iSelection, MENU_TABCONTEXT); - } - break; - - case WM_MOUSEMOVE: - GetCursorPos(&pt); - DM_DismissTip(dat, pt); - dat->Panel->trackMouse(pt); - break; - - case WM_MEASUREITEM: - { - LPMEASUREITEMSTRUCT lpmi = (LPMEASUREITEMSTRUCT) lParam; - if (dat->Panel->isHovered()) { - lpmi->itemHeight = 0; - lpmi->itemWidth = 6; - return TRUE; - } - } - return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); - - case WM_NCHITTEST: - SendMessage(hwndContainer, WM_NCHITTEST, wParam, lParam); - break; - - case WM_DRAWITEM: - return MsgWindowDrawHandler(wParam, lParam, dat); - - case WM_APPCOMMAND: - { - DWORD cmd = GET_APPCOMMAND_LPARAM(lParam); - if (cmd == APPCOMMAND_BROWSER_BACKWARD || cmd == APPCOMMAND_BROWSER_FORWARD) { - SendMessage(hwndContainer, DM_SELECTTAB, cmd == APPCOMMAND_BROWSER_BACKWARD ? DM_SELECT_PREV : DM_SELECT_NEXT, 0); - return 1; - } - } - break; - - case WM_COMMAND: - if (!dat) - break; - - // custom button handling - if (LOWORD(wParam) >= MIN_CBUTTONID && LOWORD(wParam) <= MAX_CBUTTONID) { - BB_CustomButtonClick(dat, LOWORD(wParam), GetDlgItem(hwndDlg, LOWORD(wParam)), 0); - break; - } - - switch (LOWORD(wParam)) { - case IDOK: - if (dat->fEditNotesActive) { - SendMessage(hwndDlg, 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")); - return 0; - } - else { - // don't parse text formatting when the message contains curly braces - these are used by the rtf syntax - // and the parser currently cannot handle them properly in the text - XXX needs to be fixed later. - FINDTEXTEXA fi = { 0 }; - fi.chrg.cpMin = 0; - fi.chrg.cpMax = -1; - fi.lpstrText = "{"; - int final_sendformat = SendDlgItemMessageA(hwndDlg, IDC_MESSAGE, EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi) == -1 ? dat->SendFormat : 0; - fi.lpstrText = "}"; - final_sendformat = SendDlgItemMessageA(hwndDlg, IDC_MESSAGE, EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi) == -1 ? final_sendformat : 0; - - if (GetSendButtonState(hwndDlg) == PBS_DISABLED) - break; - - ptrA streamOut(Message_GetFromStream(GetDlgItem(hwndDlg, IDC_MESSAGE), final_sendformat ? 0 : SF_TEXT)); - if (streamOut == NULL) - break; - - CMString decoded(ptrT(mir_utf8decodeT(streamOut))); - if (decoded.IsEmpty()) - break; - - char *utfResult = NULL; - if (final_sendformat) - DoRtfToTags(dat, decoded, SIZEOF(rtfDefColors), rtfDefColors); - decoded.Trim(); - int bufSize = WideCharToMultiByte(dat->codePage, 0, decoded, -1, dat->sendBuffer, 0, 0, 0); - - size_t memRequired = 0; - int flags = 0; - if (!IsUtfSendAvailable(dat->hContact)) { - flags |= PREF_UNICODE; - memRequired = bufSize + (mir_wstrlen(decoded) + 1) * sizeof(WCHAR); - } - else { - flags |= PREF_UTF; - utfResult = mir_utf8encodeT(decoded); - memRequired = strlen(utfResult) + 1; - } - - // try to detect RTL - HWND hwndEdit = GetDlgItem(hwndDlg, IDC_MESSAGE); - 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); - if (pf2.wEffects & PFE_RTLPARA) - if (SendQueue::RTL_Detect(decoded)) - flags |= PREF_RTL; - - SendMessage(hwndEdit, WM_SETREDRAW, TRUE, 0); - SendMessage(hwndEdit, EM_SETSEL, -1, -1); - InvalidateRect(hwndEdit, NULL, FALSE); - - if (memRequired > dat->iSendBufferSize) { - dat->sendBuffer = (char *)mir_realloc(dat->sendBuffer, memRequired); - dat->iSendBufferSize = memRequired; - } - if (utfResult) { - memcpy(dat->sendBuffer, utfResult, memRequired); - mir_free(utfResult); - } - else { - WideCharToMultiByte(dat->codePage, 0, decoded, -1, dat->sendBuffer, bufSize, 0, 0); - if (flags & PREF_UNICODE) - memcpy(&dat->sendBuffer[bufSize], decoded, (mir_wstrlen(decoded) + 1) * sizeof(WCHAR)); - } - - if (memRequired == 0 || dat->sendBuffer[0] == 0) - break; - - if (dat->sendMode & SMODE_CONTAINER && m_pContainer->hwndActive == hwndDlg && GetForegroundWindow() == hwndContainer) { - int tabCount = TabCtrl_GetItemCount(hwndTab); - ptrA szFromStream(Message_GetFromStream(GetDlgItem(hwndDlg, IDC_MESSAGE), dat->SendFormat ? 0 : SF_TEXT)); - - TCITEM tci = { 0 }; - tci.mask = TCIF_PARAM; - for (int i=0; i < tabCount; i++) { - TabCtrl_GetItem(hwndTab, i, &tci); - // get the contact from the tabs lparam which hopefully is the tabs hwnd so we can get its userdata.... hopefully - HWND contacthwnd = (HWND)tci.lParam; - 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 != hwndDlg) { - SETTEXTEX stx = {ST_DEFAULT, CP_UTF8}; - // send the buffer to the contacts msg typing area - SendDlgItemMessage(contacthwnd, IDC_MESSAGE, EM_SETTEXTEX, (WPARAM)&stx, (LPARAM)szFromStream); - SendMessage(contacthwnd, WM_COMMAND, IDOK, 0); - } - } - } - } - // END /all /MOD - if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) - DM_NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); - - DeletePopupsForContact(dat->hContact, PU_REMOVE_ON_SEND); - if (M.GetByte("allow_sendhook", 0)) { - int result = TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CUSTOM, MAKELONG(flags, tabMSG_WINDOW_EVT_CUSTOM_BEFORESEND)); - if (result) - return TRUE; - } - sendQueue->addTo(dat, memRequired, flags); - } - return TRUE; - - case IDC_QUOTE: - { - int iCharsPerLine = M.GetDword("quoteLineLength", 64); - CHARRANGE sel; - SETTEXTEX stx = {ST_SELECTION, 1200}; - - MEVENT hDBEvent = 0; - if (dat->hwndIEView || dat->hwndHPP) { // IEView quoting support.. - TCHAR *selected = 0, *szQuoted = 0; - - IEVIEWEVENT event = { sizeof(event) }; - event.hContact = dat->hContact; - event.dwFlags = 0; - event.iType = IEE_GET_SELECTION; - - if (dat->hwndIEView) { - event.hwnd = dat->hwndIEView; - selected = (TCHAR*)CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&event); - } - else { - event.hwnd = dat->hwndHPP; - selected = (TCHAR*)CallService(MS_HPP_EG_EVENT, 0, (LPARAM)&event); - } - - if (selected != NULL) { - szQuoted = QuoteText(selected, iCharsPerLine, 0); - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETTEXTEX, (WPARAM)&stx, (LPARAM)szQuoted); - if (szQuoted) - mir_free(szQuoted); - break; - } - else { - hDBEvent = db_event_last(dat->hContact); - goto quote_from_last; - } - } - hDBEvent = dat->hDbEventLast; - -quote_from_last: - if (hDBEvent == NULL) - break; - - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXGETSEL, 0, (LPARAM)&sel); - if (sel.cpMin == sel.cpMax) { - DBEVENTINFO dbei = { sizeof(dbei) }; - dbei.cbBlob = db_event_getBlobSize(hDBEvent); - TCHAR *szText = (TCHAR*)mir_alloc((dbei.cbBlob + 1) * sizeof(TCHAR)); //URLs are made one char bigger for crlf - dbei.pBlob = (BYTE*)szText; - db_event_get(hDBEvent, &dbei); - int iSize = int(strlen((char*)dbei.pBlob)) + 1; - - bool iAlloced = false; - TCHAR *szConverted; - if (dbei.flags & DBEF_UTF) { - szConverted = mir_utf8decodeW((char*)szText); - iAlloced = true; - } - else { - if (iSize != (int)dbei.cbBlob) - szConverted = (TCHAR*)&dbei.pBlob[iSize]; - else { - szConverted = (TCHAR*)mir_alloc(sizeof(TCHAR) * iSize); - iAlloced = true; - MultiByteToWideChar(CP_ACP, 0, (char*)dbei.pBlob, -1, szConverted, iSize); - } - } - if (dbei.eventType == EVENTTYPE_FILE) { - size_t iDescr = mir_strlen((char *)(szText + sizeof(DWORD))); - memmove(szText, szText + sizeof(DWORD), iDescr); - memmove(szText + iDescr + 2, szText + sizeof(DWORD)+iDescr, dbei.cbBlob - iDescr - sizeof(DWORD)-1); - szText[iDescr] = '\r'; - szText[iDescr + 1] = '\n'; - szConverted = (TCHAR*)mir_alloc(sizeof(TCHAR)* (1 + mir_strlen((char *)szText))); - MultiByteToWideChar(CP_ACP, 0, (char *)szText, -1, szConverted, 1 + (int)mir_strlen((char *)szText)); - iAlloced = true; - } - ptrT szQuoted(QuoteText(szConverted, iCharsPerLine, 0)); - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETTEXTEX, (WPARAM)&stx, (LPARAM)szQuoted); - mir_free(szText); - if (iAlloced) - mir_free(szConverted); - } - else { - ptrA szFromStream(Message_GetFromStream(GetDlgItem(hwndDlg, IDC_LOG), SF_TEXT | SFF_SELECTION)); - ptrW converted(mir_utf8decodeW(szFromStream)); - Utils::FilterEventMarkers(converted); - ptrT szQuoted(QuoteText(converted, iCharsPerLine, 0)); - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETTEXTEX, (WPARAM)&stx, (LPARAM)szQuoted); - } - SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); - } - break; - - case IDC_ADD: - { - ADDCONTACTSTRUCT acs = { 0 }; - acs.hContact = dat->hContact; - acs.handleType = HANDLE_CONTACT; - acs.szProto = 0; - CallService(MS_ADDCONTACT_SHOW, (WPARAM)hwndDlg, (LPARAM)&acs); - if (!db_get_b(dat->hContact, "CList", "NotOnList", 0)) { - dat->bNotOnList = FALSE; - ShowMultipleControls(hwndDlg, addControls, 2, SW_HIDE); - if (!(dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED)) - Utils::showDlgControl(hwndDlg, IDC_LOGFROZENTEXT, SW_HIDE); - SendMessage(hwndDlg, WM_SIZE, 0, 0); - } - } - break; - - case IDC_CANCELADD: - dat->bNotOnList = FALSE; - ShowMultipleControls(hwndDlg, addControls, 2, SW_HIDE); - if (!(dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED)) - Utils::showDlgControl(hwndDlg, IDC_LOGFROZENTEXT, SW_HIDE); - SendMessage(hwndDlg, WM_SIZE, 0, 0); - break; - - case IDC_MESSAGE: - if (HIWORD(wParam) == EN_CHANGE) { - if (m_pContainer->hwndActive == hwndDlg) - UpdateReadChars(dat); - dat->dwFlags |= MWF_NEEDHISTORYSAVE; - dat->dwLastActivity = GetTickCount(); - m_pContainer->dwLastActivity = dat->dwLastActivity; - SendQueue::UpdateSaveAndSendButton(dat); - if (!(GetKeyState(VK_CONTROL) & 0x8000)) { - dat->nLastTyping = GetTickCount(); - if (GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE))) { - if (dat->nTypeMode == PROTOTYPE_SELFTYPING_OFF) { - if (!(dat->dwFlags & MWF_INITMODE)) - DM_NotifyTyping(dat, PROTOTYPE_SELFTYPING_ON); - } - } - else if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) - DM_NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); - } - } - break; - - default: - Utils::CmdDispatcher(Utils::CMD_MSGDIALOG, hwndDlg, LOWORD(wParam), wParam, lParam, dat, m_pContainer); - break; - } - break; - - case WM_CONTEXTMENU: - { - DWORD idFrom = GetDlgCtrlID((HWND)wParam); - if (idFrom >= MIN_CBUTTONID && idFrom <= MAX_CBUTTONID) { - BB_CustomButtonClick(dat, idFrom, (HWND)wParam, 1); - break; - } - } - break; - - // this is now *only* called from the global ME_PROTO_ACK handler (static int ProtoAck() in msgs.c) - // it receives: - // wParam = index of the sendjob in the queue in the low word, index of the found sendID in the high word - // (normally 0, but if its a multisend job, then the sendjob may contain more than one hContact/hSendId pairs.) - // lParam = the original ackdata - // - // the "per message window" ACK hook is gone, the global ack handler cares about all types of ack's (currently - // *_MESSAGE and *_AVATAR and dispatches them to the owner windows). - case HM_EVENTSENT: - sendQueue->ackMessage(dat, wParam, lParam); - return 0; - - case DM_ACTIVATEME: - ActivateExistingTab(m_pContainer, hwndDlg); - return 0; - - // sent by the select container dialog box when a container was selected... - // lParam = (TCHAR*)selected name... - case DM_CONTAINERSELECTED: - { - TCHAR *szNewName = (TCHAR*)lParam; - if (!_tcscmp(szNewName, TranslateT("Default container"))) - szNewName = CGlobals::m_default_container_name; - - int iOldItems = TabCtrl_GetItemCount(hwndTab); - if (!_tcsncmp(m_pContainer->szName, szNewName, CONTAINER_NAMELEN)) - break; - - TContainerData *pNewContainer = FindContainerByName(szNewName); - if (pNewContainer == NULL) - if ((pNewContainer = CreateContainer(szNewName, FALSE, dat->hContact)) == NULL) - break; - - db_set_ts(dat->hContact, SRMSGMOD_T, "containerW", szNewName); - dat->fIsReattach = TRUE; - PostMessage(PluginConfig.g_hwndHotkeyHandler, DM_DOCREATETAB, (WPARAM)pNewContainer, dat->hContact); - if (iOldItems > 1) // there were more than 1 tab, container is still valid - SendMessage(m_pContainer->hwndActive, WM_SIZE, 0, 0); - SetForegroundWindow(pNewContainer->hwnd); - SetActiveWindow(pNewContainer->hwnd); - } - break; - - case DM_STATUSBARCHANGED: - UpdateStatusBar(dat); - return 0; - - case DM_UINTOCLIPBOARD: - Utils::CopyToClipBoard(dat->cache->getUIN(), hwndDlg); - return 0; - - // broadcasted when GLOBAL info panel setting changes - case DM_SETINFOPANEL: - CInfoPanel::setPanelHandler(dat, wParam, lParam); - return 0; - - // 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 - case DM_ACTIVATETOOLTIP: - if (IsIconic(hwndContainer) || m_pContainer->hwndActive != hwndDlg) - break; - - dat->Panel->showTip(wParam, lParam); - break; - - case WM_NEXTDLGCTL: - if (dat->dwFlags & MWF_WASBACKGROUNDCREATE) - return 1; - break; - - // save the contents of the log as rtf file - case DM_SAVEMESSAGELOG: - DM_SaveLogAsRTF(dat); - return 0; - - case DM_CHECKAUTOHIDE: - DM_CheckAutoHide(dat, wParam, lParam); - return 0; - - case DM_IEVIEWOPTIONSCHANGED: - if (dat->hwndIEView) - SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); - break; - - case DM_SMILEYOPTIONSCHANGED: - ConfigureSmileyButton(dat); - SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); - break; - - case DM_MYAVATARCHANGED: - { - const char *szProto = dat->cache->getActiveProto(); - if (!strcmp((char *)wParam, szProto) && mir_strlen(szProto) == mir_strlen((char *)wParam)) - LoadOwnAvatar(dat); - } - break; - - case DM_GETWINDOWSTATE: - { - UINT state = MSG_WINDOW_STATE_EXISTS; - if (IsWindowVisible(hwndDlg)) - state |= MSG_WINDOW_STATE_VISIBLE; - if (GetForegroundWindow() == hwndContainer) - state |= MSG_WINDOW_STATE_FOCUS; - if (IsIconic(hwndContainer)) - state |= MSG_WINDOW_STATE_ICONIC; - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, state); - } - return TRUE; - - case DM_CLIENTCHANGED: - GetClientIcon(dat); - if (dat->hClientIcon && dat->Panel->isActive()) - InvalidateRect(hwndDlg, NULL, TRUE); - return 0; - - case DM_UPDATEUIN: - if (dat->Panel->isActive()) - dat->Panel->Invalidate(); - if (dat->pContainer->dwFlags & CNT_UINSTATUSBAR) - UpdateStatusBar(dat); - return 0; - - case DM_REMOVEPOPUPS: - DeletePopupsForContact(dat->hContact, (DWORD)wParam); - return 0; - - case EM_THEMECHANGED: - DM_FreeTheme(dat); - return DM_ThemeChanged(dat); - - case DM_PLAYINCOMINGSOUND: - if (!dat) - return 0; - PlayIncomingSound(dat); - return 0; - - case DM_REFRESHTABINDEX: - dat->iTabID = GetTabIndexFromHWND(GetParent(hwndDlg), hwndDlg); - return 0; - - case DM_STATUSICONCHANGE: - if (m_pContainer->hwndStatus) { - SendMessage(dat->pContainer->hwnd, WM_SIZE, 0, 0); - SendMessage(m_pContainer->hwndStatus, SB_SETTEXT, (WPARAM)(SBT_OWNERDRAW) | 2, 0); - InvalidateRect(m_pContainer->hwndStatus, NULL, TRUE); - } - return 0; - - case DM_BBNEEDUPDATE: - if (lParam) - CB_ChangeButton(hwndDlg, dat, (CustomButtonData*)lParam); - else - BB_InitDlgButtons(dat); - - BB_SetButtonsPos(dat); - return 0; - - case DM_CBDESTROY: - if (lParam) - CB_DestroyButton(hwndDlg, dat, (DWORD)wParam, (DWORD)lParam); - else - CB_DestroyAllButtons(hwndDlg); - return 0; - - case WM_DROPFILES: - { - BOOL not_sending = GetKeyState(VK_CONTROL) & 0x8000; - if (!not_sending) { - const char *szProto = dat->cache->getActiveProto(); - if (szProto == NULL) - break; - - int pcaps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0); - if (!(pcaps & PF1_FILESEND)) - break; - if (dat->wStatus == ID_STATUS_OFFLINE) { - pcaps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0); - if (!(pcaps & PF4_OFFLINEFILES)) { - SendMessage(hwndDlg, DM_ACTIVATETOOLTIP, IDC_MESSAGE, (LPARAM)TranslateT("Contact is offline and this protocol does not support sending files to offline users.")); - break; - } - } - } - - if (dat->hContact != NULL) { - TCHAR szFilename[MAX_PATH]; - HDROP hDrop = (HDROP)wParam; - int fileCount = DragQueryFile(hDrop, -1, NULL, 0), totalCount = 0, i; - TCHAR** ppFiles = NULL; - for (i = 0; i < fileCount; i++) { - DragQueryFile(hDrop, i, szFilename, SIZEOF(szFilename)); - Utils::AddToFileList(&ppFiles, &totalCount, szFilename); - } - - if (!not_sending) - CallService(MS_FILE_SENDSPECIFICFILEST, dat->hContact, (LPARAM)ppFiles); - else { - if (ServiceExists(MS_HTTPSERVER_ADDFILENAME)) { - for (int i = 0; i < totalCount; i++) { - char* szFileName = mir_t2a(ppFiles[i]); - CallService(MS_HTTPSERVER_ADDFILENAME, (WPARAM)szFileName, 0); - mir_free(szFileName); - } - char *szHTTPText = "DEBUG"; - SendDlgItemMessageA(hwndDlg, IDC_MESSAGE, EM_REPLACESEL, TRUE, (LPARAM)szHTTPText); - SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); - } - } - for (i = 0; ppFiles[i]; i++) - mir_free(ppFiles[i]); - mir_free(ppFiles); - } - } - return 0; - - case DM_CHECKQUEUEFORCLOSE: - { - int *uOpen = (int*)lParam; - if (uOpen) - *uOpen += dat->iOpenJobs; - } - return 0; - - case WM_CLOSE: - // esc handles error controls if we are in error state (error controls visible) - if (wParam == 0 && lParam == 0 && dat->dwFlags & MWF_ERRORSTATE) { - SendMessage(hwndDlg, DM_ERRORDECIDED, MSGERROR_CANCEL, 0); - return TRUE; - } - - if (wParam == 0 && lParam == 0) { - if (PluginConfig.m_EscapeCloses == 1) { - SendMessage(hwndContainer, WM_SYSCOMMAND, SC_MINIMIZE, 0); - return TRUE; - } - else if (PluginConfig.m_bHideOnClose && PluginConfig.m_EscapeCloses == 2) { - ShowWindow(hwndContainer, SW_HIDE); - return TRUE; - } - _dlgReturn(hwndDlg, TRUE); - } - if(dat) { - TContainerData *pContainer = dat->pContainer; - if (dat->iOpenJobs > 0 && lParam != 2) { - if (dat->dwFlags & MWF_ERRORSTATE) { - SendMessage(hwndDlg, DM_ERRORDECIDED, MSGERROR_CANCEL, 1); - } else { - if (dat->dwFlagsEx & MWF_EX_WARNCLOSE) - return TRUE; - - dat->dwFlagsEx |= MWF_EX_WARNCLOSE; - LRESULT result = SendQueue::WarnPendingJobs(0); - dat->dwFlagsEx &= ~MWF_EX_WARNCLOSE; - if (result == IDNO) - return TRUE; - } - } - int iTabs = TabCtrl_GetItemCount(hwndTab); - if (iTabs == 1) { - PostMessage(hwndContainer, WM_CLOSE, 0, 1); - return 1; - } - - m_pContainer->iChilds--; - int i = GetTabIndexFromHWND(hwndTab, hwndDlg); - - // 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->bDontSmartClose && iTabs > 1 && lParam != 3) { - if (i == iTabs - 1) - i--; - else - i++; - TabCtrl_SetCurSel(hwndTab, i); - - TCITEM item = { 0 }; - item.mask = TCIF_PARAM; - TabCtrl_GetItem(hwndTab, i, &item); // retrieve dialog hwnd for the now active tab... - - m_pContainer->hwndActive = (HWND)item.lParam; - - SendMessage(hwndContainer, DM_QUERYCLIENTAREA, 0, (LPARAM)&rc); - SetWindowPos(m_pContainer->hwndActive, HWND_TOP, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), SWP_SHOWWINDOW); - ShowWindow((HWND)item.lParam, SW_SHOW); - SetForegroundWindow(m_pContainer->hwndActive); - SetFocus(m_pContainer->hwndActive); - SendMessage(hwndContainer, WM_SIZE, 0, 0); - } - - DestroyWindow(hwndDlg); - if (iTabs == 1) - PostMessage(GetParent(GetParent(hwndDlg)), WM_CLOSE, 0, 1); - else - SendMessage(pContainer->hwnd, WM_SIZE, 0, 0); - } - break; - - case WM_DESTROY: - if (!dat) - break; - - if (dat->hwndContactPic) - DestroyWindow(dat->hwndContactPic); - - if (dat->hwndPanelPic) - DestroyWindow(dat->hwndPanelPic); - - if (dat->hClientIcon) - DestroyIcon(dat->hClientIcon); - - if (dat->hwndPanelPicParent) - DestroyWindow(dat->hwndPanelPicParent); - - if (dat->cache->isValid()) { // not valid means the contact was deleted - TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSING, 0); - AddContactToFavorites(dat->hContact, dat->cache->getNick(), dat->cache->getActiveProto(), dat->szStatus, dat->wStatus, - LoadSkinnedProtoIcon(dat->cache->getActiveProto(), dat->cache->getActiveStatus()), 1, PluginConfig.g_hMenuRecent); - if (dat->hContact) { - if (!dat->fEditNotesActive) { - char *msg = Message_GetFromStream(GetDlgItem(hwndDlg, IDC_MESSAGE), SF_TEXT); - if (msg) { - db_set_utf(dat->hContact, SRMSGMOD, "SavedMsg", msg); - mir_free(msg); - } - else db_unset(dat->hContact, SRMSGMOD, "SavedMsg"); - } - else SendMessage(hwndDlg, WM_COMMAND, IDC_PIC, 0); - } - } - - if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) - DM_NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); - - DM_FreeTheme(dat); - - mir_free(dat->sendBuffer); - mir_free(dat->hHistoryEvents); - - // search the sendqueue for unfinished send jobs and mir_free them. Leave unsent - // messages in the queue as they can be acked later - { - SendJob *jobs = sendQueue->getJobByIndex(0); - - for (int i = 0; i < SendQueue::NR_SENDJOBS; i++) { - if (jobs[i].hContact == dat->hContact) { - if (jobs[i].iStatus >(unsigned)SendQueue::SQ_INPROGRESS) - sendQueue->clearJob(i); - - // unfinished jobs which did not yet return anything are kept in the queue. - // the hwndOwner is set to 0 because the window handle is now no longer valid. - // Response for such a job is still silently handled by AckMessage() (sendqueue.c) - if (jobs[i].iStatus == (unsigned)SendQueue::SQ_INPROGRESS) - jobs[i].hOwnerWnd = 0; - } - } - } - - mir_free(dat->hQueuedEvents); - - if (dat->hSmileyIcon) - DestroyIcon(dat->hSmileyIcon); - - if (dat->hXStatusIcon) - DestroyIcon(dat->hXStatusIcon); - - if (dat->hwndTip) - DestroyWindow(dat->hwndTip); - - if (dat->hTaskbarIcon) - DestroyIcon(dat->hTaskbarIcon); - - UpdateTrayMenuState(dat, FALSE); // remove me from the tray menu (if still there) - if (PluginConfig.g_hMenuTrayUnread) - DeleteMenu(PluginConfig.g_hMenuTrayUnread, (UINT_PTR)dat->hContact, MF_BYCOMMAND); - M.RemoveWindow(hwndDlg); - - if (dat->cache->isValid()) - db_set_dw(0, SRMSGMOD, "multisplit", dat->multiSplitterX); - - { - HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_GETFONT, 0, 0); - if (hFont != NULL && hFont != (HFONT)SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0)) - DeleteObject(hFont); - - TCITEM item = { 0 }; - item.mask = TCIF_PARAM; - - int i = GetTabIndexFromHWND(hwndTab, hwndDlg); - if (i >= 0) { - SendMessage(hwndTab, WM_USER + 100, 0, 0); // remove tooltip - TabCtrl_DeleteItem(hwndTab, i); - BroadCastContainer(m_pContainer, DM_REFRESHTABINDEX, 0, 0); - dat->iTabID = -1; - } - } - - TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSE, 0); - - // clean up IEView and H++ log windows - if (dat->hwndIEView != 0) { - IEVIEWWINDOW ieWindow; - ieWindow.cbSize = sizeof(IEVIEWWINDOW); - ieWindow.iType = IEW_DESTROY; - ieWindow.hwnd = dat->hwndIEView; - CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow); - } - if (dat->hwndHPP) { - IEVIEWWINDOW ieWindow; - ieWindow.cbSize = sizeof(IEVIEWWINDOW); - ieWindow.iType = IEW_DESTROY; - ieWindow.hwnd = dat->hwndHPP; - CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow); - } - if (dat->pWnd) { - delete dat->pWnd; - dat->pWnd = 0; - } - if (dat->sbCustom) { - delete dat->sbCustom; - dat->sbCustom = 0; - } - break; - - case WM_DWMCOMPOSITIONCHANGED: - BB_RefreshTheme(dat); - memset((void*)&dat->pContainer->mOld, -1000, sizeof(MARGINS)); - CProxyWindow::verify(dat); - break; - - case DM_FORCEREDRAW: - RedrawWindow(hwndDlg, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW); - return 0; - - case DM_CHECKINFOTIP: - dat->Panel->hideTip(reinterpret_cast<HWND>(lParam)); - return 0; - - case WM_NCDESTROY: - if (dat) { - memset((void*)&dat->pContainer->mOld, -1000, sizeof(MARGINS)); - PostMessage(dat->pContainer->hwnd, WM_SIZE, 0, 1); - if (m_pContainer->dwFlags & CNT_SIDEBAR) - m_pContainer->SideBar->removeSession(dat); - dat->cache->setWindowData(); - if (dat->cache->isValid() && !dat->fIsReattach && dat->hContact && M.GetByte("deletetemp", 0)) - if (db_get_b(dat->hContact, "CList", "NotOnList", 0)) - CallService(MS_DB_CONTACT_DELETE, dat->hContact, 0); - - delete dat->Panel; - mir_free(dat); - } - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); - break; - } - return FALSE; -} + case TABSRMM_HK_NUDGE:
+ SendNudge(dat);
+ return _dlgReturn(hwndDlg, 1);
+ case TABSRMM_HK_SENDFILE:
+ CallService(MS_FILE_SENDFILE, dat->hContact, 0);
+ return _dlgReturn(hwndDlg, 1);
+ case TABSRMM_HK_QUOTEMSG:
+ SendMessage(hwndDlg, WM_COMMAND, IDC_QUOTE, 0);
+ return _dlgReturn(hwndDlg, 1);
+ case TABSRMM_HK_USERMENU:
+ SendMessage(hwndDlg, WM_COMMAND, IDC_PROTOCOL, 0);
+ return _dlgReturn(hwndDlg, 1);
+ case TABSRMM_HK_USERDETAILS:
+ SendMessage(hwndDlg, WM_COMMAND, MAKELONG(IDC_NAME, BN_CLICKED), 0);
+ return _dlgReturn(hwndDlg, 1);
+ case TABSRMM_HK_EDITNOTES:
+ PostMessage(hwndDlg, WM_COMMAND, MAKELONG(IDC_PIC, BN_CLICKED), 0);
+ return _dlgReturn(hwndDlg, 1);
+ case TABSRMM_HK_TOGGLESENDLATER:
+ if (sendLater->isAvail()) {
+ dat->sendMode ^= SMODE_SENDLATER;
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_MESSAGE), 0, 0, 0, 0, 0, SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOZORDER |
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOCOPYBITS);
+ RedrawWindow(hwndDlg, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN);
+ }
+ else
+ CWarning::show(CWarning::WARN_NO_SENDLATER, MB_OK | MB_ICONINFORMATION, TranslateT("Configuration issue|The unattended send feature is disabled. The \\b1 send later\\b0 and \\b1 send to multiple contacts\\b0 features depend on it.\n\nYou must enable it under \\b1Options->Message sessions->Advanced tweaks\\b0. Changing this option requires a restart."));
+ return _dlgReturn(hwndDlg, 1);
+ case TABSRMM_HK_TOGGLERTL:
+ {
+ DWORD dwGlobal = M.GetDword("mwflags", MWF_LOG_DEFAULT);
+ DWORD dwMask = M.GetDword(dat->hContact, "mwmask", 0);
+ DWORD dwFlags = M.GetDword(dat->hContact, "mwflags", 0);
+
+ dat->dwFlags ^= MWF_LOG_RTL;
+ if ((dwGlobal & MWF_LOG_RTL) != (dat->dwFlags & MWF_LOG_RTL)) {
+ dwMask |= MWF_LOG_RTL;
+ dwFlags |= (dat->dwFlags & MWF_LOG_RTL);
+ }
+ else {
+ dwMask &= ~MWF_LOG_RTL;
+ dwFlags &= ~MWF_LOG_RTL;
+ }
+ if (dwMask) {
+ db_set_dw(dat->hContact, SRMSGMOD_T, "mwmask", dwMask);
+ db_set_dw(dat->hContact, SRMSGMOD_T, "mwflags", dwFlags);
+ }
+ else {
+ db_unset(dat->hContact, SRMSGMOD_T, "mwmask");
+ db_unset(dat->hContact, SRMSGMOD_T, "mwflags");
+ }
+ SendMessage(hwndDlg, DM_OPTIONSAPPLIED, 0, 0);
+ SendMessage(hwndDlg, DM_DEFERREDREMAKELOG, (WPARAM)hwndDlg, 0);
+ }
+ return _dlgReturn(hwndDlg, 1);
+
+ case TABSRMM_HK_TOGGLEMULTISEND:
+ dat->sendMode ^= SMODE_MULTIPLE;
+ if (dat->sendMode & SMODE_MULTIPLE)
+ DM_CreateClist(dat);
+ else if (IsWindow(GetDlgItem(hwndDlg, IDC_CLIST)))
+ DestroyWindow(GetDlgItem(hwndDlg, IDC_CLIST));
+
+ HWND hwndEdit = GetDlgItem(hwndDlg, IDC_MESSAGE);
+ SetWindowPos(hwndEdit, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ RedrawWindow(hwndEdit, NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW | RDW_ERASE);
+ DM_ScrollToBottom(dat, 0, 0);
+ Utils::showDlgControl(hwndDlg, IDC_MULTISPLITTER, (dat->sendMode & SMODE_MULTIPLE) ? SW_SHOW : SW_HIDE);
+ Utils::showDlgControl(hwndDlg, IDC_CLIST, (dat->sendMode & SMODE_MULTIPLE) ? SW_SHOW : SW_HIDE);
+ if (dat->sendMode & SMODE_MULTIPLE)
+ SetFocus(GetDlgItem(hwndDlg, IDC_CLIST));
+ else
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ RedrawWindow(hwndDlg, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN);
+ return _dlgReturn(hwndDlg, 1);
+ }
+ if (DM_GenericHotkeysCheck(&message, dat)) {
+ dat->fkeyProcessed = true;
+ return _dlgReturn(hwndDlg, 1);
+ }
+ }
+ if (wp == VK_BROWSER_BACK || wp == VK_BROWSER_FORWARD)
+ return 1;
+
+ if (msg == WM_CHAR) {
+ if (isCtrl && !isShift && !isAlt) {
+ switch (wp) {
+ case 23: // ctrl - w
+ PostMessage(hwndDlg, WM_CLOSE, 1, 0);
+ break;
+ case 19:
+ PostMessage(hwndDlg, WM_COMMAND, IDC_SENDMENU, IDC_SENDMENU);
+ break;
+ case 16:
+ PostMessage(hwndDlg, WM_COMMAND, IDC_PROTOMENU, IDC_PROTOMENU);
+ break;
+ case 20:
+ PostMessage(hwndDlg, WM_COMMAND, IDC_TOGGLETOOLBAR, 1);
+ break;
+ }
+ return 1;
+ }
+ }
+ if (msg == WM_KEYDOWN) {
+ if ((wp == VK_INSERT && isShift && !isCtrl) || (wp == 'V' && isCtrl && !isShift && !isAlt)) {
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_PASTESPECIAL, CF_UNICODETEXT, 0);
+ _clrMsgFilter(lParam);
+ return _dlgReturn(hwndDlg, 1);
+ }
+ if (isCtrl && isShift) {
+ if (wp == 0x9) { // ctrl-shift tab
+ SendMessage(hwndDlg, DM_SELECTTAB, DM_SELECT_PREV, 0);
+ _clrMsgFilter(lParam);
+ return _dlgReturn(hwndDlg, 1);
+ }
+ }
+ if (isCtrl && !isShift && !isAlt) {
+ if (wp == VK_TAB) {
+ SendMessage(hwndDlg, DM_SELECTTAB, DM_SELECT_NEXT, 0);
+ _clrMsgFilter(lParam);
+ return _dlgReturn(hwndDlg, 1);
+ }
+ if (wp == VK_F4) {
+ PostMessage(hwndDlg, WM_CLOSE, 1, 0);
+ return _dlgReturn(hwndDlg, 1);
+ }
+ if (wp == VK_PRIOR) {
+ SendMessage(hwndDlg, DM_SELECTTAB, DM_SELECT_PREV, 0);
+ return _dlgReturn(hwndDlg, 1);
+ }
+ if (wp == VK_NEXT) {
+ SendMessage(hwndDlg, DM_SELECTTAB, DM_SELECT_NEXT, 0);
+ return _dlgReturn(hwndDlg, 1);
+ }
+ }
+ }
+ if (msg == WM_SYSKEYDOWN && isAlt) {
+ if (wp == 0x52) {
+ SendMessage(hwndDlg, DM_QUERYPENDING, DM_QUERY_MOSTRECENT, 0);
+ return _dlgReturn(hwndDlg, 1);
+ }
+ if (wp == VK_MULTIPLY) {
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ return _dlgReturn(hwndDlg, 1);
+ }
+ if (wp == VK_DIVIDE) {
+ SetFocus(GetDlgItem(hwndDlg, IDC_LOG));
+ return _dlgReturn(hwndDlg, 1);
+ }
+ if (wp == VK_ADD) {
+ SendMessage(hwndContainer, DM_SELECTTAB, DM_SELECT_NEXT, 0);
+ return _dlgReturn(hwndDlg, 1);
+ }
+ if (wp == VK_SUBTRACT) {
+ SendMessage(hwndContainer, DM_SELECTTAB, DM_SELECT_PREV, 0);
+ return _dlgReturn(hwndDlg, 1);
+ }
+ }
+
+ if (msg == WM_KEYDOWN && wp == VK_F12) {
+ if (isShift || isCtrl || isAlt)
+ return _dlgReturn(hwndDlg, 1);
+ if (dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED)
+ SendMessage(hwndDlg, DM_REPLAYQUEUE, 0, 0);
+ dat->dwFlagsEx ^= MWF_SHOW_SCROLLINGDISABLED;
+ Utils::showDlgControl(hwndDlg, IDC_LOGFROZENTEXT, (dat->bNotOnList || dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED) ? SW_SHOW : SW_HIDE);
+ if (!(dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED))
+ SetDlgItemText(hwndDlg, IDC_LOGFROZENTEXT, TranslateT("Contact not on list. You may add it..."));
+ else
+ SetDlgItemText(hwndDlg, IDC_LOGFROZENTEXT, TranslateT("Auto scrolling is disabled (press F12 to enable it)"));
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ DM_ScrollToBottom(dat, 1, 1);
+ return _dlgReturn(hwndDlg, 1);
+ }
+
+ // tabulation mod
+ if (msg == WM_KEYDOWN && wp == VK_TAB) {
+ if (PluginConfig.m_bAllowTab) {
+ if (((NMHDR*)lParam)->idFrom == IDC_MESSAGE)
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_REPLACESEL, FALSE, (LPARAM)"\t");
+ _clrMsgFilter(lParam);
+ if (((NMHDR*)lParam)->idFrom != IDC_MESSAGE)
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ return _dlgReturn(hwndDlg, 1);
+ }
+ else {
+ if (((NMHDR*)lParam)->idFrom == IDC_MESSAGE) {
+ if (GetSendButtonState(hwndDlg) != PBS_DISABLED && !(dat->pContainer->dwFlags & CNT_HIDETOOLBAR))
+ SetFocus(GetDlgItem(hwndDlg, IDOK));
+ else
+ SetFocus(GetDlgItem(hwndDlg, IDC_LOG));
+ return _dlgReturn(hwndDlg, 1);
+ }
+ if (((NMHDR*)lParam)->idFrom == IDC_LOG) {
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ return _dlgReturn(hwndDlg, 1);
+ }
+ }
+ return _dlgReturn(hwndDlg, 0);
+ }
+
+ if (msg == WM_MOUSEWHEEL && (((NMHDR*)lParam)->idFrom == IDC_LOG || ((NMHDR*)lParam)->idFrom == IDC_MESSAGE)) {
+ GetCursorPos(&pt);
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_LOG), &rc);
+ if (PtInRect(&rc, pt)) {
+ short wDirection = (short)HIWORD(wp);
+ if (LOWORD(wp) & MK_SHIFT) {
+ if (wDirection < 0)
+ SendDlgItemMessage(hwndDlg, IDC_LOG, WM_VSCROLL, MAKEWPARAM(SB_PAGEDOWN, 0), 0);
+ else if (wDirection > 0)
+ SendDlgItemMessage(hwndDlg, IDC_LOG, WM_VSCROLL, MAKEWPARAM(SB_PAGEUP, 0), 0);
+ return 0;
+ }
+ return 0;
+ }
+ return 1;
+ }
+
+ if (msg == WM_CHAR && wp == 'c') {
+ if (isCtrl) {
+ SendDlgItemMessage(hwndDlg, ((NMHDR*)lParam)->code, WM_COPY, 0, 0);
+ break;
+ }
+ }
+ if ((msg == WM_LBUTTONDOWN || msg == WM_KEYUP || msg == WM_LBUTTONUP) && ((NMHDR*)lParam)->idFrom == IDC_MESSAGE) {
+ int bBold = IsDlgButtonChecked(hwndDlg, IDC_FONTBOLD);
+ int bItalic = IsDlgButtonChecked(hwndDlg, IDC_FONTITALIC);
+ int bUnder = IsDlgButtonChecked(hwndDlg, IDC_FONTUNDERLINE);
+ int bStrikeout = IsDlgButtonChecked(hwndDlg, IDC_FONTSTRIKEOUT);
+
+ cf2.cbSize = sizeof(CHARFORMAT2);
+ cf2.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_UNDERLINETYPE | CFM_STRIKEOUT;
+ cf2.dwEffects = 0;
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
+ if (cf2.dwEffects & CFE_BOLD) {
+ if (bBold == BST_UNCHECKED)
+ CheckDlgButton(hwndDlg, IDC_FONTBOLD, BST_CHECKED);
+ }
+ else if (bBold == BST_CHECKED)
+ CheckDlgButton(hwndDlg, IDC_FONTBOLD, BST_UNCHECKED);
+
+ if (cf2.dwEffects & CFE_ITALIC) {
+ if (bItalic == BST_UNCHECKED)
+ CheckDlgButton(hwndDlg, IDC_FONTITALIC, BST_CHECKED);
+ }
+ else if (bItalic == BST_CHECKED)
+ CheckDlgButton(hwndDlg, IDC_FONTITALIC, BST_UNCHECKED);
+
+ if (cf2.dwEffects & CFE_UNDERLINE && (cf2.bUnderlineType & CFU_UNDERLINE || cf2.bUnderlineType & CFU_UNDERLINEWORD)) {
+ if (bUnder == BST_UNCHECKED)
+ CheckDlgButton(hwndDlg, IDC_FONTUNDERLINE, BST_CHECKED);
+ }
+ else if (bUnder == BST_CHECKED)
+ CheckDlgButton(hwndDlg, IDC_FONTUNDERLINE, BST_UNCHECKED);
+
+ if (cf2.dwEffects & CFE_STRIKEOUT) {
+ if (bStrikeout == BST_UNCHECKED)
+ CheckDlgButton(hwndDlg, IDC_FONTSTRIKEOUT, BST_CHECKED);
+ }
+ else if (bStrikeout == BST_CHECKED)
+ CheckDlgButton(hwndDlg, IDC_FONTSTRIKEOUT, BST_UNCHECKED);
+ }
+ switch (msg) {
+ case WM_LBUTTONDOWN:
+ {
+ HCURSOR hCur = GetCursor();
+ m_pContainer->MenuBar->Cancel();
+ if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE)
+ || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE)) {
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ break;
+ }
+
+ // auto-select-and-copy handling...
+ // if enabled, releasing the lmb with an active selection automatically copies the selection
+ // to the clipboard.
+ // holding ctrl while releasing the button pastes the selection to the input area, using plain text
+ // holding ctrl-alt does the same, but pastes formatted text
+ case WM_LBUTTONUP:
+ if (((NMHDR*)lParam)->idFrom == IDC_LOG) {
+ CHARRANGE cr;
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXGETSEL, 0, (LPARAM)&cr);
+ if (cr.cpMax != cr.cpMin) {
+ cr.cpMin = cr.cpMax;
+ if (isCtrl && M.GetByte("autocopy", 1)) {
+ SETTEXTEX stx = { ST_KEEPUNDO | ST_SELECTION, CP_UTF8 };
+ char *streamOut = NULL;
+ if (isAlt)
+ streamOut = Message_GetFromStream(GetDlgItem(hwndDlg, IDC_LOG), SF_RTFNOOBJS | SFF_PLAINRTF | SFF_SELECTION);
+ else
+ streamOut = Message_GetFromStream(GetDlgItem(hwndDlg, IDC_LOG), SF_TEXT | SFF_SELECTION);
+ if (streamOut) {
+ Utils::FilterEventMarkers(streamOut);
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETTEXTEX, (WPARAM)&stx, (LPARAM)streamOut);
+ mir_free(streamOut);
+ }
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ }
+ else if (M.GetByte("autocopy", 1) && !isShift) {
+ SendDlgItemMessage(hwndDlg, IDC_LOG, WM_COPY, 0, 0);
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ if (m_pContainer->hwndStatus)
+ SendMessage(m_pContainer->hwndStatus, SB_SETTEXT, 0, (LPARAM)TranslateT("Selection copied to clipboard"));
+ }
+ }
+ }
+ break;
+
+ case WM_RBUTTONUP:
+ return _dlgReturn(hwndDlg, 1);
+
+ case WM_MOUSEMOVE:
+ GetCursorPos(&pt);
+ DM_DismissTip(dat, pt);
+ dat->Panel->trackMouse(pt);
+
+ HCURSOR hCur = GetCursor();
+ if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE) || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE))
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ break;
+ }
+ }
+ break;
+
+ case EN_REQUESTRESIZE:
+ DM_HandleAutoSizeRequest(dat, (REQRESIZE *)lParam);
+ break;
+
+ case EN_LINK:
+ ENLINK *pLink = (ENLINK*)lParam;
+ switch (pLink->msg) {
+ case WM_SETCURSOR:
+ SetCursor(PluginConfig.hCurHyperlinkHand);
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
+ return TRUE;
+
+ case WM_RBUTTONDOWN:
+ case WM_LBUTTONUP:
+ ptrT tszUrl(Utils::extractURLFromRichEdit((ENLINK*)lParam, GetDlgItem(hwndDlg, IDC_LOG)));
+ if (!IsStringValidLink(tszUrl))
+ break;
+
+ if (pLink->msg != WM_RBUTTONDOWN) {
+ CallService(MS_UTILS_OPENURL, OUF_TCHAR, tszUrl);
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ break;
+ }
+ HMENU hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT));
+ HMENU hSubMenu = GetSubMenu(hMenu, 1);
+ TranslateMenu(hSubMenu);
+ pt.x = (short)LOWORD(pLink->lParam);
+ pt.y = (short)HIWORD(pLink->lParam);
+ ClientToScreen(((NMHDR*)lParam)->hwndFrom, &pt);
+ switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) {
+ case IDM_OPENNEW:
+ CallService(MS_UTILS_OPENURL, OUF_NEWWINDOW | OUF_TCHAR, tszUrl);
+ break;
+
+ case IDM_OPENEXISTING:
+ CallService(MS_UTILS_OPENURL, OUF_TCHAR, tszUrl);
+ break;
+
+ case IDM_COPYLINK:
+ if (!OpenClipboard(hwndDlg))
+ break;
+
+ EmptyClipboard();
+ HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(TCHAR)*(mir_tstrlen(tszUrl) + 1));
+ TCHAR *buf = (TCHAR*)GlobalLock(hData);
+ mir_tstrcpy(buf, tszUrl);
+ GlobalUnlock(hData);
+ SetClipboardData(CF_UNICODETEXT, hData);
+ CloseClipboard();
+ break;
+ }
+ DestroyMenu(hMenu);
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ }
+ }
+ break;
+
+ case DM_TYPING:
+ {
+ int preTyping = dat->nTypeSecs != 0;
+ dat->nTypeSecs = (int)lParam > 0 ? (int)lParam : 0;
+
+ if (dat->nTypeSecs)
+ dat->bShowTyping = 0;
+
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, preTyping);
+ }
+ return TRUE;
+
+ case DM_UPDATEWINICON:
+ if (dat->hXStatusIcon) {
+ DestroyIcon(dat->hXStatusIcon);
+ dat->hXStatusIcon = 0;
+ }
+
+ if (LPCSTR szProto = dat->cache->getProto()) {
+ dat->hTabIcon = dat->hTabStatusIcon = MY_GetContactIcon(dat, "MetaiconTab");
+ if (M.GetByte("use_xicons", 1))
+ dat->hXStatusIcon = GetXStatusIcon(dat);
+
+ SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, BUTTONSETASDIMMED, (dat->dwFlagsEx & MWF_SHOW_ISIDLE) != 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_PROTOCOL, BM_SETIMAGE, IMAGE_ICON, (LPARAM)(dat->hXStatusIcon ? dat->hXStatusIcon : MY_GetContactIcon(dat, "MetaiconBar")));
+
+ if (m_pContainer->hwndActive == hwndDlg)
+ SendMessage(m_pContainer->hwnd, DM_SETICON, (WPARAM)dat, (LPARAM)(dat->hXStatusIcon ? dat->hXStatusIcon : dat->hTabIcon));
+
+ if (dat->pWnd)
+ dat->pWnd->updateIcon(dat->hXStatusIcon ? dat->hXStatusIcon : dat->hTabIcon);
+ }
+ return 0;
+
+ // configures the toolbar only... if lParam != 0, then it also calls
+ // SetDialogToType() to reconfigure the message window
+ case DM_CONFIGURETOOLBAR:
+ dat->bShowUIElements = m_pContainer->dwFlags & CNT_HIDETOOLBAR ? 0 : 1;
+
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTER), GWL_EXSTYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTER), GWL_EXSTYLE) & ~WS_EX_STATICEDGE);
+
+ if (lParam == 1) {
+ GetSendFormat(dat);
+ SetDialogToType(hwndDlg);
+ }
+
+ if (lParam == 1) {
+ DM_RecalcPictureSize(dat);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ DM_ScrollToBottom(dat, 0, 1);
+ }
+ return 0;
+
+ case DM_LOADBUTTONBARICONS:
+ for (int i = 0; i < SIZEOF(buttonicons); i++) {
+ SendDlgItemMessage(hwndDlg, buttonicons[i].id, BM_SETIMAGE, IMAGE_ICON, (LPARAM)*buttonicons[i].pIcon);
+ SendDlgItemMessage(hwndDlg, buttonicons[i].id, BUTTONSETCONTAINER, (LPARAM)m_pContainer, 0);
+ }
+
+ BB_UpdateIcons(hwndDlg);
+ SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0);
+ return 0;
+
+ case DM_OPTIONSAPPLIED:
+ DM_OptionsApplied(dat, wParam, lParam);
+ return 0;
+
+ case DM_UPDATETITLE:
+ DM_UpdateTitle(dat, wParam, lParam);
+ return 0;
+
+ case DM_UPDATESTATUSMSG:
+ dat->Panel->Invalidate();
+ return 0;
+
+ case DM_OWNNICKCHANGED:
+ GetMyNick(dat);
+ return 0;
+
+ case DM_ADDDIVIDER:
+ if (!(dat->dwFlags & MWF_DIVIDERSET) && PluginConfig.m_bUseDividers) {
+ if (GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOG)) > 0) {
+ dat->dwFlags |= MWF_DIVIDERWANTED;
+ dat->dwFlags |= MWF_DIVIDERSET;
+ }
+ }
+ return 0;
+
+ case WM_SETFOCUS:
+ MsgWindowUpdateState(dat, WM_SETFOCUS);
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ return 1;
+
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) != WA_ACTIVE)
+ break;
+
+ //fall through
+ case WM_MOUSEACTIVATE:
+ MsgWindowUpdateState(dat, WM_ACTIVATE);
+ return 1;
+
+ case DM_UPDATEPICLAYOUT:
+ LoadContactAvatar(dat);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ return 0;
+
+ case DM_SPLITTERGLOBALEVENT:
+ DM_SplitterGlobalEvent(dat, wParam, lParam);
+ return 0;
+
+ case DM_SPLITTERMOVED:
+ if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_MULTISPLITTER)) {
+ GetClientRect(hwndDlg, &rc);
+ pt.x = wParam;
+ pt.y = 0;
+ ScreenToClient(hwndDlg, &pt);
+ int oldSplitterX = dat->multiSplitterX;
+ dat->multiSplitterX = rc.right - pt.x;
+ if (dat->multiSplitterX < 25)
+ dat->multiSplitterX = 25;
+
+ if (dat->multiSplitterX > ((rc.right - rc.left) - 80))
+ dat->multiSplitterX = oldSplitterX;
+ SendMessage(dat->hwnd, WM_SIZE, 0, 0);
+ }
+ else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SPLITTER)) {
+ GetClientRect(hwndDlg, &rc);
+ rc.top += (dat->Panel->isActive() ? dat->Panel->getHeight() + 40 : 30);
+ pt.x = 0;
+ pt.y = wParam;
+ ScreenToClient(hwndDlg, &pt);
+
+ int oldSplitterY = dat->splitterY;
+ int oldDynaSplitter = dat->dynaSplitter;
+
+ dat->splitterY = rc.bottom - pt.y + DPISCALEY_S(23);
+
+ // attempt to fix splitter troubles..
+ // hardcoded limits... better solution is possible, but this works for now
+ int bottomtoolbarH = 0;
+ if (dat->pContainer->dwFlags & CNT_BOTTOMTOOLBAR)
+ bottomtoolbarH = 22;
+
+ if (dat->splitterY < (DPISCALEY_S(MINSPLITTERY) + 5 + bottomtoolbarH)) { // min splitter size
+ dat->splitterY = (DPISCALEY_S(MINSPLITTERY) + 5 + bottomtoolbarH);
+ dat->dynaSplitter = dat->splitterY - DPISCALEY_S(34);
+ DM_RecalcPictureSize(dat);
+ }
+ else if (dat->splitterY > (rc.bottom - rc.top)) {
+ dat->splitterY = oldSplitterY;
+ dat->dynaSplitter = oldDynaSplitter;
+ DM_RecalcPictureSize(dat);
+ }
+ else {
+ dat->dynaSplitter = (rc.bottom - pt.y) - DPISCALEY_S(11);
+ DM_RecalcPictureSize(dat);
+ }
+ CSkin::UpdateToolbarBG(dat);
+ SendMessage(dat->hwnd, WM_SIZE, 0, 0);
+ }
+ else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_PANELSPLITTER)) {
+ GetClientRect(GetDlgItem(hwndDlg, IDC_LOG), &rc);
+
+ POINT pt = { 0, wParam };
+ ScreenToClient(hwndDlg, &pt);
+ if ((pt.y + 2 >= MIN_PANELHEIGHT + 2) && (pt.y + 2 < 100) && (pt.y + 2 < rc.bottom - 30))
+ dat->Panel->setHeight(pt.y + 2, true);
+
+ RedrawWindow(hwndDlg, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
+ if (M.isAero())
+ InvalidateRect(GetParent(hwndDlg), NULL, FALSE);
+ }
+ break;
+
+ // queue a dm_remakelog
+ // wParam = hwnd of the sender, so we can directly do a DM_REMAKELOG if the msg came
+ // from ourself. otherwise, the dm_remakelog will be deferred until next window
+ // activation (focus)
+ case DM_DEFERREDREMAKELOG:
+ if ((HWND)wParam == hwndDlg)
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+ else {
+ if (M.GetByte(dat->hContact, "mwoverride", 0) == 0) {
+ dat->dwFlags &= ~(MWF_LOG_ALL);
+ dat->dwFlags |= (lParam & MWF_LOG_ALL);
+ dat->dwFlags |= MWF_DEFERREDREMAKELOG;
+ }
+ }
+ return 0;
+
+ case DM_FORCEDREMAKELOG:
+ if ((HWND)wParam == hwndDlg)
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+ else {
+ dat->dwFlags &= ~(MWF_LOG_ALL);
+ dat->dwFlags |= (lParam & MWF_LOG_ALL);
+ dat->dwFlags |= MWF_DEFERREDREMAKELOG;
+ }
+ return 0;
+
+ case DM_REMAKELOG:
+ dat->szMicroLf[0] = 0;
+ dat->lastEventTime = 0;
+ dat->iLastEventType = -1;
+ StreamInEvents(hwndDlg, dat->hDbEventFirst, -1, 0, NULL);
+ return 0;
+
+ case DM_APPENDMCEVENT:
+ if (dat->hContact == db_mc_getMeta(wParam) && dat->hDbEventFirst == NULL) {
+ dat->hDbEventFirst = lParam;
+ SendMessage(dat->hwnd, DM_REMAKELOG, 0, 0);
+ }
+ else if (dat->hContact == wParam && db_mc_isSub(wParam) && db_event_getContact(lParam) != wParam)
+ StreamInEvents(hwndDlg, lParam, 1, 1, NULL);
+ return 0;
+
+ case DM_APPENDTOLOG:
+ StreamInEvents(hwndDlg, wParam, 1, 1, NULL);
+ return 0;
+
+ // replays queued events after the message log has been frozen for a while
+ case DM_REPLAYQUEUE:
+ for (int i = 0; i < dat->iNextQueuedEvent; i++)
+ if (dat->hQueuedEvents[i] != 0)
+ StreamInEvents(hwndDlg, dat->hQueuedEvents[i], 1, 1, NULL);
+
+ dat->iNextQueuedEvent = 0;
+ SetDlgItemText(hwndDlg, IDC_LOGFROZENTEXT, dat->bNotOnList ? TranslateT("Contact not on list. You may add it...") :
+ TranslateT("Auto scrolling is disabled (press F12 to enable it)"));
+ return 0;
+
+ case DM_SCROLLIEVIEW:
+ {
+ IEVIEWWINDOW iew = { sizeof(iew) };
+ iew.iType = IEW_SCROLLBOTTOM;
+ if (dat->hwndIEView) {
+ iew.hwnd = dat->hwndIEView;
+ CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&iew);
+ }
+ else if (dat->hwndHPP) {
+ iew.hwnd = dat->hwndHPP;
+ CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)&iew);
+ }
+ }
+ return 0;
+
+ case HM_DBEVENTADDED:
+ // this is called whenever a new event has been added to the database.
+ // this CAN be posted (some sanity checks required).
+ if (dat && dat->hContact)
+ DM_EventAdded(dat, dat->hContact, lParam);
+ return 0;
+
+ case WM_TIMER:
+ // timer to control info panel hovering
+ if (wParam == TIMERID_AWAYMSG) {
+ KillTimer(hwndDlg, wParam);
+ GetCursorPos(&pt);
+
+ if (wParam == TIMERID_AWAYMSG && dat->Panel->hitTest(pt) != CInfoPanel::HTNIRVANA)
+ SendMessage(hwndDlg, DM_ACTIVATETOOLTIP, 0, 0);
+ else
+ dat->dwFlagsEx &= ~MWF_SHOW_AWAYMSGTIMER;
+ break;
+ }
+
+ // timer id for message timeouts is composed like:
+ // for single message sends: basevalue (TIMERID_MSGSEND) + send queue index
+ if (wParam >= TIMERID_MSGSEND) {
+ int iIndex = wParam - TIMERID_MSGSEND;
+ if (iIndex < SendQueue::NR_SENDJOBS) { // single sendjob timer
+ SendJob *job = sendQueue->getJobByIndex(iIndex);
+ KillTimer(hwndDlg, wParam);
+ mir_sntprintf(job->szErrorMsg, SIZEOF(job->szErrorMsg), TranslateT("Delivery failure: %s"),
+ TranslateT("The message send timed out"));
+ job->iStatus = SendQueue::SQ_ERROR;
+ if (!nen_options.iNoSounds && !(m_pContainer->dwFlags & CNT_NOSOUND))
+ SkinPlaySound("SendError");
+ if (!(dat->dwFlags & MWF_ERRORSTATE))
+ sendQueue->handleError(dat, iIndex);
+ break;
+ }
+ }
+ else if (wParam == TIMERID_FLASHWND) {
+ if (dat->mayFlashTab)
+ FlashTab(dat, hwndTab, dat->iTabID, &dat->bTabFlash, TRUE, dat->hTabIcon);
+ break;
+ }
+ else if (wParam == TIMERID_TYPE) {
+ DM_Typing(dat);
+ break;
+ }
+ break;
+
+ case DM_ERRORDECIDED:
+ switch (wParam) {
+ case MSGERROR_CANCEL:
+ case MSGERROR_SENDLATER:
+ if (dat->dwFlags & MWF_ERRORSTATE) {
+ dat->cache->saveHistory(0, 0);
+ if (wParam == MSGERROR_SENDLATER)
+ sendQueue->doSendLater(dat->iCurrentQueueError, dat); // to be implemented at a later time
+ dat->iOpenJobs--;
+ sendQueue->dec();
+ if (dat->iCurrentQueueError >= 0 && dat->iCurrentQueueError < SendQueue::NR_SENDJOBS)
+ sendQueue->clearJob(dat->iCurrentQueueError);
+ dat->iCurrentQueueError = -1;
+ sendQueue->showErrorControls(dat, FALSE);
+ if (wParam != MSGERROR_CANCEL || (wParam == MSGERROR_CANCEL && lParam == 0))
+ SetDlgItemText(hwndDlg, IDC_MESSAGE, _T(""));
+ sendQueue->checkQueue(dat);
+ int iNextFailed = sendQueue->findNextFailed(dat);
+ if (iNextFailed >= 0)
+ sendQueue->handleError(dat, iNextFailed);
+ }
+ break;
+
+ case MSGERROR_RETRY:
+ if (dat->dwFlags & MWF_ERRORSTATE) {
+ int resent = 0;
+
+ dat->cache->saveHistory(0, 0);
+ if (dat->iCurrentQueueError >= 0 && dat->iCurrentQueueError < SendQueue::NR_SENDJOBS) {
+ SendJob *job = sendQueue->getJobByIndex(dat->iCurrentQueueError);
+ if (job->hSendId == 0 && job->hContact == 0)
+ break;
+
+ job->hSendId = (HANDLE)CallContactService(job->hContact, PSS_MESSAGE,
+ (dat->sendMode & SMODE_FORCEANSI) ? (job->dwFlags & ~PREF_UNICODE) : job->dwFlags, (LPARAM)job->szSendBuffer);
+ resent++;
+ }
+
+ if (resent) {
+ SendJob *job = sendQueue->getJobByIndex(dat->iCurrentQueueError);
+
+ SetTimer(hwndDlg, TIMERID_MSGSEND + dat->iCurrentQueueError, PluginConfig.m_MsgTimeout, NULL);
+ job->iStatus = SendQueue::SQ_INPROGRESS;
+ dat->iCurrentQueueError = -1;
+ sendQueue->showErrorControls(dat, FALSE);
+ SetDlgItemText(hwndDlg, IDC_MESSAGE, _T(""));
+ sendQueue->checkQueue(dat);
+
+ int iNextFailed = sendQueue->findNextFailed(dat);
+ if (iNextFailed >= 0)
+ sendQueue->handleError(dat, iNextFailed);
+ }
+ }
+ }
+ break;
+
+ case DM_SELECTTAB:
+ SendMessage(hwndContainer, DM_SELECTTAB, wParam, lParam); // pass the msg to our container
+ return 0;
+
+ case DM_SETLOCALE:
+ if (dat->dwFlags & MWF_WASBACKGROUNDCREATE)
+ break;
+ if (m_pContainer->hwndActive == hwndDlg && PluginConfig.m_bAutoLocaleSupport && hwndContainer == GetForegroundWindow() && hwndContainer == GetActiveWindow()) {
+ if (lParam)
+ dat->hkl = (HKL)lParam;
+
+ if (dat->hkl)
+ ActivateKeyboardLayout(dat->hkl, 0);
+ }
+ return 0;
+
+ // return timestamp (in ticks) of last recent message which has not been read yet.
+ // 0 if there is none
+ // lParam = pointer to a dword receiving the value.
+ case DM_QUERYLASTUNREAD:
+ {
+ DWORD *pdw = (DWORD *)lParam;
+ if (pdw)
+ *pdw = dat->dwTickLastEvent;
+ }
+ return 0;
+
+ case DM_QUERYCONTAINER:
+ {
+ TContainerData **pc = (TContainerData **)lParam;
+ if (pc)
+ *pc = m_pContainer;
+ }
+ return 0;
+
+ case DM_QUERYHCONTACT:
+ {
+ MCONTACT *phContact = (MCONTACT*)lParam;
+ if (phContact)
+ *phContact = dat->hContact;
+ }
+ return 0;
+
+ case DM_UPDATELASTMESSAGE:
+ DM_UpdateLastMessage(dat);
+ return 0;
+
+ case DM_SAVESIZE:
+ if (dat->dwFlags & MWF_NEEDCHECKSIZE)
+ lParam = 0;
+
+ dat->dwFlags &= ~MWF_NEEDCHECKSIZE;
+ if (dat->dwFlags & MWF_WASBACKGROUNDCREATE) {
+ dat->dwFlags &= ~MWF_INITMODE;
+ if (dat->lastMessage)
+ DM_UpdateLastMessage(dat);
+ }
+
+ SendMessage(hwndContainer, DM_QUERYCLIENTAREA, 0, (LPARAM)&rcClient);
+ MoveWindow(hwndDlg, rcClient.left, rcClient.top, (rcClient.right - rcClient.left), (rcClient.bottom - rcClient.top), TRUE);
+ if (dat->dwFlags & MWF_WASBACKGROUNDCREATE) {
+ dat->dwFlags &= ~MWF_WASBACKGROUNDCREATE;
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ PostMessage(hwndDlg, DM_UPDATEPICLAYOUT, 0, 0);
+ if (PluginConfig.m_bAutoLocaleSupport) {
+ if (dat->hkl == 0)
+ DM_LoadLocale(dat);
+ else
+ PostMessage(hwndDlg, DM_SETLOCALE, 0, 0);
+ }
+ if (dat->hwndIEView != 0)
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ if (dat->pContainer->dwFlags & CNT_SIDEBAR)
+ dat->pContainer->SideBar->Layout();
+ }
+ else {
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ if (lParam == 0)
+ DM_ScrollToBottom(dat, 0, 1);
+ }
+ return 0;
+
+ case DM_CHECKSIZE:
+ dat->dwFlags |= MWF_NEEDCHECKSIZE;
+ return 0;
+
+ // sent by the message input area hotkeys. just pass it to our container
+ case DM_QUERYPENDING:
+ SendMessage(hwndContainer, DM_QUERYPENDING, wParam, lParam);
+ return 0;
+
+ case WM_LBUTTONDOWN:
+ GetCursorPos(&tmp);
+ cur.x = (SHORT)tmp.x;
+ cur.y = (SHORT)tmp.y;
+ if (!dat->Panel->isHovered())
+ SendMessage(hwndContainer, WM_NCLBUTTONDOWN, HTCAPTION, *((LPARAM*)(&cur)));
+ break;
+
+ case WM_LBUTTONUP:
+ GetCursorPos(&tmp);
+ if (dat->Panel->isHovered())
+ dat->Panel->handleClick(tmp);
+ else {
+ cur.x = (SHORT)tmp.x;
+ cur.y = (SHORT)tmp.y;
+ SendMessage(hwndContainer, WM_NCLBUTTONUP, HTCAPTION, *((LPARAM*)(&cur)));
+ }
+ break;
+
+ case WM_RBUTTONUP:
+ {
+ RECT rcPicture, rcPanelNick = { 0 };
+ int menuID = 0;
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_CONTACTPIC), &rcPicture);
+ rcPanelNick.left = rcPanelNick.right - 30;
+ GetCursorPos(&pt);
+
+ if (dat->Panel->invokeConfigDialog(pt))
+ break;
+
+ if (PtInRect(&rcPicture, pt))
+ menuID = MENU_PICMENU;
+
+ if ((menuID == MENU_PICMENU && ((dat->ace ? dat->ace->hbmPic : PluginConfig.g_hbmUnknown) || dat->hOwnPic) && dat->bShowAvatar != 0)) {
+ HMENU submenu = GetSubMenu(m_pContainer->hMenuContext, menuID == MENU_PICMENU ? 1 : 11);
+ GetCursorPos(&pt);
+ MsgWindowUpdateMenu(dat, submenu, menuID);
+ int iSelection = TrackPopupMenu(submenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL);
+ MsgWindowMenuHandler(dat, iSelection, menuID);
+ break;
+ }
+
+ HMENU subMenu = GetSubMenu(m_pContainer->hMenuContext, 0);
+ MsgWindowUpdateMenu(dat, subMenu, MENU_TABCONTEXT);
+
+ int iSelection = TrackPopupMenu(subMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL);
+ if (iSelection >= IDM_CONTAINERMENU) {
+ char szIndex[10];
+ char *szKey = "TAB_ContainersW";
+
+ mir_snprintf(szIndex, SIZEOF(szIndex), "%d", iSelection - IDM_CONTAINERMENU);
+ if (iSelection - IDM_CONTAINERMENU >= 0) {
+ ptrT val(db_get_tsa(NULL, szKey, szIndex));
+ if (val)
+ SendMessage(hwndDlg, DM_CONTAINERSELECTED, 0, (LPARAM)val);
+ }
+ break;
+ }
+ MsgWindowMenuHandler(dat, iSelection, MENU_TABCONTEXT);
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ GetCursorPos(&pt);
+ DM_DismissTip(dat, pt);
+ dat->Panel->trackMouse(pt);
+ break;
+
+ case WM_MEASUREITEM:
+ {
+ LPMEASUREITEMSTRUCT lpmi = (LPMEASUREITEMSTRUCT)lParam;
+ if (dat->Panel->isHovered()) {
+ lpmi->itemHeight = 0;
+ lpmi->itemWidth = 6;
+ return TRUE;
+ }
+ }
+ return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam);
+
+ case WM_NCHITTEST:
+ SendMessage(hwndContainer, WM_NCHITTEST, wParam, lParam);
+ break;
+
+ case WM_DRAWITEM:
+ return MsgWindowDrawHandler(wParam, lParam, dat);
+
+ case WM_APPCOMMAND:
+ {
+ DWORD cmd = GET_APPCOMMAND_LPARAM(lParam);
+ if (cmd == APPCOMMAND_BROWSER_BACKWARD || cmd == APPCOMMAND_BROWSER_FORWARD) {
+ SendMessage(hwndContainer, DM_SELECTTAB, cmd == APPCOMMAND_BROWSER_BACKWARD ? DM_SELECT_PREV : DM_SELECT_NEXT, 0);
+ return 1;
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ if (!dat)
+ break;
+
+ // custom button handling
+ if (LOWORD(wParam) >= MIN_CBUTTONID && LOWORD(wParam) <= MAX_CBUTTONID) {
+ BB_CustomButtonClick(dat, LOWORD(wParam), GetDlgItem(hwndDlg, LOWORD(wParam)), 0);
+ break;
+ }
+
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ if (dat->fEditNotesActive) {
+ SendMessage(hwndDlg, 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"));
+ return 0;
+ }
+ else {
+ // don't parse text formatting when the message contains curly braces - these are used by the rtf syntax
+ // and the parser currently cannot handle them properly in the text - XXX needs to be fixed later.
+ FINDTEXTEXA fi = { 0 };
+ fi.chrg.cpMin = 0;
+ fi.chrg.cpMax = -1;
+ fi.lpstrText = "{";
+ int final_sendformat = SendDlgItemMessageA(hwndDlg, IDC_MESSAGE, EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi) == -1 ? dat->SendFormat : 0;
+ fi.lpstrText = "}";
+ final_sendformat = SendDlgItemMessageA(hwndDlg, IDC_MESSAGE, EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi) == -1 ? final_sendformat : 0;
+
+ if (GetSendButtonState(hwndDlg) == PBS_DISABLED)
+ break;
+
+ ptrA streamOut(Message_GetFromStream(GetDlgItem(hwndDlg, IDC_MESSAGE), final_sendformat ? 0 : SF_TEXT));
+ if (streamOut == NULL)
+ break;
+
+ CMString decoded(ptrT(mir_utf8decodeT(streamOut)));
+ if (decoded.IsEmpty())
+ break;
+
+ char *utfResult = NULL;
+ if (final_sendformat)
+ DoRtfToTags(dat, decoded, SIZEOF(rtfDefColors), rtfDefColors);
+ decoded.Trim();
+ int bufSize = WideCharToMultiByte(dat->codePage, 0, decoded, -1, dat->sendBuffer, 0, 0, 0);
+
+ size_t memRequired = 0;
+ int flags = 0;
+ if (!IsUtfSendAvailable(dat->hContact)) {
+ flags |= PREF_UNICODE;
+ memRequired = bufSize + (mir_wstrlen(decoded) + 1) * sizeof(WCHAR);
+ }
+ else {
+ flags |= PREF_UTF;
+ utfResult = mir_utf8encodeT(decoded);
+ memRequired = strlen(utfResult) + 1;
+ }
+
+ // try to detect RTL
+ HWND hwndEdit = GetDlgItem(hwndDlg, IDC_MESSAGE);
+ 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);
+ if (pf2.wEffects & PFE_RTLPARA)
+ if (SendQueue::RTL_Detect(decoded))
+ flags |= PREF_RTL;
+
+ SendMessage(hwndEdit, WM_SETREDRAW, TRUE, 0);
+ SendMessage(hwndEdit, EM_SETSEL, -1, -1);
+ InvalidateRect(hwndEdit, NULL, FALSE);
+
+ if (memRequired > dat->iSendBufferSize) {
+ dat->sendBuffer = (char *)mir_realloc(dat->sendBuffer, memRequired);
+ dat->iSendBufferSize = memRequired;
+ }
+ if (utfResult) {
+ memcpy(dat->sendBuffer, utfResult, memRequired);
+ mir_free(utfResult);
+ }
+ else {
+ WideCharToMultiByte(dat->codePage, 0, decoded, -1, dat->sendBuffer, bufSize, 0, 0);
+ if (flags & PREF_UNICODE)
+ memcpy(&dat->sendBuffer[bufSize], decoded, (mir_wstrlen(decoded) + 1) * sizeof(WCHAR));
+ }
+
+ if (memRequired == 0 || dat->sendBuffer[0] == 0)
+ break;
+
+ if (dat->sendMode & SMODE_CONTAINER && m_pContainer->hwndActive == hwndDlg && GetForegroundWindow() == hwndContainer) {
+ int tabCount = TabCtrl_GetItemCount(hwndTab);
+ ptrA szFromStream(Message_GetFromStream(GetDlgItem(hwndDlg, IDC_MESSAGE), dat->SendFormat ? 0 : SF_TEXT));
+
+ TCITEM tci = { 0 };
+ tci.mask = TCIF_PARAM;
+ for (int i = 0; i < tabCount; i++) {
+ TabCtrl_GetItem(hwndTab, i, &tci);
+ // get the contact from the tabs lparam which hopefully is the tabs hwnd so we can get its userdata.... hopefully
+ HWND contacthwnd = (HWND)tci.lParam;
+ 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 != hwndDlg) {
+ SETTEXTEX stx = { ST_DEFAULT, CP_UTF8 };
+ // send the buffer to the contacts msg typing area
+ SendDlgItemMessage(contacthwnd, IDC_MESSAGE, EM_SETTEXTEX, (WPARAM)&stx, (LPARAM)szFromStream);
+ SendMessage(contacthwnd, WM_COMMAND, IDOK, 0);
+ }
+ }
+ }
+ }
+ // END /all /MOD
+ if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON)
+ DM_NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF);
+
+ DeletePopupsForContact(dat->hContact, PU_REMOVE_ON_SEND);
+ if (M.GetByte("allow_sendhook", 0)) {
+ int result = TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CUSTOM, MAKELONG(flags, tabMSG_WINDOW_EVT_CUSTOM_BEFORESEND));
+ if (result)
+ return TRUE;
+ }
+ sendQueue->addTo(dat, memRequired, flags);
+ }
+ return TRUE;
+
+ case IDC_QUOTE:
+ {
+ int iCharsPerLine = M.GetDword("quoteLineLength", 64);
+ CHARRANGE sel;
+ SETTEXTEX stx = { ST_SELECTION, 1200 };
+
+ MEVENT hDBEvent = 0;
+ if (dat->hwndIEView || dat->hwndHPP) { // IEView quoting support..
+ TCHAR *selected = 0, *szQuoted = 0;
+
+ IEVIEWEVENT event = { sizeof(event) };
+ event.hContact = dat->hContact;
+ event.dwFlags = 0;
+ event.iType = IEE_GET_SELECTION;
+
+ if (dat->hwndIEView) {
+ event.hwnd = dat->hwndIEView;
+ selected = (TCHAR*)CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&event);
+ }
+ else {
+ event.hwnd = dat->hwndHPP;
+ selected = (TCHAR*)CallService(MS_HPP_EG_EVENT, 0, (LPARAM)&event);
+ }
+
+ if (selected != NULL) {
+ szQuoted = QuoteText(selected, iCharsPerLine, 0);
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETTEXTEX, (WPARAM)&stx, (LPARAM)szQuoted);
+ if (szQuoted)
+ mir_free(szQuoted);
+ break;
+ }
+ else {
+ hDBEvent = db_event_last(dat->hContact);
+ goto quote_from_last;
+ }
+ }
+ hDBEvent = dat->hDbEventLast;
+
+ quote_from_last:
+ if (hDBEvent == NULL)
+ break;
+
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXGETSEL, 0, (LPARAM)&sel);
+ if (sel.cpMin == sel.cpMax) {
+ DBEVENTINFO dbei = { sizeof(dbei) };
+ dbei.cbBlob = db_event_getBlobSize(hDBEvent);
+ TCHAR *szText = (TCHAR*)mir_alloc((dbei.cbBlob + 1) * sizeof(TCHAR)); //URLs are made one char bigger for crlf
+ dbei.pBlob = (BYTE*)szText;
+ db_event_get(hDBEvent, &dbei);
+ int iSize = int(strlen((char*)dbei.pBlob)) + 1;
+
+ bool iAlloced = false;
+ TCHAR *szConverted;
+ if (dbei.flags & DBEF_UTF) {
+ szConverted = mir_utf8decodeW((char*)szText);
+ iAlloced = true;
+ }
+ else {
+ if (iSize != (int)dbei.cbBlob)
+ szConverted = (TCHAR*)&dbei.pBlob[iSize];
+ else {
+ szConverted = (TCHAR*)mir_alloc(sizeof(TCHAR) * iSize);
+ iAlloced = true;
+ MultiByteToWideChar(CP_ACP, 0, (char*)dbei.pBlob, -1, szConverted, iSize);
+ }
+ }
+ if (dbei.eventType == EVENTTYPE_FILE) {
+ size_t iDescr = mir_strlen((char *)(szText + sizeof(DWORD)));
+ memmove(szText, szText + sizeof(DWORD), iDescr);
+ memmove(szText + iDescr + 2, szText + sizeof(DWORD) + iDescr, dbei.cbBlob - iDescr - sizeof(DWORD) - 1);
+ szText[iDescr] = '\r';
+ szText[iDescr + 1] = '\n';
+ szConverted = (TCHAR*)mir_alloc(sizeof(TCHAR)* (1 + mir_strlen((char *)szText)));
+ MultiByteToWideChar(CP_ACP, 0, (char *)szText, -1, szConverted, 1 + (int)mir_strlen((char *)szText));
+ iAlloced = true;
+ }
+ ptrT szQuoted(QuoteText(szConverted, iCharsPerLine, 0));
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETTEXTEX, (WPARAM)&stx, (LPARAM)szQuoted);
+ mir_free(szText);
+ if (iAlloced)
+ mir_free(szConverted);
+ }
+ else {
+ ptrA szFromStream(Message_GetFromStream(GetDlgItem(hwndDlg, IDC_LOG), SF_TEXT | SFF_SELECTION));
+ ptrW converted(mir_utf8decodeW(szFromStream));
+ Utils::FilterEventMarkers(converted);
+ ptrT szQuoted(QuoteText(converted, iCharsPerLine, 0));
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETTEXTEX, (WPARAM)&stx, (LPARAM)szQuoted);
+ }
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ }
+ break;
+
+ case IDC_ADD:
+ {
+ ADDCONTACTSTRUCT acs = { 0 };
+ acs.hContact = dat->hContact;
+ acs.handleType = HANDLE_CONTACT;
+ acs.szProto = 0;
+ CallService(MS_ADDCONTACT_SHOW, (WPARAM)hwndDlg, (LPARAM)&acs);
+ if (!db_get_b(dat->hContact, "CList", "NotOnList", 0)) {
+ dat->bNotOnList = FALSE;
+ ShowMultipleControls(hwndDlg, addControls, 2, SW_HIDE);
+ if (!(dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED))
+ Utils::showDlgControl(hwndDlg, IDC_LOGFROZENTEXT, SW_HIDE);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ }
+ }
+ break;
+
+ case IDC_CANCELADD:
+ dat->bNotOnList = FALSE;
+ ShowMultipleControls(hwndDlg, addControls, 2, SW_HIDE);
+ if (!(dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED))
+ Utils::showDlgControl(hwndDlg, IDC_LOGFROZENTEXT, SW_HIDE);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ break;
+
+ case IDC_MESSAGE:
+ if (HIWORD(wParam) == EN_CHANGE) {
+ if (m_pContainer->hwndActive == hwndDlg)
+ UpdateReadChars(dat);
+ dat->dwFlags |= MWF_NEEDHISTORYSAVE;
+ dat->dwLastActivity = GetTickCount();
+ m_pContainer->dwLastActivity = dat->dwLastActivity;
+ SendQueue::UpdateSaveAndSendButton(dat);
+ if (!(GetKeyState(VK_CONTROL) & 0x8000)) {
+ dat->nLastTyping = GetTickCount();
+ if (GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE))) {
+ if (dat->nTypeMode == PROTOTYPE_SELFTYPING_OFF) {
+ if (!(dat->dwFlags & MWF_INITMODE))
+ DM_NotifyTyping(dat, PROTOTYPE_SELFTYPING_ON);
+ }
+ }
+ else if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON)
+ DM_NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF);
+ }
+ }
+ break;
+
+ default:
+ Utils::CmdDispatcher(Utils::CMD_MSGDIALOG, hwndDlg, LOWORD(wParam), wParam, lParam, dat, m_pContainer);
+ break;
+ }
+ break;
+
+ case WM_CONTEXTMENU:
+ {
+ DWORD idFrom = GetDlgCtrlID((HWND)wParam);
+ if (idFrom >= MIN_CBUTTONID && idFrom <= MAX_CBUTTONID) {
+ BB_CustomButtonClick(dat, idFrom, (HWND)wParam, 1);
+ break;
+ }
+ }
+ break;
+
+ // this is now *only* called from the global ME_PROTO_ACK handler (static int ProtoAck() in msgs.c)
+ // it receives:
+ // wParam = index of the sendjob in the queue in the low word, index of the found sendID in the high word
+ // (normally 0, but if its a multisend job, then the sendjob may contain more than one hContact/hSendId pairs.)
+ // lParam = the original ackdata
+ //
+ // the "per message window" ACK hook is gone, the global ack handler cares about all types of ack's (currently
+ // *_MESSAGE and *_AVATAR and dispatches them to the owner windows).
+ case HM_EVENTSENT:
+ sendQueue->ackMessage(dat, wParam, lParam);
+ return 0;
+
+ case DM_ACTIVATEME:
+ ActivateExistingTab(m_pContainer, hwndDlg);
+ return 0;
+
+ // sent by the select container dialog box when a container was selected...
+ // lParam = (TCHAR*)selected name...
+ case DM_CONTAINERSELECTED:
+ {
+ TCHAR *szNewName = (TCHAR*)lParam;
+ if (!_tcscmp(szNewName, TranslateT("Default container")))
+ szNewName = CGlobals::m_default_container_name;
+
+ int iOldItems = TabCtrl_GetItemCount(hwndTab);
+ if (!_tcsncmp(m_pContainer->szName, szNewName, CONTAINER_NAMELEN))
+ break;
+
+ TContainerData *pNewContainer = FindContainerByName(szNewName);
+ if (pNewContainer == NULL)
+ if ((pNewContainer = CreateContainer(szNewName, FALSE, dat->hContact)) == NULL)
+ break;
+
+ db_set_ts(dat->hContact, SRMSGMOD_T, "containerW", szNewName);
+ dat->fIsReattach = TRUE;
+ PostMessage(PluginConfig.g_hwndHotkeyHandler, DM_DOCREATETAB, (WPARAM)pNewContainer, dat->hContact);
+ if (iOldItems > 1) // there were more than 1 tab, container is still valid
+ SendMessage(m_pContainer->hwndActive, WM_SIZE, 0, 0);
+ SetForegroundWindow(pNewContainer->hwnd);
+ SetActiveWindow(pNewContainer->hwnd);
+ }
+ break;
+
+ case DM_STATUSBARCHANGED:
+ UpdateStatusBar(dat);
+ return 0;
+
+ case DM_UINTOCLIPBOARD:
+ Utils::CopyToClipBoard(dat->cache->getUIN(), hwndDlg);
+ return 0;
+
+ // broadcasted when GLOBAL info panel setting changes
+ case DM_SETINFOPANEL:
+ CInfoPanel::setPanelHandler(dat, wParam, lParam);
+ return 0;
+
+ // 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
+ case DM_ACTIVATETOOLTIP:
+ if (IsIconic(hwndContainer) || m_pContainer->hwndActive != hwndDlg)
+ break;
+
+ dat->Panel->showTip(wParam, lParam);
+ break;
+
+ case WM_NEXTDLGCTL:
+ if (dat->dwFlags & MWF_WASBACKGROUNDCREATE)
+ return 1;
+ break;
+
+ // save the contents of the log as rtf file
+ case DM_SAVEMESSAGELOG:
+ DM_SaveLogAsRTF(dat);
+ return 0;
+
+ case DM_CHECKAUTOHIDE:
+ DM_CheckAutoHide(dat, wParam, lParam);
+ return 0;
+
+ case DM_IEVIEWOPTIONSCHANGED:
+ if (dat->hwndIEView)
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+ break;
+
+ case DM_SMILEYOPTIONSCHANGED:
+ ConfigureSmileyButton(dat);
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+ break;
+
+ case DM_MYAVATARCHANGED:
+ {
+ const char *szProto = dat->cache->getActiveProto();
+ if (!strcmp((char *)wParam, szProto) && mir_strlen(szProto) == mir_strlen((char *)wParam))
+ LoadOwnAvatar(dat);
+ }
+ break;
+
+ case DM_GETWINDOWSTATE:
+ {
+ UINT state = MSG_WINDOW_STATE_EXISTS;
+ if (IsWindowVisible(hwndDlg))
+ state |= MSG_WINDOW_STATE_VISIBLE;
+ if (GetForegroundWindow() == hwndContainer)
+ state |= MSG_WINDOW_STATE_FOCUS;
+ if (IsIconic(hwndContainer))
+ state |= MSG_WINDOW_STATE_ICONIC;
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, state);
+ }
+ return TRUE;
+
+ case DM_CLIENTCHANGED:
+ GetClientIcon(dat);
+ if (dat->hClientIcon && dat->Panel->isActive())
+ InvalidateRect(hwndDlg, NULL, TRUE);
+ return 0;
+
+ case DM_UPDATEUIN:
+ if (dat->Panel->isActive())
+ dat->Panel->Invalidate();
+ if (dat->pContainer->dwFlags & CNT_UINSTATUSBAR)
+ UpdateStatusBar(dat);
+ return 0;
+
+ case DM_REMOVEPOPUPS:
+ DeletePopupsForContact(dat->hContact, (DWORD)wParam);
+ return 0;
+
+ case EM_THEMECHANGED:
+ DM_FreeTheme(dat);
+ return DM_ThemeChanged(dat);
+
+ case DM_PLAYINCOMINGSOUND:
+ if (!dat)
+ return 0;
+ PlayIncomingSound(dat);
+ return 0;
+
+ case DM_REFRESHTABINDEX:
+ dat->iTabID = GetTabIndexFromHWND(GetParent(hwndDlg), hwndDlg);
+ return 0;
+
+ case DM_STATUSICONCHANGE:
+ if (m_pContainer->hwndStatus) {
+ SendMessage(dat->pContainer->hwnd, WM_SIZE, 0, 0);
+ SendMessage(m_pContainer->hwndStatus, SB_SETTEXT, (WPARAM)(SBT_OWNERDRAW) | 2, 0);
+ InvalidateRect(m_pContainer->hwndStatus, NULL, TRUE);
+ }
+ return 0;
+
+ case DM_BBNEEDUPDATE:
+ if (lParam)
+ CB_ChangeButton(hwndDlg, dat, (CustomButtonData*)lParam);
+ else
+ BB_InitDlgButtons(dat);
+
+ BB_SetButtonsPos(dat);
+ return 0;
+
+ case DM_CBDESTROY:
+ if (lParam)
+ CB_DestroyButton(hwndDlg, dat, (DWORD)wParam, (DWORD)lParam);
+ else
+ CB_DestroyAllButtons(hwndDlg);
+ return 0;
+
+ case WM_DROPFILES:
+ {
+ BOOL not_sending = GetKeyState(VK_CONTROL) & 0x8000;
+ if (!not_sending) {
+ const char *szProto = dat->cache->getActiveProto();
+ if (szProto == NULL)
+ break;
+
+ int pcaps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0);
+ if (!(pcaps & PF1_FILESEND))
+ break;
+ if (dat->wStatus == ID_STATUS_OFFLINE) {
+ pcaps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0);
+ if (!(pcaps & PF4_OFFLINEFILES)) {
+ SendMessage(hwndDlg, DM_ACTIVATETOOLTIP, IDC_MESSAGE, (LPARAM)TranslateT("Contact is offline and this protocol does not support sending files to offline users."));
+ break;
+ }
+ }
+ }
+
+ if (dat->hContact != NULL) {
+ TCHAR szFilename[MAX_PATH];
+ HDROP hDrop = (HDROP)wParam;
+ int fileCount = DragQueryFile(hDrop, -1, NULL, 0), totalCount = 0, i;
+ TCHAR** ppFiles = NULL;
+ for (i = 0; i < fileCount; i++) {
+ DragQueryFile(hDrop, i, szFilename, SIZEOF(szFilename));
+ Utils::AddToFileList(&ppFiles, &totalCount, szFilename);
+ }
+
+ if (!not_sending)
+ CallService(MS_FILE_SENDSPECIFICFILEST, dat->hContact, (LPARAM)ppFiles);
+ else {
+ if (ServiceExists(MS_HTTPSERVER_ADDFILENAME)) {
+ for (int i = 0; i < totalCount; i++) {
+ char* szFileName = mir_t2a(ppFiles[i]);
+ CallService(MS_HTTPSERVER_ADDFILENAME, (WPARAM)szFileName, 0);
+ mir_free(szFileName);
+ }
+ char *szHTTPText = "DEBUG";
+ SendDlgItemMessageA(hwndDlg, IDC_MESSAGE, EM_REPLACESEL, TRUE, (LPARAM)szHTTPText);
+ SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ }
+ }
+ for (i = 0; ppFiles[i]; i++)
+ mir_free(ppFiles[i]);
+ mir_free(ppFiles);
+ }
+ }
+ return 0;
+
+ case DM_CHECKQUEUEFORCLOSE:
+ {
+ int *uOpen = (int*)lParam;
+ if (uOpen)
+ *uOpen += dat->iOpenJobs;
+ }
+ return 0;
+
+ case WM_CLOSE:
+ // esc handles error controls if we are in error state (error controls visible)
+ if (wParam == 0 && lParam == 0 && dat->dwFlags & MWF_ERRORSTATE) {
+ SendMessage(hwndDlg, DM_ERRORDECIDED, MSGERROR_CANCEL, 0);
+ return TRUE;
+ }
+
+ if (wParam == 0 && lParam == 0) {
+ if (PluginConfig.m_EscapeCloses == 1) {
+ SendMessage(hwndContainer, WM_SYSCOMMAND, SC_MINIMIZE, 0);
+ return TRUE;
+ }
+ else if (PluginConfig.m_bHideOnClose && PluginConfig.m_EscapeCloses == 2) {
+ ShowWindow(hwndContainer, SW_HIDE);
+ return TRUE;
+ }
+ _dlgReturn(hwndDlg, TRUE);
+ }
+ if (dat) {
+ TContainerData *pContainer = dat->pContainer;
+ if (dat->iOpenJobs > 0 && lParam != 2) {
+ if (dat->dwFlags & MWF_ERRORSTATE) {
+ SendMessage(hwndDlg, DM_ERRORDECIDED, MSGERROR_CANCEL, 1);
+ }
+ else {
+ if (dat->dwFlagsEx & MWF_EX_WARNCLOSE)
+ return TRUE;
+
+ dat->dwFlagsEx |= MWF_EX_WARNCLOSE;
+ LRESULT result = SendQueue::WarnPendingJobs(0);
+ dat->dwFlagsEx &= ~MWF_EX_WARNCLOSE;
+ if (result == IDNO)
+ return TRUE;
+ }
+ }
+ int iTabs = TabCtrl_GetItemCount(hwndTab);
+ if (iTabs == 1) {
+ PostMessage(hwndContainer, WM_CLOSE, 0, 1);
+ return 1;
+ }
+
+ m_pContainer->iChilds--;
+ int i = GetTabIndexFromHWND(hwndTab, hwndDlg);
+
+ // 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->bDontSmartClose && iTabs > 1 && lParam != 3) {
+ if (i == iTabs - 1)
+ i--;
+ else
+ i++;
+ TabCtrl_SetCurSel(hwndTab, i);
+
+ TCITEM item = { 0 };
+ item.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwndTab, i, &item); // retrieve dialog hwnd for the now active tab...
+
+ m_pContainer->hwndActive = (HWND)item.lParam;
+
+ SendMessage(hwndContainer, DM_QUERYCLIENTAREA, 0, (LPARAM)&rc);
+ SetWindowPos(m_pContainer->hwndActive, HWND_TOP, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), SWP_SHOWWINDOW);
+ ShowWindow((HWND)item.lParam, SW_SHOW);
+ SetForegroundWindow(m_pContainer->hwndActive);
+ SetFocus(m_pContainer->hwndActive);
+ SendMessage(hwndContainer, WM_SIZE, 0, 0);
+ }
+
+ DestroyWindow(hwndDlg);
+ if (iTabs == 1)
+ PostMessage(GetParent(GetParent(hwndDlg)), WM_CLOSE, 0, 1);
+ else
+ SendMessage(pContainer->hwnd, WM_SIZE, 0, 0);
+ }
+ break;
+
+ case WM_DESTROY:
+ if (!dat)
+ break;
+
+ if (dat->hwndContactPic)
+ DestroyWindow(dat->hwndContactPic);
+
+ if (dat->hwndPanelPic)
+ DestroyWindow(dat->hwndPanelPic);
+
+ if (dat->hClientIcon)
+ DestroyIcon(dat->hClientIcon);
+
+ if (dat->hwndPanelPicParent)
+ DestroyWindow(dat->hwndPanelPicParent);
+
+ if (dat->cache->isValid()) { // not valid means the contact was deleted
+ TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSING, 0);
+ AddContactToFavorites(dat->hContact, dat->cache->getNick(), dat->cache->getActiveProto(), dat->szStatus, dat->wStatus,
+ LoadSkinnedProtoIcon(dat->cache->getActiveProto(), dat->cache->getActiveStatus()), 1, PluginConfig.g_hMenuRecent);
+ if (dat->hContact) {
+ if (!dat->fEditNotesActive) {
+ char *msg = Message_GetFromStream(GetDlgItem(hwndDlg, IDC_MESSAGE), SF_TEXT);
+ if (msg) {
+ db_set_utf(dat->hContact, SRMSGMOD, "SavedMsg", msg);
+ mir_free(msg);
+ }
+ else db_unset(dat->hContact, SRMSGMOD, "SavedMsg");
+ }
+ else SendMessage(hwndDlg, WM_COMMAND, IDC_PIC, 0);
+ }
+ }
+
+ if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON)
+ DM_NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF);
+
+ DM_FreeTheme(dat);
+
+ mir_free(dat->sendBuffer);
+ mir_free(dat->hHistoryEvents);
+
+ // search the sendqueue for unfinished send jobs and mir_free them. Leave unsent
+ // messages in the queue as they can be acked later
+ {
+ SendJob *jobs = sendQueue->getJobByIndex(0);
+
+ for (int i = 0; i < SendQueue::NR_SENDJOBS; i++) {
+ if (jobs[i].hContact == dat->hContact) {
+ if (jobs[i].iStatus > (unsigned)SendQueue::SQ_INPROGRESS)
+ sendQueue->clearJob(i);
+
+ // unfinished jobs which did not yet return anything are kept in the queue.
+ // the hwndOwner is set to 0 because the window handle is now no longer valid.
+ // Response for such a job is still silently handled by AckMessage() (sendqueue.c)
+ if (jobs[i].iStatus == (unsigned)SendQueue::SQ_INPROGRESS)
+ jobs[i].hOwnerWnd = 0;
+ }
+ }
+ }
+
+ mir_free(dat->hQueuedEvents);
+
+ if (dat->hSmileyIcon)
+ DestroyIcon(dat->hSmileyIcon);
+
+ if (dat->hXStatusIcon)
+ DestroyIcon(dat->hXStatusIcon);
+
+ if (dat->hwndTip)
+ DestroyWindow(dat->hwndTip);
+
+ if (dat->hTaskbarIcon)
+ DestroyIcon(dat->hTaskbarIcon);
+
+ UpdateTrayMenuState(dat, FALSE); // remove me from the tray menu (if still there)
+ if (PluginConfig.g_hMenuTrayUnread)
+ DeleteMenu(PluginConfig.g_hMenuTrayUnread, (UINT_PTR)dat->hContact, MF_BYCOMMAND);
+ M.RemoveWindow(hwndDlg);
+
+ if (dat->cache->isValid())
+ db_set_dw(0, SRMSGMOD, "multisplit", dat->multiSplitterX);
+
+ {
+ HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_GETFONT, 0, 0);
+ if (hFont != NULL && hFont != (HFONT)SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0))
+ DeleteObject(hFont);
+
+ TCITEM item = { 0 };
+ item.mask = TCIF_PARAM;
+
+ int i = GetTabIndexFromHWND(hwndTab, hwndDlg);
+ if (i >= 0) {
+ SendMessage(hwndTab, WM_USER + 100, 0, 0); // remove tooltip
+ TabCtrl_DeleteItem(hwndTab, i);
+ BroadCastContainer(m_pContainer, DM_REFRESHTABINDEX, 0, 0);
+ dat->iTabID = -1;
+ }
+ }
+
+ TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSE, 0);
+
+ // clean up IEView and H++ log windows
+ if (dat->hwndIEView != 0) {
+ IEVIEWWINDOW ieWindow;
+ ieWindow.cbSize = sizeof(IEVIEWWINDOW);
+ ieWindow.iType = IEW_DESTROY;
+ ieWindow.hwnd = dat->hwndIEView;
+ CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow);
+ }
+ if (dat->hwndHPP) {
+ IEVIEWWINDOW ieWindow;
+ ieWindow.cbSize = sizeof(IEVIEWWINDOW);
+ ieWindow.iType = IEW_DESTROY;
+ ieWindow.hwnd = dat->hwndHPP;
+ CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow);
+ }
+ if (dat->pWnd) {
+ delete dat->pWnd;
+ dat->pWnd = 0;
+ }
+ if (dat->sbCustom) {
+ delete dat->sbCustom;
+ dat->sbCustom = 0;
+ }
+ break;
+
+ case WM_DWMCOMPOSITIONCHANGED:
+ BB_RefreshTheme(dat);
+ memset((void*)&dat->pContainer->mOld, -1000, sizeof(MARGINS));
+ CProxyWindow::verify(dat);
+ break;
+
+ case DM_FORCEREDRAW:
+ RedrawWindow(hwndDlg, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW);
+ return 0;
+
+ case DM_CHECKINFOTIP:
+ dat->Panel->hideTip(reinterpret_cast<HWND>(lParam));
+ return 0;
+
+ case WM_NCDESTROY:
+ if (dat) {
+ memset((void*)&dat->pContainer->mOld, -1000, sizeof(MARGINS));
+ PostMessage(dat->pContainer->hwnd, WM_SIZE, 0, 1);
+ if (m_pContainer->dwFlags & CNT_SIDEBAR)
+ m_pContainer->SideBar->removeSession(dat);
+ dat->cache->setWindowData();
+ if (dat->cache->isValid() && !dat->fIsReattach && dat->hContact && M.GetByte("deletetemp", 0))
+ if (db_get_b(dat->hContact, "CList", "NotOnList", 0))
+ CallService(MS_DB_CONTACT_DELETE, dat->hContact, 0);
+
+ delete dat->Panel;
+ mir_free(dat);
+ }
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ break;
+ }
+ return FALSE;
+}
|