summaryrefslogtreecommitdiff
path: root/plugins/TabSRMM/chat/tools.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/chat/tools.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/chat/tools.cpp')
-rw-r--r--plugins/TabSRMM/chat/tools.cpp1351
1 files changed, 1351 insertions, 0 deletions
diff --git a/plugins/TabSRMM/chat/tools.cpp b/plugins/TabSRMM/chat/tools.cpp
new file mode 100644
index 0000000000..0726a01869
--- /dev/null
+++ b/plugins/TabSRMM/chat/tools.cpp
@@ -0,0 +1,1351 @@
+/*
+ * 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.
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda IM, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: tools.cpp 13650 2011-05-30 11:53:13Z silvercircle@gmail.com $
+ *
+ * Helper functions for the group chat module.
+ *
+ */
+
+#include "../src/commonheaders.h"
+
+// externs
+extern HICON hIcons[30];
+extern FONTINFO aFonts[OPTIONS_FONTCOUNT];
+extern HMENU g_hMenu;
+extern HANDLE hBuildMenuEvent ;
+extern HANDLE hSendEvent;
+
+int GetRichTextLength(HWND hwnd)
+{
+ GETTEXTLENGTHEX gtl;
+
+ gtl.flags = GTL_PRECISE;
+ gtl.codepage = CP_ACP ;
+ return (int) SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
+}
+
+/**
+ * @param pszWord string to strip of any IRC-style
+ * formatting
+ * @param fToLower convert to lowercase
+ * @param fStripCR strip cr/lf sequences (only for highlighter, defaults to false)
+ * @param buf caller-provided buffer, use a static one
+ * when the caller does not provide a
+ * buffer
+ * caller provided buffer is NEEDED to make
+ * this thread-safe.
+ *
+ * @return TCHAR* the stripped string
+ */
+TCHAR* RemoveFormatting(const TCHAR* pszWord, bool fToLower, bool fStripCR, TCHAR* buf, const size_t len)
+{
+ static TCHAR _szTemp[20000];
+ TCHAR* szTemp = 0;
+ size_t _buflen = 0;
+
+ if(0 == buf) {
+ szTemp = _szTemp;
+ _buflen = 20000;
+ } else {
+ szTemp = buf;
+ _buflen = len;
+ szTemp[len - 1] = 0;
+ }
+
+ size_t i = 0;
+ size_t j = 0;
+
+ if (pszWord == 0)
+ return NULL;
+
+ size_t wordlen = lstrlen(pszWord);
+
+ while (j < _buflen && i <= wordlen) {
+ if (pszWord[i] == '%') {
+ switch (pszWord[i+1]) {
+ case '%':
+ szTemp[j] = '%';
+ j++;
+ i++;
+ i++;
+ break;
+ case 'b':
+ case 'u':
+ case 'i':
+ case 'B':
+ case 'U':
+ case 'I':
+ case 'r':
+ case 'C':
+ case 'F':
+ i++;
+ i++;
+ break;
+
+ case 'c':
+ case 'f':
+ i += 4;
+ break;
+
+ default:
+ szTemp[j] = pszWord[i];
+ j++;
+ i++;
+ break;
+ }
+ } else {
+ if(fStripCR) {
+ if(0x0a == pszWord[i] || 0x0c == pszWord[i]) {
+ szTemp[j++] = ' ';
+ i++;
+ continue;
+ }
+ }
+ szTemp[j] = pszWord[i];
+ j++;
+ i++;
+ }
+ }
+ if(fToLower) {
+ _wsetlocale(LC_ALL, L"");
+ wcslwr(szTemp);
+ }
+ return(szTemp);
+}
+
+static void __stdcall ShowRoomFromPopup(void * pi)
+{
+ SESSION_INFO* si = (SESSION_INFO*) pi;
+ ShowRoom(si, WINDOW_VISIBLE, TRUE);
+}
+
+static void TSAPI Chat_OpenPopup(SESSION_INFO* si, HWND hwndPopup)
+{
+ CallFunctionAsync(ShowRoomFromPopup, si);
+ PUDeletePopUp(hwndPopup);
+}
+
+static void TSAPI Chat_DismissPopup(const SESSION_INFO* si, HWND hwndPopup)
+{
+ if (si->hContact)
+ if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->hContact, (LPARAM)szChatIconString);
+
+ if (si->hWnd && KillTimer(si->hWnd, TIMERID_FLASHWND))
+ FlashWindow(si->hWnd, FALSE);
+
+ PUDeletePopUp(hwndPopup);
+}
+
+static INT_PTR CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message) {
+ case WM_COMMAND:
+ if (HIWORD(wParam) == STN_CLICKED) {
+ SESSION_INFO* si = (SESSION_INFO*)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd, (LPARAM)0);;
+
+ if(si) {
+ if(nen_options.maskActL & MASK_OPEN)
+ Chat_OpenPopup(si, hWnd);
+ else
+ Chat_DismissPopup(si, hWnd);
+ }
+ return TRUE;
+ }
+ break;
+ case WM_CONTEXTMENU: {
+ SESSION_INFO* si = (SESSION_INFO*)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd, (LPARAM)0);
+
+ if(si && si->hContact) {
+ if(nen_options.maskActR & MASK_OPEN)
+ Chat_OpenPopup(si, hWnd);
+ else
+ Chat_DismissPopup(si, hWnd);
+ }
+ }
+ break;
+ }
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+static int ShowPopup(HANDLE hContact, SESSION_INFO* si, HICON hIcon, char* pszProtoName, TCHAR* pszRoomName, COLORREF crBkg, const TCHAR* fmt, ...)
+{
+ POPUPDATAT_V2 pd = {0};
+ va_list marker;
+ static TCHAR szBuf[4*1024];
+
+ if (!fmt || lstrlen(fmt) == 0 || lstrlen(fmt) > 2000)
+ return 0;
+
+ va_start(marker, fmt);
+ _vstprintf(szBuf, fmt, marker);
+ va_end(marker);
+
+ pd.lchContact = hContact;
+
+ if (hIcon)
+ pd.lchIcon = hIcon ;
+ else
+ pd.lchIcon = LoadIconEx(IDI_CHANMGR, "window", 0, 0);
+
+ mir_sntprintf(pd.lptzContactName, MAX_CONTACTNAME - 1, _T(TCHAR_STR_PARAM) _T(" - %s"),
+ pszProtoName, CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR));
+ lstrcpyn(pd.lptzText, TranslateTS(szBuf), MAX_SECONDLINE - 1);
+ pd.iSeconds = g_Settings.iPopupTimeout;
+
+ if (g_Settings.iPopupStyle == 2) {
+ pd.colorBack = 0;
+ pd.colorText = 0;
+ } else if (g_Settings.iPopupStyle == 3) {
+ pd.colorBack = g_Settings.crPUBkgColour;
+ pd.colorText = g_Settings.crPUTextColour;
+ } else {
+ pd.colorBack = M->GetDword(FONTMODULE, SRMSGSET_BKGCOLOUR_MUC, SRMSGDEFSET_BKGCOLOUR);
+ pd.colorText = crBkg;
+ }
+
+ pd.PluginWindowProc = (WNDPROC)PopupDlgProc;
+ pd.PluginData = si;
+ return PUAddPopUpT(&pd);
+}
+
+static BOOL DoTrayIcon(SESSION_INFO* si, GCEVENT * gce)
+{
+ int iEvent = gce->pDest->iType;
+
+ if (si && (iEvent & si->iLogTrayFlags)) {
+ switch (iEvent) {
+ case GC_EVENT_MESSAGE | GC_EVENT_HIGHLIGHT :
+ case GC_EVENT_ACTION | GC_EVENT_HIGHLIGHT :
+ CList_AddEvent(si->hContact, PluginConfig.g_IconMsgEvent, szChatIconString, 0,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_HILIGHT), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_MESSAGE :
+ CList_AddEvent(si->hContact, hIcons[ICON_MESSAGE], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_MSG), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_ACTION:
+ CList_AddEvent(si->hContact, hIcons[ICON_ACTION], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_MSG), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_JOIN:
+ CList_AddEvent(si->hContact, hIcons[ICON_JOIN], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_JOINED), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_PART:
+ CList_AddEvent(si->hContact, hIcons[ICON_PART], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_LEFT), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_QUIT:
+ CList_AddEvent(si->hContact, hIcons[ICON_QUIT], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_QUIT), gce->ptszNick);
+ break;
+ case GC_EVENT_NICK:
+ CList_AddEvent(si->hContact, hIcons[ICON_NICK], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_NICK), gce->ptszNick, gce->pszText);
+ break;
+ case GC_EVENT_KICK:
+ CList_AddEvent(si->hContact, hIcons[ICON_KICK], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_KICK), gce->pszStatus, gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_NOTICE:
+ CList_AddEvent(si->hContact, hIcons[ICON_NOTICE], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_NOTICE), gce->ptszNick);
+ break;
+ case GC_EVENT_TOPIC:
+ CList_AddEvent(si->hContact, hIcons[ICON_TOPIC], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_TOPIC), si->ptszName);
+ break;
+ case GC_EVENT_INFORMATION:
+ CList_AddEvent(si->hContact, hIcons[ICON_INFO], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_INFO), si->ptszName);
+ break;
+ case GC_EVENT_ADDSTATUS:
+ CList_AddEvent(si->hContact, hIcons[ICON_ADDSTATUS], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_STATUS_ON), gce->pszText, gce->pszStatus, gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ CList_AddEvent(si->hContact, hIcons[ICON_REMSTATUS], szChatIconString, CLEF_ONLYAFEW,
+ CTranslator::get(CTranslator::GEN_MUC_TRAY_STATUS_OFF), gce->pszText, gce->pszStatus, gce->ptszNick, si->ptszName);
+ break;
+ }
+ }
+ return TRUE;
+}
+
+static BOOL DoPopup(SESSION_INFO* si, GCEVENT* gce, struct TWindowData* dat)
+{
+ int iEvent = gce->pDest->iType;
+ struct TContainerData *pContainer = dat ? dat->pContainer : NULL;
+ char *szProto = dat ? dat->szProto : si->pszModule;
+
+ TCHAR *bbStart, *bbEnd;
+ if (g_Settings.BBCodeInPopups)
+ {
+ bbStart = _T("[b]");
+ bbEnd = _T("[/b]");
+ } else
+ {
+ bbStart = bbEnd = _T("");
+ }
+
+ if (si && (iEvent & si->iLogPopupFlags)) {
+
+ if (nen_options.iMUCDisable) // no popups at all. Period
+ return 0;
+ /*
+ * check the status mode against the status mask
+ */
+
+ if (nen_options.dwStatusMask != -1) {
+ DWORD dwStatus = 0;
+ if (szProto != NULL) {
+ dwStatus = (DWORD)CallProtoService(szProto, PS_GETSTATUS, 0, 0);
+ if (!(dwStatus == 0 || dwStatus <= ID_STATUS_OFFLINE || ((1 << (dwStatus - ID_STATUS_ONLINE)) & nen_options.dwStatusMask))) // should never happen, but...
+ return 0;
+ }
+ }
+ if (dat && pContainer != 0) { // message window is open, need to check the container config if we want to see a popup nonetheless
+ if (nen_options.bWindowCheck) { // no popups at all for open windows... no exceptions
+ if(!PluginConfig.m_HideOnClose)
+ return(0);
+ if(pContainer->fHidden)
+ goto passed;
+ return(0);
+ }
+ if (pContainer->dwFlags & CNT_DONTREPORT && IsIconic(pContainer->hwnd)) // in tray counts as "minimised"
+ goto passed;
+ if (pContainer->dwFlags & CNT_DONTREPORTUNFOCUSED) {
+ if (!IsIconic(pContainer->hwnd) && GetForegroundWindow() != pContainer->hwnd && GetActiveWindow() != pContainer->hwnd)
+ goto passed;
+ }
+ if (pContainer->dwFlags & CNT_ALWAYSREPORTINACTIVE) {
+ if (pContainer->dwFlags & CNT_DONTREPORTFOCUSED)
+ goto passed;
+
+ if (pContainer->hwndActive == si->hWnd)
+ return 0;
+
+ goto passed;
+ }
+ return 0;
+ }
+passed:
+ int iNewEvent = iEvent;
+ COLORREF clr = 0;
+
+ if((iNewEvent & GC_EVENT_HIGHLIGHT)) {
+ clr = aFonts[16].color;
+ iNewEvent &= ~GC_EVENT_HIGHLIGHT;
+ }
+ switch (iNewEvent) {
+ case GC_EVENT_MESSAGE :
+ ShowPopup(si->hContact, si, hIcons[ICON_MESSAGE], si->pszModule, si->ptszName, clr ? clr : aFonts[9].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_MSG), bbStart, gce->ptszNick, bbEnd, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_ACTION:
+ ShowPopup(si->hContact, si, hIcons[ICON_ACTION], si->pszModule, si->ptszName, clr ? clr : aFonts[15].color, _T("%s %s"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_JOIN:
+ ShowPopup(si->hContact, si, hIcons[ICON_JOIN], si->pszModule, si->ptszName, clr ? clr : aFonts[3].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_JOINED), gce->ptszNick);
+ break;
+ case GC_EVENT_PART:
+ if (!gce->pszText)
+ ShowPopup(si->hContact, si, hIcons[ICON_PART], si->pszModule, si->ptszName, clr ? clr : aFonts[4].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_LEFT), gce->ptszNick);
+ else
+ ShowPopup(si->hContact, si, hIcons[ICON_PART], si->pszModule, si->ptszName, clr ? clr : aFonts[4].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_LEFT1), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_QUIT:
+ if (!gce->pszText)
+ ShowPopup(si->hContact, si, hIcons[ICON_QUIT], si->pszModule, si->ptszName, clr ? clr : aFonts[5].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_QUIT), gce->ptszNick);
+ else
+ ShowPopup(si->hContact, si, hIcons[ICON_QUIT], si->pszModule, si->ptszName, clr ? clr : aFonts[5].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_QUIT1), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_NICK:
+ ShowPopup(si->hContact, si, hIcons[ICON_NICK], si->pszModule, si->ptszName, clr ? clr : aFonts[7].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_NICK), gce->ptszNick, gce->ptszText);
+ break;
+ case GC_EVENT_KICK:
+ if (!gce->pszText)
+ ShowPopup(si->hContact, si, hIcons[ICON_KICK], si->pszModule, si->ptszName, clr ? clr : aFonts[6].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_KICK), (char *)gce->pszStatus, gce->ptszNick);
+ else
+ ShowPopup(si->hContact, si, hIcons[ICON_KICK], si->pszModule, si->ptszName, clr ? clr : aFonts[6].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_KICK1), (char *)gce->pszStatus, gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_NOTICE:
+ ShowPopup(si->hContact, si, hIcons[ICON_NOTICE], si->pszModule, si->ptszName, clr ? clr : aFonts[8].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_NOTICE), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_TOPIC:
+ if (!gce->ptszNick)
+ ShowPopup(si->hContact, si, hIcons[ICON_TOPIC], si->pszModule, si->ptszName, clr ? clr : aFonts[11].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_TOPIC), RemoveFormatting(gce->ptszText));
+ else
+ ShowPopup(si->hContact, si, hIcons[ICON_TOPIC], si->pszModule, si->ptszName, clr ? clr : aFonts[11].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_TOPIC1), RemoveFormatting(gce->ptszText), gce->ptszNick);
+ break;
+ case GC_EVENT_INFORMATION:
+ ShowPopup(si->hContact, si, hIcons[ICON_INFO], si->pszModule, si->ptszName, clr ? clr : aFonts[12].color, _T("%s"), RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_ADDSTATUS:
+ ShowPopup(si->hContact, si, hIcons[ICON_ADDSTATUS], si->pszModule, si->ptszName, clr ? clr : aFonts[13].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_STATUS_ON), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick);
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ ShowPopup(si->hContact, si, hIcons[ICON_REMSTATUS], si->pszModule, si->ptszName, clr ? clr : aFonts[14].color,
+ CTranslator::get(CTranslator::GEN_MUC_POPUP_STATUS_OFF), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick);
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+void TSAPI DoFlashAndSoundWorker(FLASH_PARAMS* p)
+{
+ SESSION_INFO* si = SM_FindSessionByHCONTACT(p->hContact);
+ TWindowData* dat = 0;
+
+ if(si == 0)
+ return;
+
+ if (si->hWnd) {
+ dat = si->dat;
+ if (dat) {
+ p->bInactive = dat->pContainer->hwnd != GetForegroundWindow();
+ p->bActiveTab = (dat->pContainer->hwndActive == si->hWnd);
+ }
+ if (p->sound && Utils::mustPlaySound(si->dat))
+ SkinPlaySound(p->sound);
+ }
+ else if(p->sound)
+ SkinPlaySound(p->sound);
+
+ if (dat) {
+ HWND hwndTab = GetParent(si->hWnd);
+ BOOL bForcedIcon = (p->hNotifyIcon == hIcons[ICON_HIGHLIGHT] || p->hNotifyIcon == hIcons[ICON_MESSAGE]);
+
+ if ((p->iEvent & si->iLogTrayFlags) || bForcedIcon) {
+ if (!p->bActiveTab) {
+ if (p->hNotifyIcon == hIcons[ICON_HIGHLIGHT])
+ dat->iFlashIcon = p->hNotifyIcon;
+ else {
+ if (dat->iFlashIcon != hIcons[ICON_HIGHLIGHT] && dat->iFlashIcon != hIcons[ICON_MESSAGE])
+ dat->iFlashIcon = p->hNotifyIcon;
+ }
+ dat->mayFlashTab = TRUE;
+ SetTimer(si->hWnd, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL);
+ }
+ }
+ if(dat->pWnd) {
+ dat->pWnd->updateIcon(p->hNotifyIcon);
+ dat->pWnd->setOverlayIcon(p->hNotifyIcon, true);
+ }
+
+ // autoswitch tab..
+ if (p->bMustAutoswitch) {
+ if ((IsIconic(dat->pContainer->hwnd)) && !IsZoomed(dat->pContainer->hwnd) && PluginConfig.haveAutoSwitch() && dat->pContainer->hwndActive != si->hWnd) {
+ int iItem = GetTabIndexFromHWND(hwndTab, si->hWnd);
+ if (iItem >= 0) {
+ TabCtrl_SetCurSel(hwndTab, iItem);
+ ShowWindow(dat->pContainer->hwndActive, SW_HIDE);
+ dat->pContainer->hwndActive = si->hWnd;
+ SendMessage(dat->pContainer->hwnd, DM_UPDATETITLE, (WPARAM)dat->hContact, 0);
+ dat->pContainer->dwFlags |= CNT_DEFERREDTABSELECT;
+ }
+ }
+ }
+
+ /*
+ * flash window if it is not focused
+ */
+ if (p->bMustFlash && p->bInactive)
+ if (!(dat->pContainer->dwFlags & CNT_NOFLASH))
+ FlashContainer(dat->pContainer, 1, 0);
+
+ if (p->hNotifyIcon && p->bInactive && ((p->iEvent & si->iLogTrayFlags) || bForcedIcon)) {
+ HICON hIcon;
+
+ if (p->bMustFlash)
+ dat->hTabIcon = p->hNotifyIcon;
+ else if (dat->iFlashIcon) {
+ TCITEM item = {0};
+
+ dat->hTabIcon = dat->iFlashIcon;
+ item.mask = TCIF_IMAGE;
+ item.iImage = 0;
+ TabCtrl_SetItem(GetParent(si->hWnd), dat->iTabID, &item);
+ }
+ hIcon = (HICON)SendMessage(dat->pContainer->hwnd, WM_GETICON, ICON_BIG, 0);
+ if (p->hNotifyIcon == hIcons[ICON_HIGHLIGHT] || (hIcon != hIcons[ICON_MESSAGE] && hIcon != hIcons[ICON_HIGHLIGHT])) {
+ SendMessage(dat->pContainer->hwnd, DM_SETICON, (WPARAM)dat, (LPARAM)p->hNotifyIcon);
+ dat->pContainer->dwFlags |= CNT_NEED_UPDATETITLE;
+ }
+ }
+
+ if (p->bMustFlash && p->bInactive)
+ UpdateTrayMenu(dat, si->wStatus, si->pszModule, dat ? dat->szStatus : NULL, si->hContact, p->bHighlight ? 1 : 1);
+ }
+
+ free(p);
+}
+
+BOOL DoSoundsFlashPopupTrayStuff(SESSION_INFO* si, GCEVENT * gce, BOOL bHighlight, int bManyFix)
+{
+ FLASH_PARAMS* params;
+ struct TWindowData *dat = 0;
+ bool fFlagUnread = false;
+ WPARAM wParamForHighLight = 0;
+
+ if (gce == 0 || si == 0 || gce->bIsMe || si->iType == GCW_SERVER)
+ return FALSE;
+
+ params = (FLASH_PARAMS*)calloc(1, sizeof(FLASH_PARAMS));
+ params->hContact = si->hContact;
+ params->bInactive = TRUE;
+ if(si->hWnd && si->dat) {
+ dat = si->dat;
+ if((si->hWnd == si->dat->pContainer->hwndActive) && GetForegroundWindow() == si->dat->pContainer->hwnd)
+ params->bInactive = FALSE;
+ }
+ params->bActiveTab = params->bMustFlash = params->bMustAutoswitch = FALSE;
+
+ params->iEvent = gce->pDest->iType;
+
+ if (bHighlight) {
+ gce->pDest->iType |= GC_EVENT_HIGHLIGHT;
+ params->sound = "ChatHighlight";
+ if (M->GetByte(si->hContact, "CList", "Hidden", 0) != 0)
+ DBDeleteContactSetting(si->hContact, "CList", "Hidden");
+ if (params->bInactive) {
+ fFlagUnread = true;
+ DoTrayIcon(si, gce);
+ }
+
+ /* TODO fix for 3.0 final !!! */
+#if !defined(__DELAYED_FOR_3_1)
+ if(g_Settings.CreateWindowOnHighlight && 0 == dat)
+ wParamForHighLight = 1;
+
+ if(dat && g_Settings.AnnoyingHighlight && params->bInactive && dat->pContainer->hwnd != GetForegroundWindow()) {
+ wParamForHighLight = 2;
+ params->hWnd = dat->hwnd;
+ }
+#endif
+ if (dat || !nen_options.iMUCDisable)
+ DoPopup(si, gce, dat);
+ if (params->bInactive && si && si->hWnd)
+ SendMessage(si->hWnd, GC_SETMESSAGEHIGHLIGHT, 0, (LPARAM) si);
+ if (g_Settings.FlashWindowHightlight && params->bInactive)
+ params->bMustFlash = TRUE;
+ params->bMustAutoswitch = TRUE;
+ params->hNotifyIcon = hIcons[ICON_HIGHLIGHT];
+ } else {
+ // do blinking icons in tray
+ if (params->bInactive || !g_Settings.TrayIconInactiveOnly) {
+ DoTrayIcon(si, gce);
+ if(params->iEvent == GC_EVENT_MESSAGE)
+ fFlagUnread = true;
+ }
+ // stupid thing to not create multiple popups for a QUIT event for instance
+ if (bManyFix == 0) {
+ // do popups
+ if (dat || !nen_options.iMUCDisable)
+ DoPopup(si, gce, dat);
+
+ // do sounds and flashing
+ switch (params->iEvent) {
+ case GC_EVENT_JOIN:
+ params->sound = "ChatJoin";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_JOIN];
+ break;
+ case GC_EVENT_PART:
+ params->sound = "ChatPart";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_PART];
+ break;
+ case GC_EVENT_QUIT:
+ params->sound = "ChatQuit";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_QUIT];
+ break;
+ case GC_EVENT_ADDSTATUS:
+ case GC_EVENT_REMOVESTATUS:
+ params->sound = "ChatMode";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[params->iEvent == GC_EVENT_ADDSTATUS ? ICON_ADDSTATUS : ICON_REMSTATUS];
+ break;
+ case GC_EVENT_KICK:
+ params->sound = "ChatKick";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_KICK];
+ break;
+ case GC_EVENT_MESSAGE:
+ params->sound = "ChatMessage";
+ if (params->bInactive && !(si->wState&STATE_TALK)) {
+ si->wState |= STATE_TALK;
+ DBWriteContactSettingWord(si->hContact, si->pszModule, "ApparentMode", (LPARAM)(WORD) 40071);
+ }
+ break;
+ case GC_EVENT_ACTION:
+ params->sound = "ChatAction";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_ACTION];
+ break;
+ case GC_EVENT_NICK:
+ params->sound = "ChatNick";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_NICK];
+ break;
+ case GC_EVENT_NOTICE:
+ params->sound = "ChatNotice";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_NOTICE];
+ break;
+ case GC_EVENT_TOPIC:
+ params->sound = "ChatTopic";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_TOPIC];
+ break;
+ }
+ } else {
+ switch (params->iEvent) {
+ case GC_EVENT_JOIN:
+ params->hNotifyIcon = hIcons[ICON_JOIN];
+ break;
+ case GC_EVENT_PART:
+ params->hNotifyIcon = hIcons[ICON_PART];
+ break;
+ case GC_EVENT_QUIT:
+ params->hNotifyIcon = hIcons[ICON_QUIT];
+ break;
+ case GC_EVENT_KICK:
+ params->hNotifyIcon = hIcons[ICON_KICK];
+ break;
+ case GC_EVENT_ACTION:
+ params->hNotifyIcon = hIcons[ICON_ACTION];
+ break;
+ case GC_EVENT_NICK:
+ params->hNotifyIcon = hIcons[ICON_NICK];
+ break;
+ case GC_EVENT_NOTICE:
+ params->hNotifyIcon = hIcons[ICON_NOTICE];
+ break;
+ case GC_EVENT_TOPIC:
+ params->hNotifyIcon = hIcons[ICON_TOPIC];
+ break;
+ case GC_EVENT_ADDSTATUS:
+ params->hNotifyIcon = hIcons[ICON_ADDSTATUS];
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ params->hNotifyIcon = hIcons[ICON_REMSTATUS];
+ break;
+ }
+ }
+
+ if (params->iEvent == GC_EVENT_MESSAGE) {
+ params->bMustAutoswitch = TRUE;
+ if (g_Settings.FlashWindow)
+ params->bMustFlash = TRUE;
+ params->hNotifyIcon = hIcons[ICON_MESSAGE];
+ }
+ }
+ if(dat && fFlagUnread) {
+ dat->dwUnread++;
+ if(dat->pWnd)
+ dat->pWnd->Invalidate();
+ }
+ PostMessage(PluginConfig.g_hwndHotkeyHandler, DM_MUCFLASHWORKER, wParamForHighLight, (LPARAM)params);
+ return TRUE;
+}
+
+int Chat_GetColorIndex(const char* pszModule, COLORREF cr)
+{
+ MODULEINFO * pMod = MM_FindModule(pszModule);
+ int i = 0;
+
+ if (!pMod || pMod->nColorCount == 0)
+ return -1;
+
+ for (i = 0; i < pMod->nColorCount; i++)
+ if (pMod->crColors[i] == cr)
+ return i;
+
+ return -1;
+}
+
+// obscure function that is used to make sure that any of the colors
+// passed by the protocol is used as fore- or background color
+// in the messagebox. THis is to vvercome limitations in the richedit
+// that I do not know currently how to fix
+
+void CheckColorsInModule(const char* pszModule)
+{
+ MODULEINFO * pMod = MM_FindModule(pszModule);
+ int i = 0;
+ COLORREF crFG;
+ COLORREF crBG = (COLORREF)M->GetDword(FONTMODULE, "inputbg", SRMSGDEFSET_BKGCOLOUR);
+
+ LoadLogfont(MSGFONTID_MESSAGEAREA, NULL, &crFG, FONTMODULE);
+
+ if (!pMod)
+ return;
+
+ for (i = 0; i < pMod->nColorCount; i++) {
+ if (pMod->crColors[i] == crFG || pMod->crColors[i] == crBG) {
+ if (pMod->crColors[i] == RGB(255, 255, 255))
+ pMod->crColors[i]--;
+ else
+ pMod->crColors[i]++;
+ }
+ }
+}
+
+TCHAR* my_strstri(const TCHAR* s1, const TCHAR* s2)
+{
+ int i, j, k;
+
+ _tsetlocale(LC_ALL, _T(""));
+ for (i = 0;s1[i];i++)
+ for (j = i, k = 0; _totlower(s1[j]) == _totlower(s2[k]);j++, k++)
+ if (!s2[k+1])
+ return (TCHAR*)(s1 + i);
+
+ return NULL;
+}
+
+/*
+ * log the event to the log file
+ * allows selective logging of wanted events
+ */
+BOOL LogToFile(SESSION_INFO* si, GCEVENT * gce)
+{
+ MODULEINFO * mi = NULL;
+ TCHAR szBuffer[4096];
+ TCHAR szLine[4096];
+ TCHAR szTime[100];
+ FILE *hFile = NULL;
+ TCHAR tszFolder[MAX_PATH];
+ TCHAR p = '\0';
+ BOOL bFileJustCreated = TRUE;
+
+ if (!si || !gce)
+ return FALSE;
+
+ mi = MM_FindModule(si->pszModule);
+ if (!mi)
+ return FALSE;
+
+ /*
+ * check whether we have to log this event
+ */
+ if(!(gce->pDest->iType & si->iDiskLogFlags))
+ return FALSE;
+
+ szBuffer[0] = '\0';
+
+ GetChatLogsFilename(si, gce->time);
+ bFileJustCreated = !PathFileExists(si->pszLogFileName);
+ _tcscpy(tszFolder, si->pszLogFileName);
+ PathRemoveFileSpec(tszFolder);
+ if (!PathIsDirectory(tszFolder))
+ CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)tszFolder);
+
+ lstrcpyn(szTime, MakeTimeStamp(g_Settings.pszTimeStampLog, gce->time), 99);
+
+ hFile = _tfopen(si->pszLogFileName, _T("ab+"));
+ if (hFile) {
+ TCHAR szTemp[512], szTemp2[512];
+ TCHAR* pszNick = NULL;
+ if (bFileJustCreated)
+ fputws((const wchar_t*)"\377\376", hFile); //UTF-16 LE BOM == FF FE
+ if (gce->ptszNick) {
+ if (g_Settings.LogLimitNames && lstrlen(gce->ptszNick) > 20) {
+ lstrcpyn(szTemp2, gce->ptszNick, 20);
+ lstrcpyn(szTemp2 + 20, _T("..."), 4);
+ } else lstrcpyn(szTemp2, gce->ptszNick, 511);
+
+ if (gce->pszUserInfo)
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s (%s)"), szTemp2, gce->pszUserInfo);
+ else
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s"), szTemp2);
+ pszNick = szTemp;
+ }
+ switch (gce->pDest->iType) {
+ case GC_EVENT_MESSAGE:
+ case GC_EVENT_MESSAGE | GC_EVENT_HIGHLIGHT:
+ p = '*';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s: %s"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_ACTION:
+ case GC_EVENT_ACTION | GC_EVENT_HIGHLIGHT:
+ p = '*';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s %s"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_JOIN:
+ p = '>';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_JOINED), (char *)pszNick);
+ break;
+ case GC_EVENT_PART:
+ p = '<';
+ if (!gce->pszText)
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_LEFT), (char *)pszNick);
+ else
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_LEFT1), (char *)pszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_QUIT:
+ p = '<';
+ if (!gce->pszText)
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_QUIT), (char *)pszNick);
+ else
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_QUIT1), (char *)pszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_NICK:
+ p = '^';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_NICK), gce->ptszNick, gce->ptszText);
+ break;
+ case GC_EVENT_KICK:
+ p = '~';
+ if (!gce->pszText)
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_KICK), (char *)gce->pszStatus, gce->ptszNick);
+ else
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_KICK1), (char *)gce->pszStatus, gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_NOTICE:
+ p = 'o';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_NOTICE), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_TOPIC:
+ p = '#';
+ if (!gce->pszNick)
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_TOPIC), RemoveFormatting(gce->ptszText));
+ else
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_TOPIC1), RemoveFormatting(gce->ptszText), gce->ptszNick);
+ break;
+ case GC_EVENT_INFORMATION:
+ p = '!';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s"), RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_ADDSTATUS:
+ p = '+';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_STATUS_ON), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick);
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ p = '-';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), CTranslator::get(CTranslator::GEN_MUC_POPUP_STATUS_OFF), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick);
+ break;
+ }
+ /*
+ * formatting strings don't need to be translatable - changing them via language pack would
+ * only screw up the log format.
+ */
+ if (p)
+ mir_sntprintf(szLine, SIZEOF(szLine), _T("%s %c %s\r\n"), szTime, p, szBuffer);
+ else
+ mir_sntprintf(szLine, SIZEOF(szLine), _T("%s %s\r\n"), szTime, szBuffer);
+
+ if (szLine[0]) {
+ _fputts(szLine, hFile);
+
+ if (g_Settings.LoggingLimit > 0) {
+ long dwSize;
+ long trimlimit;
+
+ fseek(hFile, 0, SEEK_END);
+ dwSize = ftell(hFile);
+ rewind(hFile);
+
+ trimlimit = g_Settings.LoggingLimit * 1024;
+ if (dwSize > trimlimit) {
+ TCHAR tszDrive[_MAX_DRIVE];
+ TCHAR tszDir[_MAX_DIR];
+ TCHAR tszName[_MAX_FNAME];
+ TCHAR tszExt[_MAX_EXT];
+ TCHAR tszNewName[_MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 20];
+ TCHAR tszNewPath[_MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 20];
+ TCHAR tszTimestamp[20];
+ time_t now = time(0);
+
+ _tcsftime(tszTimestamp, 20, _T("%Y%m%d-%H%M%S"), _localtime32((__time32_t *)&now));
+ tszTimestamp[19] = 0;
+ /*
+ * max size reached, rotate the log
+ * move old logs to /archived sub folder just inside the log root folder.
+ * add a time stamp to the file name.
+ */
+ _tsplitpath(si->pszLogFileName, tszDrive, tszDir, tszName, tszExt);
+
+ mir_sntprintf(tszNewPath, _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 20, _T("%s%sarchived\\"),
+ tszDrive, tszDir);
+
+ CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)tszNewPath);
+ mir_sntprintf(tszNewName, _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 20, _T("%s%s-%s%s"), tszNewPath, tszName, tszTimestamp, tszExt);
+ fclose(hFile);
+ hFile = 0;
+ if(!PathFileExists(tszNewName))
+ CopyFile(si->pszLogFileName, tszNewName, TRUE);
+ DeleteFile(si->pszLogFileName);
+ }
+ }
+ }
+
+ if (hFile)
+ fclose(hFile);
+ hFile = NULL;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+UINT CreateGCMenu(HWND hwndDlg, HMENU *hMenu, int iIndex, POINT pt, SESSION_INFO* si, TCHAR* pszUID, TCHAR* pszWordText)
+{
+ GCMENUITEMS gcmi = {0};
+ int i;
+ HMENU hSubMenu = 0;
+ DWORD codepage = M->GetDword(si->hContact, "ANSIcodepage", 0);
+ int pos;
+
+ *hMenu = GetSubMenu(g_hMenu, iIndex);
+ CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM) *hMenu, 0);
+ gcmi.pszID = si->ptszID;
+ gcmi.pszModule = si->pszModule;
+ gcmi.pszUID = pszUID;
+
+ if (iIndex == 1) {
+ int i = GetRichTextLength(GetDlgItem(hwndDlg, IDC_CHAT_LOG));
+
+ EnableMenuItem(*hMenu, ID_CLEARLOG, MF_ENABLED);
+ EnableMenuItem(*hMenu, ID_COPYALL, MF_ENABLED);
+ ModifyMenu(*hMenu, 4, MF_GRAYED | MF_BYPOSITION, 4, NULL);
+ if (!i) {
+ EnableMenuItem(*hMenu, ID_COPYALL, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem(*hMenu, ID_CLEARLOG, MF_BYCOMMAND | MF_GRAYED);
+ if (pszWordText && pszWordText[0])
+ ModifyMenu(*hMenu, 4, MF_ENABLED | MF_BYPOSITION, 4, NULL);
+ }
+
+ if (pszWordText && pszWordText[0]) {
+ TCHAR szMenuText[4096];
+ mir_sntprintf(szMenuText, 4096, CTranslator::get(CTranslator::GEN_MUC_LOOKUP), pszWordText);
+ ModifyMenu(*hMenu, 4, MF_STRING | MF_BYPOSITION, 4, szMenuText);
+ } else ModifyMenu(*hMenu, 4, MF_STRING | MF_GRAYED | MF_BYPOSITION, 4, CTranslator::get(CTranslator::GEN_MUC_LOOKUP_NOWORD));
+ gcmi.Type = MENU_ON_LOG;
+ } else if (iIndex == 0) {
+ TCHAR szTemp[30], szTemp2[30];
+ lstrcpyn(szTemp, CTranslator::get(CTranslator::GEN_MUC_MESSAGEAMP), 24);
+ if (pszUID)
+ mir_sntprintf(szTemp2, SIZEOF(szTemp2), _T("%s %s"), szTemp, pszUID);
+ else
+ lstrcpyn(szTemp2, szTemp, 24);
+
+ if (lstrlen(szTemp2) > 22)
+ lstrcpyn(szTemp2 + 22, _T("..."), 4);
+ ModifyMenu(*hMenu, ID_MESS, MF_STRING | MF_BYCOMMAND, ID_MESS, szTemp2);
+ gcmi.Type = MENU_ON_NICKLIST;
+ }
+
+ NotifyEventHooks(hBuildMenuEvent, 0, (WPARAM)&gcmi);
+
+ if (gcmi.nItems > 0)
+ AppendMenu(*hMenu, MF_SEPARATOR, 0, 0);
+
+ for (i = 0; i < gcmi.nItems; i++) {
+ TCHAR* ptszDescr = a2tf(gcmi.Item[i].pszDesc, si->dwFlags, 0);
+ DWORD dwState = gcmi.Item[i].bDisabled ? MF_GRAYED : 0;
+
+ if (gcmi.Item[i].uType == MENU_NEWPOPUP) {
+ hSubMenu = CreateMenu();
+ AppendMenu(*hMenu, dwState | MF_POPUP, (UINT_PTR)hSubMenu, ptszDescr);
+ } else if (gcmi.Item[i].uType == MENU_POPUPHMENU)
+ AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_POPUP, gcmi.Item[i].dwID, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_POPUPITEM)
+ AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_STRING, gcmi.Item[i].dwID, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_POPUPCHECK)
+ AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_CHECKED | MF_STRING, gcmi.Item[i].dwID, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_POPUPSEPARATOR)
+ AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, MF_SEPARATOR, 0, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_SEPARATOR)
+ AppendMenu(*hMenu, MF_SEPARATOR, 0, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_HMENU)
+ AppendMenu(*hMenu, dwState | MF_POPUP, gcmi.Item[i].dwID, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_ITEM)
+ AppendMenu(*hMenu, dwState | MF_STRING, gcmi.Item[i].dwID, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_CHECK)
+ AppendMenu(*hMenu, dwState | MF_CHECKED | MF_STRING, gcmi.Item[i].dwID, ptszDescr);
+
+ mir_free(ptszDescr);
+ }
+
+#if !defined(__DELAYED_FOR_3_1)
+ if (iIndex == 0) {
+ AppendMenu(*hMenu, MF_SEPARATOR, 0, 0);
+ pos = GetMenuItemCount(*hMenu);
+ InsertMenu(*hMenu, pos, MF_BYPOSITION, (UINT_PTR)20020, CTranslator::get(CTranslator::GEN_MUC_MENU_ADDTOHIGHLIGHT));
+ InsertMenu(*hMenu, pos, MF_BYPOSITION, (UINT_PTR)20021, CTranslator::get(CTranslator::GEN_MUC_MENU_EDITHIGHLIGHTLIST));
+ }
+#endif
+ if (iIndex == 1 && si->iType != GCW_SERVER && !(si->dwFlags & GC_UNICODE)) {
+ AppendMenu(*hMenu, MF_SEPARATOR, 0, 0);
+ InsertMenu(PluginConfig.g_hMenuEncoding, 1, MF_BYPOSITION | MF_STRING, (UINT_PTR)CP_UTF8, CTranslator::get(CTranslator::GEN_STRING_UTF8));
+ pos = GetMenuItemCount(*hMenu);
+ InsertMenu(*hMenu, pos, MF_BYPOSITION | MF_POPUP, (UINT_PTR) PluginConfig.g_hMenuEncoding, CTranslator::get(CTranslator::GEN_MSG_ENCODING));
+ for (i = 0; i < GetMenuItemCount(PluginConfig.g_hMenuEncoding); i++)
+ CheckMenuItem(PluginConfig.g_hMenuEncoding, i, MF_BYPOSITION | MF_UNCHECKED);
+ if (codepage == CP_ACP)
+ CheckMenuItem(PluginConfig.g_hMenuEncoding, 0, MF_BYPOSITION | MF_CHECKED);
+ else
+ CheckMenuItem(PluginConfig.g_hMenuEncoding, codepage, MF_BYCOMMAND | MF_CHECKED);
+
+ }
+
+ return TrackPopupMenu(*hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL);
+}
+
+void DestroyGCMenu(HMENU *hMenu, int iIndex)
+{
+ MENUITEMINFO mi;
+ mi.cbSize = sizeof(mi);
+ mi.fMask = MIIM_SUBMENU;
+ while (GetMenuItemInfo(*hMenu, iIndex, TRUE, &mi)) {
+ if (mi.hSubMenu != NULL)
+ DestroyMenu(mi.hSubMenu);
+ RemoveMenu(*hMenu, iIndex, MF_BYPOSITION);
+ }
+}
+
+BOOL DoEventHookAsync(HWND hwnd, const TCHAR* pszID, const char* pszModule, int iType, TCHAR* pszUID, TCHAR* pszText, DWORD dwItem)
+{
+ SESSION_INFO* si;
+ GCHOOK* gch = (GCHOOK*)mir_alloc(sizeof(GCHOOK));
+ GCDEST* gcd = (GCDEST*)mir_alloc(sizeof(GCDEST));
+
+ memset(gch, 0, sizeof(GCHOOK));
+ memset(gcd, 0, sizeof(GCDEST));
+
+ replaceStrA(&gcd->pszModule, pszModule);
+ if ((si = SM_FindSession(pszID, pszModule)) == NULL)
+ return FALSE;
+
+ if (!(si->dwFlags & GC_UNICODE)) {
+ DWORD dwCP = M->GetDword(si->hContact, "ANSIcodepage", 0);
+ gcd->pszID = t2a(pszID, 0);
+ gch->pszUID = t2a(pszUID, 0);
+ gch->pszText = t2a(pszText, dwCP);
+ } else {
+ replaceStr(&gcd->ptszID, pszID);
+ replaceStr(&gch->ptszUID, pszUID);
+ replaceStr(&gch->ptszText, pszText);
+ }
+ gcd->iType = iType;
+ gch->dwData = dwItem;
+ gch->pDest = gcd;
+ PostMessage(hwnd, GC_FIREHOOK, 0, (LPARAM) gch);
+ return TRUE;
+}
+
+BOOL DoEventHook(const TCHAR* pszID, const char* pszModule, int iType, const TCHAR* pszUID, const TCHAR* pszText, DWORD dwItem)
+{
+ SESSION_INFO* si;
+ GCHOOK gch = {0};
+ GCDEST gcd = {0};
+
+ gcd.pszModule = (char*)pszModule;
+ if ((si = SM_FindSession(pszID, pszModule)) == NULL)
+ return FALSE;
+
+ if (!(si->dwFlags & GC_UNICODE)) {
+ DWORD dwCP = M->GetDword(si->hContact, "ANSIcodepage", 0);
+ gcd.pszID = t2a(pszID, 0);
+ gch.pszUID = t2a(pszUID, 0);
+ gch.pszText = t2a(pszText, dwCP);
+ } else {
+ gcd.ptszID = mir_tstrdup(pszID);
+ gch.ptszUID = mir_tstrdup(pszUID);
+ gch.ptszText = mir_tstrdup(pszText);
+ }
+ gcd.iType = iType;
+ gch.dwData = dwItem;
+ gch.pDest = &gcd;
+ NotifyEventHooks(hSendEvent, 0, (WPARAM)&gch);
+
+ mir_free(gcd.pszID);
+ mir_free(gch.ptszUID);
+ mir_free(gch.ptszText);
+ return TRUE;
+}
+
+BOOL IsEventSupported(int eventType)
+{
+ switch (eventType) {
+ // Supported events
+ case GC_EVENT_JOIN:
+ case GC_EVENT_PART:
+ case GC_EVENT_QUIT:
+ case GC_EVENT_KICK:
+ case GC_EVENT_NICK:
+ case GC_EVENT_NOTICE:
+ case GC_EVENT_MESSAGE:
+ case GC_EVENT_TOPIC:
+ case GC_EVENT_INFORMATION:
+ case GC_EVENT_ACTION:
+ case GC_EVENT_ADDSTATUS:
+ case GC_EVENT_REMOVESTATUS:
+ case GC_EVENT_CHUID:
+ case GC_EVENT_CHANGESESSIONAME:
+ case GC_EVENT_ADDGROUP:
+ case GC_EVENT_SETITEMDATA:
+ case GC_EVENT_GETITEMDATA:
+ case GC_EVENT_SETSBTEXT:
+ case GC_EVENT_ACK:
+ case GC_EVENT_SENDMESSAGE:
+ case GC_EVENT_SETSTATUSEX:
+ case GC_EVENT_CONTROL:
+ case GC_EVENT_SETCONTACTSTATUS:
+ return TRUE;
+ }
+
+ // Other events
+ return FALSE;
+}
+
+TCHAR* a2tf(const TCHAR* str, int flags, DWORD cp)
+{
+ if (str == NULL)
+ return NULL;
+
+ if (flags & GC_UNICODE)
+ return mir_tstrdup(str);
+ else {
+ int cbLen;
+ TCHAR *result;
+
+ if (cp == CP_UTF8)
+ return(M->utf8_decodeW((char *)str));
+
+ if (cp == 0)
+ cp = PluginConfig.m_LangPackCP; // CallService( MS_LANGPACK_GETCODEPAGE, 0, 0 );
+ cbLen = MultiByteToWideChar(cp, 0, (char*)str, -1, 0, 0);
+ result = (TCHAR*)mir_alloc(sizeof(TCHAR) * (cbLen + 1));
+ if (result == NULL)
+ return NULL;
+
+ MultiByteToWideChar(cp, 0, (char*)str, -1, result, cbLen);
+ result[ cbLen ] = 0;
+ return result;
+ }
+}
+
+static char* u2a(const wchar_t* src, DWORD cp)
+{
+ int cbLen;
+ char *result;
+
+ if (cp == 0)
+ cp = PluginConfig.m_LangPackCP;
+ else if (cp == CP_UTF8)
+ return(M->utf8_encodeW(src));
+
+ cbLen = WideCharToMultiByte(cp, 0, src, -1, NULL, 0, NULL, NULL);
+ result = (char*)mir_alloc(cbLen + 1);
+ if (result == NULL)
+ return NULL;
+
+ WideCharToMultiByte(cp, 0, src, -1, result, cbLen, NULL, NULL);
+ result[ cbLen ] = 0;
+ return result;
+}
+
+char* t2a(const TCHAR* src, DWORD cp)
+{
+ return u2a(src, cp);
+}
+
+TCHAR* replaceStr(TCHAR** dest, const TCHAR* src)
+{
+ mir_free(*dest);
+ *dest = mir_tstrdup(src);
+ return *dest;
+}
+
+char* replaceStrA(char** dest, const char* src)
+{
+ mir_free(*dest);
+ *dest = mir_strdup(src);
+ return *dest;
+}
+
+/*
+ * set all filters and notification config for a session
+ * uses per channel mask + filterbits, default config as backup
+ */
+
+void Chat_SetFilters(SESSION_INFO *si)
+{
+ DWORD dwFlags_default = 0, dwMask = 0, dwFlags_local = 0;
+ int i;
+
+ if (si == NULL)
+ return;
+
+ dwFlags_default = M->GetDword("Chat", "FilterFlags", 0x03E0);
+ dwFlags_local = M->GetDword(si->hContact, "Chat", "FilterFlags", 0x03E0);
+ dwMask = M->GetDword(si->hContact, "Chat", "FilterMask", 0);
+
+ si->iLogFilterFlags = dwFlags_default;
+ for (i = 0; i < 32; i++) {
+ if (dwMask & (1 << i))
+ si->iLogFilterFlags = (dwFlags_local & (1 << i) ? si->iLogFilterFlags | (1 << i) : si->iLogFilterFlags & ~(1 << i));
+ }
+
+ dwFlags_default = M->GetDword("Chat", "PopupFlags", 0x03E0);
+ dwFlags_local = M->GetDword(si->hContact, "Chat", "PopupFlags", 0x03E0);
+ dwMask = M->GetDword(si->hContact, "Chat", "PopupMask", 0);
+
+ si->iLogPopupFlags = dwFlags_default;
+ for (i = 0; i < 32; i++) {
+ if (dwMask & (1 << i))
+ si->iLogPopupFlags = (dwFlags_local & (1 << i) ? si->iLogPopupFlags | (1 << i) : si->iLogPopupFlags & ~(1 << i));
+ }
+
+ dwFlags_default = M->GetDword("Chat", "TrayIconFlags", 0x03E0);
+ dwFlags_local = M->GetDword(si->hContact, "Chat", "TrayIconFlags", 0x03E0);
+ dwMask = M->GetDword(si->hContact, "Chat", "TrayIconMask", 0);
+
+ si->iLogTrayFlags = dwFlags_default;
+ for (i = 0; i < 32; i++) {
+ if (dwMask & (1 << i))
+ si->iLogTrayFlags = (dwFlags_local & (1 << i) ? si->iLogTrayFlags | (1 << i) : si->iLogTrayFlags & ~(1 << i));
+ }
+
+ dwFlags_default = M->GetDword("Chat", "DiskLogFlags", 0xFFFF);
+ si->iDiskLogFlags = dwFlags_default;
+
+
+ if (si->iLogFilterFlags == 0)
+ si->bFilterEnabled = 0;
+}
+
+static TCHAR tszOldTimeStamp[30] = _T("\0");
+
+TCHAR* GetChatLogsFilename(SESSION_INFO *si, time_t tTime)
+{
+ REPLACEVARSARRAY rva[11];
+ REPLACEVARSDATA dat = {0};
+ TCHAR *p = 0, *tszParsedName = 0;
+ int i;
+ bool fReparse = false;
+
+ if(!tTime)
+ time(&tTime);
+
+ /*
+ * check whether relevant parts of the timestamp have changed and
+ * we have to reparse the filename
+ */
+
+ TCHAR *tszNow = MakeTimeStamp(_T("%a%d%m%Y"), tTime);
+
+ if(_tcscmp(tszOldTimeStamp, tszNow)) {
+ _tcsncpy(tszOldTimeStamp, tszNow, 30);
+ tszOldTimeStamp[29] = 0;
+ fReparse = true;
+ }
+
+ if(fReparse || 0 == si->pszLogFileName[0]) {
+ rva[0].lptzKey = _T("d");
+ rva[0].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%#d"), tTime));
+ // day 01-31
+ rva[1].lptzKey = _T("dd");
+ rva[1].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%d"), tTime));
+ // month 1-12
+ rva[2].lptzKey = _T("m");
+ rva[2].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%#m"), tTime));
+ // month 01-12
+ rva[3].lptzKey = _T("mm");
+ rva[3].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%m"), tTime));
+ // month text short
+ rva[4].lptzKey = _T("mon");
+ rva[4].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%b"), tTime));
+ // month text
+ rva[5].lptzKey = _T("month");
+ rva[5].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%B"), tTime));
+ // year 01-99
+ rva[6].lptzKey = _T("yy");
+ rva[6].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%y"), tTime));
+ // year 1901-9999
+ rva[7].lptzKey = _T("yyyy");
+ rva[7].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%Y"), tTime));
+ // weekday short
+ rva[8].lptzKey = _T("wday");
+ rva[8].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%a"), tTime));
+ // weekday
+ rva[9].lptzKey = _T("weekday");
+ rva[9].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%A"), tTime));
+ // end of array
+ rva[10].lptzKey = NULL;
+ rva[10].lptzValue = NULL;
+
+ if (g_Settings.pszLogDir[lstrlen(g_Settings.pszLogDir)-1] == '\\')
+ _tcscat(g_Settings.pszLogDir, _T("%userid%.log"));
+
+ dat.cbSize = sizeof(dat);
+ dat.dwFlags = RVF_TCHAR;
+ dat.hContact = si->hContact;
+ dat.variables = rva;
+ tszParsedName = (TCHAR*) CallService(MS_UTILS_REPLACEVARS, (WPARAM)g_Settings.pszLogDir, (LPARAM)&dat);
+
+ if(!M->pathIsAbsolute(tszParsedName))
+ mir_sntprintf(si->pszLogFileName, MAX_PATH, _T("%s%s"), M->getChatLogPath(), tszParsedName);
+ else
+ mir_sntprintf(si->pszLogFileName, MAX_PATH, _T("%s"), tszParsedName);
+
+ mir_free(tszParsedName);
+
+ for (i=0; i < SIZEOF(rva);i++)
+ mir_free(rva[i].lptzValue);
+
+ for (p = si->pszLogFileName + 2; *p; ++p) {
+ if (*p == ':' || *p == '*' || *p == '?' || *p == '"' || *p == '<' || *p == '>' || *p == '|' )
+ *p = _T('_');
+ }
+ }
+
+ return si->pszLogFileName;
+}