summaryrefslogtreecommitdiff
path: root/plugins/TabSRMM/src/generic_msghandlers.cpp
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-05-23 07:44:30 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-05-23 07:44:30 +0000
commitf3d44bc057201407373012b7f682881bda7b3d98 (patch)
treeddf031a82529c84e13222131cf184ecf176d3954 /plugins/TabSRMM/src/generic_msghandlers.cpp
parentc2d827972a16f1710406d15e58304aecc4e1c9b5 (diff)
some includes restored, mir_full.sln updated, some renaming of folders and projects
git-svn-id: http://svn.miranda-ng.org/main/trunk@140 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/TabSRMM/src/generic_msghandlers.cpp')
-rw-r--r--plugins/TabSRMM/src/generic_msghandlers.cpp2419
1 files changed, 2419 insertions, 0 deletions
diff --git a/plugins/TabSRMM/src/generic_msghandlers.cpp b/plugins/TabSRMM/src/generic_msghandlers.cpp
new file mode 100644
index 0000000000..d507076eae
--- /dev/null
+++ b/plugins/TabSRMM/src/generic_msghandlers.cpp
@@ -0,0 +1,2419 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda IM: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 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
+ *
+ * $Id: generic_msghandlers.cpp 13587 2011-04-12 13:54:26Z george.hazan $
+ *
+ * these are generic message handlers which are used by the message dialog window procedure.
+ * calling them directly instead of using SendMessage() is faster.
+ * also contains various callback functions for custom buttons
+ */
+
+
+#include "commonheaders.h"
+
+extern RECT rcLastStatusBarClick;
+
+
+/**
+ * Save message log for given session as RTF document
+ */
+void TSAPI DM_SaveLogAsRTF(const TWindowData* dat)
+{
+ TCHAR szFilename[MAX_PATH];
+ OPENFILENAME ofn = {0};
+ EDITSTREAM stream = { 0 };
+ TCHAR szFilter[MAX_PATH];
+
+ if (dat && dat->hwndIEView != 0) {
+ IEVIEWEVENT event = {0};
+
+ event.cbSize = sizeof(IEVIEWEVENT);
+ event.hwnd = dat->hwndIEView;
+ event.hContact = dat->hContact;
+ event.iType = IEE_SAVE_DOCUMENT;
+ event.dwFlags = 0;
+ event.count = 0;
+ event.codepage = 0;
+ CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&event);
+ } else if(dat) {
+ TCHAR szInitialDir[MAX_PATH + 2];
+
+ mir_sntprintf(szFilter, SIZEOF(szFilter), _T("%s%c*.rtf%c%c"), TranslateT("Rich Edit file"), 0, 0, 0);
+ mir_sntprintf(szFilename, MAX_PATH, _T("%s.rtf"), dat->cache->getNick());
+
+ Utils::sanitizeFilename(szFilename);
+
+ mir_sntprintf(szInitialDir, MAX_PATH, _T("%s%s\\"), M->getDataPath(), _T("\\Saved message logs"));
+ CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)szInitialDir);
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = dat->hwnd;
+ ofn.lpstrFile = szFilename;
+ ofn.lpstrFilter = szFilter;
+ ofn.lpstrInitialDir = szInitialDir;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.Flags = OFN_HIDEREADONLY;
+ ofn.lpstrDefExt = _T("rtf");
+ if (GetSaveFileName(&ofn)) {
+ stream.dwCookie = (DWORD_PTR)szFilename;
+ stream.dwError = 0;
+ stream.pfnCallback = Utils::StreamOut;
+ SendDlgItemMessage(dat->hwnd, dat->bType == SESSIONTYPE_IM ? IDC_LOG : IDC_CHAT_LOG, EM_STREAMOUT, SF_RTF | SF_USECODEPAGE, (LPARAM) & stream);
+ }
+ }
+}
+
+/**
+ * This is broadcasted by the container to all child windows to check if the
+ * container can be autohidden or -closed.
+ *
+ * wParam is the autohide timeout (in seconds)
+ * lParam points to a BOOL and a session which wants to prevent auto-hiding
+ * the container must set it to FALSE.
+ *
+ * If no session in the container disagrees, the container will be hidden.
+ */
+void TSAPI DM_CheckAutoHide(const TWindowData* dat, WPARAM wParam, LPARAM lParam)
+{
+ if(dat && lParam) {
+ BOOL *fResult = (BOOL *)lParam;
+
+ if(GetWindowTextLengthA(GetDlgItem(dat->hwnd, dat->bType == SESSIONTYPE_IM ? IDC_MESSAGE : IDC_CHAT_MESSAGE)) > 0) {
+ *fResult = FALSE;
+ return; // text entered in the input area -> prevent autohide/cose
+ }
+ if(dat->dwUnread) {
+ *fResult = FALSE;
+ return; // unread events, do not hide or close the container
+ }
+ if(((GetTickCount() - dat->dwLastActivity) / 1000) <= wParam)
+ *fResult = FALSE; // time since last activity did not yet reach the threshold.
+ }
+}
+/**
+ * checks if the balloon tooltip can be dismissed (usually called by
+ * WM_MOUSEMOVE events
+ */
+
+void TSAPI DM_DismissTip(TWindowData *dat, const POINT& pt)
+{
+ RECT rc;
+
+ if(!IsWindowVisible(dat->hwndTip))
+ return;
+
+ GetWindowRect(dat->hwndTip, &rc);
+ if(PtInRect(&rc, pt))
+ return;
+
+ if(abs(pt.x - dat->ptTipActivation.x) > 5 || abs(pt.y - dat->ptTipActivation.y) > 5) {
+ SendMessage(dat->hwndTip, TTM_TRACKACTIVATE, FALSE, 0);
+ dat->ptTipActivation.x = dat->ptTipActivation.y = 0;
+ }
+}
+
+/**
+ * initialize the balloon tooltip for message window notifications
+ */
+void TSAPI DM_InitTip(TWindowData *dat)
+{
+ dat->hwndTip = CreateWindowEx(0, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX | TTS_BALLOON, CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT, dat->hwnd, NULL, g_hInst, (LPVOID) NULL);
+
+ ZeroMemory((void *)&dat->ti, sizeof(dat->ti));
+ dat->ti.cbSize = sizeof(dat->ti);
+ dat->ti.lpszText = PluginConfig.m_szNoStatus;
+ dat->ti.hinst = g_hInst;
+ dat->ti.hwnd = dat->hwnd;
+ dat->ti.uFlags = TTF_TRACK | TTF_IDISHWND | TTF_TRANSPARENT;
+ dat->ti.uId = (UINT_PTR)dat->hwnd;
+ SendMessageA(dat->hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&dat->ti);
+ SetWindowPos(dat->hwndTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER);
+}
+
+/**
+ * checks generic hotkeys valid for both IM and MUC sessions
+ *
+ * returns 1 for handled hotkeys, 0 otherwise.
+ */
+LRESULT TSAPI DM_GenericHotkeysCheck(MSG *message, TWindowData *dat)
+{
+ LRESULT mim_hotkey_check = CallService(MS_HOTKEY_CHECK, (WPARAM)message, (LPARAM)(TABSRMM_HK_SECTION_GENERIC));
+ HWND hwndDlg = dat->hwnd;
+
+ switch(mim_hotkey_check) {
+ case TABSRMM_HK_PASTEANDSEND:
+ HandlePasteAndSend(dat);
+ return(1);
+ case TABSRMM_HK_HISTORY:
+ SendMessage(hwndDlg, WM_COMMAND, IDC_HISTORY, 0);
+ return(1);
+ case TABSRMM_HK_CONTAINEROPTIONS:
+ if (dat->pContainer->hWndOptions == 0)
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_CONTAINEROPTIONS), dat->pContainer->hwnd,
+ DlgProcContainerOptions, (LPARAM)dat->pContainer);
+ return(1);
+ case TABSRMM_HK_SEND:
+ if (!(GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE), GWL_STYLE) & ES_READONLY)) {
+ PostMessage(hwndDlg, WM_COMMAND, IDOK, 0);
+ return(1);
+ }
+ break;
+ case TABSRMM_HK_TOGGLEINFOPANEL:
+ dat->Panel->setActive(dat->Panel->isActive() ? FALSE : TRUE);
+ dat->Panel->showHide();
+ return(1);
+ case TABSRMM_HK_EMOTICONS:
+ SendMessage(hwndDlg, WM_COMMAND, IDC_SMILEYBTN, 0);
+ return(1);
+ case TABSRMM_HK_TOGGLETOOLBAR:
+ SendMessage(hwndDlg, WM_COMMAND, IDC_TOGGLETOOLBAR, 0);
+ return(1);
+ case TABSRMM_HK_CLEARLOG:
+ ClearLog(dat);
+ return(1);
+ case TABSRMM_HK_TOGGLESIDEBAR:
+ if(dat->pContainer->SideBar->isActive())
+ SendMessage(hwndDlg, WM_COMMAND, IDC_TOGGLESIDEBAR, 0);
+ return(1);
+ default:
+ break;
+ }
+ return(0);
+}
+
+LRESULT TSAPI DM_MsgWindowCmdHandler(HWND hwndDlg, TContainerData *m_pContainer, TWindowData *dat, UINT cmd, WPARAM wParam, LPARAM lParam)
+{
+ HWND hwndContainer = m_pContainer->hwnd;
+
+ switch(cmd) {
+ case IDC_FONTBOLD:
+ case IDC_FONTITALIC:
+ case IDC_FONTUNDERLINE:
+ case IDC_FONTSTRIKEOUT: {
+ CHARFORMAT2 cf, cfOld;
+ int cmd = LOWORD(wParam);
+ BOOL isBold, isItalic, isUnderline, isStrikeout;
+
+ if (dat->SendFormat == 0) // dont use formatting if disabled
+ break;
+
+ ZeroMemory(&cf, sizeof(CHARFORMAT2));
+ ZeroMemory(&cfOld, sizeof(CHARFORMAT2));
+ cfOld.cbSize = cf.cbSize = sizeof(CHARFORMAT2);
+ cfOld.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_STRIKEOUT;
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfOld);
+ isBold = (cfOld.dwEffects & CFE_BOLD) && (cfOld.dwMask & CFM_BOLD);
+ isItalic = (cfOld.dwEffects & CFE_ITALIC) && (cfOld.dwMask & CFM_ITALIC);
+ isUnderline = (cfOld.dwEffects & CFE_UNDERLINE) && (cfOld.dwMask & CFM_UNDERLINE);
+ isStrikeout = (cfOld.dwEffects & CFM_STRIKEOUT) && (cfOld.dwMask & CFM_STRIKEOUT);
+
+ if (cmd == IDC_FONTBOLD && !IsWindowEnabled(GetDlgItem(hwndDlg, IDC_FONTBOLD)))
+ break;
+ if (cmd == IDC_FONTITALIC && !IsWindowEnabled(GetDlgItem(hwndDlg, IDC_FONTITALIC)))
+ break;
+ if (cmd == IDC_FONTUNDERLINE && !IsWindowEnabled(GetDlgItem(hwndDlg, IDC_FONTUNDERLINE)))
+ break;
+ if (cmd == IDC_FONTSTRIKEOUT && !IsWindowEnabled(GetDlgItem(hwndDlg, IDC_FONTSTRIKEOUT)))
+ break;
+ if (cmd == IDC_FONTBOLD) {
+ cf.dwEffects = isBold ? 0 : CFE_BOLD;
+ cf.dwMask = CFM_BOLD;
+ CheckDlgButton(hwndDlg, IDC_FONTBOLD, !isBold);
+ } else if (cmd == IDC_FONTITALIC) {
+ cf.dwEffects = isItalic ? 0 : CFE_ITALIC;
+ cf.dwMask = CFM_ITALIC;
+ CheckDlgButton(hwndDlg, IDC_FONTITALIC, !isItalic);
+ } else if (cmd == IDC_FONTUNDERLINE) {
+ cf.dwEffects = isUnderline ? 0 : CFE_UNDERLINE;
+ cf.dwMask = CFM_UNDERLINE;
+ CheckDlgButton(hwndDlg, IDC_FONTUNDERLINE, !isUnderline);
+ } else if (cmd == IDC_FONTSTRIKEOUT) {
+ cf.dwEffects = isStrikeout ? 0 : CFM_STRIKEOUT;
+ cf.dwMask = CFM_STRIKEOUT;
+ CheckDlgButton(hwndDlg, IDC_FONTSTRIKEOUT, !isStrikeout);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ break;
+ }
+ case IDC_FONTFACE: {
+ HMENU submenu = GetSubMenu(m_pContainer->hMenuContext, 7);
+ RECT rc;
+ int iSelection, i;
+ CHARFORMAT2 cf;
+
+ ZeroMemory(&cf, sizeof(CHARFORMAT2));
+ cf.cbSize = sizeof(CHARFORMAT2);
+ cf.dwMask = CFM_COLOR;
+ cf.dwEffects = 0;
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_FONTFACE), &rc);
+ iSelection = TrackPopupMenu(submenu, TPM_RETURNCMD, rc.left, rc.bottom, 0, hwndDlg, NULL);
+ if (iSelection == ID_FONT_CLEARALLFORMATTING) {
+ cf.dwMask = CFM_BOLD | CFM_COLOR | CFM_ITALIC | CFM_UNDERLINE | CFM_STRIKEOUT;
+ cf.crTextColor = M->GetDword(FONTMODULE, "Font16Col", 0);
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ break;
+ }
+ if (iSelection == ID_FONT_DEFAULTCOLOR) {
+ int i = 0;
+ cf.crTextColor = M->GetDword(FONTMODULE, "Font16Col", 0);
+ for (i = 0; i < Utils::rtf_ctable_size; i++) {
+ if (Utils::rtf_ctable[i].clr == cf.crTextColor)
+ cf.crTextColor = RGB(GetRValue(cf.crTextColor), GetGValue(cf.crTextColor), GetBValue(cf.crTextColor) == 0 ? GetBValue(cf.crTextColor) + 1 : GetBValue(cf.crTextColor) - 1);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ break;
+ }
+ for (i = 0; i < RTF_CTABLE_DEFSIZE; i++) {
+ if (Utils::rtf_ctable[i].menuid == iSelection) {
+ cf.crTextColor = Utils::rtf_ctable[i].clr;
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ }
+ break;
+ }
+
+ case IDCANCEL: {
+ ShowWindow(hwndContainer, SW_MINIMIZE);
+ return FALSE;
+ }
+
+ case IDC_SAVE:
+ SendMessage(hwndDlg, WM_CLOSE, 1, 0);
+ break;
+
+ case IDC_NAME: {
+ if (GetKeyState(VK_SHIFT) & 0x8000) // copy UIN
+ SendMessage(hwndDlg, DM_UINTOCLIPBOARD, 0, 0);
+ else {
+ CallService(MS_USERINFO_SHOWDIALOG, (WPARAM) (dat->cache->getActiveContact()), 0);
+ }
+ break;
+ }
+
+ case IDC_HISTORY:
+ CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM) dat->hContact, 0);
+ break;
+
+ case IDC_SMILEYBTN:
+ if (dat->doSmileys && PluginConfig.g_SmileyAddAvail) {
+ RECT rc;
+ HANDLE hContact = dat->cache->getActiveContact();
+
+ if (CheckValidSmileyPack(dat->cache->getActiveProto(), hContact) != 0) {
+ SMADD_SHOWSEL3 smaddInfo = {0};
+
+ if (lParam == 0)
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_SMILEYBTN), &rc);
+ else
+ GetWindowRect((HWND)lParam, &rc);
+ smaddInfo.cbSize = sizeof(SMADD_SHOWSEL3);
+ smaddInfo.hwndTarget = GetDlgItem(hwndDlg, IDC_MESSAGE);
+ smaddInfo.targetMessage = EM_REPLACESEL;
+ smaddInfo.targetWParam = TRUE;
+ smaddInfo.Protocolname = const_cast<char *>(dat->cache->getActiveProto());
+ smaddInfo.Direction = 0;
+ smaddInfo.xPosition = rc.left;
+ smaddInfo.yPosition = rc.top + 24;
+ smaddInfo.hwndParent = hwndContainer;
+ smaddInfo.hContact = hContact;
+ CallService(MS_SMILEYADD_SHOWSELECTION, (WPARAM)hwndContainer, (LPARAM) &smaddInfo);
+ }
+ }
+ break;
+ case IDC_TIME: {
+ RECT rc;
+ HMENU submenu = GetSubMenu(m_pContainer->hMenuContext, 2);
+ int iSelection, isHandled;
+ DWORD dwOldFlags = dat->dwFlags;
+ DWORD dwOldEventIsShown = dat->dwFlagsEx;
+
+ MsgWindowUpdateMenu(dat, submenu, MENU_LOGMENU);
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_TIME), &rc);
+
+ iSelection = TrackPopupMenu(submenu, TPM_RETURNCMD, rc.left, rc.bottom, 0, hwndDlg, NULL);
+ isHandled = MsgWindowMenuHandler(dat, iSelection, MENU_LOGMENU);
+ return(isHandled);
+ }
+ case IDC_PROTOMENU: {
+ RECT rc;
+ HMENU submenu = GetSubMenu(m_pContainer->hMenuContext, 4);
+ int iSelection;
+ int iOldGlobalSendFormat = PluginConfig.m_SendFormat;
+
+ if (dat->hContact) {
+ int iLocalFormat = M->GetDword(dat->hContact, "sendformat", 0);
+ int iNewLocalFormat = iLocalFormat;
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_PROTOCOL), &rc);
+
+ CheckMenuItem(submenu, ID_MODE_GLOBAL, MF_BYCOMMAND | (!(dat->dwFlagsEx & MWF_SHOW_SPLITTEROVERRIDE) ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(submenu, ID_MODE_PRIVATE, MF_BYCOMMAND | (dat->dwFlagsEx & MWF_SHOW_SPLITTEROVERRIDE ? MF_CHECKED : MF_UNCHECKED));
+
+ /*
+ * formatting menu..
+ */
+
+ CheckMenuItem(submenu, ID_GLOBAL_BBCODE, MF_BYCOMMAND | ((PluginConfig.m_SendFormat) ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(submenu, ID_GLOBAL_OFF, MF_BYCOMMAND | ((PluginConfig.m_SendFormat == SENDFORMAT_NONE) ? MF_CHECKED : MF_UNCHECKED));
+
+ CheckMenuItem(submenu, ID_THISCONTACT_GLOBALSETTING, MF_BYCOMMAND | ((iLocalFormat == SENDFORMAT_NONE) ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(submenu, ID_THISCONTACT_BBCODE, MF_BYCOMMAND | ((iLocalFormat > 0) ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(submenu, ID_THISCONTACT_OFF, MF_BYCOMMAND | ((iLocalFormat == -1) ? MF_CHECKED : MF_UNCHECKED));
+
+ iSelection = TrackPopupMenu(submenu, TPM_RETURNCMD, rc.left, rc.bottom, 0, hwndDlg, NULL);
+ switch (iSelection) {
+ case ID_MODE_GLOBAL:
+ dat->dwFlagsEx &= ~(MWF_SHOW_SPLITTEROVERRIDE);
+ M->WriteByte(dat->hContact, SRMSGMOD_T, "splitoverride", 0);
+ LoadSplitter(dat);
+ AdjustBottomAvatarDisplay(dat);
+ DM_RecalcPictureSize(dat);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ break;
+ case ID_MODE_PRIVATE:
+ dat->dwFlagsEx |= MWF_SHOW_SPLITTEROVERRIDE;
+ M->WriteByte(dat->hContact, SRMSGMOD_T, "splitoverride", 1);
+ LoadSplitter(dat);
+ AdjustBottomAvatarDisplay(dat);
+ DM_RecalcPictureSize(dat);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ break;
+ case ID_GLOBAL_BBCODE:
+ PluginConfig.m_SendFormat = SENDFORMAT_BBCODE;
+ break;
+ case ID_GLOBAL_OFF:
+ PluginConfig.m_SendFormat = SENDFORMAT_NONE;
+ break;
+ case ID_THISCONTACT_GLOBALSETTING:
+ iNewLocalFormat = 0;
+ break;
+ case ID_THISCONTACT_BBCODE:
+ iNewLocalFormat = SENDFORMAT_BBCODE;
+ break;
+ case ID_THISCONTACT_OFF:
+ iNewLocalFormat = -1;
+ break;
+ }
+ if (iNewLocalFormat == 0)
+ DBDeleteContactSetting(dat->hContact, SRMSGMOD_T, "sendformat");
+ else if (iNewLocalFormat != iLocalFormat)
+ M->WriteDword(dat->hContact, SRMSGMOD_T, "sendformat", iNewLocalFormat);
+
+ if (PluginConfig.m_SendFormat != iOldGlobalSendFormat)
+ M->WriteByte(SRMSGMOD_T, "sendformat", (BYTE)PluginConfig.m_SendFormat);
+ if (iNewLocalFormat != iLocalFormat || PluginConfig.m_SendFormat != iOldGlobalSendFormat) {
+ dat->SendFormat = M->GetDword(dat->hContact, "sendformat", PluginConfig.m_SendFormat);
+ if (dat->SendFormat == -1) // per contact override to disable it..
+ dat->SendFormat = 0;
+ M->BroadcastMessage(DM_CONFIGURETOOLBAR, 0, 1);
+ }
+ }
+ break;
+ }
+ case IDC_TOGGLETOOLBAR:
+ if (lParam == 1)
+ ApplyContainerSetting(m_pContainer, CNT_NOMENUBAR, m_pContainer->dwFlags & CNT_NOMENUBAR ? 0 : 1, true);
+ else
+ ApplyContainerSetting(m_pContainer, CNT_HIDETOOLBAR, m_pContainer->dwFlags & CNT_HIDETOOLBAR ? 0 : 1, true);
+ break;
+ case IDC_INFOPANELMENU: {
+ RECT rc;
+ int iSelection;
+
+ HMENU submenu = GetSubMenu(m_pContainer->hMenuContext, 9);
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_NAME), &rc);
+
+ EnableMenuItem(submenu, ID_FAVORITES_ADDCONTACTTOFAVORITES, !dat->cache->isFavorite() ? MF_ENABLED : MF_GRAYED);
+ EnableMenuItem(submenu, ID_FAVORITES_REMOVECONTACTFROMFAVORITES, !dat->cache->isFavorite() ? MF_GRAYED : MF_ENABLED);
+
+ iSelection = TrackPopupMenu(submenu, TPM_RETURNCMD, rc.left, rc.bottom, 0, hwndDlg, NULL);
+
+ switch(iSelection) {
+ case ID_FAVORITES_ADDCONTACTTOFAVORITES:
+ DBWriteContactSettingByte(dat->hContact, SRMSGMOD_T, "isFavorite", 1);
+ AddContactToFavorites(dat->hContact, dat->cache->getNick(), dat->cache->getActiveProto(), dat->szStatus, dat->wStatus, LoadSkinnedProtoIcon(dat->cache->getActiveProto(), dat->cache->getActiveStatus()), 1, PluginConfig.g_hMenuFavorites);
+ break;
+ case ID_FAVORITES_REMOVECONTACTFROMFAVORITES:
+ DBWriteContactSettingByte(dat->hContact, SRMSGMOD_T, "isFavorite", 0);
+ DeleteMenu(PluginConfig.g_hMenuFavorites, (UINT_PTR)dat->hContact, MF_BYCOMMAND);
+ break;
+ default:
+ break;
+ }
+ dat->cache->updateFavorite();
+ break;
+ }
+ case IDC_SENDMENU: {
+ RECT rc;
+ HMENU submenu = GetSubMenu(m_pContainer->hMenuContext, 3);
+ int iSelection;
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDOK), &rc);
+ CheckMenuItem(submenu, ID_SENDMENU_SENDTOMULTIPLEUSERS, MF_BYCOMMAND | (dat->sendMode & SMODE_MULTIPLE ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(submenu, ID_SENDMENU_SENDDEFAULT, MF_BYCOMMAND | (dat->sendMode == 0 ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(submenu, ID_SENDMENU_SENDTOCONTAINER, MF_BYCOMMAND | (dat->sendMode & SMODE_CONTAINER ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(submenu, ID_SENDMENU_FORCEANSISEND, MF_BYCOMMAND | (dat->sendMode & SMODE_FORCEANSI ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(submenu, ID_SENDMENU_SENDLATER, MF_BYCOMMAND | (dat->sendMode & SMODE_SENDLATER ? MF_CHECKED : MF_UNCHECKED));
+ CheckMenuItem(submenu, ID_SENDMENU_SENDWITHOUTTIMEOUTS, MF_BYCOMMAND | (dat->sendMode & SMODE_NOACK ? MF_CHECKED : MF_UNCHECKED));
+ {
+ const char *szFinalProto = dat->cache->getActiveProto();
+ char szServiceName[128];
+
+ mir_snprintf(szServiceName, 128, "%s/SendNudge", szFinalProto);
+ EnableMenuItem(submenu, ID_SENDMENU_SENDNUDGE, MF_BYCOMMAND | ((ServiceExists(szServiceName) && ServiceExists(MS_NUDGE_SEND)) ? MF_ENABLED : MF_GRAYED));
+ }
+ if (lParam)
+ iSelection = TrackPopupMenu(submenu, TPM_RETURNCMD, rc.left, rc.bottom, 0, hwndDlg, NULL);
+ else
+ iSelection = HIWORD(wParam);
+
+ switch (iSelection) {
+ case ID_SENDMENU_SENDTOMULTIPLEUSERS:
+ dat->sendMode ^= SMODE_MULTIPLE;
+ if (dat->sendMode & SMODE_MULTIPLE)
+ HWND hwndClist = DM_CreateClist(dat);
+ else {
+ if (IsWindow(GetDlgItem(hwndDlg, IDC_CLIST)))
+ DestroyWindow(GetDlgItem(hwndDlg, IDC_CLIST));
+ }
+ break;
+ case ID_SENDMENU_SENDNUDGE:
+ SendNudge(dat);
+ break;
+ case ID_SENDMENU_SENDDEFAULT:
+ dat->sendMode = 0;
+ break;
+ case ID_SENDMENU_SENDTOCONTAINER:
+ dat->sendMode ^= SMODE_CONTAINER;
+ RedrawWindow(hwndDlg, 0, 0, RDW_ERASENOW|RDW_UPDATENOW);
+ break;
+ case ID_SENDMENU_FORCEANSISEND:
+ dat->sendMode ^= SMODE_FORCEANSI;
+ break;
+ case ID_SENDMENU_SENDLATER:
+ if(sendLater->isAvail())
+ dat->sendMode ^= SMODE_SENDLATER;
+ else
+ CWarning::show(CWarning::WARN_NO_SENDLATER, MB_OK|MB_ICONINFORMATION, CTranslator::get(CTranslator::QMGR_ERROR_NOMULTISEND));
+ break;
+ case ID_SENDMENU_SENDWITHOUTTIMEOUTS:
+ dat->sendMode ^= SMODE_NOACK;
+ if (dat->sendMode & SMODE_NOACK)
+ M->WriteByte(dat->hContact, SRMSGMOD_T, "no_ack", 1);
+ else
+ DBDeleteContactSetting(dat->hContact, SRMSGMOD_T, "no_ack");
+ break;
+ }
+ M->WriteByte(dat->hContact, SRMSGMOD_T, "no_ack", (BYTE)(dat->sendMode & SMODE_NOACK ? 1 : 0));
+ M->WriteByte(dat->hContact, SRMSGMOD_T, "forceansi", (BYTE)(dat->sendMode & SMODE_FORCEANSI ? 1 : 0));
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_MESSAGE), 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE);
+ if (dat->sendMode & SMODE_MULTIPLE || dat->sendMode & SMODE_CONTAINER) {
+ 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 {
+ if (IsWindow(GetDlgItem(hwndDlg, IDC_CLIST)))
+ DestroyWindow(GetDlgItem(hwndDlg, IDC_CLIST));
+ 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);
+ }
+ SendMessage(hwndContainer, DM_QUERYCLIENTAREA, 0, (LPARAM)&rc);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ DM_ScrollToBottom(dat, 1, 1);
+ 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);
+ break;
+ }
+ case IDC_TOGGLESIDEBAR: {
+ SendMessage(m_pContainer->hwnd, WM_COMMAND, IDC_TOGGLESIDEBAR, 0);
+ break;
+ }
+ case IDC_PIC: {
+ RECT rc;
+ GetClientRect(hwndDlg, &rc);
+
+ dat->fEditNotesActive = !dat->fEditNotesActive;
+ if(dat->fEditNotesActive) {
+ int iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE));
+ if(iLen != 0) {
+ SendMessage(hwndDlg, DM_ACTIVATETOOLTIP, IDC_MESSAGE, (LPARAM)CTranslator::get(CTranslator::GEN_MSG_NO_EDIT_NOTES));
+ dat->fEditNotesActive = false;
+ break;
+ }
+
+ if(!dat->fIsAutosizingInput) {
+ dat->iSplitterSaved = dat->splitterY;
+ dat->splitterY = rc.bottom / 2;
+ SendMessage(hwndDlg, WM_SIZE, 1, 1);
+ }
+
+ DBVARIANT dbv = {0};
+
+ if(0 == M->GetTString(dat->hContact, "UserInfo", "MyNotes", &dbv)) {
+ SetDlgItemText(hwndDlg, IDC_MESSAGE, dbv.ptszVal);
+ mir_free(dbv.ptszVal);
+ }
+ }
+ else {
+ int iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE));
+
+ TCHAR *buf = (TCHAR *)mir_alloc((iLen + 2) * sizeof(TCHAR));
+ GetDlgItemText(hwndDlg, IDC_MESSAGE, buf, iLen + 1);
+ M->WriteTString(dat->hContact, "UserInfo", "MyNotes", buf);
+ SetDlgItemText(hwndDlg, IDC_MESSAGE, _T(""));
+
+ if(!dat->fIsAutosizingInput) {
+ dat->splitterY = dat->iSplitterSaved;
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ DM_ScrollToBottom(dat, 0, 1);
+ }
+ }
+ 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_FRAME|RDW_UPDATENOW|RDW_ALLCHILDREN);
+
+ if(dat->fEditNotesActive)
+ CWarning::show(CWarning::WARN_EDITUSERNOTES, MB_OK|MB_ICONINFORMATION);
+ break;
+ }
+ case IDM_CLEAR:
+ ClearLog(dat);
+ break;
+ case IDC_PROTOCOL: {
+ RECT rc;
+ int iSel = 0;
+
+ HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) dat->hContact, 0);
+ if(lParam == 0)
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_PROTOCOL/*IDC_NAME*/), &rc);
+ else
+ GetWindowRect((HWND)lParam, &rc);
+ iSel = TrackPopupMenu(hMenu, TPM_RETURNCMD, rc.left, rc.bottom, 0, hwndDlg, NULL);
+
+ if(iSel)
+ CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(iSel), MPCF_CONTACTMENU), (LPARAM) dat->hContact);
+
+ DestroyMenu(hMenu);
+ break;
+ }
+ // error control
+ case IDC_CANCELSEND:
+ SendMessage(hwndDlg, DM_ERRORDECIDED, MSGERROR_CANCEL, 0);
+ break;
+ case IDC_RETRY:
+ SendMessage(hwndDlg, DM_ERRORDECIDED, MSGERROR_RETRY, 0);
+ break;
+ case IDC_MSGSENDLATER:
+ SendMessage(hwndDlg, DM_ERRORDECIDED, MSGERROR_SENDLATER, 0);
+ break;
+ case IDC_SELFTYPING:
+ if (dat->hContact) {
+ int iCurrentTypingMode = M->GetByte(dat->hContact, SRMSGMOD, SRMSGSET_TYPING, M->GetByte(SRMSGMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW));
+
+ if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON && iCurrentTypingMode) {
+ DM_NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF);
+ dat->nTypeMode = PROTOTYPE_SELFTYPING_OFF;
+ }
+ M->WriteByte(dat->hContact, SRMSGMOD, SRMSGSET_TYPING, (BYTE)!iCurrentTypingMode);
+ }
+ break;
+ default:
+ return(0);
+ }
+ return(1);
+}
+
+LRESULT TSAPI DM_ContainerCmdHandler(TContainerData *pContainer, UINT cmd, WPARAM wParam, LPARAM lParam)
+{
+ if(!pContainer)
+ return(0);
+
+ HWND hwndDlg = pContainer->hwnd;
+
+ switch(cmd) {
+ case IDC_CLOSE:
+ SendMessage(hwndDlg, WM_SYSCOMMAND, SC_CLOSE, 0);
+ break;
+ case IDC_MINIMIZE:
+ PostMessage(hwndDlg, WM_SYSCOMMAND, SC_MINIMIZE, 0);
+ break;
+ case IDC_MAXIMIZE:
+ SendMessage(hwndDlg, WM_SYSCOMMAND, IsZoomed(hwndDlg) ? SC_RESTORE : SC_MAXIMIZE, 0);
+ break;
+ case IDOK:
+ SendMessage(pContainer->hwndActive, WM_COMMAND, wParam, lParam); // pass the IDOK command to the active child - fixes the "enter not working
+ break;
+ case ID_FILE_SAVEMESSAGELOGAS:
+ SendMessage(pContainer->hwndActive, DM_SAVEMESSAGELOG, 0, 0);
+ break;
+ case ID_FILE_CLOSEMESSAGESESSION:
+ PostMessage(pContainer->hwndActive, WM_CLOSE, 0, 1);
+ break;
+ case ID_FILE_CLOSE:
+ PostMessage(hwndDlg, WM_CLOSE, 0, 1);
+ break;
+ case ID_VIEW_SHOWSTATUSBAR:
+ ApplyContainerSetting(pContainer, CNT_NOSTATUSBAR, pContainer->dwFlags & CNT_NOSTATUSBAR ? 0 : 1, true);
+ break;
+ case ID_VIEW_VERTICALMAXIMIZE:
+ ApplyContainerSetting(pContainer, CNT_VERTICALMAX, pContainer->dwFlags & CNT_VERTICALMAX ? 0 : 1, false);
+ break;
+ case ID_VIEW_BOTTOMTOOLBAR:
+ ApplyContainerSetting(pContainer, CNT_BOTTOMTOOLBAR, pContainer->dwFlags & CNT_BOTTOMTOOLBAR ? 0 : 1, false);
+ M->BroadcastMessage(DM_CONFIGURETOOLBAR, 0, 1);
+ return 0;
+ case ID_VIEW_SHOWTOOLBAR:
+ ApplyContainerSetting(pContainer, CNT_HIDETOOLBAR, pContainer->dwFlags & CNT_HIDETOOLBAR ? 0 : 1, false);
+ M->BroadcastMessage(DM_CONFIGURETOOLBAR, 0, 1);
+ return 0;
+ case ID_VIEW_SHOWMENUBAR:
+ ApplyContainerSetting(pContainer, CNT_NOMENUBAR, pContainer->dwFlags & CNT_NOMENUBAR ? 0 : 1, true);
+ break;
+ case ID_VIEW_SHOWTITLEBAR:
+ ApplyContainerSetting(pContainer, CNT_NOTITLE, pContainer->dwFlags & CNT_NOTITLE ? 0 : 1, true);
+ break;
+ case ID_VIEW_TABSATBOTTOM:
+ ApplyContainerSetting(pContainer, CNT_TABSBOTTOM, pContainer->dwFlags & CNT_TABSBOTTOM ? 0 : 1, false);
+ break;
+ case ID_VIEW_SHOWMULTISENDCONTACTLIST:
+ SendMessage(pContainer->hwndActive, WM_COMMAND, MAKEWPARAM(IDC_SENDMENU, ID_SENDMENU_SENDTOMULTIPLEUSERS), 0);
+ break;
+ case ID_VIEW_STAYONTOP:
+ SendMessage(hwndDlg, WM_SYSCOMMAND, IDM_STAYONTOP, 0);
+ break;
+ case ID_CONTAINER_CONTAINEROPTIONS:
+ SendMessage(hwndDlg, WM_SYSCOMMAND, IDM_MOREOPTIONS, 0);
+ break;
+ case ID_EVENTPOPUPS_DISABLEALLEVENTPOPUPS:
+ ApplyContainerSetting(pContainer, (CNT_DONTREPORT | CNT_DONTREPORTUNFOCUSED | CNT_DONTREPORTFOCUSED | CNT_ALWAYSREPORTINACTIVE), 0, false);
+ return 0;
+ case ID_EVENTPOPUPS_SHOWPOPUPSIFWINDOWISMINIMIZED:
+ ApplyContainerSetting(pContainer, CNT_DONTREPORT, pContainer->dwFlags & CNT_DONTREPORT ? 0 : 1, false);
+ return 0;
+ case ID_EVENTPOPUPS_SHOWPOPUPSIFWINDOWISUNFOCUSED:
+ ApplyContainerSetting(pContainer, CNT_DONTREPORTUNFOCUSED, pContainer->dwFlags & CNT_DONTREPORTUNFOCUSED ? 0 : 1, false);
+ return 0;
+ case ID_EVENTPOPUPS_SHOWPOPUPSIFWINDOWISFOCUSED:
+ ApplyContainerSetting(pContainer, CNT_DONTREPORTFOCUSED, pContainer->dwFlags & CNT_DONTREPORTFOCUSED ? 0 : 1, false);
+ return 0;
+ case ID_EVENTPOPUPS_SHOWPOPUPSFORALLINACTIVESESSIONS:
+ ApplyContainerSetting(pContainer, CNT_ALWAYSREPORTINACTIVE, pContainer->dwFlags & CNT_ALWAYSREPORTINACTIVE ? 0 : 1, false);
+ return 0;
+ case ID_WINDOWFLASHING_DISABLEFLASHING:
+ ApplyContainerSetting(pContainer, CNT_NOFLASH, 1, false);
+ ApplyContainerSetting(pContainer, CNT_FLASHALWAYS, 0, false);
+ return 0;
+ case ID_WINDOWFLASHING_FLASHUNTILFOCUSED:
+ ApplyContainerSetting(pContainer, CNT_NOFLASH, 0, false);
+ ApplyContainerSetting(pContainer, CNT_FLASHALWAYS, 1, false);
+ return 0;
+ case ID_WINDOWFLASHING_USEDEFAULTVALUES:
+ ApplyContainerSetting(pContainer, (CNT_NOFLASH | CNT_FLASHALWAYS), 0, false);
+ return 0;
+ case ID_OPTIONS_SAVECURRENTWINDOWPOSITIONASDEFAULT: {
+ WINDOWPLACEMENT wp = {0};
+
+ wp.length = sizeof(wp);
+ if (GetWindowPlacement(hwndDlg, &wp)) {
+ M->WriteDword(SRMSGMOD_T, "splitx", wp.rcNormalPosition.left);
+ M->WriteDword(SRMSGMOD_T, "splity", wp.rcNormalPosition.top);
+ M->WriteDword(SRMSGMOD_T, "splitwidth", wp.rcNormalPosition.right - wp.rcNormalPosition.left);
+ M->WriteDword(SRMSGMOD_T, "splitheight", wp.rcNormalPosition.bottom - wp.rcNormalPosition.top);
+ }
+ return 0;
+ }
+ case ID_VIEW_INFOPANEL: {
+ TWindowData *dat = (TWindowData *)GetWindowLongPtr(pContainer->hwndActive, GWLP_USERDATA);
+ if(dat) {
+ RECT rc;
+ POINT pt;
+ GetWindowRect(pContainer->hwndActive, &rc);
+ pt.x = rc.left + 10;
+ pt.y = rc.top + dat->Panel->getHeight() - 10;
+ dat->Panel->invokeConfigDialog(pt);
+ }
+ return(0);
+ }
+ /*
+ * commands from the message log popup will be routed to the
+ * message log menu handler
+ */
+ case ID_MESSAGELOGSETTINGS_FORTHISCONTACT:
+ case ID_MESSAGELOGSETTINGS_GLOBAL: {
+ struct TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(pContainer->hwndActive, GWLP_USERDATA);
+
+ if(dat) {
+ MsgWindowMenuHandler(dat, (int)LOWORD(wParam), MENU_LOGMENU);
+ return(1);
+ }
+ break;
+ }
+ case ID_HELP_ABOUTTABSRMM:
+ CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_ABOUT), 0, DlgProcAbout, 0);
+ break;
+ default:
+ return(0); // not handled
+ }
+ return(1); // handled
+}
+
+/**
+ * initialize rich edit control (log and edit control) for both MUC and
+ * standard IM session windows.
+ */
+void TSAPI DM_InitRichEdit(TWindowData *dat)
+
+{
+ char* szStreamOut = NULL;
+ SETTEXTEX stx = {ST_DEFAULT, CP_UTF8};
+ COLORREF colour;
+ COLORREF inputcharcolor;
+ CHARFORMAT2A cf2;
+ LOGFONTA lf;
+ int i = 0;
+ bool fIsChat = ((dat->bType == SESSIONTYPE_CHAT) ? true : false);
+ HWND hwndLog = GetDlgItem(dat->hwnd, !fIsChat ? IDC_LOG : IDC_CHAT_LOG);
+ HWND hwndEdit= GetDlgItem(dat->hwnd, !fIsChat ? IDC_MESSAGE : IDC_CHAT_MESSAGE);
+ HWND hwndDlg = dat->hwnd;
+
+ ZeroMemory(&cf2, sizeof(CHARFORMAT2A));
+
+ dat->inputbg = fIsChat ? M->GetDword(FONTMODULE, "inputbg", SRMSGDEFSET_BKGCOLOUR) : dat->pContainer->theme.inputbg;
+ colour = fIsChat ? M->GetDword(FONTMODULE, SRMSGSET_BKGCOLOUR_MUC, SRMSGDEFSET_BKGCOLOUR) : dat->pContainer->theme.bg;
+
+ if(!fIsChat) {
+ if (GetWindowTextLengthA(hwndEdit) > 0)
+ szStreamOut = Message_GetFromStream(hwndEdit, dat, (CP_UTF8 << 16) | (SF_RTFNOOBJS | SFF_PLAINRTF | SF_USECODEPAGE));
+ }
+
+ SendMessage(hwndLog, EM_SETBKGNDCOLOR, 0, colour);
+ SendMessage(hwndEdit, EM_SETBKGNDCOLOR, 0, dat->inputbg);
+
+ if(fIsChat)
+ LoadLogfont(MSGFONTID_MESSAGEAREA, &lf, &inputcharcolor, FONTMODULE);
+ else {
+ lf = dat->pContainer->theme.logFonts[MSGFONTID_MESSAGEAREA];
+ inputcharcolor = dat->pContainer->theme.fontColors[MSGFONTID_MESSAGEAREA];
+ }
+ /*
+ * correct the input area text color to avoid a color from the table of usable bbcode colors
+ */
+ if(!fIsChat) {
+ for (i = 0; i < Utils::rtf_ctable_size; i++) {
+ if (Utils::rtf_ctable[i].clr == inputcharcolor)
+ inputcharcolor = RGB(GetRValue(inputcharcolor), GetGValue(inputcharcolor), GetBValue(inputcharcolor) == 0 ? GetBValue(inputcharcolor) + 1 : GetBValue(inputcharcolor) - 1);
+ }
+ }
+ if(fIsChat) {
+ cf2.dwMask = CFM_COLOR | CFM_FACE | CFM_CHARSET | CFM_SIZE | CFM_WEIGHT | CFM_ITALIC | CFM_BACKCOLOR;
+ cf2.cbSize = sizeof(cf2);
+ cf2.crTextColor = inputcharcolor;
+ cf2.bCharSet = lf.lfCharSet;
+ cf2.crBackColor = dat->inputbg;
+ strncpy(cf2.szFaceName, lf.lfFaceName, LF_FACESIZE);
+ cf2.dwEffects = 0;
+ cf2.wWeight = (WORD)lf.lfWeight;
+ cf2.bPitchAndFamily = lf.lfPitchAndFamily;
+ cf2.yHeight = abs(lf.lfHeight) * 15;
+ SetWindowText(hwndEdit, _T(""));
+ SendMessage(hwndEdit, EM_SETCHARFORMAT, 0, (LPARAM)&cf2);
+ }
+ else {
+ cf2.dwMask = CFM_COLOR | CFM_FACE | CFM_CHARSET | CFM_SIZE | CFM_WEIGHT | CFM_BOLD | CFM_ITALIC;
+ cf2.cbSize = sizeof(cf2);
+ cf2.crTextColor = inputcharcolor;
+ cf2.bCharSet = lf.lfCharSet;
+ strncpy(cf2.szFaceName, lf.lfFaceName, LF_FACESIZE);
+ cf2.dwEffects = ((lf.lfWeight >= FW_BOLD) ? CFE_BOLD : 0) | (lf.lfItalic ? CFE_ITALIC : 0)|(lf.lfUnderline ? CFE_UNDERLINE : 0)|(lf.lfStrikeOut ? CFE_STRIKEOUT : 0);
+ cf2.wWeight = (WORD)lf.lfWeight;
+ cf2.bPitchAndFamily = lf.lfPitchAndFamily;
+ cf2.yHeight = abs(lf.lfHeight) * 15;
+ SendMessageA(hwndEdit, EM_SETCHARFORMAT, 0, (LPARAM)&cf2);
+ }
+
+ /*
+ * setup the rich edit control(s)
+ * LOG is always set to RTL, because this is needed for proper bidirectional operation later.
+ * The real text direction is then enforced by the streaming code which adds appropiate paragraph
+ * and textflow formatting commands to the
+ */
+
+ PARAFORMAT2 pf2;
+ ZeroMemory(&pf2, sizeof(PARAFORMAT2));
+
+ pf2.cbSize = sizeof(pf2);
+
+ pf2.wEffects = PFE_RTLPARA;
+ pf2.dwMask = PFM_RTLPARA;
+ if (Utils::FindRTLLocale(dat))
+ SendMessage(hwndEdit, EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
+ if (!(dat->dwFlags & MWF_LOG_RTL)) {
+ pf2.wEffects = 0;
+ SendMessage(hwndEdit, EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
+ }
+ SendMessage(hwndEdit, EM_SETLANGOPTIONS, 0, (LPARAM) SendMessage(hwndEdit, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD);
+ pf2.wEffects = PFE_RTLPARA;
+ pf2.dwMask |= PFM_OFFSET;
+ if (dat->dwFlags & MWF_INITMODE) {
+ pf2.dwMask |= (PFM_RIGHTINDENT | PFM_OFFSETINDENT);
+ pf2.dxStartIndent = 30;
+ pf2.dxRightIndent = 30;
+ }
+ pf2.dxOffset = dat->pContainer->theme.left_indent + 30;
+ if(!fIsChat) {
+ SetWindowText(hwndLog, _T(""));
+ SendMessage(hwndLog, EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
+ SendMessage(hwndLog, EM_SETLANGOPTIONS, 0, (LPARAM) SendDlgItemMessage(hwndDlg, IDC_LOG, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD);
+ }
+
+ /*
+ * set the scrollbars etc to RTL/LTR (only for manual RTL mode)
+ */
+
+ if(!fIsChat) {
+ if (dat->dwFlags & MWF_LOG_RTL) {
+ SetWindowLongPtr(hwndEdit, GWL_EXSTYLE, GetWindowLongPtr(hwndEdit, GWL_EXSTYLE) | WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR);
+ SetWindowLongPtr(hwndLog, GWL_EXSTYLE, GetWindowLongPtr(hwndLog, GWL_EXSTYLE) | WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR);
+ } else {
+ SetWindowLongPtr(hwndEdit, GWL_EXSTYLE, GetWindowLongPtr(hwndEdit, GWL_EXSTYLE) &~(WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR));
+ SetWindowLongPtr(hwndLog, GWL_EXSTYLE, GetWindowLongPtr(hwndLog, GWL_EXSTYLE) &~(WS_EX_RIGHT | WS_EX_RTLREADING | WS_EX_LEFTSCROLLBAR));
+ }
+ SetWindowText(hwndEdit, _T(""));
+ }
+ if (szStreamOut != NULL) {
+ SendMessage(hwndEdit, EM_SETTEXTEX, (WPARAM)&stx, (LPARAM)szStreamOut);
+ free(szStreamOut);
+ }
+}
+
+/*
+* action and callback procedures for the stock button objects
+*/
+
+static void BTN_StockAction(ButtonItem *item, HWND hwndDlg, struct TWindowData *dat, HWND hwndBtn)
+{
+ if (item->dwStockFlags & SBI_HANDLEBYCLIENT && IsWindow(hwndDlg) && dat)
+ SendMessage(hwndDlg, WM_COMMAND, MAKELONG(item->uId, BN_CLICKED), (LPARAM)hwndBtn);
+ else {
+ switch (item->uId) {
+ case IDC_SBAR_CANCEL:
+ PostMessage(hwndDlg, WM_COMMAND, MAKELONG(IDC_SAVE, BN_CLICKED), (LPARAM)hwndBtn);
+ break;
+ case IDC_SBAR_SLIST:
+ SendMessage(PluginConfig.g_hwndHotkeyHandler, DM_TRAYICONNOTIFY, 101, WM_LBUTTONUP);
+ break;
+ case IDC_SBAR_FAVORITES: {
+ POINT pt;
+ int iSelection;
+ GetCursorPos(&pt);
+ iSelection = TrackPopupMenu(PluginConfig.g_hMenuFavorites, TPM_RETURNCMD, pt.x, pt.y, 0, PluginConfig.g_hwndHotkeyHandler, NULL);
+ HandleMenuEntryFromhContact(iSelection);
+ break;
+ }
+ case IDC_SBAR_RECENT: {
+ POINT pt;
+ int iSelection;
+ GetCursorPos(&pt);
+ iSelection = TrackPopupMenu(PluginConfig.g_hMenuRecent, TPM_RETURNCMD, pt.x, pt.y, 0, PluginConfig.g_hwndHotkeyHandler, NULL);
+ HandleMenuEntryFromhContact(iSelection);
+ break;
+ }
+ case IDC_SBAR_USERPREFS: {
+ HANDLE hContact = 0;
+ SendMessage(hwndDlg, DM_QUERYHCONTACT, 0, (LPARAM)&hContact);
+ if (hContact != 0)
+ CallService(MS_TABMSG_SETUSERPREFS, (WPARAM)hContact, 0);
+ break;
+ }
+ case IDC_SBAR_TOGGLEFORMAT: {
+ if (dat) {
+ if (IsDlgButtonChecked(hwndDlg, IDC_SBAR_TOGGLEFORMAT) == BST_UNCHECKED) {
+ dat->SendFormat = 0;
+ GetSendFormat(dat, 0);
+ } else {
+ dat->SendFormat = SENDFORMAT_BBCODE;
+ GetSendFormat(dat, 0);
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+static void BTN_StockCallback(ButtonItem *item, HWND hwndDlg, struct TWindowData *dat, HWND hwndBtn)
+{
+}
+
+/*
+* predefined button objects for customizeable buttons
+*/
+
+static struct SIDEBARITEM sbarItems[] = {
+ 0, 0, 0, 0, 0, _T(""), NULL, NULL, _T("")
+};
+
+int TSAPI BTN_GetStockItem(ButtonItem *item, const TCHAR *szName)
+{
+ int i = 0;
+
+ while (sbarItems[i].uId) {
+ if (!_tcsicmp(sbarItems[i].szName, szName)) {
+ item->uId = sbarItems[i].uId;
+ //item->dwFlags |= BUTTON_ISSIDEBAR;
+ //myGlobals.m_SideBarEnabled = TRUE;
+ if (item->dwFlags & BUTTON_ISSIDEBAR) {
+ if (sbarItems[i].dwFlags & SBI_TOP)
+ item->yOff = 0;
+ else if (sbarItems[i].dwFlags & SBI_BOTTOM)
+ item->yOff = -1;
+ }
+ item->dwStockFlags = sbarItems[i].dwFlags;
+ item->dwFlags = sbarItems[i].dwFlags & SBI_TOGGLE ? item->dwFlags | BUTTON_ISTOGGLE : item->dwFlags & ~BUTTON_ISTOGGLE;
+ item->pfnAction = sbarItems[i].pfnAction;
+ item->pfnCallback = sbarItems[i].pfnCallback;
+ lstrcpyn(item->szTip, sbarItems[i].tszTip, 256);
+ item->szTip[255] = 0;
+ if (sbarItems[i].hIcon) {
+ item->normalGlyphMetrics[0] = (LONG_PTR)sbarItems[i].hIcon;
+ item->dwFlags |= BUTTON_NORMALGLYPHISICON;
+ }
+ if (sbarItems[i].hIconPressed) {
+ item->pressedGlyphMetrics[0] = (LONG_PTR)sbarItems[i].hIconPressed;
+ item->dwFlags |= BUTTON_PRESSEDGLYPHISICON;
+ }
+ if (sbarItems[i].hIconHover) {
+ item->hoverGlyphMetrics[0] = (LONG_PTR)sbarItems[i].hIconHover;
+ item->dwFlags |= BUTTON_HOVERGLYPHISICON;
+ }
+ return 1;
+ }
+ i++;
+ }
+ return 0;
+}
+
+/*
+* set the states of defined database action buttons (only if button is a toggle)
+*/
+
+void TSAPI DM_SetDBButtonStates(HWND hwndChild, struct TWindowData *dat)
+{
+ ButtonItem *buttonItem = dat->pContainer->buttonItems;
+ HANDLE hContact = dat->hContact, hFinalContact = 0;
+ char *szModule, *szSetting;
+ HWND hwndContainer = dat->pContainer->hwnd;;
+
+ while (buttonItem) {
+ BOOL result = FALSE;
+ HWND hWnd = GetDlgItem(hwndContainer, buttonItem->uId);
+
+ if (buttonItem->pfnCallback)
+ buttonItem->pfnCallback(buttonItem, hwndChild, dat, hWnd);
+
+ if (!(buttonItem->dwFlags & BUTTON_ISTOGGLE && buttonItem->dwFlags & BUTTON_ISDBACTION)) {
+ buttonItem = buttonItem->nextItem;
+ continue;
+ }
+ szModule = buttonItem->szModule;
+ szSetting = buttonItem->szSetting;
+ if (buttonItem->dwFlags & BUTTON_DBACTIONONCONTACT || buttonItem->dwFlags & BUTTON_ISCONTACTDBACTION) {
+ if (hContact == 0) {
+ SendMessage(hWnd, BM_SETCHECK, BST_UNCHECKED, 0);
+ buttonItem = buttonItem->nextItem;
+ continue;
+ }
+ if (buttonItem->dwFlags & BUTTON_ISCONTACTDBACTION)
+ szModule = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ hFinalContact = hContact;
+ } else
+ hFinalContact = 0;
+
+ if (buttonItem->type == DBVT_ASCIIZ) {
+ DBVARIANT dbv = {0};
+
+ if (!DBGetContactSettingString(hFinalContact, szModule, szSetting, &dbv)) {
+ result = !strcmp((char *)buttonItem->bValuePush, dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ } else {
+ switch (buttonItem->type) {
+ case DBVT_BYTE: {
+ BYTE val = M->GetByte(hFinalContact, szModule, szSetting, 0);
+ result = (val == buttonItem->bValuePush[0]);
+ break;
+ }
+ case DBVT_WORD: {
+ WORD val = DBGetContactSettingWord(hFinalContact, szModule, szSetting, 0);
+ result = (val == *((WORD *) & buttonItem->bValuePush));
+ break;
+ }
+ case DBVT_DWORD: {
+ DWORD val = M->GetDword(hFinalContact, szModule, szSetting, 0);
+ result = (val == *((DWORD *) & buttonItem->bValuePush));
+ break;
+ }
+ }
+ }
+ SendMessage(hWnd, BM_SETCHECK, (WPARAM)result, 0);
+ buttonItem = buttonItem->nextItem;
+ }
+}
+
+LRESULT TSAPI DM_ScrollToBottom(TWindowData *dat, WPARAM wParam, LPARAM lParam)
+{
+ if (dat) {
+
+ if (dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED)
+ return 0;
+
+ if (IsIconic(dat->pContainer->hwnd))
+ dat->dwFlags |= MWF_DEFERREDSCROLL;
+
+ if (dat->hwndIEView) {
+ PostMessage(dat->hwnd, DM_SCROLLIEVIEW, 0, 0);
+ return 0;
+ } else if (dat->hwndHPP) {
+ SendMessage(dat->hwnd, DM_SCROLLIEVIEW, 0, 0);
+ return 0;
+ } else {
+ HWND hwnd = GetDlgItem(dat->hwnd, dat->bType == SESSIONTYPE_IM ? IDC_LOG : IDC_CHAT_LOG);
+ if (lParam)
+ SendMessage(hwnd, WM_SIZE, 0, 0);
+
+ if (wParam == 1 && lParam == 1) {
+ RECT rc;
+ int len;
+
+ GetClientRect(hwnd, &rc);
+ len = GetWindowTextLengthA(hwnd);
+ SendMessage(hwnd, EM_SETSEL, len - 1, len - 1);
+ }
+ if (wParam)
+ SendMessage(hwnd, WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, 0), 0);
+ else
+ PostMessage(hwnd, WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, 0), 0);
+ if (lParam)
+ InvalidateRect(hwnd, NULL, FALSE);
+ }
+ }
+ return 0;
+}
+
+static unsigned __stdcall LoadKLThread(LPVOID vParam)
+{
+ HANDLE hContact = reinterpret_cast<HANDLE>(vParam);
+ DBVARIANT dbv = {0};
+
+ LRESULT res = M->GetTString(hContact, SRMSGMOD_T, "locale", &dbv);
+ if (res == 0) {
+ HKL hkl = LoadKeyboardLayout(dbv.ptszVal, 0);
+ PostMessage(PluginConfig.g_hwndHotkeyHandler, DM_SETLOCALE, (WPARAM)hContact, (LPARAM)hkl);
+ DBFreeVariant(&dbv);
+ }
+ return(0);
+}
+
+
+LRESULT TSAPI DM_LoadLocale(TWindowData *dat)
+{
+ /*
+ * set locale if saved to contact
+ */
+ if (dat) {
+ if (dat->dwFlags & MWF_WASBACKGROUNDCREATE)
+ return 0;
+
+ if (PluginConfig.m_AutoLocaleSupport) {
+ DBVARIANT dbv;
+ int res;
+ TCHAR szKLName[KL_NAMELENGTH+1];
+ UINT flags = KLF_ACTIVATE;
+
+ res = DBGetContactSettingTString(dat->hContact, SRMSGMOD_T, "locale", &dbv);
+ if (res == 0) {
+
+ /*
+ dat->hkl = LoadKeyboardLayout(dbv.ptszVal, KLF_REPLACELANG | KLF_NOTELLSHELL);
+ GetLocaleID(dat, dbv.ptszVal);
+ PostMessage(dat->hwnd, DM_SETLOCALE, 0, 0);*/
+ DBFreeVariant(&dbv);
+ CloseHandle((HANDLE)mir_forkthreadex(LoadKLThread, reinterpret_cast<void *>(dat->hContact), 16000, NULL));
+ } else {
+ if(!PluginConfig.m_dontUseDefaultKbd) {
+ TCHAR szBuf[20];
+
+ GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_ILANGUAGE, szBuf, 20);
+ mir_sntprintf(szKLName, KL_NAMELENGTH, _T("0000%s"), szBuf);
+ M->WriteTString(dat->hContact, SRMSGMOD_T, "locale", szKLName);
+ }
+ else {
+ GetKeyboardLayoutName(szKLName);
+ M->WriteTString(dat->hContact, SRMSGMOD_T, "locale", szKLName);
+ }
+ /*dat->hkl = LoadKeyboardLayout(szKLName, KLF_NOTELLSHELL | KLF_REPLACELANG);
+ GetLocaleID(dat, szKLName);
+ PostMessage(dat->hwnd, DM_SETLOCALE, 0, 0);*/
+ CloseHandle((HANDLE)mir_forkthreadex(LoadKLThread, reinterpret_cast<void *>(dat->hContact), 16000, NULL));
+ }
+ }
+ }
+ return 0;
+}
+
+LRESULT TSAPI DM_RecalcPictureSize(TWindowData *dat)
+{
+ BITMAP bminfo;
+ HBITMAP hbm;
+
+ if (dat) {
+ hbm = ((dat->Panel->isActive()) && dat->pContainer->avatarMode != 3) ? dat->hOwnPic : (dat->ace ? dat->ace->hbmPic : PluginConfig.g_hbmUnknown);
+
+ if (hbm == 0) {
+ dat->pic.cy = dat->pic.cx = 60;
+ return 0;
+ }
+ GetObject(hbm, sizeof(bminfo), &bminfo);
+ CalcDynamicAvatarSize(dat, &bminfo);
+ SendMessage(dat->hwnd, WM_SIZE, 0, 0);
+ }
+ return 0;
+}
+
+LRESULT TSAPI DM_UpdateLastMessage(const TWindowData *dat)
+{
+ if (dat) {
+ if (dat->pContainer->hwndStatus == 0)
+ return 0;
+ if (dat->pContainer->hwndActive != dat->hwnd)
+ return 0;
+ if (dat->showTyping) {
+ TCHAR szBuf[80];
+
+ mir_sntprintf(szBuf, safe_sizeof(szBuf), CTranslator::get(CTranslator::GEN_MTN_STARTWITHNICK), dat->cache->getNick());
+ SendMessage(dat->pContainer->hwndStatus, SB_SETTEXT, 0, (LPARAM) szBuf);
+ SendMessage(dat->pContainer->hwndStatus, SB_SETICON, 0, (LPARAM) PluginConfig.g_buttonBarIcons[ICON_DEFAULT_TYPING]);
+ return 0;
+ }
+ else
+ SendMessage(dat->pContainer->hwndStatus, SB_SETICON, 0, 0);
+
+ if (dat->lastMessage || dat->pContainer->dwFlags & CNT_UINSTATUSBAR) {
+ TCHAR date[64], time[64];
+
+ if (!(dat->pContainer->dwFlags & CNT_UINSTATUSBAR)) {
+ tmi.printTimeStamp(NULL, dat->lastMessage, _T("d"), date, safe_sizeof(date), 0);
+ if (dat->pContainer->dwFlags & CNT_UINSTATUSBAR && lstrlen(date) > 6)
+ date[lstrlen(date) - 5] = 0;
+ tmi.printTimeStamp(NULL, dat->lastMessage, _T("t"), time, safe_sizeof(time), 0);
+ }
+ if (dat->pContainer->dwFlags & CNT_UINSTATUSBAR) {
+ TCHAR fmt[100];
+ mir_sntprintf(fmt, safe_sizeof(fmt), _T("UID: %s"), dat->cache->getUIN());
+ SendMessage(dat->pContainer->hwndStatus, SB_SETTEXT, 0, (LPARAM)fmt);
+ } else {
+ TCHAR fmt[100];
+ mir_sntprintf(fmt, safe_sizeof(fmt), CTranslator::get(CTranslator::GEN_SBAR_LASTRECEIVED), date, time);
+ SendMessage(dat->pContainer->hwndStatus, SB_SETTEXT, 0, (LPARAM) fmt);
+ }
+ } else
+ SendMessageA(dat->pContainer->hwndStatus, SB_SETTEXTA, 0, (LPARAM) "");
+ }
+ return 0;
+}
+
+/*
+* save current keyboard layout for the given contact
+*/
+
+LRESULT TSAPI DM_SaveLocale(TWindowData *dat, WPARAM wParam, LPARAM lParam)
+{
+ if (dat) {
+ if (PluginConfig.m_AutoLocaleSupport && dat->hContact && dat->pContainer->hwndActive == dat->hwnd) {
+ TCHAR szKLName[KL_NAMELENGTH + 1];
+ if ((HKL)lParam != dat->hkl) {
+ dat->hkl = (HKL)lParam;
+ ActivateKeyboardLayout(dat->hkl, 0);
+ GetKeyboardLayoutName(szKLName);
+ M->WriteTString(dat->hContact, SRMSGMOD_T, "locale", szKLName);
+ GetLocaleID(dat, szKLName);
+ UpdateReadChars(dat);
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+* generic handler for the WM_COPY message in message log/chat history richedit control(s).
+* it filters out the invisible event boundary markers from the text copied to the clipboard.
+*/
+
+LRESULT TSAPI DM_WMCopyHandler(HWND hwnd, WNDPROC oldWndProc, WPARAM wParam, LPARAM lParam)
+{
+ LRESULT result = CallWindowProc(oldWndProc, hwnd, WM_COPY, wParam, lParam);
+
+ if (OpenClipboard(hwnd)) {
+ HANDLE hClip = GetClipboardData(CF_UNICODETEXT);
+ if (hClip) {
+ HGLOBAL hgbl;
+ TCHAR *tszLocked;
+ TCHAR *tszText = (TCHAR *)malloc((lstrlen((TCHAR *)hClip) + 2) * sizeof(TCHAR));
+
+ lstrcpy(tszText, (TCHAR *)hClip);
+ Utils::FilterEventMarkers(tszText);
+ EmptyClipboard();
+
+ hgbl = GlobalAlloc(GMEM_MOVEABLE, (lstrlen(tszText) + 1) * sizeof(TCHAR));
+ tszLocked = (TCHAR *)GlobalLock(hgbl);
+ lstrcpy(tszLocked, tszText);
+ GlobalUnlock(hgbl);
+ SetClipboardData(CF_UNICODETEXT, hgbl);
+ if (tszText)
+ free(tszText);
+ }
+ CloseClipboard();
+ }
+ return result;
+}
+
+/*
+* create embedded contact list control
+*/
+
+HWND TSAPI DM_CreateClist(TWindowData *dat)
+{
+ if(!sendLater->isAvail()) {
+ CWarning::show(CWarning::WARN_NO_SENDLATER, MB_OK|MB_ICONINFORMATION, CTranslator::get(CTranslator::QMGR_ERROR_NOMULTISEND));
+ dat->sendMode &= ~SMODE_MULTIPLE;
+ return(0);
+ }
+ HWND hwndClist = CreateWindowExA(0, "CListControl", "", WS_TABSTOP | WS_VISIBLE | WS_CHILD | 0x248,
+ 184, 0, 30, 30, dat->hwnd, (HMENU)IDC_CLIST, g_hInst, NULL);
+
+ //MAD: fix for little bug, when following code didn't work (another hack :) )
+ HANDLE hItem;
+ SendMessage(hwndClist, WM_TIMER, 14, 0);
+ //
+ hItem = (HANDLE) SendMessage(hwndClist, CLM_FINDCONTACT, (WPARAM) dat->hContact, 0);
+
+ SetWindowLongPtr(hwndClist, GWL_EXSTYLE, GetWindowLongPtr(hwndClist, GWL_EXSTYLE) & ~CLS_EX_TRACKSELECT);
+ SetWindowLongPtr(hwndClist, GWL_EXSTYLE, GetWindowLongPtr(hwndClist, GWL_EXSTYLE) | (CLS_EX_NOSMOOTHSCROLLING | CLS_EX_NOTRANSLUCENTSEL));
+ //MAD: show offline contacts in multi-send
+ if (!PluginConfig.m_AllowOfflineMultisend)
+ SetWindowLongPtr(hwndClist, GWL_STYLE, GetWindowLongPtr(hwndClist, GWL_STYLE) | CLS_HIDEOFFLINE);
+ //
+ if (hItem)
+ SendMessage(hwndClist, CLM_SETCHECKMARK, (WPARAM) hItem, 1);
+
+ if (CallService(MS_CLUI_GETCAPS, 0, 0) & CLUIF_DISABLEGROUPS && !M->GetByte("CList", "UseGroups", SETTING_USEGROUPS_DEFAULT))
+ SendMessage(hwndClist, CLM_SETUSEGROUPS, (WPARAM) FALSE, 0);
+ else
+ SendMessage(hwndClist, CLM_SETUSEGROUPS, (WPARAM) TRUE, 0);
+ if (CallService(MS_CLUI_GETCAPS, 0, 0) & CLUIF_HIDEEMPTYGROUPS && M->GetByte("CList", "HideEmptyGroups", SETTING_USEGROUPS_DEFAULT))
+ SendMessage(hwndClist, CLM_SETHIDEEMPTYGROUPS, (WPARAM) TRUE, 0);
+ else
+ SendMessage(hwndClist, CLM_SETHIDEEMPTYGROUPS, (WPARAM) FALSE, 0);
+ SendMessage(hwndClist, CLM_FIRST + 106, 0, 1);
+ SendMessage(hwndClist, CLM_AUTOREBUILD, 0, 0);
+ if(hwndClist)
+ RedrawWindow(hwndClist, 0, 0, RDW_INVALIDATE|RDW_ERASE|RDW_UPDATENOW);
+ return hwndClist;
+}
+
+LRESULT TSAPI DM_MouseWheelHandler(HWND hwnd, HWND hwndParent, struct TWindowData *mwdat, WPARAM wParam, LPARAM lParam)
+{
+ RECT rc, rc1;
+ POINT pt;
+ TCHITTESTINFO hti;
+ HWND hwndTab;
+ UINT uID = mwdat->bType == SESSIONTYPE_IM ? IDC_LOG : IDC_CHAT_LOG;
+ UINT uIDMsg = mwdat->bType == SESSIONTYPE_IM ? IDC_MESSAGE : IDC_CHAT_MESSAGE;
+
+ GetCursorPos(&pt);
+ GetWindowRect(hwnd, &rc);
+ if (PtInRect(&rc, pt))
+ return 1;
+ if (mwdat->pContainer->dwFlags & CNT_SIDEBAR) {
+ GetWindowRect(GetDlgItem(mwdat->pContainer->hwnd, IDC_SIDEBARUP), &rc);
+ GetWindowRect(GetDlgItem(mwdat->pContainer->hwnd, IDC_SIDEBARDOWN), &rc1);
+ rc.bottom = rc1.bottom;
+ if (PtInRect(&rc, pt)) {
+ short amount = (short)(HIWORD(wParam));
+ SendMessage(mwdat->pContainer->hwnd, WM_COMMAND, MAKELONG(amount > 0 ? IDC_SIDEBARUP : IDC_SIDEBARDOWN, 0), (LPARAM)uIDMsg);
+ return 0;
+ }
+ }
+ if (mwdat->bType == SESSIONTYPE_CHAT) { // scroll nick list by just hovering it
+ RECT rcNicklist;
+ GetWindowRect(GetDlgItem(mwdat->hwnd, IDC_LIST), &rcNicklist);
+ if (PtInRect(&rcNicklist, pt)) {
+ SendMessage(GetDlgItem(mwdat->hwnd, IDC_LIST), WM_MOUSEWHEEL, wParam, lParam);
+ return(0);
+ }
+ }
+ if (mwdat->hwndIEView)
+ GetWindowRect(mwdat->hwndIEView, &rc);
+ else if (mwdat->hwndHPP)
+ GetWindowRect(mwdat->hwndHPP, &rc);
+ else
+ GetWindowRect(GetDlgItem(hwndParent, uID), &rc);
+ if (PtInRect(&rc, pt)) {
+ HWND hwnd = (mwdat->hwndIEView || mwdat->hwndHPP) ? mwdat->hwndIWebBrowserControl : GetDlgItem(hwndParent, uID);
+ short wDirection = (short)HIWORD(wParam);
+
+ if (hwnd == 0)
+ hwnd = WindowFromPoint(pt);
+
+ if (LOWORD(wParam) & MK_SHIFT || M->GetByte("fastscroll", 0)) {
+ if (wDirection < 0)
+ SendMessage(hwnd, WM_VSCROLL, MAKEWPARAM(SB_PAGEDOWN, 0), 0);
+ else if (wDirection > 0)
+ SendMessage(hwnd, WM_VSCROLL, MAKEWPARAM(SB_PAGEUP, 0), 0);
+ } else
+ SendMessage(hwnd, WM_MOUSEWHEEL, wParam, lParam);
+ return 0;
+ }
+ hwndTab = GetDlgItem(mwdat->pContainer->hwnd, IDC_MSGTABS);
+ GetCursorPos(&hti.pt);
+ ScreenToClient(hwndTab, &hti.pt);
+ hti.flags = 0;
+ if (TabCtrl_HitTest(hwndTab, &hti) != -1) {
+ SendMessage(hwndTab, WM_MOUSEWHEEL, wParam, -1);
+ return 0;
+ }
+ return 1;
+}
+
+void TSAPI DM_FreeTheme(TWindowData *dat)
+{
+ if(dat) {
+ if (CMimAPI::m_pfnCloseThemeData) {
+ if(dat->hTheme) {
+ CMimAPI::m_pfnCloseThemeData(dat->hTheme);
+ dat->hTheme = 0;
+ }
+ if(dat->hThemeIP) {
+ CMimAPI::m_pfnCloseThemeData(dat->hThemeIP);
+ dat->hThemeIP = 0;
+ }
+ if(dat->hThemeToolbar) {
+ CMimAPI::m_pfnCloseThemeData(dat->hThemeToolbar);
+ dat->hThemeToolbar = 0;
+ }
+ }
+ }
+}
+
+LRESULT TSAPI DM_ThemeChanged(TWindowData *dat)
+{
+ CSkinItem *item_log = &SkinItems[ID_EXTBKHISTORY];
+ CSkinItem *item_msg = &SkinItems[ID_EXTBKINPUTAREA];
+
+ HWND hwnd = dat->hwnd;
+
+ dat->hTheme = (M->isVSAPIState() && CMimAPI::m_pfnOpenThemeData) ? CMimAPI::m_pfnOpenThemeData(hwnd, L"EDIT") : 0;
+
+ if (dat->bType == SESSIONTYPE_IM) {
+ if (dat->hTheme != 0 || (CSkin::m_skinEnabled && !item_log->IGNORED))
+ SetWindowLongPtr(GetDlgItem(hwnd, IDC_LOG), GWL_EXSTYLE, GetWindowLongPtr(GetDlgItem(hwnd, IDC_LOG), GWL_EXSTYLE) & ~WS_EX_STATICEDGE);
+ if (dat->hTheme != 0 || (CSkin::m_skinEnabled && !item_msg->IGNORED))
+ SetWindowLongPtr(GetDlgItem(hwnd, IDC_MESSAGE), GWL_EXSTYLE, GetWindowLongPtr(GetDlgItem(hwnd, IDC_MESSAGE), GWL_EXSTYLE) & ~WS_EX_STATICEDGE);
+ } else {
+ if (dat->hTheme != 0 || (CSkin::m_skinEnabled && !item_log->IGNORED)) {
+ SetWindowLongPtr(GetDlgItem(hwnd, IDC_CHAT_LOG), GWL_EXSTYLE, GetWindowLongPtr(GetDlgItem(hwnd, IDC_CHAT_LOG), GWL_EXSTYLE) & ~WS_EX_STATICEDGE);
+ SetWindowLongPtr(GetDlgItem(hwnd, IDC_LIST), GWL_EXSTYLE, GetWindowLongPtr(GetDlgItem(hwnd, IDC_LIST), GWL_EXSTYLE) & ~(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
+ }
+ if (dat->hTheme != 0 || (CSkin::m_skinEnabled && !item_msg->IGNORED))
+ SetWindowLongPtr(GetDlgItem(hwnd, IDC_CHAT_MESSAGE), GWL_EXSTYLE, GetWindowLongPtr(GetDlgItem(hwnd, IDC_CHAT_MESSAGE), GWL_EXSTYLE) & ~WS_EX_STATICEDGE);
+ }
+ dat->hThemeIP = M->isAero() ? CMimAPI::m_pfnOpenThemeData(hwnd, L"ButtonStyle") : 0;
+ dat->hThemeToolbar = (M->isAero() || (!CSkin::m_skinEnabled && M->isVSThemed())) ? CMimAPI::m_pfnOpenThemeData(hwnd, L"REBAR") : 0;
+
+ return 0;
+}
+
+/**
+ * send out message typing notifications (MTN) when the
+ * user is typing/editing text in the messgae input area.
+ */
+void TSAPI DM_NotifyTyping(struct TWindowData *dat, int mode)
+{
+ DWORD protoStatus;
+ DWORD protoCaps;
+ DWORD typeCaps;
+ const char* szProto = 0;
+ HANDLE hContact = 0;
+
+ if (dat && dat->hContact) {
+ DeletePopupsForContact(dat->hContact, PU_REMOVE_ON_TYPE);
+
+ if(dat->bIsMeta){
+ szProto = dat->cache->getActiveProto();
+ hContact = dat->cache->getActiveContact();
+ }
+ else {
+ szProto = dat->szProto;
+ hContact = dat->hContact;
+ }
+
+ /*
+ * editing user notes or preparing a message for queued delivery -> don't send MTN
+ */
+ if(dat->fEditNotesActive || dat->sendMode & SMODE_SENDLATER)
+ return;
+
+ /*
+ * allow supression of sending out TN for the contact (NOTE: for metacontacts, do NOT use the subcontact handle)
+ */
+ if (!M->GetByte(dat->hContact, SRMSGMOD, SRMSGSET_TYPING, M->GetByte(SRMSGMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW)))
+ return;
+
+ if (!dat->szProto) // should not, but who knows...
+ return;
+
+ /*
+ * check status and capabilities of the protocol
+ */
+ protoStatus = CallProtoService(szProto, PS_GETSTATUS, 0, 0);
+ protoCaps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0);
+ typeCaps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0);
+
+ if (!(typeCaps & PF4_SUPPORTTYPING))
+ return;
+ if (protoStatus < ID_STATUS_ONLINE)
+ return;
+
+ /*
+ * check visibility/invisibility lists to not "accidentially" send MTN to contacts who
+ * should not see them (privacy issue)
+ */
+ if (protoCaps & PF1_VISLIST && DBGetContactSettingWord(hContact, szProto, "ApparentMode", 0) == ID_STATUS_OFFLINE)
+ return;
+
+ if (protoCaps & PF1_INVISLIST && protoStatus == ID_STATUS_INVISIBLE && DBGetContactSettingWord(hContact, szProto, "ApparentMode", 0) != ID_STATUS_ONLINE)
+ return;
+
+ /*
+ * don't send to contacts which are not permanently added to the contact list,
+ * unless the option to ignore added status is set.
+ */
+ if (M->GetByte(dat->hContact, "CList", "NotOnList", 0)
+ && !M->GetByte(SRMSGMOD, SRMSGSET_TYPINGUNKNOWN, SRMSGDEFSET_TYPINGUNKNOWN))
+ return;
+ // End user check
+ dat->nTypeMode = mode;
+ CallService(MS_PROTO_SELFISTYPING, (WPARAM) hContact, dat->nTypeMode);
+ }
+}
+
+void TSAPI DM_OptionsApplied(TWindowData *dat, WPARAM wParam, LPARAM lParam)
+{
+ if(dat == 0)
+ return;
+
+ HWND hwndDlg = dat->hwnd;
+ TContainerData *m_pContainer = dat->pContainer;
+
+ dat->szMicroLf[0] = 0;
+ if (!(dat->pContainer->theme.isPrivate)) {
+ LoadThemeDefaults(dat->pContainer);
+ dat->dwFlags = dat->pContainer->theme.dwFlags;
+ }
+ LoadLocalFlags(hwndDlg, dat);
+
+ LoadTimeZone(dat);
+
+ if (dat->hContact && dat->szProto != NULL && dat->bIsMeta) {
+ DWORD dwForcedContactNum = 0;
+ CallService(MS_MC_GETFORCESTATE, (WPARAM)dat->hContact, (LPARAM)&dwForcedContactNum);
+ M->WriteDword(dat->hContact, SRMSGMOD_T, "tabSRMM_forced", dwForcedContactNum);
+ }
+
+ dat->showUIElements = m_pContainer->dwFlags & CNT_HIDETOOLBAR ? 0 : 1;
+
+ dat->dwFlagsEx = M->GetByte(SRMSGSET_SHOWURLS, SRMSGDEFSET_SHOWURLS) ? MWF_SHOW_URLEVENTS : 0;
+ dat->dwFlagsEx |= M->GetByte(SRMSGSET_SHOWFILES, SRMSGDEFSET_SHOWFILES) ? MWF_SHOW_FILEEVENTS : 0;
+ dat->dwFlagsEx |= M->GetByte(dat->hContact, "splitoverride", 0) ? MWF_SHOW_SPLITTEROVERRIDE : 0;
+ dat->Panel->getVisibility();
+
+ // small inner margins (padding) for the text areas
+
+ SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(0, 0));
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3));
+
+ GetSendFormat(dat, 1);
+ SetDialogToType(hwndDlg);
+ SendMessage(hwndDlg, DM_CONFIGURETOOLBAR, 0, 0);
+
+ DM_InitRichEdit(dat);
+ if (hwndDlg == m_pContainer->hwndActive)
+ SendMessage(m_pContainer->hwnd, WM_SIZE, 0, 0);
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_MESSAGE), NULL, FALSE);
+ if (!lParam)
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+
+ ShowWindow(dat->hwndPanelPicParent, PluginConfig.g_bDisableAniAvatars ? SW_HIDE : SW_SHOW);
+ EnableWindow(dat->hwndPanelPicParent, PluginConfig.g_bDisableAniAvatars ? FALSE : TRUE);
+
+ SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0);
+}
+
+
+void TSAPI DM_Typing(TWindowData *dat, bool fForceOff)
+{
+ if(dat == 0)
+ return;
+
+ HWND hwndDlg = dat->hwnd;
+ HWND hwndContainer = dat->pContainer->hwnd;
+ HWND hwndStatus = dat->pContainer->hwndStatus;
+
+ if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON && GetTickCount() - dat->nLastTyping > TIMEOUT_TYPEOFF) {
+ DM_NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF);
+ }
+ if (dat->showTyping == 1) {
+ if (dat->nTypeSecs > 0) {
+ dat->nTypeSecs--;
+ if (GetForegroundWindow() == hwndContainer)
+ SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0);
+ } else {
+ struct TWindowData *dat_active = NULL;
+
+ if(!fForceOff) {
+ dat->showTyping = 2;
+ dat->nTypeSecs = 86400;
+
+ mir_sntprintf(dat->szStatusBar, safe_sizeof(dat->szStatusBar),
+ CTranslator::get(CTranslator::GEN_MTN_STOPPED), dat->cache->getNick());
+ if(hwndStatus && dat->pContainer->hwndActive == hwndDlg)
+ SendMessage(hwndStatus, SB_SETTEXT, 0, (LPARAM) dat->szStatusBar);
+ }
+ SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0);
+ HandleIconFeedback(dat, (HICON) - 1);
+ dat_active = (struct TWindowData *)GetWindowLongPtr(dat->pContainer->hwndActive, GWLP_USERDATA);
+ if (dat_active && dat_active->bType == SESSIONTYPE_IM)
+ SendMessage(hwndContainer, DM_UPDATETITLE, 0, 0);
+ else
+ SendMessage(hwndContainer, DM_UPDATETITLE, (WPARAM)dat->pContainer->hwndActive, (LPARAM)1);
+ if (!(dat->pContainer->dwFlags & CNT_NOFLASH) && PluginConfig.m_FlashOnMTN)
+ ReflashContainer(dat->pContainer);
+ }
+ } else if(dat->showTyping == 2) {
+ if (dat->nTypeSecs > 0)
+ dat->nTypeSecs--;
+ else {
+ dat->szStatusBar[0] = 0;
+ dat->showTyping = 0;
+ }
+ UpdateStatusBar(dat);
+ }
+ else {
+ if (dat->nTypeSecs > 0) {
+ mir_sntprintf(dat->szStatusBar, safe_sizeof(dat->szStatusBar), CTranslator::get(CTranslator::GEN_MTN_STARTWITHNICK), dat->cache->getNick());
+
+ dat->nTypeSecs--;
+ if (hwndStatus && dat->pContainer->hwndActive == hwndDlg) {
+ SendMessage(hwndStatus, SB_SETTEXT, 0, (LPARAM) dat->szStatusBar);
+ SendMessage(hwndStatus, SB_SETICON, 0, (LPARAM) PluginConfig.g_buttonBarIcons[ICON_DEFAULT_TYPING]);
+ }
+ if (IsIconic(hwndContainer) || GetForegroundWindow() != hwndContainer || GetActiveWindow() != hwndContainer) {
+ SetWindowText(hwndContainer, dat->szStatusBar);
+ dat->pContainer->dwFlags |= CNT_NEED_UPDATETITLE;
+ if (!(dat->pContainer->dwFlags & CNT_NOFLASH) && PluginConfig.m_FlashOnMTN)
+ ReflashContainer(dat->pContainer);
+ }
+ if (dat->pContainer->hwndActive != hwndDlg) {
+ if (dat->mayFlashTab)
+ dat->iFlashIcon = PluginConfig.g_IconTypingEvent;
+ HandleIconFeedback(dat, PluginConfig.g_IconTypingEvent);
+ } else { // active tab may show icon if status bar is disabled
+ if (!hwndStatus) {
+ if (TabCtrl_GetItemCount(GetParent(hwndDlg)) > 1 || !(dat->pContainer->dwFlags & CNT_HIDETABS)) {
+ HandleIconFeedback(dat, PluginConfig.g_IconTypingEvent);
+ }
+ }
+ }
+ if ((GetForegroundWindow() != hwndContainer) || (dat->pContainer->hwndStatus == 0) || (dat->pContainer->hwndActive != hwndDlg))
+ SendMessage(hwndContainer, DM_SETICON, (WPARAM)dat, (LPARAM) PluginConfig.g_buttonBarIcons[ICON_DEFAULT_TYPING]);
+ dat->showTyping = 1;
+ }
+ }
+}
+
+/**
+ * sync splitter position for all open sessions.
+ * This cares about private / per container / MUC <> IM splitter syncing and everything.
+ * called from IM and MUC windows via DM_SPLITTERGLOBALEVENT
+ */
+int TSAPI DM_SplitterGlobalEvent(TWindowData *dat, WPARAM wParam, LPARAM lParam)
+{
+ RECT rcWin;
+ short newMessagePos;
+ LONG newPos;
+ TWindowData* srcDat = PluginConfig.lastSPlitterPos.pSrcDat;
+ TContainerData* srcCnt = PluginConfig.lastSPlitterPos.pSrcContainer;
+ bool fCntGlobal = (!dat->pContainer->settings->fPrivate ? true : false);
+
+#if defined(__FEAT_EXP_AUTOSPLITTER)
+ if(dat->fIsAutosizingInput)
+ return(0);
+#endif
+
+ GetWindowRect(dat->hwnd, &rcWin);
+
+ if(wParam == 0 && lParam == 0) {
+ if((dat->dwFlagsEx & MWF_SHOW_SPLITTEROVERRIDE) && dat != srcDat)
+ return(0);
+
+ if(srcDat->bType == dat->bType)
+ newPos = PluginConfig.lastSPlitterPos.pos;
+ else if(srcDat->bType == SESSIONTYPE_IM && dat->bType == SESSIONTYPE_CHAT)
+ newPos = PluginConfig.lastSPlitterPos.pos + PluginConfig.lastSPlitterPos.off_im;
+ else if(srcDat->bType == SESSIONTYPE_CHAT && dat->bType == SESSIONTYPE_IM)
+ newPos = PluginConfig.lastSPlitterPos.pos + PluginConfig.lastSPlitterPos.off_im;
+
+ if(dat == srcDat) {
+ if(dat->bType == SESSIONTYPE_IM) {
+ dat->pContainer->settings->splitterPos = dat->splitterY;
+ if(fCntGlobal) {
+ SaveSplitter(dat);
+ if(PluginConfig.lastSPlitterPos.bSync)
+ g_Settings.iSplitterY = dat->splitterY - DPISCALEY_S(23);
+ }
+ }
+ if(dat->bType == SESSIONTYPE_CHAT) {
+ SESSION_INFO *si = dat->si;
+ if(si) {
+ dat->pContainer->settings->splitterPos = si->iSplitterY + DPISCALEY_S(23);
+ if(fCntGlobal) {
+ g_Settings.iSplitterY = si->iSplitterY;
+ if(PluginConfig.lastSPlitterPos.bSync)
+ M->WriteDword(SRMSGMOD_T, "splitsplity", (DWORD)si->iSplitterY + DPISCALEY_S(23));
+ }
+ }
+ }
+ return(0);
+ }
+
+ if(!fCntGlobal && dat->pContainer != srcCnt)
+ return(0);
+ if(srcCnt->settings->fPrivate && dat->pContainer != srcCnt)
+ return(0);
+
+ if(!PluginConfig.lastSPlitterPos.bSync && dat->bType != srcDat->bType)
+ return(0);
+
+ /*
+ * for inactive sessions, delay the splitter repositioning until they become
+ * active (faster, avoid redraw/resize problems for minimized windows)
+ */
+ if (IsIconic(dat->pContainer->hwnd) || dat->pContainer->hwndActive != dat->hwnd) {
+ dat->dwFlagsEx |= MWF_EX_DELAYEDSPLITTER;
+ dat->wParam = newPos;
+ dat->lParam = PluginConfig.lastSPlitterPos.lParam;
+ return(0);
+ }
+ }
+ else
+ newPos = wParam;
+
+ newMessagePos = (short)rcWin.bottom - (short)newPos;
+
+ if(dat->bType == SESSIONTYPE_IM) {
+ LoadSplitter(dat);
+ AdjustBottomAvatarDisplay(dat);
+ DM_RecalcPictureSize(dat);
+ SendMessage(dat->hwnd, WM_SIZE, 0, 0);
+ DM_ScrollToBottom(dat, 1,1);
+ if(dat != srcDat)
+ CSkin::UpdateToolbarBG(dat);
+ }
+ else {
+ SESSION_INFO *si = dat->si;
+ if(si) {
+ si->iSplitterY = g_Settings.iSplitterY;
+ SendMessage(dat->hwnd, WM_SIZE, 0, 0);
+ }
+ }
+ return(0);
+}
+
+/**
+ * incoming event handler
+ */
+
+void TSAPI DM_EventAdded(TWindowData *dat, WPARAM wParam, LPARAM lParam)
+{
+ TContainerData *m_pContainer = dat->pContainer;
+ DBEVENTINFO dbei = {0};
+ DWORD dwTimestamp = 0;
+ BOOL fIsStatusChangeEvent = FALSE, fIsNotifyEvent = FALSE;
+ HWND hwndDlg = dat->hwnd, hwndContainer = m_pContainer->hwnd, hwndTab = GetParent(dat->hwnd);
+
+ dbei.cbSize = sizeof(dbei);
+ dbei.cbBlob = 0;
+
+ CallService(MS_DB_EVENT_GET, lParam, (LPARAM) & dbei);
+ if (dat->hDbEventFirst == NULL)
+ dat->hDbEventFirst = (HANDLE) lParam;
+
+ fIsStatusChangeEvent = IsStatusEvent(dbei.eventType);
+ fIsNotifyEvent = (dbei.eventType == EVENTTYPE_MESSAGE || dbei.eventType == EVENTTYPE_FILE);
+
+ if (!fIsStatusChangeEvent) {
+ int heFlags = HistoryEvents_GetFlags(dbei.eventType);
+ if (heFlags != -1 && !(heFlags & HISTORYEVENTS_FLAG_DEFAULT) && !(heFlags & HISTORYEVENTS_FLAG_FLASH_MSG_WINDOW))
+ fIsStatusChangeEvent = TRUE;
+ }
+
+ if (dbei.eventType == EVENTTYPE_MESSAGE && (dbei.flags & DBEF_READ))
+ return;
+
+ if (DbEventIsShown(dat, &dbei)) {
+ if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & (DBEF_SENT))) {
+ dat->lastMessage = dbei.timestamp;
+ dat->szStatusBar[0] = 0;
+ if(dat->showTyping) {
+ dat->nTypeSecs = 0;
+ DM_Typing(dat, true);
+ dat->showTyping = 0;
+ }
+ HandleIconFeedback(dat, (HICON)-1);
+ if(m_pContainer->hwndStatus)
+ PostMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0);
+ }
+ /*
+ * set the message log divider to mark new (maybe unseen) messages, if the container has
+ * been minimized or in the background.
+ */
+ if (!(dbei.flags & DBEF_SENT) && !fIsStatusChangeEvent) {
+
+ if (PluginConfig.m_DividersUsePopupConfig && PluginConfig.m_UseDividers) {
+ if (!MessageWindowOpened((WPARAM)dat->hContact, 0))
+ SendMessage(hwndDlg, DM_ADDDIVIDER, 0, 0);
+ } else if (PluginConfig.m_UseDividers) {
+ if ((GetForegroundWindow() != hwndContainer || GetActiveWindow() != hwndContainer))
+ SendMessage(hwndDlg, DM_ADDDIVIDER, 0, 0);
+ else {
+ if (m_pContainer->hwndActive != hwndDlg)
+ SendMessage(hwndDlg, DM_ADDDIVIDER, 0, 0);
+ }
+ }
+ tabSRMM_ShowPopup(wParam, lParam, dbei.eventType, m_pContainer->fHidden ? 0 : 1, m_pContainer, hwndDlg, dat->cache->getActiveProto(), dat);
+ if(IsWindowVisible(m_pContainer->hwnd))
+ m_pContainer->fHidden = false;
+ }
+ dat->cache->updateStats(TSessionStats::UPDATE_WITH_LAST_RCV, 0);
+
+ if ((HANDLE) lParam != dat->hDbEventFirst) {
+ HANDLE nextEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, lParam, 0);
+ if (1 || nextEvent == 0) {
+ if (!(dat->dwFlagsEx & MWF_SHOW_SCROLLINGDISABLED))
+ SendMessage(hwndDlg, DM_APPENDTOLOG, lParam, 0);
+ else {
+ TCHAR szBuf[100];
+
+ if (dat->iNextQueuedEvent >= dat->iEventQueueSize) {
+ dat->hQueuedEvents = (HANDLE *)realloc(dat->hQueuedEvents, (dat->iEventQueueSize + 10) * sizeof(HANDLE));
+ dat->iEventQueueSize += 10;
+ }
+ dat->hQueuedEvents[dat->iNextQueuedEvent++] = (HANDLE)lParam;
+ mir_sntprintf(szBuf, safe_sizeof(szBuf), CTranslator::get(CTranslator::GEN_MSG_LOGFROZENQUEUED),
+ dat->iNextQueuedEvent);
+ SetDlgItemText(hwndDlg, IDC_LOGFROZENTEXT, szBuf);
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_LOGFROZENTEXT), NULL, NULL, RDW_INVALIDATE);
+ }
+ } else
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+ } else
+ SendMessage(hwndDlg, DM_REMAKELOG, 0, 0);
+
+ // handle tab flashing
+
+ if ((TabCtrl_GetCurSel(hwndTab) != dat->iTabID) && !(dbei.flags & DBEF_SENT) && !fIsStatusChangeEvent) {
+ switch (dbei.eventType) {
+ case EVENTTYPE_MESSAGE:
+ dat->iFlashIcon = PluginConfig.g_IconMsgEvent;
+ break;
+ case EVENTTYPE_FILE:
+ dat->iFlashIcon = PluginConfig.g_IconFileEvent;
+ break;
+ default:
+ dat->iFlashIcon = PluginConfig.g_IconMsgEvent;
+ break;
+ }
+ SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL);
+ dat->mayFlashTab = TRUE;
+ }
+ /*
+ * try to flash the contact list...
+ */
+
+ FlashOnClist(hwndDlg, dat, (HANDLE)lParam, &dbei);
+ /*
+ * autoswitch tab if option is set AND container is minimized (otherwise, we never autoswitch)
+ * never switch for status changes...
+ */
+ if (!(dbei.flags & DBEF_SENT) && !fIsStatusChangeEvent) {
+ if(PluginConfig.haveAutoSwitch() && m_pContainer->hwndActive != hwndDlg) {
+ if ((IsIconic(hwndContainer) && !IsZoomed(hwndContainer)) || (PluginConfig.m_HideOnClose && !IsWindowVisible(m_pContainer->hwnd))) {
+ int iItem = GetTabIndexFromHWND(GetParent(hwndDlg), hwndDlg);
+ if (iItem >= 0) {
+ TabCtrl_SetCurSel(GetParent(hwndDlg), iItem);
+ ShowWindow(m_pContainer->hwndActive, SW_HIDE);
+ m_pContainer->hwndActive = hwndDlg;
+ SendMessage(hwndContainer, DM_UPDATETITLE, (WPARAM)dat->hContact, 0);
+ m_pContainer->dwFlags |= CNT_DEFERREDTABSELECT;
+ }
+ }
+ }
+ }
+ /*
+ * flash window if it is not focused
+ */
+ if ((GetActiveWindow() != hwndContainer || GetForegroundWindow() != hwndContainer || dat->pContainer->hwndActive != hwndDlg) && !(dbei.flags & DBEF_SENT) && !fIsStatusChangeEvent) {
+ if (!(m_pContainer->dwFlags & CNT_NOFLASH) && (GetActiveWindow() != hwndContainer || GetForegroundWindow() != hwndContainer))
+ FlashContainer(m_pContainer, 1, 0);
+ SendMessage(hwndContainer, DM_SETICON, (WPARAM)dat, (LPARAM)LoadSkinnedIcon(SKINICON_EVENT_MESSAGE));
+ m_pContainer->dwFlags |= CNT_NEED_UPDATETITLE;
+ }
+ /*
+ * play a sound
+ */
+ if (dbei.eventType == EVENTTYPE_MESSAGE && !(dbei.flags & (DBEF_SENT)))
+ PostMessage(hwndDlg, DM_PLAYINCOMINGSOUND, 0, 0);
+
+ if(dat->pWnd)
+ dat->pWnd->Invalidate();
+ }
+}
+
+void TSAPI DM_HandleAutoSizeRequest(TWindowData *dat, REQRESIZE* rr)
+{
+ if(dat && rr && GetForegroundWindow() == dat->pContainer->hwnd) {
+ if(dat->fIsAutosizingInput && dat->iInputAreaHeight != -1) {
+ LONG heightLimit = M->GetDword("autoSplitMinLimit", 0);
+ LONG iNewHeight = rr->rc.bottom - rr->rc.top;
+
+ if(CSkin::m_skinEnabled && !SkinItems[ID_EXTBKINPUTAREA].IGNORED)
+ iNewHeight += (SkinItems[ID_EXTBKINPUTAREA].MARGIN_TOP + SkinItems[ID_EXTBKINPUTAREA].MARGIN_BOTTOM - 2);
+
+ if(heightLimit && iNewHeight < heightLimit)
+ iNewHeight = heightLimit;
+
+ if(iNewHeight != dat->iInputAreaHeight) {
+ RECT rc;
+
+ GetClientRect(dat->hwnd, &rc);
+ LONG cy = rc.bottom - rc.top;
+ LONG panelHeight = (dat->Panel->isActive() ? dat->Panel->getHeight() : 0);
+
+ if(iNewHeight > (cy - panelHeight) / 2)
+ iNewHeight = (cy - panelHeight) / 2;
+
+ if(dat->bType == SESSIONTYPE_IM) {
+ dat->dynaSplitter = rc.bottom - (rc.bottom - iNewHeight + DPISCALEY_S(2));
+ if(dat->pContainer->dwFlags & CNT_BOTTOMTOOLBAR)
+ dat->dynaSplitter += DPISCALEY_S(22);
+ dat->splitterY = dat->dynaSplitter + DPISCALEY_S(34);
+ DM_RecalcPictureSize(dat);
+ }
+ else if (dat->si) {
+ dat->si->iSplitterY = (rc.bottom - (rc.bottom - iNewHeight + DPISCALEY_S(3))) + DPISCALEY_S(34);
+ if(!(dat->pContainer->dwFlags & CNT_BOTTOMTOOLBAR))
+ dat->si->iSplitterY -= DPISCALEY_S(22);
+ SendMessage(dat->hwnd, WM_SIZE, 0, 0);
+ }
+ dat->iInputAreaHeight = iNewHeight;
+ CSkin::UpdateToolbarBG(dat);
+ DM_ScrollToBottom(dat, 1, 0);
+ }
+ }
+ }
+}
+
+void TSAPI DM_UpdateTitle(TWindowData *dat, WPARAM wParam, LPARAM lParam)
+{
+ TCHAR newtitle[128];
+ TCHAR* pszNewTitleEnd;
+ TCHAR newcontactname[128];
+ TCITEM item;
+ DWORD dwOldIdle = dat->idle;
+ const char* szActProto = 0;
+ HANDLE hActContact = 0;
+
+ HWND hwndDlg = dat->hwnd;
+ HWND hwndTab = GetParent(hwndDlg);
+ HWND hwndContainer = dat->pContainer->hwnd;
+ TContainerData* m_pContainer = dat->pContainer;
+
+ ZeroMemory((void *)newcontactname, sizeof(newcontactname));
+ dat->szStatus[0] = 0;
+
+ pszNewTitleEnd = _T("Message Session");
+
+ if (dat->iTabID == -1)
+ return;
+
+ ZeroMemory((void *)&item, sizeof(item));
+ if (dat->hContact) {
+ int iHasName;
+ TCHAR fulluin[256];
+ const TCHAR* szNick = dat->cache->getNick();
+
+ if (dat->szProto) {
+
+ szActProto = dat->cache->getActiveProto();
+ hActContact = dat->hContact;
+
+ iHasName = (dat->cache->getUIN()[0] != 0);
+ dat->idle = dat->cache->getIdleTS();
+ dat->dwFlagsEx = dat->idle ? dat->dwFlagsEx | MWF_SHOW_ISIDLE : dat->dwFlagsEx & ~MWF_SHOW_ISIDLE;
+
+ dat->wStatus = dat->cache->getStatus();
+ mir_sntprintf(dat->szStatus, safe_sizeof(dat->szStatus), _T("%s"), (char *) CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, dat->szProto == NULL ? ID_STATUS_OFFLINE : dat->wStatus, GSMDF_TCHAR));
+
+ if (lParam != 0) {
+ if (PluginConfig.m_CutContactNameOnTabs)
+ CutContactName(szNick, newcontactname, safe_sizeof(newcontactname));
+ else
+ lstrcpyn(newcontactname, szNick, safe_sizeof(newcontactname));
+
+ Utils::DoubleAmpersands(newcontactname);
+
+ if (lstrlen(newcontactname) != 0 && dat->szStatus != NULL) {
+ if (PluginConfig.m_StatusOnTabs)
+ mir_sntprintf(newtitle, 127, _T("%s (%s)"), newcontactname, dat->szStatus);
+ else
+ mir_sntprintf(newtitle, 127, _T("%s"), newcontactname);
+ } else
+ mir_sntprintf(newtitle, 127, _T("%s"), _T("Forward"));
+
+ item.mask |= TCIF_TEXT;
+ }
+ SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0);
+ if (dat->bIsMeta)
+ mir_sntprintf(fulluin, safe_sizeof(fulluin),
+ CTranslator::get(CTranslator::GEN_MSG_UINCOPY),
+ iHasName ? dat->cache->getUIN() : CTranslator::get(CTranslator::GEN_MSG_NOUIN));
+ else
+ mir_sntprintf(fulluin, safe_sizeof(fulluin),
+ CTranslator::get(CTranslator::GEN_MSG_UINCOPY_NOMC),
+ iHasName ? dat->cache->getUIN() : CTranslator::get(CTranslator::GEN_MSG_NOUIN));
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_NAME), BUTTONADDTOOLTIP, /*iHasName ?*/ (WPARAM)fulluin /*: (WPARAM)_T("")*/, 0);
+ }
+ } else
+ lstrcpyn(newtitle, pszNewTitleEnd, safe_sizeof(newtitle));
+
+ if (dat->idle != dwOldIdle || lParam != 0) {
+
+ if (item.mask & TCIF_TEXT) {
+ item.pszText = newtitle;
+ _tcsncpy(dat->newtitle, newtitle, safe_sizeof(dat->newtitle));
+ dat->newtitle[127] = 0;
+ item.cchTextMax = 127;
+ if(dat->pWnd)
+ dat->pWnd->updateTitle(dat->cache->getNick());
+ }
+ if (dat->iTabID >= 0) {
+ TabCtrl_SetItem(hwndTab, dat->iTabID, &item);
+ if(m_pContainer->dwFlags & CNT_SIDEBAR)
+ m_pContainer->SideBar->updateSession(dat);
+ }
+ if (m_pContainer->hwndActive == hwndDlg && lParam)
+ SendMessage(hwndContainer, DM_UPDATETITLE, (WPARAM)dat->hContact, 0);
+
+ UpdateTrayMenuState(dat, TRUE);
+ if (dat->cache->isFavorite())
+ AddContactToFavorites(dat->hContact, dat->cache->getNick(), szActProto, dat->szStatus, dat->wStatus,
+ LoadSkinnedProtoIcon(dat->cache->getActiveProto(), dat->cache->getActiveStatus()), 0, PluginConfig.g_hMenuFavorites);
+ if (dat->cache->isRecent()) {
+ AddContactToFavorites(dat->hContact, dat->cache->getNick(), szActProto, dat->szStatus, dat->wStatus,
+ LoadSkinnedProtoIcon(dat->cache->getActiveProto(), dat->cache->getActiveStatus()), 0, PluginConfig.g_hMenuRecent);
+ }
+
+ dat->Panel->Invalidate();
+ if(dat->pWnd)
+ dat->pWnd->Invalidate();
+
+ if (PluginConfig.g_FlashAvatarAvail) {
+ FLASHAVATAR fa = {0};
+
+ fa.hContact = dat->hContact;
+ fa.hWindow = 0;
+ fa.id = 25367;
+ fa.cProto = dat->szProto;
+
+ CallService(MS_FAVATAR_GETINFO, (WPARAM)&fa, 0);
+ dat->hwndFlash = fa.hWindow;
+ if (dat->hwndFlash) {
+ bool isInfoPanel = dat->Panel->isActive();
+ SetParent(dat->hwndFlash, isInfoPanel ? dat->hwndPanelPicParent : GetDlgItem(hwndDlg, IDC_CONTACTPIC));
+ }
+ }
+ }
+ // care about MetaContacts and update the statusbar icon with the currently "most online" contact...
+ if (dat->bIsMeta) {
+ PostMessage(hwndDlg, DM_UPDATEMETACONTACTINFO, 0, 0);
+ PostMessage(hwndDlg, DM_OWNNICKCHANGED, 0, 0);
+ if (m_pContainer->dwFlags & CNT_UINSTATUSBAR)
+ DM_UpdateLastMessage(dat);
+ }
+}
+
+/*
+* status icon stuff (by sje, used for indicating encryption status in the status bar
+* this is now part of the message window api
+*/
+
+static HANDLE hHookIconPressedEvt;
+struct TStatusBarIconNode *status_icon_list = 0;
+int status_icon_list_size = 0;
+
+static INT_PTR SI_AddStatusIcon(WPARAM wParam, LPARAM lParam)
+{
+ StatusIconData *sid = (StatusIconData *)lParam;
+ struct TStatusBarIconNode *siln = (struct TStatusBarIconNode *)mir_alloc(sizeof(struct TStatusBarIconNode));
+
+ siln->sid.cbSize = sid->cbSize;
+ siln->sid.szModule = mir_strdup(sid->szModule);
+ siln->sid.dwId = sid->dwId;
+ siln->sid.hIcon = sid->hIcon;
+ siln->sid.hIconDisabled = sid->hIconDisabled;
+ siln->sid.flags = sid->flags;
+ if (sid->szTooltip) siln->sid.szTooltip = mir_strdup(sid->szTooltip);
+ else siln->sid.szTooltip = 0;
+
+ siln->next = status_icon_list;
+ status_icon_list = siln;
+ status_icon_list_size++;
+
+ M->BroadcastMessage(DM_STATUSICONCHANGE, 0, 0);
+ return 0;
+}
+
+static INT_PTR SI_RemoveStatusIcon(WPARAM wParam, LPARAM lParam)
+{
+ StatusIconData *sid = (StatusIconData *)lParam;
+ struct TStatusBarIconNode *current = status_icon_list, *prev = 0;
+
+ while (current) {
+ if (strcmp(current->sid.szModule, sid->szModule) == 0 && current->sid.dwId == sid->dwId) {
+ if (prev) prev->next = current->next;
+ else status_icon_list = current->next;
+
+ status_icon_list_size--;
+
+ mir_free(current->sid.szModule);
+ DestroyIcon(current->sid.hIcon);
+ if (current->sid.hIconDisabled) DestroyIcon(current->sid.hIconDisabled);
+ if (current->sid.szTooltip) mir_free(current->sid.szTooltip);
+ mir_free(current);
+ M->BroadcastMessage(DM_STATUSICONCHANGE, 0, 0);
+ return 0;
+ }
+
+ prev = current;
+ current = current->next;
+ }
+ return 1;
+}
+
+static void SI_RemoveAllStatusIcons(void)
+{
+ struct TStatusBarIconNode *current;
+
+ while (status_icon_list) {
+ current = status_icon_list;
+ status_icon_list = status_icon_list->next;
+ status_icon_list_size--;
+
+ mir_free(current->sid.szModule);
+ DestroyIcon(current->sid.hIcon);
+ if (current->sid.hIconDisabled) DestroyIcon(current->sid.hIconDisabled);
+ if (current->sid.szTooltip) mir_free(current->sid.szTooltip);
+ mir_free(current);
+ }
+ M->BroadcastMessage(DM_STATUSICONCHANGE, 0, 0);
+}
+
+static INT_PTR SI_ModifyStatusIcon(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+
+ StatusIconData *sid = (StatusIconData *)lParam;
+ struct TStatusBarIconNode *current = status_icon_list;
+
+ while (current) {
+ if (strcmp(current->sid.szModule, sid->szModule) == 0 && current->sid.dwId == sid->dwId) {
+ if (!hContact) {
+ current->sid.flags = sid->flags;
+ if (sid->hIcon) {
+ DestroyIcon(current->sid.hIcon);
+ current->sid.hIcon = sid->hIcon;
+ }
+ if (sid->hIconDisabled) {
+ DestroyIcon(current->sid.hIconDisabled);
+ current->sid.hIconDisabled = sid->hIconDisabled;
+ }
+ if (sid->szTooltip) {
+ if (current->sid.szTooltip) mir_free(current->sid.szTooltip);
+ current->sid.szTooltip = mir_strdup(sid->szTooltip);
+ }
+
+ M->BroadcastMessage(DM_STATUSICONCHANGE, 0, 0);
+ } else {
+ char buff[256];
+ HWND hwnd;
+ if (!(sid->flags&MBF_OWNERSTATE)) {
+ sprintf(buff, "SRMMStatusIconFlags%d", (int)sid->dwId);
+ M->WriteByte(hContact, sid->szModule, buff, (BYTE)sid->flags);
+ }
+ if ((hwnd = M->FindWindow(hContact))) {
+ if (sid->flags&MBF_OWNERSTATE) {
+
+ struct TStatusBarIconNode *siln = NULL;
+ struct TWindowData *dat = (struct TWindowData *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ struct TStatusBarIconNode *psi = dat->pSINod;
+ while (psi) {
+ if (strcmp(psi->sid.szModule, sid->szModule) == 0 && psi->sid.dwId == sid->dwId) {
+ siln = psi;
+ break;
+ }
+ psi = psi->next;
+ }
+ if (!siln) {
+ siln = (struct TStatusBarIconNode *)mir_alloc(sizeof(struct TStatusBarIconNode));
+ siln->sid.szModule = mir_strdup(sid->szModule);
+ siln->sid.dwId = sid->dwId;
+ siln->sid.hIcon = sid->hIcon;
+ siln->sid.hIconDisabled = sid->hIconDisabled;
+ siln->sid.flags = sid->flags;
+
+ if (sid->szTooltip) siln->sid.szTooltip = mir_strdup(sid->szTooltip);
+ else siln->sid.szTooltip = 0;
+
+ siln->next = dat->pSINod;
+ dat->pSINod = siln;
+ } else {
+ siln->sid.hIcon = sid->hIcon;
+ siln->sid.hIconDisabled = sid->hIconDisabled;
+ siln->sid.flags = sid->flags;
+ if (siln->sid.szTooltip) mir_free(siln->sid.szTooltip);
+
+ if (sid->szTooltip) siln->sid.szTooltip = mir_strdup(sid->szTooltip);
+ else siln->sid.szTooltip = 0;
+
+ }
+
+
+ PostMessage(hwnd, DM_STATUSICONCHANGE, 0, 0);
+ } else
+ PostMessage(hwnd, DM_STATUSICONCHANGE, 0, 0);
+ }
+ }
+ return 0;
+ }
+ current = current->next;
+ }
+ return 1;
+}
+
+void DrawStatusIcons(struct TWindowData *dat, HDC hDC, RECT r, int gap)
+{
+ TStatusBarIconNode* current = status_icon_list;
+ HICON hIcon = NULL;
+ char buff[256];
+ int flags;
+ int x = r.left;
+ LONG cx_icon = PluginConfig.m_smcxicon;
+ LONG cy_icon = PluginConfig.m_smcyicon;
+ LONG y = (r.top + r.bottom - cx_icon) >> 1;
+
+ SetBkMode(hDC, TRANSPARENT);
+ while (current) {
+ if (current->sid.flags&MBF_OWNERSTATE) {
+ struct TStatusBarIconNode *currentSIN = dat->pSINod;
+ flags = current->sid.flags;
+ hIcon = current->sid.hIcon;
+ while (currentSIN) {
+ if (strcmp(currentSIN->sid.szModule, current->sid.szModule) == 0 && currentSIN->sid.dwId == current->sid.dwId) {
+ flags = currentSIN->sid.flags;
+ hIcon = currentSIN->sid.hIcon;
+ break;
+ }
+ currentSIN = currentSIN->next;
+ }
+ } else {
+ sprintf(buff, "SRMMStatusIconFlags%d", (int)current->sid.dwId);
+ flags = M->GetByte(dat->hContact, current->sid.szModule, buff, current->sid.flags);
+ }
+
+ if (!(flags & MBF_HIDDEN)) {
+ if (!(flags&MBF_OWNERSTATE) && (flags & MBF_DISABLED) && current->sid.hIconDisabled)
+ hIcon = current->sid.hIconDisabled;
+ else if (!(flags&MBF_OWNERSTATE))
+ hIcon = current->sid.hIcon;
+
+ if (flags & MBF_DISABLED && current->sid.hIconDisabled == (HICON)0)
+ CSkin::DrawDimmedIcon(hDC, x, y, cx_icon, cy_icon, hIcon, 50);
+ else
+ DrawIconEx(hDC, x, y, hIcon, 16, 16, 0, NULL, DI_NORMAL);
+
+ x += 16 + gap;
+ }
+ current = current->next;
+ }
+ DrawIconEx(hDC, x, y, PluginConfig.g_buttonBarIcons[ICON_DEFAULT_SOUNDS],
+ cx_icon, cy_icon, 0, NULL, DI_NORMAL);
+
+ DrawIconEx(hDC, x, y, dat->pContainer->dwFlags & CNT_NOSOUND ?
+ PluginConfig.g_iconOverlayDisabled : PluginConfig.g_iconOverlayEnabled,
+ cx_icon, cy_icon, 0, NULL, DI_NORMAL);
+
+ x += (cx_icon + gap);
+
+ if (dat->bType == SESSIONTYPE_IM) {
+ DrawIconEx(hDC, x, y,
+ PluginConfig.g_buttonBarIcons[ICON_DEFAULT_TYPING], cx_icon, cy_icon, 0, NULL, DI_NORMAL);
+ DrawIconEx(hDC, x, y, M->GetByte(dat->hContact, SRMSGMOD, SRMSGSET_TYPING, M->GetByte(SRMSGMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW)) ?
+ PluginConfig.g_iconOverlayEnabled : PluginConfig.g_iconOverlayDisabled, cx_icon, cy_icon, 0, NULL, DI_NORMAL);
+ }
+ else
+ CSkin::DrawDimmedIcon(hDC, x, y, cx_icon, cy_icon,
+ PluginConfig.g_buttonBarIcons[ICON_DEFAULT_TYPING], 50);
+
+ x += (cx_icon + gap);
+ DrawIconEx(hDC, x, y, PluginConfig.g_sideBarIcons[0], cx_icon, cy_icon, 0, NULL, DI_NORMAL);
+}
+
+void SI_CheckStatusIconClick(struct TWindowData *dat, HWND hwndFrom, POINT pt, RECT r, int gap, int code)
+{
+ StatusIconClickData sicd;
+ struct TStatusBarIconNode *current = status_icon_list;
+ struct TStatusBarIconNode *clicked = NULL;
+
+ unsigned int iconNum = (pt.x - (r.left + 0)) / (PluginConfig.m_smcxicon + gap);
+ unsigned int list_icons = 0;
+ char buff[100];
+ DWORD flags;
+
+ if (dat && (code == NM_CLICK || code == NM_RCLICK)) {
+ POINT ptScreen;
+
+ GetCursorPos(&ptScreen);
+ if (!PtInRect(&rcLastStatusBarClick, ptScreen))
+ return;
+ }
+ while (current && dat) {
+ if (current->sid.flags&MBF_OWNERSTATE) {
+ struct TStatusBarIconNode *currentSIN = dat->pSINod;
+ flags = current->sid.flags;
+ while (currentSIN) {
+ if (strcmp(currentSIN->sid.szModule, current->sid.szModule) == 0 && currentSIN->sid.dwId == current->sid.dwId) {
+ flags = currentSIN->sid.flags;
+ break;
+ }
+ currentSIN = currentSIN->next;
+ }
+ } else {
+ sprintf(buff, "SRMMStatusIconFlags%d", (int)current->sid.dwId);
+ flags = M->GetByte(dat->hContact, current->sid.szModule, buff, current->sid.flags);
+ }
+ if (!(flags & MBF_HIDDEN)) {
+ if (list_icons++ == iconNum)
+ clicked = current;
+ }
+ current = current->next;
+ }
+
+ if ((int)iconNum == list_icons && code != NM_RCLICK) {
+ if (GetKeyState(VK_SHIFT) & 0x8000) {
+ struct TContainerData *piContainer = pFirstContainer;
+
+ while (piContainer) {
+ piContainer->dwFlags = ((dat->pContainer->dwFlags & CNT_NOSOUND) ? piContainer->dwFlags | CNT_NOSOUND : piContainer->dwFlags & ~CNT_NOSOUND);
+ InvalidateRect(dat->pContainer->hwndStatus, NULL, TRUE);
+ piContainer = piContainer->pNextContainer;
+ }
+ } else {
+ dat->pContainer->dwFlags ^= CNT_NOSOUND;
+ InvalidateRect(dat->pContainer->hwndStatus, NULL, TRUE);
+ }
+ } else if ((int)iconNum == list_icons + 1 && code != NM_RCLICK && dat->bType == SESSIONTYPE_IM) {
+ SendMessage(dat->pContainer->hwndActive, WM_COMMAND, IDC_SELFTYPING, 0);
+ InvalidateRect(dat->pContainer->hwndStatus, NULL, TRUE);
+ } else if ((int)iconNum == list_icons + 2) {
+ if(code == NM_CLICK)
+ PostMessage(PluginConfig.g_hwndHotkeyHandler, DM_TRAYICONNOTIFY, 101, WM_LBUTTONUP);
+ else if(code == NM_RCLICK)
+ PostMessage(PluginConfig.g_hwndHotkeyHandler, DM_TRAYICONNOTIFY, 101, WM_RBUTTONUP);
+ } else if (clicked) {
+ sicd.cbSize = sizeof(StatusIconClickData);
+ GetCursorPos(&sicd.clickLocation);
+ sicd.dwId = clicked->sid.dwId;
+ sicd.szModule = clicked->sid.szModule;
+ sicd.flags = (code == NM_RCLICK ? MBCF_RIGHTBUTTON : 0);
+ NotifyEventHooks(hHookIconPressedEvt, (WPARAM)dat->hContact, (LPARAM)&sicd);
+ InvalidateRect(dat->pContainer->hwndStatus, NULL, TRUE);
+ }
+}
+
+static HANDLE SI_hServiceIcon[3];
+
+int SI_InitStatusIcons()
+{
+ SI_hServiceIcon[0] = CreateServiceFunction(MS_MSG_ADDICON, SI_AddStatusIcon);
+ SI_hServiceIcon[1] = CreateServiceFunction(MS_MSG_REMOVEICON, SI_RemoveStatusIcon);
+ SI_hServiceIcon[2] = CreateServiceFunction(MS_MSG_MODIFYICON, SI_ModifyStatusIcon);
+ hHookIconPressedEvt = CreateHookableEvent(ME_MSG_ICONPRESSED);
+
+ return 0;
+}
+
+
+int SI_DeinitStatusIcons()
+{
+ int i;
+ DestroyHookableEvent(hHookIconPressedEvt);
+ for (i = 0; i < 3; i++)
+ DestroyServiceFunction(SI_hServiceIcon[i]);
+ SI_RemoveAllStatusIcons();
+ return 0;
+}
+
+int SI_GetStatusIconsCount()
+{
+ return status_icon_list_size;
+}