From 5d2730f1fb7c3d79ce55292f1d5d7bb5dc33cb44 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 8 Mar 2017 15:39:07 +0300 Subject: code reordering --- plugins/TabSRMM/res/chat.rc | 5 +- plugins/TabSRMM/src/chat.h | 147 ++ plugins/TabSRMM/src/chat/chat.h | 147 -- plugins/TabSRMM/src/chat/chat_resource.h | 143 -- plugins/TabSRMM/src/chat/log.cpp | 1023 --------- plugins/TabSRMM/src/chat/main.cpp | 262 --- plugins/TabSRMM/src/chat/manager.cpp | 123 -- plugins/TabSRMM/src/chat/muchighlight.cpp | 336 --- plugins/TabSRMM/src/chat/muchighlight.h | 87 - plugins/TabSRMM/src/chat/options.cpp | 1006 --------- plugins/TabSRMM/src/chat/services.cpp | 160 -- plugins/TabSRMM/src/chat/tools.cpp | 696 ------ plugins/TabSRMM/src/chat/window.cpp | 3124 --------------------------- plugins/TabSRMM/src/chat_log.cpp | 1023 +++++++++ plugins/TabSRMM/src/chat_main.cpp | 262 +++ plugins/TabSRMM/src/chat_manager.cpp | 123 ++ plugins/TabSRMM/src/chat_options.cpp | 1006 +++++++++ plugins/TabSRMM/src/chat_resource.h | 143 ++ plugins/TabSRMM/src/chat_tools.cpp | 696 ++++++ plugins/TabSRMM/src/chat_window.cpp | 3258 +++++++++++++++++++++++++++++ plugins/TabSRMM/src/muchighlight.cpp | 336 +++ plugins/TabSRMM/src/muchighlight.h | 87 + plugins/TabSRMM/src/stdafx.h | 4 +- plugins/TabSRMM/tabsrmm.vcxproj | 8 - 24 files changed, 7086 insertions(+), 7119 deletions(-) create mode 100644 plugins/TabSRMM/src/chat.h delete mode 100644 plugins/TabSRMM/src/chat/chat.h delete mode 100644 plugins/TabSRMM/src/chat/chat_resource.h delete mode 100644 plugins/TabSRMM/src/chat/log.cpp delete mode 100644 plugins/TabSRMM/src/chat/main.cpp delete mode 100644 plugins/TabSRMM/src/chat/manager.cpp delete mode 100644 plugins/TabSRMM/src/chat/muchighlight.cpp delete mode 100644 plugins/TabSRMM/src/chat/muchighlight.h delete mode 100644 plugins/TabSRMM/src/chat/options.cpp delete mode 100644 plugins/TabSRMM/src/chat/services.cpp delete mode 100644 plugins/TabSRMM/src/chat/tools.cpp delete mode 100644 plugins/TabSRMM/src/chat/window.cpp create mode 100644 plugins/TabSRMM/src/chat_log.cpp create mode 100644 plugins/TabSRMM/src/chat_main.cpp create mode 100644 plugins/TabSRMM/src/chat_manager.cpp create mode 100644 plugins/TabSRMM/src/chat_options.cpp create mode 100644 plugins/TabSRMM/src/chat_resource.h create mode 100644 plugins/TabSRMM/src/chat_tools.cpp create mode 100644 plugins/TabSRMM/src/chat_window.cpp create mode 100644 plugins/TabSRMM/src/muchighlight.cpp create mode 100644 plugins/TabSRMM/src/muchighlight.h (limited to 'plugins') diff --git a/plugins/TabSRMM/res/chat.rc b/plugins/TabSRMM/res/chat.rc index b19880376f..87e0f3685f 100644 --- a/plugins/TabSRMM/res/chat.rc +++ b/plugins/TabSRMM/res/chat.rc @@ -1,6 +1,6 @@ // Microsoft Visual C++ generated resource script. // -#include "..\src\chat\chat_resource.h" +#include "..\src\chat_resource.h" #include "..\src\resource.h" #define APSTUDIO_READONLY_SYMBOLS @@ -294,7 +294,8 @@ END 1 TEXTINCLUDE BEGIN - "..\\src\\chat\\chat_resource.h\0" + "..\\src\\chat_resource.h\r\n" + "..\\src\\resource.h\0" END 2 TEXTINCLUDE diff --git a/plugins/TabSRMM/src/chat.h b/plugins/TabSRMM/src/chat.h new file mode 100644 index 0000000000..9551527c54 --- /dev/null +++ b/plugins/TabSRMM/src/chat.h @@ -0,0 +1,147 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Miranda NG: the free IM client for Microsoft* Windows* +// +// Copyright (ñ) 2012-17 Miranda NG project, +// Copyright (c) 2000-09 Miranda ICQ/IM project, +// all portions of this codebase are copyrighted to the people +// listed in contributors.txt. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// you should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// part of tabSRMM messaging plugin for Miranda. +// +// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + +#ifndef _CHAT_H_ +#define _CHAT_H_ + +//defines + +enum TChatStatusEx +{ + CHAT_STATUS_NORMAL, + CHAT_STATUS_AWAY, + CHAT_STATUS_OFFLINE, + CHAT_STATUS_MAX +}; + +class CMUCHighlight; + +// structs + +struct MODULEINFO : public GCModuleInfoBase +{ + DWORD idleTimeStamp; + DWORD lastIdleCheck; + wchar_t tszIdleMsg[60]; +}; + +struct SESSION_INFO : public GCSessionInfoBase +{ + CChatRoomDlg *dat; + int iLogTrayFlags, iLogPopupFlags, iDiskLogFlags; +}; + +struct LOGSTREAMDATA : public GCLogStreamDataBase +{ + int crCount; + CChatRoomDlg *dat; +}; + +struct TMUCSettings : public GlobalLogSettingsBase +{ + HICON hIconOverlay; + DWORD dwIconFlags; + LONG iNickListFontHeight; + int iEventLimitThreshold; + + HFONT UserListFonts[CHAT_STATUS_MAX]; + COLORREF UserListColors[CHAT_STATUS_MAX]; + + COLORREF nickColors[8]; + HBRUSH SelectionBGBrush; + bool bOpenInDefault, bBBCodeInPopups; + bool bDoubleClick4Privat, bShowContactStatus, bContactStatusFirst; + + bool bLogClassicIndicators, bAlternativeSorting, bAnnoyingHighlight, bCreateWindowOnHighlight; + bool bLogSymbols, bClassicIndicators, bClickableNicks, bColorizeNicks, bColorizeNicksInLog; + bool bScaleIcons, bUseCommaAsColon, bNewLineAfterNames; + + CMUCHighlight* Highlight; +}; + +struct FLASH_PARAMS +{ + MCONTACT hContact; + const char* sound; + int iEvent; + HICON hNotifyIcon; + bool bActiveTab, bHighlight, bInactive, bMustFlash, bMustAutoswitch; + HWND hWnd; +}; + +extern TMUCSettings g_Settings; +extern CHAT_MANAGER saveCI; + +#pragma comment(lib,"comctl32.lib") + +////////////////////////////////////////////////////////////////////////////////// + +// log.c +char* Log_CreateRtfHeader(MODULEINFO *mi); + +// window.c +int GetTextPixelSize(wchar_t* pszText, HFONT hFont, bool bWidth); + +// options.c +enum { FONTSECTION_AUTO, FONTSECTION_IM, FONTSECTION_IP }; +void LoadMsgDlgFont(int section, int i, LOGFONT * lf, COLORREF * colour, char* szMod); +void AddIcons(void); +HICON LoadIconEx(char *pszIcoLibName); + +// services.c +void ShowRoom(SESSION_INFO *si); + +// manager.c +SESSION_INFO* SM_FindSessionByHWND(HWND h); +SESSION_INFO* SM_FindSessionByHCONTACT(MCONTACT h); +SESSION_INFO* SM_FindSessionAutoComplete(const char* pszModule, SESSION_INFO* currSession, SESSION_INFO* prevSession, const wchar_t* pszOriginal, const wchar_t* pszCurrent); + +BOOL SM_ReconfigureFilters(); + +int UM_CompareItem(USERINFO *u1, const wchar_t* pszNick, WORD wStatus); + +// tools.c +BOOL DoSoundsFlashPopupTrayStuff(SESSION_INFO *si, GCEVENT *gce, BOOL bHighlight, int bManyFix); +int Chat_GetColorIndex(const char* pszModule, COLORREF cr); +wchar_t* my_strstri(const wchar_t* s1, const wchar_t* s2); +int GetRichTextLength(HWND hwnd); +bool IsHighlighted(SESSION_INFO *si, GCEVENT *pszText); +char GetIndicator(SESSION_INFO *si, LPCTSTR ptszNick, int *iNickIndex); +UINT CreateGCMenu(HWND hwndDlg, HMENU *hMenu, int iIndex, POINT pt, SESSION_INFO *si, wchar_t* pszUID, wchar_t* pszWordText); +void DestroyGCMenu(HMENU *hMenu, int iIndex); +void Chat_SetFilters(SESSION_INFO *si); +void DoFlashAndSoundWorker(FLASH_PARAMS* p); +BOOL DoPopup(SESSION_INFO *si, GCEVENT* gce); +int ShowPopup(MCONTACT hContact, SESSION_INFO *si, HICON hIcon, char* pszProtoName, wchar_t* pszRoomName, COLORREF crBkg, const wchar_t* fmt, ...); +BOOL LogToFile(SESSION_INFO *si, GCEVENT *gce); + +#include "chat_resource.h" + +extern char szIndicators[]; + +#define DEFLOGFILENAME L"%miranda_logpath%\\%proto%\\%userid%.log" + +#endif diff --git a/plugins/TabSRMM/src/chat/chat.h b/plugins/TabSRMM/src/chat/chat.h deleted file mode 100644 index 9551527c54..0000000000 --- a/plugins/TabSRMM/src/chat/chat.h +++ /dev/null @@ -1,147 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////////////// -// Miranda NG: the free IM client for Microsoft* Windows* -// -// Copyright (ñ) 2012-17 Miranda NG project, -// Copyright (c) 2000-09 Miranda ICQ/IM project, -// all portions of this codebase are copyrighted to the people -// listed in contributors.txt. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// you should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -// part of tabSRMM messaging plugin for Miranda. -// -// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors - -#ifndef _CHAT_H_ -#define _CHAT_H_ - -//defines - -enum TChatStatusEx -{ - CHAT_STATUS_NORMAL, - CHAT_STATUS_AWAY, - CHAT_STATUS_OFFLINE, - CHAT_STATUS_MAX -}; - -class CMUCHighlight; - -// structs - -struct MODULEINFO : public GCModuleInfoBase -{ - DWORD idleTimeStamp; - DWORD lastIdleCheck; - wchar_t tszIdleMsg[60]; -}; - -struct SESSION_INFO : public GCSessionInfoBase -{ - CChatRoomDlg *dat; - int iLogTrayFlags, iLogPopupFlags, iDiskLogFlags; -}; - -struct LOGSTREAMDATA : public GCLogStreamDataBase -{ - int crCount; - CChatRoomDlg *dat; -}; - -struct TMUCSettings : public GlobalLogSettingsBase -{ - HICON hIconOverlay; - DWORD dwIconFlags; - LONG iNickListFontHeight; - int iEventLimitThreshold; - - HFONT UserListFonts[CHAT_STATUS_MAX]; - COLORREF UserListColors[CHAT_STATUS_MAX]; - - COLORREF nickColors[8]; - HBRUSH SelectionBGBrush; - bool bOpenInDefault, bBBCodeInPopups; - bool bDoubleClick4Privat, bShowContactStatus, bContactStatusFirst; - - bool bLogClassicIndicators, bAlternativeSorting, bAnnoyingHighlight, bCreateWindowOnHighlight; - bool bLogSymbols, bClassicIndicators, bClickableNicks, bColorizeNicks, bColorizeNicksInLog; - bool bScaleIcons, bUseCommaAsColon, bNewLineAfterNames; - - CMUCHighlight* Highlight; -}; - -struct FLASH_PARAMS -{ - MCONTACT hContact; - const char* sound; - int iEvent; - HICON hNotifyIcon; - bool bActiveTab, bHighlight, bInactive, bMustFlash, bMustAutoswitch; - HWND hWnd; -}; - -extern TMUCSettings g_Settings; -extern CHAT_MANAGER saveCI; - -#pragma comment(lib,"comctl32.lib") - -////////////////////////////////////////////////////////////////////////////////// - -// log.c -char* Log_CreateRtfHeader(MODULEINFO *mi); - -// window.c -int GetTextPixelSize(wchar_t* pszText, HFONT hFont, bool bWidth); - -// options.c -enum { FONTSECTION_AUTO, FONTSECTION_IM, FONTSECTION_IP }; -void LoadMsgDlgFont(int section, int i, LOGFONT * lf, COLORREF * colour, char* szMod); -void AddIcons(void); -HICON LoadIconEx(char *pszIcoLibName); - -// services.c -void ShowRoom(SESSION_INFO *si); - -// manager.c -SESSION_INFO* SM_FindSessionByHWND(HWND h); -SESSION_INFO* SM_FindSessionByHCONTACT(MCONTACT h); -SESSION_INFO* SM_FindSessionAutoComplete(const char* pszModule, SESSION_INFO* currSession, SESSION_INFO* prevSession, const wchar_t* pszOriginal, const wchar_t* pszCurrent); - -BOOL SM_ReconfigureFilters(); - -int UM_CompareItem(USERINFO *u1, const wchar_t* pszNick, WORD wStatus); - -// tools.c -BOOL DoSoundsFlashPopupTrayStuff(SESSION_INFO *si, GCEVENT *gce, BOOL bHighlight, int bManyFix); -int Chat_GetColorIndex(const char* pszModule, COLORREF cr); -wchar_t* my_strstri(const wchar_t* s1, const wchar_t* s2); -int GetRichTextLength(HWND hwnd); -bool IsHighlighted(SESSION_INFO *si, GCEVENT *pszText); -char GetIndicator(SESSION_INFO *si, LPCTSTR ptszNick, int *iNickIndex); -UINT CreateGCMenu(HWND hwndDlg, HMENU *hMenu, int iIndex, POINT pt, SESSION_INFO *si, wchar_t* pszUID, wchar_t* pszWordText); -void DestroyGCMenu(HMENU *hMenu, int iIndex); -void Chat_SetFilters(SESSION_INFO *si); -void DoFlashAndSoundWorker(FLASH_PARAMS* p); -BOOL DoPopup(SESSION_INFO *si, GCEVENT* gce); -int ShowPopup(MCONTACT hContact, SESSION_INFO *si, HICON hIcon, char* pszProtoName, wchar_t* pszRoomName, COLORREF crBkg, const wchar_t* fmt, ...); -BOOL LogToFile(SESSION_INFO *si, GCEVENT *gce); - -#include "chat_resource.h" - -extern char szIndicators[]; - -#define DEFLOGFILENAME L"%miranda_logpath%\\%proto%\\%userid%.log" - -#endif diff --git a/plugins/TabSRMM/src/chat/chat_resource.h b/plugins/TabSRMM/src/chat/chat_resource.h deleted file mode 100644 index ee8255a0db..0000000000 --- a/plugins/TabSRMM/src/chat/chat_resource.h +++ /dev/null @@ -1,143 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by chat.rc -// -#define IDR_MENU 151 -#define IDD_CHANNEL 401 -#define IDD_OPTIONS1 402 -#define IDD_OPTIONS2 403 -#define IDD_FILTER 404 -#define IDD_OPTIONSPOPUP 405 -#define IDD_OPTIONS3 407 -#define IDD_OPTIONS4 408 -#define IDD_ADDHIGHLIGHT 409 -#define IDC_CHECKBOXES 1021 -#define IDC_NICKROW2 1023 -#define IDC_NICKROW 1024 -#define IDC_LOGLIMIT 1024 -#define IDC_CHAT_SPIN2 1029 -#define IDC_CHAT_SPIN3 1030 -#define IDC_CHAT_SPIN4 1031 -#define IDC_PANELNICK 1032 -#define IDC_PANELUIN 1033 -#define IDC_INSTAMP 1041 -#define IDC_OUTSTAMP 1043 -#define IDC_TIMESTAMP 1046 -#define IDC_FONTCHOOSE 1047 -#define IDC_LOGDIRECTORY 1048 -#define IDC_LIMIT 1050 -#define IDC_LOGTIMESTAMP 1051 -#define IDC_GROUP 1057 -#define IDC_RADIO2 1062 -#define IDC_RADIO3 1063 -#define IDC_TEXT 1064 -#define IDC_BKG 1065 -#define IDC_TIMEOUT 1067 -#define IDC_TEXTO 1069 -#define IDC_LOGGING 1069 -#define IDC_TEXTO2 1070 -#define IDC_TEXTO3 1071 -#define IDC_LIST 1072 -#define IDC_TEXTO4 1072 -#define IDC_STATIC_ADD 1077 -#define IDC_STATIC_ULIST 1078 -#define IDC_STATIC_OTHER 1079 -#define IDC_STATIC110 1082 -#define IDC_STATIC112 1085 -#define IDC_TRAYONLYFORINACTIVE 1086 -#define IDC_LOGICONTYPE 1088 -#define IDC_HIGHLIGHTNICKENABLE 1089 -#define IDC_HIGHLIGHTNICKUID 1090 -#define IDC_HIGHLIGHTNICKPATTERN 1091 -#define IDC_HIGHLIGHTTEXTENABLE 1092 -#define IDC_COMBO1 1092 -#define IDC_ADDHIGHLIGHTNAME 1092 -#define IDC_HIGHLIGHTTEXTPATTERN 1093 -#define IDC_ADDHIGHLIGHTTITLE 1093 -#define IDC_ADDHIGHLIGHTEXPLAIN 1094 -#define IDC_HIGHLIGHTNICKUID2 1094 -#define IDC_HIGHLIGHTME 1094 -#define IDC_ADDHIGHLIGHTEDITLIST 1095 -#define IDC_MUC_OPENLOGBASEDIR 1096 -#define IDC_BOLD 1106 -#define IDC_ITALICS 1107 -#define IDC_UNDERLINE 1108 -#define IDC_COLOR 1110 -#define IDC_1 1200 -#define IDC_2 1201 -#define IDC_3 1202 -#define IDC_4 1203 -#define IDC_5 1204 -#define IDC_6 1205 -#define IDC_7 1206 -#define IDC_8 1207 -#define IDC_9 1208 -#define IDC_10 1209 -#define IDC_11 1210 -#define IDC_PANELSPLITTER 1216 -#define IDC_P1 1300 -#define IDC_P2 1301 -#define IDC_P3 1302 -#define IDC_P4 1303 -#define IDC_P5 1304 -#define IDC_P6 1305 -#define IDC_P7 1306 -#define IDC_P8 1307 -#define IDC_P9 1308 -#define IDC_P10 1309 -#define IDC_P11 1310 -#define IDC_P12 1311 -#define IDC_T1 1400 -#define IDC_T2 1401 -#define IDC_T3 1402 -#define IDC_T4 1403 -#define IDC_T5 1404 -#define IDC_T6 1405 -#define IDC_T7 1406 -#define IDC_T8 1407 -#define IDC_T9 1408 -#define IDC_T10 1409 -#define IDC_T11 1410 -#define IDC_T12 1411 -#define IDC_L1 1500 -#define IDC_L2 1501 -#define IDC_L3 1502 -#define IDC_L4 1503 -#define IDC_L5 1504 -#define IDC_L6 1505 -#define IDC_L7 1506 -#define IDC_L8 1507 -#define IDC_L9 1508 -#define IDC_L10 1509 -#define IDC_L11 1510 -#define IDC_WHITERECT 1600 -#define ID_MESS 40001 -#define ID_NEW 40002 -#define ID_CURR 40003 -#define ID_COPY 40004 -#define ID_COPYALL 40006 -#define ID_CLEARLOG 40009 -#define ID_MESSAGE_UNDO 40013 -#define ID_MESSAGE_COPY 40014 -#define ID_MESSAGE_CUT 40015 -#define ID_MESSAGE_CLEAR 40017 -#define ID_MESSAGE_SELECTALL 40018 -#define ID_MESSAGE_REDO 40019 -#define ID_MESSAGE_PASTE 40020 -#define ID_CLOSE 40022 -#define ID_CLOSEOTHER 40023 -#define ID_LOCKPOSITION 40024 -#define ID_SEARCH_GOOGLE 40027 -#define ID_SEARCH_WIKIPEDIA 40028 -#define ID_WIKIPEDIA_ 40029 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 163 -#define _APS_NEXT_COMMAND_VALUE 40030 -#define _APS_NEXT_CONTROL_VALUE 1097 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/plugins/TabSRMM/src/chat/log.cpp b/plugins/TabSRMM/src/chat/log.cpp deleted file mode 100644 index 5981eb3557..0000000000 --- a/plugins/TabSRMM/src/chat/log.cpp +++ /dev/null @@ -1,1023 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////////////// -// Miranda NG: the free IM client for Microsoft* Windows* -// -// Copyright (ñ) 2012-17 Miranda NG project, -// Copyright (c) 2000-09 Miranda ICQ/IM project, -// all portions of this codebase are copyrighted to the people -// listed in contributors.txt. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// you should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -// part of tabSRMM messaging plugin for Miranda. -// -// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors -// -// Implements the richedit-based message history display for the group -// chat window. - -#include "../stdafx.h" - -/* - * The code for streaming the text is to a large extent copied from - * the srmm module and then modified to fit the chat module. - */ - -static char *szDivider = "\\strike----------------------------------------------------------------------------\\strike0"; - -/* - * ieview MUC support - mostly from scriver - */ - -/* - -static char* u2a(const wchar_t* src, int codepage) -{ - int cbLen = WideCharToMultiByte(codepage, 0, src, -1, NULL, 0, NULL, NULL); - char* result = (char*)mir_alloc(cbLen + 1); - if (result == NULL) - return NULL; - - WideCharToMultiByte(codepage, 0, src, -1, result, cbLen, NULL, NULL); - result[cbLen] = 0; - return result; -} - -static char* t2acp(const wchar_t* src, int codepage) -{ - return u2a(src, codepage); -} - -static wchar_t *a2tcp(const char *text, int cp) -{ - if (text != NULL) { - int cbLen = MultiByteToWideChar(cp, 0, text, -1, NULL, 0); - wchar_t* result = (wchar_t*)mir_alloc(sizeof(wchar_t)*(cbLen + 1)); - if (result == NULL) - return NULL; - MultiByteToWideChar(cp, 0, text, -1, result, cbLen); - return result; - } - return NULL; -} - -static int Log_AppendIEView(LOGSTREAMDATA* streamData, BOOL simpleMode, wchar_t **buffer, int *cbBufferEnd, int *cbBufferAlloced, const wchar_t *fmt, ...) -{ - va_list va; - int lineLen, textCharsCount = 0; - wchar_t* line = (wchar_t*)_alloca(8001 * sizeof(wchar_t)); - wchar_t* d; - MODULEINFO *mi = pci->MM_FindModule(streamData->si->pszModule); - - va_start(va, fmt); - lineLen = mir_vsnwprintf(line, 8000, fmt, va); - if (lineLen < 0) - return 0; - line[lineLen] = 0; - va_end(va); - lineLen = lineLen * 9 + 8; - if (*cbBufferEnd + lineLen > *cbBufferAlloced) { - cbBufferAlloced[0] += (lineLen + 1024 - lineLen % 1024); - *buffer = (wchar_t*)mir_realloc(*buffer, *cbBufferAlloced * sizeof(wchar_t)); - } - - d = *buffer + *cbBufferEnd; - - for (; *line; line++, textCharsCount++) { - if (*line == '%' && !simpleMode) { - wchar_t szTemp[200]; - - szTemp[0] = '\0'; - switch (*++line) { - case '\0': - case '%': - *d++ = '%'; - break; - - case 'c': - case 'f': - if (!g_Settings.bStripFormat && !streamData->bStripFormat) { - if (line[1] != '\0' && line[2] != '\0') { - wchar_t szTemp3[3], c = *line; - int col; - szTemp3[0] = line[1]; - szTemp3[1] = line[2]; - szTemp3[2] = '\0'; - col = _wtoi(szTemp3); - mir_snwprintf(szTemp, L"%%%c#%02X%02X%02X", c, GetRValue(mi->crColors[col]), GetGValue(mi->crColors[col]), GetBValue(mi->crColors[col])); - } - } - line += 2; - break; - case 'C': - case 'F': - if (!g_Settings.bStripFormat && !streamData->bStripFormat) { - mir_snwprintf(szTemp, L"%%%c", *line); - } - break; - case 'b': - case 'u': - case 'i': - case 'B': - case 'U': - case 'I': - case 'r': - if (!streamData->bStripFormat) { - mir_snwprintf(szTemp, L"%%%c", *line); - } - break; - } - - if (szTemp[0]) { - size_t iLen = mir_wstrlen(szTemp); - memcpy(d, szTemp, iLen * sizeof(wchar_t)); - d += iLen; - } - } - else if (*line == '%') { - *d++ = '%'; - *d++ = (char)*line; - } - else { - *d++ = (wchar_t)*line; - } - } - *d = '\0'; - *cbBufferEnd = (int)(d - *buffer); - return textCharsCount; -} - -static void AddEventTextToBufferIEView(wchar_t **buffer, int *bufferEnd, int *bufferAlloced, LOGSTREAMDATA *streamData) -{ - if (streamData->lin->ptszText) - Log_AppendIEView(streamData, FALSE, str, L": %s", streamData->lin->ptszText); -} - -static void AddEventToBufferIEView(wchar_t **buffer, int *bufferEnd, int *bufferAlloced, LOGSTREAMDATA *streamData, wchar_t *pszNick) -{ - - if (streamData && streamData->lin) { - switch (streamData->lin->iType) { - case GC_EVENT_MESSAGE: - if (streamData->lin->ptszText) { - wchar_t *ptszTemp = NULL; - wchar_t *ptszText = streamData->lin->ptszText; - if (streamData->dat->codePage != CP_ACP) { - char *aText = t2acp(streamData->lin->ptszText, CP_ACP); - ptszText = ptszTemp = a2tcp(aText, streamData->dat->codePage); - mir_free(aText); - } - Log_AppendIEView(streamData, FALSE, str, L"%s", ptszText); - mir_free(ptszTemp); - } - break; - case GC_EVENT_ACTION: - if (pszNick && streamData->lin->ptszText) { - Log_AppendIEView(streamData, TRUE, str, L"%s ", streamData->lin->ptszNick); - Log_AppendIEView(streamData, FALSE, str, L"%s", streamData->lin->ptszText); - } - break; - case GC_EVENT_JOIN: - if (pszNick) { - if (!streamData->lin->bIsMe) - Log_AppendIEView(streamData, TRUE, str, TranslateT("%s has joined"), pszNick); - else - Log_AppendIEView(streamData, TRUE, str, TranslateT("You have joined %s"), streamData->si->ptszName); - } - break; - case GC_EVENT_PART: - if (pszNick) - Log_AppendIEView(streamData, TRUE, str, TranslateT("%s has left"), pszNick); - AddEventTextToBufferIEView(str, streamData); - break; - case GC_EVENT_QUIT: - if (pszNick) - Log_AppendIEView(streamData, TRUE, str, TranslateT("%s has disconnected"), pszNick); - AddEventTextToBufferIEView(str, streamData); - break; - case GC_EVENT_NICK: - if (pszNick && streamData->lin->ptszText) { - if (!streamData->lin->bIsMe) - Log_AppendIEView(streamData, TRUE, str, TranslateT("%s is now known as %s"), pszNick, streamData->lin->ptszText); - else - Log_AppendIEView(streamData, TRUE, str, TranslateT("You are now known as %s"), streamData->lin->ptszText); - } - break; - case GC_EVENT_KICK: - if (pszNick && streamData->lin->ptszStatus) - Log_AppendIEView(streamData, TRUE, str, TranslateT("%s kicked %s"), streamData->lin->ptszStatus, streamData->lin->ptszNick); - AddEventTextToBufferIEView(str, streamData); - break; - case GC_EVENT_NOTICE: - if (pszNick && streamData->lin->ptszText) { - Log_AppendIEView(streamData, TRUE, str, TranslateT("Notice from %s"), pszNick); - AddEventTextToBufferIEView(str, streamData); - } - break; - case GC_EVENT_TOPIC: - if (streamData->lin->ptszText) - Log_AppendIEView(streamData, FALSE, str, TranslateT("The topic is '%s%s'"), streamData->lin->ptszText, L"%r"); - if (pszNick) - Log_AppendIEView(streamData, TRUE, str, - streamData->lin->ptszUserInfo ? TranslateT(" (set by %s on %s)") : TranslateT(" (set by %s)"), - pszNick, streamData->lin->ptszUserInfo); - break; - case GC_EVENT_INFORMATION: - if (streamData->lin->ptszText) - Log_AppendIEView(streamData, FALSE, str, (streamData->lin->bIsMe) ? L"--> %s" : L"%s", streamData->lin->ptszText); - break; - case GC_EVENT_ADDSTATUS: - if (pszNick && streamData->lin->ptszText && streamData->lin->ptszStatus) - Log_AppendIEView(streamData, TRUE, str, TranslateT("%s enables '%s' status for %s"), streamData->lin->ptszText, streamData->lin->ptszStatus, streamData->lin->ptszNick); - break; - case GC_EVENT_REMOVESTATUS: - if (pszNick && streamData->lin->ptszText && streamData->lin->ptszStatus) - Log_AppendIEView(streamData, TRUE, str, TranslateT("%s disables '%s' status for %s"), streamData->lin->ptszText, streamData->lin->ptszStatus, streamData->lin->ptszNick); - break; - } - } -} - -static void LogEventIEView(LOGSTREAMDATA *streamData, wchar_t *ptszNick) -{ - wchar_t *buffer = NULL; - int bufferEnd = 0; - int bufferAlloced = 0; - IEVIEWEVENTDATA ied; - IEVIEWEVENT event; - memset(&event, 0, sizeof(event)); - event.cbSize = sizeof(event); - event.dwFlags = 0; - event.hwnd = streamData->dat->m_hwndIEView ? streamData->dat->m_hwndIEView : streamData->dat->m_hwndHPP; - event.hContact = streamData->dat->m_hContact; - event.codepage = streamData->dat->codePage; - event.pszProto = streamData->si->pszModule; - event.iType = IEE_LOG_MEM_EVENTS; - event.eventData = &ied; - event.count = 1; - - memset(&ied, 0, sizeof(ied)); - AddEventToBufferIEView(str, streamData, ptszNick); - ied.ptszNick = ptszNick; - ied.ptszText = buffer; - ied.time = streamData->lin->time; - ied.bIsMe = streamData->lin->bIsMe; - - switch (streamData->lin->iType) { - case GC_EVENT_MESSAGE: - ied.iType = IEED_GC_EVENT_MESSAGE; - ied.dwData = IEEDD_GC_SHOW_NICK; - break; - case GC_EVENT_ACTION: - ied.iType = IEED_GC_EVENT_ACTION; - break; - case GC_EVENT_JOIN: - ied.iType = IEED_GC_EVENT_JOIN; - break; - case GC_EVENT_PART: - ied.iType = IEED_GC_EVENT_PART; - break; - case GC_EVENT_QUIT: - ied.iType = IEED_GC_EVENT_QUIT; - break; - case GC_EVENT_NICK: - ied.iType = IEED_GC_EVENT_NICK; - break; - case GC_EVENT_KICK: - ied.iType = IEED_GC_EVENT_KICK; - break; - case GC_EVENT_NOTICE: - ied.iType = IEED_GC_EVENT_NOTICE; - break; - case GC_EVENT_TOPIC: - ied.iType = IEED_GC_EVENT_TOPIC; - break; - case GC_EVENT_INFORMATION: - ied.iType = IEED_GC_EVENT_INFORMATION; - break; - case GC_EVENT_ADDSTATUS: - ied.iType = IEED_GC_EVENT_ADDSTATUS; - break; - case GC_EVENT_REMOVESTATUS: - ied.iType = IEED_GC_EVENT_REMOVESTATUS; - break; - } - ied.dwData |= g_Settings.bShowTime ? IEEDD_GC_SHOW_TIME : 0; - ied.dwData |= IEEDD_GC_SHOW_ICON; - ied.dwFlags = IEEDF_UNICODE_TEXT | IEEDF_UNICODE_NICK | IEEDF_UNICODE_TEXT2; - ied.next = NULL; - CallService(streamData->dat->m_hwndIEView ? MS_IEVIEW_EVENT : MS_HPP_EG_EVENT, 0, (LPARAM)&event); - mir_free(buffer); -} - -*/ - -static int EventToIndex(LOGINFO * lin) -{ - switch (lin->iType) { - case GC_EVENT_MESSAGE: - if (lin->bIsMe) - return 10; - else - return 9; - - case GC_EVENT_JOIN: - return 3; - case GC_EVENT_PART: - return 4; - case GC_EVENT_QUIT: - return 5; - case GC_EVENT_NICK: - return 7; - case GC_EVENT_KICK: - return 6; - case GC_EVENT_NOTICE: - return 8; - case GC_EVENT_TOPIC: - return 11; - case GC_EVENT_INFORMATION: - return 12; - case GC_EVENT_ADDSTATUS: - return 13; - case GC_EVENT_REMOVESTATUS: - return 14; - case GC_EVENT_ACTION: - return 15; - } - return 0; -} - -static BYTE EventToSymbol(LOGINFO *lin) -{ - switch (lin->iType) { - case GC_EVENT_MESSAGE: - return (lin->bIsMe) ? 0x37 : 0x38; - case GC_EVENT_JOIN: - return 0x34; - case GC_EVENT_PART: - return 0x33; - case GC_EVENT_QUIT: - return 0x39; - case GC_EVENT_NICK: - return 0x71; - case GC_EVENT_KICK: - return 0x72; - case GC_EVENT_NOTICE: - return 0x28; - case GC_EVENT_INFORMATION: - return 0x69; - case GC_EVENT_ADDSTATUS: - return 0x35; - case GC_EVENT_REMOVESTATUS: - return 0x36; - case GC_EVENT_ACTION: - return 0x60; - } - return 0x73; -} - -static int EventToIcon(LOGINFO * lin) -{ - switch (lin->iType) { - case GC_EVENT_MESSAGE: - if (lin->bIsMe) - return ICON_MESSAGEOUT; - else - return ICON_MESSAGE; - - case GC_EVENT_JOIN: - return ICON_JOIN; - case GC_EVENT_PART: - return ICON_PART; - case GC_EVENT_QUIT: - return ICON_QUIT; - case GC_EVENT_NICK: - return ICON_NICK; - case GC_EVENT_KICK: - return ICON_KICK; - case GC_EVENT_NOTICE: - return ICON_NOTICE; - case GC_EVENT_TOPIC: - return ICON_TOPIC; - case GC_EVENT_INFORMATION: - return ICON_INFO; - case GC_EVENT_ADDSTATUS: - return ICON_ADDSTATUS; - case GC_EVENT_REMOVESTATUS: - return ICON_REMSTATUS; - case GC_EVENT_ACTION: - return ICON_ACTION; - } - return 0; -} - -static void Log_AppendRTF(LOGSTREAMDATA *streamData, BOOL simpleMode, CMStringA &str, const wchar_t *fmt, ...) -{ - int textCharsCount = 0; - wchar_t *line = (wchar_t*)_alloca(8001 * sizeof(wchar_t)); - - va_list va; - va_start(va, fmt); - int lineLen = mir_vsnwprintf(line, 8000, fmt, va); - if (lineLen < 0) - lineLen = 8000; - line[lineLen] = 0; - va_end(va); - - CMStringA res; - - for (; *line; line++, textCharsCount++) { - if (*line == '\r' && line[1] == '\n') { - res.Append("\\par "); - line++; - } - else if (*line == '\n') { - res.Append("\\line "); - } - else if (*line == '%' && !simpleMode) { - char szTemp[200]; szTemp[0] = '\0'; - switch (*++line) { - case '\0': - case '%': - res.AppendChar('%'); - break; - - case 'c': - case 'f': - if (g_Settings.bStripFormat || streamData->bStripFormat) - line += 2; - else if (line[1] != '\0' && line[2] != '\0') { - wchar_t szTemp3[3], c = *line; - int col; - szTemp3[0] = line[1]; - szTemp3[1] = line[2]; - szTemp3[2] = '\0'; - line += 2; - - col = _wtoi(szTemp3); - col += (OPTIONS_FONTCOUNT + 1); - res.AppendFormat((c == 'c') ? "\\cf%u " : "\\highlight%u ", col); - } - break; - case 'C': - case 'F': - if (!g_Settings.bStripFormat && !streamData->bStripFormat) { - int j = streamData->lin->bIsHighlighted ? 16 : EventToIndex(streamData->lin); - if (*line == 'C') - res.AppendFormat("\\cf%u ", j + 1); - else - res.Append("\\highlight0 "); - } - break; - case 'b': - case 'u': - case 'i': - if (!streamData->bStripFormat) - res.AppendFormat((*line == 'u') ? "\\%cl " : "\\%c ", *line); - break; - - case 'B': - case 'U': - case 'I': - if (!streamData->bStripFormat) - res.AppendFormat((*line == 'U') ? "\\%cl0 " : "\\%c0 ", tolower(*line)); - break; - - case 'r': - if (!streamData->bStripFormat) { - int index = EventToIndex(streamData->lin); - res.AppendFormat("%s ", pci->Log_SetStyle(index)); - } - break; - } - } - else if (*line == '\t' && !streamData->bStripFormat) { - res.Append("\\tab "); - } - else if ((*line == '\\' || *line == '{' || *line == '}') && !streamData->bStripFormat) { - res.AppendChar('\\'); - res.AppendChar(*line); - } - else if (*line > 0 && *line < 128) { - res.AppendChar((char)*line); - } - else res.AppendFormat("\\u%u ?", (WORD)* line); - } - - str += res; -} - -static void AddEventToBuffer(CMStringA &str, LOGSTREAMDATA *streamData) -{ - wchar_t szTemp[512], szTemp2[512]; - wchar_t* pszNick = NULL; - - if (streamData == NULL) - return; - - if (streamData->lin == NULL) - return; - - if (streamData->lin->ptszNick) { - if (g_Settings.bLogLimitNames && mir_wstrlen(streamData->lin->ptszNick) > 20) { - wcsncpy_s(szTemp, 20, streamData->lin->ptszNick, _TRUNCATE); - wcsncpy_s(szTemp + 20, 4, L"...", _TRUNCATE); - } - else wcsncpy_s(szTemp, streamData->lin->ptszNick, _TRUNCATE); - - if (g_Settings.bClickableNicks) - mir_snwprintf(szTemp2, L"~~++#%s#++~~", szTemp); - else - wcsncpy_s(szTemp2, szTemp, _TRUNCATE); - - if (streamData->lin->ptszUserInfo && streamData->lin->iType != GC_EVENT_TOPIC) - mir_snwprintf(szTemp, L"%s (%s)", szTemp2, streamData->lin->ptszUserInfo); - else - wcsncpy_s(szTemp, szTemp2, _TRUNCATE); - pszNick = szTemp; - } - - switch (streamData->lin->iType) { - case GC_EVENT_MESSAGE: - if (streamData->lin->ptszText) - Log_AppendRTF(streamData, FALSE, str, L"%s", streamData->lin->ptszText); - break; - case GC_EVENT_ACTION: - if (streamData->lin->ptszNick && streamData->lin->ptszText) { - Log_AppendRTF(streamData, TRUE, str, L"%s ", streamData->lin->ptszNick); - Log_AppendRTF(streamData, FALSE, str, L"%s", streamData->lin->ptszText); - } - break; - case GC_EVENT_JOIN: - if (pszNick) { - if (!streamData->lin->bIsMe) - /* replace nick of a newcomer with a link */ - Log_AppendRTF(streamData, TRUE, str, TranslateT("%s has joined"), pszNick); - else - Log_AppendRTF(streamData, TRUE, str, TranslateT("You have joined %s"), streamData->si->ptszName); - } - break; - case GC_EVENT_PART: - if (pszNick) - Log_AppendRTF(streamData, TRUE, str, TranslateT("%s has left"), pszNick); - if (streamData->lin->ptszText) - Log_AppendRTF(streamData, FALSE, str, L": %s", streamData->lin->ptszText); - break; - case GC_EVENT_QUIT: - if (pszNick) - Log_AppendRTF(streamData, TRUE, str, TranslateT("%s has disconnected"), pszNick); - if (streamData->lin->ptszText) - Log_AppendRTF(streamData, FALSE, str, L": %s", streamData->lin->ptszText); - break; - case GC_EVENT_NICK: - if (pszNick && streamData->lin->ptszText) { - if (!streamData->lin->bIsMe) - Log_AppendRTF(streamData, TRUE, str, TranslateT("%s is now known as %s"), pszNick, streamData->lin->ptszText); - else - Log_AppendRTF(streamData, TRUE, str, TranslateT("You are now known as %s"), streamData->lin->ptszText); - } - break; - case GC_EVENT_KICK: - if (pszNick && streamData->lin->ptszStatus) - Log_AppendRTF(streamData, TRUE, str, - TranslateT("%s kicked %s"), streamData->lin->ptszStatus, pszNick); - - if (streamData->lin->ptszText) - Log_AppendRTF(streamData, FALSE, str, L": %s", streamData->lin->ptszText); - break; - case GC_EVENT_NOTICE: - if (pszNick && streamData->lin->ptszText) { - Log_AppendRTF(streamData, TRUE, str, TranslateT("Notice from %s: "), pszNick); - Log_AppendRTF(streamData, FALSE, str, L"%s", streamData->lin->ptszText); - } - break; - case GC_EVENT_TOPIC: - if (streamData->lin->ptszText) - Log_AppendRTF(streamData, FALSE, str, TranslateT("The topic is '%s%s'"), streamData->lin->ptszText, L"%r"); - if (pszNick) - Log_AppendRTF(streamData, TRUE, str, - (streamData->lin->ptszUserInfo) ? TranslateT(" (set by %s on %s)") : - TranslateT(" (set by %s)"), - pszNick, streamData->lin->ptszUserInfo); - break; - case GC_EVENT_INFORMATION: - if (streamData->lin->ptszText) - Log_AppendRTF(streamData, FALSE, str, (streamData->lin->bIsMe) ? L"--> %s" : L"%s", streamData->lin->ptszText); - break; - case GC_EVENT_ADDSTATUS: - if (pszNick && streamData->lin->ptszText && streamData->lin->ptszStatus) - Log_AppendRTF(streamData, TRUE, str, - TranslateT("%s enables '%s' status for %s"), - streamData->lin->ptszText, streamData->lin->ptszStatus, pszNick); - break; - case GC_EVENT_REMOVESTATUS: - if (pszNick && streamData->lin->ptszText && streamData->lin->ptszStatus) { - Log_AppendRTF(streamData, TRUE, str, - TranslateT("%s disables '%s' status for %s"), - streamData->lin->ptszText, streamData->lin->ptszStatus, pszNick); - } - break; - } -} - -char* Log_CreateRtfHeader(MODULEINFO *mi) -{ - int i = 0; - - // get the number of pixels per logical inch - if (pci->logPixelSY == 0) { - HDC hdc = GetDC(NULL); - pci->logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); - pci->logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX); - ReleaseDC(NULL, hdc); - } - - // ### RTF HEADER - - // font table - CMStringA str("{\\rtf1\\ansi\\deff0{\\fonttbl"); - for (i = 0; i < OPTIONS_FONTCOUNT; i++) - str.AppendFormat("{\\f%u\\fnil\\fcharset%u%S;}", i, pci->aFonts[i].lf.lfCharSet, pci->aFonts[i].lf.lfFaceName); - - // colour table - str.Append("}{\\colortbl ;"); - - for (i = 0; i < OPTIONS_FONTCOUNT; i++) - str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(pci->aFonts[i].color), GetGValue(pci->aFonts[i].color), GetBValue(pci->aFonts[i].color)); - - for (i = 0; i < mi->nColorCount; i++) - str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(mi->crColors[i]), GetGValue(mi->crColors[i]), GetBValue(mi->crColors[i])); - - for (i = 0; i < STATUSICONCOUNT; i++) - str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(g_Settings.nickColors[i]), GetGValue(g_Settings.nickColors[i]), GetBValue(g_Settings.nickColors[i])); - - // new paragraph - str.AppendFormat("}\\pard\\sl%d", 1000); - - // set tabs and indents - int iIndent = 0; - - if (g_Settings.bLogSymbols) { - wchar_t szString[2]; - LOGFONT lf; - - szString[1] = 0; - szString[0] = 0x28; - pci->LoadMsgDlgFont(17, &lf, NULL); - HFONT hFont = CreateFontIndirect(&lf); - int iText = GetTextPixelSize(szString, hFont, true) + 3; - DeleteObject(hFont); - iIndent += (iText * 1440) / pci->logPixelSX; - str.AppendFormat("\\tx%u", iIndent); - } - else if (g_Settings.dwIconFlags) { - iIndent += ((g_Settings.bScaleIcons ? 14 : 20) * 1440) / pci->logPixelSX; - str.AppendFormat("\\tx%u", iIndent); - } - if (g_Settings.bShowTime) { - int iSize = (g_Settings.LogTextIndent * 1440) / pci->logPixelSX; - str.AppendFormat("\\tx%u", iIndent + iSize); - if (g_Settings.bLogIndentEnabled) - iIndent += iSize; - } - str.AppendFormat("\\fi-%u\\li%u", iIndent, iIndent); - - return str.Detach(); -} - -static char* Log_CreateRTF(LOGSTREAMDATA *streamData) -{ - LOGINFO *lin = streamData->lin; - MODULEINFO *mi = pci->MM_FindModule(streamData->si->pszModule); - - // ### RTF HEADER - - if (0 == mi->pszHeader) - mi->pszHeader = Log_CreateRtfHeader(mi); - - char *header = mi->pszHeader; - streamData->crCount = mi->nColorCount; - - CMStringA str; - if (header) - str.Append(header); - - // ### RTF BODY (one iteration per event that should be streamed in) - while (lin) { - // filter - if ((streamData->si->iType != GCW_CHATROOM && streamData->si->iType != GCW_PRIVMESS) || !streamData->si->bFilterEnabled || (streamData->si->iLogFilterFlags & lin->iType) != 0) { - if (lin->next != NULL) - str.Append("\\par "); - - if (streamData->dat->m_dwFlags & MWF_DIVIDERWANTED || lin->dwFlags & MWF_DIVIDERWANTED) { - static char szStyle_div[128] = "\0"; - if (szStyle_div[0] == 0) - mir_snprintf(szStyle_div, "\\f%u\\cf%u\\ul0\\b%d\\i%d\\fs%u", 17, 18, 0, 0, 5); - - lin->dwFlags |= MWF_DIVIDERWANTED; - if (lin->prev || !streamData->bRedraw) - str.AppendFormat("\\qc\\sl-1\\highlight%d %s ---------------------------------------------------------------------------------------\\par ", 18, szStyle_div); - streamData->dat->m_dwFlags &= ~MWF_DIVIDERWANTED; - } - // create new line, and set font and color - str.AppendFormat("\\ql\\sl0%s ", pci->Log_SetStyle(0)); - str.AppendFormat("\\v~-+%d+-~\\v0 ", lin); - - // Insert icon - if (g_Settings.bLogSymbols) // use symbols - str.AppendFormat("%s %c", pci->Log_SetStyle(17), EventToSymbol(lin)); - else if (g_Settings.dwIconFlags) { - int iIndex = lin->bIsHighlighted ? ICON_HIGHLIGHT : EventToIcon(lin); - str.Append("\\f0\\fs14"); - str.Append(pci->pLogIconBmpBits[iIndex]); - } - - if (g_Settings.bTimeStampEventColour) { - // colored timestamps - static char szStyle[256]; - LOGFONT &F = pci->aFonts[0].lf; - int iii; - if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) { - iii = lin->bIsHighlighted ? 16 : (lin->bIsMe ? 2 : 1); - mir_snprintf(szStyle, "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\ul%d\\fs%u", - iii + 1, F.lfWeight >= FW_BOLD ? 1 : 0, F.lfItalic, F.lfUnderline, 2 * abs(F.lfHeight) * 74 / pci->logPixelSY); - str.Append(szStyle); - } - else { - iii = lin->bIsHighlighted ? 16 : EventToIndex(lin); - mir_snprintf(szStyle, "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\ul%d\\fs%u", - iii + 1, F.lfWeight >= FW_BOLD ? 1 : 0, F.lfItalic, F.lfUnderline, 2 * abs(F.lfHeight) * 74 / pci->logPixelSY); - str.Append(szStyle); - } - } - else str.Append(pci->Log_SetStyle(0)); - str.AppendChar(' '); - - // insert a TAB if necessary to put the timestamp in the right position - if (g_Settings.dwIconFlags) - str.Append("\\tab "); - - //insert timestamp - if (g_Settings.bShowTime) { - wchar_t szTimeStamp[30], szOldTimeStamp[30]; - - wcsncpy_s(szTimeStamp, pci->MakeTimeStamp(g_Settings.pszTimeStamp, lin->time), _TRUNCATE); - wcsncpy_s(szOldTimeStamp, pci->MakeTimeStamp(g_Settings.pszTimeStamp, streamData->si->LastTime), _TRUNCATE); - if (!g_Settings.bShowTimeIfChanged || streamData->si->LastTime == 0 || mir_wstrcmp(szTimeStamp, szOldTimeStamp)) { - streamData->si->LastTime = lin->time; - Log_AppendRTF(streamData, TRUE, str, L"%s", szTimeStamp); - } - str.Append("\\tab "); - } - - // Insert the nick - if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) { - char pszIndicator[3] = "\0\0"; - int crNickIndex = 0; - - if (g_Settings.bLogClassicIndicators || g_Settings.bColorizeNicksInLog) - pszIndicator[0] = GetIndicator(streamData->si, lin->ptszNick, &crNickIndex); - - str.Append(pci->Log_SetStyle(lin->bIsMe ? 2 : 1)); - str.AppendChar(' '); - - if (g_Settings.bLogClassicIndicators) - str.Append(pszIndicator); - - CMStringW pszTemp(lin->bIsMe ? g_Settings.pszOutgoingNick : g_Settings.pszIncomingNick); - pszTemp.Replace(L"%n", L"%s"); - if (!lin->bIsMe) { - if (g_Settings.bClickableNicks) - pszTemp.Replace(L"%s", L"~~++#%s#++~~"); - - if (g_Settings.bColorizeNicksInLog && pszIndicator[0]) - str.AppendFormat("\\cf%u ", OPTIONS_FONTCOUNT + streamData->crCount + crNickIndex); - } - - if (g_Settings.bNewLineAfterNames) - pszTemp.AppendChar('\n'); - - Log_AppendRTF(streamData, TRUE, str, pszTemp, lin->ptszNick); - str.AppendChar(' '); - } - - // Insert the message - str.Append(pci->Log_SetStyle(lin->bIsHighlighted ? 16 : EventToIndex(lin))); - str.AppendChar(' '); - - streamData->lin = lin; - AddEventToBuffer(str, streamData); - } - lin = lin->prev; - } - - // ### RTF END - if (streamData->bRedraw) - str.Append("\\par}"); - else - str.Append("}"); - return str.Detach(); -} - -static DWORD CALLBACK Log_StreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb) -{ - LOGSTREAMDATA *lstrdat = (LOGSTREAMDATA*)dwCookie; - - if (lstrdat) { - // create the RTF - if (lstrdat->buffer == NULL) { - lstrdat->bufferOffset = 0; - lstrdat->buffer = Log_CreateRTF(lstrdat); - lstrdat->bufferLen = (int)mir_strlen(lstrdat->buffer); - } - - // give the RTF to the RE control - *pcb = min(cb, lstrdat->bufferLen - lstrdat->bufferOffset); - memcpy(pbBuff, lstrdat->buffer + lstrdat->bufferOffset, *pcb); - lstrdat->bufferOffset += *pcb; - - // mir_free stuff if the streaming operation is complete - if (lstrdat->bufferOffset == lstrdat->bufferLen) { - mir_free(lstrdat->buffer); - lstrdat->buffer = NULL; - } - } - - return 0; -} - -void CChatRoomDlg::StreamInEvents(LOGINFO *lin, SESSION_INFO *si, bool bRedraw) -{ - CHARRANGE oldsel, sel, newsel; - POINT point = { 0 }; - - if (m_hwnd == 0 || lin == 0 || si == 0) - return; - - HWND hwndRich = GetDlgItem(m_hwnd, IDC_LOG); - - LOGSTREAMDATA streamData; - memset(&streamData, 0, sizeof(streamData)); - streamData.hwnd = hwndRich; - streamData.si = si; - streamData.lin = lin; - streamData.bStripFormat = FALSE; - streamData.dat = this; - - if (!bRedraw && (si->iType == GCW_CHATROOM || si->iType == GCW_PRIVMESS) && si->bFilterEnabled && (si->iLogFilterFlags & lin->iType) == 0) - return; - - bool bFlag = false, fDoReplace; - - EDITSTREAM stream = { 0 }; - stream.pfnCallback = Log_StreamCallback; - stream.dwCookie = (DWORD_PTR)& streamData; - - SCROLLINFO scroll = { 0 }; - scroll.cbSize = sizeof(SCROLLINFO); - scroll.fMask = SIF_RANGE | SIF_POS | SIF_PAGE; - GetScrollInfo(GetDlgItem(m_hwnd, IDC_LOG), SB_VERT, &scroll); - SendMessage(hwndRich, EM_GETSCROLLPOS, 0, (LPARAM)&point); - - // do not scroll to bottom if there is a selection - SendMessage(hwndRich, EM_EXGETSEL, 0, (LPARAM)&oldsel); - if (oldsel.cpMax != oldsel.cpMin) - SendMessage(hwndRich, WM_SETREDRAW, FALSE, 0); - - //set the insertion point at the bottom - sel.cpMin = sel.cpMax = GetRichTextLength(hwndRich); - SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM)&sel); - - // fix for the indent... must be a M$ bug - if (sel.cpMax == 0) - bRedraw = TRUE; - - // should the event(s) be appended to the current log - WPARAM wp = bRedraw ? SF_RTF : SFF_SELECTION | SF_RTF; - - //get the number of pixels per logical inch - if (bRedraw) { - HDC hdc = GetDC(NULL); - pci->logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); - pci->logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX); - ReleaseDC(NULL, hdc); - SendMessage(hwndRich, WM_SETREDRAW, FALSE, 0); - bFlag = true; - // SetCursor(LoadCursor(NULL, IDC_ARROW)); - } - - // stream in the event(s) - streamData.lin = lin; - streamData.bRedraw = bRedraw; - SendMessage(hwndRich, EM_STREAMIN, wp, (LPARAM)&stream); - - // for new added events, only replace in message or action events. - // no need to replace smileys or math formulas elsewhere - fDoReplace = (bRedraw || (lin->ptszText && (lin->iType == GC_EVENT_MESSAGE || lin->iType == GC_EVENT_ACTION))); - - // replace marked nicknames with hyperlinks to make the nicks clickable - if (g_Settings.bClickableNicks) { - FINDTEXTEX fi, fi2; - - CHARFORMAT2 cf2; - memset(&cf2, 0, sizeof(CHARFORMAT2)); - cf2.cbSize = sizeof(cf2); - - fi2.lpstrText = L"#++~~"; - fi.chrg.cpMin = bRedraw ? 0 : sel.cpMin; - fi.chrg.cpMax = -1; - fi.lpstrText = L"~~++#"; - - while (SendMessage(hwndRich, EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi) > -1) { - fi2.chrg.cpMin = fi.chrgText.cpMin; - fi2.chrg.cpMax = -1; - - if (SendMessage(hwndRich, EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi2) > -1) { - - SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM)&fi.chrgText); - SendMessage(hwndRich, EM_REPLACESEL, TRUE, (LPARAM)L""); - fi2.chrgText.cpMin -= fi.chrgText.cpMax - fi.chrgText.cpMin; - fi2.chrgText.cpMax -= fi.chrgText.cpMax - fi.chrgText.cpMin; - SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM)&fi2.chrgText); - SendMessage(hwndRich, EM_REPLACESEL, TRUE, (LPARAM)L""); - fi2.chrgText.cpMax = fi2.chrgText.cpMin; - - fi2.chrgText.cpMin = fi.chrgText.cpMin; - SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM)&fi2.chrgText); - cf2.dwMask = CFM_PROTECTED; - cf2.dwEffects = CFE_PROTECTED; - SendMessage(hwndRich, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2); - } - fi.chrg.cpMin = fi.chrgText.cpMax; - } - SendMessage(hwndRich, EM_SETSEL, -1, -1); - } - - // run smileyadd - if (PluginConfig.g_SmileyAddAvail && fDoReplace) { - newsel.cpMax = -1; - newsel.cpMin = sel.cpMin; - if (newsel.cpMin < 0) - newsel.cpMin = 0; - - SMADD_RICHEDIT3 sm = { sizeof(sm) }; - sm.hwndRichEditControl = hwndRich; - sm.Protocolname = si->pszModule; - sm.rangeToReplace = bRedraw ? NULL : &newsel; - sm.disableRedraw = TRUE; - sm.hContact = si->hContact; - CallService(MS_SMILEYADD_REPLACESMILEYS, 0, (LPARAM)&sm); - } - - // trim the message log to the number of most recent events - // this uses hidden marks in the rich text to find the events which should be deleted - if (si->bTrimmed) { - wchar_t szPattern[50]; - mir_snwprintf(szPattern, L"~-+%d+-~", si->pLogEnd); - - FINDTEXTEX fi; - fi.lpstrText = szPattern; - fi.chrg.cpMin = 0; - fi.chrg.cpMax = -1; - if (SendMessage(hwndRich, EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi) != 0) { - CHARRANGE rng; - rng.cpMin = 0; - rng.cpMax = 20; - SendMessage(hwndRich, EM_SETSEL, 0, fi.chrgText.cpMax + 1); - SendMessage(hwndRich, EM_REPLACESEL, TRUE, (LPARAM)L""); - } - si->bTrimmed = FALSE; - } - - // scroll log to bottom if the log was previously scrolled to bottom, else restore old position - if ((bRedraw || (UINT)scroll.nPos >= (UINT)scroll.nMax - scroll.nPage - 5 || scroll.nMax - scroll.nMin - scroll.nPage < 50)) - SendMessage(GetParent(hwndRich), GC_SCROLLTOBOTTOM, 0, 0); - else - SendMessage(hwndRich, EM_SETSCROLLPOS, 0, (LPARAM)&point); - - // do we need to restore the selection - if (oldsel.cpMax != oldsel.cpMin) { - SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM)&oldsel); - SendMessage(hwndRich, WM_SETREDRAW, TRUE, 0); - InvalidateRect(hwndRich, NULL, TRUE); - } - - // need to invalidate the window - if (bFlag) { - sel.cpMin = sel.cpMax = GetRichTextLength(hwndRich); - SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM)&sel); - SendMessage(hwndRich, WM_SETREDRAW, TRUE, 0); - InvalidateRect(hwndRich, NULL, TRUE); - } -} diff --git a/plugins/TabSRMM/src/chat/main.cpp b/plugins/TabSRMM/src/chat/main.cpp deleted file mode 100644 index 8bc209800c..0000000000 --- a/plugins/TabSRMM/src/chat/main.cpp +++ /dev/null @@ -1,262 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////////////// -// Miranda NG: the free IM client for Microsoft* Windows* -// -// Copyright (ñ) 2012-17 Miranda NG project, -// Copyright (c) 2000-09 Miranda ICQ/IM project, -// all portions of this codebase are copyrighted to the people -// listed in contributors.txt. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// you should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -// part of tabSRMM messaging plugin for Miranda. -// -// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors -// -// chat module exports and functions to load/unload the plugin. - -#include "../stdafx.h" - -HANDLE g_hWindowList; -HMENU g_hMenu = NULL; - -CHAT_MANAGER *pci; -TMUCSettings g_Settings; - -static void OnCreateSession(SESSION_INFO *si, MODULEINFO *mi) -{ - si->bFilterEnabled = db_get_b(si->hContact, "Chat", "FilterEnabled", M.GetByte("Chat", "FilterEnabled", 0)); - - Chat_SetFilters(si); - if (mi) { - mi->idleTimeStamp = time(0); - pci->SM_BroadcastMessage(mi->pszModule, GC_UPDATESTATUSBAR, 0, 1, TRUE); - } -} - -static void OnReplaceSession(SESSION_INFO *si) -{ - if (si->hContact) - Chat_SetFilters(si); - if (si->hWnd) - RedrawWindow(GetDlgItem(si->hWnd, IDC_LIST), NULL, NULL, RDW_INVALIDATE); -} - -static void OnSetTopic(SESSION_INFO *si) -{ - if (si->hWnd) - si->dat->m_pPanel.Invalidate(true); -} - -static void OnNewUser(SESSION_INFO *si, USERINFO*) -{ - if (si->hWnd) { - SendMessage(si->hWnd, GC_UPDATENICKLIST, 0, 0); - if (si->dat) - si->dat->GetMyNick(); - } -} - -static void OnChangeNick(SESSION_INFO *si) -{ - if (si->hWnd) { - if (si->dat) - si->dat->GetMyNick(); - SendMessage(si->hWnd, GC_UPDATESTATUSBAR, 0, 0); - } -} - -static void OnCreateModule(MODULEINFO *mi) -{ - mi->idleTimeStamp = time(0); -} - -static void OnLoadSettings() -{ - g_Settings.iEventLimitThreshold = db_get_w(NULL, CHAT_MODULE, "LogLimitThreshold", 20); - g_Settings.dwIconFlags = M.GetDword(CHAT_MODULE, "IconFlags", 0x0000); - g_Settings.bOpenInDefault = M.GetBool(CHAT_MODULE, "DefaultContainer", true); - g_Settings.UserListColors[CHAT_STATUS_NORMAL] = M.GetDword(CHATFONT_MODULE, "Font18Col", RGB(0, 0, 0)); - g_Settings.UserListColors[CHAT_STATUS_AWAY] = M.GetDword(CHATFONT_MODULE, "Font19Col", RGB(170, 170, 170)); - g_Settings.UserListColors[CHAT_STATUS_OFFLINE] = M.GetDword(CHATFONT_MODULE, "Font5Col", RGB(160, 90, 90)); - g_Settings.bBBCodeInPopups = M.GetBool(CHAT_MODULE, "BBCodeInPopups", false); - g_Settings.bClassicIndicators = M.GetBool(CHAT_MODULE, "ClassicIndicators", false); - g_Settings.bLogClassicIndicators = M.GetBool(CHAT_MODULE, "LogClassicIndicators", false); - g_Settings.bAlternativeSorting = M.GetBool(CHAT_MODULE, "AlternativeSorting", true); - g_Settings.bAnnoyingHighlight = M.GetBool(CHAT_MODULE, "AnnoyingHighlight", false); - g_Settings.bCreateWindowOnHighlight = M.GetBool(CHAT_MODULE, "CreateWindowOnHighlight", true); - - g_Settings.bLogSymbols = M.GetBool(CHAT_MODULE, "LogSymbols", true); - g_Settings.bClickableNicks = M.GetBool(CHAT_MODULE, "ClickableNicks", true); - g_Settings.bColorizeNicks = M.GetBool(CHAT_MODULE, "ColorizeNicks", true); - g_Settings.bColorizeNicksInLog = M.GetBool(CHAT_MODULE, "ColorizeNicksInLog", true); - g_Settings.bScaleIcons = M.GetBool(CHAT_MODULE, "ScaleIcons", true); - - g_Settings.bDoubleClick4Privat = M.GetBool(CHAT_MODULE, "DoubleClick4Privat", false); - g_Settings.bShowContactStatus = M.GetBool(CHAT_MODULE, "ShowContactStatus", true); - g_Settings.bContactStatusFirst = M.GetBool(CHAT_MODULE, "ContactStatusFirst", false); - - g_Settings.bNewLineAfterNames = M.GetBool(CHAT_MODULE, "NewlineAfterNames", false); - g_Settings.bUseCommaAsColon = M.GetBool(CHAT_MODULE, "UseCommaAsColon", false); - - replaceStrW(g_Settings.pszLogDir, M.getChatLogPath()); - - g_Settings.LogIconSize = (g_Settings.bScaleIcons) ? 12 : 16; - - // nicklist - if (g_Settings.UserListFonts[0]) { - DeleteObject(g_Settings.UserListFonts[CHAT_STATUS_NORMAL]); - DeleteObject(g_Settings.UserListFonts[CHAT_STATUS_AWAY]); - DeleteObject(g_Settings.UserListFonts[CHAT_STATUS_OFFLINE]); - } - - LOGFONT lf; - pci->LoadMsgDlgFont(18, &lf, NULL); - g_Settings.UserListFonts[CHAT_STATUS_NORMAL] = CreateFontIndirect(&lf); - - pci->LoadMsgDlgFont(19, &lf, NULL); - g_Settings.UserListFonts[CHAT_STATUS_AWAY] = CreateFontIndirect(&lf); - - pci->LoadMsgDlgFont(5, &lf, NULL); - g_Settings.UserListFonts[CHAT_STATUS_OFFLINE] = CreateFontIndirect(&lf); - - int ih = GetTextPixelSize(L"AQGglo", g_Settings.UserListFonts[CHAT_STATUS_NORMAL], false); - int ih2 = GetTextPixelSize(L"AQGglo", g_Settings.UserListFonts[CHAT_STATUS_AWAY], false); - g_Settings.iNickListFontHeight = max(M.GetByte(CHAT_MODULE, "NicklistRowDist", 12), (ih > ih2 ? ih : ih2)); - - for (int i = 0; i < 5; i++) { - char szBuf[40]; - mir_snprintf(szBuf, "NickColor%d", i); - g_Settings.nickColors[i] = M.GetDword(CHAT_MODULE, szBuf, g_Settings.UserListColors[0]); - } - g_Settings.nickColors[5] = M.GetDword(CHAT_MODULE, "NickColor5", GetSysColor(COLOR_HIGHLIGHT)); - g_Settings.nickColors[6] = M.GetDword(CHAT_MODULE, "NickColor6", GetSysColor(COLOR_HIGHLIGHTTEXT)); - - if (g_Settings.SelectionBGBrush) - DeleteObject(g_Settings.SelectionBGBrush); - g_Settings.SelectionBGBrush = CreateSolidBrush(g_Settings.nickColors[5]); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -void Chat_ModulesLoaded() -{ - g_Settings.hIconOverlay = LoadIconEx("overlay"); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// load the group chat module - -CHAT_MANAGER saveCI; - -static int CopyChatSetting(const char *szSetting, LPARAM param) -{ - LIST *szSettings = (LIST*)param; - szSettings->insert(mir_strdup(szSetting)); - return 0; -} - -static void CheckUpdate() -{ - // already converted? - int compat = db_get_b(NULL, "Compatibility", "TabChatFonts", 0); - if (compat >= 3) - return; - - if (compat == 0) { - LIST szSettings(120); - db_enum_settings(NULL, CopyChatSetting, CHAT_OLDFONTMODULE, &szSettings); - - DBVARIANT dbv; - for (int i = szSettings.getCount() - 1; i >= 0; i--) { - char *p = szSettings[i]; - db_get(NULL, CHAT_OLDFONTMODULE, p, &dbv); - db_set(NULL, CHATFONT_MODULE, p, &dbv); - db_free(&dbv); - mir_free(p); - } - - db_delete_module(NULL, CHAT_OLDFONTMODULE); - compat++; - } - - if (compat == 1) { - DWORD oldBackColor = db_get_dw(0, FONTMODULE, "BkgColourMUC", SRMSGDEFSET_BKGCOLOUR); - db_set_dw(NULL, CHAT_MODULE, "ColorLogBG", oldBackColor); - db_unset(0, FONTMODULE, "BkgColourMUC"); - compat++; - } - - if (compat == 2) { - COLORREF color0 = M.GetDword(CHAT_MODULE, "NickColor2", 0); - COLORREF color2 = M.GetDword(CHAT_MODULE, "NickColor0", 0); - db_set_dw(NULL, CHAT_MODULE, "NickColor0", color0); - db_set_dw(NULL, CHAT_MODULE, "NickColor2", color2); - compat++; - } - - db_set_b(NULL, "Compatibility", "TabChatFonts", 3); -} - -// load the module -int Chat_Load() -{ - CheckUpdate(); - - CHAT_MANAGER_INITDATA data = { &g_Settings, sizeof(MODULEINFO), sizeof(SESSION_INFO), LPGENW("Message Sessions") L"/" LPGENW("Group chats"), FONTMODE_ALTER }; - pci = Chat_GetInterface(&data); - saveCI = *pci; - pci->OnCreateModule = OnCreateModule; - pci->OnNewUser = OnNewUser; - - pci->OnSetTopic = OnSetTopic; - - pci->OnCreateSession = OnCreateSession; - pci->OnReplaceSession = OnReplaceSession; - - pci->OnChangeNick = OnChangeNick; - pci->ShowRoom = ShowRoom; - pci->OnLoadSettings = OnLoadSettings; - - // this operation is unsafe, that's why we restore the old pci state on exit - pci->DoSoundsFlashPopupTrayStuff = DoSoundsFlashPopupTrayStuff; - pci->IsHighlighted = IsHighlighted; - pci->LogToFile = LogToFile; - pci->DoPopup = DoPopup; - pci->ShowPopup = ShowPopup; - pci->Log_CreateRtfHeader = Log_CreateRtfHeader; - pci->UM_CompareItem = UM_CompareItem; - pci->ReloadSettings(); - - g_hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU)); - - g_Settings.Highlight = new CMUCHighlight(); - return 0; -} - -// unload the module. final cleanup -int Chat_Unload(void) -{ - if (g_Settings.SelectionBGBrush) - DeleteObject(g_Settings.SelectionBGBrush); - - for (int i = 0; i < _countof(g_Settings.UserListFonts); i++) - if (g_Settings.UserListFonts[i]) - DeleteObject(g_Settings.UserListFonts[i]); - - delete g_Settings.Highlight; - - DestroyMenu(g_hMenu); - return 0; -} diff --git a/plugins/TabSRMM/src/chat/manager.cpp b/plugins/TabSRMM/src/chat/manager.cpp deleted file mode 100644 index 735d0a2e0f..0000000000 --- a/plugins/TabSRMM/src/chat/manager.cpp +++ /dev/null @@ -1,123 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////////////// -// Miranda NG: the free IM client for Microsoft* Windows* -// -// Copyright (ñ) 2012-17 Miranda NG project, -// Copyright (c) 2000-09 Miranda ICQ/IM project, -// all portions of this codebase are copyrighted to the people -// listed in contributors.txt. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// you should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -// part of tabSRMM messaging plugin for Miranda. -// -// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors - -#include "../stdafx.h" - -static int sttCompareNicknames(const wchar_t *s1, const wchar_t *s2) -{ - if (s2 == NULL) - return 1; - - // skip rubbish - while (*s1 && !iswalpha(*s1)) ++s1; - while (*s2 && !iswalpha(*s2)) ++s2; - - // are there ~0veRy^kEwL_n1kz? - if (!*s1 && !*s2) return 0; - if (!*s1 && *s2) return +1; - if (*s1 && !*s2) return -1; - - // compare tails - return mir_wstrcmpi(s1, s2); -} - -int UM_CompareItem(USERINFO *u1, const wchar_t* pszNick, WORD wStatus) -{ - WORD dw1 = u1->Status; - WORD dw2 = wStatus; - - for (int i = 0; i < 8; i++) { - if ((dw1 & 1) && !(dw2 & 1)) - return -1; - if ((dw2 & 1) && !(dw1 & 1)) - return 1; - if ((dw1 & 1) && (dw2 & 1)) { - if (g_Settings.bAlternativeSorting) - return sttCompareNicknames(u1->pszNick, pszNick); - else - return mir_wstrcmp(u1->pszNick, pszNick); - } - dw1 = dw1 >> 1; - dw2 = dw2 >> 1; - } - - if (g_Settings.bAlternativeSorting) - return sttCompareNicknames(u1->pszNick, pszNick); - return mir_wstrcmp(u1->pszNick, pszNick); -} - -//--------------------------------------------------- -// Session Manager functions -// -// Keeps track of all sessions and its windows -//--------------------------------------------------- - -BOOL SM_ReconfigureFilters() -{ - for (SESSION_INFO *si = pci->wndList; si; si = si->next) - Chat_SetFilters(si); - - return TRUE; -} - -SESSION_INFO* SM_FindSessionByHWND(HWND hWnd) -{ - for (SESSION_INFO *si = pci->wndList; si; si = si->next) - if (si->hWnd == hWnd) - return si; - - return NULL; -} - -SESSION_INFO* SM_FindSessionByHCONTACT(MCONTACT h) -{ - for (SESSION_INFO *si = pci->wndList; si; si = si->next) - if (si->hContact == h) - return si; - - return NULL; -} - -SESSION_INFO* SM_FindSessionAutoComplete(const char* pszModule, SESSION_INFO* currSession, SESSION_INFO* prevSession, const wchar_t* pszOriginal, const wchar_t* pszCurrent) -{ - if (prevSession == NULL && my_strstri(currSession->ptszName, pszOriginal) == currSession->ptszName) - return currSession; - - wchar_t *pszName = NULL; - if (currSession == prevSession) - pszCurrent = pszOriginal; - - SESSION_INFO *pResult = NULL; - for (SESSION_INFO *si = pci->wndList; si; si = si->next) - if (si != currSession && !mir_strcmpi(pszModule, si->pszModule)) - if (my_strstri(si->ptszName, pszOriginal) == si->ptszName) - if (prevSession != si && mir_wstrcmpi(si->ptszName, pszCurrent) > 0 && (!pszName || mir_wstrcmpi(si->ptszName, pszName) < 0)) { - pResult = si; - pszName = si->ptszName; - } - - return pResult; -} diff --git a/plugins/TabSRMM/src/chat/muchighlight.cpp b/plugins/TabSRMM/src/chat/muchighlight.cpp deleted file mode 100644 index 1992ca9777..0000000000 --- a/plugins/TabSRMM/src/chat/muchighlight.cpp +++ /dev/null @@ -1,336 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////////////// -// Miranda NG: the free IM client for Microsoft* Windows* -// -// Copyright (ñ) 2012-17 Miranda NG project, -// Copyright (c) 2000-09 Miranda ICQ/IM project, -// all portions of this codebase are copyrighted to the people -// listed in contributors.txt. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// you should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -// part of tabSRMM messaging plugin for Miranda. -// -// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors -// -// highlighter class for multi user chats - -#include "../stdafx.h" - -void CMUCHighlight::cleanup() -{ - mir_free(m_NickPatternString); - mir_free(m_TextPatternString); - m_TextPatternString = m_NickPatternString = 0; - - mir_free(m_NickPatterns); - mir_free(m_TextPatterns); - m_iNickPatterns = m_iTextPatterns = 0; - m_NickPatterns = m_TextPatterns = 0; -} - -void CMUCHighlight::init() -{ - DBVARIANT dbv = { 0 }; - - if (m_fInitialized) - cleanup(); // clean up first, if we were already initialized - - m_fInitialized = true; - - if (0 == db_get_ws(0, CHAT_MODULE, "HighlightWords", &dbv)) { - m_TextPatternString = dbv.ptszVal; - _wsetlocale(LC_ALL, L""); - wcslwr(m_TextPatternString); - } - - if (0 == db_get_ws(0, CHAT_MODULE, "HighlightNames", &dbv)) - m_NickPatternString = dbv.ptszVal; - - m_dwFlags = M.GetByte(CHAT_MODULE, "HighlightEnabled", MATCH_TEXT); - m_fHighlightMe = (M.GetByte(CHAT_MODULE, "HighlightMe", 1) ? true : false); - - tokenize(m_TextPatternString, m_TextPatterns, m_iTextPatterns); - tokenize(m_NickPatternString, m_NickPatterns, m_iNickPatterns); -} - -void CMUCHighlight::tokenize(wchar_t *tszString, wchar_t**& patterns, UINT& nr) -{ - if (tszString == 0) - return; - - wchar_t *p = tszString; - - if (*p == 0) - return; - - nr = 0; - - if (*p != ' ') - nr++; - - while (*p) { - if (*p == ' ') { - p++; - while (*p && iswspace(*p)) - p++; - if (*p) - nr++; - } - p++; - } - patterns = (wchar_t **)mir_alloc(nr * sizeof(wchar_t*)); - - p = tszString; - nr = 0; - - if (*p != ' ') - patterns[nr++] = p; - - while (*p) { - if (*p == ' ') { - *p++ = 0; - while (*p && iswspace(*p)) - p++; - if (*p) - patterns[nr++] = p; - } - p++; - } -} - -bool CMUCHighlight::match(const GCEVENT *pgce, const SESSION_INFO *psi, DWORD dwFlags) -{ - int result = 0, nResult = 0; - - if (pgce == 0 || m_Valid == false) - return false; - - if ((m_dwFlags & MATCH_TEXT) && (dwFlags & MATCH_TEXT) && (m_fHighlightMe || m_iTextPatterns > 0) && psi != 0) { - wchar_t *p = pci->RemoveFormatting(pgce->ptszText); - p = NEWWSTR_ALLOCA(p); - if (p == NULL) - return false; - CharLower(p); - - wchar_t *tszMe = ((psi && psi->pMe) ? NEWWSTR_ALLOCA(psi->pMe->pszNick) : 0); - if (tszMe) - CharLower(tszMe); - - if (m_fHighlightMe && tszMe) { - result = wcsstr(p, tszMe) ? MATCH_TEXT : 0; - if (0 == m_iTextPatterns) - goto skip_textpatterns; - } - - while (p && !result) { - while (*p && (*p == ' ' || *p == ',' || *p == '.' || *p == ':' || *p == ';' || *p == '?' || *p == '!')) - p++; - - if (*p == 0) - break; - - wchar_t *p1 = p; - while (*p1 && *p1 != ' ' && *p1 != ',' && *p1 != '.' && *p1 != ':' && *p1 != ';' && *p1 != '?' && *p1 != '!') - p1++; - - if (*p1) - *p1 = 0; - else - p1 = 0; - - for (UINT i = 0; i < m_iTextPatterns && !result; i++) - result = wildcmpw(p, m_TextPatterns[i]) ? MATCH_TEXT : 0; - - if (p1) { - *p1 = ' '; - p = p1 + 1; - } - else p = 0; - } - } - -skip_textpatterns: - - // optionally, match the nickname against the list of nicks to highlight - if ((m_dwFlags & MATCH_NICKNAME) && (dwFlags & MATCH_NICKNAME) && pgce->ptszNick && m_iNickPatterns > 0) { - for (UINT i = 0; i < m_iNickPatterns && !nResult; i++) { - if (pgce->ptszNick) - nResult = wildcmpw(pgce->ptszNick, m_NickPatterns[i]) ? MATCH_NICKNAME : 0; - if ((m_dwFlags & MATCH_UIN) && pgce->ptszUserInfo) - nResult = wildcmpw(pgce->ptszUserInfo, m_NickPatterns[i]) ? MATCH_NICKNAME : 0; - } - } - - return result || nResult; -} - -/** - * Dialog procedure to handle global highlight settings - * - * @param Standard Windows dialog procedure parameters - */ -INT_PTR CALLBACK CMUCHighlight::dlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - { - DBVARIANT dbv = { 0 }; - if (!db_get_ws(0, CHAT_MODULE, "HighlightWords", &dbv)) { - ::SetDlgItemText(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN, dbv.ptszVal); - ::db_free(&dbv); - } - - if (!db_get_ws(0, CHAT_MODULE, "HighlightNames", &dbv)) { - ::SetDlgItemText(hwndDlg, IDC_HIGHLIGHTNICKPATTERN, dbv.ptszVal); - ::db_free(&dbv); - } - - DWORD dwFlags = M.GetByte(CHAT_MODULE, "HighlightEnabled", MATCH_TEXT); - - ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTNICKENABLE, dwFlags & MATCH_NICKNAME ? BST_CHECKED : BST_UNCHECKED); - ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTNICKUID, dwFlags & MATCH_UIN ? BST_CHECKED : BST_UNCHECKED); - ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTTEXTENABLE, dwFlags & MATCH_TEXT ? BST_CHECKED : BST_UNCHECKED); - ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTME, M.GetByte(CHAT_MODULE, "HighlightMe", 1) ? BST_CHECKED : BST_UNCHECKED); - - ::SendMessage(hwndDlg, WM_USER + 100, 0, 0); - } - return TRUE; - - case WM_USER + 100: - Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN, - ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTTEXTENABLE) ? TRUE : FALSE); - - Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTNICKPATTERN, - ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKENABLE) ? TRUE : FALSE); - - Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTNICKUID, - ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKENABLE) ? TRUE : FALSE); - - Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTME, - ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTTEXTENABLE) ? TRUE : FALSE); - return FALSE; - - case WM_COMMAND: - if ((LOWORD(wParam) == IDC_HIGHLIGHTNICKPATTERN - || LOWORD(wParam) == IDC_HIGHLIGHTTEXTPATTERN) - && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != ::GetFocus())) - return 0; - - ::SendMessage(hwndDlg, WM_USER + 100, 0, 0); - if (lParam != 0) - ::SendMessage(::GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - - case WM_NOTIFY: - switch (((LPNMHDR)lParam)->idFrom) { - case 0: - switch (((LPNMHDR)lParam)->code) { - case PSN_APPLY: - { - wchar_t* szBuf = 0; - int iLen = ::GetWindowTextLength(::GetDlgItem(hwndDlg, IDC_HIGHLIGHTNICKPATTERN)); - if (iLen) { - szBuf = reinterpret_cast(mir_alloc((iLen + 2) * sizeof(wchar_t))); - ::GetDlgItemText(hwndDlg, IDC_HIGHLIGHTNICKPATTERN, szBuf, iLen + 1); - db_set_ws(0, CHAT_MODULE, "HighlightNames", szBuf); - } - - iLen = ::GetWindowTextLength(::GetDlgItem(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN)); - if (iLen) { - szBuf = reinterpret_cast(mir_realloc(szBuf, sizeof(wchar_t) * (iLen + 2))); - ::GetDlgItemText(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN, szBuf, iLen + 1); - db_set_ws(0, CHAT_MODULE, "HighlightWords", szBuf); - } - else db_set_ws(0, CHAT_MODULE, "HighlightWords", L""); - - mir_free(szBuf); - BYTE dwFlags = (::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKENABLE) ? MATCH_NICKNAME : 0) | - (::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTTEXTENABLE) ? MATCH_TEXT : 0); - - if (dwFlags & MATCH_NICKNAME) - dwFlags |= (::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKUID) ? MATCH_UIN : 0); - - db_set_b(0, CHAT_MODULE, "HighlightEnabled", dwFlags); - db_set_b(0, CHAT_MODULE, "HighlightMe", ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTME) ? 1 : 0); - g_Settings.Highlight->init(); - } - return TRUE; - } - } - break; - } - return FALSE; -} - -/** - * dialog procedure for the small "add user to highlight list" dialog box - * TODO: finish it - */ -INT_PTR CALLBACK CMUCHighlight::dlgProcAdd(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_INITDIALOG: - { - HFONT hFont = (HFONT)::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTTITLE, WM_GETFONT, 0, 0); - - THighLightEdit *the = reinterpret_cast(lParam); - ::SetWindowLongPtr(hwndDlg, GWLP_USERDATA, the->uCmd); - - LOGFONT lf = { 0 }; - ::GetObject(hFont, sizeof(lf), &lf); - lf.lfWeight = FW_BOLD; - lf.lfHeight = (int)(lf.lfHeight * 1.2); - hFont = ::CreateFontIndirect(&lf); - - ::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTTITLE, WM_SETFONT, (WPARAM)hFont, FALSE); - if (the->uCmd == THighLightEdit::CMD_ADD) { - Utils::showDlgControl(hwndDlg, IDC_ADDHIGHLIGHTEDITLIST, SW_HIDE); - ::SetDlgItemText(hwndDlg, IDC_ADDHIGHLIGHTTITLE, TranslateT("Add user to highlight list")); - ::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTNAME, CB_INSERTSTRING, -1, (LPARAM)the->ui->pszNick); - if (mir_wstrcmp(the->ui->pszNick, the->ui->pszUID)) - ::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTNAME, CB_INSERTSTRING, -1, (LPARAM)the->ui->pszUID); - ::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTNAME, CB_SETCURSEL, 0, 0); - } - else { - Utils::showDlgControl(hwndDlg, IDC_ADDHIGHLIGHTNAME, SW_HIDE); - Utils::showDlgControl(hwndDlg, IDC_ADDHIGHLIGHTEXPLAIN, SW_HIDE); - ::SetDlgItemText(hwndDlg, IDC_ADDHIGHLIGHTTITLE, TranslateT("Edit user highlight list")); - } - } - break; - - case WM_CTLCOLOREDIT: - case WM_CTLCOLORSTATIC: - { - HWND hwndChild = (HWND)lParam; - if (hwndChild == ::GetDlgItem(hwndDlg, IDC_ADDHIGHLIGHTTITLE)) - ::SetTextColor((HDC)wParam, RGB(60, 60, 150)); - ::SetBkColor((HDC)wParam, ::GetSysColor(COLOR_WINDOW)); - return (INT_PTR)::GetSysColorBrush(COLOR_WINDOW); - } - - case WM_COMMAND: - if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) - ::DestroyWindow(hwndDlg); - break; - - case WM_DESTROY: - HFONT hFont = (HFONT)::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTTITLE, WM_GETFONT, 0, 0); - ::DeleteObject(hFont); - break; - } - return FALSE; -} diff --git a/plugins/TabSRMM/src/chat/muchighlight.h b/plugins/TabSRMM/src/chat/muchighlight.h deleted file mode 100644 index 9ca56c95d0..0000000000 --- a/plugins/TabSRMM/src/chat/muchighlight.h +++ /dev/null @@ -1,87 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////////////// -// Miranda NG: the free IM client for Microsoft* Windows* -// -// Copyright (ñ) 2012-17 Miranda NG project, -// Copyright (c) 2000-09 Miranda ICQ/IM project, -// all portions of this codebase are copyrighted to the people -// listed in contributors.txt. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// you should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -// part of tabSRMM messaging plugin for Miranda. -// -// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors -// -// highlighter class for multi user chats - -class CMUCHighlight { - -public: - - enum { - MATCH_TEXT = 1, - MATCH_NICKNAME = 2, - MATCH_UIN = 4, - }; - - CMUCHighlight() - { - m_fInitialized = false; - m_TextPatternString = m_NickPatternString = 0; - m_NickPatterns = m_TextPatterns = 0; - m_iNickPatterns = m_iTextPatterns = 0; - m_dwFlags = 0; - m_Valid = true; - init(); - } - - ~CMUCHighlight() - { - cleanup(); - } - - void init(); - void cleanup(); - bool match(const GCEVENT *pgce, const SESSION_INFO *psi, DWORD dwFlags = MATCH_NICKNAME); - - static INT_PTR CALLBACK dlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); // option page dlg proc - static INT_PTR CALLBACK dlgProcAdd(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); // for the "add to" dialog - -private: - void tokenize(wchar_t *tszString, wchar_t**& patterns, UINT& nr); - - DWORD m_dwFlags; - bool m_fInitialized; - wchar_t** m_NickPatterns; - wchar_t** m_TextPatterns; - UINT m_iNickPatterns; - UINT m_iTextPatterns; - wchar_t *m_NickPatternString; - wchar_t *m_TextPatternString; - bool m_Valid; - bool m_fHighlightMe; -}; - -struct THighLightEdit -{ - enum { - CMD_ADD = 1, - CMD_EDIT = 2 - }; - - UINT uCmd; - SESSION_INFO *si; - USERINFO *ui; -}; diff --git a/plugins/TabSRMM/src/chat/options.cpp b/plugins/TabSRMM/src/chat/options.cpp deleted file mode 100644 index d44966e935..0000000000 --- a/plugins/TabSRMM/src/chat/options.cpp +++ /dev/null @@ -1,1006 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////////////// -// Miranda NG: the free IM client for Microsoft* Windows* -// -// Copyright (ñ) 2012-17 Miranda NG project, -// Copyright (c) 2000-09 Miranda ICQ/IM project, -// all portions of this codebase are copyrighted to the people -// listed in contributors.txt. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// you should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -// part of tabSRMM messaging plugin for Miranda. -// -// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors -// -// group chat options and generic font handling - -#include "../stdafx.h" - -#define FONTF_BOLD 1 -#define FONTF_ITALIC 2 - -struct FontOptionsList -{ - wchar_t *szDescr; - COLORREF defColour; - wchar_t *szDefFace; - BYTE defCharset, defStyle; - char defSize; - COLORREF colour; - wchar_t szFace[LF_FACESIZE]; - BYTE charset, style; - char size; -}; - -struct ColorOptionsList -{ - int order; - wchar_t *tszGroup; - wchar_t *tszName; - char *szSetting; - COLORREF def; -}; - -/* -* note: bits 24-31 in default color indicates that color is a system color index -* (GetSysColor(default_color & 0x00ffffff)), not a rgb value. -*/ -static ColorOptionsList _clrs[] = { - { 0, LPGENW("Message Sessions"), LPGENW("Input area background"), "inputbg", SRMSGDEFSET_BKGCOLOUR }, - { 1, LPGENW("Message Sessions"), LPGENW("Log background"), SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR }, - { 0, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), LPGENW("Outgoing background"), "outbg", SRMSGDEFSET_BKGOUTCOLOUR }, - { 1, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), LPGENW("Incoming background"), "inbg", SRMSGDEFSET_BKGINCOLOUR }, - { 2, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), LPGENW("Status background"), "statbg", SRMSGDEFSET_BKGCOLOUR }, - { 3, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), LPGENW("Incoming background(old)"), "oldinbg", SRMSGDEFSET_BKGINCOLOUR }, - { 4, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), LPGENW("Outgoing background(old)"), "oldoutbg", SRMSGDEFSET_BKGOUTCOLOUR }, - { 5, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), LPGENW("Horizontal Grid Lines"), "hgrid", RGB(224, 224, 224) }, - { 0, LPGENW("Message Sessions") L"/" LPGENW("Info Panel"), LPGENW("Panel background low"), "ipfieldsbg", 0x62caff }, - { 1, LPGENW("Message Sessions") L"/" LPGENW("Info Panel"), LPGENW("Panel background high"), "ipfieldsbgHigh", 0xf0f0f0 }, - { 0, LPGENW("Message Sessions") L"/" LPGENW("Common colors"), LPGENW("Toolbar background high"), "tbBgHigh", 0 }, - { 1, LPGENW("Message Sessions") L"/" LPGENW("Common colors"), LPGENW("Toolbar background low"), "tbBgLow", 0 }, - { 2, LPGENW("Message Sessions") L"/" LPGENW("Common colors"), LPGENW("Window fill color"), "fillColor", 0 }, - { 3, LPGENW("Message Sessions") L"/" LPGENW("Common colors"), LPGENW("Text area borders"), "cRichBorders", 0 }, - { 4, LPGENW("Message Sessions") L"/" LPGENW("Common colors"), LPGENW("Aero glow effect"), "aeroGlow", RGB(40, 40, 255) }, - { 4, LPGENW("Message Sessions") L"/" LPGENW("Common colors"), LPGENW("Generic text color (only when fill color is set)"), "genericTxtClr", 0xff000000 | COLOR_BTNTEXT }, -}; - -static ColorOptionsList _tabclrs[] = { - { 0, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Normal text"), "tab_txt_normal", 0xff000000 | COLOR_BTNTEXT }, - { 1, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Active text"), "tab_txt_active", 0xff000000 | COLOR_BTNTEXT }, - { 2, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Hovered text"), "tab_txt_hottrack", 0xff000000 | COLOR_HOTLIGHT }, - { 3, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Unread text"), "tab_txt_unread", 0xff000000 | COLOR_HOTLIGHT }, - - { 4, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Normal background"), "tab_bg_normal", 0xff000000 | COLOR_3DFACE }, - { 5, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Active background"), "tab_bg_active", 0xff000000 | COLOR_3DFACE }, - { 6, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Hovered background"), "tab_bg_hottrack", 0xff000000 | COLOR_3DFACE }, - { 7, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Unread background"), "tab_bg_unread", 0xff000000 | COLOR_3DFACE } -}; - -extern LOGFONT lfDefault; - -static FontOptionsList IM_fontOptionsList[] = { - { LPGENW(">> Outgoing messages"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW(">> Outgoing misc events"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW("<< Incoming messages"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW("<< Incoming misc events"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW(">> Outgoing name"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, - { LPGENW(">> Outgoing timestamp"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, - { LPGENW("<< Incoming name"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, - { LPGENW("<< Incoming timestamp"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, - { LPGENW(">> Outgoing messages (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW(">> Outgoing misc events (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW("<< Incoming messages (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW("<< Incoming misc events (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW(">> Outgoing name (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, - { LPGENW(">> Outgoing timestamp (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, - { LPGENW("<< Incoming name (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, - { LPGENW("<< Incoming timestamp (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, - { LPGENW("* Message Input Area"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW("* Status changes"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW("* Dividers"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW("* Error and warning messages"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW("* Symbols (incoming)"), RGB(50, 50, 50), L"Webdings", SYMBOL_CHARSET, 0, -12 }, - { LPGENW("* Symbols (outgoing)"), RGB(50, 50, 50), L"Webdings", SYMBOL_CHARSET, 0, -12 }, -}; - -static FontOptionsList IP_fontOptionsList[] = { - { LPGENW("Nickname"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW("UIN"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW("Status"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW("Protocol"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW("Contacts local time"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, - { LPGENW("Window caption (skinned mode)"), RGB(255, 255, 255), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, -}; - -static FontOptionsList *fontOptionsList = IM_fontOptionsList; -static int fontCount = MSGDLGFONTCOUNT; - -struct branch_t -{ - wchar_t* szDescr; - char* szDBName; - int iMode; - BYTE bDefault; - HTREEITEM hItem; -}; -static branch_t branch1[] = { - { LPGENW("Open new chat rooms in the default container"), "DefaultContainer", 0, 1, NULL }, - { LPGENW("Flash window when someone speaks"), "FlashWindow", 0, 0, NULL }, - { LPGENW("Flash window when a word is highlighted"), "FlashWindowHighlight", 0, 1, NULL }, - { LPGENW("Create tabs or windows for highlight events"), "CreateWindowOnHighlight", 0, 0, NULL }, - { LPGENW("Activate chat window on highlight"), "AnnoyingHighlight", 0, 0, NULL }, - { LPGENW("Show list of users in the chat room"), "ShowNicklist", 0, 1, NULL }, - { LPGENW("Colorize nicknames in member list"), "ColorizeNicks", 0, 1, NULL }, - { LPGENW("Show button menus when right clicking the buttons"), "RightClickFilter", 0, 1, NULL }, - { LPGENW("Show topic as status message on the contact list"), "TopicOnClist", 0, 1, NULL }, - { LPGENW("Do not pop up the window when joining a chat room"), "PopupOnJoin", 0, 0, NULL }, - { LPGENW("Hide or show the window by double click in the contact list"), "ToggleVisibility", 0, 0, NULL }, - { LPGENW("Sync splitter position with standard IM sessions"), "SyncSplitter", 0, 0, NULL }, - { LPGENW("Show contact's status modes if supported by the protocol"), "ShowContactStatus", 0, 1, NULL }, - { LPGENW("Display contact's status icon before user role icon"), "ContactStatusFirst", 0, 0, NULL }, - { LPGENW("Use IRC style status indicators in the nick list"), "ClassicIndicators", 0, 0, NULL }, - { LPGENW("Use alternative sorting method in member list"), "AlternativeSorting", 0, 1, NULL } -}; - -static branch_t branch2[] = { - { LPGENW("Prefix all events with a timestamp"), "ShowTimeStamp", 0, 1, NULL }, - { LPGENW("Timestamp only when event time differs"), "ShowTimeStampIfChanged", 0, 0, NULL }, - { LPGENW("Timestamp has same color as the event"), "TimeStampEventColour", 0, 0, NULL }, - { LPGENW("Indent the second line of a message"), "LogIndentEnabled", 0, 1, NULL }, - { LPGENW("Limit user names in the message log to 20 characters"), "LogLimitNames", 0, 1, NULL }, - { LPGENW("Add a colon (:) to auto-completed user names"), "AddColonToAutoComplete", 0, 1, NULL }, - { LPGENW("Add a comma instead of a colon to auto-completed user names"), "UseCommaAsColon", 0, 0, NULL }, - { LPGENW("Start private conversation on double click in nick list (insert nick if unchecked)"), "DoubleClick4Privat", 0, 0, NULL }, - { LPGENW("Strip colors from messages in the log"), "StripFormatting", 0, 0, NULL }, - { LPGENW("Enable the 'event filter' for new rooms"), "FilterEnabled", 0, 0, NULL }, - { LPGENW("Use IRC style status indicators in the log"), "LogClassicIndicators", 0, 0, NULL }, - { LPGENW("Allow clickable user names in the message log"), "ClickableNicks", 0, 1, NULL }, - { LPGENW("Add new line after names"), "NewlineAfterNames", 0, 0, NULL }, - { LPGENW("Colorize user names in message log"), "ColorizeNicksInLog", 0, 1, NULL }, - { LPGENW("Scale down icons to 10x10 pixels in the chat log"), "ScaleIcons", 0, 1, NULL } -}; - -static HWND hPathTip = 0; - -void LoadMsgDlgFont(int section, int i, LOGFONT *lf, COLORREF* colour, char *szMod) -{ - char str[32]; - int style; - int j = (i >= 100 ? i - 100 : i); - - FontOptionsList *fol = fontOptionsList; - switch (section) { - case FONTSECTION_IM: fol = IM_fontOptionsList; break; - case FONTSECTION_IP: fol = IP_fontOptionsList; break; - } - - if (colour) { - mir_snprintf(str, "Font%dCol", i); - *colour = M.GetDword(szMod, str, fol[j].defColour); - } - - if (lf) { - mir_snprintf(str, "Font%dSize", i); - lf->lfHeight = (char)M.GetByte(szMod, str, fol[j].defSize); - lf->lfWidth = 0; - lf->lfEscapement = 0; - lf->lfOrientation = 0; - mir_snprintf(str, "Font%dSty", i); - style = M.GetByte(szMod, str, fol[j].defStyle); - if (i == MSGFONTID_MESSAGEAREA && section == FONTSECTION_IM && M.GetByte("inputFontFix", 1) == 1) { - lf->lfWeight = FW_NORMAL; - lf->lfItalic = 0; - lf->lfUnderline = 0; - lf->lfStrikeOut = 0; - } - else { - lf->lfWeight = style & FONTF_BOLD ? FW_BOLD : FW_NORMAL; - lf->lfItalic = style & FONTF_ITALIC ? 1 : 0; - lf->lfUnderline = style & FONTF_UNDERLINE ? 1 : 0; - lf->lfStrikeOut = style & FONTF_STRIKEOUT ? 1 : 0; - } - mir_snprintf(str, "Font%dSet", i); - lf->lfCharSet = M.GetByte(szMod, str, fol[j].defCharset); - lf->lfOutPrecision = OUT_DEFAULT_PRECIS; - lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; - lf->lfQuality = DEFAULT_QUALITY; - lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; - mir_snprintf(str, "Font%d", i); - if ((i == 17 && !mir_strcmp(szMod, CHATFONT_MODULE)) || ((i == 20 || i == 21) && !mir_strcmp(szMod, FONTMODULE))) { - lf->lfCharSet = SYMBOL_CHARSET; - wcsncpy_s(lf->lfFaceName, L"Webdings", _TRUNCATE); - } - else { - ptrW tszDefFace(db_get_wsa(NULL, szMod, str)); - if (tszDefFace == NULL) - wcsncpy_s(lf->lfFaceName, fol[j].szDefFace, _TRUNCATE); - else - wcsncpy_s(lf->lfFaceName, tszDefFace, _TRUNCATE); - } - } -} - -static HTREEITEM InsertBranch(HWND hwndTree, wchar_t* pszDescr, BOOL bExpanded) -{ - TVINSERTSTRUCT tvis; - tvis.hParent = NULL; - tvis.hInsertAfter = TVI_LAST; - tvis.item.mask = TVIF_TEXT | TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; - tvis.item.pszText = TranslateW(pszDescr); - tvis.item.stateMask = TVIS_EXPANDED | TVIS_BOLD; - tvis.item.state = (bExpanded ? TVIS_EXPANDED : 0) | TVIS_BOLD; - tvis.item.iImage = tvis.item.iSelectedImage = (bExpanded ? IMG_GRPOPEN : IMG_GRPCLOSED); - return TreeView_InsertItem(hwndTree, &tvis); -} - -static void FillBranch(HWND hwndTree, HTREEITEM hParent, branch_t *branch, int nValues, DWORD defaultval) -{ - if (hParent == 0) - return; - - TVINSERTSTRUCT tvis = { 0 }; - - for (int i = 0; i < nValues; i++) { - tvis.hParent = hParent; - tvis.hInsertAfter = TVI_LAST; - tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; - tvis.item.pszText = TranslateW(branch[i].szDescr); - if (branch[i].iMode) - tvis.item.iImage = tvis.item.iSelectedImage = ((((M.GetDword(CHAT_MODULE, branch[i].szDBName, defaultval) & branch[i].iMode) & branch[i].iMode) != 0) ? IMG_CHECK : IMG_NOCHECK); - else - tvis.item.iImage = tvis.item.iSelectedImage = ((M.GetByte(CHAT_MODULE, branch[i].szDBName, branch[i].bDefault) != 0) ? IMG_CHECK : IMG_NOCHECK); - branch[i].hItem = TreeView_InsertItem(hwndTree, &tvis); - } -} - -static void SaveBranch(HWND hwndTree, branch_t *branch, int nValues) -{ - TVITEM tvi = { 0 }; - BYTE bChecked; - DWORD iState = 0; - - for (int i = 0; i < nValues; i++) { - tvi.mask = TVIF_HANDLE | TVIF_IMAGE; - tvi.hItem = branch[i].hItem; - TreeView_GetItem(hwndTree, &tvi); - bChecked = ((tvi.iImage == IMG_CHECK) ? 1 : 0); - if (branch[i].iMode) { - if (bChecked) - iState |= branch[i].iMode; - if (iState & GC_EVENT_ADDSTATUS) - iState |= GC_EVENT_REMOVESTATUS; - db_set_dw(0, CHAT_MODULE, branch[i].szDBName, iState); - } - else db_set_b(0, CHAT_MODULE, branch[i].szDBName, bChecked); - } -} - -static INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM) -{ - char szDir[MAX_PATH]; - switch (uMsg) { - case BFFM_INITIALIZED: - SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)M.getUserDir()); - break; - - case BFFM_SELCHANGED: - if (SHGetPathFromIDListA((LPITEMIDLIST)lp, szDir)) - SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)szDir); - break; - } - return 0; -} - -static IconItem _icons[] = -{ - { LPGEN("Window Icon"), "chat_window", IDI_CHANMGR }, - { LPGEN("Icon overlay"), "chat_overlay", IDI_OVERLAY }, - - { LPGEN("Status 1 (10x10)"), "chat_status0", IDI_STATUS0 }, - { LPGEN("Status 2 (10x10)"), "chat_status1", IDI_STATUS1 }, - { LPGEN("Status 3 (10x10)"), "chat_status2", IDI_STATUS2 }, - { LPGEN("Status 4 (10x10)"), "chat_status3", IDI_STATUS3 }, - { LPGEN("Status 5 (10x10)"), "chat_status4", IDI_STATUS4 }, - { LPGEN("Status 6 (10x10)"), "chat_status5", IDI_STATUS5 } -}; - -static IconItem _logicons[] = -{ - { LPGEN("Message in (10x10)"), "chat_log_message_in", IDI_MESSAGE }, - { LPGEN("Message out (10x10)"), "chat_log_message_out", IDI_MESSAGEOUT }, - { LPGEN("Action (10x10)"), "chat_log_action", IDI_ACTION }, - { LPGEN("Add Status (10x10)"), "chat_log_addstatus", IDI_ADDSTATUS }, - { LPGEN("Remove Status (10x10)"), "chat_log_removestatus", IDI_REMSTATUS }, - { LPGEN("Join (10x10)"), "chat_log_join", IDI_JOIN }, - { LPGEN("Leave (10x10)"), "chat_log_part", IDI_PART }, - { LPGEN("Quit (10x10)"), "chat_log_quit", IDI_QUIT }, - { LPGEN("Kick (10x10)"), "chat_log_kick", IDI_KICK }, - { LPGEN("Notice (10x10)"), "chat_log_notice", IDI_NOTICE }, - { LPGEN("Nickchange (10x10)"), "chat_log_nick", IDI_NICK }, - { LPGEN("Topic (10x10)"), "chat_log_topic", IDI_TOPIC }, - { LPGEN("Highlight (10x10)"), "chat_log_highlight", IDI_HIGHLIGHT }, - { LPGEN("Information (10x10)"), "chat_log_info", IDI_INFO } -}; - -// add icons to the skinning module -void Chat_AddIcons(void) -{ - Icon_Register(g_hIconDLL, LPGEN("Message Sessions") "/" LPGEN("Group chat windows"), _icons, _countof(_icons)); - Icon_Register(g_hIconDLL, LPGEN("Message Sessions") "/" LPGEN("Group chat log"), _logicons, _countof(_logicons)); - pci->MM_IconsChanged(); -} - -/* - * get icon by name from the core icon library service - */ -HICON LoadIconEx(char *pszIcoLibName) -{ - char szTemp[256]; - mir_snprintf(szTemp, "chat_%s", pszIcoLibName); - return IcoLib_GetIcon(szTemp); -} - -static void InitSetting(wchar_t* &ppPointer, const char *pszSetting, const wchar_t *pszDefault) -{ - ptrW val(db_get_wsa(NULL, CHAT_MODULE, pszSetting)); - replaceStrW(ppPointer, (val != NULL) ? val : pszDefault); -} - -#define OPT_FIXHEADINGS (WM_USER+1) - -static UINT _o1controls[] = { IDC_CHECKBOXES, IDC_GROUP, IDC_STATIC_ADD }; - -HWND CreateToolTip(HWND hwndParent, LPTSTR ptszText, LPTSTR ptszTitle) -{ - HWND hwndTT = CreateWindowEx(WS_EX_TOPMOST, - TOOLTIPS_CLASS, NULL, - WS_POPUP | TTS_NOPREFIX, - CW_USEDEFAULT, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, - hwndParent, NULL, g_hInst, NULL); - - SetWindowPos(hwndTT, HWND_TOPMOST, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); - - TOOLINFO ti = { 0 }; - ti.cbSize = sizeof(TOOLINFO); - ti.uFlags = TTF_SUBCLASS | TTF_CENTERTIP; - ti.hwnd = hwndParent; - ti.hinst = g_hInst; - ti.lpszText = ptszText; - GetClientRect(hwndParent, &ti.rect); - ti.rect.left = -65; - - SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM)&ti); - SendMessage(hwndTT, TTM_SETTITLE, 1, (LPARAM)ptszTitle); - SendMessage(hwndTT, TTM_SETMAXTIPWIDTH, 0, (LPARAM)640); - return hwndTT; -} - -INT_PTR CALLBACK DlgProcOptions1(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - static HTREEITEM hListHeading1 = 0; - static HTREEITEM hListHeading2 = 0; - - switch (uMsg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - { - SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHECKBOXES), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHECKBOXES), GWL_STYLE) | (TVS_NOHSCROLL)); - /* Replace image list, destroy old. */ - ImageList_Destroy(TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_CHECKBOXES), CreateStateImageList(), TVSIL_NORMAL)); - - hListHeading1 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), TranslateT("Appearance and functionality of chat room windows"), TRUE); - hListHeading2 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), TranslateT("Appearance of the message log"), TRUE); - - FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading1, branch1, _countof(branch1), 0x0000); - FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2, branch2, _countof(branch2), 0x0000); - - wchar_t* pszGroup = NULL; - InitSetting(pszGroup, "AddToGroup", L"Chat rooms"); - SetDlgItemText(hwndDlg, IDC_GROUP, pszGroup); - mir_free(pszGroup); - } - break; - - case WM_COMMAND: - if ((LOWORD(wParam) == IDC_GROUP) && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) - return 0; - - if (lParam != 0) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - - case WM_NOTIFY: - switch (((LPNMHDR)lParam)->idFrom) { - case IDC_CHECKBOXES: - return TreeViewHandleClick(hwndDlg, ((LPNMHDR)lParam)->hwndFrom, wParam, lParam); - break; - - case 0: - switch (((LPNMHDR)lParam)->code) { - case PSN_APPLY: - int iLen; - wchar_t *pszText = NULL; - BYTE b; - - iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_GROUP)); - if (iLen > 0) { - pszText = (wchar_t*)mir_realloc(pszText, (iLen + 2) * sizeof(wchar_t)); - GetDlgItemText(hwndDlg, IDC_GROUP, pszText, iLen + 1); - db_set_ws(NULL, CHAT_MODULE, "AddToGroup", pszText); - } - else db_set_ws(NULL, CHAT_MODULE, "AddToGroup", L""); - - mir_free(pszText); - - b = M.GetByte(CHAT_MODULE, "Tabs", 1); - SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch1, _countof(branch1)); - SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch2, _countof(branch2)); - - pci->ReloadSettings(); - pci->MM_IconsChanged(); - pci->MM_FontsChanged(); - pci->SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE); - SM_ReconfigureFilters(); - return TRUE; - } - } - break; - - case WM_DESTROY: - BYTE b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading1, TVIS_EXPANDED) & TVIS_EXPANDED ? 1 : 0; - db_set_b(0, CHAT_MODULE, "Branch1Exp", b); - b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2, TVIS_EXPANDED) & TVIS_EXPANDED ? 1 : 0; - db_set_b(0, CHAT_MODULE, "Branch2Exp", b); - TreeViewDestroy(GetDlgItem(hwndDlg, IDC_CHECKBOXES)); - } - return FALSE; -} - -static wchar_t* chatcolorsnames[] = -{ - LPGENW("Voiced"), - LPGENW("Half operators"), - LPGENW("Channel operators"), - LPGENW("Extended mode 1"), - LPGENW("Extended mode 2"), - LPGENW("Selection background"), - LPGENW("Selected text"), - LPGENW("Incremental search highlight") -}; - -void RegisterFontServiceFonts() -{ - char szTemp[100]; - LOGFONT lf; - FontIDW fid = { 0 }; - ColourIDW cid = { 0 }; - - fid.cbSize = sizeof(FontIDW); - cid.cbSize = sizeof(ColourIDW); - - strncpy(fid.dbSettingsGroup, FONTMODULE, _countof(fid.dbSettingsGroup)); - - for (int i = 0; i < _countof(IM_fontOptionsList); i++) { - fid.flags = FIDF_DEFAULTVALID | FIDF_ALLOWEFFECTS; - LoadMsgDlgFont(FONTSECTION_IM, i, &lf, &fontOptionsList[i].colour, FONTMODULE); - mir_snprintf(szTemp, "Font%d", i); - strncpy(fid.prefix, szTemp, _countof(fid.prefix)); - fid.order = i; - wcsncpy(fid.name, fontOptionsList[i].szDescr, _countof(fid.name)); - fid.deffontsettings.colour = fontOptionsList[i].colour; - fid.deffontsettings.size = (char)lf.lfHeight; - fid.deffontsettings.style = (lf.lfWeight >= FW_BOLD ? FONTF_BOLD : 0) | (lf.lfItalic ? FONTF_ITALIC : 0); - fid.deffontsettings.charset = lf.lfCharSet; - fid.flags = fid.flags & ~FIDF_CLASSMASK | (fid.deffontsettings.style&FONTF_BOLD ? FIDF_CLASSHEADER : FIDF_CLASSGENERAL); - wcsncpy(fid.deffontsettings.szFace, lf.lfFaceName, LF_FACESIZE); - wcsncpy(fid.backgroundGroup, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), _countof(fid.backgroundGroup)); - wcsncpy(fid.group, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), _countof(fid.group)); - switch (i) { - case MSGFONTID_MYMSG: - case 1: - case MSGFONTID_MYNAME: - case MSGFONTID_MYTIME: - case 21: - wcsncpy(fid.backgroundName, LPGENW("Outgoing background"), _countof(fid.backgroundName)); - break; - case 8: - case 9: - case 12: - case 13: - wcsncpy(fid.backgroundName, LPGENW("Outgoing background(old)"), _countof(fid.backgroundName)); - break; - case 10: - case 11: - case 14: - case 15: - wcsncpy(fid.backgroundName, LPGENW("Incoming background(old)"), _countof(fid.backgroundName)); - break; - case MSGFONTID_MESSAGEAREA: - wcsncpy(fid.group, LPGENW("Message Sessions"), _countof(fid.group)); - wcsncpy(fid.backgroundGroup, LPGENW("Message Sessions"), _countof(fid.backgroundGroup)); - wcsncpy(fid.backgroundName, LPGENW("Input area background"), _countof(fid.backgroundName)); - fid.flags |= FIDF_DISABLESTYLES; - fid.flags &= ~FIDF_ALLOWEFFECTS; - break; - case 17: - wcsncpy(fid.backgroundName, LPGENW("Status background"), _countof(fid.backgroundName)); - break; - case 18: - wcsncpy(fid.backgroundGroup, LPGENW("Message Sessions"), _countof(fid.backgroundGroup)); - wcsncpy(fid.backgroundName, LPGENW("Log background"), _countof(fid.backgroundName)); - break; - case 19: - wcsncpy(fid.backgroundName, L"", _countof(fid.backgroundName)); - break; - default: - wcsncpy(fid.backgroundName, LPGENW("Incoming background"), _countof(fid.backgroundName)); - break; - } - Font_RegisterW(&fid); - } - - fontOptionsList = IP_fontOptionsList; - fid.flags = FIDF_DEFAULTVALID | FIDF_ALLOWEFFECTS; - wcsncpy(fid.group, LPGENW("Message Sessions") L"/" LPGENW("Info Panel"), _countof(fid.group)); - wcsncpy(fid.backgroundGroup, LPGENW("Message Sessions") L"/" LPGENW("Info Panel"), _countof(fid.backgroundGroup)); - wcsncpy(fid.backgroundName, LPGENW("Fields background"), _countof(fid.backgroundName)); - for (int i = 0; i < IPFONTCOUNT; i++) { - LoadMsgDlgFont(FONTSECTION_IP, i + 100, &lf, &fontOptionsList[i].colour, FONTMODULE); - mir_snprintf(szTemp, "Font%d", i + 100); - strncpy(fid.prefix, szTemp, _countof(fid.prefix)); - fid.order = i + 100; - wcsncpy(fid.name, fontOptionsList[i].szDescr, _countof(fid.name)); - fid.deffontsettings.colour = fontOptionsList[i].colour; - fid.deffontsettings.size = (char)lf.lfHeight; - fid.deffontsettings.style = (lf.lfWeight >= FW_BOLD ? FONTF_BOLD : 0) | (lf.lfItalic ? FONTF_ITALIC : 0); - fid.deffontsettings.charset = lf.lfCharSet; - fid.flags = fid.flags & ~FIDF_CLASSMASK | (fid.deffontsettings.style&FONTF_BOLD ? FIDF_CLASSHEADER : FIDF_CLASSGENERAL); - fid.deffontsettings.charset = lf.lfCharSet; - wcsncpy(fid.deffontsettings.szFace, lf.lfFaceName, LF_FACESIZE); - if (i == IPFONTCOUNT - 1) { - wcsncpy(fid.backgroundGroup, L"", _countof(fid.backgroundGroup)); - wcsncpy(fid.backgroundName, L"", _countof(fid.backgroundName)); - wcsncpy(fid.group, LPGENW("Message Sessions"), _countof(fid.group)); - } - Font_RegisterW(&fid); - } - - wcsncpy(cid.group, LPGENW("Message Sessions") L"/" LPGENW("Group chats"), _countof(cid.group)); - strncpy(cid.dbSettingsGroup, CHAT_MODULE, _countof(cid.dbSettingsGroup)); - for (int i = 0; i <= 7; i++) { - mir_snprintf(szTemp, "NickColor%d", i); - wcsncpy(cid.name, chatcolorsnames[i], _countof(cid.name)); - cid.order = i + 1; - strncpy(cid.setting, szTemp, _countof(cid.setting)); - switch (i) { - case 5: - cid.defcolour = GetSysColor(COLOR_HIGHLIGHT); - break; - case 6: - cid.defcolour = GetSysColor(COLOR_HIGHLIGHTTEXT); - break; - default: - cid.defcolour = RGB(0, 0, 0); - break; - } - Colour_RegisterW(&cid); - } - cid.order++; - wcsncpy_s(cid.name, LPGENW("Nick list background"), _TRUNCATE); - strncpy_s(cid.setting, "ColorNicklistBG", _TRUNCATE); - cid.defcolour = SRMSGDEFSET_BKGCOLOUR; - Colour_RegisterW(&cid); - - cid.order++; - wcsncpy_s(cid.name, LPGENW("Group chat log background"), _TRUNCATE); - strncpy_s(cid.setting, "ColorLogBG", _TRUNCATE); - Colour_RegisterW(&cid); - - // static colors (info panel, tool bar background etc...) - strncpy(fid.dbSettingsGroup, FONTMODULE, _countof(fid.dbSettingsGroup)); - strncpy(cid.dbSettingsGroup, FONTMODULE, _countof(fid.dbSettingsGroup)); - - for (int i = 0; i < _countof(_clrs); i++) { - cid.order = _clrs[i].order; - wcsncpy(cid.group, _clrs[i].tszGroup, _countof(fid.group)); - wcsncpy(cid.name, _clrs[i].tszName, _countof(cid.name)); - strncpy(cid.setting, _clrs[i].szSetting, _countof(cid.setting)); - if (_clrs[i].def & 0xff000000) - cid.defcolour = GetSysColor(_clrs[i].def & 0x000000ff); - else - cid.defcolour = _clrs[i].def; - Colour_RegisterW(&cid); - } - - strncpy(cid.dbSettingsGroup, SRMSGMOD_T, _countof(fid.dbSettingsGroup)); - - // text and background colors for tabs - for (int i = 0; i < _countof(_tabclrs); i++) { - cid.order = _tabclrs[i].order; - wcsncpy(cid.group, _tabclrs[i].tszGroup, _countof(fid.group)); - wcsncpy(cid.name, _tabclrs[i].tszName, _countof(cid.name)); - strncpy(cid.setting, _tabclrs[i].szSetting, _countof(cid.setting)); - if (_tabclrs[i].def & 0xff000000) - cid.defcolour = GetSysColor(_tabclrs[i].def & 0x000000ff); - else - cid.defcolour = _tabclrs[i].def; - - Colour_RegisterW(&cid); - } -} - -int FontServiceFontsChanged(WPARAM, LPARAM) -{ - PluginConfig.reloadSettings(); - CSkin::initAeroEffect(); - CacheMsgLogIcons(); - CacheLogFonts(); - FreeTabConfig(); - ReloadTabConfig(); - Skin->setupAeroSkins(); - M.BroadcastMessage(DM_OPTIONSAPPLIED, 1, 0); - return 0; -} - -static UINT _o2chatcontrols[] = -{ - IDC_CHAT_SPIN2, IDC_LIMIT, IDC_CHAT_SPIN4, IDC_LOGTIMESTAMP, IDC_TIMESTAMP, - IDC_OUTSTAMP, IDC_FONTCHOOSE, IDC_LOGGING, IDC_LOGDIRECTORY, IDC_INSTAMP, IDC_CHAT_SPIN2, IDC_CHAT_SPIN3, IDC_NICKROW2, IDC_LOGLIMIT, - IDC_STATIC110, IDC_STATIC112, 0 -}; - -static UINT _o3chatcontrols[] = { 0 }; - -INT_PTR CALLBACK DlgProcOptions2(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - switch (uMsg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - { - SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN2, UDM_SETRANGE, 0, MAKELONG(5000, 0)); - SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN2, UDM_SETPOS, 0, MAKELONG(db_get_w(NULL, CHAT_MODULE, "LogLimit", 100), 0)); - SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN3, UDM_SETRANGE, 0, MAKELONG(255, 10)); - SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN3, UDM_SETPOS, 0, MAKELONG(M.GetByte(CHAT_MODULE, "NicklistRowDist", 12), 0)); - SetDlgItemText(hwndDlg, IDC_LOGTIMESTAMP, g_Settings.pszTimeStampLog); - SetDlgItemText(hwndDlg, IDC_TIMESTAMP, g_Settings.pszTimeStamp); - SetDlgItemText(hwndDlg, IDC_OUTSTAMP, g_Settings.pszOutgoingNick); - SetDlgItemText(hwndDlg, IDC_INSTAMP, g_Settings.pszIncomingNick); - CheckDlgButton(hwndDlg, IDC_LOGGING, g_Settings.bLoggingEnabled ? BST_CHECKED : BST_UNCHECKED); - SetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, g_Settings.pszLogDir); - Utils::enableDlgControl(hwndDlg, IDC_LOGDIRECTORY, g_Settings.bLoggingEnabled); - Utils::enableDlgControl(hwndDlg, IDC_FONTCHOOSE, g_Settings.bLoggingEnabled); - SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN4, UDM_SETRANGE, 0, MAKELONG(10000, 0)); - SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN4, UDM_SETPOS, 0, MAKELONG(db_get_w(NULL, CHAT_MODULE, "LoggingLimit", 100), 0)); - Utils::enableDlgControl(hwndDlg, IDC_LIMIT, g_Settings.bLoggingEnabled); - - wchar_t tszTooltipText[2048]; - - mir_snwprintf(tszTooltipText, - L"%s - %s\n%s - %s\n%s - %s\n%s - %s\n\n" - L"%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n\n" - L"%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s", - // contact vars - L"%nick%", TranslateT("nick of current contact (if defined)"), - L"%proto%", TranslateT("protocol name of current contact (if defined). Account name is used when protocol supports multiple accounts"), - L"%accountname%", TranslateT("user-defined account name of current contact (if defined)."), - L"%userid%", TranslateT("user ID of current contact (if defined). It is like UIN for ICQ, JID for Jabber, etc."), - // global vars - L"%miranda_path%", TranslateT("path to Miranda root folder"), - L"%miranda_profilesdir%", TranslateT("path to folder containing Miranda profiles"), - L"%miranda_profilename%", TranslateT("name of current Miranda profile (filename, without extension)"), - L"%miranda_userdata%", TranslateT("will return parsed string %miranda_profilesdir%\\%miranda_profilename%"), - L"%miranda_logpath%", TranslateT("will return parsed string %miranda_userdata%\\Logs"), - L"%appdata%", TranslateT("same as environment variable %APPDATA% for currently logged-on Windows user"), - L"%username%", TranslateT("username for currently logged-on Windows user"), - L"%mydocuments%", TranslateT("\"My Documents\" folder for currently logged-on Windows user"), - L"%desktop%", TranslateT("\"Desktop\" folder for currently logged-on Windows user"), - L"%xxxxxxx%", TranslateT("any environment variable defined in current Windows session (like %systemroot%, %allusersprofile%, etc.)"), - // date/time vars - L"%d%", TranslateT("day of month, 1-31"), - L"%dd%", TranslateT("day of month, 01-31"), - L"%m%", TranslateT("month number, 1-12"), - L"%mm%", TranslateT("month number, 01-12"), - L"%mon%", TranslateT("abbreviated month name"), - L"%month%", TranslateT("full month name"), - L"%yy%", TranslateT("year without century, 01-99"), - L"%yyyy%", TranslateT("year with century, 1901-9999"), - L"%wday%", TranslateT("abbreviated weekday name"), - L"%weekday%", TranslateT("full weekday name")); - hPathTip = CreateToolTip(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY), tszTooltipText, TranslateT("Variables")); - } - if (hPathTip) - SetTimer(hwndDlg, 0, 3000, NULL); - break; - - case WM_COMMAND: - if ((LOWORD(wParam) == IDC_INSTAMP - || LOWORD(wParam) == IDC_OUTSTAMP - || LOWORD(wParam) == IDC_TIMESTAMP - || LOWORD(wParam) == IDC_LOGLIMIT - || LOWORD(wParam) == IDC_NICKROW2 - || LOWORD(wParam) == IDC_LOGDIRECTORY - || LOWORD(wParam) == IDC_LIMIT - || LOWORD(wParam) == IDC_LOGTIMESTAMP) - && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0; - - // open the base directory for MUC logs, using a standard file selector - // dialog. Simply allows the user to view what log files are there - // and possibly delete archived logs. - switch (LOWORD(wParam)) { - case IDC_MUC_OPENLOGBASEDIR: - { - wchar_t tszTemp[MAX_PATH + 20]; - wcsncpy_s(tszTemp, g_Settings.pszLogDir, _TRUNCATE); - - wchar_t *p = tszTemp; - while (*p && (*p == '\\' || *p == '.')) - p++; - - if (*p) - if (wchar_t *p1 = wcschr(p, '\\')) - *p1 = 0; - - wchar_t tszInitialDir[_MAX_DRIVE + _MAX_PATH + 10]; - mir_snwprintf(tszInitialDir, L"%s%s", M.getChatLogPath(), p); - if (!PathFileExists(tszInitialDir)) - wcsncpy_s(tszInitialDir, M.getChatLogPath(), _TRUNCATE); - - wchar_t tszReturnName[MAX_PATH]; tszReturnName[0] = 0; - mir_snwprintf(tszTemp, L"%s%c*.*%c%c", TranslateT("All files"), 0, 0, 0); - - OPENFILENAME ofn = { 0 }; - ofn.lpstrInitialDir = tszInitialDir; - ofn.lpstrFilter = tszTemp; - ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; - ofn.lpstrFile = tszReturnName; - ofn.nMaxFile = MAX_PATH; - ofn.nMaxFileTitle = MAX_PATH; - ofn.Flags = OFN_HIDEREADONLY | OFN_DONTADDTORECENT; - ofn.lpstrDefExt = L"log"; - GetOpenFileName(&ofn); - } - break; - - case IDC_FONTCHOOSE: - { - wchar_t tszDirectory[MAX_PATH]; - LPMALLOC psMalloc; - - if (SUCCEEDED(CoGetMalloc(1, &psMalloc))) { - BROWSEINFO bi = { 0 }; - bi.hwndOwner = hwndDlg; - bi.pszDisplayName = tszDirectory; - bi.lpszTitle = TranslateT("Select folder"); - bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_EDITBOX | BIF_RETURNONLYFSDIRS; - bi.lpfn = BrowseCallbackProc; - bi.lParam = (LPARAM)tszDirectory; - - LPITEMIDLIST idList = SHBrowseForFolder(&bi); - if (idList) { - const wchar_t *szUserDir = M.getUserDir(); - SHGetPathFromIDList(idList, tszDirectory); - mir_wstrcat(tszDirectory, L"\\"); - - wchar_t tszTemp[MAX_PATH]; - PathToRelativeW(tszDirectory, tszTemp, szUserDir); - SetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, mir_wstrlen(tszTemp) > 1 ? tszTemp : DEFLOGFILENAME); - } - psMalloc->Free(idList); - psMalloc->Release(); - } - } - break; - - case IDC_LOGGING: - Utils::enableDlgControl(hwndDlg, IDC_LOGDIRECTORY, IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED ? TRUE : FALSE); - Utils::enableDlgControl(hwndDlg, IDC_FONTCHOOSE, IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED ? TRUE : FALSE); - Utils::enableDlgControl(hwndDlg, IDC_LIMIT, IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED ? TRUE : FALSE); - break; - } - - if (lParam != 0) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - - case WM_NOTIFY: - if (((LPNMHDR)lParam)->idFrom == 0 && ((LPNMHDR)lParam)->code == PSN_APPLY) { - char *pszText = NULL; - - int iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY)); - if (iLen > 0) { - wchar_t *pszText1 = (wchar_t*)mir_alloc(iLen*sizeof(wchar_t) + 2); - GetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, pszText1, iLen + 1); - db_set_ws(NULL, CHAT_MODULE, "LogDirectory", pszText1); - mir_free(pszText1); - g_Settings.bLoggingEnabled = IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED; - db_set_b(0, CHAT_MODULE, "LoggingEnabled", g_Settings.bLoggingEnabled); - } - else { - db_unset(NULL, CHAT_MODULE, "LogDirectory"); - db_set_b(0, CHAT_MODULE, "LoggingEnabled", 0); - } - pci->SM_InvalidateLogDirectories(); - - iLen = SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN4, UDM_GETPOS, 0, 0); - db_set_w(NULL, CHAT_MODULE, "LoggingLimit", (WORD)iLen); - - iLen = SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN3, UDM_GETPOS, 0, 0); - if (iLen > 0) - db_set_b(0, CHAT_MODULE, "NicklistRowDist", (BYTE)iLen); - else - db_unset(NULL, CHAT_MODULE, "NicklistRowDist"); - - iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOGTIMESTAMP)); - if (iLen > 0) { - pszText = (char *)mir_realloc(pszText, iLen + 1); - GetDlgItemTextA(hwndDlg, IDC_LOGTIMESTAMP, pszText, iLen + 1); - db_set_s(NULL, CHAT_MODULE, "LogTimestamp", pszText); - } - else db_unset(NULL, CHAT_MODULE, "LogTimestamp"); - - iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_TIMESTAMP)); - if (iLen > 0) { - pszText = (char *)mir_realloc(pszText, iLen + 1); - GetDlgItemTextA(hwndDlg, IDC_TIMESTAMP, pszText, iLen + 1); - db_set_s(NULL, CHAT_MODULE, "HeaderTime", pszText); - } - else db_unset(NULL, CHAT_MODULE, "HeaderTime"); - - iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_INSTAMP)); - if (iLen > 0) { - pszText = (char *)mir_realloc(pszText, iLen + 1); - GetDlgItemTextA(hwndDlg, IDC_INSTAMP, pszText, iLen + 1); - db_set_s(NULL, CHAT_MODULE, "HeaderIncoming", pszText); - } - else db_unset(NULL, CHAT_MODULE, "HeaderIncoming"); - - iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_OUTSTAMP)); - if (iLen > 0) { - pszText = (char *)mir_realloc(pszText, iLen + 1); - GetDlgItemTextA(hwndDlg, IDC_OUTSTAMP, pszText, iLen + 1); - db_set_s(NULL, CHAT_MODULE, "HeaderOutgoing", pszText); - } - else db_unset(NULL, CHAT_MODULE, "HeaderOutgoing"); - - iLen = SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN2, UDM_GETPOS, 0, 0); - db_set_w(NULL, CHAT_MODULE, "LogLimit", (WORD)iLen); - mir_free(pszText); - - if (pci->hListBkgBrush) - DeleteObject(pci->hListBkgBrush); - pci->hListBkgBrush = CreateSolidBrush(M.GetDword(CHAT_MODULE, "ColorNicklistBG", SRMSGDEFSET_BKGCOLOUR)); - - pci->ReloadSettings(); - pci->MM_FontsChanged(); - pci->MM_FixColors(); - pci->SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE); - - PluginConfig.reloadSettings(); - CacheMsgLogIcons(); - CacheLogFonts(); - return TRUE; - } - break; - - case WM_TIMER: - if (IsWindow(hPathTip)) - KillTimer(hPathTip, 4); // It will prevent tooltip autoclosing - break; - - case WM_DESTROY: - if (hPathTip) { - KillTimer(hwndDlg, 0); - DestroyWindow(hPathTip); - hPathTip = 0; - } - break; - } - return FALSE; -} - -#define NR_GC_EVENTS 12 - -static UINT _eventorder[] = -{ - GC_EVENT_ACTION, - GC_EVENT_MESSAGE, - GC_EVENT_NICK, - GC_EVENT_JOIN, - GC_EVENT_PART, - GC_EVENT_TOPIC, - GC_EVENT_ADDSTATUS, - GC_EVENT_INFORMATION, - GC_EVENT_QUIT, - GC_EVENT_KICK, - GC_EVENT_NOTICE, - GC_EVENT_HIGHLIGHT -}; - -// Dialog procedure for group chat options tab #3 (event filter configuration) -INT_PTR CALLBACK DlgProcOptions3(HWND hwndDlg, UINT uMsg, WPARAM, LPARAM lParam) -{ - switch (uMsg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - { - DWORD dwFilterFlags = M.GetDword(CHAT_MODULE, "FilterFlags", GC_EVENT_ALL); - DWORD dwTrayFlags = M.GetDword(CHAT_MODULE, "TrayIconFlags", GC_EVENT_HIGHLIGHT); - DWORD dwPopupFlags = M.GetDword(CHAT_MODULE, "PopupFlags", GC_EVENT_HIGHLIGHT); - DWORD dwLogFlags = M.GetDword(CHAT_MODULE, "DiskLogFlags", GC_EVENT_ALL); - - for (int i = 0; i < _countof(_eventorder); i++) { - if (_eventorder[i] != GC_EVENT_HIGHLIGHT) { - CheckDlgButton(hwndDlg, IDC_1 + i, dwFilterFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_L1 + i, dwLogFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED); - } - CheckDlgButton(hwndDlg, IDC_P1 + i, dwPopupFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_T1 + i, dwTrayFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED); - } - } - SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_ADDSTRING, -1, (LPARAM)TranslateT("No markers")); - SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_ADDSTRING, -1, (LPARAM)TranslateT("Show as icons")); - SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_ADDSTRING, -1, (LPARAM)TranslateT("Show as text symbols")); - - SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_SETCURSEL, (g_Settings.bLogSymbols ? 2 : (g_Settings.dwIconFlags ? 1 : 0)), 0); - - CheckDlgButton(hwndDlg, IDC_TRAYONLYFORINACTIVE, M.GetByte(CHAT_MODULE, "TrayIconInactiveOnly", 0) ? BST_CHECKED : BST_UNCHECKED); - break; - - case WM_COMMAND: - if (lParam != 0) - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - - case WM_NOTIFY: - switch (((LPNMHDR)lParam)->idFrom) { - case 0: - switch (((LPNMHDR)lParam)->code) { - case PSN_APPLY: - DWORD dwFilterFlags = 0, dwTrayFlags = 0, - dwPopupFlags = 0, dwLogFlags = 0; - - for (int i = 0; i < _countof(_eventorder); i++) { - if (_eventorder[i] != GC_EVENT_HIGHLIGHT) { - dwFilterFlags |= (IsDlgButtonChecked(hwndDlg, IDC_1 + i) ? _eventorder[i] : 0); - dwLogFlags |= (IsDlgButtonChecked(hwndDlg, IDC_L1 + i) ? _eventorder[i] : 0); - } - dwPopupFlags |= (IsDlgButtonChecked(hwndDlg, IDC_P1 + i) ? _eventorder[i] : 0); - dwTrayFlags |= (IsDlgButtonChecked(hwndDlg, IDC_T1 + i) ? _eventorder[i] : 0); - } - db_set_dw(0, CHAT_MODULE, "FilterFlags", dwFilterFlags); - db_set_dw(0, CHAT_MODULE, "PopupFlags", dwPopupFlags); - db_set_dw(0, CHAT_MODULE, "TrayIconFlags", dwTrayFlags); - db_set_dw(0, CHAT_MODULE, "DiskLogFlags", dwLogFlags); - - LRESULT lr = SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_GETCURSEL, 0, 0); - - db_set_dw(0, CHAT_MODULE, "IconFlags", lr == 1 ? 1 : 0); - db_set_b(0, CHAT_MODULE, "LogSymbols", lr == 2 ? 1 : 0); - - db_set_b(0, CHAT_MODULE, "TrayIconInactiveOnly", IsDlgButtonChecked(hwndDlg, IDC_TRAYONLYFORINACTIVE) ? 1 : 0); - - pci->ReloadSettings(); - pci->MM_FontsChanged(); - pci->SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE); - SM_ReconfigureFilters(); - return TRUE; - } - } - break; - } - return FALSE; -} diff --git a/plugins/TabSRMM/src/chat/services.cpp b/plugins/TabSRMM/src/chat/services.cpp deleted file mode 100644 index 9e7d82272d..0000000000 --- a/plugins/TabSRMM/src/chat/services.cpp +++ /dev/null @@ -1,160 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////////////// -// Miranda NG: the free IM client for Microsoft* Windows* -// -// Copyright (ñ) 2012-17 Miranda NG project, -// Copyright (c) 2000-09 Miranda ICQ/IM project, -// all portions of this codebase are copyrighted to the people -// listed in contributors.txt. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// you should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -// part of tabSRMM messaging plugin for Miranda. -// -// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors -// -// This implements the services that form the group chat API - -#include "../stdafx.h" - -void ShowRoom(SESSION_INFO *si) -{ - if (si == nullptr) - return; - - if (si->hWnd != nullptr) { - ActivateExistingTab(si->dat->m_pContainer, si->hWnd); - return; - } - - wchar_t szName[CONTAINER_NAMELEN + 2]; szName[0] = 0; - TContainerData *pContainer = nullptr; - if (si->dat != nullptr) - pContainer = si->dat->m_pContainer; - if (pContainer == nullptr) { - GetContainerNameForContact(si->hContact, szName, CONTAINER_NAMELEN); - if (!g_Settings.bOpenInDefault && !mir_wstrcmp(szName, L"default")) - wcsncpy(szName, L"Chat Rooms", CONTAINER_NAMELEN); - szName[CONTAINER_NAMELEN] = 0; - pContainer = FindContainerByName(szName); - } - if (pContainer == nullptr) - pContainer = CreateContainer(szName, FALSE, si->hContact); - if (pContainer == nullptr) - return; // smth went wrong, nothing to do here - - MCONTACT hContact = si->hContact; - if (M.FindWindow(hContact) != 0) - return; - - if (hContact != 0 && M.GetByte("limittabs", 0) && !wcsncmp(pContainer->szName, L"default", 6)) { - if ((pContainer = FindMatchingContainer(L"default")) == NULL) { - wchar_t szName[CONTAINER_NAMELEN + 1]; - mir_snwprintf(szName, L"default"); - if ((pContainer = CreateContainer(szName, CNT_CREATEFLAG_CLONED, hContact)) == NULL) - return; - } - } - - wchar_t *contactName = pcli->pfnGetContactDisplayName(hContact, 0); - - // cut nickname if larger than x chars... - wchar_t newcontactname[128]; - if (mir_wstrlen(contactName) > 0) { - if (M.GetByte("cuttitle", 0)) - CutContactName(contactName, newcontactname, _countof(newcontactname)); - else - wcsncpy_s(newcontactname, contactName, _TRUNCATE); - } - else wcsncpy_s(newcontactname, L"_U_", _TRUNCATE); - - HWND hwndTab = GetDlgItem(pContainer->hwnd, IDC_MSGTABS); - - // hide the active tab - if (pContainer->hwndActive) - ShowWindow(pContainer->hwndActive, SW_HIDE); - - int iTabIndex_wanted = M.GetDword(hContact, "tabindex", pContainer->iChilds * 100); - int iCount = TabCtrl_GetItemCount(hwndTab); - - pContainer->iTabIndex = iCount; - if (iCount > 0) { - TCITEM item = {}; - for (int i = iCount - 1; i >= 0; i--) { - item.mask = TCIF_PARAM; - TabCtrl_GetItem(hwndTab, i, &item); - HWND hwnd = (HWND)item.lParam; - CSrmmWindow *dat = (CSrmmWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA); - if (dat) { - int relPos = M.GetDword(dat->m_hContact, "tabindex", i * 100); - if (iTabIndex_wanted <= relPos) - pContainer->iTabIndex = i; - } - } - } - - TCITEM item = {}; - item.pszText = newcontactname; - item.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM; - int iTabId = TabCtrl_InsertItem(hwndTab, pContainer->iTabIndex, &item); - - SendMessage(hwndTab, EM_REFRESHWITHOUTCLIP, 0, 0); - TabCtrl_SetCurSel(hwndTab, iTabId); - pContainer->iChilds++; - - CChatRoomDlg *pDlg = new CChatRoomDlg(si); - pDlg->m_iTabID = iTabId; - pDlg->m_pContainer = pContainer; - pDlg->SetParent(hwndTab); - pDlg->Create(); - - HWND hwndNew = pDlg->GetHwnd(); - item.lParam = (LPARAM)hwndNew; - TabCtrl_SetItem(hwndTab, iTabId, &item); - - if (pContainer->dwFlags & CNT_SIDEBAR) - pContainer->SideBar->addSession(pDlg, pContainer->iTabIndex); - - SendMessage(pContainer->hwnd, WM_SIZE, 0, 0); - // if the container is minimized, then pop it up... - if (IsIconic(pContainer->hwnd)) { - SendMessage(pContainer->hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); - SetFocus(pContainer->hwndActive); - } - - if (PluginConfig.m_bHideOnClose && !IsWindowVisible(pContainer->hwnd)) { - WINDOWPLACEMENT wp = { 0 }; - wp.length = sizeof(wp); - GetWindowPlacement(pContainer->hwnd, &wp); - - BroadCastContainer(pContainer, DM_CHECKSIZE, 0, 0); // make sure all tabs will re-check layout on activation - if (wp.showCmd == SW_SHOWMAXIMIZED) - ShowWindow(pContainer->hwnd, SW_SHOWMAXIMIZED); - else { - ShowWindow(pContainer->hwnd, SW_SHOWNORMAL); - } - SendMessage(pContainer->hwndActive, WM_SIZE, 0, 0); - SetFocus(hwndNew); - } - else { - SetFocus(hwndNew); - RedrawWindow(pContainer->hwnd, NULL, NULL, RDW_INVALIDATE); - UpdateWindow(pContainer->hwnd); - if (GetForegroundWindow() != pContainer->hwnd) - SetForegroundWindow(pContainer->hwnd); - } - - if (PluginConfig.m_bIsWin7 && PluginConfig.m_useAeroPeek && CSkin::m_skinEnabled && !M.GetByte("forceAeroPeek", 0)) - CWarning::show(CWarning::WARN_AEROPEEK_SKIN, MB_ICONWARNING | MB_OK); -} diff --git a/plugins/TabSRMM/src/chat/tools.cpp b/plugins/TabSRMM/src/chat/tools.cpp deleted file mode 100644 index 47feb637df..0000000000 --- a/plugins/TabSRMM/src/chat/tools.cpp +++ /dev/null @@ -1,696 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////////////// -// Miranda NG: the free IM client for Microsoft* Windows* -// -// Copyright (ñ) 2012-17 Miranda NG project, -// Copyright (c) 2000-09 Miranda ICQ/IM project, -// all portions of this codebase are copyrighted to the people -// listed in contributors.txt. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// you should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -// part of tabSRMM messaging plugin for Miranda. -// -// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors -// -// Helper functions for the group chat module. - -#include "../stdafx.h" - -int GetRichTextLength(HWND hwnd) -{ - GETTEXTLENGTHEX gtl; - gtl.flags = GTL_PRECISE; - gtl.codepage = CP_ACP; - return (int)SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>l, 0); -} - -static void __stdcall ShowRoomFromPopup(void *pi) -{ - SESSION_INFO *si = (SESSION_INFO*)pi; - ShowRoom(si); -} - -static void __stdcall Chat_DismissPopup(void *pi) -{ - SESSION_INFO *si = (SESSION_INFO*)pi; - if (si->hContact) - if (pcli->pfnGetEvent(si->hContact, 0)) - pcli->pfnRemoveEvent(si->hContact, GC_FAKE_EVENT); - - if (si->hWnd && KillTimer(si->hWnd, TIMERID_FLASHWND)) - FlashWindow(si->hWnd, FALSE); -} - -static LRESULT CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - SESSION_INFO *si = (SESSION_INFO*)PUGetPluginData(hWnd); - - switch (message) { - case WM_COMMAND: - if (HIWORD(wParam) == STN_CLICKED) { - if (si) { - if (nen_options.maskActL & MASK_OPEN) - CallFunctionAsync(ShowRoomFromPopup, si); - else - CallFunctionAsync(Chat_DismissPopup, si); - PUDeletePopup(hWnd); - } - return TRUE; - } - break; - - case WM_CONTEXTMENU: - if (si && si->hContact) { - if (nen_options.maskActR & MASK_OPEN) - CallFunctionAsync(ShowRoomFromPopup, si); - else - CallFunctionAsync(Chat_DismissPopup, si); - PUDeletePopup(hWnd); - } - break; - } - return DefWindowProc(hWnd, message, wParam, lParam); -} - -BOOL DoTrayIcon(SESSION_INFO *si, GCEVENT *gce) -{ - int iEvent = gce->pDest->iType; - if (si && (iEvent & si->iLogTrayFlags)) - return saveCI.DoTrayIcon(si, gce); - return TRUE; -} - -int ShowPopup(MCONTACT hContact, SESSION_INFO *si, HICON hIcon, char* pszProtoName, wchar_t*, COLORREF crBkg, const wchar_t* fmt, ...) -{ - POPUPDATAT pd = { 0 }; - va_list marker; - static wchar_t szBuf[4 * 1024]; - - if (!fmt || mir_wstrlen(fmt) == 0 || mir_wstrlen(fmt) > 2000) - return 0; - - va_start(marker, fmt); - mir_vsnwprintf(szBuf, _countof(szBuf), fmt, marker); - va_end(marker); - - pd.lchContact = hContact; - - if (hIcon) - pd.lchIcon = hIcon; - else - pd.lchIcon = LoadIconEx("window"); - - PROTOACCOUNT *pa = Proto_GetAccount(pszProtoName); - mir_snwprintf(pd.lptzContactName, L"%s - %s", (pa == NULL) ? _A2T(pszProtoName) : pa->tszAccountName, pcli->pfnGetContactDisplayName(hContact, 0)); - wcsncpy_s(pd.lptzText, TranslateW(szBuf), _TRUNCATE); - 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 = g_Settings.crLogBackground; - pd.colorText = crBkg; - } - - pd.PluginWindowProc = PopupDlgProc; - pd.PluginData = si; - return PUAddPopupT(&pd); -} - -BOOL DoPopup(SESSION_INFO *si, GCEVENT *gce) -{ - int iEvent = gce->pDest->iType; - if (si == NULL || !(iEvent & si->iLogPopupFlags)) - return true; - - CTabBaseDlg *dat = si->dat; - TContainerData *pContainer = dat ? dat->m_pContainer : NULL; - - wchar_t *bbStart, *bbEnd; - if (g_Settings.bBBCodeInPopups) { - bbStart = L"[b]"; - bbEnd = L"[/b]"; - } - else bbStart = bbEnd = L""; - - if (nen_options.iMUCDisable) // no popups at all. Period - return 0; - /* - * check the status mode against the status mask - */ - - char *szProto = dat ? dat->m_szProto : si->pszModule; - 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_bHideOnClose) - 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 = pci->aFonts[16].color; - iNewEvent &= ~GC_EVENT_HIGHLIGHT; - } - - if (iNewEvent == GC_EVENT_MESSAGE) { - ShowPopup(si->hContact, si, pci->hIcons[ICON_MESSAGE], si->pszModule, si->ptszName, clr ? clr : pci->aFonts[9].color, - TranslateT("%s%s says:%s %s"), bbStart, gce->ptszNick, bbEnd, pci->RemoveFormatting(gce->ptszText)); - } - else saveCI.DoPopup(si, gce); - - return TRUE; -} - -void DoFlashAndSoundWorker(FLASH_PARAMS* p) -{ - SESSION_INFO *si = SM_FindSessionByHCONTACT(p->hContact); - if (si == 0) - return; - - CTabBaseDlg *dat = 0; - if (si->hWnd) { - dat = si->dat; - if (dat) { - p->bInactive = dat->m_pContainer->hwnd != GetForegroundWindow(); - p->bActiveTab = (dat->m_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 == pci->hIcons[ICON_HIGHLIGHT] || p->hNotifyIcon == pci->hIcons[ICON_MESSAGE]); - - if ((p->iEvent & si->iLogTrayFlags) || bForcedIcon) { - if (!p->bActiveTab) { - if (p->hNotifyIcon == pci->hIcons[ICON_HIGHLIGHT]) - dat->m_iFlashIcon = p->hNotifyIcon; - else { - if (dat->m_iFlashIcon != pci->hIcons[ICON_HIGHLIGHT] && dat->m_iFlashIcon != pci->hIcons[ICON_MESSAGE]) - dat->m_iFlashIcon = p->hNotifyIcon; - } - dat->m_bCanFlashTab = TRUE; - SetTimer(si->hWnd, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL); - } - } - if (dat->m_pWnd) { - dat->m_pWnd->updateIcon(p->hNotifyIcon); - dat->m_pWnd->setOverlayIcon(p->hNotifyIcon, true); - } - - // autoswitch tab.. - if (p->bMustAutoswitch) { - if ((IsIconic(dat->m_pContainer->hwnd)) && !IsZoomed(dat->m_pContainer->hwnd) && PluginConfig.haveAutoSwitch() && dat->m_pContainer->hwndActive != si->hWnd) { - int iItem = GetTabIndexFromHWND(hwndTab, si->hWnd); - if (iItem >= 0) { - TabCtrl_SetCurSel(hwndTab, iItem); - ShowWindow(dat->m_pContainer->hwndActive, SW_HIDE); - dat->m_pContainer->hwndActive = si->hWnd; - SendMessage(dat->m_pContainer->hwnd, DM_UPDATETITLE, dat->m_hContact, 0); - dat->m_pContainer->dwFlags |= CNT_DEFERREDTABSELECT; - } - } - } - - // flash window if it is not focused - if (p->bMustFlash && p->bInactive) - if (!(dat->m_pContainer->dwFlags & CNT_NOFLASH)) - FlashContainer(dat->m_pContainer, 1, 0); - - if (p->hNotifyIcon && p->bInactive && ((p->iEvent & si->iLogTrayFlags) || bForcedIcon)) { - if (p->bMustFlash) - dat->m_hTabIcon = p->hNotifyIcon; - else if (dat->m_iFlashIcon) { - dat->m_hTabIcon = dat->m_iFlashIcon; - - TCITEM item = {}; - item.mask = TCIF_IMAGE; - item.iImage = 0; - TabCtrl_SetItem(GetParent(si->hWnd), dat->m_iTabID, &item); - } - - HICON hIcon = (HICON)SendMessage(dat->m_pContainer->hwnd, WM_GETICON, ICON_BIG, 0); - if (p->hNotifyIcon == pci->hIcons[ICON_HIGHLIGHT] || (hIcon != pci->hIcons[ICON_MESSAGE] && hIcon != pci->hIcons[ICON_HIGHLIGHT])) { - SendMessage(dat->m_pContainer->hwnd, DM_SETICON, (WPARAM)dat, (LPARAM)p->hNotifyIcon); - dat->m_pContainer->dwFlags |= CNT_NEED_UPDATETITLE; - } - } - - if (p->bMustFlash && p->bInactive) - UpdateTrayMenu(dat, si->wStatus, si->pszModule, dat->m_wszStatus, si->hContact, 1); - } - - mir_free(p); -} - -BOOL DoSoundsFlashPopupTrayStuff(SESSION_INFO *si, GCEVENT *gce, BOOL bHighlight, int bManyFix) -{ - if (gce == 0 || si == 0 || gce->bIsMe || si->iType == GCW_SERVER) - return FALSE; - - CTabBaseDlg *dat = NULL; - FLASH_PARAMS *params = (FLASH_PARAMS*)mir_calloc(sizeof(FLASH_PARAMS)); - params->hContact = si->hContact; - params->bInactive = TRUE; - if (si->hWnd && si->dat) { - dat = si->dat; - if ((si->hWnd == si->dat->m_pContainer->hwndActive) && GetForegroundWindow() == si->dat->m_pContainer->hwnd) - params->bInactive = FALSE; - } - params->bActiveTab = params->bMustFlash = params->bMustAutoswitch = FALSE; - params->iEvent = gce->pDest->iType; - - WPARAM wParamForHighLight = 0; - bool bFlagUnread = false; - if (bHighlight) { - gce->pDest->iType |= GC_EVENT_HIGHLIGHT; - params->sound = "ChatHighlight"; - if (db_get_b(si->hContact, "CList", "Hidden", 0) != 0) - db_unset(si->hContact, "CList", "Hidden"); - if (params->bInactive) { - bFlagUnread = true; - DoTrayIcon(si, gce); - } - - if (g_Settings.bCreateWindowOnHighlight && dat == NULL) - wParamForHighLight = 1; - - if (dat && g_Settings.bAnnoyingHighlight && params->bInactive && dat->m_pContainer->hwnd != GetForegroundWindow()) { - wParamForHighLight = 2; - params->hWnd = dat->GetHwnd(); - } - - if (dat || !nen_options.iMUCDisable) - DoPopup(si, gce); - if (params->bInactive && si && si->hWnd) - SendMessage(si->hWnd, GC_SETMESSAGEHIGHLIGHT, 0, (LPARAM)si); - if (g_Settings.bFlashWindowHighlight && params->bInactive) - params->bMustFlash = TRUE; - params->bMustAutoswitch = TRUE; - params->hNotifyIcon = pci->hIcons[ICON_HIGHLIGHT]; - } - else { - // do blinking icons in tray - if (params->bInactive || !g_Settings.bTrayIconInactiveOnly) { - DoTrayIcon(si, gce); - if (params->iEvent == GC_EVENT_MESSAGE) - bFlagUnread = 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); - - // do sounds and flashing - switch (params->iEvent) { - case GC_EVENT_JOIN: - params->sound = "ChatJoin"; - if (params->bInactive) - params->hNotifyIcon = pci->hIcons[ICON_JOIN]; - break; - case GC_EVENT_PART: - params->sound = "ChatPart"; - if (params->bInactive) - params->hNotifyIcon = pci->hIcons[ICON_PART]; - break; - case GC_EVENT_QUIT: - params->sound = "ChatQuit"; - if (params->bInactive) - params->hNotifyIcon = pci->hIcons[ICON_QUIT]; - break; - case GC_EVENT_ADDSTATUS: - case GC_EVENT_REMOVESTATUS: - params->sound = "ChatMode"; - if (params->bInactive) - params->hNotifyIcon = pci->hIcons[params->iEvent == GC_EVENT_ADDSTATUS ? ICON_ADDSTATUS : ICON_REMSTATUS]; - break; - case GC_EVENT_KICK: - params->sound = "ChatKick"; - if (params->bInactive) - params->hNotifyIcon = pci->hIcons[ICON_KICK]; - break; - case GC_EVENT_MESSAGE: - params->sound = "ChatMessage"; - if (params->bInactive && !(si->wState & STATE_TALK)) { - si->wState |= STATE_TALK; - db_set_w(si->hContact, si->pszModule, "ApparentMode", ID_STATUS_OFFLINE); - } - break; - case GC_EVENT_ACTION: - params->sound = "ChatAction"; - if (params->bInactive) - params->hNotifyIcon = pci->hIcons[ICON_ACTION]; - break; - case GC_EVENT_NICK: - params->sound = "ChatNick"; - if (params->bInactive) - params->hNotifyIcon = pci->hIcons[ICON_NICK]; - break; - case GC_EVENT_NOTICE: - params->sound = "ChatNotice"; - if (params->bInactive) - params->hNotifyIcon = pci->hIcons[ICON_NOTICE]; - break; - case GC_EVENT_TOPIC: - params->sound = "ChatTopic"; - if (params->bInactive) - params->hNotifyIcon = pci->hIcons[ICON_TOPIC]; - break; - } - } - else { - switch (params->iEvent) { - case GC_EVENT_JOIN: - params->hNotifyIcon = pci->hIcons[ICON_JOIN]; - break; - case GC_EVENT_PART: - params->hNotifyIcon = pci->hIcons[ICON_PART]; - break; - case GC_EVENT_QUIT: - params->hNotifyIcon = pci->hIcons[ICON_QUIT]; - break; - case GC_EVENT_KICK: - params->hNotifyIcon = pci->hIcons[ICON_KICK]; - break; - case GC_EVENT_ACTION: - params->hNotifyIcon = pci->hIcons[ICON_ACTION]; - break; - case GC_EVENT_NICK: - params->hNotifyIcon = pci->hIcons[ICON_NICK]; - break; - case GC_EVENT_NOTICE: - params->hNotifyIcon = pci->hIcons[ICON_NOTICE]; - break; - case GC_EVENT_TOPIC: - params->hNotifyIcon = pci->hIcons[ICON_TOPIC]; - break; - case GC_EVENT_ADDSTATUS: - params->hNotifyIcon = pci->hIcons[ICON_ADDSTATUS]; - break; - case GC_EVENT_REMOVESTATUS: - params->hNotifyIcon = pci->hIcons[ICON_REMSTATUS]; - break; - } - } - - if (params->iEvent == GC_EVENT_MESSAGE) { - params->bMustAutoswitch = TRUE; - if (g_Settings.bFlashWindow) - params->bMustFlash = TRUE; - params->hNotifyIcon = pci->hIcons[ICON_MESSAGE]; - } - } - if (dat && bFlagUnread) { - dat->m_dwUnread++; - if (dat->m_pWnd) - dat->m_pWnd->Invalidate(); - } - PostMessage(PluginConfig.g_hwndHotkeyHandler, DM_MUCFLASHWORKER, wParamForHighLight, (LPARAM)params); - return TRUE; -} - -int Chat_GetColorIndex(const char* pszModule, COLORREF cr) -{ - MODULEINFO *pMod = pci->MM_FindModule(pszModule); - if (!pMod || pMod->nColorCount == 0) - return -1; - - for (int i = 0; i < pMod->nColorCount; i++) - if (pMod->crColors[i] == cr) - return i; - - return -1; -} - -wchar_t* my_strstri(const wchar_t* s1, const wchar_t* s2) -{ - int i, j, k; - - _wsetlocale(LC_ALL, L""); - for (i = 0; s1[i]; i++) - for (j = i, k = 0; towlower(s1[j]) == towlower(s2[k]); j++, k++) - if (!s2[k + 1]) - return (wchar_t*)(s1 + i); - - return NULL; -} - -/* -* log the event to the log file -* allows selective logging of wanted events -*/ -BOOL LogToFile(SESSION_INFO *si, GCEVENT *gce) -{ - if (!si || !gce) - return FALSE; - - /* - * check whether we have to log this event - */ - if (!(gce->pDest->iType & si->iDiskLogFlags)) - return FALSE; - - return saveCI.LogToFile(si, gce); // call kernel method -} - -UINT CreateGCMenu(HWND hwndDlg, HMENU *hMenu, int iIndex, POINT pt, SESSION_INFO *si, wchar_t* pszUID, wchar_t* pszWordText) -{ - HMENU hSubMenu = 0; - - *hMenu = GetSubMenu(g_hMenu, iIndex); - TranslateMenu(*hMenu); - - GCMENUITEMS gcmi = { 0 }; - gcmi.pszID = si->ptszID; - gcmi.pszModule = si->pszModule; - gcmi.pszUID = pszUID; - - if (iIndex == 1) { - int i = GetRichTextLength(GetDlgItem(hwndDlg, IDC_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]) { - wchar_t szMenuText[4096]; - mir_snwprintf(szMenuText, TranslateT("Look up '%s':"), pszWordText); - ModifyMenu(*hMenu, 4, MF_STRING | MF_BYPOSITION, 4, szMenuText); - } - else ModifyMenu(*hMenu, 4, MF_STRING | MF_GRAYED | MF_BYPOSITION, 4, TranslateT("No word to look up")); - gcmi.Type = MENU_ON_LOG; - } - else if (iIndex == 0) { - wchar_t szTemp[50]; - if (pszWordText) - mir_snwprintf(szTemp, TranslateT("&Message %s"), pszWordText); - else - wcsncpy_s(szTemp, TranslateT("&Message"), _TRUNCATE); - - if (mir_wstrlen(szTemp) > 40) - wcsncpy_s(szTemp + 40, 4, L"...", _TRUNCATE); - ModifyMenu(*hMenu, ID_MESS, MF_STRING | MF_BYCOMMAND, ID_MESS, szTemp); - gcmi.Type = MENU_ON_NICKLIST; - } - - NotifyEventHooks(pci->hBuildMenuEvent, 0, (WPARAM)&gcmi); - - if (gcmi.nItems > 0) - AppendMenu(*hMenu, MF_SEPARATOR, 0, 0); - - for (int i = 0; i < gcmi.nItems; i++) { - wchar_t *ptszText = TranslateW(gcmi.Item[i].pszDesc); - 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, ptszText); - } - else if (gcmi.Item[i].uType == MENU_POPUPHMENU) - AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_POPUP, gcmi.Item[i].dwID, ptszText); - else if (gcmi.Item[i].uType == MENU_POPUPITEM) - AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_STRING, gcmi.Item[i].dwID, ptszText); - else if (gcmi.Item[i].uType == MENU_POPUPCHECK) - AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_CHECKED | MF_STRING, gcmi.Item[i].dwID, ptszText); - else if (gcmi.Item[i].uType == MENU_POPUPSEPARATOR) - AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, MF_SEPARATOR, 0, ptszText); - else if (gcmi.Item[i].uType == MENU_SEPARATOR) - AppendMenu(*hMenu, MF_SEPARATOR, 0, ptszText); - else if (gcmi.Item[i].uType == MENU_HMENU) - AppendMenu(*hMenu, dwState | MF_POPUP, gcmi.Item[i].dwID, ptszText); - else if (gcmi.Item[i].uType == MENU_ITEM) - AppendMenu(*hMenu, dwState | MF_STRING, gcmi.Item[i].dwID, ptszText); - else if (gcmi.Item[i].uType == MENU_CHECK) - AppendMenu(*hMenu, dwState | MF_CHECKED | MF_STRING, gcmi.Item[i].dwID, ptszText); - } - - if (iIndex == 0) { - AppendMenu(*hMenu, MF_SEPARATOR, 0, 0); - int pos = GetMenuItemCount(*hMenu); - InsertMenu(*hMenu, pos, MF_BYPOSITION, (UINT_PTR)20020, TranslateT("Highlight user...")); - InsertMenu(*hMenu, pos, MF_BYPOSITION, (UINT_PTR)20021, TranslateT("Edit highlight list...")); - } - - return TrackPopupMenu(*hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL); -} - -void DestroyGCMenu(HMENU *hMenu, int iIndex) -{ - MENUITEMINFO mii = { 0 }; - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_SUBMENU; - while (GetMenuItemInfo(*hMenu, iIndex, TRUE, &mii)) { - if (mii.hSubMenu != NULL) - DestroyMenu(mii.hSubMenu); - RemoveMenu(*hMenu, iIndex, MF_BYPOSITION); - } -} - -/* - * set all filters and notification config for a session - * uses per channel mask + filterbits, default config as backup - */ -void Chat_SetFilters(SESSION_INFO *si) -{ - if (si == NULL) - return; - - DWORD dwFlags_default = M.GetDword(CHAT_MODULE, "FilterFlags", GC_EVENT_ALL); - DWORD dwFlags_local = db_get_dw(si->hContact, CHAT_MODULE, "FilterFlags", GC_EVENT_ALL); - DWORD dwMask = db_get_dw(si->hContact, CHAT_MODULE, "FilterMask", 0); - - si->iLogFilterFlags = dwFlags_default; - for (int i = 0; i < 32; i++) { - DWORD dwBit = 1 << i; - if (dwMask & dwBit) - si->iLogFilterFlags = (dwFlags_local & dwBit) ? si->iLogFilterFlags | dwBit : si->iLogFilterFlags & ~dwBit; - } - - dwFlags_default = M.GetDword(CHAT_MODULE, "PopupFlags", GC_EVENT_HIGHLIGHT); - dwFlags_local = db_get_dw(si->hContact, CHAT_MODULE, "PopupFlags", GC_EVENT_HIGHLIGHT); - dwMask = db_get_dw(si->hContact, CHAT_MODULE, "PopupMask", 0); - - si->iLogPopupFlags = dwFlags_default; - for (int i = 0; i < 32; i++) { - DWORD dwBit = 1 << i; - if (dwMask & dwBit) - si->iLogPopupFlags = (dwFlags_local & dwBit) ? si->iLogPopupFlags | dwBit : si->iLogPopupFlags & ~dwBit; - } - - dwFlags_default = M.GetDword(CHAT_MODULE, "TrayIconFlags", GC_EVENT_HIGHLIGHT); - dwFlags_local = db_get_dw(si->hContact, CHAT_MODULE, "TrayIconFlags", GC_EVENT_HIGHLIGHT); - dwMask = db_get_dw(si->hContact, CHAT_MODULE, "TrayIconMask", 0); - - si->iDiskLogFlags = M.GetDword(CHAT_MODULE, "DiskLogFlags", GC_EVENT_ALL); - - si->iLogTrayFlags = dwFlags_default; - for (int i = 0; i < 32; i++) { - DWORD dwBit = 1 << i; - if (dwMask & dwBit) - si->iLogTrayFlags = (dwFlags_local & dwBit) ? si->iLogTrayFlags | dwBit : si->iLogTrayFlags & ~dwBit; - } - - if (si->iLogFilterFlags == 0) - si->bFilterEnabled = 0; -} - -char GetIndicator(SESSION_INFO *si, LPCTSTR ptszNick, int *iNickIndex) -{ - if (iNickIndex) - *iNickIndex = 0; - - for (USERINFO *ui = si->pUsers; ui; ui = ui->next) { - if (!mir_wstrcmp(ui->pszNick, ptszNick)) { - STATUSINFO *ti = pci->TM_FindStatus(si->pStatuses, pci->TM_WordToString(si->pStatuses, ui->Status)); - if (ti && (INT_PTR)ti->hIcon < si->iStatusCount) { - if (iNickIndex) - *iNickIndex = (INT_PTR)ti->hIcon; // color table's index is not zero-based - return szIndicators[(INT_PTR)ti->hIcon]; - } - break; - } - } - return 0; -} - -bool IsHighlighted(SESSION_INFO *si, GCEVENT *gce) -{ - if (!g_Settings.bHighlightEnabled || !gce || gce->bIsMe) - return FALSE; - - GCEVENT evTmp = *gce; - - int dwMask = 0; - if (gce->ptszText != NULL) - dwMask |= CMUCHighlight::MATCH_TEXT; - - if (gce->ptszNick != NULL) { - dwMask |= CMUCHighlight::MATCH_NICKNAME; - if (si && g_Settings.bLogClassicIndicators) { - size_t len = mir_wstrlen(gce->ptszNick) + 1; - wchar_t *tmp = (wchar_t*)_alloca(sizeof(wchar_t)*(len + 1)); - *tmp = GetIndicator(si, gce->ptszNick, 0); - mir_wstrcpy(tmp + 1, gce->ptszNick); - evTmp.ptszNick = tmp; - } - } - return g_Settings.Highlight->match(&evTmp, si, dwMask); -} diff --git a/plugins/TabSRMM/src/chat/window.cpp b/plugins/TabSRMM/src/chat/window.cpp deleted file mode 100644 index 066e83b176..0000000000 --- a/plugins/TabSRMM/src/chat/window.cpp +++ /dev/null @@ -1,3124 +0,0 @@ -///////////////////////////////////////////////////////////////////////////////////////// -// Miranda NG: the free IM client for Microsoft* Windows* -// -// Copyright (ñ) 2012-17 Miranda NG project, -// Copyright (c) 2000-09 Miranda ICQ/IM project, -// all portions of this codebase are copyrighted to the people -// listed in contributors.txt. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// you should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -// part of tabSRMM messaging plugin for Miranda. -// -// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors -// -// This implements the group chat dialog window - -#include "../stdafx.h" - -// externs... -extern LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); -extern HRESULT(WINAPI *MyCloseThemeData)(HANDLE); - -int g_cLinesPerPage = 0; -int g_iWheelCarryover = 0; - -extern HMENU g_hMenu; - -static HKL hkl = NULL; -char szIndicators[] = { 0, '+', '%', '@', '!', '*' }; - -struct MESSAGESUBDATA -{ - time_t lastEnterTime; - wchar_t *szSearchQuery; - wchar_t *szSearchResult; - BOOL iSavedSpaces; - SESSION_INFO *lastSession; -}; - -const CLSID IID_ITextDocument = { 0x8CC497C0, 0xA1DF, 0x11CE, { 0x80, 0x98, 0x00, 0xAA, 0x00, 0x47, 0xBE, 0x5D } }; - -///////////////////////////////////////////////////////////////////////////////////////// -// checking if theres's protected text at the point -// emulates EN_LINK WM_NOTIFY to parent to process links - -static BOOL CheckCustomLink(HWND hwndDlg, POINT *ptClient, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL bUrlNeeded) -{ - long res = 0, cnt = 0; - long cpMin = 0, cpMax = 0; - POINT ptEnd = { 0 }; - IRichEditOle *RichEditOle = NULL; - ITextDocument *TextDocument = NULL; - ITextRange *TextRange = NULL; - ITextFont *TextFont = NULL; - BOOL bIsCustomLink = FALSE; - - POINT pt = *ptClient; - ClientToScreen(hwndDlg, &pt); - - do { - if (!SendMessage(hwndDlg, EM_GETOLEINTERFACE, 0, (LPARAM)&RichEditOle)) break; - if (RichEditOle->QueryInterface(IID_ITextDocument, (void**)&TextDocument) != S_OK) break; - if (TextDocument->RangeFromPoint(pt.x, pt.y, &TextRange) != S_OK) break; - - TextRange->GetStart(&cpMin); - cpMax = cpMin + 1; - TextRange->SetEnd(cpMax); - - if (TextRange->GetFont(&TextFont) != S_OK) - break; - - TextFont->GetProtected(&res); - if (res != tomTrue) - break; - - TextRange->GetPoint(tomEnd + TA_BOTTOM + TA_RIGHT, &ptEnd.x, &ptEnd.y); - if (pt.x > ptEnd.x || pt.y > ptEnd.y) - break; - - if (bUrlNeeded) { - TextRange->GetStoryLength(&cnt); - for (; cpMin > 0; cpMin--) { - res = tomTrue; - TextRange->SetIndex(tomCharacter, cpMin + 1, tomTrue); - TextFont->GetProtected(&res); - if (res != tomTrue) { cpMin++; break; } - } - for (cpMax--; cpMax < cnt; cpMax++) { - res = tomTrue; - TextRange->SetIndex(tomCharacter, cpMax + 1, tomTrue); - TextFont->GetProtected(&res); - if (res != tomTrue) - break; - } - } - - bIsCustomLink = (cpMin < cpMax); - } while (FALSE); - - if (TextFont) TextFont->Release(); - if (TextRange) TextRange->Release(); - if (TextDocument) TextDocument->Release(); - if (RichEditOle) RichEditOle->Release(); - - if (bIsCustomLink) { - ENLINK enlink = { 0 }; - enlink.nmhdr.hwndFrom = hwndDlg; - enlink.nmhdr.idFrom = IDC_LOG; - enlink.nmhdr.code = EN_LINK; - enlink.msg = uMsg; - enlink.wParam = wParam; - enlink.lParam = lParam; - enlink.chrg.cpMin = cpMin; - enlink.chrg.cpMax = cpMax; - SendMessage(GetParent(hwndDlg), WM_NOTIFY, IDC_LOG, (LPARAM)&enlink); - } - return bIsCustomLink; -} - -bool IsStringValidLink(wchar_t *pszText) -{ - if (pszText == NULL) - return false; - - if (mir_wstrlen(pszText) < 5 || wcschr(pszText, '"')) - return false; - - if (towlower(pszText[0]) == 'w' && towlower(pszText[1]) == 'w' && towlower(pszText[2]) == 'w' && pszText[3] == '.' && iswalnum(pszText[4])) - return true; - - return wcsstr(pszText, L"://") != NULL; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// called whenever a group chat tab becomes active(either by switching tabs or activating a -// container window - -void CChatRoomDlg::UpdateWindowState(UINT msg) -{ - if (si == NULL) - return; - - if (msg == WM_ACTIVATE) { - if (m_pContainer->dwFlags & CNT_TRANSPARENCY) { - DWORD trans = LOWORD(m_pContainer->settings->dwTransparency); - SetLayeredWindowAttributes(m_pContainer->hwnd, CSkin::m_ContainerColorKey, (BYTE)trans, (m_pContainer->dwFlags & CNT_TRANSPARENCY ? LWA_ALPHA : 0)); - } - } - - if (m_hwndFilter) { - POINT pt; - GetCursorPos(&pt); - - RECT rcFilter; - GetWindowRect(m_hwndFilter, &rcFilter); - if (!PtInRect(&rcFilter, pt)) { - SendMessage(m_hwndFilter, WM_CLOSE, 1, 1); - m_hwndFilter = 0; - } - } - - if (m_bIsAutosizingInput && m_iInputAreaHeight == -1) { - m_iInputAreaHeight = 0; - m_message.SendMsg(EM_REQUESTRESIZE, 0, 0); - } - - m_pPanel.dismissConfig(); - m_dwUnread = 0; - if (m_pWnd) { - m_pWnd->activateTab(); - m_pWnd->setOverlayIcon(0, true); - } - - if (m_pContainer->hwndSaved == m_hwnd || m_bWasDeleted) - return; - - m_pContainer->hwndSaved = m_hwnd; - - pci->SetActiveSession(si->ptszID, si->pszModule); - m_hTabIcon = m_hTabStatusIcon; - - if (m_iTabID >= 0) { - if (db_get_w(si->hContact, si->pszModule, "ApparentMode", 0) != 0) - db_set_w(si->hContact, si->pszModule, "ApparentMode", 0); - if (pcli->pfnGetEvent(si->hContact, 0)) - pcli->pfnRemoveEvent(si->hContact, GC_FAKE_EVENT); - - SendMessage(m_hwnd, GC_UPDATETITLE, 0, 1); - m_dwTickLastEvent = 0; - m_dwFlags &= ~MWF_DIVIDERSET; - if (KillTimer(m_hwnd, TIMERID_FLASHWND) || m_iFlashIcon) { - FlashTab(false); - m_bCanFlashTab = FALSE; - m_iFlashIcon = 0; - } - if (m_pContainer->dwFlashingStarted != 0) { - FlashContainer(m_pContainer, 0, 0); - m_pContainer->dwFlashingStarted = 0; - } - m_pContainer->dwFlags &= ~CNT_NEED_UPDATETITLE; - - if (m_dwFlags & MWF_NEEDCHECKSIZE) - PostMessage(m_hwnd, DM_SAVESIZE, 0, 0); - - if (PluginConfig.m_bAutoLocaleSupport) { - if (hkl == 0) - DM_LoadLocale(); - else - SendMessage(m_hwnd, DM_SETLOCALE, 0, 0); - } - SetFocus(GetDlgItem(m_hwnd, IDC_MESSAGE)); - m_dwLastActivity = GetTickCount(); - m_pContainer->dwLastActivity = m_dwLastActivity; - m_pContainer->MenuBar->configureMenu(); - UpdateTrayMenuState(this, FALSE); - DM_SetDBButtonStates(); - - if (m_dwFlagsEx & MWF_EX_DELAYEDSPLITTER) { - m_dwFlagsEx &= ~MWF_EX_DELAYEDSPLITTER; - ShowWindow(m_pContainer->hwnd, SW_RESTORE); - PostMessage(m_hwnd, DM_SPLITTERGLOBALEVENT, m_wParam, m_lParam); - PostMessage(m_hwnd, WM_SIZE, 0, 0); - m_wParam = m_lParam = 0; - } - } - BB_SetButtonsPos(); - if (M.isAero()) - InvalidateRect(m_hwndParent, NULL, FALSE); - if (m_pContainer->dwFlags & CNT_SIDEBAR) - m_pContainer->SideBar->setActiveItem(this); - - if (m_pWnd) - m_pWnd->Invalidate(); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// resizer callback for the group chat session window.Called from Mirandas dialog -// resizing service - -int CChatRoomDlg::Resizer(UTILRESIZECONTROL *urc) -{ - bool bToolbar = !(m_pContainer->dwFlags & CNT_HIDETOOLBAR); - bool bBottomToolbar = (m_pContainer->dwFlags & CNT_BOTTOMTOOLBAR) != 0; - bool bNick = si->iType != GCW_SERVER && si->bNicklistEnabled; - bool bInfoPanel = m_pPanel.isActive(); - int panelHeight = m_pPanel.getHeight() + 1; - int iSplitterX = m_pContainer->settings->iSplitterX; - - RECT rcTabs; - GetClientRect(m_hwnd, &rcTabs); - - if (m_bIsAutosizingInput) - Utils::showDlgControl(m_hwnd, IDC_SPLITTERY, SW_HIDE); - - if (si->iType != GCW_SERVER) { - Utils::showDlgControl(m_hwnd, IDC_LIST, si->bNicklistEnabled ? SW_SHOW : SW_HIDE); - Utils::showDlgControl(m_hwnd, IDC_SPLITTERX, si->bNicklistEnabled ? SW_SHOW : SW_HIDE); - - m_btnNickList.Enable(true); - m_btnFilter.Enable(true); - if (si->iType == GCW_CHATROOM) { - MODULEINFO *tmp = pci->MM_FindModule(si->pszModule); - if (tmp) - m_btnChannelMgr.Enable(tmp->bChanMgr); - } - } - else { - Utils::showDlgControl(m_hwnd, IDC_LIST, SW_HIDE); - Utils::showDlgControl(m_hwnd, IDC_SPLITTERX, SW_HIDE); - } - - if (si->iType == GCW_SERVER) { - m_btnNickList.Enable(false); - m_btnFilter.Enable(false); - m_btnChannelMgr.Enable(false); - } - - switch (urc->wId) { - case IDC_PANELSPLITTER: - urc->rcItem.bottom = panelHeight; - urc->rcItem.top = panelHeight - 2; - return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP; - - case IDC_LOG: - urc->rcItem.top = 0; - urc->rcItem.left = 0; - urc->rcItem.right = bNick ? urc->dlgNewSize.cx - iSplitterX : urc->dlgNewSize.cx; - urc->rcItem.bottom = urc->dlgNewSize.cy - m_iSplitterY; - if (!bToolbar || bBottomToolbar) - urc->rcItem.bottom += DPISCALEY_S(21); - if (bInfoPanel) - urc->rcItem.top += panelHeight; - if (CSkin::m_skinEnabled) { - CSkinItem *item = &SkinItems[ID_EXTBKHISTORY]; - if (!item->IGNORED) { - urc->rcItem.left += item->MARGIN_LEFT; - urc->rcItem.right -= item->MARGIN_RIGHT; - urc->rcItem.top += item->MARGIN_TOP; - urc->rcItem.bottom -= item->MARGIN_BOTTOM; - } - } - return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; - - case IDC_LIST: - urc->rcItem.top = 0; - urc->rcItem.right = urc->dlgNewSize.cx; - urc->rcItem.left = urc->dlgNewSize.cx - iSplitterX + 2; - urc->rcItem.bottom = urc->dlgNewSize.cy - m_iSplitterY; - if (!bToolbar || bBottomToolbar) - urc->rcItem.bottom += DPISCALEY_S(21); - if (bInfoPanel) - urc->rcItem.top += panelHeight; - if (CSkin::m_skinEnabled) { - CSkinItem *item = &SkinItems[ID_EXTBKUSERLIST]; - if (!item->IGNORED) { - urc->rcItem.left += item->MARGIN_LEFT; - urc->rcItem.right -= item->MARGIN_RIGHT; - urc->rcItem.top += item->MARGIN_TOP; - urc->rcItem.bottom -= item->MARGIN_BOTTOM; - } - } - return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; - - case IDC_SPLITTERX: - urc->rcItem.right = urc->dlgNewSize.cx - iSplitterX + 2; - urc->rcItem.left = urc->dlgNewSize.cx - iSplitterX; - urc->rcItem.bottom = urc->dlgNewSize.cy - m_iSplitterY; - if (!bToolbar || bBottomToolbar) - urc->rcItem.bottom += DPISCALEY_S(21); - urc->rcItem.top = 0; - if (bInfoPanel) - urc->rcItem.top += panelHeight; - return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; - - case IDC_SPLITTERY: - urc->rcItem.right = urc->dlgNewSize.cx; - urc->rcItem.top = urc->dlgNewSize.cy - m_iSplitterY + DPISCALEY_S(23); - urc->rcItem.bottom = urc->rcItem.top + DPISCALEY_S(2); - urc->rcItem.left = 0; - urc->rcItem.bottom++; - urc->rcItem.top++; - return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; - - case IDC_MESSAGE: - urc->rcItem.right = urc->dlgNewSize.cx; - urc->rcItem.top = urc->dlgNewSize.cy - m_iSplitterY + 3 + DPISCALEY_S(23); - urc->rcItem.bottom = urc->dlgNewSize.cy; - if (bBottomToolbar && bToolbar) - urc->rcItem.bottom -= DPISCALEY_S(22); - - if (m_bIsAutosizingInput) - urc->rcItem.top -= DPISCALEY_S(1); - - if (CSkin::m_skinEnabled) { - CSkinItem *item = &SkinItems[ID_EXTBKINPUTAREA]; - if (!item->IGNORED) { - urc->rcItem.left += item->MARGIN_LEFT; - urc->rcItem.right -= item->MARGIN_RIGHT; - urc->rcItem.top += item->MARGIN_TOP; - urc->rcItem.bottom -= item->MARGIN_BOTTOM; - } - } - return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; - } - return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// subclassing for the message input control(a richedit text control) - -static bool TabAutoComplete(HWND hwnd, MESSAGESUBDATA *dat, SESSION_INFO *si) -{ - LRESULT lResult = (LRESULT)SendMessage(hwnd, EM_GETSEL, 0, 0); - int start = LOWORD(lResult), end = HIWORD(lResult); - SendMessage(hwnd, EM_SETSEL, end, end); - - GETTEXTEX gt = { 0 }; - gt.codepage = 1200; - gt.flags = GTL_DEFAULT | GTL_PRECISE; - int iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>, 0); - if (iLen <= 0) - return false; - - bool isTopic = false, isRoom = false; - wchar_t *pszName = NULL; - wchar_t *pszText = (wchar_t*)mir_calloc((iLen + 10) * sizeof(wchar_t)); - - gt.flags = GT_DEFAULT; - gt.cb = (iLen + 9) * sizeof(wchar_t); - SendMessage(hwnd, EM_GETTEXTEX, (WPARAM)>, (LPARAM)pszText); - - if (start > 1 && pszText[start - 1] == ' ' && pszText[start - 2] == ':') - start -= 2; - - if (dat->szSearchResult != NULL) { - int cbResult = (int)mir_wstrlen(dat->szSearchResult); - if (start >= cbResult && !wcsnicmp(dat->szSearchResult, pszText + start - cbResult, cbResult)) { - start -= cbResult; - goto LBL_SkipEnd; - } - } - - while (start > 0 && pszText[start - 1] != ' ' && pszText[start - 1] != 13 && pszText[start - 1] != VK_TAB) - start--; - -LBL_SkipEnd: - while (end < iLen && pszText[end] != ' ' && pszText[end] != 13 && pszText[end - 1] != VK_TAB) - end++; - - if (pszText[start] == '#') - isRoom = TRUE; - else { - int topicStart = start; - while (topicStart > 0 && (pszText[topicStart - 1] == ' ' || pszText[topicStart - 1] == 13 || pszText[topicStart - 1] == VK_TAB)) - topicStart--; - if (topicStart > 5 && wcsstr(&pszText[topicStart - 6], L"/topic") == &pszText[topicStart - 6]) - isTopic = TRUE; - } - if (dat->szSearchQuery == NULL) { - dat->szSearchQuery = mir_wstrndup(pszText + start, end - start); - dat->szSearchResult = mir_wstrdup(dat->szSearchQuery); - dat->lastSession = NULL; - } - if (isTopic) - pszName = si->ptszTopic; - else if (isRoom) { - dat->lastSession = SM_FindSessionAutoComplete(si->pszModule, si, dat->lastSession, dat->szSearchQuery, dat->szSearchResult); - if (dat->lastSession != NULL) - pszName = dat->lastSession->ptszName; - } - else pszName = pci->UM_FindUserAutoComplete(si->pUsers, dat->szSearchQuery, dat->szSearchResult); - - replaceStrW(dat->szSearchResult, NULL); - - if (pszName != NULL) { - dat->szSearchResult = mir_wstrdup(pszName); - if (end != start) { - ptrW szReplace; - if (!isRoom && !isTopic && g_Settings.bAddColonToAutoComplete && start == 0) { - szReplace = (wchar_t*)mir_alloc((mir_wstrlen(pszName) + 4) * sizeof(wchar_t)); - mir_wstrcpy(szReplace, pszName); - mir_wstrcat(szReplace, g_Settings.bUseCommaAsColon ? L", " : L": "); - pszName = szReplace; - } - SendMessage(hwnd, EM_SETSEL, start, end); - SendMessage(hwnd, EM_REPLACESEL, TRUE, (LPARAM)pszName); - } - return true; - } - - if (end != start) { - SendMessage(hwnd, EM_SETSEL, start, end); - SendMessage(hwnd, EM_REPLACESEL, TRUE, (LPARAM)dat->szSearchQuery); - } - replaceStrW(dat->szSearchQuery, NULL); - return false; -} - -static LRESULT CALLBACK MessageSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HWND hwndParent = GetParent(hwnd); - CChatRoomDlg *mwdat = (CChatRoomDlg*)GetWindowLongPtr(hwndParent, GWLP_USERDATA); - MESSAGESUBDATA *dat = (MESSAGESUBDATA*)GetWindowLongPtr(hwnd, GWLP_USERDATA); - - if (mwdat != nullptr) - if (mwdat->m_fkeyProcessed && (msg == WM_KEYUP)) { - GetKeyboardState(mwdat->kstate); - if (!(mwdat->kstate[VK_CONTROL] & 0x80) && !(mwdat->kstate[VK_SHIFT] & 0x80)) - mwdat->m_fkeyProcessed = false; - return 0; - } - - switch (msg) { - case WM_NCCALCSIZE: - return CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKINPUTAREA, msg, wParam, lParam, MessageSubclassProc); - - case WM_NCPAINT: - return CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKINPUTAREA, msg, wParam, lParam, MessageSubclassProc); - - case EM_SUBCLASSED: - dat = (MESSAGESUBDATA*)mir_calloc(sizeof(MESSAGESUBDATA)); - SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dat); - return 0; - - case WM_CONTEXTMENU: - POINT pt; - GetCursorPos(&pt); - { - HMENU hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)); - HMENU hSubMenu = GetSubMenu(hMenu, 2); - RemoveMenu(hSubMenu, 9, MF_BYPOSITION); - RemoveMenu(hSubMenu, 8, MF_BYPOSITION); - RemoveMenu(hSubMenu, 4, MF_BYPOSITION); - - MODULEINFO *mi = pci->MM_FindModule(mwdat->si->pszModule); - EnableMenuItem(hSubMenu, IDM_PASTEFORMATTED, MF_BYCOMMAND | ((mi && mi->bBold) ? MF_ENABLED : MF_GRAYED)); - TranslateMenu(hSubMenu); - - CHARRANGE sel, all = { 0, -1 }; - SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); - if (sel.cpMin == sel.cpMax) { - EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(hSubMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED); - } - - MessageWindowPopupData mwpd = { sizeof(mwpd) }; - mwpd.uType = MSG_WINDOWPOPUP_SHOWING; - mwpd.uFlags = MSG_WINDOWPOPUP_INPUT; - mwpd.hContact = mwdat->m_hContact; - mwpd.hwnd = hwnd; - mwpd.hMenu = hSubMenu; - mwpd.pt = pt; - NotifyEventHooks(PluginConfig.m_event_MsgPopup, 0, (LPARAM)&mwpd); - - int iSelection = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, GetParent(hwnd), NULL); - - mwpd.selection = iSelection; - mwpd.uType = MSG_WINDOWPOPUP_SELECTED; - NotifyEventHooks(PluginConfig.m_event_MsgPopup, 0, (LPARAM)&mwpd); - - switch (iSelection) { - case IDM_COPY: - SendMessage(hwnd, WM_COPY, 0, 0); - break; - case IDM_CUT: - SendMessage(hwnd, WM_CUT, 0, 0); - break; - case IDM_PASTE: - case IDM_PASTEFORMATTED: - SendMessage(hwnd, EM_PASTESPECIAL, (iSelection == IDM_PASTE) ? CF_UNICODETEXT : 0, 0); - break; - case IDM_COPYALL: - SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&all); - SendMessage(hwnd, WM_COPY, 0, 0); - SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); - break; - case IDM_SELECTALL: - SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&all); - break; - } - DestroyMenu(hMenu); - } - return TRUE; - - case WM_MOUSEWHEEL: - if (mwdat->DM_MouseWheelHandler(wParam, lParam) == 0) - return 0; - - dat->lastEnterTime = 0; - break; - - case WM_SYSKEYUP: - if (wParam == VK_MENU) { - ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_MESSAGE); - return 0; - } - break; - - case WM_SYSKEYDOWN: - mwdat->m_fkeyProcessed = false; - if (ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_MESSAGE)) { - mwdat->m_fkeyProcessed = true; - return 0; - } - break; - - case WM_SYSCHAR: - if (mwdat->m_fkeyProcessed) { - mwdat->m_fkeyProcessed = false; // preceeding key event has been processed by miranda hotkey service - return 0; - } - - if ((wParam >= '0' && wParam <= '9') && (GetKeyState(VK_MENU) & 0x8000)) { // ALT-1 -> ALT-0 direct tab selection - BYTE bChar = (BYTE)wParam; - int iIndex = (bChar == '0') ? 10 : bChar - (BYTE)'0'; - SendMessage(mwdat->m_pContainer->hwnd, DM_SELECTTAB, DM_SELECT_BY_INDEX, (LPARAM)iIndex); - return 0; - } - break; - - case WM_CHAR: - bool isShift, isAlt, isCtrl; - mwdat->KbdState(isShift, isCtrl, isAlt); - - if (PluginConfig.m_bSoundOnTyping && !isAlt &&!isCtrl&&!(mwdat->m_pContainer->dwFlags & CNT_NOSOUND) && wParam != VK_ESCAPE&&!(wParam == VK_TAB && PluginConfig.m_bAllowTab)) - SkinPlaySound("SoundOnTyping"); - - if (isCtrl && !isAlt && !isShift) { - MODULEINFO *mi = pci->MM_FindModule(mwdat->si->pszModule); - if (mi == NULL) - return 0; - - switch (wParam) { - case 0x09: // ctrl-i (italics) - if (mi->bItalics) { - CheckDlgButton(hwndParent, IDC_ITALICS, IsDlgButtonChecked(hwndParent, IDC_ITALICS) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED); - SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_ITALICS, 0), 0); - } - return 0; - case 0x02: // ctrl-b (bold) - if (mi->bBold) { - CheckDlgButton(hwndParent, IDC_BOLD, IsDlgButtonChecked(hwndParent, IDC_BOLD) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED); - SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_BOLD, 0), 0); - } - return 0; - case 0x20: // ctrl-space clear formatting - if (mi->bBold && mi->bItalics && mi->bUnderline) { - CheckDlgButton(hwndParent, IDC_BKGCOLOR, BST_UNCHECKED); - CheckDlgButton(hwndParent, IDC_COLOR, BST_UNCHECKED); - CheckDlgButton(hwndParent, IDC_BOLD, BST_UNCHECKED); - CheckDlgButton(hwndParent, IDC_UNDERLINE, BST_UNCHECKED); - CheckDlgButton(hwndParent, IDC_ITALICS, BST_UNCHECKED); - SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_BKGCOLOR, 0), 0); - SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_COLOR, 0), 0); - SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_BOLD, 0), 0); - SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_UNDERLINE, 0), 0); - SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_ITALICS, 0), 0); - } - return 0; - case 0x0c: // ctrl-l background color - if (mi->bBkgColor) { - CheckDlgButton(hwndParent, IDC_BKGCOLOR, IsDlgButtonChecked(hwndParent, IDC_BKGCOLOR) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED); - SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_BKGCOLOR, 0), 0); - } - return 0; - case 0x15: // ctrl-u underlined - if (mi->bUnderline) { - CheckDlgButton(hwndParent, IDC_UNDERLINE, IsDlgButtonChecked(hwndParent, IDC_UNDERLINE) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED); - SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_UNDERLINE, 0), 0); - } - return 0; // ctrl-k color - case 0x0b: - if (mi->bColor) { - CheckDlgButton(hwndParent, IDC_COLOR, IsDlgButtonChecked(hwndParent, IDC_COLOR) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED); - SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_COLOR, 0), 0); - } - return 0; - case 0x17: - PostMessage(hwndParent, WM_CLOSE, 0, 1); - return 0; - } - } - break; - - case WM_KEYDOWN: - mwdat->KbdState(isShift, isCtrl, isAlt); - - // sound on typing.. - if (PluginConfig.m_bSoundOnTyping && !isAlt && wParam == VK_DELETE) - SkinPlaySound("SoundOnTyping"); - - if (wParam == VK_INSERT && !isShift && !isCtrl && !isAlt) { - mwdat->m_fInsertMode = !mwdat->m_fInsertMode; - SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM)hwnd); - } - if (wParam == VK_CAPITAL || wParam == VK_NUMLOCK) - SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM)hwnd); - - if (isCtrl && isAlt && !isShift) { - switch (wParam) { - case VK_UP: - case VK_DOWN: - case VK_PRIOR: - case VK_NEXT: - case VK_HOME: - case VK_END: - WPARAM wp = 0; - - if (wParam == VK_UP) - wp = MAKEWPARAM(SB_LINEUP, 0); - else if (wParam == VK_PRIOR) - wp = MAKEWPARAM(SB_PAGEUP, 0); - else if (wParam == VK_NEXT) - wp = MAKEWPARAM(SB_PAGEDOWN, 0); - else if (wParam == VK_HOME) - wp = MAKEWPARAM(SB_TOP, 0); - else if (wParam == VK_END) { - mwdat->DM_ScrollToBottom(0, 0); - return 0; - } - else if (wParam == VK_DOWN) - wp = MAKEWPARAM(SB_LINEDOWN, 0); - - SendDlgItemMessage(hwndParent, IDC_LOG, WM_VSCROLL, wp, 0); - return 0; - } - } - - if (wParam == VK_RETURN) { - if (isShift) { - if (PluginConfig.m_bSendOnShiftEnter) { - PostMessage(hwndParent, WM_COMMAND, IDOK, 0); - return 0; - } - break; - } - if ((isCtrl && !isShift) ^ (0 != PluginConfig.m_bSendOnEnter)) { - PostMessage(hwndParent, WM_COMMAND, IDOK, 0); - return 0; - } - if (!PluginConfig.m_bSendOnEnter && !PluginConfig.m_bSendOnDblEnter) - break; - if (isCtrl) - break; - - if (PluginConfig.m_bSendOnDblEnter) { - if (dat->lastEnterTime + 2 < time(NULL)) { - dat->lastEnterTime = time(NULL); - break; - } - - SendMessage(hwnd, WM_KEYDOWN, VK_BACK, 0); - SendMessage(hwnd, WM_KEYUP, VK_BACK, 0); - PostMessage(hwndParent, WM_COMMAND, IDOK, 0); - return 0; - } - PostMessage(hwndParent, WM_COMMAND, IDOK, 0); - return 0; - } - else dat->lastEnterTime = 0; - - if ((wParam == VK_NEXT && isCtrl && !isShift) || (wParam == VK_TAB && isCtrl && !isShift)) { // CTRL-TAB (switch tab/window) - SendMessage(mwdat->m_pContainer->hwnd, DM_SELECTTAB, DM_SELECT_NEXT, 0); - return TRUE; - } - - if ((wParam == VK_PRIOR && isCtrl && !isShift) || (wParam == VK_TAB && isCtrl && isShift)) { // CTRL_SHIFT-TAB (switch tab/window) - SendMessage(mwdat->m_pContainer->hwnd, DM_SELECTTAB, DM_SELECT_PREV, 0); - return TRUE; - } - if (wParam == VK_TAB && !isCtrl && !isShift) { //tab-autocomplete - SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); - bool fCompleted = TabAutoComplete(hwnd, dat, mwdat->si); - SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); - RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); - if (!fCompleted && !PluginConfig.m_bAllowTab) { - if ((GetSendButtonState(mwdat->GetHwnd()) != PBS_DISABLED)) - SetFocus(GetDlgItem(mwdat->GetHwnd(), IDOK)); - else - SetFocus(GetDlgItem(mwdat->GetHwnd(), IDC_LOG)); - } - return 0; - } - if (wParam != VK_RIGHT && wParam != VK_LEFT) { - mir_free(dat->szSearchQuery); - dat->szSearchQuery = NULL; - mir_free(dat->szSearchResult); - dat->szSearchResult = NULL; - } - - if (wParam == VK_F4 && isCtrl && !isAlt) { // ctrl-F4 (close tab) - SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_CLOSE, BN_CLICKED), 0); - return 0; - } - - if (wParam == VK_NEXT || wParam == VK_PRIOR) { - HWND htemp = hwndParent; - SendDlgItemMessage(htemp, IDC_LOG, msg, wParam, lParam); - dat->lastEnterTime = 0; - return 0; - } - - if (wParam == VK_UP && isCtrl && !isAlt) { - char *lpPrevCmd = pci->SM_GetPrevCommand(mwdat->si->ptszID, mwdat->si->pszModule); - - if (!mwdat->si->lpCurrentCommand || !mwdat->si->lpCurrentCommand->last) { - // Next command is not defined. It means currently entered text is not saved in the history and it - // need to be saved in the window context. - char *enteredText = Message_GetFromStream(hwndParent); - if (mwdat->m_enteredText) - mir_free(mwdat->m_enteredText); - - mwdat->m_enteredText = enteredText; - } - - SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); - - LOGFONTA lf; - LoadLogfont(MSGFONTID_MESSAGEAREA, &lf, NULL, FONTMODULE); - - SETTEXTEX ste; - ste.flags = ST_DEFAULT; - ste.codepage = CP_ACP; - if (lpPrevCmd) - SendMessage(hwnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)lpPrevCmd); - else - SetWindowText(hwnd, L""); - - GETTEXTLENGTHEX gtl = { 0 }; - gtl.flags = GTL_PRECISE; - gtl.codepage = CP_ACP; - int iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>l, 0); - SendMessage(hwnd, EM_SCROLLCARET, 0, 0); - SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); - RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); - SendMessage(hwnd, EM_SETSEL, iLen, iLen); - dat->lastEnterTime = 0; - return 0; - } - - if (wParam == VK_DOWN && isCtrl && !isAlt) { - SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); - - SETTEXTEX ste; - ste.flags = ST_DEFAULT; - ste.codepage = CP_ACP; - - char *lpPrevCmd = pci->SM_GetNextCommand(mwdat->si->ptszID, mwdat->si->pszModule); - if (lpPrevCmd) - SendMessage(hwnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)lpPrevCmd); - else if (mwdat->m_enteredText) { - // If we cannot load the message from history, load the last edited text. - SendMessage(hwnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)mwdat->m_enteredText); - mir_free(mwdat->m_enteredText); - mwdat->m_enteredText = NULL; - } - - GETTEXTLENGTHEX gtl = { 0 }; - gtl.flags = GTL_PRECISE; - gtl.codepage = CP_ACP; - int iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>l, 0); - SendMessage(hwnd, EM_SCROLLCARET, 0, 0); - SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); - RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); - SendMessage(hwnd, EM_SETSEL, iLen, iLen); - dat->lastEnterTime = 0; - return 0; - } - // fall through - - case WM_LBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_KILLFOCUS: - dat->lastEnterTime = 0; - break; - - case WM_KEYUP: - case WM_LBUTTONUP: - case WM_RBUTTONUP: - case WM_MBUTTONUP: - COLORREF cr; - LoadLogfont(MSGFONTID_MESSAGEAREA, NULL, &cr, FONTMODULE); - - CHARFORMAT2 cf; - cf.cbSize = sizeof(CHARFORMAT2); - cf.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_BACKCOLOR | CFM_COLOR | CFM_UNDERLINETYPE; - cf.dwEffects = 0; - SendMessage(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); - { - MODULEINFO *mi = pci->MM_FindModule(mwdat->si->pszModule); - if (mi == NULL) - break; - - if (mi->bColor) { - int index = Chat_GetColorIndex(mwdat->si->pszModule, cf.crTextColor); - UINT u = IsDlgButtonChecked(GetParent(hwnd), IDC_COLOR); - - if (index >= 0) { - mwdat->si->bFGSet = TRUE; - mwdat->si->iFG = index; - } - - if (u == BST_UNCHECKED && cf.crTextColor != cr) - CheckDlgButton(hwndParent, IDC_COLOR, BST_CHECKED); - else if (u == BST_CHECKED && cf.crTextColor == cr) - CheckDlgButton(hwndParent, IDC_COLOR, BST_UNCHECKED); - } - - if (mi->bBkgColor) { - int index = Chat_GetColorIndex(mwdat->si->pszModule, cf.crBackColor); - COLORREF crB = (COLORREF)M.GetDword(FONTMODULE, "inputbg", SRMSGDEFSET_BKGCOLOUR); - UINT u = IsDlgButtonChecked(hwndParent, IDC_BKGCOLOR); - - if (index >= 0) { - mwdat->si->bBGSet = TRUE; - mwdat->si->iBG = index; - } - - if (u == BST_UNCHECKED && cf.crBackColor != crB) - CheckDlgButton(hwndParent, IDC_BKGCOLOR, BST_CHECKED); - else if (u == BST_CHECKED && cf.crBackColor == crB) - CheckDlgButton(hwndParent, IDC_BKGCOLOR, BST_UNCHECKED); - } - - if (mi->bBold) { - UINT u = IsDlgButtonChecked(hwndParent, IDC_BOLD); - UINT u2 = cf.dwEffects; - u2 &= CFE_BOLD; - if (u == BST_UNCHECKED && u2) - CheckDlgButton(hwndParent, IDC_BOLD, BST_CHECKED); - else if (u == BST_CHECKED && u2 == 0) - CheckDlgButton(hwndParent, IDC_BOLD, BST_UNCHECKED); - } - - if (mi->bItalics) { - UINT u = IsDlgButtonChecked(hwndParent, IDC_ITALICS); - UINT u2 = cf.dwEffects; - u2 &= CFE_ITALIC; - if (u == BST_UNCHECKED && u2) - CheckDlgButton(hwndParent, IDC_ITALICS, BST_CHECKED); - else if (u == BST_CHECKED && u2 == 0) - CheckDlgButton(hwndParent, IDC_ITALICS, BST_UNCHECKED); - } - - if (mi->bUnderline) { - UINT u = IsDlgButtonChecked(hwndParent, IDC_UNDERLINE); - if (cf.dwEffects & CFE_UNDERLINE && (cf.bUnderlineType & CFU_UNDERLINE || cf.bUnderlineType & CFU_UNDERLINEWORD)) { - if (u == BST_UNCHECKED) - CheckDlgButton(hwndParent, IDC_UNDERLINE, BST_CHECKED); - } - else { - if (u == BST_CHECKED) - CheckDlgButton(hwndParent, IDC_UNDERLINE, BST_UNCHECKED); - } - } - } - break; - - case WM_INPUTLANGCHANGE: - if (PluginConfig.m_bAutoLocaleSupport && GetFocus() == hwnd && mwdat->m_pContainer->hwndActive == hwndParent && GetForegroundWindow() == mwdat->m_pContainer->hwnd && GetActiveWindow() == mwdat->m_pContainer->hwnd) { - mwdat->DM_SaveLocale(wParam, lParam); - SendMessage(hwnd, EM_SETLANGOPTIONS, 0, (LPARAM)SendMessage(hwnd, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD); - return 1; - } - break; - - case WM_ERASEBKGND: - return !CSkin::m_skinEnabled; - - case WM_DESTROY: - mir_free(dat); - } - - return mir_callNextSubclass(hwnd, MessageSubclassProc, msg, wParam, lParam); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// subclassing for the message filter dialog (set and configure event filters for the -// current session - -static UINT _eventorder[] = -{ - GC_EVENT_ACTION, - GC_EVENT_MESSAGE, - GC_EVENT_NICK, - GC_EVENT_JOIN, - GC_EVENT_PART, - GC_EVENT_TOPIC, - GC_EVENT_ADDSTATUS, - GC_EVENT_INFORMATION, - GC_EVENT_QUIT, - GC_EVENT_KICK, - GC_EVENT_NOTICE -}; - -static INT_PTR CALLBACK FilterWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - SESSION_INFO *si = (SESSION_INFO*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - switch (uMsg) { - case WM_INITDIALOG: - si = (SESSION_INFO*)lParam; - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)si); - { - DWORD dwMask = db_get_dw(si->hContact, CHAT_MODULE, "FilterMask", 0); - DWORD dwFlags = db_get_dw(si->hContact, CHAT_MODULE, "FilterFlags", 0); - - DWORD dwPopupMask = db_get_dw(si->hContact, CHAT_MODULE, "PopupMask", 0); - DWORD dwPopupFlags = db_get_dw(si->hContact, CHAT_MODULE, "PopupFlags", 0); - - DWORD dwTrayMask = db_get_dw(si->hContact, CHAT_MODULE, "TrayIconMask", 0); - DWORD dwTrayFlags = db_get_dw(si->hContact, CHAT_MODULE, "TrayIconFlags", 0); - - for (int i = 0; i < _countof(_eventorder); i++) { - CheckDlgButton(hwndDlg, IDC_1 + i, dwMask & _eventorder[i] ? (dwFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED) : BST_INDETERMINATE); - CheckDlgButton(hwndDlg, IDC_P1 + i, dwPopupMask & _eventorder[i] ? (dwPopupFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED) : BST_INDETERMINATE); - CheckDlgButton(hwndDlg, IDC_T1 + i, dwTrayMask & _eventorder[i] ? (dwTrayFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED) : BST_INDETERMINATE); - } - } - return FALSE; - - case WM_CTLCOLOREDIT: - case WM_CTLCOLORSTATIC: - SetTextColor((HDC)wParam, RGB(60, 60, 150)); - SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW)); - return (INT_PTR)GetSysColorBrush(COLOR_WINDOW); - - case WM_CLOSE: - if (wParam == 1 && lParam == 1) { - int iFlags = 0, i; - DWORD dwMask = 0; - - for (i = 0; i < _countof(_eventorder); i++) { - int result = IsDlgButtonChecked(hwndDlg, IDC_1 + i); - dwMask |= (result != BST_INDETERMINATE ? _eventorder[i] : 0); - iFlags |= (result == BST_CHECKED ? _eventorder[i] : 0); - } - - if (iFlags&GC_EVENT_ADDSTATUS) - iFlags |= GC_EVENT_REMOVESTATUS; - - if (si) { - if (dwMask == 0) { - db_unset(si->hContact, CHAT_MODULE, "FilterFlags"); - db_unset(si->hContact, CHAT_MODULE, "FilterMask"); - } - else { - db_set_dw(si->hContact, CHAT_MODULE, "FilterFlags", iFlags); - db_set_dw(si->hContact, CHAT_MODULE, "FilterMask", dwMask); - } - } - - dwMask = iFlags = 0; - - for (i = 0; i < _countof(_eventorder); i++) { - int result = IsDlgButtonChecked(hwndDlg, IDC_P1 + i); - dwMask |= (result != BST_INDETERMINATE ? _eventorder[i] : 0); - iFlags |= (result == BST_CHECKED ? _eventorder[i] : 0); - } - - if (iFlags & GC_EVENT_ADDSTATUS) - iFlags |= GC_EVENT_REMOVESTATUS; - - if (si) { - if (dwMask == 0) { - db_unset(si->hContact, CHAT_MODULE, "PopupFlags"); - db_unset(si->hContact, CHAT_MODULE, "PopupMask"); - } - else { - db_set_dw(si->hContact, CHAT_MODULE, "PopupFlags", iFlags); - db_set_dw(si->hContact, CHAT_MODULE, "PopupMask", dwMask); - } - } - - dwMask = iFlags = 0; - - for (i = 0; i < _countof(_eventorder); i++) { - int result = IsDlgButtonChecked(hwndDlg, IDC_T1 + i); - dwMask |= (result != BST_INDETERMINATE ? _eventorder[i] : 0); - iFlags |= (result == BST_CHECKED ? _eventorder[i] : 0); - } - if (iFlags & GC_EVENT_ADDSTATUS) - iFlags |= GC_EVENT_REMOVESTATUS; - - if (si) { - if (dwMask == 0) { - db_unset(si->hContact, CHAT_MODULE, "TrayIconFlags"); - db_unset(si->hContact, CHAT_MODULE, "TrayIconMask"); - } - else { - db_set_dw(si->hContact, CHAT_MODULE, "TrayIconFlags", iFlags); - db_set_dw(si->hContact, CHAT_MODULE, "TrayIconMask", dwMask); - } - Chat_SetFilters(si); - SendMessage(si->hWnd, GC_CHANGEFILTERFLAG, 0, iFlags); - if (si->bFilterEnabled) - SendMessage(si->hWnd, GC_REDRAWLOG, 0, 0); - } - } - DestroyWindow(hwndDlg); - break; - - case WM_DESTROY: - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); - break; - } - return FALSE; -} - -///////////////////////////////////////////////////////////////////////////////////////// -// subclass for some tool bar buttons which must perform special actions -// on right click. - -static LRESULT CALLBACK ButtonSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_RBUTTONUP: - if (M.GetByte(CHAT_MODULE, "RightClickFilter", 0) != 0) { - HWND hwndParent = GetParent(hwnd); - switch (GetDlgCtrlID(hwnd)) { - case IDC_FILTER: - SendMessage(hwndParent, GC_SHOWFILTERMENU, 0, 0); - break; - case IDC_COLOR: - SendMessage(hwndParent, GC_SHOWCOLORCHOOSER, 0, IDC_COLOR); - break; - case IDC_BKGCOLOR: - SendMessage(hwndParent, GC_SHOWCOLORCHOOSER, 0, IDC_BKGCOLOR); - } - } - break; - } - - return mir_callNextSubclass(hwnd, ButtonSubclassProc, msg, wParam, lParam); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// subclassing for the message history display(rich edit control in which the chat history appears) - -static LRESULT CALLBACK LogSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HWND hwndParent = GetParent(hwnd); - CChatRoomDlg *mwdat = (CChatRoomDlg*)GetWindowLongPtr(hwndParent, GWLP_USERDATA); - - switch (msg) { - case WM_NCCALCSIZE: - return CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, LogSubclassProc); - - case WM_NCPAINT: - return CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, LogSubclassProc); - - case WM_COPY: - return Utils::WMCopyHandler(hwnd, LogSubclassProc, msg, wParam, lParam); - - case WM_SETCURSOR: - if (g_Settings.bClickableNicks && (LOWORD(lParam) == HTCLIENT)) { - POINT pt; - GetCursorPos(&pt); - ScreenToClient(hwnd, &pt); - if (CheckCustomLink(hwnd, &pt, msg, wParam, lParam, FALSE)) return TRUE; - } - break; - - case WM_LBUTTONDOWN: - case WM_LBUTTONDBLCLK: - case WM_RBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONDBLCLK: - if (g_Settings.bClickableNicks) { - POINT pt = { LOWORD(lParam), HIWORD(lParam) }; - CheckCustomLink(hwnd, &pt, msg, wParam, lParam, TRUE); - } - break; - - case WM_LBUTTONUP: - if (g_Settings.bClickableNicks) { - POINT pt = { LOWORD(lParam), HIWORD(lParam) }; - CheckCustomLink(hwnd, &pt, msg, wParam, lParam, TRUE); - } - if (M.GetByte("autocopy", 1)) { - CHARRANGE sel; - SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); - if (sel.cpMin != sel.cpMax) { - SendMessage(hwnd, WM_COPY, 0, 0); - sel.cpMin = sel.cpMax; - SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); - SetFocus(GetDlgItem(hwndParent, IDC_MESSAGE)); - } - } - break; - - case WM_KEYDOWN: - if (wParam == 0x57 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w (close window) - PostMessage(hwndParent, WM_CLOSE, 0, 1); - return TRUE; - } - if (wParam == VK_INSERT && GetKeyState(VK_CONTROL) & 0x8000) - return Utils::WMCopyHandler(hwnd, LogSubclassProc, msg, wParam, lParam); - break; - - case WM_SYSKEYUP: - if (wParam == VK_MENU) { - ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_LOG); - return 0; - } - break; - - case WM_SYSKEYDOWN: - mwdat->m_fkeyProcessed = false; - if (ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_LOG)) { - mwdat->m_fkeyProcessed = true; - return 0; - } - break; - - case WM_SYSCHAR: - if (mwdat->m_fkeyProcessed) { - mwdat->m_fkeyProcessed = false; - return 0; - } - break; - - case WM_ACTIVATE: - if (LOWORD(wParam) == WA_INACTIVE) { - CHARRANGE sel; - SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); - if (sel.cpMin != sel.cpMax) { - sel.cpMin = sel.cpMax; - SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); - } - } - break; - - case WM_CHAR: - bool isCtrl, isShift, isAlt; - mwdat->KbdState(isShift, isCtrl, isAlt); - if (wParam == 0x03 && isCtrl) // Ctrl+C - return Utils::WMCopyHandler(hwnd, LogSubclassProc, msg, wParam, lParam); - - SetFocus(GetDlgItem(hwndParent, IDC_MESSAGE)); - SendDlgItemMessage(hwndParent, IDC_MESSAGE, WM_CHAR, wParam, lParam); - break; - } - - return mir_callNextSubclass(hwnd, LogSubclassProc, msg, wParam, lParam); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// subclassing for the nickname list control.It is an ownerdrawn listbox - -static LRESULT CALLBACK NicklistSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HWND hwndParent = GetParent(hwnd); - CChatRoomDlg *dat = (CChatRoomDlg*)GetWindowLongPtr(hwndParent, GWLP_USERDATA); - - switch (msg) { - case WM_NCCALCSIZE: - if (CSkin::m_DisableScrollbars) { - RECT lpRect; - GetClientRect(hwnd, &lpRect); - LONG itemHeight = SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0); - g_cLinesPerPage = (lpRect.bottom - lpRect.top) / itemHeight; - } - return CSkin::NcCalcRichEditFrame(hwnd, dat, ID_EXTBKUSERLIST, msg, wParam, lParam, NicklistSubclassProc); - - case WM_NCPAINT: - return CSkin::DrawRichEditFrame(hwnd, dat, ID_EXTBKUSERLIST, msg, wParam, lParam, NicklistSubclassProc); - - case WM_ERASEBKGND: - { - HDC dc = (HDC)wParam; - if (dc) { - int index = SendMessage(hwnd, LB_GETTOPINDEX, 0, 0); - if (index == LB_ERR || dat->si->nUsersInNicklist <= 0) - return 0; - - int items = dat->si->nUsersInNicklist - index; - int height = SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0); - - if (height != LB_ERR) { - RECT rc = { 0 }; - GetClientRect(hwnd, &rc); - - if (rc.bottom - rc.top > items * height) { - rc.top = items * height; - FillRect(dc, &rc, pci->hListBkgBrush); - } - } - } - } - return 1; - - case WM_MOUSEWHEEL: - if (CSkin::m_DisableScrollbars) { - UINT uScroll; - short zDelta = (short)HIWORD(wParam); - if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &uScroll, 0)) - uScroll = 3; /* default value */ - - if (uScroll == WHEEL_PAGESCROLL) - uScroll = g_cLinesPerPage; - if (uScroll == 0) - return 0; - - zDelta += g_iWheelCarryover; /* Accumulate wheel motion */ - - int dLines = zDelta * (int)uScroll / WHEEL_DELTA; - - //Record the unused portion as the next carryover. - g_iWheelCarryover = zDelta - dLines * WHEEL_DELTA / (int)uScroll; - - // scrolling. - while (abs(dLines)) { - if (dLines > 0) { - SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0); - dLines--; - } - else { - SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0); - dLines++; - } - } - return 0; - } - break; - - case WM_KEYDOWN: - if (wParam == 0x57 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w (close window) - PostMessage(hwndParent, WM_CLOSE, 0, 1); - return TRUE; - } - - if (wParam == VK_ESCAPE || wParam == VK_UP || wParam == VK_DOWN || wParam == VK_NEXT || - wParam == VK_PRIOR || wParam == VK_TAB || wParam == VK_HOME || wParam == VK_END) { - if (dat) { - dat->m_wszSearch[0] = 0; - dat->m_iSearchItem = -1; - } - } - break; - - case WM_SETFOCUS: - case WM_KILLFOCUS: - if (dat) { // set/kill focus invalidates incremental search status - dat->m_wszSearch[0] = 0; - dat->m_iSearchItem = -1; - } - break; - - case WM_CHAR: - case WM_UNICHAR: - // simple incremental search for the user (nick) - list control - // typing esc or movement keys will clear the current search string - if (dat) { - if (wParam == 27 && dat->m_wszSearch[0]) { // escape - reset everything - dat->m_wszSearch[0] = 0; - dat->m_iSearchItem = -1; - break; - } - if (wParam == '\b' && dat->m_wszSearch[0]) // backspace - dat->m_wszSearch[mir_wstrlen(dat->m_wszSearch) - 1] = '\0'; - else if (wParam < ' ') - break; - else { - if (mir_wstrlen(dat->m_wszSearch) >= _countof(dat->m_wszSearch) - 2) { - MessageBeep(MB_OK); - break; - } - wchar_t szNew[2]; - szNew[0] = (wchar_t)wParam; - szNew[1] = '\0'; - mir_wstrcat(dat->m_wszSearch, szNew); - } - if (dat->m_wszSearch[0]) { - // iterate over the (sorted) list of nicknames and search for the - // string we have - int i, iItems = SendMessage(hwnd, LB_GETCOUNT, 0, 0); - for (i = 0; i < iItems; i++) { - USERINFO *ui = pci->UM_FindUserFromIndex(dat->si->pUsers, i); - if (ui) { - if (!wcsnicmp(ui->pszNick, dat->m_wszSearch, mir_wstrlen(dat->m_wszSearch))) { - SendMessage(hwnd, LB_SETSEL, FALSE, -1); - SendMessage(hwnd, LB_SETSEL, TRUE, i); - dat->m_iSearchItem = i; - InvalidateRect(hwnd, NULL, FALSE); - return 0; - } - } - } - if (i == iItems) { - MessageBeep(MB_OK); - dat->m_wszSearch[mir_wstrlen(dat->m_wszSearch) - 1] = '\0'; - return 0; - } - } - } - break; - - case WM_RBUTTONDOWN: - { - int iCounts = SendMessage(hwnd, LB_GETSELCOUNT, 0, 0); - if (iCounts != LB_ERR && iCounts > 1) - return 0; - SendMessage(hwnd, WM_LBUTTONDOWN, wParam, lParam); - } - break; - - case WM_RBUTTONUP: - SendMessage(hwnd, WM_LBUTTONUP, wParam, lParam); - break; - - case WM_MEASUREITEM: - { - MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam; - if (mis->CtlType == ODT_MENU) - return Menu_MeasureItem(lParam); - } - return FALSE; - - case WM_DRAWITEM: - { - DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam; - if (dis->CtlType == ODT_MENU) - return Menu_DrawItem(lParam); - } - return FALSE; - - case WM_CONTEXTMENU: - { - SESSION_INFO *si = dat->si; - if (si == NULL) - break; - - int height = 0; - TVHITTESTINFO hti; - hti.pt.x = GET_X_LPARAM(lParam); - hti.pt.y = GET_Y_LPARAM(lParam); - if (hti.pt.x == -1 && hti.pt.y == -1) { - int index = SendMessage(hwnd, LB_GETCURSEL, 0, 0); - int top = SendMessage(hwnd, LB_GETTOPINDEX, 0, 0); - height = SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0); - hti.pt.x = 4; - hti.pt.y = (index - top) * height + 1; - } - else ScreenToClient(hwnd, &hti.pt); - - int item = (DWORD)(SendMessage(hwnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(hti.pt.x, hti.pt.y))); - if (HIWORD(item) == 1) - item = (DWORD)(-1); - else - item &= 0xFFFF; - - USERINFO *ui = pci->SM_GetUserFromIndex(si->ptszID, si->pszModule, item); - if (ui) { - HMENU hMenu = 0; - USERINFO uinew; - memcpy(&uinew, ui, sizeof(USERINFO)); - if (hti.pt.x == -1 && hti.pt.y == -1) - hti.pt.y += height - 4; - ClientToScreen(hwnd, &hti.pt); - - UINT uID = CreateGCMenu(hwnd, &hMenu, 0, hti.pt, si, uinew.pszUID, uinew.pszNick); - switch (uID) { - case 0: - break; - - case 20020: // add to highlight... - { - THighLightEdit the = { THighLightEdit::CMD_ADD, si, ui }; - HWND hwndDlg = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_ADDHIGHLIGHT), dat->m_pContainer->hwnd, CMUCHighlight::dlgProcAdd, (LPARAM)&the); - TranslateDialogDefault(hwndDlg); - - RECT rc, rcWnd; - GetClientRect(dat->m_pContainer->hwnd, &rcWnd); - GetWindowRect(hwndDlg, &rc); - SetWindowPos(hwndDlg, HWND_TOP, (rcWnd.right - (rc.right - rc.left)) / 2, (rcWnd.bottom - (rc.bottom - rc.top)) / 2, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); - } - break; - - case ID_MESS: - pci->DoEventHookAsync(GetParent(hwnd), si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui, nullptr, 0); - break; - - default: - int iCount = SendMessage(hwnd, LB_GETCOUNT, 0, 0); - if (iCount != LB_ERR) { - int iSelectedItems = SendMessage(hwnd, LB_GETSELCOUNT, 0, 0); - if (iSelectedItems != LB_ERR) { - int *pItems = (int *)mir_alloc(sizeof(int) * (iSelectedItems + 1)); - if (pItems) { - if (SendMessage(hwnd, LB_GETSELITEMS, iSelectedItems, (LPARAM)pItems) != LB_ERR) { - for (int i = 0; i < iSelectedItems; i++) { - USERINFO *ui1 = pci->SM_GetUserFromIndex(si->ptszID, si->pszModule, pItems[i]); - if (ui1) - pci->DoEventHookAsync(hwndParent, si->ptszID, si->pszModule, GC_USER_NICKLISTMENU, ui1, nullptr, (LPARAM)uID); - } - } - mir_free(pItems); - } - } - } - break; - } - DestroyGCMenu(&hMenu, 1); - return TRUE; - } - } - break; - - case WM_MOUSEMOVE: - Chat_HoverMouse(dat->si, hwnd, lParam, M.GetByte("adv_TipperTooltip", 1) && ServiceExists("mToolTip/HideTip")); - break; - } - return mir_callNextSubclass(hwnd, NicklistSubclassProc, msg, wParam, lParam); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// calculate the required rectangle for a string using the given font. This is more -// precise than using GetTextExtentPoint...() - -int GetTextPixelSize(wchar_t* pszText, HFONT hFont, bool bWidth) -{ - if (!pszText || !hFont) - return 0; - - HDC hdc = GetDC(NULL); - HFONT hOldFont = (HFONT)SelectObject(hdc, hFont); - - RECT rc = { 0 }; - DrawText(hdc, pszText, -1, &rc, DT_CALCRECT); - - SelectObject(hdc, hOldFont); - ReleaseDC(NULL, hdc); - return bWidth ? rc.right - rc.left : rc.bottom - rc.top; -} - -static void __cdecl phase2(void * lParam) -{ - Thread_SetName("TabSRMM: phase2"); - - SESSION_INFO *si = (SESSION_INFO*)lParam; - Sleep(30); - if (si && si->hWnd) - PostMessage(si->hWnd, GC_REDRAWLOG2, 0, 0); -} - -///////////////////////////////////////////////////////////////////////////////////////// -// the actual group chat session window procedure.Handles the entire chat session window -// which is usually a (tabbed) child of a container class window. - -CChatRoomDlg::CChatRoomDlg(SESSION_INFO *_si) - : CTabBaseDlg(IDD_CHANNEL), - m_btnOk(this, IDOK), - m_list(this, IDC_LIST), - m_btnBold(this, IDC_BOLD), - m_btnColor(this, IDC_COLOR), - m_btnFilter(this, IDC_FILTER), - m_btnItalic(this, IDC_ITALICS), - m_btnHistory(this, IDC_HISTORY), - m_btnBkColor(this, IDC_BKGCOLOR), - m_btnChannelMgr(this, IDC_CHANMGR), - m_btnUnderline(this, IDC_UNDERLINE), - m_btnNickList(this, IDC_SHOWNICKLIST) -{ - m_bType = SESSIONTYPE_CHAT; - - si = _si; - m_hContact = si->hContact; - m_szProto = GetContactProto(si->hContact); - - m_btnOk.OnClick = Callback(this, &CChatRoomDlg::OnClick_OK); - m_btnFilter.OnClick = Callback(this, &CChatRoomDlg::OnClick_Filter); - m_btnHistory.OnClick = Callback(this, &CChatRoomDlg::OnClick_History); - m_btnNickList.OnClick = Callback(this, &CChatRoomDlg::OnClick_ShowNickList); - m_btnChannelMgr.OnClick = Callback(this, &CChatRoomDlg::OnClick_ChanMgr); - - m_btnColor.OnClick = Callback(this, &CChatRoomDlg::OnClick_Color); - m_btnBkColor.OnClick = Callback(this, &CChatRoomDlg::OnClick_BkColor); - m_btnBold.OnClick = m_btnItalic.OnClick = m_btnUnderline.OnClick = Callback(this, &CChatRoomDlg::OnClick_BIU); - - m_message.OnChange = Callback(this, &CChatRoomDlg::OnChange_Message); - - m_list.OnDblClick = Callback(this, &CChatRoomDlg::OnDblClick_List); -} - -CThumbBase* CChatRoomDlg::CreateThumb(CProxyWindow *pProxy) const -{ - return new CThumbMUC(pProxy, si); -} - -void CChatRoomDlg::ClearLog() -{ - SESSION_INFO *s = pci->SM_FindSession(si->ptszID, si->pszModule); - if (s) { - m_log.SetText(L""); - pci->LM_RemoveAll(&s->pLog, &s->pLogEnd); - s->iEventCount = 0; - s->LastTime = 0; - si->iEventCount = 0; - si->LastTime = 0; - si->pLog = s->pLog; - si->pLogEnd = s->pLogEnd; - PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); - } -} - -void CChatRoomDlg::OnInitDialog() -{ - SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)this); - - m_cache = CContactCache::getContactCache(m_hContact); - m_cache->updateNick(); - m_cache->updateUIN(); - - si->hWnd = m_hwnd; - si->dat = this; - m_bIsAutosizingInput = IsAutoSplitEnabled(); - m_fLimitedUpdate = false; - m_iInputAreaHeight = -1; - - m_iSplitterY = m_pContainer->settings->iSplitterY; - if (m_bIsAutosizingInput) - m_iSplitterY = GetDefaultMinimumInputHeight(); - - CProxyWindow::add(this); - - // Typing support for GCW_PRIVMESS sessions - if (si->iType == GCW_PRIVMESS) { - m_nTypeMode = PROTOTYPE_SELFTYPING_OFF; - SetTimer(m_hwnd, TIMERID_TYPE, 1000, NULL); - } - - m_pPanel.setActive(false); - m_pPanel.Configure(); - M.AddWindow(m_hwnd, m_hContact); - BroadCastContainer(m_pContainer, DM_REFRESHTABINDEX, 0, 0); - - m_log.SendMsg(EM_SETOLECALLBACK, 0, (LPARAM)&reOleCallback); - m_log.SendMsg(EM_AUTOURLDETECT, 1, 0); - SetWindowLongPtr(GetDlgItem(m_hwnd, IDC_PANELSPLITTER), GWLP_WNDPROC, (LONG_PTR)SplitterSubclassProc); - TABSRMM_FireEvent(m_hContact, m_hwnd, MSG_WINDOW_EVT_OPENING, 0); - - m_log.SendMsg(EM_SETEVENTMASK, 0, m_log.SendMsg(EM_GETEVENTMASK, 0, 0) | ENM_LINK | ENM_MOUSEEVENTS | ENM_KEYEVENTS); - m_log.SendMsg(EM_LIMITTEXT, 0x7FFFFFFF, 0); - m_log.SendMsg(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3)); - - m_message.SendMsg(EM_SETEVENTMASK, 0, ENM_REQUESTRESIZE | ENM_MOUSEEVENTS | ENM_SCROLL | ENM_KEYEVENTS | ENM_CHANGE); - m_message.SendMsg(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3)); - - m_pPanel.loadHeight(); - - if (PluginConfig.g_hMenuTrayUnread != 0 && m_hContact != 0 && m_szProto != NULL) - UpdateTrayMenu(0, m_wStatus, m_szProto, m_wszStatus, m_hContact, FALSE); - - DM_ThemeChanged(); - m_log.SendMsg(EM_HIDESELECTION, TRUE, 0); - - GetMYUIN(); - GetMyNick(); - - HWND hwndBtn = CreateWindowEx(0, L"MButtonClass", L"", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 0, 6, DPISCALEY_S(20), m_hwnd, (HMENU)IDC_TOGGLESIDEBAR, g_hInst, NULL); - CustomizeButton(hwndBtn); - SendMessage(hwndBtn, BUTTONSETASTHEMEDBTN, 1, 0); - SendMessage(hwndBtn, BUTTONSETCONTAINER, (LPARAM)m_pContainer, 0); - SendMessage(hwndBtn, BUTTONSETASFLATBTN, FALSE, 0); - SendMessage(hwndBtn, BUTTONSETASTOOLBARBUTTON, TRUE, 0); - SendMessage(hwndBtn, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Expand or collapse the side bar"), BATF_UNICODE); - - DM_InitTip(); - BB_InitDlgButtons(); - SendMessage(m_hwnd, WM_CBD_LOADICONS, 0, 0); - - mir_subclassWindow(GetDlgItem(m_hwnd, IDC_SPLITTERX), SplitterSubclassProc); - mir_subclassWindow(GetDlgItem(m_hwnd, IDC_SPLITTERY), SplitterSubclassProc); - mir_subclassWindow(m_list.GetHwnd(), NicklistSubclassProc); - mir_subclassWindow(m_log.GetHwnd(), LogSubclassProc); - mir_subclassWindow(m_btnFilter.GetHwnd(), ButtonSubclassProc); - mir_subclassWindow(m_btnColor.GetHwnd(), ButtonSubclassProc); - mir_subclassWindow(m_btnBkColor.GetHwnd(), ButtonSubclassProc); - - mir_subclassWindow(m_message.GetHwnd(), MessageSubclassProc); - m_message.SendMsg(EM_SUBCLASSED, 0, 0); - - SendMessage(m_hwnd, GC_SETWNDPROPS, 0, 0); - SendMessage(m_hwnd, GC_UPDATESTATUSBAR, 0, 0); - SendMessage(m_hwnd, GC_UPDATETITLE, 0, 1); - - RECT rc; - SendMessage(m_pContainer->hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)&rc); - SetWindowPos(m_hwnd, HWND_TOP, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), 0); - ShowWindow(m_hwnd, SW_SHOW); - PostMessage(m_hwnd, GC_UPDATENICKLIST, 0, 0); - m_pContainer->hwndActive = m_hwnd; - TABSRMM_FireEvent(m_hContact, m_hwnd, MSG_WINDOW_EVT_OPEN, 0); -} - -void CChatRoomDlg::OnDestroy() -{ - // Typing support for GCW_PRIVMESS sessions - if (si->iType == GCW_PRIVMESS) - if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) - DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); - - if (pcli->pfnGetEvent(si->hContact, 0)) - pcli->pfnRemoveEvent(si->hContact, GC_FAKE_EVENT); - si->wState &= ~STATE_TALK; - si->hWnd = NULL; - si->dat = NULL; - si = NULL; - - TABSRMM_FireEvent(m_hContact, m_hwnd, MSG_WINDOW_EVT_CLOSING, 0); - - DM_FreeTheme(); - - UpdateTrayMenuState(this, FALSE); // remove me from the tray menu (if still there) - if (PluginConfig.g_hMenuTrayUnread) - DeleteMenu(PluginConfig.g_hMenuTrayUnread, (UINT_PTR)m_hContact, MF_BYCOMMAND); - - if (m_hSmileyIcon) - DestroyIcon(m_hSmileyIcon); - - if (m_hwndTip) - DestroyWindow(m_hwndTip); - - int i = GetTabIndexFromHWND(m_hwndParent, m_hwnd); - if (i >= 0) { - SendMessage(m_hwndParent, WM_USER + 100, 0, 0); // clean up tooltip - TabCtrl_DeleteItem(m_hwndParent, i); - BroadCastContainer(m_pContainer, DM_REFRESHTABINDEX, 0, 0); - m_iTabID = -1; - } - if (m_pWnd) { - delete m_pWnd; - m_pWnd = 0; - } - if (m_sbCustom) { - delete m_sbCustom; - m_sbCustom = 0; - } - - M.RemoveWindow(m_hwnd); - - TABSRMM_FireEvent(m_hContact, m_hwnd, MSG_WINDOW_EVT_CLOSE, 0); - - memset((void*)&m_pContainer->mOld, -1000, sizeof(MARGINS)); - PostMessage(m_pContainer->hwnd, WM_SIZE, 0, 1); - - if (m_pContainer->dwFlags & CNT_SIDEBAR) - m_pContainer->SideBar->removeSession(this); - mir_free(m_enteredText); - SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0); -} - -void CChatRoomDlg::OnClick_OK(CCtrlButton*) -{ - if (GetSendButtonState(m_hwnd) == PBS_DISABLED) - return; - - MODULEINFO *mi = pci->MM_FindModule(si->pszModule); - if (mi == NULL) - return; - - ptrA pszRtf(Message_GetFromStream(m_message.GetHwnd())); - pci->SM_AddCommand(si->ptszID, si->pszModule, pszRtf); - - CMStringW ptszText(ptrW(mir_utf8decodeW(pszRtf))); - if (ptszText.IsEmpty()) - return; - - DoRtfToTags(ptszText, mi->nColorCount, mi->crColors); - ptszText.Trim(); - ptszText.Replace(L"%", L"%%"); - - if (mi->bAckMsg) { - Utils::enableDlgControl(m_hwnd, IDC_MESSAGE, false); - m_message.SendMsg(EM_SETREADONLY, TRUE, 0); - } - else SetDlgItemText(m_hwnd, IDC_MESSAGE, L""); - - Utils::enableDlgControl(m_hwnd, IDOK, false); - - // Typing support for GCW_PRIVMESS sessions - if (si->iType == GCW_PRIVMESS) - if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) - DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); - - bool fSound = true; - if (ptszText[0] == '/' || si->iType == GCW_SERVER) - fSound = false; - pci->DoEventHookAsync(m_hwnd, si->ptszID, si->pszModule, GC_USER_MESSAGE, NULL, ptszText, 0); - mi->idleTimeStamp = time(0); - mi->lastIdleCheck = 0; - pci->SM_BroadcastMessage(si->pszModule, GC_UPDATESTATUSBAR, 0, 1, TRUE); - if (m_pContainer) - if (fSound && !nen_options.iNoSounds && !(m_pContainer->dwFlags & CNT_NOSOUND)) - SkinPlaySound("ChatSent"); - - SetFocus(m_message.GetHwnd()); -} - -void CChatRoomDlg::OnClick_Filter(CCtrlButton *pButton) -{ - if (!pButton->Enabled()) - return; - - if (si->iLogFilterFlags == 0 && !si->bFilterEnabled) { - MessageBox(0, TranslateT("The filter cannot be enabled, because there are no event types selected either global or for this chat room"), TranslateT("Event filter error"), MB_OK); - si->bFilterEnabled = 0; - } - else si->bFilterEnabled = !si->bFilterEnabled; - - m_btnFilter.SendMsg(BUTTONSETOVERLAYICON, - (LPARAM)(si->bFilterEnabled ? PluginConfig.g_iconOverlayEnabled : PluginConfig.g_iconOverlayDisabled), 0); - - if (si->bFilterEnabled && M.GetByte(CHAT_MODULE, "RightClickFilter", 0) == 0) { - SendMessage(m_hwnd, GC_SHOWFILTERMENU, 0, 0); - return; - } - SendMessage(m_hwnd, GC_REDRAWLOG, 0, 0); - SendMessage(m_hwnd, GC_UPDATETITLE, 0, 0); - db_set_b(si->hContact, CHAT_MODULE, "FilterEnabled", (BYTE)si->bFilterEnabled); -} - -void CChatRoomDlg::OnClick_History(CCtrlButton *pButton) -{ - if (!pButton->Enabled()) - return; - - MODULEINFO *pInfo = pci->MM_FindModule(si->pszModule); - if (ServiceExists("MSP/HTMLlog/ViewLog") && strstr(si->pszModule, "IRC")) { - char szName[MAX_PATH]; - WideCharToMultiByte(CP_ACP, 0, si->ptszName, -1, szName, MAX_PATH, 0, 0); - szName[MAX_PATH - 1] = 0; - CallService("MSP/HTMLlog/ViewLog", (WPARAM)si->pszModule, (LPARAM)szName); - } - else if (pInfo) - ShellExecute(m_hwnd, NULL, pci->GetChatLogsFilename(si, 0), NULL, NULL, SW_SHOW); -} - -void CChatRoomDlg::OnClick_ShowNickList(CCtrlButton *pButton) -{ - if (!pButton->Enabled()) - return; - if (si->iType == GCW_SERVER) - return; - - si->bNicklistEnabled = !si->bNicklistEnabled; - - SendMessage(m_hwnd, WM_SIZE, 0, 0); - if (CSkin::m_skinEnabled) - InvalidateRect(m_hwnd, NULL, TRUE); - PostMessage(m_hwnd, GC_SCROLLTOBOTTOM, 0, 0); -} - -void CChatRoomDlg::OnClick_ChanMgr(CCtrlButton *pButton) -{ - if (pButton->Enabled()) - pci->DoEventHookAsync(m_hwnd, si->ptszID, si->pszModule, GC_USER_CHANMGR, NULL, NULL, 0); -} - -void CChatRoomDlg::OnClick_BIU(CCtrlButton *pButton) -{ - if (!pButton->Enabled()) - return; - - CHARFORMAT2 cf; - cf.cbSize = sizeof(CHARFORMAT2); - cf.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE; - cf.dwEffects = 0; - - if (IsDlgButtonChecked(m_hwnd, IDC_BOLD)) - cf.dwEffects |= CFE_BOLD; - if (IsDlgButtonChecked(m_hwnd, IDC_ITALICS)) - cf.dwEffects |= CFE_ITALIC; - if (IsDlgButtonChecked(m_hwnd, IDC_UNDERLINE)) - cf.dwEffects |= CFE_UNDERLINE; - - m_message.SendMsg(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); -} - -void CChatRoomDlg::OnClick_Color(CCtrlButton *pButton) -{ - if (!pButton->Enabled()) - return; - - CHARFORMAT2 cf; - cf.cbSize = sizeof(CHARFORMAT2); - cf.dwEffects = 0; - - if (IsDlgButtonChecked(m_hwnd, IDC_COLOR)) { - if (M.GetByte(CHAT_MODULE, "RightClickFilter", 0) == 0) - SendMessage(m_hwnd, GC_SHOWCOLORCHOOSER, 0, IDC_COLOR); - else if (si->bFGSet) { - cf.dwMask = CFM_COLOR; - cf.crTextColor = pci->MM_FindModule(si->pszModule)->crColors[si->iFG]; - m_message.SendMsg(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); - } - } - else { - COLORREF cr; - LoadLogfont(MSGFONTID_MESSAGEAREA, NULL, &cr, FONTMODULE); - cf.dwMask = CFM_COLOR; - cf.crTextColor = cr; - m_message.SendMsg(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); - } -} - -void CChatRoomDlg::OnClick_BkColor(CCtrlButton *pButton) -{ - if (!pButton->Enabled()) - return; - - CHARFORMAT2 cf; - cf.cbSize = sizeof(CHARFORMAT2); - cf.dwEffects = 0; - - if (IsDlgButtonChecked(m_hwnd, IDC_BKGCOLOR)) { - if (M.GetByte(CHAT_MODULE, "RightClickFilter", 0) == 0) - SendMessage(m_hwnd, GC_SHOWCOLORCHOOSER, 0, IDC_BKGCOLOR); - else if (si->bBGSet) { - cf.dwMask = CFM_BACKCOLOR; - cf.crBackColor = pci->MM_FindModule(si->pszModule)->crColors[si->iBG]; - m_message.SendMsg(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); - } - } - else { - cf.dwMask = CFM_BACKCOLOR; - cf.crBackColor = (COLORREF)M.GetDword(FONTMODULE, "inputbg", SRMSGDEFSET_BKGCOLOUR); - m_message.SendMsg(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); - } -} - -void CChatRoomDlg::OnChange_Message(CCtrlEdit*) -{ - if (m_pContainer->hwndActive == m_hwnd) - UpdateReadChars(); - m_dwLastActivity = GetTickCount(); - m_pContainer->dwLastActivity = m_dwLastActivity; - m_btnOk.SendMsg(BUTTONSETASNORMAL, GetRichTextLength(m_message.GetHwnd()) != 0, 0); - m_btnOk.Enable(GetRichTextLength(m_message.GetHwnd()) != 0); - - // Typing support for GCW_PRIVMESS sessions - if (si->iType == GCW_PRIVMESS) { - if (!(GetKeyState(VK_CONTROL) & 0x8000)) { - m_nLastTyping = GetTickCount(); - if (GetWindowTextLength(m_message.GetHwnd())) { - if (m_nTypeMode == PROTOTYPE_SELFTYPING_OFF) { - if (!(m_dwFlags & MWF_INITMODE)) - DM_NotifyTyping(PROTOTYPE_SELFTYPING_ON); - } - } - else if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) - DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); - } - } -} - -void CChatRoomDlg::OnDblClick_List(CCtrlListBox*) -{ - TVHITTESTINFO hti; - hti.pt.x = (short)LOWORD(GetMessagePos()); - hti.pt.y = (short)HIWORD(GetMessagePos()); - ScreenToClient(m_list.GetHwnd(), &hti.pt); - - int item = LOWORD(m_list.SendMsg(LB_ITEMFROMPOINT, 0, MAKELPARAM(hti.pt.x, hti.pt.y))); - USERINFO *ui = pci->UM_FindUserFromIndex(si->pUsers, item); - if (ui == nullptr) - return; - - bool bShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0; - if (g_Settings.bDoubleClick4Privat ? bShift : !bShift) { - int selStart = LOWORD(m_message.SendMsg(EM_GETSEL, 0, 0)); - CMStringW tszName(ui->pszNick); - if (selStart == 0) - tszName.AppendChar(':'); - tszName.AppendChar(' '); - - m_message.SendMsg(EM_REPLACESEL, FALSE, (LPARAM)tszName.GetString()); - PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); - SetFocus(m_message.GetHwnd()); - } - else pci->DoEventHookAsync(m_hwnd, si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui, NULL, 0); -} - -INT_PTR CChatRoomDlg::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (si == NULL && (uMsg == WM_ACTIVATE || uMsg == WM_SETFOCUS)) - return 0; - - POINT pt, tmp, cur; - RECT rc; - MODULEINFO *pInfo; - - switch (uMsg) { - case WM_SETFOCUS: - if (CMimAPI::m_shutDown) - break; - - UpdateWindowState(WM_SETFOCUS); - SetFocus(m_message.GetHwnd()); - return 1; - - case WM_TIMECHANGE: - PostMessage(m_hwnd, GC_REDRAWLOG, 0, 0); - break; - - case WM_CBD_LOADICONS: - Srmm_UpdateToolbarIcons(m_hwnd); - return 0; - - case GC_SETWNDPROPS: - pInfo = si ? pci->MM_FindModule(si->pszModule) : NULL; - if (pInfo) { - m_btnBold.Enable(pInfo->bBold); - m_btnItalic.Enable(pInfo->bItalics); - m_btnUnderline.Enable(pInfo->bUnderline); - m_btnColor.Enable(pInfo->bColor); - m_btnBkColor.Enable(pInfo->bBkgColor); - if (si->iType == GCW_CHATROOM) - m_btnChannelMgr.Enable(pInfo->bChanMgr); - } - m_log.SendMsg(EM_SETBKGNDCOLOR, 0, M.GetDword(FONTMODULE, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR)); - - DM_InitRichEdit(); - m_btnOk.SendMsg(BUTTONSETASNORMAL, TRUE, 0); - - m_list.SetItemHeight(0, g_Settings.iNickListFontHeight); - InvalidateRect(m_list.GetHwnd(), NULL, TRUE); - - m_btnFilter.SendMsg(BUTTONSETOVERLAYICON, (LPARAM)(si->bFilterEnabled ? PluginConfig.g_iconOverlayEnabled : PluginConfig.g_iconOverlayDisabled), 0); - SendMessage(m_hwnd, WM_SIZE, 0, 0); - SendMessage(m_hwnd, GC_REDRAWLOG2, 0, 0); - break; - - case DM_UPDATETITLE: - case GC_UPDATETITLE: - if (!m_bWasDeleted) { - m_wStatus = si->wStatus; - - const wchar_t *szNick = m_cache->getNick(); - if (mir_wstrlen(szNick) > 0) { - if (M.GetByte("cuttitle", 0)) - CutContactName(szNick, m_wszTitle, _countof(m_wszTitle)); - else - wcsncpy_s(m_wszTitle, szNick, _TRUNCATE); - } - - wchar_t szTemp[100]; - HICON hIcon = 0; - - switch (si->iType) { - case GCW_CHATROOM: - hIcon = Skin_LoadProtoIcon(si->pszModule, (m_wStatus <= ID_STATUS_OFFLINE) ? ID_STATUS_OFFLINE : m_wStatus); - mir_snwprintf(szTemp, - (si->nUsersInNicklist == 1) ? TranslateT("%s: chat room (%u user%s)") : TranslateT("%s: chat room (%u users%s)"), - szNick, si->nUsersInNicklist, si->bFilterEnabled ? TranslateT(", event filter active") : L""); - break; - case GCW_PRIVMESS: - hIcon = Skin_LoadProtoIcon(si->pszModule, (m_wStatus <= ID_STATUS_OFFLINE) ? ID_STATUS_OFFLINE : m_wStatus); - if (si->nUsersInNicklist == 1) - mir_snwprintf(szTemp, TranslateT("%s: message session"), szNick); - else - mir_snwprintf(szTemp, TranslateT("%s: message session (%u users)"), szNick, si->nUsersInNicklist); - break; - case GCW_SERVER: - mir_snwprintf(szTemp, L"%s: Server", szNick); - hIcon = LoadIconEx("window"); - break; - } - - if (m_pWnd) { - m_pWnd->updateTitle(m_wszTitle); - m_pWnd->updateIcon(hIcon); - } - m_hTabStatusIcon = hIcon; - - if (lParam) - m_hTabIcon = m_hTabStatusIcon; - - if (m_cache->getStatus() != m_cache->getOldStatus()) { - wcsncpy_s(m_wszStatus, pcli->pfnGetStatusModeDescription(m_wStatus, 0), _TRUNCATE); - - TCITEM item = {}; - item.mask = TCIF_TEXT; - item.pszText = m_wszTitle; - TabCtrl_SetItem(m_hwndParent, m_iTabID, &item); - } - SetWindowText(m_hwnd, szTemp); - if (m_pContainer->hwndActive == m_hwnd) { - SendMessage(m_pContainer->hwnd, DM_UPDATETITLE, (WPARAM)m_hwnd, 1); - SendMessage(m_hwnd, GC_UPDATESTATUSBAR, 0, 0); - } - } - break; - - case GC_UPDATESTATUSBAR: - if (m_bWasDeleted) - return 0; - - if (m_pContainer->hwndActive != m_hwnd || m_pContainer->hwndStatus == 0 || CMimAPI::m_shutDown || m_wszStatusBar[0]) - break; - - if (si->pszModule != NULL) { - wchar_t szFinalStatusBarText[512]; - - //Mad: strange rare crash here... - MODULEINFO *mi = pci->MM_FindModule(si->pszModule); - if (!mi) - break; - - if (!mi->ptszModDispName) - break; - - int x = 12; - x += GetTextPixelSize(mi->ptszModDispName, (HFONT)SendMessage(m_pContainer->hwndStatus, WM_GETFONT, 0, 0), TRUE); - x += GetSystemMetrics(SM_CXSMICON); - - if (m_pPanel.isActive()) { - time_t now = time(0); - DWORD diff = (now - mi->idleTimeStamp) / 60; - - if ((diff >= 1 && diff != mi->lastIdleCheck) || lParam) { - mi->lastIdleCheck = diff; - if (diff == 0) - mi->tszIdleMsg[0] = 0; - else if (diff > 59) { - DWORD hours = diff / 60; - DWORD minutes = diff % 60; - mir_snwprintf(mi->tszIdleMsg, TranslateT(", %d %s, %d %s idle"), hours, hours > 1 ? - TranslateT("hours") : TranslateT("hour"), - minutes, minutes > 1 ? TranslateT("minutes") : TranslateT("minute")); - } - else mir_snwprintf(mi->tszIdleMsg, TranslateT(", %d %s idle"), diff, diff > 1 ? TranslateT("minutes") : TranslateT("minute")); - } - mir_snwprintf(szFinalStatusBarText, TranslateT("%s on %s%s"), m_wszMyNickname, mi->ptszModDispName, mi->tszIdleMsg); - } - else { - if (si->ptszStatusbarText) - mir_snwprintf(szFinalStatusBarText, L"%s %s", mi->ptszModDispName, si->ptszStatusbarText); - else - wcsncpy_s(szFinalStatusBarText, mi->ptszModDispName, _TRUNCATE); - } - SendMessage(m_pContainer->hwndStatus, SB_SETTEXT, 0, (LPARAM)szFinalStatusBarText); - UpdateStatusBar(); - m_pPanel.Invalidate(); - if (m_pWnd) - m_pWnd->Invalidate(); - return TRUE; - } - break; - - case WM_SIZE: - if (m_ipFieldHeight == 0) - m_ipFieldHeight = CInfoPanel::m_ipConfig.height1; - - if (wParam == SIZE_MAXIMIZED) - PostMessage(m_hwnd, GC_SCROLLTOBOTTOM, 0, 0); - - if (!IsIconic(m_hwnd)) { - int panelHeight = m_pPanel.getHeight() + 1; - - GetClientRect(m_hwnd, &rc); - int cx = rc.right; - - CTabBaseDlg::DlgProc(uMsg, 0, 0); // call basic window resizer - - BB_SetButtonsPos(); - - rc.left = panelHeight <= CInfoPanel::LEFT_OFFSET_LOGO ? panelHeight : CInfoPanel::LEFT_OFFSET_LOGO; - rc.right = cx; - rc.top = 1; - rc.bottom = (panelHeight > CInfoPanel::DEGRADE_THRESHOLD ? rc.top + m_ipFieldHeight - 2 : panelHeight - 1); - m_rcNick = rc; - - rc.left = panelHeight <= CInfoPanel::LEFT_OFFSET_LOGO ? panelHeight : CInfoPanel::LEFT_OFFSET_LOGO; - rc.right = cx; - rc.bottom = panelHeight - 2; - rc.top = m_rcNick.bottom + 1; - m_rcUIN = rc; - - if (m_hwndIEView || m_hwndHPP) - ResizeIeView(); - DetermineMinHeight(); - } - return 0; - - case GC_REDRAWWINDOW: - InvalidateRect(m_hwnd, NULL, TRUE); - break; - - case GC_REDRAWLOG: - si->LastTime = 0; - if (si->pLog) { - LOGINFO * pLog = si->pLog; - if (si->iEventCount > 60) { - int index = 0; - while (index < 59) { - if (pLog->next == NULL) - break; - pLog = pLog->next; - if ((si->iType != GCW_CHATROOM && si->iType != GCW_PRIVMESS) || !si->bFilterEnabled || (si->iLogFilterFlags&pLog->iType) != 0) - index++; - } - StreamInEvents(pLog, si, TRUE); - mir_forkthread(phase2, si); - } - else StreamInEvents(si->pLogEnd, si, TRUE); - } - else SendMessage(m_hwnd, GC_CONTROL_MSG, WINDOW_CLEARLOG, 0); - break; - - case GC_REDRAWLOG2: - si->LastTime = 0; - if (si->pLog) - StreamInEvents(si->pLogEnd, si, TRUE); - break; - - case GC_ADDLOG: - if (PluginConfig.m_bUseDividers) { - if (PluginConfig.m_bDividersUsePopupConfig) { - if (!MessageWindowOpened(0, (LPARAM)m_hwnd)) - DM_AddDivider(); - } - else { - bool bInactive = (GetForegroundWindow() != m_pContainer->hwnd || GetActiveWindow() != m_pContainer->hwnd); - if (bInactive) - DM_AddDivider(); - else if (m_pContainer->hwndActive != m_hwnd) - DM_AddDivider(); - } - } - - if (si->pLogEnd) - StreamInEvents(si->pLog, si, FALSE); - else - SendMessage(m_hwnd, GC_CONTROL_MSG, WINDOW_CLEARLOG, 0); - break; - - case DM_TYPING: - // Typing support for GCW_PRIVMESS sessions - if (si->iType == GCW_PRIVMESS) { - int preTyping = m_nTypeSecs != 0; - m_nTypeSecs = (int)lParam > 0 ? (int)lParam : 0; - - if (m_nTypeSecs) - m_bShowTyping = 0; - - SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, preTyping); - } - return TRUE; - - case WM_CTLCOLORLISTBOX: - SetBkColor((HDC)wParam, g_Settings.crUserListBGColor); - return (INT_PTR)pci->hListBkgBrush; - - case WM_MEASUREITEM: - { - MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam; - if (mis->CtlType == ODT_MENU) { - if (m_pPanel.isHovered()) { - mis->itemHeight = 0; - mis->itemWidth = 6; - return TRUE; - } - return Menu_MeasureItem(lParam); - } - mis->itemHeight = g_Settings.iNickListFontHeight; - } - return TRUE; - - case WM_DRAWITEM: - { - DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam; - if (dis->CtlType == ODT_MENU) { - if (m_pPanel.isHovered()) { - DrawMenuItem(dis, (HICON)dis->itemData, 0); - return TRUE; - } - return Menu_DrawItem(lParam); - } - - if (dis->CtlID == IDC_LIST) { - int x_offset = 0; - int index = dis->itemID; - - USERINFO *ui = pci->UM_FindUserFromIndex(si->pUsers, index); - if (ui == NULL) - return TRUE; - - int height = dis->rcItem.bottom - dis->rcItem.top; - if (height & 1) - height++; - int offset = (height == 10) ? 0 : height / 2; - - HICON hIcon = pci->SM_GetStatusIcon(si, ui); - HFONT hFont = g_Settings.UserListFonts[ui->iStatusEx]; - HFONT hOldFont = (HFONT)SelectObject(dis->hDC, hFont); - SetBkMode(dis->hDC, TRANSPARENT); - - int nickIndex = 0; - for (int i = 0; i < STATUSICONCOUNT; i++) { - if (hIcon == pci->hIcons[ICON_STATUS0 + i]) { - nickIndex = i; - break; - } - } - - if (dis->itemState & ODS_SELECTED) { - FillRect(dis->hDC, &dis->rcItem, g_Settings.SelectionBGBrush); - SetTextColor(dis->hDC, g_Settings.nickColors[6]); - } - else { - FillRect(dis->hDC, &dis->rcItem, pci->hListBkgBrush); - if (g_Settings.bColorizeNicks && nickIndex != 0) - SetTextColor(dis->hDC, g_Settings.nickColors[nickIndex - 1]); - else - SetTextColor(dis->hDC, g_Settings.UserListColors[ui->iStatusEx]); - } - x_offset = 2; - - if (g_Settings.bShowContactStatus && g_Settings.bContactStatusFirst && ui->ContactStatus) { - HICON icon = Skin_LoadProtoIcon(si->pszModule, ui->ContactStatus); - DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 8, icon, 16, 16, 0, NULL, DI_NORMAL); - IcoLib_ReleaseIcon(icon); - x_offset += 18; - } - - if (g_Settings.bClassicIndicators) { - char szTemp[3]; - szTemp[1] = 0; - szTemp[0] = szIndicators[nickIndex]; - if (szTemp[0]) { - SIZE szUmode; - GetTextExtentPoint32A(dis->hDC, szTemp, 1, &szUmode); - TextOutA(dis->hDC, x_offset, dis->rcItem.top, szTemp, 1); - x_offset += szUmode.cx + 2; - } - else x_offset += 8; - } - else { - DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 5, hIcon, 10, 10, 0, NULL, DI_NORMAL); - x_offset += 12; - } - - if (g_Settings.bShowContactStatus && !g_Settings.bContactStatusFirst && ui->ContactStatus) { - HICON icon = Skin_LoadProtoIcon(si->pszModule, ui->ContactStatus); - DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 8, icon, 16, 16, 0, NULL, DI_NORMAL); - IcoLib_ReleaseIcon(icon); - x_offset += 18; - } - - SIZE sz; - if (m_iSearchItem != -1 && m_iSearchItem == index && m_wszSearch[0]) { - COLORREF clr_orig = GetTextColor(dis->hDC); - GetTextExtentPoint32(dis->hDC, ui->pszNick, (int)mir_wstrlen(m_wszSearch), &sz); - SetTextColor(dis->hDC, RGB(250, 250, 0)); - TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick, (int)mir_wstrlen(m_wszSearch)); - SetTextColor(dis->hDC, clr_orig); - x_offset += sz.cx; - TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick + mir_wstrlen(m_wszSearch), int(mir_wstrlen(ui->pszNick) - mir_wstrlen(m_wszSearch))); - } - else { - GetTextExtentPoint32(dis->hDC, ui->pszNick, (int)mir_wstrlen(ui->pszNick), &sz); - TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick, (int)mir_wstrlen(ui->pszNick)); - SelectObject(dis->hDC, hOldFont); - } - return TRUE; - } - } - break; - - case WM_CONTEXTMENU: - { - DWORD idFrom = GetDlgCtrlID((HWND)wParam); - if (idFrom >= MIN_CBUTTONID && idFrom <= MAX_CBUTTONID) - Srmm_ClickToolbarIcon(m_hContact, idFrom, (HWND)wParam, 1); - } - break; - - case GC_UPDATENICKLIST: - { - int i = m_list.SendMsg(LB_GETTOPINDEX, 0, 0); - m_list.SendMsg(LB_SETCOUNT, si->nUsersInNicklist, 0); - m_list.SendMsg(LB_SETTOPINDEX, i, 0); - SendMessage(m_hwnd, GC_UPDATETITLE, 0, 0); - } - break; - - case GC_CONTROL_MSG: - switch (wParam) { - case SESSION_OFFLINE: - SendMessage(m_hwnd, GC_UPDATESTATUSBAR, 0, 0); - SendMessage(si->hWnd, GC_UPDATENICKLIST, 0, 0); - return TRUE; - - case SESSION_ONLINE: - SendMessage(m_hwnd, GC_UPDATESTATUSBAR, 0, 0); - return TRUE; - - case WINDOW_HIDDEN: - SendMessage(m_hwnd, GC_CLOSEWINDOW, 0, 1); - return TRUE; - - case WINDOW_CLEARLOG: - SetDlgItemText(m_hwnd, IDC_LOG, L""); - return TRUE; - - case SESSION_TERMINATE: - if (pcli->pfnGetEvent(si->hContact, 0)) - pcli->pfnRemoveEvent(si->hContact, GC_FAKE_EVENT); - - si->wState &= ~STATE_TALK; - m_bWasDeleted = true; - db_set_w(si->hContact, si->pszModule, "ApparentMode", 0); - SendMessage(m_hwnd, GC_CLOSEWINDOW, 0, lParam == 2 ? lParam : 1); - return TRUE; - - case WINDOW_MINIMIZE: - ShowWindow(m_hwnd, SW_MINIMIZE); -LABEL_SHOWWINDOW: - SendMessage(m_hwnd, WM_SIZE, 0, 0); - SendMessage(m_hwnd, GC_REDRAWLOG, 0, 0); - SendMessage(m_hwnd, GC_UPDATENICKLIST, 0, 0); - SendMessage(m_hwnd, GC_UPDATESTATUSBAR, 0, 0); - ShowWindow(m_hwnd, SW_SHOW); - SendMessage(m_hwnd, WM_SIZE, 0, 0); - SetForegroundWindow(m_hwnd); - return TRUE; - - case WINDOW_MAXIMIZE: - ShowWindow(m_hwnd, SW_MAXIMIZE); - goto LABEL_SHOWWINDOW; - - case SESSION_INITDONE: - if (M.GetByte(CHAT_MODULE, "PopupOnJoin", 0) != 0) - return TRUE; - - // fall through - case WINDOW_VISIBLE: - if (IsIconic(m_hwnd)) - ShowWindow(m_hwnd, SW_NORMAL); - goto LABEL_SHOWWINDOW; - } - break; - - case DM_SPLITTERMOVED: - RECT rcLog; - { - GetWindowRect(m_log.GetHwnd(), &rcLog); - if ((HWND)lParam == GetDlgItem(m_hwnd, IDC_SPLITTERX)) { - GetClientRect(m_hwnd, &rc); - pt.x = wParam, pt.y = 0; - ScreenToClient(m_hwnd, &pt); - - int iSplitterX = rc.right - pt.x + 1; - if (iSplitterX < 35) - iSplitterX = 35; - if (iSplitterX > rc.right - rc.left - 35) - iSplitterX = rc.right - rc.left - 35; - m_pContainer->settings->iSplitterX = iSplitterX; - SendMessage(m_hwnd, WM_SIZE, 0, 0); - } - else if ((HWND)lParam == GetDlgItem(m_hwnd, IDC_SPLITTERY) || lParam == -1) { - GetClientRect(m_hwnd, &rc); - rc.top += (m_pPanel.isActive() ? m_pPanel.getHeight() + 40 : 30); - pt.x = 0, pt.y = wParam; - ScreenToClient(m_hwnd, &pt); - - m_iSplitterY = rc.bottom - pt.y + DPISCALEY_S(1); - if (m_iSplitterY < DPISCALEY_S(23)) - m_iSplitterY = DPISCALEY_S(23); - if (m_iSplitterY > rc.bottom - rc.top - DPISCALEY_S(40)) - m_iSplitterY = rc.bottom - rc.top - DPISCALEY_S(40); - m_pContainer->settings->iSplitterY = m_iSplitterY; - UpdateToolbarBG(); - SendMessage(m_hwnd, WM_SIZE, 0, 0); - } - else if ((HWND)lParam == GetDlgItem(m_hwnd, IDC_PANELSPLITTER)) { - pt.x = 0, pt.y = wParam; - ScreenToClient(m_hwnd, &pt); - GetClientRect(m_log.GetHwnd(), &rc); - if ((pt.y + 2 >= MIN_PANELHEIGHT + 2) && (pt.y + 2 < 100) && (pt.y + 2 < rc.bottom - 30)) - m_pPanel.setHeight(pt.y + 2); - RedrawWindow(m_hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); - if (M.isAero()) - InvalidateRect(m_hwndParent, NULL, FALSE); - SendMessage(m_hwnd, WM_SIZE, DM_SPLITTERMOVED, 0); - break; - } - } - break; - - case GC_FIREHOOK: - if (lParam) { - GCHOOK *gch = (GCHOOK*)lParam; - NotifyEventHooks(pci->hSendEvent, 0, (WPARAM)gch); - if (gch->pDest) { - mir_free((void*)gch->pDest->ptszID); - mir_free((void*)gch->pDest->pszModule); - mir_free(gch->pDest); - } - mir_free(gch->ptszText); - mir_free(gch->ptszUID); - mir_free(gch); - } - break; - - case GC_CHANGEFILTERFLAG: - if (si->iLogFilterFlags == 0 && si->bFilterEnabled) - SendMessage(m_hwnd, WM_COMMAND, IDC_FILTER, 0); - break; - - case GC_SHOWFILTERMENU: - m_hwndFilter = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_FILTER), m_pContainer->hwnd, FilterWndProc, (LPARAM)si); - TranslateDialogDefault(m_hwndFilter); - - RECT rcFilter; - GetClientRect(m_hwndFilter, &rcFilter); - GetWindowRect(m_log.GetHwnd(), &rcLog); - - pt.x = rcLog.right; pt.y = rcLog.bottom; - ScreenToClient(m_pContainer->hwnd, &pt); - - SetWindowPos(m_hwndFilter, HWND_TOP, pt.x - rcFilter.right, pt.y - rcFilter.bottom, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); - break; - - case GC_SHOWCOLORCHOOSER: - pci->ColorChooser(si, lParam == IDC_COLOR, m_hwnd, m_message.GetHwnd(), GetDlgItem(m_hwnd, lParam)); - break; - - case GC_SCROLLTOBOTTOM: - DM_ScrollToBottom(wParam, lParam); - return 0; - - case WM_TIMER: - if (wParam == TIMERID_FLASHWND) - if (m_bCanFlashTab) - FlashTab(true); - - // Typing support for GCW_PRIVMESS sessions - if (si->iType == GCW_PRIVMESS && wParam == TIMERID_TYPE) - DM_Typing(false); - break; - - case WM_ACTIVATE: - if (LOWORD(wParam) != WA_ACTIVE) { - m_pContainer->hwndSaved = 0; - break; - } - // fall through - - case WM_MOUSEACTIVATE: - UpdateWindowState(WM_ACTIVATE); - return 1; - - case WM_NOTIFY: - switch (((LPNMHDR)lParam)->code) { - case EN_MSGFILTER: - bool isShift, isCtrl, isMenu; - { - UINT msg = ((MSGFILTER *)lParam)->msg; - WPARAM wp = ((MSGFILTER *)lParam)->wParam; - LPARAM lp = ((MSGFILTER *)lParam)->lParam; - - KbdState(isShift, isCtrl, isMenu); - - MSG message; - message.hwnd = m_hwnd; - message.message = msg; - message.lParam = lp; - message.wParam = wp; - - if (msg == WM_SYSKEYUP) { - if (wp == VK_MENU) - if (!m_fkeyProcessed && !(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000) && !(lp & (1 << 24))) - m_pContainer->MenuBar->autoShow(); - - return _dlgReturn(m_hwnd, 0); - } - - if (msg == WM_MOUSEMOVE) { - GetCursorPos(&pt); - DM_DismissTip(pt); - m_pPanel.trackMouse(pt); - break; - } - if (msg == WM_KEYDOWN) { - if ((wp == VK_INSERT && isShift && !isCtrl && !isMenu) || (wp == 'V' && !isShift && !isMenu && isCtrl)) { - m_message.SendMsg(EM_PASTESPECIAL, CF_UNICODETEXT, 0); - ((MSGFILTER*)lParam)->msg = WM_NULL; - ((MSGFILTER*)lParam)->wParam = 0; - ((MSGFILTER*)lParam)->lParam = 0; - return _dlgReturn(m_hwnd, 1); - } - } - - if (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN || msg == WM_MBUTTONDOWN) - m_pContainer->MenuBar->Cancel(); - - if ((msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) && !(GetKeyState(VK_RMENU) & 0x8000)) { - if (DM_GenericHotkeysCheck(&message)) { - m_fkeyProcessed = true; - return _dlgReturn(m_hwnd, 1); - } - - LRESULT mim_hotkey_check = CallService(MS_HOTKEY_CHECK, (WPARAM)&message, (LPARAM)(TABSRMM_HK_SECTION_GC)); - if (mim_hotkey_check) - m_fkeyProcessed = true; - - switch (mim_hotkey_check) { - case TABSRMM_HK_CHANNELMGR: - OnClick_ChanMgr(&m_btnChannelMgr); - return _dlgReturn(m_hwnd, 1); - case TABSRMM_HK_FILTERTOGGLE: - OnClick_Filter(&m_btnFilter); - InvalidateRect(m_btnFilter.GetHwnd(), NULL, TRUE); - return _dlgReturn(m_hwnd, 1); - case TABSRMM_HK_LISTTOGGLE: - OnClick_ShowNickList(&m_btnNickList); - return _dlgReturn(m_hwnd, 1); - case TABSRMM_HK_MUC_SHOWSERVER: - if (si->iType != GCW_SERVER) - pci->DoEventHookAsync(m_hwnd, si->ptszID, si->pszModule, GC_USER_MESSAGE, NULL, L"/servershow", 0); - return _dlgReturn(m_hwnd, 1); - } - } - - if (msg == WM_KEYDOWN && ((NMHDR*)lParam)->idFrom != IDC_MESSAGE) { - if ((wp == VK_NEXT && isCtrl && !isShift) || (wp == VK_TAB && isCtrl && !isShift)) // CTRL-TAB (switch tab/window) - SendMessage(m_pContainer->hwnd, DM_SELECTTAB, DM_SELECT_NEXT, 0); - else if ((wp == VK_PRIOR && isCtrl && !isShift) || (wp == VK_TAB && isCtrl && isShift)) // CTRL_SHIFT-TAB (switch tab/window) - SendMessage(m_pContainer->hwnd, DM_SELECTTAB, DM_SELECT_PREV, 0); - } - - if (msg == WM_KEYDOWN && wp == VK_TAB) { - if (((NMHDR*)lParam)->idFrom == IDC_LOG) { - SetFocus(m_message.GetHwnd()); - return _dlgReturn(m_hwnd, 1); - } - } - - if (((LPNMHDR)lParam)->idFrom == IDC_LOG && ((MSGFILTER *)lParam)->msg == WM_RBUTTONUP) { - CHARRANGE sel, all = { 0, -1 }; - - pt.x = LOWORD(((ENLINK*)lParam)->lParam), pt.y = HIWORD(((ENLINK*)lParam)->lParam); - ClientToScreen(((LPNMHDR)lParam)->hwndFrom, &pt); - - // fixing stuff for searches - wchar_t *pszWord = (wchar_t*)_alloca(8192); - pszWord[0] = '\0'; - POINTL ptl = { pt.x, pt.y }; - ScreenToClient(m_log.GetHwnd(), (LPPOINT)&ptl); - int iCharIndex = m_log.SendMsg(EM_CHARFROMPOS, 0, (LPARAM)&ptl); - if (iCharIndex < 0) - break; - - int start = m_log.SendMsg(EM_FINDWORDBREAK, WB_LEFT, iCharIndex); - int end = m_log.SendMsg(EM_FINDWORDBREAK, WB_RIGHT, iCharIndex); - - if (end - start > 0) { - static char szTrimString[] = ":;,.!?\'\"><()[]- \r\n"; - - CHARRANGE cr; - cr.cpMin = start; - cr.cpMax = end; - - TEXTRANGE tr = { 0 }; - tr.chrg = cr; - tr.lpstrText = (wchar_t*)pszWord; - int iRes = m_log.SendMsg(EM_GETTEXTRANGE, 0, (LPARAM)&tr); - - if (iRes > 0) { - size_t iLen = mir_wstrlen(pszWord) - 1; - while (strchr(szTrimString, pszWord[iLen])) { - pszWord[iLen] = '\0'; - iLen--; - } - } - } - - HMENU hMenu = 0; - UINT uID = CreateGCMenu(m_hwnd, &hMenu, 1, pt, si, NULL, pszWord); - switch (uID) { - case 0: - PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); - break; - - case ID_COPYALL: - SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_EXGETSEL, 0, (LPARAM)&sel); - SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM)&all); - SendMessage(((LPNMHDR)lParam)->hwndFrom, WM_COPY, 0, 0); - SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM)&sel); - PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); - break; - - case ID_CLEARLOG: - ClearLog(); - break; - - case ID_SEARCH_GOOGLE: - if (pszWord[0]) - Utils_OpenUrlW(CMStringW(FORMAT, L"http://www.google.com/search?q=%s", pszWord)); - - PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); - break; - - case ID_SEARCH_WIKIPEDIA: - if (pszWord[0]) - Utils_OpenUrlW(CMStringW(FORMAT, L"http://en.wikipedia.org/wiki/%s", pszWord)); - - PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); - break; - - default: - PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); - pci->DoEventHookAsync(m_hwnd, si->ptszID, si->pszModule, GC_USER_LOGMENU, NULL, NULL, (LPARAM)uID); - break; - } - - DestroyGCMenu(&hMenu, 5); - } - } - break; - - case EN_REQUESTRESIZE: - if (((LPNMHDR)lParam)->idFrom == IDC_MESSAGE) - DM_HandleAutoSizeRequest((REQRESIZE *)lParam); - break; - - case EN_LINK: - if (((LPNMHDR)lParam)->idFrom == IDC_LOG) { - switch (((ENLINK*)lParam)->msg) { - case WM_RBUTTONDOWN: - case WM_LBUTTONUP: - case WM_LBUTTONDBLCLK: - CHARRANGE sel; - SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_EXGETSEL, 0, (LPARAM)&sel); - if (sel.cpMin == sel.cpMax) { - UINT msg = ((ENLINK*)lParam)->msg; - m_pContainer->MenuBar->Cancel(); - - TEXTRANGE tr; - tr.lpstrText = NULL; - tr.chrg = ((ENLINK*)lParam)->chrg; - tr.lpstrText = (wchar_t*)mir_alloc(sizeof(wchar_t) * (tr.chrg.cpMax - tr.chrg.cpMin + 2)); - SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&tr); - - BOOL isLink = IsStringValidLink(tr.lpstrText); - if (isLink) // handled by core - break; - - // clicked a nick name - if (g_Settings.bClickableNicks) { - if (msg == WM_RBUTTONDOWN) { - HMENU hMenu = 0; - USERINFO uiNew; - for (USERINFO *ui = si->pUsers; ui; ui = ui->next) { - if (mir_wstrcmp(ui->pszNick, tr.lpstrText)) - continue; - - pt.x = (short)LOWORD(((ENLINK*)lParam)->lParam); - pt.y = (short)HIWORD(((ENLINK*)lParam)->lParam); - ClientToScreen(((NMHDR*)lParam)->hwndFrom, &pt); - memcpy(&uiNew, ui, sizeof(USERINFO)); - UINT uID = CreateGCMenu(m_hwnd, &hMenu, 0, pt, si, uiNew.pszUID, uiNew.pszNick); - switch (uID) { - case 0: - break; - - case ID_MESS: - pci->DoEventHookAsync(m_hwnd, si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui, NULL, 0); - break; - - default: - pci->DoEventHookAsync(m_hwnd, si->ptszID, si->pszModule, GC_USER_NICKLISTMENU, ui, NULL, (LPARAM)uID); - break; - } - DestroyGCMenu(&hMenu, 1); - return TRUE; - } - return TRUE; - } - - if (msg == WM_LBUTTONUP) { - CHARRANGE chr; - m_message.SendMsg(EM_EXGETSEL, 0, (LPARAM)&chr); - - wchar_t tszAplTmpl[] = L"%s:"; - size_t bufSize = mir_wstrlen(tr.lpstrText) + mir_wstrlen(tszAplTmpl) + 3; - wchar_t *tszTmp = (wchar_t*)mir_alloc(bufSize * sizeof(wchar_t)), *tszAppeal = tszTmp; - - TEXTRANGE tr2; - tr2.lpstrText = (LPTSTR)mir_alloc(sizeof(wchar_t) * 2); - if (chr.cpMin) { - // prepend nick with space if needed - tr2.chrg.cpMin = chr.cpMin - 1; - tr2.chrg.cpMax = chr.cpMin; - m_message.SendMsg(EM_GETTEXTRANGE, 0, (LPARAM)&tr2); - if (!iswspace(*tr2.lpstrText)) - *tszTmp++ = ' '; - mir_wstrcpy(tszTmp, tr.lpstrText); - } - else // in the beginning of the message window - mir_snwprintf(tszAppeal, bufSize, tszAplTmpl, tr.lpstrText); - - size_t st = mir_wstrlen(tszAppeal); - if (chr.cpMax != -1) { - tr2.chrg.cpMin = chr.cpMax; - tr2.chrg.cpMax = chr.cpMax + 1; - // if there is no space after selection, - // or there is nothing after selection at all... - if (!m_message.SendMsg(EM_GETTEXTRANGE, 0, (LPARAM)&tr2) || !iswspace(*tr2.lpstrText)) { - tszAppeal[st++] = ' '; - tszAppeal[st++] = '\0'; - } - } - else { - tszAppeal[st++] = ' '; - tszAppeal[st++] = '\0'; - } - m_message.SendMsg(EM_REPLACESEL, FALSE, (LPARAM)tszAppeal); - mir_free((void*)tr2.lpstrText); - mir_free((void*)tszAppeal); - } - } - SetFocus(m_message.GetHwnd()); - mir_free(tr.lpstrText); - return TRUE; - } - } - break; - } - break; - } - break; - - case WM_LBUTTONDOWN: - GetCursorPos(&tmp); - if (!m_pPanel.isHovered()) { - cur.x = (SHORT)tmp.x; - cur.y = (SHORT)tmp.y; - SendMessage(m_pContainer->hwnd, WM_NCLBUTTONDOWN, HTCAPTION, *((LPARAM*)(&cur))); - } - break; - - case WM_LBUTTONUP: - GetCursorPos(&tmp); - if (m_pPanel.isHovered()) - m_pPanel.handleClick(tmp); - else { - cur.x = (SHORT)tmp.x; - cur.y = (SHORT)tmp.y; - SendMessage(m_pContainer->hwnd, WM_NCLBUTTONUP, HTCAPTION, *((LPARAM*)(&cur))); - } - break; - - case WM_MOUSEMOVE: - GetCursorPos(&pt); - DM_DismissTip(pt); - m_pPanel.trackMouse(pt); - break; - - case WM_APPCOMMAND: - { - DWORD cmd = GET_APPCOMMAND_LPARAM(lParam); - if (cmd == APPCOMMAND_BROWSER_BACKWARD || cmd == APPCOMMAND_BROWSER_FORWARD) { - SendMessage(m_pContainer->hwnd, DM_SELECTTAB, cmd == APPCOMMAND_BROWSER_BACKWARD ? DM_SELECT_PREV : DM_SELECT_NEXT, 0); - return 1; - } - } - break; - - case WM_COMMAND: - if (LOWORD(wParam) >= MIN_CBUTTONID && LOWORD(wParam) <= MAX_CBUTTONID){ - Srmm_ClickToolbarIcon(m_hContact, LOWORD(wParam), GetDlgItem(m_hwnd, LOWORD(wParam)), 0); - break; - } - - switch (LOWORD(wParam)) { - case IDC_TOGGLESIDEBAR: - SendMessage(m_pContainer->hwnd, WM_COMMAND, IDC_TOGGLESIDEBAR, 0); - break; - - case IDCANCEL: - ShowWindow(m_pContainer->hwnd, SW_MINIMIZE); - return FALSE; - - case IDC_CLOSE: - SendMessage(m_hwnd, WM_CLOSE, 0, 1); - break; - - case IDC_SELFTYPING: - // Typing support for GCW_PRIVMESS sessions - if (si->iType == GCW_PRIVMESS) { - if (m_hContact) { - int iCurrentTypingMode = db_get_b(m_hContact, SRMSGMOD, SRMSGSET_TYPING, M.GetByte(SRMSGMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW)); - - if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON && iCurrentTypingMode) { - DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); - m_nTypeMode = PROTOTYPE_SELFTYPING_OFF; - } - db_set_b(m_hContact, SRMSGMOD, SRMSGSET_TYPING, (BYTE)!iCurrentTypingMode); - } - } - break; - } - break; - - case WM_KEYDOWN: - SetFocus(m_message.GetHwnd()); - break; - - case WM_ERASEBKGND: - RECT rcClient, rcWindow; - { - HDC hdc = (HDC)wParam; - UINT item_ids[3] = { ID_EXTBKUSERLIST, ID_EXTBKHISTORY, ID_EXTBKINPUTAREA }; - UINT ctl_ids[3] = { IDC_LIST, IDC_LOG, IDC_MESSAGE }; - HANDLE hbp = 0; - HDC hdcMem = 0; - HBITMAP hbm, hbmOld; - - GetClientRect(m_hwnd, &rcClient); - LONG cx = rcClient.right - rcClient.left; - LONG cy = rcClient.bottom - rcClient.top; - - if (CMimAPI::m_haveBufferedPaint) { - hbp = CSkin::InitiateBufferedPaint(hdc, rcClient, hdcMem); - hbm = hbmOld = 0; - } - else { - hdcMem = CreateCompatibleDC(hdc); - hbm = CSkin::CreateAeroCompatibleBitmap(rcClient, hdc); - hbmOld = (HBITMAP)SelectObject(hdcMem, hbm); - } - - if (CSkin::m_skinEnabled && !M.isAero()) { - CSkin::SkinDrawBG(m_hwnd, m_pContainer->hwnd, m_pContainer, &rcClient, hdcMem); - for (int i = 0; i < 3; i++) { - CSkinItem *item = &SkinItems[item_ids[i]]; - if (!item->IGNORED) { - GetWindowRect(GetDlgItem(m_hwnd, ctl_ids[i]), &rcWindow); - pt.x = rcWindow.left; - pt.y = rcWindow.top; - ScreenToClient(m_hwnd, &pt); - rc.left = pt.x - item->MARGIN_LEFT; - rc.top = pt.y - item->MARGIN_TOP; - rc.right = rc.left + item->MARGIN_RIGHT + (rcWindow.right - rcWindow.left) + item->MARGIN_LEFT; - rc.bottom = rc.top + item->MARGIN_BOTTOM + (rcWindow.bottom - rcWindow.top) + item->MARGIN_TOP; - CSkin::DrawItem(hdcMem, &rc, item); - } - } - } - else { - CSkin::FillBack(hdcMem, &rcClient); - - if (M.isAero()) { - LONG temp = rcClient.bottom; - rcClient.bottom = m_pPanel.isActive() ? m_pPanel.getHeight() + 5 : 5; - FillRect(hdcMem, &rcClient, (HBRUSH)GetStockObject(BLACK_BRUSH)); - rcClient.bottom = temp; - } - } - - GetClientRect(m_hwnd, &rc); - m_pPanel.renderBG(hdcMem, rc, &SkinItems[ID_EXTBKINFOPANELBG], M.isAero()); - m_pPanel.renderContent(hdcMem); - - if (!CSkin::m_skinEnabled) - RenderToolbarBG(hdcMem, rcClient); - - if (hbp) - CSkin::FinalizeBufferedPaint(hbp, &rcClient); - else { - BitBlt(hdc, 0, 0, cx, cy, hdcMem, 0, 0, SRCCOPY); - SelectObject(hdcMem, hbmOld); - DeleteObject(hbm); - DeleteDC(hdcMem); - } - if (!m_fLimitedUpdate) - SetAeroMargins(m_pContainer); - } - return TRUE; - - case WM_NCPAINT: - if (CSkin::m_skinEnabled) - return 0; - break; - - case WM_PAINT: - PAINTSTRUCT ps; - BeginPaint(m_hwnd, &ps); - EndPaint(m_hwnd, &ps); - return 0; - - case WM_RBUTTONUP: - GetCursorPos(&pt); - if (!m_pPanel.invokeConfigDialog(pt)) { - HMENU subMenu = GetSubMenu(PluginConfig.g_hMenuContext, 0); - - MsgWindowUpdateMenu(subMenu, MENU_TABCONTEXT); - - int iSelection = TrackPopupMenu(subMenu, TPM_RETURNCMD, pt.x, pt.y, 0, m_hwnd, NULL); - if (iSelection >= IDM_CONTAINERMENU) { - char szIndex[10]; - _itoa_s(iSelection - IDM_CONTAINERMENU, szIndex, 10); - ptrW wszContainer(db_get_wsa(NULL, "TAB_ContainersW", szIndex)); - if (wszContainer != nullptr) - SendMessage(m_hwnd, DM_CONTAINERSELECTED, 0, wszContainer); - break; - } - MsgWindowMenuHandler(iSelection, MENU_TABCONTEXT); - } - break; - - case WM_LBUTTONDBLCLK: - if (LOWORD(lParam) < 30) - PostMessage(m_hwnd, GC_SCROLLTOBOTTOM, 0, 0); - break; - - case WM_CLOSE: - if (wParam == 0 && lParam == 0) { - if (PluginConfig.m_EscapeCloses == 1) { - SendMessage(m_pContainer->hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); - return TRUE; - } - if (PluginConfig.m_bHideOnClose && PluginConfig.m_EscapeCloses == 2) { - ShowWindow(m_pContainer->hwnd, SW_HIDE); - return TRUE; - } - _dlgReturn(m_hwnd, TRUE); - } - SendMessage(m_hwnd, GC_CLOSEWINDOW, 0, 1); - return 0; - - case GC_CLOSEWINDOW: - { - bool bForced = (lParam == 2); - - int iTabs = TabCtrl_GetItemCount(m_hwndParent); - if (iTabs == 1 && CMimAPI::m_shutDown == 0) { - SendMessage(m_pContainer->hwnd, WM_CLOSE, 0, 1); - return 1; - } - - m_pContainer->iChilds--; - int i = GetTabIndexFromHWND(m_hwndParent, m_hwnd); - - // after closing a tab, we need to activate the tab to the left side of - // the previously open tab. - // normally, this tab has the same index after the deletion of the formerly active tab - // unless, of course, we closed the last (rightmost) tab. - if (!m_pContainer->bDontSmartClose && iTabs > 1 && !bForced) { - if (i == iTabs - 1) - i--; - else - i++; - TabCtrl_SetCurSel(m_hwndParent, i); - - TCITEM item = {}; - item.mask = TCIF_PARAM; - TabCtrl_GetItem(m_hwndParent, i, &item); // retrieve dialog hwnd for the now active tab... - m_pContainer->hwndActive = (HWND)item.lParam; - - SendMessage(m_pContainer->hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)&rc); - SetWindowPos(m_pContainer->hwndActive, HWND_TOP, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), SWP_SHOWWINDOW); - ShowWindow((HWND)item.lParam, SW_SHOW); - SetForegroundWindow(m_pContainer->hwndActive); - SetFocus(m_pContainer->hwndActive); - SendMessage(m_pContainer->hwnd, WM_SIZE, 0, 0); - } - - if (iTabs == 1) - SendMessage(m_pContainer->hwnd, WM_CLOSE, 0, 1); - else { - PostMessage(m_pContainer->hwnd, WM_SIZE, 0, 0); - DestroyWindow(m_hwnd); - } - } - return 0; - - case DM_SAVESIZE: - if (m_dwFlags & MWF_NEEDCHECKSIZE) - lParam = 0; - - m_dwFlags &= ~MWF_NEEDCHECKSIZE; - if (m_dwFlags & MWF_WASBACKGROUNDCREATE) - m_dwFlags &= ~MWF_INITMODE; - - SendMessage(m_pContainer->hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)&rcClient); - MoveWindow(m_hwnd, rcClient.left, rcClient.top, (rcClient.right - rcClient.left), (rcClient.bottom - rcClient.top), TRUE); - - if (m_dwFlags & MWF_WASBACKGROUNDCREATE) { - m_dwFlags &= ~MWF_WASBACKGROUNDCREATE; - SendMessage(m_hwnd, WM_SIZE, 0, 0); - - pt.x = pt.y = 0; - m_log.SendMsg(EM_SETSCROLLPOS, 0, (LPARAM)&pt); - if (PluginConfig.m_bAutoLocaleSupport) { - if (hkl == 0) - DM_LoadLocale(); - else - PostMessage(m_hwnd, DM_SETLOCALE, 0, 0); - } - } - else { - SendMessage(m_hwnd, WM_SIZE, 0, 0); - if (lParam == 0) - PostMessage(m_hwnd, GC_SCROLLTOBOTTOM, 1, 1); - } - return 0; - - case DM_REFRESHTABINDEX: - m_iTabID = GetTabIndexFromHWND(m_hwndParent, m_hwnd); - return 0; - - case WM_CBD_UPDATED: - if (lParam) - CB_ChangeButton((CustomButtonData*)lParam); - else - BB_InitDlgButtons(); - - BB_SetButtonsPos(); - return 0; - - case WM_CBD_REMOVED: - if (lParam) - CB_DestroyButton((DWORD)wParam, (DWORD)lParam); - else - CB_DestroyAllButtons(); - break; - - case DM_CONFIGURETOOLBAR: - SendMessage(m_hwnd, WM_SIZE, 0, 0); - break; - - case DM_SMILEYOPTIONSCHANGED: - SendMessage(m_hwnd, GC_REDRAWLOG, 0, 1); - break; - - case EM_THEMECHANGED: - DM_FreeTheme(); - DM_ThemeChanged(); - return 0; - - case WM_DWMCOMPOSITIONCHANGED: - BB_RefreshTheme(); - memset(&m_pContainer->mOld, -1000, sizeof(MARGINS)); - CProxyWindow::verify(this); - break; - } - return CTabBaseDlg::DlgProc(uMsg, wParam, lParam); -} diff --git a/plugins/TabSRMM/src/chat_log.cpp b/plugins/TabSRMM/src/chat_log.cpp new file mode 100644 index 0000000000..90d2441eb4 --- /dev/null +++ b/plugins/TabSRMM/src/chat_log.cpp @@ -0,0 +1,1023 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Miranda NG: the free IM client for Microsoft* Windows* +// +// Copyright (ñ) 2012-17 Miranda NG project, +// Copyright (c) 2000-09 Miranda ICQ/IM project, +// all portions of this codebase are copyrighted to the people +// listed in contributors.txt. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// you should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// part of tabSRMM messaging plugin for Miranda. +// +// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors +// +// Implements the richedit-based message history display for the group +// chat window. + +#include "stdafx.h" + +/* + * The code for streaming the text is to a large extent copied from + * the srmm module and then modified to fit the chat module. + */ + +static char *szDivider = "\\strike----------------------------------------------------------------------------\\strike0"; + +/* + * ieview MUC support - mostly from scriver + */ + +/* + +static char* u2a(const wchar_t* src, int codepage) +{ + int cbLen = WideCharToMultiByte(codepage, 0, src, -1, NULL, 0, NULL, NULL); + char* result = (char*)mir_alloc(cbLen + 1); + if (result == NULL) + return NULL; + + WideCharToMultiByte(codepage, 0, src, -1, result, cbLen, NULL, NULL); + result[cbLen] = 0; + return result; +} + +static char* t2acp(const wchar_t* src, int codepage) +{ + return u2a(src, codepage); +} + +static wchar_t *a2tcp(const char *text, int cp) +{ + if (text != NULL) { + int cbLen = MultiByteToWideChar(cp, 0, text, -1, NULL, 0); + wchar_t* result = (wchar_t*)mir_alloc(sizeof(wchar_t)*(cbLen + 1)); + if (result == NULL) + return NULL; + MultiByteToWideChar(cp, 0, text, -1, result, cbLen); + return result; + } + return NULL; +} + +static int Log_AppendIEView(LOGSTREAMDATA* streamData, BOOL simpleMode, wchar_t **buffer, int *cbBufferEnd, int *cbBufferAlloced, const wchar_t *fmt, ...) +{ + va_list va; + int lineLen, textCharsCount = 0; + wchar_t* line = (wchar_t*)_alloca(8001 * sizeof(wchar_t)); + wchar_t* d; + MODULEINFO *mi = pci->MM_FindModule(streamData->si->pszModule); + + va_start(va, fmt); + lineLen = mir_vsnwprintf(line, 8000, fmt, va); + if (lineLen < 0) + return 0; + line[lineLen] = 0; + va_end(va); + lineLen = lineLen * 9 + 8; + if (*cbBufferEnd + lineLen > *cbBufferAlloced) { + cbBufferAlloced[0] += (lineLen + 1024 - lineLen % 1024); + *buffer = (wchar_t*)mir_realloc(*buffer, *cbBufferAlloced * sizeof(wchar_t)); + } + + d = *buffer + *cbBufferEnd; + + for (; *line; line++, textCharsCount++) { + if (*line == '%' && !simpleMode) { + wchar_t szTemp[200]; + + szTemp[0] = '\0'; + switch (*++line) { + case '\0': + case '%': + *d++ = '%'; + break; + + case 'c': + case 'f': + if (!g_Settings.bStripFormat && !streamData->bStripFormat) { + if (line[1] != '\0' && line[2] != '\0') { + wchar_t szTemp3[3], c = *line; + int col; + szTemp3[0] = line[1]; + szTemp3[1] = line[2]; + szTemp3[2] = '\0'; + col = _wtoi(szTemp3); + mir_snwprintf(szTemp, L"%%%c#%02X%02X%02X", c, GetRValue(mi->crColors[col]), GetGValue(mi->crColors[col]), GetBValue(mi->crColors[col])); + } + } + line += 2; + break; + case 'C': + case 'F': + if (!g_Settings.bStripFormat && !streamData->bStripFormat) { + mir_snwprintf(szTemp, L"%%%c", *line); + } + break; + case 'b': + case 'u': + case 'i': + case 'B': + case 'U': + case 'I': + case 'r': + if (!streamData->bStripFormat) { + mir_snwprintf(szTemp, L"%%%c", *line); + } + break; + } + + if (szTemp[0]) { + size_t iLen = mir_wstrlen(szTemp); + memcpy(d, szTemp, iLen * sizeof(wchar_t)); + d += iLen; + } + } + else if (*line == '%') { + *d++ = '%'; + *d++ = (char)*line; + } + else { + *d++ = (wchar_t)*line; + } + } + *d = '\0'; + *cbBufferEnd = (int)(d - *buffer); + return textCharsCount; +} + +static void AddEventTextToBufferIEView(wchar_t **buffer, int *bufferEnd, int *bufferAlloced, LOGSTREAMDATA *streamData) +{ + if (streamData->lin->ptszText) + Log_AppendIEView(streamData, FALSE, str, L": %s", streamData->lin->ptszText); +} + +static void AddEventToBufferIEView(wchar_t **buffer, int *bufferEnd, int *bufferAlloced, LOGSTREAMDATA *streamData, wchar_t *pszNick) +{ + + if (streamData && streamData->lin) { + switch (streamData->lin->iType) { + case GC_EVENT_MESSAGE: + if (streamData->lin->ptszText) { + wchar_t *ptszTemp = NULL; + wchar_t *ptszText = streamData->lin->ptszText; + if (streamData->dat->codePage != CP_ACP) { + char *aText = t2acp(streamData->lin->ptszText, CP_ACP); + ptszText = ptszTemp = a2tcp(aText, streamData->dat->codePage); + mir_free(aText); + } + Log_AppendIEView(streamData, FALSE, str, L"%s", ptszText); + mir_free(ptszTemp); + } + break; + case GC_EVENT_ACTION: + if (pszNick && streamData->lin->ptszText) { + Log_AppendIEView(streamData, TRUE, str, L"%s ", streamData->lin->ptszNick); + Log_AppendIEView(streamData, FALSE, str, L"%s", streamData->lin->ptszText); + } + break; + case GC_EVENT_JOIN: + if (pszNick) { + if (!streamData->lin->bIsMe) + Log_AppendIEView(streamData, TRUE, str, TranslateT("%s has joined"), pszNick); + else + Log_AppendIEView(streamData, TRUE, str, TranslateT("You have joined %s"), streamData->si->ptszName); + } + break; + case GC_EVENT_PART: + if (pszNick) + Log_AppendIEView(streamData, TRUE, str, TranslateT("%s has left"), pszNick); + AddEventTextToBufferIEView(str, streamData); + break; + case GC_EVENT_QUIT: + if (pszNick) + Log_AppendIEView(streamData, TRUE, str, TranslateT("%s has disconnected"), pszNick); + AddEventTextToBufferIEView(str, streamData); + break; + case GC_EVENT_NICK: + if (pszNick && streamData->lin->ptszText) { + if (!streamData->lin->bIsMe) + Log_AppendIEView(streamData, TRUE, str, TranslateT("%s is now known as %s"), pszNick, streamData->lin->ptszText); + else + Log_AppendIEView(streamData, TRUE, str, TranslateT("You are now known as %s"), streamData->lin->ptszText); + } + break; + case GC_EVENT_KICK: + if (pszNick && streamData->lin->ptszStatus) + Log_AppendIEView(streamData, TRUE, str, TranslateT("%s kicked %s"), streamData->lin->ptszStatus, streamData->lin->ptszNick); + AddEventTextToBufferIEView(str, streamData); + break; + case GC_EVENT_NOTICE: + if (pszNick && streamData->lin->ptszText) { + Log_AppendIEView(streamData, TRUE, str, TranslateT("Notice from %s"), pszNick); + AddEventTextToBufferIEView(str, streamData); + } + break; + case GC_EVENT_TOPIC: + if (streamData->lin->ptszText) + Log_AppendIEView(streamData, FALSE, str, TranslateT("The topic is '%s%s'"), streamData->lin->ptszText, L"%r"); + if (pszNick) + Log_AppendIEView(streamData, TRUE, str, + streamData->lin->ptszUserInfo ? TranslateT(" (set by %s on %s)") : TranslateT(" (set by %s)"), + pszNick, streamData->lin->ptszUserInfo); + break; + case GC_EVENT_INFORMATION: + if (streamData->lin->ptszText) + Log_AppendIEView(streamData, FALSE, str, (streamData->lin->bIsMe) ? L"--> %s" : L"%s", streamData->lin->ptszText); + break; + case GC_EVENT_ADDSTATUS: + if (pszNick && streamData->lin->ptszText && streamData->lin->ptszStatus) + Log_AppendIEView(streamData, TRUE, str, TranslateT("%s enables '%s' status for %s"), streamData->lin->ptszText, streamData->lin->ptszStatus, streamData->lin->ptszNick); + break; + case GC_EVENT_REMOVESTATUS: + if (pszNick && streamData->lin->ptszText && streamData->lin->ptszStatus) + Log_AppendIEView(streamData, TRUE, str, TranslateT("%s disables '%s' status for %s"), streamData->lin->ptszText, streamData->lin->ptszStatus, streamData->lin->ptszNick); + break; + } + } +} + +static void LogEventIEView(LOGSTREAMDATA *streamData, wchar_t *ptszNick) +{ + wchar_t *buffer = NULL; + int bufferEnd = 0; + int bufferAlloced = 0; + IEVIEWEVENTDATA ied; + IEVIEWEVENT event; + memset(&event, 0, sizeof(event)); + event.cbSize = sizeof(event); + event.dwFlags = 0; + event.hwnd = streamData->dat->m_hwndIEView ? streamData->dat->m_hwndIEView : streamData->dat->m_hwndHPP; + event.hContact = streamData->dat->m_hContact; + event.codepage = streamData->dat->codePage; + event.pszProto = streamData->si->pszModule; + event.iType = IEE_LOG_MEM_EVENTS; + event.eventData = &ied; + event.count = 1; + + memset(&ied, 0, sizeof(ied)); + AddEventToBufferIEView(str, streamData, ptszNick); + ied.ptszNick = ptszNick; + ied.ptszText = buffer; + ied.time = streamData->lin->time; + ied.bIsMe = streamData->lin->bIsMe; + + switch (streamData->lin->iType) { + case GC_EVENT_MESSAGE: + ied.iType = IEED_GC_EVENT_MESSAGE; + ied.dwData = IEEDD_GC_SHOW_NICK; + break; + case GC_EVENT_ACTION: + ied.iType = IEED_GC_EVENT_ACTION; + break; + case GC_EVENT_JOIN: + ied.iType = IEED_GC_EVENT_JOIN; + break; + case GC_EVENT_PART: + ied.iType = IEED_GC_EVENT_PART; + break; + case GC_EVENT_QUIT: + ied.iType = IEED_GC_EVENT_QUIT; + break; + case GC_EVENT_NICK: + ied.iType = IEED_GC_EVENT_NICK; + break; + case GC_EVENT_KICK: + ied.iType = IEED_GC_EVENT_KICK; + break; + case GC_EVENT_NOTICE: + ied.iType = IEED_GC_EVENT_NOTICE; + break; + case GC_EVENT_TOPIC: + ied.iType = IEED_GC_EVENT_TOPIC; + break; + case GC_EVENT_INFORMATION: + ied.iType = IEED_GC_EVENT_INFORMATION; + break; + case GC_EVENT_ADDSTATUS: + ied.iType = IEED_GC_EVENT_ADDSTATUS; + break; + case GC_EVENT_REMOVESTATUS: + ied.iType = IEED_GC_EVENT_REMOVESTATUS; + break; + } + ied.dwData |= g_Settings.bShowTime ? IEEDD_GC_SHOW_TIME : 0; + ied.dwData |= IEEDD_GC_SHOW_ICON; + ied.dwFlags = IEEDF_UNICODE_TEXT | IEEDF_UNICODE_NICK | IEEDF_UNICODE_TEXT2; + ied.next = NULL; + CallService(streamData->dat->m_hwndIEView ? MS_IEVIEW_EVENT : MS_HPP_EG_EVENT, 0, (LPARAM)&event); + mir_free(buffer); +} + +*/ + +static int EventToIndex(LOGINFO * lin) +{ + switch (lin->iType) { + case GC_EVENT_MESSAGE: + if (lin->bIsMe) + return 10; + else + return 9; + + case GC_EVENT_JOIN: + return 3; + case GC_EVENT_PART: + return 4; + case GC_EVENT_QUIT: + return 5; + case GC_EVENT_NICK: + return 7; + case GC_EVENT_KICK: + return 6; + case GC_EVENT_NOTICE: + return 8; + case GC_EVENT_TOPIC: + return 11; + case GC_EVENT_INFORMATION: + return 12; + case GC_EVENT_ADDSTATUS: + return 13; + case GC_EVENT_REMOVESTATUS: + return 14; + case GC_EVENT_ACTION: + return 15; + } + return 0; +} + +static BYTE EventToSymbol(LOGINFO *lin) +{ + switch (lin->iType) { + case GC_EVENT_MESSAGE: + return (lin->bIsMe) ? 0x37 : 0x38; + case GC_EVENT_JOIN: + return 0x34; + case GC_EVENT_PART: + return 0x33; + case GC_EVENT_QUIT: + return 0x39; + case GC_EVENT_NICK: + return 0x71; + case GC_EVENT_KICK: + return 0x72; + case GC_EVENT_NOTICE: + return 0x28; + case GC_EVENT_INFORMATION: + return 0x69; + case GC_EVENT_ADDSTATUS: + return 0x35; + case GC_EVENT_REMOVESTATUS: + return 0x36; + case GC_EVENT_ACTION: + return 0x60; + } + return 0x73; +} + +static int EventToIcon(LOGINFO * lin) +{ + switch (lin->iType) { + case GC_EVENT_MESSAGE: + if (lin->bIsMe) + return ICON_MESSAGEOUT; + else + return ICON_MESSAGE; + + case GC_EVENT_JOIN: + return ICON_JOIN; + case GC_EVENT_PART: + return ICON_PART; + case GC_EVENT_QUIT: + return ICON_QUIT; + case GC_EVENT_NICK: + return ICON_NICK; + case GC_EVENT_KICK: + return ICON_KICK; + case GC_EVENT_NOTICE: + return ICON_NOTICE; + case GC_EVENT_TOPIC: + return ICON_TOPIC; + case GC_EVENT_INFORMATION: + return ICON_INFO; + case GC_EVENT_ADDSTATUS: + return ICON_ADDSTATUS; + case GC_EVENT_REMOVESTATUS: + return ICON_REMSTATUS; + case GC_EVENT_ACTION: + return ICON_ACTION; + } + return 0; +} + +static void Log_AppendRTF(LOGSTREAMDATA *streamData, BOOL simpleMode, CMStringA &str, const wchar_t *fmt, ...) +{ + int textCharsCount = 0; + wchar_t *line = (wchar_t*)_alloca(8001 * sizeof(wchar_t)); + + va_list va; + va_start(va, fmt); + int lineLen = mir_vsnwprintf(line, 8000, fmt, va); + if (lineLen < 0) + lineLen = 8000; + line[lineLen] = 0; + va_end(va); + + CMStringA res; + + for (; *line; line++, textCharsCount++) { + if (*line == '\r' && line[1] == '\n') { + res.Append("\\par "); + line++; + } + else if (*line == '\n') { + res.Append("\\line "); + } + else if (*line == '%' && !simpleMode) { + char szTemp[200]; szTemp[0] = '\0'; + switch (*++line) { + case '\0': + case '%': + res.AppendChar('%'); + break; + + case 'c': + case 'f': + if (g_Settings.bStripFormat || streamData->bStripFormat) + line += 2; + else if (line[1] != '\0' && line[2] != '\0') { + wchar_t szTemp3[3], c = *line; + int col; + szTemp3[0] = line[1]; + szTemp3[1] = line[2]; + szTemp3[2] = '\0'; + line += 2; + + col = _wtoi(szTemp3); + col += (OPTIONS_FONTCOUNT + 1); + res.AppendFormat((c == 'c') ? "\\cf%u " : "\\highlight%u ", col); + } + break; + case 'C': + case 'F': + if (!g_Settings.bStripFormat && !streamData->bStripFormat) { + int j = streamData->lin->bIsHighlighted ? 16 : EventToIndex(streamData->lin); + if (*line == 'C') + res.AppendFormat("\\cf%u ", j + 1); + else + res.Append("\\highlight0 "); + } + break; + case 'b': + case 'u': + case 'i': + if (!streamData->bStripFormat) + res.AppendFormat((*line == 'u') ? "\\%cl " : "\\%c ", *line); + break; + + case 'B': + case 'U': + case 'I': + if (!streamData->bStripFormat) + res.AppendFormat((*line == 'U') ? "\\%cl0 " : "\\%c0 ", tolower(*line)); + break; + + case 'r': + if (!streamData->bStripFormat) { + int index = EventToIndex(streamData->lin); + res.AppendFormat("%s ", pci->Log_SetStyle(index)); + } + break; + } + } + else if (*line == '\t' && !streamData->bStripFormat) { + res.Append("\\tab "); + } + else if ((*line == '\\' || *line == '{' || *line == '}') && !streamData->bStripFormat) { + res.AppendChar('\\'); + res.AppendChar(*line); + } + else if (*line > 0 && *line < 128) { + res.AppendChar((char)*line); + } + else res.AppendFormat("\\u%u ?", (WORD)* line); + } + + str += res; +} + +static void AddEventToBuffer(CMStringA &str, LOGSTREAMDATA *streamData) +{ + wchar_t szTemp[512], szTemp2[512]; + wchar_t* pszNick = NULL; + + if (streamData == NULL) + return; + + if (streamData->lin == NULL) + return; + + if (streamData->lin->ptszNick) { + if (g_Settings.bLogLimitNames && mir_wstrlen(streamData->lin->ptszNick) > 20) { + wcsncpy_s(szTemp, 20, streamData->lin->ptszNick, _TRUNCATE); + wcsncpy_s(szTemp + 20, 4, L"...", _TRUNCATE); + } + else wcsncpy_s(szTemp, streamData->lin->ptszNick, _TRUNCATE); + + if (g_Settings.bClickableNicks) + mir_snwprintf(szTemp2, L"~~++#%s#++~~", szTemp); + else + wcsncpy_s(szTemp2, szTemp, _TRUNCATE); + + if (streamData->lin->ptszUserInfo && streamData->lin->iType != GC_EVENT_TOPIC) + mir_snwprintf(szTemp, L"%s (%s)", szTemp2, streamData->lin->ptszUserInfo); + else + wcsncpy_s(szTemp, szTemp2, _TRUNCATE); + pszNick = szTemp; + } + + switch (streamData->lin->iType) { + case GC_EVENT_MESSAGE: + if (streamData->lin->ptszText) + Log_AppendRTF(streamData, FALSE, str, L"%s", streamData->lin->ptszText); + break; + case GC_EVENT_ACTION: + if (streamData->lin->ptszNick && streamData->lin->ptszText) { + Log_AppendRTF(streamData, TRUE, str, L"%s ", streamData->lin->ptszNick); + Log_AppendRTF(streamData, FALSE, str, L"%s", streamData->lin->ptszText); + } + break; + case GC_EVENT_JOIN: + if (pszNick) { + if (!streamData->lin->bIsMe) + /* replace nick of a newcomer with a link */ + Log_AppendRTF(streamData, TRUE, str, TranslateT("%s has joined"), pszNick); + else + Log_AppendRTF(streamData, TRUE, str, TranslateT("You have joined %s"), streamData->si->ptszName); + } + break; + case GC_EVENT_PART: + if (pszNick) + Log_AppendRTF(streamData, TRUE, str, TranslateT("%s has left"), pszNick); + if (streamData->lin->ptszText) + Log_AppendRTF(streamData, FALSE, str, L": %s", streamData->lin->ptszText); + break; + case GC_EVENT_QUIT: + if (pszNick) + Log_AppendRTF(streamData, TRUE, str, TranslateT("%s has disconnected"), pszNick); + if (streamData->lin->ptszText) + Log_AppendRTF(streamData, FALSE, str, L": %s", streamData->lin->ptszText); + break; + case GC_EVENT_NICK: + if (pszNick && streamData->lin->ptszText) { + if (!streamData->lin->bIsMe) + Log_AppendRTF(streamData, TRUE, str, TranslateT("%s is now known as %s"), pszNick, streamData->lin->ptszText); + else + Log_AppendRTF(streamData, TRUE, str, TranslateT("You are now known as %s"), streamData->lin->ptszText); + } + break; + case GC_EVENT_KICK: + if (pszNick && streamData->lin->ptszStatus) + Log_AppendRTF(streamData, TRUE, str, + TranslateT("%s kicked %s"), streamData->lin->ptszStatus, pszNick); + + if (streamData->lin->ptszText) + Log_AppendRTF(streamData, FALSE, str, L": %s", streamData->lin->ptszText); + break; + case GC_EVENT_NOTICE: + if (pszNick && streamData->lin->ptszText) { + Log_AppendRTF(streamData, TRUE, str, TranslateT("Notice from %s: "), pszNick); + Log_AppendRTF(streamData, FALSE, str, L"%s", streamData->lin->ptszText); + } + break; + case GC_EVENT_TOPIC: + if (streamData->lin->ptszText) + Log_AppendRTF(streamData, FALSE, str, TranslateT("The topic is '%s%s'"), streamData->lin->ptszText, L"%r"); + if (pszNick) + Log_AppendRTF(streamData, TRUE, str, + (streamData->lin->ptszUserInfo) ? TranslateT(" (set by %s on %s)") : + TranslateT(" (set by %s)"), + pszNick, streamData->lin->ptszUserInfo); + break; + case GC_EVENT_INFORMATION: + if (streamData->lin->ptszText) + Log_AppendRTF(streamData, FALSE, str, (streamData->lin->bIsMe) ? L"--> %s" : L"%s", streamData->lin->ptszText); + break; + case GC_EVENT_ADDSTATUS: + if (pszNick && streamData->lin->ptszText && streamData->lin->ptszStatus) + Log_AppendRTF(streamData, TRUE, str, + TranslateT("%s enables '%s' status for %s"), + streamData->lin->ptszText, streamData->lin->ptszStatus, pszNick); + break; + case GC_EVENT_REMOVESTATUS: + if (pszNick && streamData->lin->ptszText && streamData->lin->ptszStatus) { + Log_AppendRTF(streamData, TRUE, str, + TranslateT("%s disables '%s' status for %s"), + streamData->lin->ptszText, streamData->lin->ptszStatus, pszNick); + } + break; + } +} + +char* Log_CreateRtfHeader(MODULEINFO *mi) +{ + int i = 0; + + // get the number of pixels per logical inch + if (pci->logPixelSY == 0) { + HDC hdc = GetDC(NULL); + pci->logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); + pci->logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX); + ReleaseDC(NULL, hdc); + } + + // ### RTF HEADER + + // font table + CMStringA str("{\\rtf1\\ansi\\deff0{\\fonttbl"); + for (i = 0; i < OPTIONS_FONTCOUNT; i++) + str.AppendFormat("{\\f%u\\fnil\\fcharset%u%S;}", i, pci->aFonts[i].lf.lfCharSet, pci->aFonts[i].lf.lfFaceName); + + // colour table + str.Append("}{\\colortbl ;"); + + for (i = 0; i < OPTIONS_FONTCOUNT; i++) + str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(pci->aFonts[i].color), GetGValue(pci->aFonts[i].color), GetBValue(pci->aFonts[i].color)); + + for (i = 0; i < mi->nColorCount; i++) + str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(mi->crColors[i]), GetGValue(mi->crColors[i]), GetBValue(mi->crColors[i])); + + for (i = 0; i < STATUSICONCOUNT; i++) + str.AppendFormat("\\red%u\\green%u\\blue%u;", GetRValue(g_Settings.nickColors[i]), GetGValue(g_Settings.nickColors[i]), GetBValue(g_Settings.nickColors[i])); + + // new paragraph + str.AppendFormat("}\\pard\\sl%d", 1000); + + // set tabs and indents + int iIndent = 0; + + if (g_Settings.bLogSymbols) { + wchar_t szString[2]; + LOGFONT lf; + + szString[1] = 0; + szString[0] = 0x28; + pci->LoadMsgDlgFont(17, &lf, NULL); + HFONT hFont = CreateFontIndirect(&lf); + int iText = GetTextPixelSize(szString, hFont, true) + 3; + DeleteObject(hFont); + iIndent += (iText * 1440) / pci->logPixelSX; + str.AppendFormat("\\tx%u", iIndent); + } + else if (g_Settings.dwIconFlags) { + iIndent += ((g_Settings.bScaleIcons ? 14 : 20) * 1440) / pci->logPixelSX; + str.AppendFormat("\\tx%u", iIndent); + } + if (g_Settings.bShowTime) { + int iSize = (g_Settings.LogTextIndent * 1440) / pci->logPixelSX; + str.AppendFormat("\\tx%u", iIndent + iSize); + if (g_Settings.bLogIndentEnabled) + iIndent += iSize; + } + str.AppendFormat("\\fi-%u\\li%u", iIndent, iIndent); + + return str.Detach(); +} + +static char* Log_CreateRTF(LOGSTREAMDATA *streamData) +{ + LOGINFO *lin = streamData->lin; + MODULEINFO *mi = pci->MM_FindModule(streamData->si->pszModule); + + // ### RTF HEADER + + if (0 == mi->pszHeader) + mi->pszHeader = Log_CreateRtfHeader(mi); + + char *header = mi->pszHeader; + streamData->crCount = mi->nColorCount; + + CMStringA str; + if (header) + str.Append(header); + + // ### RTF BODY (one iteration per event that should be streamed in) + while (lin) { + // filter + if ((streamData->si->iType != GCW_CHATROOM && streamData->si->iType != GCW_PRIVMESS) || !streamData->si->bFilterEnabled || (streamData->si->iLogFilterFlags & lin->iType) != 0) { + if (lin->next != NULL) + str.Append("\\par "); + + if (streamData->dat->m_dwFlags & MWF_DIVIDERWANTED || lin->dwFlags & MWF_DIVIDERWANTED) { + static char szStyle_div[128] = "\0"; + if (szStyle_div[0] == 0) + mir_snprintf(szStyle_div, "\\f%u\\cf%u\\ul0\\b%d\\i%d\\fs%u", 17, 18, 0, 0, 5); + + lin->dwFlags |= MWF_DIVIDERWANTED; + if (lin->prev || !streamData->bRedraw) + str.AppendFormat("\\qc\\sl-1\\highlight%d %s ---------------------------------------------------------------------------------------\\par ", 18, szStyle_div); + streamData->dat->m_dwFlags &= ~MWF_DIVIDERWANTED; + } + // create new line, and set font and color + str.AppendFormat("\\ql\\sl0%s ", pci->Log_SetStyle(0)); + str.AppendFormat("\\v~-+%d+-~\\v0 ", lin); + + // Insert icon + if (g_Settings.bLogSymbols) // use symbols + str.AppendFormat("%s %c", pci->Log_SetStyle(17), EventToSymbol(lin)); + else if (g_Settings.dwIconFlags) { + int iIndex = lin->bIsHighlighted ? ICON_HIGHLIGHT : EventToIcon(lin); + str.Append("\\f0\\fs14"); + str.Append(pci->pLogIconBmpBits[iIndex]); + } + + if (g_Settings.bTimeStampEventColour) { + // colored timestamps + static char szStyle[256]; + LOGFONT &F = pci->aFonts[0].lf; + int iii; + if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) { + iii = lin->bIsHighlighted ? 16 : (lin->bIsMe ? 2 : 1); + mir_snprintf(szStyle, "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\ul%d\\fs%u", + iii + 1, F.lfWeight >= FW_BOLD ? 1 : 0, F.lfItalic, F.lfUnderline, 2 * abs(F.lfHeight) * 74 / pci->logPixelSY); + str.Append(szStyle); + } + else { + iii = lin->bIsHighlighted ? 16 : EventToIndex(lin); + mir_snprintf(szStyle, "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\ul%d\\fs%u", + iii + 1, F.lfWeight >= FW_BOLD ? 1 : 0, F.lfItalic, F.lfUnderline, 2 * abs(F.lfHeight) * 74 / pci->logPixelSY); + str.Append(szStyle); + } + } + else str.Append(pci->Log_SetStyle(0)); + str.AppendChar(' '); + + // insert a TAB if necessary to put the timestamp in the right position + if (g_Settings.dwIconFlags) + str.Append("\\tab "); + + //insert timestamp + if (g_Settings.bShowTime) { + wchar_t szTimeStamp[30], szOldTimeStamp[30]; + + wcsncpy_s(szTimeStamp, pci->MakeTimeStamp(g_Settings.pszTimeStamp, lin->time), _TRUNCATE); + wcsncpy_s(szOldTimeStamp, pci->MakeTimeStamp(g_Settings.pszTimeStamp, streamData->si->LastTime), _TRUNCATE); + if (!g_Settings.bShowTimeIfChanged || streamData->si->LastTime == 0 || mir_wstrcmp(szTimeStamp, szOldTimeStamp)) { + streamData->si->LastTime = lin->time; + Log_AppendRTF(streamData, TRUE, str, L"%s", szTimeStamp); + } + str.Append("\\tab "); + } + + // Insert the nick + if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) { + char pszIndicator[3] = "\0\0"; + int crNickIndex = 0; + + if (g_Settings.bLogClassicIndicators || g_Settings.bColorizeNicksInLog) + pszIndicator[0] = GetIndicator(streamData->si, lin->ptszNick, &crNickIndex); + + str.Append(pci->Log_SetStyle(lin->bIsMe ? 2 : 1)); + str.AppendChar(' '); + + if (g_Settings.bLogClassicIndicators) + str.Append(pszIndicator); + + CMStringW pszTemp(lin->bIsMe ? g_Settings.pszOutgoingNick : g_Settings.pszIncomingNick); + pszTemp.Replace(L"%n", L"%s"); + if (!lin->bIsMe) { + if (g_Settings.bClickableNicks) + pszTemp.Replace(L"%s", L"~~++#%s#++~~"); + + if (g_Settings.bColorizeNicksInLog && pszIndicator[0]) + str.AppendFormat("\\cf%u ", OPTIONS_FONTCOUNT + streamData->crCount + crNickIndex); + } + + if (g_Settings.bNewLineAfterNames) + pszTemp.AppendChar('\n'); + + Log_AppendRTF(streamData, TRUE, str, pszTemp, lin->ptszNick); + str.AppendChar(' '); + } + + // Insert the message + str.Append(pci->Log_SetStyle(lin->bIsHighlighted ? 16 : EventToIndex(lin))); + str.AppendChar(' '); + + streamData->lin = lin; + AddEventToBuffer(str, streamData); + } + lin = lin->prev; + } + + // ### RTF END + if (streamData->bRedraw) + str.Append("\\par}"); + else + str.Append("}"); + return str.Detach(); +} + +static DWORD CALLBACK Log_StreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb) +{ + LOGSTREAMDATA *lstrdat = (LOGSTREAMDATA*)dwCookie; + + if (lstrdat) { + // create the RTF + if (lstrdat->buffer == NULL) { + lstrdat->bufferOffset = 0; + lstrdat->buffer = Log_CreateRTF(lstrdat); + lstrdat->bufferLen = (int)mir_strlen(lstrdat->buffer); + } + + // give the RTF to the RE control + *pcb = min(cb, lstrdat->bufferLen - lstrdat->bufferOffset); + memcpy(pbBuff, lstrdat->buffer + lstrdat->bufferOffset, *pcb); + lstrdat->bufferOffset += *pcb; + + // mir_free stuff if the streaming operation is complete + if (lstrdat->bufferOffset == lstrdat->bufferLen) { + mir_free(lstrdat->buffer); + lstrdat->buffer = NULL; + } + } + + return 0; +} + +void CChatRoomDlg::StreamInEvents(LOGINFO *lin, SESSION_INFO *si, bool bRedraw) +{ + CHARRANGE oldsel, sel, newsel; + POINT point = { 0 }; + + if (m_hwnd == 0 || lin == 0 || si == 0) + return; + + HWND hwndRich = GetDlgItem(m_hwnd, IDC_LOG); + + LOGSTREAMDATA streamData; + memset(&streamData, 0, sizeof(streamData)); + streamData.hwnd = hwndRich; + streamData.si = si; + streamData.lin = lin; + streamData.bStripFormat = FALSE; + streamData.dat = this; + + if (!bRedraw && (si->iType == GCW_CHATROOM || si->iType == GCW_PRIVMESS) && si->bFilterEnabled && (si->iLogFilterFlags & lin->iType) == 0) + return; + + bool bFlag = false, fDoReplace; + + EDITSTREAM stream = { 0 }; + stream.pfnCallback = Log_StreamCallback; + stream.dwCookie = (DWORD_PTR)& streamData; + + SCROLLINFO scroll = { 0 }; + scroll.cbSize = sizeof(SCROLLINFO); + scroll.fMask = SIF_RANGE | SIF_POS | SIF_PAGE; + GetScrollInfo(GetDlgItem(m_hwnd, IDC_LOG), SB_VERT, &scroll); + SendMessage(hwndRich, EM_GETSCROLLPOS, 0, (LPARAM)&point); + + // do not scroll to bottom if there is a selection + SendMessage(hwndRich, EM_EXGETSEL, 0, (LPARAM)&oldsel); + if (oldsel.cpMax != oldsel.cpMin) + SendMessage(hwndRich, WM_SETREDRAW, FALSE, 0); + + //set the insertion point at the bottom + sel.cpMin = sel.cpMax = GetRichTextLength(hwndRich); + SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM)&sel); + + // fix for the indent... must be a M$ bug + if (sel.cpMax == 0) + bRedraw = TRUE; + + // should the event(s) be appended to the current log + WPARAM wp = bRedraw ? SF_RTF : SFF_SELECTION | SF_RTF; + + //get the number of pixels per logical inch + if (bRedraw) { + HDC hdc = GetDC(NULL); + pci->logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); + pci->logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX); + ReleaseDC(NULL, hdc); + SendMessage(hwndRich, WM_SETREDRAW, FALSE, 0); + bFlag = true; + // SetCursor(LoadCursor(NULL, IDC_ARROW)); + } + + // stream in the event(s) + streamData.lin = lin; + streamData.bRedraw = bRedraw; + SendMessage(hwndRich, EM_STREAMIN, wp, (LPARAM)&stream); + + // for new added events, only replace in message or action events. + // no need to replace smileys or math formulas elsewhere + fDoReplace = (bRedraw || (lin->ptszText && (lin->iType == GC_EVENT_MESSAGE || lin->iType == GC_EVENT_ACTION))); + + // replace marked nicknames with hyperlinks to make the nicks clickable + if (g_Settings.bClickableNicks) { + FINDTEXTEX fi, fi2; + + CHARFORMAT2 cf2; + memset(&cf2, 0, sizeof(CHARFORMAT2)); + cf2.cbSize = sizeof(cf2); + + fi2.lpstrText = L"#++~~"; + fi.chrg.cpMin = bRedraw ? 0 : sel.cpMin; + fi.chrg.cpMax = -1; + fi.lpstrText = L"~~++#"; + + while (SendMessage(hwndRich, EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi) > -1) { + fi2.chrg.cpMin = fi.chrgText.cpMin; + fi2.chrg.cpMax = -1; + + if (SendMessage(hwndRich, EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi2) > -1) { + + SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM)&fi.chrgText); + SendMessage(hwndRich, EM_REPLACESEL, TRUE, (LPARAM)L""); + fi2.chrgText.cpMin -= fi.chrgText.cpMax - fi.chrgText.cpMin; + fi2.chrgText.cpMax -= fi.chrgText.cpMax - fi.chrgText.cpMin; + SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM)&fi2.chrgText); + SendMessage(hwndRich, EM_REPLACESEL, TRUE, (LPARAM)L""); + fi2.chrgText.cpMax = fi2.chrgText.cpMin; + + fi2.chrgText.cpMin = fi.chrgText.cpMin; + SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM)&fi2.chrgText); + cf2.dwMask = CFM_PROTECTED; + cf2.dwEffects = CFE_PROTECTED; + SendMessage(hwndRich, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2); + } + fi.chrg.cpMin = fi.chrgText.cpMax; + } + SendMessage(hwndRich, EM_SETSEL, -1, -1); + } + + // run smileyadd + if (PluginConfig.g_SmileyAddAvail && fDoReplace) { + newsel.cpMax = -1; + newsel.cpMin = sel.cpMin; + if (newsel.cpMin < 0) + newsel.cpMin = 0; + + SMADD_RICHEDIT3 sm = { sizeof(sm) }; + sm.hwndRichEditControl = hwndRich; + sm.Protocolname = si->pszModule; + sm.rangeToReplace = bRedraw ? NULL : &newsel; + sm.disableRedraw = TRUE; + sm.hContact = si->hContact; + CallService(MS_SMILEYADD_REPLACESMILEYS, 0, (LPARAM)&sm); + } + + // trim the message log to the number of most recent events + // this uses hidden marks in the rich text to find the events which should be deleted + if (si->bTrimmed) { + wchar_t szPattern[50]; + mir_snwprintf(szPattern, L"~-+%d+-~", si->pLogEnd); + + FINDTEXTEX fi; + fi.lpstrText = szPattern; + fi.chrg.cpMin = 0; + fi.chrg.cpMax = -1; + if (SendMessage(hwndRich, EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi) != 0) { + CHARRANGE rng; + rng.cpMin = 0; + rng.cpMax = 20; + SendMessage(hwndRich, EM_SETSEL, 0, fi.chrgText.cpMax + 1); + SendMessage(hwndRich, EM_REPLACESEL, TRUE, (LPARAM)L""); + } + si->bTrimmed = FALSE; + } + + // scroll log to bottom if the log was previously scrolled to bottom, else restore old position + if ((bRedraw || (UINT)scroll.nPos >= (UINT)scroll.nMax - scroll.nPage - 5 || scroll.nMax - scroll.nMin - scroll.nPage < 50)) + SendMessage(GetParent(hwndRich), GC_SCROLLTOBOTTOM, 0, 0); + else + SendMessage(hwndRich, EM_SETSCROLLPOS, 0, (LPARAM)&point); + + // do we need to restore the selection + if (oldsel.cpMax != oldsel.cpMin) { + SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM)&oldsel); + SendMessage(hwndRich, WM_SETREDRAW, TRUE, 0); + InvalidateRect(hwndRich, NULL, TRUE); + } + + // need to invalidate the window + if (bFlag) { + sel.cpMin = sel.cpMax = GetRichTextLength(hwndRich); + SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM)&sel); + SendMessage(hwndRich, WM_SETREDRAW, TRUE, 0); + InvalidateRect(hwndRich, NULL, TRUE); + } +} diff --git a/plugins/TabSRMM/src/chat_main.cpp b/plugins/TabSRMM/src/chat_main.cpp new file mode 100644 index 0000000000..7ff48d9c6e --- /dev/null +++ b/plugins/TabSRMM/src/chat_main.cpp @@ -0,0 +1,262 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Miranda NG: the free IM client for Microsoft* Windows* +// +// Copyright (ñ) 2012-17 Miranda NG project, +// Copyright (c) 2000-09 Miranda ICQ/IM project, +// all portions of this codebase are copyrighted to the people +// listed in contributors.txt. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// you should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// part of tabSRMM messaging plugin for Miranda. +// +// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors +// +// chat module exports and functions to load/unload the plugin. + +#include "stdafx.h" + +HANDLE g_hWindowList; +HMENU g_hMenu = NULL; + +CHAT_MANAGER *pci; +TMUCSettings g_Settings; + +static void OnCreateSession(SESSION_INFO *si, MODULEINFO *mi) +{ + si->bFilterEnabled = db_get_b(si->hContact, "Chat", "FilterEnabled", M.GetByte("Chat", "FilterEnabled", 0)); + + Chat_SetFilters(si); + if (mi) { + mi->idleTimeStamp = time(0); + pci->SM_BroadcastMessage(mi->pszModule, GC_UPDATESTATUSBAR, 0, 1, TRUE); + } +} + +static void OnReplaceSession(SESSION_INFO *si) +{ + if (si->hContact) + Chat_SetFilters(si); + if (si->hWnd) + RedrawWindow(GetDlgItem(si->hWnd, IDC_LIST), NULL, NULL, RDW_INVALIDATE); +} + +static void OnSetTopic(SESSION_INFO *si) +{ + if (si->hWnd) + si->dat->m_pPanel.Invalidate(true); +} + +static void OnNewUser(SESSION_INFO *si, USERINFO*) +{ + if (si->hWnd) { + SendMessage(si->hWnd, GC_UPDATENICKLIST, 0, 0); + if (si->dat) + si->dat->GetMyNick(); + } +} + +static void OnChangeNick(SESSION_INFO *si) +{ + if (si->hWnd) { + if (si->dat) + si->dat->GetMyNick(); + SendMessage(si->hWnd, GC_UPDATESTATUSBAR, 0, 0); + } +} + +static void OnCreateModule(MODULEINFO *mi) +{ + mi->idleTimeStamp = time(0); +} + +static void OnLoadSettings() +{ + g_Settings.iEventLimitThreshold = db_get_w(NULL, CHAT_MODULE, "LogLimitThreshold", 20); + g_Settings.dwIconFlags = M.GetDword(CHAT_MODULE, "IconFlags", 0x0000); + g_Settings.bOpenInDefault = M.GetBool(CHAT_MODULE, "DefaultContainer", true); + g_Settings.UserListColors[CHAT_STATUS_NORMAL] = M.GetDword(CHATFONT_MODULE, "Font18Col", RGB(0, 0, 0)); + g_Settings.UserListColors[CHAT_STATUS_AWAY] = M.GetDword(CHATFONT_MODULE, "Font19Col", RGB(170, 170, 170)); + g_Settings.UserListColors[CHAT_STATUS_OFFLINE] = M.GetDword(CHATFONT_MODULE, "Font5Col", RGB(160, 90, 90)); + g_Settings.bBBCodeInPopups = M.GetBool(CHAT_MODULE, "BBCodeInPopups", false); + g_Settings.bClassicIndicators = M.GetBool(CHAT_MODULE, "ClassicIndicators", false); + g_Settings.bLogClassicIndicators = M.GetBool(CHAT_MODULE, "LogClassicIndicators", false); + g_Settings.bAlternativeSorting = M.GetBool(CHAT_MODULE, "AlternativeSorting", true); + g_Settings.bAnnoyingHighlight = M.GetBool(CHAT_MODULE, "AnnoyingHighlight", false); + g_Settings.bCreateWindowOnHighlight = M.GetBool(CHAT_MODULE, "CreateWindowOnHighlight", true); + + g_Settings.bLogSymbols = M.GetBool(CHAT_MODULE, "LogSymbols", true); + g_Settings.bClickableNicks = M.GetBool(CHAT_MODULE, "ClickableNicks", true); + g_Settings.bColorizeNicks = M.GetBool(CHAT_MODULE, "ColorizeNicks", true); + g_Settings.bColorizeNicksInLog = M.GetBool(CHAT_MODULE, "ColorizeNicksInLog", true); + g_Settings.bScaleIcons = M.GetBool(CHAT_MODULE, "ScaleIcons", true); + + g_Settings.bDoubleClick4Privat = M.GetBool(CHAT_MODULE, "DoubleClick4Privat", false); + g_Settings.bShowContactStatus = M.GetBool(CHAT_MODULE, "ShowContactStatus", true); + g_Settings.bContactStatusFirst = M.GetBool(CHAT_MODULE, "ContactStatusFirst", false); + + g_Settings.bNewLineAfterNames = M.GetBool(CHAT_MODULE, "NewlineAfterNames", false); + g_Settings.bUseCommaAsColon = M.GetBool(CHAT_MODULE, "UseCommaAsColon", false); + + replaceStrW(g_Settings.pszLogDir, M.getChatLogPath()); + + g_Settings.LogIconSize = (g_Settings.bScaleIcons) ? 12 : 16; + + // nicklist + if (g_Settings.UserListFonts[0]) { + DeleteObject(g_Settings.UserListFonts[CHAT_STATUS_NORMAL]); + DeleteObject(g_Settings.UserListFonts[CHAT_STATUS_AWAY]); + DeleteObject(g_Settings.UserListFonts[CHAT_STATUS_OFFLINE]); + } + + LOGFONT lf; + pci->LoadMsgDlgFont(18, &lf, NULL); + g_Settings.UserListFonts[CHAT_STATUS_NORMAL] = CreateFontIndirect(&lf); + + pci->LoadMsgDlgFont(19, &lf, NULL); + g_Settings.UserListFonts[CHAT_STATUS_AWAY] = CreateFontIndirect(&lf); + + pci->LoadMsgDlgFont(5, &lf, NULL); + g_Settings.UserListFonts[CHAT_STATUS_OFFLINE] = CreateFontIndirect(&lf); + + int ih = GetTextPixelSize(L"AQGglo", g_Settings.UserListFonts[CHAT_STATUS_NORMAL], false); + int ih2 = GetTextPixelSize(L"AQGglo", g_Settings.UserListFonts[CHAT_STATUS_AWAY], false); + g_Settings.iNickListFontHeight = max(M.GetByte(CHAT_MODULE, "NicklistRowDist", 12), (ih > ih2 ? ih : ih2)); + + for (int i = 0; i < 5; i++) { + char szBuf[40]; + mir_snprintf(szBuf, "NickColor%d", i); + g_Settings.nickColors[i] = M.GetDword(CHAT_MODULE, szBuf, g_Settings.UserListColors[0]); + } + g_Settings.nickColors[5] = M.GetDword(CHAT_MODULE, "NickColor5", GetSysColor(COLOR_HIGHLIGHT)); + g_Settings.nickColors[6] = M.GetDword(CHAT_MODULE, "NickColor6", GetSysColor(COLOR_HIGHLIGHTTEXT)); + + if (g_Settings.SelectionBGBrush) + DeleteObject(g_Settings.SelectionBGBrush); + g_Settings.SelectionBGBrush = CreateSolidBrush(g_Settings.nickColors[5]); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void Chat_ModulesLoaded() +{ + g_Settings.hIconOverlay = LoadIconEx("overlay"); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// load the group chat module + +CHAT_MANAGER saveCI; + +static int CopyChatSetting(const char *szSetting, LPARAM param) +{ + LIST *szSettings = (LIST*)param; + szSettings->insert(mir_strdup(szSetting)); + return 0; +} + +static void CheckUpdate() +{ + // already converted? + int compat = db_get_b(NULL, "Compatibility", "TabChatFonts", 0); + if (compat >= 3) + return; + + if (compat == 0) { + LIST szSettings(120); + db_enum_settings(NULL, CopyChatSetting, CHAT_OLDFONTMODULE, &szSettings); + + DBVARIANT dbv; + for (int i = szSettings.getCount() - 1; i >= 0; i--) { + char *p = szSettings[i]; + db_get(NULL, CHAT_OLDFONTMODULE, p, &dbv); + db_set(NULL, CHATFONT_MODULE, p, &dbv); + db_free(&dbv); + mir_free(p); + } + + db_delete_module(NULL, CHAT_OLDFONTMODULE); + compat++; + } + + if (compat == 1) { + DWORD oldBackColor = db_get_dw(0, FONTMODULE, "BkgColourMUC", SRMSGDEFSET_BKGCOLOUR); + db_set_dw(NULL, CHAT_MODULE, "ColorLogBG", oldBackColor); + db_unset(0, FONTMODULE, "BkgColourMUC"); + compat++; + } + + if (compat == 2) { + COLORREF color0 = M.GetDword(CHAT_MODULE, "NickColor2", 0); + COLORREF color2 = M.GetDword(CHAT_MODULE, "NickColor0", 0); + db_set_dw(NULL, CHAT_MODULE, "NickColor0", color0); + db_set_dw(NULL, CHAT_MODULE, "NickColor2", color2); + compat++; + } + + db_set_b(NULL, "Compatibility", "TabChatFonts", 3); +} + +// load the module +int Chat_Load() +{ + CheckUpdate(); + + CHAT_MANAGER_INITDATA data = { &g_Settings, sizeof(MODULEINFO), sizeof(SESSION_INFO), LPGENW("Message Sessions") L"/" LPGENW("Group chats"), FONTMODE_ALTER }; + pci = Chat_GetInterface(&data); + saveCI = *pci; + pci->OnCreateModule = OnCreateModule; + pci->OnNewUser = OnNewUser; + + pci->OnSetTopic = OnSetTopic; + + pci->OnCreateSession = OnCreateSession; + pci->OnReplaceSession = OnReplaceSession; + + pci->OnChangeNick = OnChangeNick; + pci->ShowRoom = ShowRoom; + pci->OnLoadSettings = OnLoadSettings; + + // this operation is unsafe, that's why we restore the old pci state on exit + pci->DoSoundsFlashPopupTrayStuff = DoSoundsFlashPopupTrayStuff; + pci->IsHighlighted = IsHighlighted; + pci->LogToFile = LogToFile; + pci->DoPopup = DoPopup; + pci->ShowPopup = ShowPopup; + pci->Log_CreateRtfHeader = Log_CreateRtfHeader; + pci->UM_CompareItem = UM_CompareItem; + pci->ReloadSettings(); + + g_hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU)); + + g_Settings.Highlight = new CMUCHighlight(); + return 0; +} + +// unload the module. final cleanup +int Chat_Unload(void) +{ + if (g_Settings.SelectionBGBrush) + DeleteObject(g_Settings.SelectionBGBrush); + + for (int i = 0; i < _countof(g_Settings.UserListFonts); i++) + if (g_Settings.UserListFonts[i]) + DeleteObject(g_Settings.UserListFonts[i]); + + delete g_Settings.Highlight; + + DestroyMenu(g_hMenu); + return 0; +} diff --git a/plugins/TabSRMM/src/chat_manager.cpp b/plugins/TabSRMM/src/chat_manager.cpp new file mode 100644 index 0000000000..3a93a8a444 --- /dev/null +++ b/plugins/TabSRMM/src/chat_manager.cpp @@ -0,0 +1,123 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Miranda NG: the free IM client for Microsoft* Windows* +// +// Copyright (ñ) 2012-17 Miranda NG project, +// Copyright (c) 2000-09 Miranda ICQ/IM project, +// all portions of this codebase are copyrighted to the people +// listed in contributors.txt. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// you should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// part of tabSRMM messaging plugin for Miranda. +// +// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors + +#include "stdafx.h" + +static int sttCompareNicknames(const wchar_t *s1, const wchar_t *s2) +{ + if (s2 == NULL) + return 1; + + // skip rubbish + while (*s1 && !iswalpha(*s1)) ++s1; + while (*s2 && !iswalpha(*s2)) ++s2; + + // are there ~0veRy^kEwL_n1kz? + if (!*s1 && !*s2) return 0; + if (!*s1 && *s2) return +1; + if (*s1 && !*s2) return -1; + + // compare tails + return mir_wstrcmpi(s1, s2); +} + +int UM_CompareItem(USERINFO *u1, const wchar_t* pszNick, WORD wStatus) +{ + WORD dw1 = u1->Status; + WORD dw2 = wStatus; + + for (int i = 0; i < 8; i++) { + if ((dw1 & 1) && !(dw2 & 1)) + return -1; + if ((dw2 & 1) && !(dw1 & 1)) + return 1; + if ((dw1 & 1) && (dw2 & 1)) { + if (g_Settings.bAlternativeSorting) + return sttCompareNicknames(u1->pszNick, pszNick); + else + return mir_wstrcmp(u1->pszNick, pszNick); + } + dw1 = dw1 >> 1; + dw2 = dw2 >> 1; + } + + if (g_Settings.bAlternativeSorting) + return sttCompareNicknames(u1->pszNick, pszNick); + return mir_wstrcmp(u1->pszNick, pszNick); +} + +//--------------------------------------------------- +// Session Manager functions +// +// Keeps track of all sessions and its windows +//--------------------------------------------------- + +BOOL SM_ReconfigureFilters() +{ + for (SESSION_INFO *si = pci->wndList; si; si = si->next) + Chat_SetFilters(si); + + return TRUE; +} + +SESSION_INFO* SM_FindSessionByHWND(HWND hWnd) +{ + for (SESSION_INFO *si = pci->wndList; si; si = si->next) + if (si->hWnd == hWnd) + return si; + + return NULL; +} + +SESSION_INFO* SM_FindSessionByHCONTACT(MCONTACT h) +{ + for (SESSION_INFO *si = pci->wndList; si; si = si->next) + if (si->hContact == h) + return si; + + return NULL; +} + +SESSION_INFO* SM_FindSessionAutoComplete(const char* pszModule, SESSION_INFO* currSession, SESSION_INFO* prevSession, const wchar_t* pszOriginal, const wchar_t* pszCurrent) +{ + if (prevSession == NULL && my_strstri(currSession->ptszName, pszOriginal) == currSession->ptszName) + return currSession; + + wchar_t *pszName = NULL; + if (currSession == prevSession) + pszCurrent = pszOriginal; + + SESSION_INFO *pResult = NULL; + for (SESSION_INFO *si = pci->wndList; si; si = si->next) + if (si != currSession && !mir_strcmpi(pszModule, si->pszModule)) + if (my_strstri(si->ptszName, pszOriginal) == si->ptszName) + if (prevSession != si && mir_wstrcmpi(si->ptszName, pszCurrent) > 0 && (!pszName || mir_wstrcmpi(si->ptszName, pszName) < 0)) { + pResult = si; + pszName = si->ptszName; + } + + return pResult; +} diff --git a/plugins/TabSRMM/src/chat_options.cpp b/plugins/TabSRMM/src/chat_options.cpp new file mode 100644 index 0000000000..15d829834f --- /dev/null +++ b/plugins/TabSRMM/src/chat_options.cpp @@ -0,0 +1,1006 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Miranda NG: the free IM client for Microsoft* Windows* +// +// Copyright (ñ) 2012-17 Miranda NG project, +// Copyright (c) 2000-09 Miranda ICQ/IM project, +// all portions of this codebase are copyrighted to the people +// listed in contributors.txt. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// you should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// part of tabSRMM messaging plugin for Miranda. +// +// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors +// +// group chat options and generic font handling + +#include "stdafx.h" + +#define FONTF_BOLD 1 +#define FONTF_ITALIC 2 + +struct FontOptionsList +{ + wchar_t *szDescr; + COLORREF defColour; + wchar_t *szDefFace; + BYTE defCharset, defStyle; + char defSize; + COLORREF colour; + wchar_t szFace[LF_FACESIZE]; + BYTE charset, style; + char size; +}; + +struct ColorOptionsList +{ + int order; + wchar_t *tszGroup; + wchar_t *tszName; + char *szSetting; + COLORREF def; +}; + +/* +* note: bits 24-31 in default color indicates that color is a system color index +* (GetSysColor(default_color & 0x00ffffff)), not a rgb value. +*/ +static ColorOptionsList _clrs[] = { + { 0, LPGENW("Message Sessions"), LPGENW("Input area background"), "inputbg", SRMSGDEFSET_BKGCOLOUR }, + { 1, LPGENW("Message Sessions"), LPGENW("Log background"), SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR }, + { 0, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), LPGENW("Outgoing background"), "outbg", SRMSGDEFSET_BKGOUTCOLOUR }, + { 1, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), LPGENW("Incoming background"), "inbg", SRMSGDEFSET_BKGINCOLOUR }, + { 2, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), LPGENW("Status background"), "statbg", SRMSGDEFSET_BKGCOLOUR }, + { 3, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), LPGENW("Incoming background(old)"), "oldinbg", SRMSGDEFSET_BKGINCOLOUR }, + { 4, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), LPGENW("Outgoing background(old)"), "oldoutbg", SRMSGDEFSET_BKGOUTCOLOUR }, + { 5, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), LPGENW("Horizontal Grid Lines"), "hgrid", RGB(224, 224, 224) }, + { 0, LPGENW("Message Sessions") L"/" LPGENW("Info Panel"), LPGENW("Panel background low"), "ipfieldsbg", 0x62caff }, + { 1, LPGENW("Message Sessions") L"/" LPGENW("Info Panel"), LPGENW("Panel background high"), "ipfieldsbgHigh", 0xf0f0f0 }, + { 0, LPGENW("Message Sessions") L"/" LPGENW("Common colors"), LPGENW("Toolbar background high"), "tbBgHigh", 0 }, + { 1, LPGENW("Message Sessions") L"/" LPGENW("Common colors"), LPGENW("Toolbar background low"), "tbBgLow", 0 }, + { 2, LPGENW("Message Sessions") L"/" LPGENW("Common colors"), LPGENW("Window fill color"), "fillColor", 0 }, + { 3, LPGENW("Message Sessions") L"/" LPGENW("Common colors"), LPGENW("Text area borders"), "cRichBorders", 0 }, + { 4, LPGENW("Message Sessions") L"/" LPGENW("Common colors"), LPGENW("Aero glow effect"), "aeroGlow", RGB(40, 40, 255) }, + { 4, LPGENW("Message Sessions") L"/" LPGENW("Common colors"), LPGENW("Generic text color (only when fill color is set)"), "genericTxtClr", 0xff000000 | COLOR_BTNTEXT }, +}; + +static ColorOptionsList _tabclrs[] = { + { 0, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Normal text"), "tab_txt_normal", 0xff000000 | COLOR_BTNTEXT }, + { 1, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Active text"), "tab_txt_active", 0xff000000 | COLOR_BTNTEXT }, + { 2, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Hovered text"), "tab_txt_hottrack", 0xff000000 | COLOR_HOTLIGHT }, + { 3, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Unread text"), "tab_txt_unread", 0xff000000 | COLOR_HOTLIGHT }, + + { 4, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Normal background"), "tab_bg_normal", 0xff000000 | COLOR_3DFACE }, + { 5, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Active background"), "tab_bg_active", 0xff000000 | COLOR_3DFACE }, + { 6, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Hovered background"), "tab_bg_hottrack", 0xff000000 | COLOR_3DFACE }, + { 7, LPGENW("Message Sessions") L"/" LPGENW("Tabs"), LPGENW("Unread background"), "tab_bg_unread", 0xff000000 | COLOR_3DFACE } +}; + +extern LOGFONT lfDefault; + +static FontOptionsList IM_fontOptionsList[] = { + { LPGENW(">> Outgoing messages"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW(">> Outgoing misc events"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW("<< Incoming messages"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW("<< Incoming misc events"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW(">> Outgoing name"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, + { LPGENW(">> Outgoing timestamp"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, + { LPGENW("<< Incoming name"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, + { LPGENW("<< Incoming timestamp"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, + { LPGENW(">> Outgoing messages (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW(">> Outgoing misc events (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW("<< Incoming messages (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW("<< Incoming misc events (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW(">> Outgoing name (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, + { LPGENW(">> Outgoing timestamp (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, + { LPGENW("<< Incoming name (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, + { LPGENW("<< Incoming timestamp (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12 }, + { LPGENW("* Message Input Area"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW("* Status changes"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW("* Dividers"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW("* Error and warning messages"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW("* Symbols (incoming)"), RGB(50, 50, 50), L"Webdings", SYMBOL_CHARSET, 0, -12 }, + { LPGENW("* Symbols (outgoing)"), RGB(50, 50, 50), L"Webdings", SYMBOL_CHARSET, 0, -12 }, +}; + +static FontOptionsList IP_fontOptionsList[] = { + { LPGENW("Nickname"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW("UIN"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW("Status"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW("Protocol"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW("Contacts local time"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, + { LPGENW("Window caption (skinned mode)"), RGB(255, 255, 255), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12 }, +}; + +static FontOptionsList *fontOptionsList = IM_fontOptionsList; +static int fontCount = MSGDLGFONTCOUNT; + +struct branch_t +{ + wchar_t* szDescr; + char* szDBName; + int iMode; + BYTE bDefault; + HTREEITEM hItem; +}; +static branch_t branch1[] = { + { LPGENW("Open new chat rooms in the default container"), "DefaultContainer", 0, 1, NULL }, + { LPGENW("Flash window when someone speaks"), "FlashWindow", 0, 0, NULL }, + { LPGENW("Flash window when a word is highlighted"), "FlashWindowHighlight", 0, 1, NULL }, + { LPGENW("Create tabs or windows for highlight events"), "CreateWindowOnHighlight", 0, 0, NULL }, + { LPGENW("Activate chat window on highlight"), "AnnoyingHighlight", 0, 0, NULL }, + { LPGENW("Show list of users in the chat room"), "ShowNicklist", 0, 1, NULL }, + { LPGENW("Colorize nicknames in member list"), "ColorizeNicks", 0, 1, NULL }, + { LPGENW("Show button menus when right clicking the buttons"), "RightClickFilter", 0, 1, NULL }, + { LPGENW("Show topic as status message on the contact list"), "TopicOnClist", 0, 1, NULL }, + { LPGENW("Do not pop up the window when joining a chat room"), "PopupOnJoin", 0, 0, NULL }, + { LPGENW("Hide or show the window by double click in the contact list"), "ToggleVisibility", 0, 0, NULL }, + { LPGENW("Sync splitter position with standard IM sessions"), "SyncSplitter", 0, 0, NULL }, + { LPGENW("Show contact's status modes if supported by the protocol"), "ShowContactStatus", 0, 1, NULL }, + { LPGENW("Display contact's status icon before user role icon"), "ContactStatusFirst", 0, 0, NULL }, + { LPGENW("Use IRC style status indicators in the nick list"), "ClassicIndicators", 0, 0, NULL }, + { LPGENW("Use alternative sorting method in member list"), "AlternativeSorting", 0, 1, NULL } +}; + +static branch_t branch2[] = { + { LPGENW("Prefix all events with a timestamp"), "ShowTimeStamp", 0, 1, NULL }, + { LPGENW("Timestamp only when event time differs"), "ShowTimeStampIfChanged", 0, 0, NULL }, + { LPGENW("Timestamp has same color as the event"), "TimeStampEventColour", 0, 0, NULL }, + { LPGENW("Indent the second line of a message"), "LogIndentEnabled", 0, 1, NULL }, + { LPGENW("Limit user names in the message log to 20 characters"), "LogLimitNames", 0, 1, NULL }, + { LPGENW("Add a colon (:) to auto-completed user names"), "AddColonToAutoComplete", 0, 1, NULL }, + { LPGENW("Add a comma instead of a colon to auto-completed user names"), "UseCommaAsColon", 0, 0, NULL }, + { LPGENW("Start private conversation on double click in nick list (insert nick if unchecked)"), "DoubleClick4Privat", 0, 0, NULL }, + { LPGENW("Strip colors from messages in the log"), "StripFormatting", 0, 0, NULL }, + { LPGENW("Enable the 'event filter' for new rooms"), "FilterEnabled", 0, 0, NULL }, + { LPGENW("Use IRC style status indicators in the log"), "LogClassicIndicators", 0, 0, NULL }, + { LPGENW("Allow clickable user names in the message log"), "ClickableNicks", 0, 1, NULL }, + { LPGENW("Add new line after names"), "NewlineAfterNames", 0, 0, NULL }, + { LPGENW("Colorize user names in message log"), "ColorizeNicksInLog", 0, 1, NULL }, + { LPGENW("Scale down icons to 10x10 pixels in the chat log"), "ScaleIcons", 0, 1, NULL } +}; + +static HWND hPathTip = 0; + +void LoadMsgDlgFont(int section, int i, LOGFONT *lf, COLORREF* colour, char *szMod) +{ + char str[32]; + int style; + int j = (i >= 100 ? i - 100 : i); + + FontOptionsList *fol = fontOptionsList; + switch (section) { + case FONTSECTION_IM: fol = IM_fontOptionsList; break; + case FONTSECTION_IP: fol = IP_fontOptionsList; break; + } + + if (colour) { + mir_snprintf(str, "Font%dCol", i); + *colour = M.GetDword(szMod, str, fol[j].defColour); + } + + if (lf) { + mir_snprintf(str, "Font%dSize", i); + lf->lfHeight = (char)M.GetByte(szMod, str, fol[j].defSize); + lf->lfWidth = 0; + lf->lfEscapement = 0; + lf->lfOrientation = 0; + mir_snprintf(str, "Font%dSty", i); + style = M.GetByte(szMod, str, fol[j].defStyle); + if (i == MSGFONTID_MESSAGEAREA && section == FONTSECTION_IM && M.GetByte("inputFontFix", 1) == 1) { + lf->lfWeight = FW_NORMAL; + lf->lfItalic = 0; + lf->lfUnderline = 0; + lf->lfStrikeOut = 0; + } + else { + lf->lfWeight = style & FONTF_BOLD ? FW_BOLD : FW_NORMAL; + lf->lfItalic = style & FONTF_ITALIC ? 1 : 0; + lf->lfUnderline = style & FONTF_UNDERLINE ? 1 : 0; + lf->lfStrikeOut = style & FONTF_STRIKEOUT ? 1 : 0; + } + mir_snprintf(str, "Font%dSet", i); + lf->lfCharSet = M.GetByte(szMod, str, fol[j].defCharset); + lf->lfOutPrecision = OUT_DEFAULT_PRECIS; + lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf->lfQuality = DEFAULT_QUALITY; + lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; + mir_snprintf(str, "Font%d", i); + if ((i == 17 && !mir_strcmp(szMod, CHATFONT_MODULE)) || ((i == 20 || i == 21) && !mir_strcmp(szMod, FONTMODULE))) { + lf->lfCharSet = SYMBOL_CHARSET; + wcsncpy_s(lf->lfFaceName, L"Webdings", _TRUNCATE); + } + else { + ptrW tszDefFace(db_get_wsa(NULL, szMod, str)); + if (tszDefFace == NULL) + wcsncpy_s(lf->lfFaceName, fol[j].szDefFace, _TRUNCATE); + else + wcsncpy_s(lf->lfFaceName, tszDefFace, _TRUNCATE); + } + } +} + +static HTREEITEM InsertBranch(HWND hwndTree, wchar_t* pszDescr, BOOL bExpanded) +{ + TVINSERTSTRUCT tvis; + tvis.hParent = NULL; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_TEXT | TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvis.item.pszText = TranslateW(pszDescr); + tvis.item.stateMask = TVIS_EXPANDED | TVIS_BOLD; + tvis.item.state = (bExpanded ? TVIS_EXPANDED : 0) | TVIS_BOLD; + tvis.item.iImage = tvis.item.iSelectedImage = (bExpanded ? IMG_GRPOPEN : IMG_GRPCLOSED); + return TreeView_InsertItem(hwndTree, &tvis); +} + +static void FillBranch(HWND hwndTree, HTREEITEM hParent, branch_t *branch, int nValues, DWORD defaultval) +{ + if (hParent == 0) + return; + + TVINSERTSTRUCT tvis = { 0 }; + + for (int i = 0; i < nValues; i++) { + tvis.hParent = hParent; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvis.item.pszText = TranslateW(branch[i].szDescr); + if (branch[i].iMode) + tvis.item.iImage = tvis.item.iSelectedImage = ((((M.GetDword(CHAT_MODULE, branch[i].szDBName, defaultval) & branch[i].iMode) & branch[i].iMode) != 0) ? IMG_CHECK : IMG_NOCHECK); + else + tvis.item.iImage = tvis.item.iSelectedImage = ((M.GetByte(CHAT_MODULE, branch[i].szDBName, branch[i].bDefault) != 0) ? IMG_CHECK : IMG_NOCHECK); + branch[i].hItem = TreeView_InsertItem(hwndTree, &tvis); + } +} + +static void SaveBranch(HWND hwndTree, branch_t *branch, int nValues) +{ + TVITEM tvi = { 0 }; + BYTE bChecked; + DWORD iState = 0; + + for (int i = 0; i < nValues; i++) { + tvi.mask = TVIF_HANDLE | TVIF_IMAGE; + tvi.hItem = branch[i].hItem; + TreeView_GetItem(hwndTree, &tvi); + bChecked = ((tvi.iImage == IMG_CHECK) ? 1 : 0); + if (branch[i].iMode) { + if (bChecked) + iState |= branch[i].iMode; + if (iState & GC_EVENT_ADDSTATUS) + iState |= GC_EVENT_REMOVESTATUS; + db_set_dw(0, CHAT_MODULE, branch[i].szDBName, iState); + } + else db_set_b(0, CHAT_MODULE, branch[i].szDBName, bChecked); + } +} + +static INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM) +{ + char szDir[MAX_PATH]; + switch (uMsg) { + case BFFM_INITIALIZED: + SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)M.getUserDir()); + break; + + case BFFM_SELCHANGED: + if (SHGetPathFromIDListA((LPITEMIDLIST)lp, szDir)) + SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)szDir); + break; + } + return 0; +} + +static IconItem _icons[] = +{ + { LPGEN("Window Icon"), "chat_window", IDI_CHANMGR }, + { LPGEN("Icon overlay"), "chat_overlay", IDI_OVERLAY }, + + { LPGEN("Status 1 (10x10)"), "chat_status0", IDI_STATUS0 }, + { LPGEN("Status 2 (10x10)"), "chat_status1", IDI_STATUS1 }, + { LPGEN("Status 3 (10x10)"), "chat_status2", IDI_STATUS2 }, + { LPGEN("Status 4 (10x10)"), "chat_status3", IDI_STATUS3 }, + { LPGEN("Status 5 (10x10)"), "chat_status4", IDI_STATUS4 }, + { LPGEN("Status 6 (10x10)"), "chat_status5", IDI_STATUS5 } +}; + +static IconItem _logicons[] = +{ + { LPGEN("Message in (10x10)"), "chat_log_message_in", IDI_MESSAGE }, + { LPGEN("Message out (10x10)"), "chat_log_message_out", IDI_MESSAGEOUT }, + { LPGEN("Action (10x10)"), "chat_log_action", IDI_ACTION }, + { LPGEN("Add Status (10x10)"), "chat_log_addstatus", IDI_ADDSTATUS }, + { LPGEN("Remove Status (10x10)"), "chat_log_removestatus", IDI_REMSTATUS }, + { LPGEN("Join (10x10)"), "chat_log_join", IDI_JOIN }, + { LPGEN("Leave (10x10)"), "chat_log_part", IDI_PART }, + { LPGEN("Quit (10x10)"), "chat_log_quit", IDI_QUIT }, + { LPGEN("Kick (10x10)"), "chat_log_kick", IDI_KICK }, + { LPGEN("Notice (10x10)"), "chat_log_notice", IDI_NOTICE }, + { LPGEN("Nickchange (10x10)"), "chat_log_nick", IDI_NICK }, + { LPGEN("Topic (10x10)"), "chat_log_topic", IDI_TOPIC }, + { LPGEN("Highlight (10x10)"), "chat_log_highlight", IDI_HIGHLIGHT }, + { LPGEN("Information (10x10)"), "chat_log_info", IDI_INFO } +}; + +// add icons to the skinning module +void Chat_AddIcons(void) +{ + Icon_Register(g_hIconDLL, LPGEN("Message Sessions") "/" LPGEN("Group chat windows"), _icons, _countof(_icons)); + Icon_Register(g_hIconDLL, LPGEN("Message Sessions") "/" LPGEN("Group chat log"), _logicons, _countof(_logicons)); + pci->MM_IconsChanged(); +} + +/* + * get icon by name from the core icon library service + */ +HICON LoadIconEx(char *pszIcoLibName) +{ + char szTemp[256]; + mir_snprintf(szTemp, "chat_%s", pszIcoLibName); + return IcoLib_GetIcon(szTemp); +} + +static void InitSetting(wchar_t* &ppPointer, const char *pszSetting, const wchar_t *pszDefault) +{ + ptrW val(db_get_wsa(NULL, CHAT_MODULE, pszSetting)); + replaceStrW(ppPointer, (val != NULL) ? val : pszDefault); +} + +#define OPT_FIXHEADINGS (WM_USER+1) + +static UINT _o1controls[] = { IDC_CHECKBOXES, IDC_GROUP, IDC_STATIC_ADD }; + +HWND CreateToolTip(HWND hwndParent, LPTSTR ptszText, LPTSTR ptszTitle) +{ + HWND hwndTT = CreateWindowEx(WS_EX_TOPMOST, + TOOLTIPS_CLASS, NULL, + WS_POPUP | TTS_NOPREFIX, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + hwndParent, NULL, g_hInst, NULL); + + SetWindowPos(hwndTT, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + + TOOLINFO ti = { 0 }; + ti.cbSize = sizeof(TOOLINFO); + ti.uFlags = TTF_SUBCLASS | TTF_CENTERTIP; + ti.hwnd = hwndParent; + ti.hinst = g_hInst; + ti.lpszText = ptszText; + GetClientRect(hwndParent, &ti.rect); + ti.rect.left = -65; + + SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM)&ti); + SendMessage(hwndTT, TTM_SETTITLE, 1, (LPARAM)ptszTitle); + SendMessage(hwndTT, TTM_SETMAXTIPWIDTH, 0, (LPARAM)640); + return hwndTT; +} + +INT_PTR CALLBACK DlgProcOptions1(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + static HTREEITEM hListHeading1 = 0; + static HTREEITEM hListHeading2 = 0; + + switch (uMsg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHECKBOXES), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHECKBOXES), GWL_STYLE) | (TVS_NOHSCROLL)); + /* Replace image list, destroy old. */ + ImageList_Destroy(TreeView_SetImageList(GetDlgItem(hwndDlg, IDC_CHECKBOXES), CreateStateImageList(), TVSIL_NORMAL)); + + hListHeading1 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), TranslateT("Appearance and functionality of chat room windows"), TRUE); + hListHeading2 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), TranslateT("Appearance of the message log"), TRUE); + + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading1, branch1, _countof(branch1), 0x0000); + FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2, branch2, _countof(branch2), 0x0000); + + wchar_t* pszGroup = NULL; + InitSetting(pszGroup, "AddToGroup", L"Chat rooms"); + SetDlgItemText(hwndDlg, IDC_GROUP, pszGroup); + mir_free(pszGroup); + } + break; + + case WM_COMMAND: + if ((LOWORD(wParam) == IDC_GROUP) && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) + return 0; + + if (lParam != 0) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->idFrom) { + case IDC_CHECKBOXES: + return TreeViewHandleClick(hwndDlg, ((LPNMHDR)lParam)->hwndFrom, wParam, lParam); + break; + + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: + int iLen; + wchar_t *pszText = NULL; + BYTE b; + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_GROUP)); + if (iLen > 0) { + pszText = (wchar_t*)mir_realloc(pszText, (iLen + 2) * sizeof(wchar_t)); + GetDlgItemText(hwndDlg, IDC_GROUP, pszText, iLen + 1); + db_set_ws(NULL, CHAT_MODULE, "AddToGroup", pszText); + } + else db_set_ws(NULL, CHAT_MODULE, "AddToGroup", L""); + + mir_free(pszText); + + b = M.GetByte(CHAT_MODULE, "Tabs", 1); + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch1, _countof(branch1)); + SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch2, _countof(branch2)); + + pci->ReloadSettings(); + pci->MM_IconsChanged(); + pci->MM_FontsChanged(); + pci->SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE); + SM_ReconfigureFilters(); + return TRUE; + } + } + break; + + case WM_DESTROY: + BYTE b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading1, TVIS_EXPANDED) & TVIS_EXPANDED ? 1 : 0; + db_set_b(0, CHAT_MODULE, "Branch1Exp", b); + b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2, TVIS_EXPANDED) & TVIS_EXPANDED ? 1 : 0; + db_set_b(0, CHAT_MODULE, "Branch2Exp", b); + TreeViewDestroy(GetDlgItem(hwndDlg, IDC_CHECKBOXES)); + } + return FALSE; +} + +static wchar_t* chatcolorsnames[] = +{ + LPGENW("Voiced"), + LPGENW("Half operators"), + LPGENW("Channel operators"), + LPGENW("Extended mode 1"), + LPGENW("Extended mode 2"), + LPGENW("Selection background"), + LPGENW("Selected text"), + LPGENW("Incremental search highlight") +}; + +void RegisterFontServiceFonts() +{ + char szTemp[100]; + LOGFONT lf; + FontIDW fid = { 0 }; + ColourIDW cid = { 0 }; + + fid.cbSize = sizeof(FontIDW); + cid.cbSize = sizeof(ColourIDW); + + strncpy(fid.dbSettingsGroup, FONTMODULE, _countof(fid.dbSettingsGroup)); + + for (int i = 0; i < _countof(IM_fontOptionsList); i++) { + fid.flags = FIDF_DEFAULTVALID | FIDF_ALLOWEFFECTS; + LoadMsgDlgFont(FONTSECTION_IM, i, &lf, &fontOptionsList[i].colour, FONTMODULE); + mir_snprintf(szTemp, "Font%d", i); + strncpy(fid.prefix, szTemp, _countof(fid.prefix)); + fid.order = i; + wcsncpy(fid.name, fontOptionsList[i].szDescr, _countof(fid.name)); + fid.deffontsettings.colour = fontOptionsList[i].colour; + fid.deffontsettings.size = (char)lf.lfHeight; + fid.deffontsettings.style = (lf.lfWeight >= FW_BOLD ? FONTF_BOLD : 0) | (lf.lfItalic ? FONTF_ITALIC : 0); + fid.deffontsettings.charset = lf.lfCharSet; + fid.flags = fid.flags & ~FIDF_CLASSMASK | (fid.deffontsettings.style&FONTF_BOLD ? FIDF_CLASSHEADER : FIDF_CLASSGENERAL); + wcsncpy(fid.deffontsettings.szFace, lf.lfFaceName, LF_FACESIZE); + wcsncpy(fid.backgroundGroup, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), _countof(fid.backgroundGroup)); + wcsncpy(fid.group, LPGENW("Message Sessions") L"/" LPGENW("Single Messaging"), _countof(fid.group)); + switch (i) { + case MSGFONTID_MYMSG: + case 1: + case MSGFONTID_MYNAME: + case MSGFONTID_MYTIME: + case 21: + wcsncpy(fid.backgroundName, LPGENW("Outgoing background"), _countof(fid.backgroundName)); + break; + case 8: + case 9: + case 12: + case 13: + wcsncpy(fid.backgroundName, LPGENW("Outgoing background(old)"), _countof(fid.backgroundName)); + break; + case 10: + case 11: + case 14: + case 15: + wcsncpy(fid.backgroundName, LPGENW("Incoming background(old)"), _countof(fid.backgroundName)); + break; + case MSGFONTID_MESSAGEAREA: + wcsncpy(fid.group, LPGENW("Message Sessions"), _countof(fid.group)); + wcsncpy(fid.backgroundGroup, LPGENW("Message Sessions"), _countof(fid.backgroundGroup)); + wcsncpy(fid.backgroundName, LPGENW("Input area background"), _countof(fid.backgroundName)); + fid.flags |= FIDF_DISABLESTYLES; + fid.flags &= ~FIDF_ALLOWEFFECTS; + break; + case 17: + wcsncpy(fid.backgroundName, LPGENW("Status background"), _countof(fid.backgroundName)); + break; + case 18: + wcsncpy(fid.backgroundGroup, LPGENW("Message Sessions"), _countof(fid.backgroundGroup)); + wcsncpy(fid.backgroundName, LPGENW("Log background"), _countof(fid.backgroundName)); + break; + case 19: + wcsncpy(fid.backgroundName, L"", _countof(fid.backgroundName)); + break; + default: + wcsncpy(fid.backgroundName, LPGENW("Incoming background"), _countof(fid.backgroundName)); + break; + } + Font_RegisterW(&fid); + } + + fontOptionsList = IP_fontOptionsList; + fid.flags = FIDF_DEFAULTVALID | FIDF_ALLOWEFFECTS; + wcsncpy(fid.group, LPGENW("Message Sessions") L"/" LPGENW("Info Panel"), _countof(fid.group)); + wcsncpy(fid.backgroundGroup, LPGENW("Message Sessions") L"/" LPGENW("Info Panel"), _countof(fid.backgroundGroup)); + wcsncpy(fid.backgroundName, LPGENW("Fields background"), _countof(fid.backgroundName)); + for (int i = 0; i < IPFONTCOUNT; i++) { + LoadMsgDlgFont(FONTSECTION_IP, i + 100, &lf, &fontOptionsList[i].colour, FONTMODULE); + mir_snprintf(szTemp, "Font%d", i + 100); + strncpy(fid.prefix, szTemp, _countof(fid.prefix)); + fid.order = i + 100; + wcsncpy(fid.name, fontOptionsList[i].szDescr, _countof(fid.name)); + fid.deffontsettings.colour = fontOptionsList[i].colour; + fid.deffontsettings.size = (char)lf.lfHeight; + fid.deffontsettings.style = (lf.lfWeight >= FW_BOLD ? FONTF_BOLD : 0) | (lf.lfItalic ? FONTF_ITALIC : 0); + fid.deffontsettings.charset = lf.lfCharSet; + fid.flags = fid.flags & ~FIDF_CLASSMASK | (fid.deffontsettings.style&FONTF_BOLD ? FIDF_CLASSHEADER : FIDF_CLASSGENERAL); + fid.deffontsettings.charset = lf.lfCharSet; + wcsncpy(fid.deffontsettings.szFace, lf.lfFaceName, LF_FACESIZE); + if (i == IPFONTCOUNT - 1) { + wcsncpy(fid.backgroundGroup, L"", _countof(fid.backgroundGroup)); + wcsncpy(fid.backgroundName, L"", _countof(fid.backgroundName)); + wcsncpy(fid.group, LPGENW("Message Sessions"), _countof(fid.group)); + } + Font_RegisterW(&fid); + } + + wcsncpy(cid.group, LPGENW("Message Sessions") L"/" LPGENW("Group chats"), _countof(cid.group)); + strncpy(cid.dbSettingsGroup, CHAT_MODULE, _countof(cid.dbSettingsGroup)); + for (int i = 0; i <= 7; i++) { + mir_snprintf(szTemp, "NickColor%d", i); + wcsncpy(cid.name, chatcolorsnames[i], _countof(cid.name)); + cid.order = i + 1; + strncpy(cid.setting, szTemp, _countof(cid.setting)); + switch (i) { + case 5: + cid.defcolour = GetSysColor(COLOR_HIGHLIGHT); + break; + case 6: + cid.defcolour = GetSysColor(COLOR_HIGHLIGHTTEXT); + break; + default: + cid.defcolour = RGB(0, 0, 0); + break; + } + Colour_RegisterW(&cid); + } + cid.order++; + wcsncpy_s(cid.name, LPGENW("Nick list background"), _TRUNCATE); + strncpy_s(cid.setting, "ColorNicklistBG", _TRUNCATE); + cid.defcolour = SRMSGDEFSET_BKGCOLOUR; + Colour_RegisterW(&cid); + + cid.order++; + wcsncpy_s(cid.name, LPGENW("Group chat log background"), _TRUNCATE); + strncpy_s(cid.setting, "ColorLogBG", _TRUNCATE); + Colour_RegisterW(&cid); + + // static colors (info panel, tool bar background etc...) + strncpy(fid.dbSettingsGroup, FONTMODULE, _countof(fid.dbSettingsGroup)); + strncpy(cid.dbSettingsGroup, FONTMODULE, _countof(fid.dbSettingsGroup)); + + for (int i = 0; i < _countof(_clrs); i++) { + cid.order = _clrs[i].order; + wcsncpy(cid.group, _clrs[i].tszGroup, _countof(fid.group)); + wcsncpy(cid.name, _clrs[i].tszName, _countof(cid.name)); + strncpy(cid.setting, _clrs[i].szSetting, _countof(cid.setting)); + if (_clrs[i].def & 0xff000000) + cid.defcolour = GetSysColor(_clrs[i].def & 0x000000ff); + else + cid.defcolour = _clrs[i].def; + Colour_RegisterW(&cid); + } + + strncpy(cid.dbSettingsGroup, SRMSGMOD_T, _countof(fid.dbSettingsGroup)); + + // text and background colors for tabs + for (int i = 0; i < _countof(_tabclrs); i++) { + cid.order = _tabclrs[i].order; + wcsncpy(cid.group, _tabclrs[i].tszGroup, _countof(fid.group)); + wcsncpy(cid.name, _tabclrs[i].tszName, _countof(cid.name)); + strncpy(cid.setting, _tabclrs[i].szSetting, _countof(cid.setting)); + if (_tabclrs[i].def & 0xff000000) + cid.defcolour = GetSysColor(_tabclrs[i].def & 0x000000ff); + else + cid.defcolour = _tabclrs[i].def; + + Colour_RegisterW(&cid); + } +} + +int FontServiceFontsChanged(WPARAM, LPARAM) +{ + PluginConfig.reloadSettings(); + CSkin::initAeroEffect(); + CacheMsgLogIcons(); + CacheLogFonts(); + FreeTabConfig(); + ReloadTabConfig(); + Skin->setupAeroSkins(); + M.BroadcastMessage(DM_OPTIONSAPPLIED, 1, 0); + return 0; +} + +static UINT _o2chatcontrols[] = +{ + IDC_CHAT_SPIN2, IDC_LIMIT, IDC_CHAT_SPIN4, IDC_LOGTIMESTAMP, IDC_TIMESTAMP, + IDC_OUTSTAMP, IDC_FONTCHOOSE, IDC_LOGGING, IDC_LOGDIRECTORY, IDC_INSTAMP, IDC_CHAT_SPIN2, IDC_CHAT_SPIN3, IDC_NICKROW2, IDC_LOGLIMIT, + IDC_STATIC110, IDC_STATIC112, 0 +}; + +static UINT _o3chatcontrols[] = { 0 }; + +INT_PTR CALLBACK DlgProcOptions2(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN2, UDM_SETRANGE, 0, MAKELONG(5000, 0)); + SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN2, UDM_SETPOS, 0, MAKELONG(db_get_w(NULL, CHAT_MODULE, "LogLimit", 100), 0)); + SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN3, UDM_SETRANGE, 0, MAKELONG(255, 10)); + SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN3, UDM_SETPOS, 0, MAKELONG(M.GetByte(CHAT_MODULE, "NicklistRowDist", 12), 0)); + SetDlgItemText(hwndDlg, IDC_LOGTIMESTAMP, g_Settings.pszTimeStampLog); + SetDlgItemText(hwndDlg, IDC_TIMESTAMP, g_Settings.pszTimeStamp); + SetDlgItemText(hwndDlg, IDC_OUTSTAMP, g_Settings.pszOutgoingNick); + SetDlgItemText(hwndDlg, IDC_INSTAMP, g_Settings.pszIncomingNick); + CheckDlgButton(hwndDlg, IDC_LOGGING, g_Settings.bLoggingEnabled ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, g_Settings.pszLogDir); + Utils::enableDlgControl(hwndDlg, IDC_LOGDIRECTORY, g_Settings.bLoggingEnabled); + Utils::enableDlgControl(hwndDlg, IDC_FONTCHOOSE, g_Settings.bLoggingEnabled); + SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN4, UDM_SETRANGE, 0, MAKELONG(10000, 0)); + SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN4, UDM_SETPOS, 0, MAKELONG(db_get_w(NULL, CHAT_MODULE, "LoggingLimit", 100), 0)); + Utils::enableDlgControl(hwndDlg, IDC_LIMIT, g_Settings.bLoggingEnabled); + + wchar_t tszTooltipText[2048]; + + mir_snwprintf(tszTooltipText, + L"%s - %s\n%s - %s\n%s - %s\n%s - %s\n\n" + L"%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n\n" + L"%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s\n%s - %s", + // contact vars + L"%nick%", TranslateT("nick of current contact (if defined)"), + L"%proto%", TranslateT("protocol name of current contact (if defined). Account name is used when protocol supports multiple accounts"), + L"%accountname%", TranslateT("user-defined account name of current contact (if defined)."), + L"%userid%", TranslateT("user ID of current contact (if defined). It is like UIN for ICQ, JID for Jabber, etc."), + // global vars + L"%miranda_path%", TranslateT("path to Miranda root folder"), + L"%miranda_profilesdir%", TranslateT("path to folder containing Miranda profiles"), + L"%miranda_profilename%", TranslateT("name of current Miranda profile (filename, without extension)"), + L"%miranda_userdata%", TranslateT("will return parsed string %miranda_profilesdir%\\%miranda_profilename%"), + L"%miranda_logpath%", TranslateT("will return parsed string %miranda_userdata%\\Logs"), + L"%appdata%", TranslateT("same as environment variable %APPDATA% for currently logged-on Windows user"), + L"%username%", TranslateT("username for currently logged-on Windows user"), + L"%mydocuments%", TranslateT("\"My Documents\" folder for currently logged-on Windows user"), + L"%desktop%", TranslateT("\"Desktop\" folder for currently logged-on Windows user"), + L"%xxxxxxx%", TranslateT("any environment variable defined in current Windows session (like %systemroot%, %allusersprofile%, etc.)"), + // date/time vars + L"%d%", TranslateT("day of month, 1-31"), + L"%dd%", TranslateT("day of month, 01-31"), + L"%m%", TranslateT("month number, 1-12"), + L"%mm%", TranslateT("month number, 01-12"), + L"%mon%", TranslateT("abbreviated month name"), + L"%month%", TranslateT("full month name"), + L"%yy%", TranslateT("year without century, 01-99"), + L"%yyyy%", TranslateT("year with century, 1901-9999"), + L"%wday%", TranslateT("abbreviated weekday name"), + L"%weekday%", TranslateT("full weekday name")); + hPathTip = CreateToolTip(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY), tszTooltipText, TranslateT("Variables")); + } + if (hPathTip) + SetTimer(hwndDlg, 0, 3000, NULL); + break; + + case WM_COMMAND: + if ((LOWORD(wParam) == IDC_INSTAMP + || LOWORD(wParam) == IDC_OUTSTAMP + || LOWORD(wParam) == IDC_TIMESTAMP + || LOWORD(wParam) == IDC_LOGLIMIT + || LOWORD(wParam) == IDC_NICKROW2 + || LOWORD(wParam) == IDC_LOGDIRECTORY + || LOWORD(wParam) == IDC_LIMIT + || LOWORD(wParam) == IDC_LOGTIMESTAMP) + && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0; + + // open the base directory for MUC logs, using a standard file selector + // dialog. Simply allows the user to view what log files are there + // and possibly delete archived logs. + switch (LOWORD(wParam)) { + case IDC_MUC_OPENLOGBASEDIR: + { + wchar_t tszTemp[MAX_PATH + 20]; + wcsncpy_s(tszTemp, g_Settings.pszLogDir, _TRUNCATE); + + wchar_t *p = tszTemp; + while (*p && (*p == '\\' || *p == '.')) + p++; + + if (*p) + if (wchar_t *p1 = wcschr(p, '\\')) + *p1 = 0; + + wchar_t tszInitialDir[_MAX_DRIVE + _MAX_PATH + 10]; + mir_snwprintf(tszInitialDir, L"%s%s", M.getChatLogPath(), p); + if (!PathFileExists(tszInitialDir)) + wcsncpy_s(tszInitialDir, M.getChatLogPath(), _TRUNCATE); + + wchar_t tszReturnName[MAX_PATH]; tszReturnName[0] = 0; + mir_snwprintf(tszTemp, L"%s%c*.*%c%c", TranslateT("All files"), 0, 0, 0); + + OPENFILENAME ofn = { 0 }; + ofn.lpstrInitialDir = tszInitialDir; + ofn.lpstrFilter = tszTemp; + ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; + ofn.lpstrFile = tszReturnName; + ofn.nMaxFile = MAX_PATH; + ofn.nMaxFileTitle = MAX_PATH; + ofn.Flags = OFN_HIDEREADONLY | OFN_DONTADDTORECENT; + ofn.lpstrDefExt = L"log"; + GetOpenFileName(&ofn); + } + break; + + case IDC_FONTCHOOSE: + { + wchar_t tszDirectory[MAX_PATH]; + LPMALLOC psMalloc; + + if (SUCCEEDED(CoGetMalloc(1, &psMalloc))) { + BROWSEINFO bi = { 0 }; + bi.hwndOwner = hwndDlg; + bi.pszDisplayName = tszDirectory; + bi.lpszTitle = TranslateT("Select folder"); + bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_EDITBOX | BIF_RETURNONLYFSDIRS; + bi.lpfn = BrowseCallbackProc; + bi.lParam = (LPARAM)tszDirectory; + + LPITEMIDLIST idList = SHBrowseForFolder(&bi); + if (idList) { + const wchar_t *szUserDir = M.getUserDir(); + SHGetPathFromIDList(idList, tszDirectory); + mir_wstrcat(tszDirectory, L"\\"); + + wchar_t tszTemp[MAX_PATH]; + PathToRelativeW(tszDirectory, tszTemp, szUserDir); + SetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, mir_wstrlen(tszTemp) > 1 ? tszTemp : DEFLOGFILENAME); + } + psMalloc->Free(idList); + psMalloc->Release(); + } + } + break; + + case IDC_LOGGING: + Utils::enableDlgControl(hwndDlg, IDC_LOGDIRECTORY, IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED ? TRUE : FALSE); + Utils::enableDlgControl(hwndDlg, IDC_FONTCHOOSE, IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED ? TRUE : FALSE); + Utils::enableDlgControl(hwndDlg, IDC_LIMIT, IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED ? TRUE : FALSE); + break; + } + + if (lParam != 0) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->idFrom == 0 && ((LPNMHDR)lParam)->code == PSN_APPLY) { + char *pszText = NULL; + + int iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY)); + if (iLen > 0) { + wchar_t *pszText1 = (wchar_t*)mir_alloc(iLen*sizeof(wchar_t) + 2); + GetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, pszText1, iLen + 1); + db_set_ws(NULL, CHAT_MODULE, "LogDirectory", pszText1); + mir_free(pszText1); + g_Settings.bLoggingEnabled = IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED; + db_set_b(0, CHAT_MODULE, "LoggingEnabled", g_Settings.bLoggingEnabled); + } + else { + db_unset(NULL, CHAT_MODULE, "LogDirectory"); + db_set_b(0, CHAT_MODULE, "LoggingEnabled", 0); + } + pci->SM_InvalidateLogDirectories(); + + iLen = SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN4, UDM_GETPOS, 0, 0); + db_set_w(NULL, CHAT_MODULE, "LoggingLimit", (WORD)iLen); + + iLen = SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN3, UDM_GETPOS, 0, 0); + if (iLen > 0) + db_set_b(0, CHAT_MODULE, "NicklistRowDist", (BYTE)iLen); + else + db_unset(NULL, CHAT_MODULE, "NicklistRowDist"); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOGTIMESTAMP)); + if (iLen > 0) { + pszText = (char *)mir_realloc(pszText, iLen + 1); + GetDlgItemTextA(hwndDlg, IDC_LOGTIMESTAMP, pszText, iLen + 1); + db_set_s(NULL, CHAT_MODULE, "LogTimestamp", pszText); + } + else db_unset(NULL, CHAT_MODULE, "LogTimestamp"); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_TIMESTAMP)); + if (iLen > 0) { + pszText = (char *)mir_realloc(pszText, iLen + 1); + GetDlgItemTextA(hwndDlg, IDC_TIMESTAMP, pszText, iLen + 1); + db_set_s(NULL, CHAT_MODULE, "HeaderTime", pszText); + } + else db_unset(NULL, CHAT_MODULE, "HeaderTime"); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_INSTAMP)); + if (iLen > 0) { + pszText = (char *)mir_realloc(pszText, iLen + 1); + GetDlgItemTextA(hwndDlg, IDC_INSTAMP, pszText, iLen + 1); + db_set_s(NULL, CHAT_MODULE, "HeaderIncoming", pszText); + } + else db_unset(NULL, CHAT_MODULE, "HeaderIncoming"); + + iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_OUTSTAMP)); + if (iLen > 0) { + pszText = (char *)mir_realloc(pszText, iLen + 1); + GetDlgItemTextA(hwndDlg, IDC_OUTSTAMP, pszText, iLen + 1); + db_set_s(NULL, CHAT_MODULE, "HeaderOutgoing", pszText); + } + else db_unset(NULL, CHAT_MODULE, "HeaderOutgoing"); + + iLen = SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN2, UDM_GETPOS, 0, 0); + db_set_w(NULL, CHAT_MODULE, "LogLimit", (WORD)iLen); + mir_free(pszText); + + if (pci->hListBkgBrush) + DeleteObject(pci->hListBkgBrush); + pci->hListBkgBrush = CreateSolidBrush(M.GetDword(CHAT_MODULE, "ColorNicklistBG", SRMSGDEFSET_BKGCOLOUR)); + + pci->ReloadSettings(); + pci->MM_FontsChanged(); + pci->MM_FixColors(); + pci->SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE); + + PluginConfig.reloadSettings(); + CacheMsgLogIcons(); + CacheLogFonts(); + return TRUE; + } + break; + + case WM_TIMER: + if (IsWindow(hPathTip)) + KillTimer(hPathTip, 4); // It will prevent tooltip autoclosing + break; + + case WM_DESTROY: + if (hPathTip) { + KillTimer(hwndDlg, 0); + DestroyWindow(hPathTip); + hPathTip = 0; + } + break; + } + return FALSE; +} + +#define NR_GC_EVENTS 12 + +static UINT _eventorder[] = +{ + GC_EVENT_ACTION, + GC_EVENT_MESSAGE, + GC_EVENT_NICK, + GC_EVENT_JOIN, + GC_EVENT_PART, + GC_EVENT_TOPIC, + GC_EVENT_ADDSTATUS, + GC_EVENT_INFORMATION, + GC_EVENT_QUIT, + GC_EVENT_KICK, + GC_EVENT_NOTICE, + GC_EVENT_HIGHLIGHT +}; + +// Dialog procedure for group chat options tab #3 (event filter configuration) +INT_PTR CALLBACK DlgProcOptions3(HWND hwndDlg, UINT uMsg, WPARAM, LPARAM lParam) +{ + switch (uMsg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + DWORD dwFilterFlags = M.GetDword(CHAT_MODULE, "FilterFlags", GC_EVENT_ALL); + DWORD dwTrayFlags = M.GetDword(CHAT_MODULE, "TrayIconFlags", GC_EVENT_HIGHLIGHT); + DWORD dwPopupFlags = M.GetDword(CHAT_MODULE, "PopupFlags", GC_EVENT_HIGHLIGHT); + DWORD dwLogFlags = M.GetDword(CHAT_MODULE, "DiskLogFlags", GC_EVENT_ALL); + + for (int i = 0; i < _countof(_eventorder); i++) { + if (_eventorder[i] != GC_EVENT_HIGHLIGHT) { + CheckDlgButton(hwndDlg, IDC_1 + i, dwFilterFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_L1 + i, dwLogFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED); + } + CheckDlgButton(hwndDlg, IDC_P1 + i, dwPopupFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_T1 + i, dwTrayFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED); + } + } + SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_ADDSTRING, -1, (LPARAM)TranslateT("No markers")); + SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_ADDSTRING, -1, (LPARAM)TranslateT("Show as icons")); + SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_ADDSTRING, -1, (LPARAM)TranslateT("Show as text symbols")); + + SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_SETCURSEL, (g_Settings.bLogSymbols ? 2 : (g_Settings.dwIconFlags ? 1 : 0)), 0); + + CheckDlgButton(hwndDlg, IDC_TRAYONLYFORINACTIVE, M.GetByte(CHAT_MODULE, "TrayIconInactiveOnly", 0) ? BST_CHECKED : BST_UNCHECKED); + break; + + case WM_COMMAND: + if (lParam != 0) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: + DWORD dwFilterFlags = 0, dwTrayFlags = 0, + dwPopupFlags = 0, dwLogFlags = 0; + + for (int i = 0; i < _countof(_eventorder); i++) { + if (_eventorder[i] != GC_EVENT_HIGHLIGHT) { + dwFilterFlags |= (IsDlgButtonChecked(hwndDlg, IDC_1 + i) ? _eventorder[i] : 0); + dwLogFlags |= (IsDlgButtonChecked(hwndDlg, IDC_L1 + i) ? _eventorder[i] : 0); + } + dwPopupFlags |= (IsDlgButtonChecked(hwndDlg, IDC_P1 + i) ? _eventorder[i] : 0); + dwTrayFlags |= (IsDlgButtonChecked(hwndDlg, IDC_T1 + i) ? _eventorder[i] : 0); + } + db_set_dw(0, CHAT_MODULE, "FilterFlags", dwFilterFlags); + db_set_dw(0, CHAT_MODULE, "PopupFlags", dwPopupFlags); + db_set_dw(0, CHAT_MODULE, "TrayIconFlags", dwTrayFlags); + db_set_dw(0, CHAT_MODULE, "DiskLogFlags", dwLogFlags); + + LRESULT lr = SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_GETCURSEL, 0, 0); + + db_set_dw(0, CHAT_MODULE, "IconFlags", lr == 1 ? 1 : 0); + db_set_b(0, CHAT_MODULE, "LogSymbols", lr == 2 ? 1 : 0); + + db_set_b(0, CHAT_MODULE, "TrayIconInactiveOnly", IsDlgButtonChecked(hwndDlg, IDC_TRAYONLYFORINACTIVE) ? 1 : 0); + + pci->ReloadSettings(); + pci->MM_FontsChanged(); + pci->SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE); + SM_ReconfigureFilters(); + return TRUE; + } + } + break; + } + return FALSE; +} diff --git a/plugins/TabSRMM/src/chat_resource.h b/plugins/TabSRMM/src/chat_resource.h new file mode 100644 index 0000000000..ee8255a0db --- /dev/null +++ b/plugins/TabSRMM/src/chat_resource.h @@ -0,0 +1,143 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by chat.rc +// +#define IDR_MENU 151 +#define IDD_CHANNEL 401 +#define IDD_OPTIONS1 402 +#define IDD_OPTIONS2 403 +#define IDD_FILTER 404 +#define IDD_OPTIONSPOPUP 405 +#define IDD_OPTIONS3 407 +#define IDD_OPTIONS4 408 +#define IDD_ADDHIGHLIGHT 409 +#define IDC_CHECKBOXES 1021 +#define IDC_NICKROW2 1023 +#define IDC_NICKROW 1024 +#define IDC_LOGLIMIT 1024 +#define IDC_CHAT_SPIN2 1029 +#define IDC_CHAT_SPIN3 1030 +#define IDC_CHAT_SPIN4 1031 +#define IDC_PANELNICK 1032 +#define IDC_PANELUIN 1033 +#define IDC_INSTAMP 1041 +#define IDC_OUTSTAMP 1043 +#define IDC_TIMESTAMP 1046 +#define IDC_FONTCHOOSE 1047 +#define IDC_LOGDIRECTORY 1048 +#define IDC_LIMIT 1050 +#define IDC_LOGTIMESTAMP 1051 +#define IDC_GROUP 1057 +#define IDC_RADIO2 1062 +#define IDC_RADIO3 1063 +#define IDC_TEXT 1064 +#define IDC_BKG 1065 +#define IDC_TIMEOUT 1067 +#define IDC_TEXTO 1069 +#define IDC_LOGGING 1069 +#define IDC_TEXTO2 1070 +#define IDC_TEXTO3 1071 +#define IDC_LIST 1072 +#define IDC_TEXTO4 1072 +#define IDC_STATIC_ADD 1077 +#define IDC_STATIC_ULIST 1078 +#define IDC_STATIC_OTHER 1079 +#define IDC_STATIC110 1082 +#define IDC_STATIC112 1085 +#define IDC_TRAYONLYFORINACTIVE 1086 +#define IDC_LOGICONTYPE 1088 +#define IDC_HIGHLIGHTNICKENABLE 1089 +#define IDC_HIGHLIGHTNICKUID 1090 +#define IDC_HIGHLIGHTNICKPATTERN 1091 +#define IDC_HIGHLIGHTTEXTENABLE 1092 +#define IDC_COMBO1 1092 +#define IDC_ADDHIGHLIGHTNAME 1092 +#define IDC_HIGHLIGHTTEXTPATTERN 1093 +#define IDC_ADDHIGHLIGHTTITLE 1093 +#define IDC_ADDHIGHLIGHTEXPLAIN 1094 +#define IDC_HIGHLIGHTNICKUID2 1094 +#define IDC_HIGHLIGHTME 1094 +#define IDC_ADDHIGHLIGHTEDITLIST 1095 +#define IDC_MUC_OPENLOGBASEDIR 1096 +#define IDC_BOLD 1106 +#define IDC_ITALICS 1107 +#define IDC_UNDERLINE 1108 +#define IDC_COLOR 1110 +#define IDC_1 1200 +#define IDC_2 1201 +#define IDC_3 1202 +#define IDC_4 1203 +#define IDC_5 1204 +#define IDC_6 1205 +#define IDC_7 1206 +#define IDC_8 1207 +#define IDC_9 1208 +#define IDC_10 1209 +#define IDC_11 1210 +#define IDC_PANELSPLITTER 1216 +#define IDC_P1 1300 +#define IDC_P2 1301 +#define IDC_P3 1302 +#define IDC_P4 1303 +#define IDC_P5 1304 +#define IDC_P6 1305 +#define IDC_P7 1306 +#define IDC_P8 1307 +#define IDC_P9 1308 +#define IDC_P10 1309 +#define IDC_P11 1310 +#define IDC_P12 1311 +#define IDC_T1 1400 +#define IDC_T2 1401 +#define IDC_T3 1402 +#define IDC_T4 1403 +#define IDC_T5 1404 +#define IDC_T6 1405 +#define IDC_T7 1406 +#define IDC_T8 1407 +#define IDC_T9 1408 +#define IDC_T10 1409 +#define IDC_T11 1410 +#define IDC_T12 1411 +#define IDC_L1 1500 +#define IDC_L2 1501 +#define IDC_L3 1502 +#define IDC_L4 1503 +#define IDC_L5 1504 +#define IDC_L6 1505 +#define IDC_L7 1506 +#define IDC_L8 1507 +#define IDC_L9 1508 +#define IDC_L10 1509 +#define IDC_L11 1510 +#define IDC_WHITERECT 1600 +#define ID_MESS 40001 +#define ID_NEW 40002 +#define ID_CURR 40003 +#define ID_COPY 40004 +#define ID_COPYALL 40006 +#define ID_CLEARLOG 40009 +#define ID_MESSAGE_UNDO 40013 +#define ID_MESSAGE_COPY 40014 +#define ID_MESSAGE_CUT 40015 +#define ID_MESSAGE_CLEAR 40017 +#define ID_MESSAGE_SELECTALL 40018 +#define ID_MESSAGE_REDO 40019 +#define ID_MESSAGE_PASTE 40020 +#define ID_CLOSE 40022 +#define ID_CLOSEOTHER 40023 +#define ID_LOCKPOSITION 40024 +#define ID_SEARCH_GOOGLE 40027 +#define ID_SEARCH_WIKIPEDIA 40028 +#define ID_WIKIPEDIA_ 40029 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 163 +#define _APS_NEXT_COMMAND_VALUE 40030 +#define _APS_NEXT_CONTROL_VALUE 1097 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/TabSRMM/src/chat_tools.cpp b/plugins/TabSRMM/src/chat_tools.cpp new file mode 100644 index 0000000000..329ba9b6b3 --- /dev/null +++ b/plugins/TabSRMM/src/chat_tools.cpp @@ -0,0 +1,696 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Miranda NG: the free IM client for Microsoft* Windows* +// +// Copyright (ñ) 2012-17 Miranda NG project, +// Copyright (c) 2000-09 Miranda ICQ/IM project, +// all portions of this codebase are copyrighted to the people +// listed in contributors.txt. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// you should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// part of tabSRMM messaging plugin for Miranda. +// +// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors +// +// Helper functions for the group chat module. + +#include "stdafx.h" + +int GetRichTextLength(HWND hwnd) +{ + GETTEXTLENGTHEX gtl; + gtl.flags = GTL_PRECISE; + gtl.codepage = CP_ACP; + return (int)SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>l, 0); +} + +static void __stdcall ShowRoomFromPopup(void *pi) +{ + SESSION_INFO *si = (SESSION_INFO*)pi; + ShowRoom(si); +} + +static void __stdcall Chat_DismissPopup(void *pi) +{ + SESSION_INFO *si = (SESSION_INFO*)pi; + if (si->hContact) + if (pcli->pfnGetEvent(si->hContact, 0)) + pcli->pfnRemoveEvent(si->hContact, GC_FAKE_EVENT); + + if (si->hWnd && KillTimer(si->hWnd, TIMERID_FLASHWND)) + FlashWindow(si->hWnd, FALSE); +} + +static LRESULT CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + SESSION_INFO *si = (SESSION_INFO*)PUGetPluginData(hWnd); + + switch (message) { + case WM_COMMAND: + if (HIWORD(wParam) == STN_CLICKED) { + if (si) { + if (nen_options.maskActL & MASK_OPEN) + CallFunctionAsync(ShowRoomFromPopup, si); + else + CallFunctionAsync(Chat_DismissPopup, si); + PUDeletePopup(hWnd); + } + return TRUE; + } + break; + + case WM_CONTEXTMENU: + if (si && si->hContact) { + if (nen_options.maskActR & MASK_OPEN) + CallFunctionAsync(ShowRoomFromPopup, si); + else + CallFunctionAsync(Chat_DismissPopup, si); + PUDeletePopup(hWnd); + } + break; + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + +BOOL DoTrayIcon(SESSION_INFO *si, GCEVENT *gce) +{ + int iEvent = gce->pDest->iType; + if (si && (iEvent & si->iLogTrayFlags)) + return saveCI.DoTrayIcon(si, gce); + return TRUE; +} + +int ShowPopup(MCONTACT hContact, SESSION_INFO *si, HICON hIcon, char* pszProtoName, wchar_t*, COLORREF crBkg, const wchar_t* fmt, ...) +{ + POPUPDATAT pd = { 0 }; + va_list marker; + static wchar_t szBuf[4 * 1024]; + + if (!fmt || mir_wstrlen(fmt) == 0 || mir_wstrlen(fmt) > 2000) + return 0; + + va_start(marker, fmt); + mir_vsnwprintf(szBuf, _countof(szBuf), fmt, marker); + va_end(marker); + + pd.lchContact = hContact; + + if (hIcon) + pd.lchIcon = hIcon; + else + pd.lchIcon = LoadIconEx("window"); + + PROTOACCOUNT *pa = Proto_GetAccount(pszProtoName); + mir_snwprintf(pd.lptzContactName, L"%s - %s", (pa == NULL) ? _A2T(pszProtoName) : pa->tszAccountName, pcli->pfnGetContactDisplayName(hContact, 0)); + wcsncpy_s(pd.lptzText, TranslateW(szBuf), _TRUNCATE); + 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 = g_Settings.crLogBackground; + pd.colorText = crBkg; + } + + pd.PluginWindowProc = PopupDlgProc; + pd.PluginData = si; + return PUAddPopupT(&pd); +} + +BOOL DoPopup(SESSION_INFO *si, GCEVENT *gce) +{ + int iEvent = gce->pDest->iType; + if (si == NULL || !(iEvent & si->iLogPopupFlags)) + return true; + + CTabBaseDlg *dat = si->dat; + TContainerData *pContainer = dat ? dat->m_pContainer : NULL; + + wchar_t *bbStart, *bbEnd; + if (g_Settings.bBBCodeInPopups) { + bbStart = L"[b]"; + bbEnd = L"[/b]"; + } + else bbStart = bbEnd = L""; + + if (nen_options.iMUCDisable) // no popups at all. Period + return 0; + /* + * check the status mode against the status mask + */ + + char *szProto = dat ? dat->m_szProto : si->pszModule; + 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_bHideOnClose) + 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 = pci->aFonts[16].color; + iNewEvent &= ~GC_EVENT_HIGHLIGHT; + } + + if (iNewEvent == GC_EVENT_MESSAGE) { + ShowPopup(si->hContact, si, pci->hIcons[ICON_MESSAGE], si->pszModule, si->ptszName, clr ? clr : pci->aFonts[9].color, + TranslateT("%s%s says:%s %s"), bbStart, gce->ptszNick, bbEnd, pci->RemoveFormatting(gce->ptszText)); + } + else saveCI.DoPopup(si, gce); + + return TRUE; +} + +void DoFlashAndSoundWorker(FLASH_PARAMS* p) +{ + SESSION_INFO *si = SM_FindSessionByHCONTACT(p->hContact); + if (si == 0) + return; + + CTabBaseDlg *dat = 0; + if (si->hWnd) { + dat = si->dat; + if (dat) { + p->bInactive = dat->m_pContainer->hwnd != GetForegroundWindow(); + p->bActiveTab = (dat->m_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 == pci->hIcons[ICON_HIGHLIGHT] || p->hNotifyIcon == pci->hIcons[ICON_MESSAGE]); + + if ((p->iEvent & si->iLogTrayFlags) || bForcedIcon) { + if (!p->bActiveTab) { + if (p->hNotifyIcon == pci->hIcons[ICON_HIGHLIGHT]) + dat->m_iFlashIcon = p->hNotifyIcon; + else { + if (dat->m_iFlashIcon != pci->hIcons[ICON_HIGHLIGHT] && dat->m_iFlashIcon != pci->hIcons[ICON_MESSAGE]) + dat->m_iFlashIcon = p->hNotifyIcon; + } + dat->m_bCanFlashTab = TRUE; + SetTimer(si->hWnd, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL); + } + } + if (dat->m_pWnd) { + dat->m_pWnd->updateIcon(p->hNotifyIcon); + dat->m_pWnd->setOverlayIcon(p->hNotifyIcon, true); + } + + // autoswitch tab.. + if (p->bMustAutoswitch) { + if ((IsIconic(dat->m_pContainer->hwnd)) && !IsZoomed(dat->m_pContainer->hwnd) && PluginConfig.haveAutoSwitch() && dat->m_pContainer->hwndActive != si->hWnd) { + int iItem = GetTabIndexFromHWND(hwndTab, si->hWnd); + if (iItem >= 0) { + TabCtrl_SetCurSel(hwndTab, iItem); + ShowWindow(dat->m_pContainer->hwndActive, SW_HIDE); + dat->m_pContainer->hwndActive = si->hWnd; + SendMessage(dat->m_pContainer->hwnd, DM_UPDATETITLE, dat->m_hContact, 0); + dat->m_pContainer->dwFlags |= CNT_DEFERREDTABSELECT; + } + } + } + + // flash window if it is not focused + if (p->bMustFlash && p->bInactive) + if (!(dat->m_pContainer->dwFlags & CNT_NOFLASH)) + FlashContainer(dat->m_pContainer, 1, 0); + + if (p->hNotifyIcon && p->bInactive && ((p->iEvent & si->iLogTrayFlags) || bForcedIcon)) { + if (p->bMustFlash) + dat->m_hTabIcon = p->hNotifyIcon; + else if (dat->m_iFlashIcon) { + dat->m_hTabIcon = dat->m_iFlashIcon; + + TCITEM item = {}; + item.mask = TCIF_IMAGE; + item.iImage = 0; + TabCtrl_SetItem(GetParent(si->hWnd), dat->m_iTabID, &item); + } + + HICON hIcon = (HICON)SendMessage(dat->m_pContainer->hwnd, WM_GETICON, ICON_BIG, 0); + if (p->hNotifyIcon == pci->hIcons[ICON_HIGHLIGHT] || (hIcon != pci->hIcons[ICON_MESSAGE] && hIcon != pci->hIcons[ICON_HIGHLIGHT])) { + SendMessage(dat->m_pContainer->hwnd, DM_SETICON, (WPARAM)dat, (LPARAM)p->hNotifyIcon); + dat->m_pContainer->dwFlags |= CNT_NEED_UPDATETITLE; + } + } + + if (p->bMustFlash && p->bInactive) + UpdateTrayMenu(dat, si->wStatus, si->pszModule, dat->m_wszStatus, si->hContact, 1); + } + + mir_free(p); +} + +BOOL DoSoundsFlashPopupTrayStuff(SESSION_INFO *si, GCEVENT *gce, BOOL bHighlight, int bManyFix) +{ + if (gce == 0 || si == 0 || gce->bIsMe || si->iType == GCW_SERVER) + return FALSE; + + CTabBaseDlg *dat = NULL; + FLASH_PARAMS *params = (FLASH_PARAMS*)mir_calloc(sizeof(FLASH_PARAMS)); + params->hContact = si->hContact; + params->bInactive = TRUE; + if (si->hWnd && si->dat) { + dat = si->dat; + if ((si->hWnd == si->dat->m_pContainer->hwndActive) && GetForegroundWindow() == si->dat->m_pContainer->hwnd) + params->bInactive = FALSE; + } + params->bActiveTab = params->bMustFlash = params->bMustAutoswitch = FALSE; + params->iEvent = gce->pDest->iType; + + WPARAM wParamForHighLight = 0; + bool bFlagUnread = false; + if (bHighlight) { + gce->pDest->iType |= GC_EVENT_HIGHLIGHT; + params->sound = "ChatHighlight"; + if (db_get_b(si->hContact, "CList", "Hidden", 0) != 0) + db_unset(si->hContact, "CList", "Hidden"); + if (params->bInactive) { + bFlagUnread = true; + DoTrayIcon(si, gce); + } + + if (g_Settings.bCreateWindowOnHighlight && dat == NULL) + wParamForHighLight = 1; + + if (dat && g_Settings.bAnnoyingHighlight && params->bInactive && dat->m_pContainer->hwnd != GetForegroundWindow()) { + wParamForHighLight = 2; + params->hWnd = dat->GetHwnd(); + } + + if (dat || !nen_options.iMUCDisable) + DoPopup(si, gce); + if (params->bInactive && si && si->hWnd) + SendMessage(si->hWnd, GC_SETMESSAGEHIGHLIGHT, 0, (LPARAM)si); + if (g_Settings.bFlashWindowHighlight && params->bInactive) + params->bMustFlash = TRUE; + params->bMustAutoswitch = TRUE; + params->hNotifyIcon = pci->hIcons[ICON_HIGHLIGHT]; + } + else { + // do blinking icons in tray + if (params->bInactive || !g_Settings.bTrayIconInactiveOnly) { + DoTrayIcon(si, gce); + if (params->iEvent == GC_EVENT_MESSAGE) + bFlagUnread = 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); + + // do sounds and flashing + switch (params->iEvent) { + case GC_EVENT_JOIN: + params->sound = "ChatJoin"; + if (params->bInactive) + params->hNotifyIcon = pci->hIcons[ICON_JOIN]; + break; + case GC_EVENT_PART: + params->sound = "ChatPart"; + if (params->bInactive) + params->hNotifyIcon = pci->hIcons[ICON_PART]; + break; + case GC_EVENT_QUIT: + params->sound = "ChatQuit"; + if (params->bInactive) + params->hNotifyIcon = pci->hIcons[ICON_QUIT]; + break; + case GC_EVENT_ADDSTATUS: + case GC_EVENT_REMOVESTATUS: + params->sound = "ChatMode"; + if (params->bInactive) + params->hNotifyIcon = pci->hIcons[params->iEvent == GC_EVENT_ADDSTATUS ? ICON_ADDSTATUS : ICON_REMSTATUS]; + break; + case GC_EVENT_KICK: + params->sound = "ChatKick"; + if (params->bInactive) + params->hNotifyIcon = pci->hIcons[ICON_KICK]; + break; + case GC_EVENT_MESSAGE: + params->sound = "ChatMessage"; + if (params->bInactive && !(si->wState & STATE_TALK)) { + si->wState |= STATE_TALK; + db_set_w(si->hContact, si->pszModule, "ApparentMode", ID_STATUS_OFFLINE); + } + break; + case GC_EVENT_ACTION: + params->sound = "ChatAction"; + if (params->bInactive) + params->hNotifyIcon = pci->hIcons[ICON_ACTION]; + break; + case GC_EVENT_NICK: + params->sound = "ChatNick"; + if (params->bInactive) + params->hNotifyIcon = pci->hIcons[ICON_NICK]; + break; + case GC_EVENT_NOTICE: + params->sound = "ChatNotice"; + if (params->bInactive) + params->hNotifyIcon = pci->hIcons[ICON_NOTICE]; + break; + case GC_EVENT_TOPIC: + params->sound = "ChatTopic"; + if (params->bInactive) + params->hNotifyIcon = pci->hIcons[ICON_TOPIC]; + break; + } + } + else { + switch (params->iEvent) { + case GC_EVENT_JOIN: + params->hNotifyIcon = pci->hIcons[ICON_JOIN]; + break; + case GC_EVENT_PART: + params->hNotifyIcon = pci->hIcons[ICON_PART]; + break; + case GC_EVENT_QUIT: + params->hNotifyIcon = pci->hIcons[ICON_QUIT]; + break; + case GC_EVENT_KICK: + params->hNotifyIcon = pci->hIcons[ICON_KICK]; + break; + case GC_EVENT_ACTION: + params->hNotifyIcon = pci->hIcons[ICON_ACTION]; + break; + case GC_EVENT_NICK: + params->hNotifyIcon = pci->hIcons[ICON_NICK]; + break; + case GC_EVENT_NOTICE: + params->hNotifyIcon = pci->hIcons[ICON_NOTICE]; + break; + case GC_EVENT_TOPIC: + params->hNotifyIcon = pci->hIcons[ICON_TOPIC]; + break; + case GC_EVENT_ADDSTATUS: + params->hNotifyIcon = pci->hIcons[ICON_ADDSTATUS]; + break; + case GC_EVENT_REMOVESTATUS: + params->hNotifyIcon = pci->hIcons[ICON_REMSTATUS]; + break; + } + } + + if (params->iEvent == GC_EVENT_MESSAGE) { + params->bMustAutoswitch = TRUE; + if (g_Settings.bFlashWindow) + params->bMustFlash = TRUE; + params->hNotifyIcon = pci->hIcons[ICON_MESSAGE]; + } + } + if (dat && bFlagUnread) { + dat->m_dwUnread++; + if (dat->m_pWnd) + dat->m_pWnd->Invalidate(); + } + PostMessage(PluginConfig.g_hwndHotkeyHandler, DM_MUCFLASHWORKER, wParamForHighLight, (LPARAM)params); + return TRUE; +} + +int Chat_GetColorIndex(const char* pszModule, COLORREF cr) +{ + MODULEINFO *pMod = pci->MM_FindModule(pszModule); + if (!pMod || pMod->nColorCount == 0) + return -1; + + for (int i = 0; i < pMod->nColorCount; i++) + if (pMod->crColors[i] == cr) + return i; + + return -1; +} + +wchar_t* my_strstri(const wchar_t* s1, const wchar_t* s2) +{ + int i, j, k; + + _wsetlocale(LC_ALL, L""); + for (i = 0; s1[i]; i++) + for (j = i, k = 0; towlower(s1[j]) == towlower(s2[k]); j++, k++) + if (!s2[k + 1]) + return (wchar_t*)(s1 + i); + + return NULL; +} + +/* +* log the event to the log file +* allows selective logging of wanted events +*/ +BOOL LogToFile(SESSION_INFO *si, GCEVENT *gce) +{ + if (!si || !gce) + return FALSE; + + /* + * check whether we have to log this event + */ + if (!(gce->pDest->iType & si->iDiskLogFlags)) + return FALSE; + + return saveCI.LogToFile(si, gce); // call kernel method +} + +UINT CreateGCMenu(HWND hwndDlg, HMENU *hMenu, int iIndex, POINT pt, SESSION_INFO *si, wchar_t* pszUID, wchar_t* pszWordText) +{ + HMENU hSubMenu = 0; + + *hMenu = GetSubMenu(g_hMenu, iIndex); + TranslateMenu(*hMenu); + + GCMENUITEMS gcmi = { 0 }; + gcmi.pszID = si->ptszID; + gcmi.pszModule = si->pszModule; + gcmi.pszUID = pszUID; + + if (iIndex == 1) { + int i = GetRichTextLength(GetDlgItem(hwndDlg, IDC_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]) { + wchar_t szMenuText[4096]; + mir_snwprintf(szMenuText, TranslateT("Look up '%s':"), pszWordText); + ModifyMenu(*hMenu, 4, MF_STRING | MF_BYPOSITION, 4, szMenuText); + } + else ModifyMenu(*hMenu, 4, MF_STRING | MF_GRAYED | MF_BYPOSITION, 4, TranslateT("No word to look up")); + gcmi.Type = MENU_ON_LOG; + } + else if (iIndex == 0) { + wchar_t szTemp[50]; + if (pszWordText) + mir_snwprintf(szTemp, TranslateT("&Message %s"), pszWordText); + else + wcsncpy_s(szTemp, TranslateT("&Message"), _TRUNCATE); + + if (mir_wstrlen(szTemp) > 40) + wcsncpy_s(szTemp + 40, 4, L"...", _TRUNCATE); + ModifyMenu(*hMenu, ID_MESS, MF_STRING | MF_BYCOMMAND, ID_MESS, szTemp); + gcmi.Type = MENU_ON_NICKLIST; + } + + NotifyEventHooks(pci->hBuildMenuEvent, 0, (WPARAM)&gcmi); + + if (gcmi.nItems > 0) + AppendMenu(*hMenu, MF_SEPARATOR, 0, 0); + + for (int i = 0; i < gcmi.nItems; i++) { + wchar_t *ptszText = TranslateW(gcmi.Item[i].pszDesc); + 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, ptszText); + } + else if (gcmi.Item[i].uType == MENU_POPUPHMENU) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_POPUP, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_POPUPITEM) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_STRING, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_POPUPCHECK) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, dwState | MF_CHECKED | MF_STRING, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_POPUPSEPARATOR) + AppendMenu(hSubMenu == 0 ? *hMenu : hSubMenu, MF_SEPARATOR, 0, ptszText); + else if (gcmi.Item[i].uType == MENU_SEPARATOR) + AppendMenu(*hMenu, MF_SEPARATOR, 0, ptszText); + else if (gcmi.Item[i].uType == MENU_HMENU) + AppendMenu(*hMenu, dwState | MF_POPUP, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_ITEM) + AppendMenu(*hMenu, dwState | MF_STRING, gcmi.Item[i].dwID, ptszText); + else if (gcmi.Item[i].uType == MENU_CHECK) + AppendMenu(*hMenu, dwState | MF_CHECKED | MF_STRING, gcmi.Item[i].dwID, ptszText); + } + + if (iIndex == 0) { + AppendMenu(*hMenu, MF_SEPARATOR, 0, 0); + int pos = GetMenuItemCount(*hMenu); + InsertMenu(*hMenu, pos, MF_BYPOSITION, (UINT_PTR)20020, TranslateT("Highlight user...")); + InsertMenu(*hMenu, pos, MF_BYPOSITION, (UINT_PTR)20021, TranslateT("Edit highlight list...")); + } + + return TrackPopupMenu(*hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL); +} + +void DestroyGCMenu(HMENU *hMenu, int iIndex) +{ + MENUITEMINFO mii = { 0 }; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_SUBMENU; + while (GetMenuItemInfo(*hMenu, iIndex, TRUE, &mii)) { + if (mii.hSubMenu != NULL) + DestroyMenu(mii.hSubMenu); + RemoveMenu(*hMenu, iIndex, MF_BYPOSITION); + } +} + +/* + * set all filters and notification config for a session + * uses per channel mask + filterbits, default config as backup + */ +void Chat_SetFilters(SESSION_INFO *si) +{ + if (si == NULL) + return; + + DWORD dwFlags_default = M.GetDword(CHAT_MODULE, "FilterFlags", GC_EVENT_ALL); + DWORD dwFlags_local = db_get_dw(si->hContact, CHAT_MODULE, "FilterFlags", GC_EVENT_ALL); + DWORD dwMask = db_get_dw(si->hContact, CHAT_MODULE, "FilterMask", 0); + + si->iLogFilterFlags = dwFlags_default; + for (int i = 0; i < 32; i++) { + DWORD dwBit = 1 << i; + if (dwMask & dwBit) + si->iLogFilterFlags = (dwFlags_local & dwBit) ? si->iLogFilterFlags | dwBit : si->iLogFilterFlags & ~dwBit; + } + + dwFlags_default = M.GetDword(CHAT_MODULE, "PopupFlags", GC_EVENT_HIGHLIGHT); + dwFlags_local = db_get_dw(si->hContact, CHAT_MODULE, "PopupFlags", GC_EVENT_HIGHLIGHT); + dwMask = db_get_dw(si->hContact, CHAT_MODULE, "PopupMask", 0); + + si->iLogPopupFlags = dwFlags_default; + for (int i = 0; i < 32; i++) { + DWORD dwBit = 1 << i; + if (dwMask & dwBit) + si->iLogPopupFlags = (dwFlags_local & dwBit) ? si->iLogPopupFlags | dwBit : si->iLogPopupFlags & ~dwBit; + } + + dwFlags_default = M.GetDword(CHAT_MODULE, "TrayIconFlags", GC_EVENT_HIGHLIGHT); + dwFlags_local = db_get_dw(si->hContact, CHAT_MODULE, "TrayIconFlags", GC_EVENT_HIGHLIGHT); + dwMask = db_get_dw(si->hContact, CHAT_MODULE, "TrayIconMask", 0); + + si->iDiskLogFlags = M.GetDword(CHAT_MODULE, "DiskLogFlags", GC_EVENT_ALL); + + si->iLogTrayFlags = dwFlags_default; + for (int i = 0; i < 32; i++) { + DWORD dwBit = 1 << i; + if (dwMask & dwBit) + si->iLogTrayFlags = (dwFlags_local & dwBit) ? si->iLogTrayFlags | dwBit : si->iLogTrayFlags & ~dwBit; + } + + if (si->iLogFilterFlags == 0) + si->bFilterEnabled = 0; +} + +char GetIndicator(SESSION_INFO *si, LPCTSTR ptszNick, int *iNickIndex) +{ + if (iNickIndex) + *iNickIndex = 0; + + for (USERINFO *ui = si->pUsers; ui; ui = ui->next) { + if (!mir_wstrcmp(ui->pszNick, ptszNick)) { + STATUSINFO *ti = pci->TM_FindStatus(si->pStatuses, pci->TM_WordToString(si->pStatuses, ui->Status)); + if (ti && (INT_PTR)ti->hIcon < si->iStatusCount) { + if (iNickIndex) + *iNickIndex = (INT_PTR)ti->hIcon; // color table's index is not zero-based + return szIndicators[(INT_PTR)ti->hIcon]; + } + break; + } + } + return 0; +} + +bool IsHighlighted(SESSION_INFO *si, GCEVENT *gce) +{ + if (!g_Settings.bHighlightEnabled || !gce || gce->bIsMe) + return FALSE; + + GCEVENT evTmp = *gce; + + int dwMask = 0; + if (gce->ptszText != NULL) + dwMask |= CMUCHighlight::MATCH_TEXT; + + if (gce->ptszNick != NULL) { + dwMask |= CMUCHighlight::MATCH_NICKNAME; + if (si && g_Settings.bLogClassicIndicators) { + size_t len = mir_wstrlen(gce->ptszNick) + 1; + wchar_t *tmp = (wchar_t*)_alloca(sizeof(wchar_t)*(len + 1)); + *tmp = GetIndicator(si, gce->ptszNick, 0); + mir_wstrcpy(tmp + 1, gce->ptszNick); + evTmp.ptszNick = tmp; + } + } + return g_Settings.Highlight->match(&evTmp, si, dwMask); +} diff --git a/plugins/TabSRMM/src/chat_window.cpp b/plugins/TabSRMM/src/chat_window.cpp new file mode 100644 index 0000000000..da5e408c66 --- /dev/null +++ b/plugins/TabSRMM/src/chat_window.cpp @@ -0,0 +1,3258 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Miranda NG: the free IM client for Microsoft* Windows* +// +// Copyright (ñ) 2012-17 Miranda NG project, +// Copyright (c) 2000-09 Miranda ICQ/IM project, +// all portions of this codebase are copyrighted to the people +// listed in contributors.txt. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// you should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// part of tabSRMM messaging plugin for Miranda. +// +// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors +// +// This implements the group chat dialog window + +#include "stdafx.h" + +// externs... +extern LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +extern HRESULT(WINAPI *MyCloseThemeData)(HANDLE); + +int g_cLinesPerPage = 0; +int g_iWheelCarryover = 0; + +extern HMENU g_hMenu; + +static HKL hkl = NULL; +char szIndicators[] = { 0, '+', '%', '@', '!', '*' }; + +struct MESSAGESUBDATA +{ + time_t lastEnterTime; + wchar_t *szSearchQuery; + wchar_t *szSearchResult; + BOOL iSavedSpaces; + SESSION_INFO *lastSession; +}; + +const CLSID IID_ITextDocument = { 0x8CC497C0, 0xA1DF, 0x11CE, { 0x80, 0x98, 0x00, 0xAA, 0x00, 0x47, 0xBE, 0x5D } }; + +///////////////////////////////////////////////////////////////////////////////////////// +// checking if theres's protected text at the point +// emulates EN_LINK WM_NOTIFY to parent to process links + +static BOOL CheckCustomLink(HWND hwndDlg, POINT *ptClient, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL bUrlNeeded) +{ + long res = 0, cnt = 0; + long cpMin = 0, cpMax = 0; + POINT ptEnd = { 0 }; + IRichEditOle *RichEditOle = NULL; + ITextDocument *TextDocument = NULL; + ITextRange *TextRange = NULL; + ITextFont *TextFont = NULL; + BOOL bIsCustomLink = FALSE; + + POINT pt = *ptClient; + ClientToScreen(hwndDlg, &pt); + + do { + if (!SendMessage(hwndDlg, EM_GETOLEINTERFACE, 0, (LPARAM)&RichEditOle)) break; + if (RichEditOle->QueryInterface(IID_ITextDocument, (void**)&TextDocument) != S_OK) break; + if (TextDocument->RangeFromPoint(pt.x, pt.y, &TextRange) != S_OK) break; + + TextRange->GetStart(&cpMin); + cpMax = cpMin + 1; + TextRange->SetEnd(cpMax); + + if (TextRange->GetFont(&TextFont) != S_OK) + break; + + TextFont->GetProtected(&res); + if (res != tomTrue) + break; + + TextRange->GetPoint(tomEnd + TA_BOTTOM + TA_RIGHT, &ptEnd.x, &ptEnd.y); + if (pt.x > ptEnd.x || pt.y > ptEnd.y) + break; + + if (bUrlNeeded) { + TextRange->GetStoryLength(&cnt); + for (; cpMin > 0; cpMin--) { + res = tomTrue; + TextRange->SetIndex(tomCharacter, cpMin + 1, tomTrue); + TextFont->GetProtected(&res); + if (res != tomTrue) { cpMin++; break; } + } + for (cpMax--; cpMax < cnt; cpMax++) { + res = tomTrue; + TextRange->SetIndex(tomCharacter, cpMax + 1, tomTrue); + TextFont->GetProtected(&res); + if (res != tomTrue) + break; + } + } + + bIsCustomLink = (cpMin < cpMax); + } while (FALSE); + + if (TextFont) TextFont->Release(); + if (TextRange) TextRange->Release(); + if (TextDocument) TextDocument->Release(); + if (RichEditOle) RichEditOle->Release(); + + if (bIsCustomLink) { + ENLINK enlink = { 0 }; + enlink.nmhdr.hwndFrom = hwndDlg; + enlink.nmhdr.idFrom = IDC_LOG; + enlink.nmhdr.code = EN_LINK; + enlink.msg = uMsg; + enlink.wParam = wParam; + enlink.lParam = lParam; + enlink.chrg.cpMin = cpMin; + enlink.chrg.cpMax = cpMax; + SendMessage(GetParent(hwndDlg), WM_NOTIFY, IDC_LOG, (LPARAM)&enlink); + } + return bIsCustomLink; +} + +bool IsStringValidLink(wchar_t *pszText) +{ + if (pszText == NULL) + return false; + + if (mir_wstrlen(pszText) < 5 || wcschr(pszText, '"')) + return false; + + if (towlower(pszText[0]) == 'w' && towlower(pszText[1]) == 'w' && towlower(pszText[2]) == 'w' && pszText[3] == '.' && iswalnum(pszText[4])) + return true; + + return wcsstr(pszText, L"://") != NULL; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// called whenever a group chat tab becomes active(either by switching tabs or activating a +// container window + +void CChatRoomDlg::UpdateWindowState(UINT msg) +{ + if (si == NULL) + return; + + if (msg == WM_ACTIVATE) { + if (m_pContainer->dwFlags & CNT_TRANSPARENCY) { + DWORD trans = LOWORD(m_pContainer->settings->dwTransparency); + SetLayeredWindowAttributes(m_pContainer->hwnd, CSkin::m_ContainerColorKey, (BYTE)trans, (m_pContainer->dwFlags & CNT_TRANSPARENCY ? LWA_ALPHA : 0)); + } + } + + if (m_hwndFilter) { + POINT pt; + GetCursorPos(&pt); + + RECT rcFilter; + GetWindowRect(m_hwndFilter, &rcFilter); + if (!PtInRect(&rcFilter, pt)) { + SendMessage(m_hwndFilter, WM_CLOSE, 1, 1); + m_hwndFilter = 0; + } + } + + if (m_bIsAutosizingInput && m_iInputAreaHeight == -1) { + m_iInputAreaHeight = 0; + m_message.SendMsg(EM_REQUESTRESIZE, 0, 0); + } + + m_pPanel.dismissConfig(); + m_dwUnread = 0; + if (m_pWnd) { + m_pWnd->activateTab(); + m_pWnd->setOverlayIcon(0, true); + } + + if (m_pContainer->hwndSaved == m_hwnd || m_bWasDeleted) + return; + + m_pContainer->hwndSaved = m_hwnd; + + pci->SetActiveSession(si->ptszID, si->pszModule); + m_hTabIcon = m_hTabStatusIcon; + + if (m_iTabID >= 0) { + if (db_get_w(si->hContact, si->pszModule, "ApparentMode", 0) != 0) + db_set_w(si->hContact, si->pszModule, "ApparentMode", 0); + if (pcli->pfnGetEvent(si->hContact, 0)) + pcli->pfnRemoveEvent(si->hContact, GC_FAKE_EVENT); + + SendMessage(m_hwnd, GC_UPDATETITLE, 0, 1); + m_dwTickLastEvent = 0; + m_dwFlags &= ~MWF_DIVIDERSET; + if (KillTimer(m_hwnd, TIMERID_FLASHWND) || m_iFlashIcon) { + FlashTab(false); + m_bCanFlashTab = FALSE; + m_iFlashIcon = 0; + } + if (m_pContainer->dwFlashingStarted != 0) { + FlashContainer(m_pContainer, 0, 0); + m_pContainer->dwFlashingStarted = 0; + } + m_pContainer->dwFlags &= ~CNT_NEED_UPDATETITLE; + + if (m_dwFlags & MWF_NEEDCHECKSIZE) + PostMessage(m_hwnd, DM_SAVESIZE, 0, 0); + + if (PluginConfig.m_bAutoLocaleSupport) { + if (hkl == 0) + DM_LoadLocale(); + else + SendMessage(m_hwnd, DM_SETLOCALE, 0, 0); + } + SetFocus(GetDlgItem(m_hwnd, IDC_MESSAGE)); + m_dwLastActivity = GetTickCount(); + m_pContainer->dwLastActivity = m_dwLastActivity; + m_pContainer->MenuBar->configureMenu(); + UpdateTrayMenuState(this, FALSE); + DM_SetDBButtonStates(); + + if (m_dwFlagsEx & MWF_EX_DELAYEDSPLITTER) { + m_dwFlagsEx &= ~MWF_EX_DELAYEDSPLITTER; + ShowWindow(m_pContainer->hwnd, SW_RESTORE); + PostMessage(m_hwnd, DM_SPLITTERGLOBALEVENT, m_wParam, m_lParam); + PostMessage(m_hwnd, WM_SIZE, 0, 0); + m_wParam = m_lParam = 0; + } + } + BB_SetButtonsPos(); + if (M.isAero()) + InvalidateRect(m_hwndParent, NULL, FALSE); + if (m_pContainer->dwFlags & CNT_SIDEBAR) + m_pContainer->SideBar->setActiveItem(this); + + if (m_pWnd) + m_pWnd->Invalidate(); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// resizer callback for the group chat session window.Called from Mirandas dialog +// resizing service + +int CChatRoomDlg::Resizer(UTILRESIZECONTROL *urc) +{ + bool bToolbar = !(m_pContainer->dwFlags & CNT_HIDETOOLBAR); + bool bBottomToolbar = (m_pContainer->dwFlags & CNT_BOTTOMTOOLBAR) != 0; + bool bNick = si->iType != GCW_SERVER && si->bNicklistEnabled; + bool bInfoPanel = m_pPanel.isActive(); + int panelHeight = m_pPanel.getHeight() + 1; + int iSplitterX = m_pContainer->settings->iSplitterX; + + RECT rcTabs; + GetClientRect(m_hwnd, &rcTabs); + + if (m_bIsAutosizingInput) + Utils::showDlgControl(m_hwnd, IDC_SPLITTERY, SW_HIDE); + + if (si->iType != GCW_SERVER) { + Utils::showDlgControl(m_hwnd, IDC_LIST, si->bNicklistEnabled ? SW_SHOW : SW_HIDE); + Utils::showDlgControl(m_hwnd, IDC_SPLITTERX, si->bNicklistEnabled ? SW_SHOW : SW_HIDE); + + m_btnNickList.Enable(true); + m_btnFilter.Enable(true); + if (si->iType == GCW_CHATROOM) { + MODULEINFO *tmp = pci->MM_FindModule(si->pszModule); + if (tmp) + m_btnChannelMgr.Enable(tmp->bChanMgr); + } + } + else { + Utils::showDlgControl(m_hwnd, IDC_LIST, SW_HIDE); + Utils::showDlgControl(m_hwnd, IDC_SPLITTERX, SW_HIDE); + } + + if (si->iType == GCW_SERVER) { + m_btnNickList.Enable(false); + m_btnFilter.Enable(false); + m_btnChannelMgr.Enable(false); + } + + switch (urc->wId) { + case IDC_PANELSPLITTER: + urc->rcItem.bottom = panelHeight; + urc->rcItem.top = panelHeight - 2; + return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP; + + case IDC_LOG: + urc->rcItem.top = 0; + urc->rcItem.left = 0; + urc->rcItem.right = bNick ? urc->dlgNewSize.cx - iSplitterX : urc->dlgNewSize.cx; + urc->rcItem.bottom = urc->dlgNewSize.cy - m_iSplitterY; + if (!bToolbar || bBottomToolbar) + urc->rcItem.bottom += DPISCALEY_S(21); + if (bInfoPanel) + urc->rcItem.top += panelHeight; + if (CSkin::m_skinEnabled) { + CSkinItem *item = &SkinItems[ID_EXTBKHISTORY]; + if (!item->IGNORED) { + urc->rcItem.left += item->MARGIN_LEFT; + urc->rcItem.right -= item->MARGIN_RIGHT; + urc->rcItem.top += item->MARGIN_TOP; + urc->rcItem.bottom -= item->MARGIN_BOTTOM; + } + } + return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; + + case IDC_LIST: + urc->rcItem.top = 0; + urc->rcItem.right = urc->dlgNewSize.cx; + urc->rcItem.left = urc->dlgNewSize.cx - iSplitterX + 2; + urc->rcItem.bottom = urc->dlgNewSize.cy - m_iSplitterY; + if (!bToolbar || bBottomToolbar) + urc->rcItem.bottom += DPISCALEY_S(21); + if (bInfoPanel) + urc->rcItem.top += panelHeight; + if (CSkin::m_skinEnabled) { + CSkinItem *item = &SkinItems[ID_EXTBKUSERLIST]; + if (!item->IGNORED) { + urc->rcItem.left += item->MARGIN_LEFT; + urc->rcItem.right -= item->MARGIN_RIGHT; + urc->rcItem.top += item->MARGIN_TOP; + urc->rcItem.bottom -= item->MARGIN_BOTTOM; + } + } + return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; + + case IDC_SPLITTERX: + urc->rcItem.right = urc->dlgNewSize.cx - iSplitterX + 2; + urc->rcItem.left = urc->dlgNewSize.cx - iSplitterX; + urc->rcItem.bottom = urc->dlgNewSize.cy - m_iSplitterY; + if (!bToolbar || bBottomToolbar) + urc->rcItem.bottom += DPISCALEY_S(21); + urc->rcItem.top = 0; + if (bInfoPanel) + urc->rcItem.top += panelHeight; + return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; + + case IDC_SPLITTERY: + urc->rcItem.right = urc->dlgNewSize.cx; + urc->rcItem.top = urc->dlgNewSize.cy - m_iSplitterY + DPISCALEY_S(23); + urc->rcItem.bottom = urc->rcItem.top + DPISCALEY_S(2); + urc->rcItem.left = 0; + urc->rcItem.bottom++; + urc->rcItem.top++; + return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; + + case IDC_MESSAGE: + urc->rcItem.right = urc->dlgNewSize.cx; + urc->rcItem.top = urc->dlgNewSize.cy - m_iSplitterY + 3 + DPISCALEY_S(23); + urc->rcItem.bottom = urc->dlgNewSize.cy; + if (bBottomToolbar && bToolbar) + urc->rcItem.bottom -= DPISCALEY_S(22); + + if (m_bIsAutosizingInput) + urc->rcItem.top -= DPISCALEY_S(1); + + if (CSkin::m_skinEnabled) { + CSkinItem *item = &SkinItems[ID_EXTBKINPUTAREA]; + if (!item->IGNORED) { + urc->rcItem.left += item->MARGIN_LEFT; + urc->rcItem.right -= item->MARGIN_RIGHT; + urc->rcItem.top += item->MARGIN_TOP; + urc->rcItem.bottom -= item->MARGIN_BOTTOM; + } + } + return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM; + } + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// subclassing for the message input control(a richedit text control) + +static bool TabAutoComplete(HWND hwnd, MESSAGESUBDATA *dat, SESSION_INFO *si) +{ + LRESULT lResult = (LRESULT)SendMessage(hwnd, EM_GETSEL, 0, 0); + int start = LOWORD(lResult), end = HIWORD(lResult); + SendMessage(hwnd, EM_SETSEL, end, end); + + GETTEXTEX gt = { 0 }; + gt.codepage = 1200; + gt.flags = GTL_DEFAULT | GTL_PRECISE; + int iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>, 0); + if (iLen <= 0) + return false; + + bool isTopic = false, isRoom = false; + wchar_t *pszName = NULL; + wchar_t *pszText = (wchar_t*)mir_calloc((iLen + 10) * sizeof(wchar_t)); + + gt.flags = GT_DEFAULT; + gt.cb = (iLen + 9) * sizeof(wchar_t); + SendMessage(hwnd, EM_GETTEXTEX, (WPARAM)>, (LPARAM)pszText); + + if (start > 1 && pszText[start - 1] == ' ' && pszText[start - 2] == ':') + start -= 2; + + if (dat->szSearchResult != NULL) { + int cbResult = (int)mir_wstrlen(dat->szSearchResult); + if (start >= cbResult && !wcsnicmp(dat->szSearchResult, pszText + start - cbResult, cbResult)) { + start -= cbResult; + goto LBL_SkipEnd; + } + } + + while (start > 0 && pszText[start - 1] != ' ' && pszText[start - 1] != 13 && pszText[start - 1] != VK_TAB) + start--; + +LBL_SkipEnd: + while (end < iLen && pszText[end] != ' ' && pszText[end] != 13 && pszText[end - 1] != VK_TAB) + end++; + + if (pszText[start] == '#') + isRoom = TRUE; + else { + int topicStart = start; + while (topicStart > 0 && (pszText[topicStart - 1] == ' ' || pszText[topicStart - 1] == 13 || pszText[topicStart - 1] == VK_TAB)) + topicStart--; + if (topicStart > 5 && wcsstr(&pszText[topicStart - 6], L"/topic") == &pszText[topicStart - 6]) + isTopic = TRUE; + } + if (dat->szSearchQuery == NULL) { + dat->szSearchQuery = mir_wstrndup(pszText + start, end - start); + dat->szSearchResult = mir_wstrdup(dat->szSearchQuery); + dat->lastSession = NULL; + } + if (isTopic) + pszName = si->ptszTopic; + else if (isRoom) { + dat->lastSession = SM_FindSessionAutoComplete(si->pszModule, si, dat->lastSession, dat->szSearchQuery, dat->szSearchResult); + if (dat->lastSession != NULL) + pszName = dat->lastSession->ptszName; + } + else pszName = pci->UM_FindUserAutoComplete(si->pUsers, dat->szSearchQuery, dat->szSearchResult); + + replaceStrW(dat->szSearchResult, NULL); + + if (pszName != NULL) { + dat->szSearchResult = mir_wstrdup(pszName); + if (end != start) { + ptrW szReplace; + if (!isRoom && !isTopic && g_Settings.bAddColonToAutoComplete && start == 0) { + szReplace = (wchar_t*)mir_alloc((mir_wstrlen(pszName) + 4) * sizeof(wchar_t)); + mir_wstrcpy(szReplace, pszName); + mir_wstrcat(szReplace, g_Settings.bUseCommaAsColon ? L", " : L": "); + pszName = szReplace; + } + SendMessage(hwnd, EM_SETSEL, start, end); + SendMessage(hwnd, EM_REPLACESEL, TRUE, (LPARAM)pszName); + } + return true; + } + + if (end != start) { + SendMessage(hwnd, EM_SETSEL, start, end); + SendMessage(hwnd, EM_REPLACESEL, TRUE, (LPARAM)dat->szSearchQuery); + } + replaceStrW(dat->szSearchQuery, NULL); + return false; +} + +static LRESULT CALLBACK MessageSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HWND hwndParent = GetParent(hwnd); + CChatRoomDlg *mwdat = (CChatRoomDlg*)GetWindowLongPtr(hwndParent, GWLP_USERDATA); + MESSAGESUBDATA *dat = (MESSAGESUBDATA*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + + if (mwdat != nullptr) + if (mwdat->m_fkeyProcessed && (msg == WM_KEYUP)) { + GetKeyboardState(mwdat->kstate); + if (!(mwdat->kstate[VK_CONTROL] & 0x80) && !(mwdat->kstate[VK_SHIFT] & 0x80)) + mwdat->m_fkeyProcessed = false; + return 0; + } + + switch (msg) { + case WM_NCCALCSIZE: + return CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKINPUTAREA, msg, wParam, lParam, MessageSubclassProc); + + case WM_NCPAINT: + return CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKINPUTAREA, msg, wParam, lParam, MessageSubclassProc); + + case EM_SUBCLASSED: + dat = (MESSAGESUBDATA*)mir_calloc(sizeof(MESSAGESUBDATA)); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)dat); + return 0; + + case WM_CONTEXTMENU: + POINT pt; + GetCursorPos(&pt); + { + HMENU hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)); + HMENU hSubMenu = GetSubMenu(hMenu, 2); + RemoveMenu(hSubMenu, 9, MF_BYPOSITION); + RemoveMenu(hSubMenu, 8, MF_BYPOSITION); + RemoveMenu(hSubMenu, 4, MF_BYPOSITION); + + MODULEINFO *mi = pci->MM_FindModule(mwdat->si->pszModule); + EnableMenuItem(hSubMenu, IDM_PASTEFORMATTED, MF_BYCOMMAND | ((mi && mi->bBold) ? MF_ENABLED : MF_GRAYED)); + TranslateMenu(hSubMenu); + + CHARRANGE sel, all = { 0, -1 }; + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin == sel.cpMax) { + EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(hSubMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED); + } + + MessageWindowPopupData mwpd = { sizeof(mwpd) }; + mwpd.uType = MSG_WINDOWPOPUP_SHOWING; + mwpd.uFlags = MSG_WINDOWPOPUP_INPUT; + mwpd.hContact = mwdat->m_hContact; + mwpd.hwnd = hwnd; + mwpd.hMenu = hSubMenu; + mwpd.pt = pt; + NotifyEventHooks(PluginConfig.m_event_MsgPopup, 0, (LPARAM)&mwpd); + + int iSelection = TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, GetParent(hwnd), NULL); + + mwpd.selection = iSelection; + mwpd.uType = MSG_WINDOWPOPUP_SELECTED; + NotifyEventHooks(PluginConfig.m_event_MsgPopup, 0, (LPARAM)&mwpd); + + switch (iSelection) { + case IDM_COPY: + SendMessage(hwnd, WM_COPY, 0, 0); + break; + case IDM_CUT: + SendMessage(hwnd, WM_CUT, 0, 0); + break; + case IDM_PASTE: + case IDM_PASTEFORMATTED: + SendMessage(hwnd, EM_PASTESPECIAL, (iSelection == IDM_PASTE) ? CF_UNICODETEXT : 0, 0); + break; + case IDM_COPYALL: + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&all); + SendMessage(hwnd, WM_COPY, 0, 0); + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); + break; + case IDM_SELECTALL: + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&all); + break; + } + DestroyMenu(hMenu); + } + return TRUE; + + case WM_MOUSEWHEEL: + if (mwdat->DM_MouseWheelHandler(wParam, lParam) == 0) + return 0; + + dat->lastEnterTime = 0; + break; + + case WM_SYSKEYUP: + if (wParam == VK_MENU) { + ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_MESSAGE); + return 0; + } + break; + + case WM_SYSKEYDOWN: + mwdat->m_fkeyProcessed = false; + if (ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_MESSAGE)) { + mwdat->m_fkeyProcessed = true; + return 0; + } + break; + + case WM_SYSCHAR: + if (mwdat->m_fkeyProcessed) { + mwdat->m_fkeyProcessed = false; // preceeding key event has been processed by miranda hotkey service + return 0; + } + + if ((wParam >= '0' && wParam <= '9') && (GetKeyState(VK_MENU) & 0x8000)) { // ALT-1 -> ALT-0 direct tab selection + BYTE bChar = (BYTE)wParam; + int iIndex = (bChar == '0') ? 10 : bChar - (BYTE)'0'; + SendMessage(mwdat->m_pContainer->hwnd, DM_SELECTTAB, DM_SELECT_BY_INDEX, (LPARAM)iIndex); + return 0; + } + break; + + case WM_CHAR: + bool isShift, isAlt, isCtrl; + mwdat->KbdState(isShift, isCtrl, isAlt); + + if (PluginConfig.m_bSoundOnTyping && !isAlt &&!isCtrl&&!(mwdat->m_pContainer->dwFlags & CNT_NOSOUND) && wParam != VK_ESCAPE&&!(wParam == VK_TAB && PluginConfig.m_bAllowTab)) + SkinPlaySound("SoundOnTyping"); + + if (isCtrl && !isAlt && !isShift) { + MODULEINFO *mi = pci->MM_FindModule(mwdat->si->pszModule); + if (mi == NULL) + return 0; + + switch (wParam) { + case 0x09: // ctrl-i (italics) + if (mi->bItalics) { + CheckDlgButton(hwndParent, IDC_ITALICS, IsDlgButtonChecked(hwndParent, IDC_ITALICS) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED); + SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_ITALICS, 0), 0); + } + return 0; + case 0x02: // ctrl-b (bold) + if (mi->bBold) { + CheckDlgButton(hwndParent, IDC_BOLD, IsDlgButtonChecked(hwndParent, IDC_BOLD) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED); + SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_BOLD, 0), 0); + } + return 0; + case 0x20: // ctrl-space clear formatting + if (mi->bBold && mi->bItalics && mi->bUnderline) { + CheckDlgButton(hwndParent, IDC_BKGCOLOR, BST_UNCHECKED); + CheckDlgButton(hwndParent, IDC_COLOR, BST_UNCHECKED); + CheckDlgButton(hwndParent, IDC_BOLD, BST_UNCHECKED); + CheckDlgButton(hwndParent, IDC_UNDERLINE, BST_UNCHECKED); + CheckDlgButton(hwndParent, IDC_ITALICS, BST_UNCHECKED); + SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_BKGCOLOR, 0), 0); + SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_COLOR, 0), 0); + SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_BOLD, 0), 0); + SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_UNDERLINE, 0), 0); + SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_ITALICS, 0), 0); + } + return 0; + case 0x0c: // ctrl-l background color + if (mi->bBkgColor) { + CheckDlgButton(hwndParent, IDC_BKGCOLOR, IsDlgButtonChecked(hwndParent, IDC_BKGCOLOR) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED); + SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_BKGCOLOR, 0), 0); + } + return 0; + case 0x15: // ctrl-u underlined + if (mi->bUnderline) { + CheckDlgButton(hwndParent, IDC_UNDERLINE, IsDlgButtonChecked(hwndParent, IDC_UNDERLINE) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED); + SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_UNDERLINE, 0), 0); + } + return 0; // ctrl-k color + case 0x0b: + if (mi->bColor) { + CheckDlgButton(hwndParent, IDC_COLOR, IsDlgButtonChecked(hwndParent, IDC_COLOR) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED); + SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_COLOR, 0), 0); + } + return 0; + case 0x17: + PostMessage(hwndParent, WM_CLOSE, 0, 1); + return 0; + } + } + break; + + case WM_KEYDOWN: + mwdat->KbdState(isShift, isCtrl, isAlt); + + // sound on typing.. + if (PluginConfig.m_bSoundOnTyping && !isAlt && wParam == VK_DELETE) + SkinPlaySound("SoundOnTyping"); + + if (wParam == VK_INSERT && !isShift && !isCtrl && !isAlt) { + mwdat->m_fInsertMode = !mwdat->m_fInsertMode; + SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM)hwnd); + } + if (wParam == VK_CAPITAL || wParam == VK_NUMLOCK) + SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM)hwnd); + + if (isCtrl && isAlt && !isShift) { + switch (wParam) { + case VK_UP: + case VK_DOWN: + case VK_PRIOR: + case VK_NEXT: + case VK_HOME: + case VK_END: + WPARAM wp = 0; + + if (wParam == VK_UP) + wp = MAKEWPARAM(SB_LINEUP, 0); + else if (wParam == VK_PRIOR) + wp = MAKEWPARAM(SB_PAGEUP, 0); + else if (wParam == VK_NEXT) + wp = MAKEWPARAM(SB_PAGEDOWN, 0); + else if (wParam == VK_HOME) + wp = MAKEWPARAM(SB_TOP, 0); + else if (wParam == VK_END) { + mwdat->DM_ScrollToBottom(0, 0); + return 0; + } + else if (wParam == VK_DOWN) + wp = MAKEWPARAM(SB_LINEDOWN, 0); + + SendDlgItemMessage(hwndParent, IDC_LOG, WM_VSCROLL, wp, 0); + return 0; + } + } + + if (wParam == VK_RETURN) { + if (isShift) { + if (PluginConfig.m_bSendOnShiftEnter) { + PostMessage(hwndParent, WM_COMMAND, IDOK, 0); + return 0; + } + break; + } + if ((isCtrl && !isShift) ^ (0 != PluginConfig.m_bSendOnEnter)) { + PostMessage(hwndParent, WM_COMMAND, IDOK, 0); + return 0; + } + if (!PluginConfig.m_bSendOnEnter && !PluginConfig.m_bSendOnDblEnter) + break; + if (isCtrl) + break; + + if (PluginConfig.m_bSendOnDblEnter) { + if (dat->lastEnterTime + 2 < time(NULL)) { + dat->lastEnterTime = time(NULL); + break; + } + + SendMessage(hwnd, WM_KEYDOWN, VK_BACK, 0); + SendMessage(hwnd, WM_KEYUP, VK_BACK, 0); + PostMessage(hwndParent, WM_COMMAND, IDOK, 0); + return 0; + } + PostMessage(hwndParent, WM_COMMAND, IDOK, 0); + return 0; + } + else dat->lastEnterTime = 0; + + if ((wParam == VK_NEXT && isCtrl && !isShift) || (wParam == VK_TAB && isCtrl && !isShift)) { // CTRL-TAB (switch tab/window) + SendMessage(mwdat->m_pContainer->hwnd, DM_SELECTTAB, DM_SELECT_NEXT, 0); + return TRUE; + } + + if ((wParam == VK_PRIOR && isCtrl && !isShift) || (wParam == VK_TAB && isCtrl && isShift)) { // CTRL_SHIFT-TAB (switch tab/window) + SendMessage(mwdat->m_pContainer->hwnd, DM_SELECTTAB, DM_SELECT_PREV, 0); + return TRUE; + } + if (wParam == VK_TAB && !isCtrl && !isShift) { //tab-autocomplete + SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); + bool fCompleted = TabAutoComplete(hwnd, dat, mwdat->si); + SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); + if (!fCompleted && !PluginConfig.m_bAllowTab) { + if ((GetSendButtonState(mwdat->GetHwnd()) != PBS_DISABLED)) + SetFocus(GetDlgItem(mwdat->GetHwnd(), IDOK)); + else + SetFocus(GetDlgItem(mwdat->GetHwnd(), IDC_LOG)); + } + return 0; + } + if (wParam != VK_RIGHT && wParam != VK_LEFT) { + mir_free(dat->szSearchQuery); + dat->szSearchQuery = NULL; + mir_free(dat->szSearchResult); + dat->szSearchResult = NULL; + } + + if (wParam == VK_F4 && isCtrl && !isAlt) { // ctrl-F4 (close tab) + SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_CLOSE, BN_CLICKED), 0); + return 0; + } + + if (wParam == VK_NEXT || wParam == VK_PRIOR) { + HWND htemp = hwndParent; + SendDlgItemMessage(htemp, IDC_LOG, msg, wParam, lParam); + dat->lastEnterTime = 0; + return 0; + } + + if (wParam == VK_UP && isCtrl && !isAlt) { + char *lpPrevCmd = pci->SM_GetPrevCommand(mwdat->si->ptszID, mwdat->si->pszModule); + + if (!mwdat->si->lpCurrentCommand || !mwdat->si->lpCurrentCommand->last) { + // Next command is not defined. It means currently entered text is not saved in the history and it + // need to be saved in the window context. + char *enteredText = Message_GetFromStream(hwndParent); + if (mwdat->m_enteredText) + mir_free(mwdat->m_enteredText); + + mwdat->m_enteredText = enteredText; + } + + SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); + + LOGFONTA lf; + LoadLogfont(MSGFONTID_MESSAGEAREA, &lf, NULL, FONTMODULE); + + SETTEXTEX ste; + ste.flags = ST_DEFAULT; + ste.codepage = CP_ACP; + if (lpPrevCmd) + SendMessage(hwnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)lpPrevCmd); + else + SetWindowText(hwnd, L""); + + GETTEXTLENGTHEX gtl = { 0 }; + gtl.flags = GTL_PRECISE; + gtl.codepage = CP_ACP; + int iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>l, 0); + SendMessage(hwnd, EM_SCROLLCARET, 0, 0); + SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); + SendMessage(hwnd, EM_SETSEL, iLen, iLen); + dat->lastEnterTime = 0; + return 0; + } + + if (wParam == VK_DOWN && isCtrl && !isAlt) { + SendMessage(hwnd, WM_SETREDRAW, FALSE, 0); + + SETTEXTEX ste; + ste.flags = ST_DEFAULT; + ste.codepage = CP_ACP; + + char *lpPrevCmd = pci->SM_GetNextCommand(mwdat->si->ptszID, mwdat->si->pszModule); + if (lpPrevCmd) + SendMessage(hwnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)lpPrevCmd); + else if (mwdat->m_enteredText) { + // If we cannot load the message from history, load the last edited text. + SendMessage(hwnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)mwdat->m_enteredText); + mir_free(mwdat->m_enteredText); + mwdat->m_enteredText = NULL; + } + + GETTEXTLENGTHEX gtl = { 0 }; + gtl.flags = GTL_PRECISE; + gtl.codepage = CP_ACP; + int iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)>l, 0); + SendMessage(hwnd, EM_SCROLLCARET, 0, 0); + SendMessage(hwnd, WM_SETREDRAW, TRUE, 0); + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE); + SendMessage(hwnd, EM_SETSEL, iLen, iLen); + dat->lastEnterTime = 0; + return 0; + } + // fall through + + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_KILLFOCUS: + dat->lastEnterTime = 0; + break; + + case WM_KEYUP: + case WM_LBUTTONUP: + case WM_RBUTTONUP: + case WM_MBUTTONUP: + COLORREF cr; + LoadLogfont(MSGFONTID_MESSAGEAREA, NULL, &cr, FONTMODULE); + + CHARFORMAT2 cf; + cf.cbSize = sizeof(CHARFORMAT2); + cf.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_BACKCOLOR | CFM_COLOR | CFM_UNDERLINETYPE; + cf.dwEffects = 0; + SendMessage(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + { + MODULEINFO *mi = pci->MM_FindModule(mwdat->si->pszModule); + if (mi == NULL) + break; + + if (mi->bColor) { + int index = Chat_GetColorIndex(mwdat->si->pszModule, cf.crTextColor); + UINT u = IsDlgButtonChecked(GetParent(hwnd), IDC_COLOR); + + if (index >= 0) { + mwdat->si->bFGSet = TRUE; + mwdat->si->iFG = index; + } + + if (u == BST_UNCHECKED && cf.crTextColor != cr) + CheckDlgButton(hwndParent, IDC_COLOR, BST_CHECKED); + else if (u == BST_CHECKED && cf.crTextColor == cr) + CheckDlgButton(hwndParent, IDC_COLOR, BST_UNCHECKED); + } + + if (mi->bBkgColor) { + int index = Chat_GetColorIndex(mwdat->si->pszModule, cf.crBackColor); + COLORREF crB = (COLORREF)M.GetDword(FONTMODULE, "inputbg", SRMSGDEFSET_BKGCOLOUR); + UINT u = IsDlgButtonChecked(hwndParent, IDC_BKGCOLOR); + + if (index >= 0) { + mwdat->si->bBGSet = TRUE; + mwdat->si->iBG = index; + } + + if (u == BST_UNCHECKED && cf.crBackColor != crB) + CheckDlgButton(hwndParent, IDC_BKGCOLOR, BST_CHECKED); + else if (u == BST_CHECKED && cf.crBackColor == crB) + CheckDlgButton(hwndParent, IDC_BKGCOLOR, BST_UNCHECKED); + } + + if (mi->bBold) { + UINT u = IsDlgButtonChecked(hwndParent, IDC_BOLD); + UINT u2 = cf.dwEffects; + u2 &= CFE_BOLD; + if (u == BST_UNCHECKED && u2) + CheckDlgButton(hwndParent, IDC_BOLD, BST_CHECKED); + else if (u == BST_CHECKED && u2 == 0) + CheckDlgButton(hwndParent, IDC_BOLD, BST_UNCHECKED); + } + + if (mi->bItalics) { + UINT u = IsDlgButtonChecked(hwndParent, IDC_ITALICS); + UINT u2 = cf.dwEffects; + u2 &= CFE_ITALIC; + if (u == BST_UNCHECKED && u2) + CheckDlgButton(hwndParent, IDC_ITALICS, BST_CHECKED); + else if (u == BST_CHECKED && u2 == 0) + CheckDlgButton(hwndParent, IDC_ITALICS, BST_UNCHECKED); + } + + if (mi->bUnderline) { + UINT u = IsDlgButtonChecked(hwndParent, IDC_UNDERLINE); + if (cf.dwEffects & CFE_UNDERLINE && (cf.bUnderlineType & CFU_UNDERLINE || cf.bUnderlineType & CFU_UNDERLINEWORD)) { + if (u == BST_UNCHECKED) + CheckDlgButton(hwndParent, IDC_UNDERLINE, BST_CHECKED); + } + else { + if (u == BST_CHECKED) + CheckDlgButton(hwndParent, IDC_UNDERLINE, BST_UNCHECKED); + } + } + } + break; + + case WM_INPUTLANGCHANGE: + if (PluginConfig.m_bAutoLocaleSupport && GetFocus() == hwnd && mwdat->m_pContainer->hwndActive == hwndParent && GetForegroundWindow() == mwdat->m_pContainer->hwnd && GetActiveWindow() == mwdat->m_pContainer->hwnd) { + mwdat->DM_SaveLocale(wParam, lParam); + SendMessage(hwnd, EM_SETLANGOPTIONS, 0, (LPARAM)SendMessage(hwnd, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD); + return 1; + } + break; + + case WM_ERASEBKGND: + return !CSkin::m_skinEnabled; + + case WM_DESTROY: + mir_free(dat); + } + + return mir_callNextSubclass(hwnd, MessageSubclassProc, msg, wParam, lParam); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// subclassing for the message filter dialog (set and configure event filters for the +// current session + +static UINT _eventorder[] = +{ + GC_EVENT_ACTION, + GC_EVENT_MESSAGE, + GC_EVENT_NICK, + GC_EVENT_JOIN, + GC_EVENT_PART, + GC_EVENT_TOPIC, + GC_EVENT_ADDSTATUS, + GC_EVENT_INFORMATION, + GC_EVENT_QUIT, + GC_EVENT_KICK, + GC_EVENT_NOTICE +}; + +static INT_PTR CALLBACK FilterWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + SESSION_INFO *si = (SESSION_INFO*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + switch (uMsg) { + case WM_INITDIALOG: + si = (SESSION_INFO*)lParam; + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)si); + { + DWORD dwMask = db_get_dw(si->hContact, CHAT_MODULE, "FilterMask", 0); + DWORD dwFlags = db_get_dw(si->hContact, CHAT_MODULE, "FilterFlags", 0); + + DWORD dwPopupMask = db_get_dw(si->hContact, CHAT_MODULE, "PopupMask", 0); + DWORD dwPopupFlags = db_get_dw(si->hContact, CHAT_MODULE, "PopupFlags", 0); + + DWORD dwTrayMask = db_get_dw(si->hContact, CHAT_MODULE, "TrayIconMask", 0); + DWORD dwTrayFlags = db_get_dw(si->hContact, CHAT_MODULE, "TrayIconFlags", 0); + + for (int i = 0; i < _countof(_eventorder); i++) { + CheckDlgButton(hwndDlg, IDC_1 + i, dwMask & _eventorder[i] ? (dwFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED) : BST_INDETERMINATE); + CheckDlgButton(hwndDlg, IDC_P1 + i, dwPopupMask & _eventorder[i] ? (dwPopupFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED) : BST_INDETERMINATE); + CheckDlgButton(hwndDlg, IDC_T1 + i, dwTrayMask & _eventorder[i] ? (dwTrayFlags & _eventorder[i] ? BST_CHECKED : BST_UNCHECKED) : BST_INDETERMINATE); + } + } + return FALSE; + + case WM_CTLCOLOREDIT: + case WM_CTLCOLORSTATIC: + SetTextColor((HDC)wParam, RGB(60, 60, 150)); + SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW)); + return (INT_PTR)GetSysColorBrush(COLOR_WINDOW); + + case WM_CLOSE: + if (wParam == 1 && lParam == 1) { + int iFlags = 0, i; + DWORD dwMask = 0; + + for (i = 0; i < _countof(_eventorder); i++) { + int result = IsDlgButtonChecked(hwndDlg, IDC_1 + i); + dwMask |= (result != BST_INDETERMINATE ? _eventorder[i] : 0); + iFlags |= (result == BST_CHECKED ? _eventorder[i] : 0); + } + + if (iFlags&GC_EVENT_ADDSTATUS) + iFlags |= GC_EVENT_REMOVESTATUS; + + if (si) { + if (dwMask == 0) { + db_unset(si->hContact, CHAT_MODULE, "FilterFlags"); + db_unset(si->hContact, CHAT_MODULE, "FilterMask"); + } + else { + db_set_dw(si->hContact, CHAT_MODULE, "FilterFlags", iFlags); + db_set_dw(si->hContact, CHAT_MODULE, "FilterMask", dwMask); + } + } + + dwMask = iFlags = 0; + + for (i = 0; i < _countof(_eventorder); i++) { + int result = IsDlgButtonChecked(hwndDlg, IDC_P1 + i); + dwMask |= (result != BST_INDETERMINATE ? _eventorder[i] : 0); + iFlags |= (result == BST_CHECKED ? _eventorder[i] : 0); + } + + if (iFlags & GC_EVENT_ADDSTATUS) + iFlags |= GC_EVENT_REMOVESTATUS; + + if (si) { + if (dwMask == 0) { + db_unset(si->hContact, CHAT_MODULE, "PopupFlags"); + db_unset(si->hContact, CHAT_MODULE, "PopupMask"); + } + else { + db_set_dw(si->hContact, CHAT_MODULE, "PopupFlags", iFlags); + db_set_dw(si->hContact, CHAT_MODULE, "PopupMask", dwMask); + } + } + + dwMask = iFlags = 0; + + for (i = 0; i < _countof(_eventorder); i++) { + int result = IsDlgButtonChecked(hwndDlg, IDC_T1 + i); + dwMask |= (result != BST_INDETERMINATE ? _eventorder[i] : 0); + iFlags |= (result == BST_CHECKED ? _eventorder[i] : 0); + } + if (iFlags & GC_EVENT_ADDSTATUS) + iFlags |= GC_EVENT_REMOVESTATUS; + + if (si) { + if (dwMask == 0) { + db_unset(si->hContact, CHAT_MODULE, "TrayIconFlags"); + db_unset(si->hContact, CHAT_MODULE, "TrayIconMask"); + } + else { + db_set_dw(si->hContact, CHAT_MODULE, "TrayIconFlags", iFlags); + db_set_dw(si->hContact, CHAT_MODULE, "TrayIconMask", dwMask); + } + Chat_SetFilters(si); + SendMessage(si->hWnd, GC_CHANGEFILTERFLAG, 0, iFlags); + if (si->bFilterEnabled) + SendMessage(si->hWnd, GC_REDRAWLOG, 0, 0); + } + } + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); + break; + } + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// subclass for some tool bar buttons which must perform special actions +// on right click. + +static LRESULT CALLBACK ButtonSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_RBUTTONUP: + if (M.GetByte(CHAT_MODULE, "RightClickFilter", 0) != 0) { + HWND hwndParent = GetParent(hwnd); + switch (GetDlgCtrlID(hwnd)) { + case IDC_FILTER: + SendMessage(hwndParent, GC_SHOWFILTERMENU, 0, 0); + break; + case IDC_COLOR: + SendMessage(hwndParent, GC_SHOWCOLORCHOOSER, 0, IDC_COLOR); + break; + case IDC_BKGCOLOR: + SendMessage(hwndParent, GC_SHOWCOLORCHOOSER, 0, IDC_BKGCOLOR); + } + } + break; + } + + return mir_callNextSubclass(hwnd, ButtonSubclassProc, msg, wParam, lParam); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// subclassing for the message history display(rich edit control in which the chat history appears) + +static LRESULT CALLBACK LogSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HWND hwndParent = GetParent(hwnd); + CChatRoomDlg *mwdat = (CChatRoomDlg*)GetWindowLongPtr(hwndParent, GWLP_USERDATA); + + switch (msg) { + case WM_NCCALCSIZE: + return CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, LogSubclassProc); + + case WM_NCPAINT: + return CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, LogSubclassProc); + + case WM_COPY: + return Utils::WMCopyHandler(hwnd, LogSubclassProc, msg, wParam, lParam); + + case WM_SETCURSOR: + if (g_Settings.bClickableNicks && (LOWORD(lParam) == HTCLIENT)) { + POINT pt; + GetCursorPos(&pt); + ScreenToClient(hwnd, &pt); + if (CheckCustomLink(hwnd, &pt, msg, wParam, lParam, FALSE)) return TRUE; + } + break; + + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + case WM_RBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONDBLCLK: + if (g_Settings.bClickableNicks) { + POINT pt = { LOWORD(lParam), HIWORD(lParam) }; + CheckCustomLink(hwnd, &pt, msg, wParam, lParam, TRUE); + } + break; + + case WM_LBUTTONUP: + if (g_Settings.bClickableNicks) { + POINT pt = { LOWORD(lParam), HIWORD(lParam) }; + CheckCustomLink(hwnd, &pt, msg, wParam, lParam, TRUE); + } + if (M.GetByte("autocopy", 1)) { + CHARRANGE sel; + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin != sel.cpMax) { + SendMessage(hwnd, WM_COPY, 0, 0); + sel.cpMin = sel.cpMax; + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); + SetFocus(GetDlgItem(hwndParent, IDC_MESSAGE)); + } + } + break; + + case WM_KEYDOWN: + if (wParam == 0x57 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w (close window) + PostMessage(hwndParent, WM_CLOSE, 0, 1); + return TRUE; + } + if (wParam == VK_INSERT && GetKeyState(VK_CONTROL) & 0x8000) + return Utils::WMCopyHandler(hwnd, LogSubclassProc, msg, wParam, lParam); + break; + + case WM_SYSKEYUP: + if (wParam == VK_MENU) { + ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_LOG); + return 0; + } + break; + + case WM_SYSKEYDOWN: + mwdat->m_fkeyProcessed = false; + if (ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_LOG)) { + mwdat->m_fkeyProcessed = true; + return 0; + } + break; + + case WM_SYSCHAR: + if (mwdat->m_fkeyProcessed) { + mwdat->m_fkeyProcessed = false; + return 0; + } + break; + + case WM_ACTIVATE: + if (LOWORD(wParam) == WA_INACTIVE) { + CHARRANGE sel; + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin != sel.cpMax) { + sel.cpMin = sel.cpMax; + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel); + } + } + break; + + case WM_CHAR: + bool isCtrl, isShift, isAlt; + mwdat->KbdState(isShift, isCtrl, isAlt); + if (wParam == 0x03 && isCtrl) // Ctrl+C + return Utils::WMCopyHandler(hwnd, LogSubclassProc, msg, wParam, lParam); + + SetFocus(GetDlgItem(hwndParent, IDC_MESSAGE)); + SendDlgItemMessage(hwndParent, IDC_MESSAGE, WM_CHAR, wParam, lParam); + break; + } + + return mir_callNextSubclass(hwnd, LogSubclassProc, msg, wParam, lParam); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// subclassing for the nickname list control.It is an ownerdrawn listbox + +static LRESULT CALLBACK NicklistSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HWND hwndParent = GetParent(hwnd); + CChatRoomDlg *dat = (CChatRoomDlg*)GetWindowLongPtr(hwndParent, GWLP_USERDATA); + + switch (msg) { + case WM_NCCALCSIZE: + if (CSkin::m_DisableScrollbars) { + RECT lpRect; + GetClientRect(hwnd, &lpRect); + LONG itemHeight = SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0); + g_cLinesPerPage = (lpRect.bottom - lpRect.top) / itemHeight; + } + return CSkin::NcCalcRichEditFrame(hwnd, dat, ID_EXTBKUSERLIST, msg, wParam, lParam, NicklistSubclassProc); + + case WM_NCPAINT: + return CSkin::DrawRichEditFrame(hwnd, dat, ID_EXTBKUSERLIST, msg, wParam, lParam, NicklistSubclassProc); + + case WM_ERASEBKGND: + { + HDC dc = (HDC)wParam; + if (dc) { + int index = SendMessage(hwnd, LB_GETTOPINDEX, 0, 0); + if (index == LB_ERR || dat->si->nUsersInNicklist <= 0) + return 0; + + int items = dat->si->nUsersInNicklist - index; + int height = SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0); + + if (height != LB_ERR) { + RECT rc = { 0 }; + GetClientRect(hwnd, &rc); + + if (rc.bottom - rc.top > items * height) { + rc.top = items * height; + FillRect(dc, &rc, pci->hListBkgBrush); + } + } + } + } + return 1; + + case WM_MOUSEWHEEL: + if (CSkin::m_DisableScrollbars) { + UINT uScroll; + short zDelta = (short)HIWORD(wParam); + if (!SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &uScroll, 0)) + uScroll = 3; /* default value */ + + if (uScroll == WHEEL_PAGESCROLL) + uScroll = g_cLinesPerPage; + if (uScroll == 0) + return 0; + + zDelta += g_iWheelCarryover; /* Accumulate wheel motion */ + + int dLines = zDelta * (int)uScroll / WHEEL_DELTA; + + //Record the unused portion as the next carryover. + g_iWheelCarryover = zDelta - dLines * WHEEL_DELTA / (int)uScroll; + + // scrolling. + while (abs(dLines)) { + if (dLines > 0) { + SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0); + dLines--; + } + else { + SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0); + dLines++; + } + } + return 0; + } + break; + + case WM_KEYDOWN: + if (wParam == 0x57 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w (close window) + PostMessage(hwndParent, WM_CLOSE, 0, 1); + return TRUE; + } + + if (wParam == VK_ESCAPE || wParam == VK_UP || wParam == VK_DOWN || wParam == VK_NEXT || + wParam == VK_PRIOR || wParam == VK_TAB || wParam == VK_HOME || wParam == VK_END) { + if (dat) { + dat->m_wszSearch[0] = 0; + dat->m_iSearchItem = -1; + } + } + break; + + case WM_SETFOCUS: + case WM_KILLFOCUS: + if (dat) { // set/kill focus invalidates incremental search status + dat->m_wszSearch[0] = 0; + dat->m_iSearchItem = -1; + } + break; + + case WM_CHAR: + case WM_UNICHAR: + // simple incremental search for the user (nick) - list control + // typing esc or movement keys will clear the current search string + if (dat) { + if (wParam == 27 && dat->m_wszSearch[0]) { // escape - reset everything + dat->m_wszSearch[0] = 0; + dat->m_iSearchItem = -1; + break; + } + if (wParam == '\b' && dat->m_wszSearch[0]) // backspace + dat->m_wszSearch[mir_wstrlen(dat->m_wszSearch) - 1] = '\0'; + else if (wParam < ' ') + break; + else { + if (mir_wstrlen(dat->m_wszSearch) >= _countof(dat->m_wszSearch) - 2) { + MessageBeep(MB_OK); + break; + } + wchar_t szNew[2]; + szNew[0] = (wchar_t)wParam; + szNew[1] = '\0'; + mir_wstrcat(dat->m_wszSearch, szNew); + } + if (dat->m_wszSearch[0]) { + // iterate over the (sorted) list of nicknames and search for the + // string we have + int i, iItems = SendMessage(hwnd, LB_GETCOUNT, 0, 0); + for (i = 0; i < iItems; i++) { + USERINFO *ui = pci->UM_FindUserFromIndex(dat->si->pUsers, i); + if (ui) { + if (!wcsnicmp(ui->pszNick, dat->m_wszSearch, mir_wstrlen(dat->m_wszSearch))) { + SendMessage(hwnd, LB_SETSEL, FALSE, -1); + SendMessage(hwnd, LB_SETSEL, TRUE, i); + dat->m_iSearchItem = i; + InvalidateRect(hwnd, NULL, FALSE); + return 0; + } + } + } + if (i == iItems) { + MessageBeep(MB_OK); + dat->m_wszSearch[mir_wstrlen(dat->m_wszSearch) - 1] = '\0'; + return 0; + } + } + } + break; + + case WM_RBUTTONDOWN: + { + int iCounts = SendMessage(hwnd, LB_GETSELCOUNT, 0, 0); + if (iCounts != LB_ERR && iCounts > 1) + return 0; + SendMessage(hwnd, WM_LBUTTONDOWN, wParam, lParam); + } + break; + + case WM_RBUTTONUP: + SendMessage(hwnd, WM_LBUTTONUP, wParam, lParam); + break; + + case WM_MEASUREITEM: + { + MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam; + if (mis->CtlType == ODT_MENU) + return Menu_MeasureItem(lParam); + } + return FALSE; + + case WM_DRAWITEM: + { + DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam; + if (dis->CtlType == ODT_MENU) + return Menu_DrawItem(lParam); + } + return FALSE; + + case WM_CONTEXTMENU: + { + SESSION_INFO *si = dat->si; + if (si == NULL) + break; + + int height = 0; + TVHITTESTINFO hti; + hti.pt.x = GET_X_LPARAM(lParam); + hti.pt.y = GET_Y_LPARAM(lParam); + if (hti.pt.x == -1 && hti.pt.y == -1) { + int index = SendMessage(hwnd, LB_GETCURSEL, 0, 0); + int top = SendMessage(hwnd, LB_GETTOPINDEX, 0, 0); + height = SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0); + hti.pt.x = 4; + hti.pt.y = (index - top) * height + 1; + } + else ScreenToClient(hwnd, &hti.pt); + + int item = (DWORD)(SendMessage(hwnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(hti.pt.x, hti.pt.y))); + if (HIWORD(item) == 1) + item = (DWORD)(-1); + else + item &= 0xFFFF; + + USERINFO *ui = pci->SM_GetUserFromIndex(si->ptszID, si->pszModule, item); + if (ui) { + HMENU hMenu = 0; + USERINFO uinew; + memcpy(&uinew, ui, sizeof(USERINFO)); + if (hti.pt.x == -1 && hti.pt.y == -1) + hti.pt.y += height - 4; + ClientToScreen(hwnd, &hti.pt); + + UINT uID = CreateGCMenu(hwnd, &hMenu, 0, hti.pt, si, uinew.pszUID, uinew.pszNick); + switch (uID) { + case 0: + break; + + case 20020: // add to highlight... + { + THighLightEdit the = { THighLightEdit::CMD_ADD, si, ui }; + HWND hwndDlg = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_ADDHIGHLIGHT), dat->m_pContainer->hwnd, CMUCHighlight::dlgProcAdd, (LPARAM)&the); + TranslateDialogDefault(hwndDlg); + + RECT rc, rcWnd; + GetClientRect(dat->m_pContainer->hwnd, &rcWnd); + GetWindowRect(hwndDlg, &rc); + SetWindowPos(hwndDlg, HWND_TOP, (rcWnd.right - (rc.right - rc.left)) / 2, (rcWnd.bottom - (rc.bottom - rc.top)) / 2, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); + } + break; + + case ID_MESS: + pci->DoEventHookAsync(GetParent(hwnd), si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui, nullptr, 0); + break; + + default: + int iCount = SendMessage(hwnd, LB_GETCOUNT, 0, 0); + if (iCount != LB_ERR) { + int iSelectedItems = SendMessage(hwnd, LB_GETSELCOUNT, 0, 0); + if (iSelectedItems != LB_ERR) { + int *pItems = (int *)mir_alloc(sizeof(int) * (iSelectedItems + 1)); + if (pItems) { + if (SendMessage(hwnd, LB_GETSELITEMS, iSelectedItems, (LPARAM)pItems) != LB_ERR) { + for (int i = 0; i < iSelectedItems; i++) { + USERINFO *ui1 = pci->SM_GetUserFromIndex(si->ptszID, si->pszModule, pItems[i]); + if (ui1) + pci->DoEventHookAsync(hwndParent, si->ptszID, si->pszModule, GC_USER_NICKLISTMENU, ui1, nullptr, (LPARAM)uID); + } + } + mir_free(pItems); + } + } + } + break; + } + DestroyGCMenu(&hMenu, 1); + return TRUE; + } + } + break; + + case WM_MOUSEMOVE: + Chat_HoverMouse(dat->si, hwnd, lParam, M.GetByte("adv_TipperTooltip", 1) && ServiceExists("mToolTip/HideTip")); + break; + } + return mir_callNextSubclass(hwnd, NicklistSubclassProc, msg, wParam, lParam); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// calculate the required rectangle for a string using the given font. This is more +// precise than using GetTextExtentPoint...() + +int GetTextPixelSize(wchar_t* pszText, HFONT hFont, bool bWidth) +{ + if (!pszText || !hFont) + return 0; + + HDC hdc = GetDC(NULL); + HFONT hOldFont = (HFONT)SelectObject(hdc, hFont); + + RECT rc = { 0 }; + DrawText(hdc, pszText, -1, &rc, DT_CALCRECT); + + SelectObject(hdc, hOldFont); + ReleaseDC(NULL, hdc); + return bWidth ? rc.right - rc.left : rc.bottom - rc.top; +} + +static void __cdecl phase2(void * lParam) +{ + Thread_SetName("TabSRMM: phase2"); + + SESSION_INFO *si = (SESSION_INFO*)lParam; + Sleep(30); + if (si && si->hWnd) + PostMessage(si->hWnd, GC_REDRAWLOG2, 0, 0); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// the actual group chat session window procedure.Handles the entire chat session window +// which is usually a (tabbed) child of a container class window. + +CChatRoomDlg::CChatRoomDlg(SESSION_INFO *_si) + : CTabBaseDlg(IDD_CHANNEL), + m_btnOk(this, IDOK), + m_list(this, IDC_LIST), + m_btnBold(this, IDC_BOLD), + m_btnColor(this, IDC_COLOR), + m_btnFilter(this, IDC_FILTER), + m_btnItalic(this, IDC_ITALICS), + m_btnHistory(this, IDC_HISTORY), + m_btnBkColor(this, IDC_BKGCOLOR), + m_btnChannelMgr(this, IDC_CHANMGR), + m_btnUnderline(this, IDC_UNDERLINE), + m_btnNickList(this, IDC_SHOWNICKLIST) +{ + m_bType = SESSIONTYPE_CHAT; + + si = _si; + m_hContact = si->hContact; + m_szProto = GetContactProto(si->hContact); + + m_btnOk.OnClick = Callback(this, &CChatRoomDlg::OnClick_OK); + m_btnFilter.OnClick = Callback(this, &CChatRoomDlg::OnClick_Filter); + m_btnHistory.OnClick = Callback(this, &CChatRoomDlg::OnClick_History); + m_btnNickList.OnClick = Callback(this, &CChatRoomDlg::OnClick_ShowNickList); + m_btnChannelMgr.OnClick = Callback(this, &CChatRoomDlg::OnClick_ChanMgr); + + m_btnColor.OnClick = Callback(this, &CChatRoomDlg::OnClick_Color); + m_btnBkColor.OnClick = Callback(this, &CChatRoomDlg::OnClick_BkColor); + m_btnBold.OnClick = m_btnItalic.OnClick = m_btnUnderline.OnClick = Callback(this, &CChatRoomDlg::OnClick_BIU); + + m_message.OnChange = Callback(this, &CChatRoomDlg::OnChange_Message); + + m_list.OnDblClick = Callback(this, &CChatRoomDlg::OnDblClick_List); +} + +CThumbBase* CChatRoomDlg::CreateThumb(CProxyWindow *pProxy) const +{ + return new CThumbMUC(pProxy, si); +} + +void CChatRoomDlg::ClearLog() +{ + SESSION_INFO *s = pci->SM_FindSession(si->ptszID, si->pszModule); + if (s) { + m_log.SetText(L""); + pci->LM_RemoveAll(&s->pLog, &s->pLogEnd); + s->iEventCount = 0; + s->LastTime = 0; + si->iEventCount = 0; + si->LastTime = 0; + si->pLog = s->pLog; + si->pLogEnd = s->pLogEnd; + PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); + } +} + +void CChatRoomDlg::OnInitDialog() +{ + SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)this); + + m_cache = CContactCache::getContactCache(m_hContact); + m_cache->updateNick(); + m_cache->updateUIN(); + + si->hWnd = m_hwnd; + si->dat = this; + m_bIsAutosizingInput = IsAutoSplitEnabled(); + m_fLimitedUpdate = false; + m_iInputAreaHeight = -1; + + m_iSplitterY = m_pContainer->settings->iSplitterY; + if (m_bIsAutosizingInput) + m_iSplitterY = GetDefaultMinimumInputHeight(); + + CProxyWindow::add(this); + + // Typing support for GCW_PRIVMESS sessions + if (si->iType == GCW_PRIVMESS) { + m_nTypeMode = PROTOTYPE_SELFTYPING_OFF; + SetTimer(m_hwnd, TIMERID_TYPE, 1000, NULL); + } + + m_pPanel.setActive(false); + m_pPanel.Configure(); + M.AddWindow(m_hwnd, m_hContact); + BroadCastContainer(m_pContainer, DM_REFRESHTABINDEX, 0, 0); + + m_log.SendMsg(EM_SETOLECALLBACK, 0, (LPARAM)&reOleCallback); + m_log.SendMsg(EM_AUTOURLDETECT, 1, 0); + SetWindowLongPtr(GetDlgItem(m_hwnd, IDC_PANELSPLITTER), GWLP_WNDPROC, (LONG_PTR)SplitterSubclassProc); + TABSRMM_FireEvent(m_hContact, m_hwnd, MSG_WINDOW_EVT_OPENING, 0); + + m_log.SendMsg(EM_SETEVENTMASK, 0, m_log.SendMsg(EM_GETEVENTMASK, 0, 0) | ENM_LINK | ENM_MOUSEEVENTS | ENM_KEYEVENTS); + m_log.SendMsg(EM_LIMITTEXT, 0x7FFFFFFF, 0); + m_log.SendMsg(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3)); + + m_message.SendMsg(EM_SETEVENTMASK, 0, ENM_REQUESTRESIZE | ENM_MOUSEEVENTS | ENM_SCROLL | ENM_KEYEVENTS | ENM_CHANGE); + m_message.SendMsg(EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3)); + + m_pPanel.loadHeight(); + + if (PluginConfig.g_hMenuTrayUnread != 0 && m_hContact != 0 && m_szProto != NULL) + UpdateTrayMenu(0, m_wStatus, m_szProto, m_wszStatus, m_hContact, FALSE); + + DM_ThemeChanged(); + m_log.SendMsg(EM_HIDESELECTION, TRUE, 0); + + GetMYUIN(); + GetMyNick(); + + HWND hwndBtn = CreateWindowEx(0, L"MButtonClass", L"", WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 0, 6, DPISCALEY_S(20), m_hwnd, (HMENU)IDC_TOGGLESIDEBAR, g_hInst, NULL); + CustomizeButton(hwndBtn); + SendMessage(hwndBtn, BUTTONSETASTHEMEDBTN, 1, 0); + SendMessage(hwndBtn, BUTTONSETCONTAINER, (LPARAM)m_pContainer, 0); + SendMessage(hwndBtn, BUTTONSETASFLATBTN, FALSE, 0); + SendMessage(hwndBtn, BUTTONSETASTOOLBARBUTTON, TRUE, 0); + SendMessage(hwndBtn, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Expand or collapse the side bar"), BATF_UNICODE); + + DM_InitTip(); + BB_InitDlgButtons(); + SendMessage(m_hwnd, WM_CBD_LOADICONS, 0, 0); + + mir_subclassWindow(GetDlgItem(m_hwnd, IDC_SPLITTERX), SplitterSubclassProc); + mir_subclassWindow(GetDlgItem(m_hwnd, IDC_SPLITTERY), SplitterSubclassProc); + mir_subclassWindow(m_list.GetHwnd(), NicklistSubclassProc); + mir_subclassWindow(m_log.GetHwnd(), LogSubclassProc); + mir_subclassWindow(m_btnFilter.GetHwnd(), ButtonSubclassProc); + mir_subclassWindow(m_btnColor.GetHwnd(), ButtonSubclassProc); + mir_subclassWindow(m_btnBkColor.GetHwnd(), ButtonSubclassProc); + + mir_subclassWindow(m_message.GetHwnd(), MessageSubclassProc); + m_message.SendMsg(EM_SUBCLASSED, 0, 0); + + SendMessage(m_hwnd, GC_SETWNDPROPS, 0, 0); + SendMessage(m_hwnd, GC_UPDATESTATUSBAR, 0, 0); + SendMessage(m_hwnd, GC_UPDATETITLE, 0, 1); + + RECT rc; + SendMessage(m_pContainer->hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)&rc); + SetWindowPos(m_hwnd, HWND_TOP, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), 0); + ShowWindow(m_hwnd, SW_SHOW); + PostMessage(m_hwnd, GC_UPDATENICKLIST, 0, 0); + m_pContainer->hwndActive = m_hwnd; + TABSRMM_FireEvent(m_hContact, m_hwnd, MSG_WINDOW_EVT_OPEN, 0); +} + +void CChatRoomDlg::OnDestroy() +{ + // Typing support for GCW_PRIVMESS sessions + if (si->iType == GCW_PRIVMESS) + if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) + DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); + + if (pcli->pfnGetEvent(si->hContact, 0)) + pcli->pfnRemoveEvent(si->hContact, GC_FAKE_EVENT); + si->wState &= ~STATE_TALK; + si->hWnd = NULL; + si->dat = NULL; + si = NULL; + + TABSRMM_FireEvent(m_hContact, m_hwnd, MSG_WINDOW_EVT_CLOSING, 0); + + DM_FreeTheme(); + + UpdateTrayMenuState(this, FALSE); // remove me from the tray menu (if still there) + if (PluginConfig.g_hMenuTrayUnread) + DeleteMenu(PluginConfig.g_hMenuTrayUnread, (UINT_PTR)m_hContact, MF_BYCOMMAND); + + if (m_hSmileyIcon) + DestroyIcon(m_hSmileyIcon); + + if (m_hwndTip) + DestroyWindow(m_hwndTip); + + int i = GetTabIndexFromHWND(m_hwndParent, m_hwnd); + if (i >= 0) { + SendMessage(m_hwndParent, WM_USER + 100, 0, 0); // clean up tooltip + TabCtrl_DeleteItem(m_hwndParent, i); + BroadCastContainer(m_pContainer, DM_REFRESHTABINDEX, 0, 0); + m_iTabID = -1; + } + if (m_pWnd) { + delete m_pWnd; + m_pWnd = 0; + } + if (m_sbCustom) { + delete m_sbCustom; + m_sbCustom = 0; + } + + M.RemoveWindow(m_hwnd); + + TABSRMM_FireEvent(m_hContact, m_hwnd, MSG_WINDOW_EVT_CLOSE, 0); + + memset((void*)&m_pContainer->mOld, -1000, sizeof(MARGINS)); + PostMessage(m_pContainer->hwnd, WM_SIZE, 0, 1); + + if (m_pContainer->dwFlags & CNT_SIDEBAR) + m_pContainer->SideBar->removeSession(this); + mir_free(m_enteredText); + SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0); +} + +void CChatRoomDlg::OnClick_OK(CCtrlButton*) +{ + if (GetSendButtonState(m_hwnd) == PBS_DISABLED) + return; + + MODULEINFO *mi = pci->MM_FindModule(si->pszModule); + if (mi == NULL) + return; + + ptrA pszRtf(Message_GetFromStream(m_message.GetHwnd())); + pci->SM_AddCommand(si->ptszID, si->pszModule, pszRtf); + + CMStringW ptszText(ptrW(mir_utf8decodeW(pszRtf))); + if (ptszText.IsEmpty()) + return; + + DoRtfToTags(ptszText, mi->nColorCount, mi->crColors); + ptszText.Trim(); + ptszText.Replace(L"%", L"%%"); + + if (mi->bAckMsg) { + Utils::enableDlgControl(m_hwnd, IDC_MESSAGE, false); + m_message.SendMsg(EM_SETREADONLY, TRUE, 0); + } + else SetDlgItemText(m_hwnd, IDC_MESSAGE, L""); + + Utils::enableDlgControl(m_hwnd, IDOK, false); + + // Typing support for GCW_PRIVMESS sessions + if (si->iType == GCW_PRIVMESS) + if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) + DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); + + bool fSound = true; + if (ptszText[0] == '/' || si->iType == GCW_SERVER) + fSound = false; + pci->DoEventHookAsync(m_hwnd, si->ptszID, si->pszModule, GC_USER_MESSAGE, NULL, ptszText, 0); + mi->idleTimeStamp = time(0); + mi->lastIdleCheck = 0; + pci->SM_BroadcastMessage(si->pszModule, GC_UPDATESTATUSBAR, 0, 1, TRUE); + if (m_pContainer) + if (fSound && !nen_options.iNoSounds && !(m_pContainer->dwFlags & CNT_NOSOUND)) + SkinPlaySound("ChatSent"); + + SetFocus(m_message.GetHwnd()); +} + +void CChatRoomDlg::OnClick_Filter(CCtrlButton *pButton) +{ + if (!pButton->Enabled()) + return; + + if (si->iLogFilterFlags == 0 && !si->bFilterEnabled) { + MessageBox(0, TranslateT("The filter cannot be enabled, because there are no event types selected either global or for this chat room"), TranslateT("Event filter error"), MB_OK); + si->bFilterEnabled = 0; + } + else si->bFilterEnabled = !si->bFilterEnabled; + + m_btnFilter.SendMsg(BUTTONSETOVERLAYICON, + (LPARAM)(si->bFilterEnabled ? PluginConfig.g_iconOverlayEnabled : PluginConfig.g_iconOverlayDisabled), 0); + + if (si->bFilterEnabled && M.GetByte(CHAT_MODULE, "RightClickFilter", 0) == 0) { + SendMessage(m_hwnd, GC_SHOWFILTERMENU, 0, 0); + return; + } + SendMessage(m_hwnd, GC_REDRAWLOG, 0, 0); + SendMessage(m_hwnd, GC_UPDATETITLE, 0, 0); + db_set_b(si->hContact, CHAT_MODULE, "FilterEnabled", (BYTE)si->bFilterEnabled); +} + +void CChatRoomDlg::OnClick_History(CCtrlButton *pButton) +{ + if (!pButton->Enabled()) + return; + + MODULEINFO *pInfo = pci->MM_FindModule(si->pszModule); + if (ServiceExists("MSP/HTMLlog/ViewLog") && strstr(si->pszModule, "IRC")) { + char szName[MAX_PATH]; + WideCharToMultiByte(CP_ACP, 0, si->ptszName, -1, szName, MAX_PATH, 0, 0); + szName[MAX_PATH - 1] = 0; + CallService("MSP/HTMLlog/ViewLog", (WPARAM)si->pszModule, (LPARAM)szName); + } + else if (pInfo) + ShellExecute(m_hwnd, NULL, pci->GetChatLogsFilename(si, 0), NULL, NULL, SW_SHOW); +} + +void CChatRoomDlg::OnClick_ShowNickList(CCtrlButton *pButton) +{ + if (!pButton->Enabled()) + return; + if (si->iType == GCW_SERVER) + return; + + si->bNicklistEnabled = !si->bNicklistEnabled; + + SendMessage(m_hwnd, WM_SIZE, 0, 0); + if (CSkin::m_skinEnabled) + InvalidateRect(m_hwnd, NULL, TRUE); + PostMessage(m_hwnd, GC_SCROLLTOBOTTOM, 0, 0); +} + +void CChatRoomDlg::OnClick_ChanMgr(CCtrlButton *pButton) +{ + if (pButton->Enabled()) + pci->DoEventHookAsync(m_hwnd, si->ptszID, si->pszModule, GC_USER_CHANMGR, NULL, NULL, 0); +} + +void CChatRoomDlg::OnClick_BIU(CCtrlButton *pButton) +{ + if (!pButton->Enabled()) + return; + + CHARFORMAT2 cf; + cf.cbSize = sizeof(CHARFORMAT2); + cf.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE; + cf.dwEffects = 0; + + if (IsDlgButtonChecked(m_hwnd, IDC_BOLD)) + cf.dwEffects |= CFE_BOLD; + if (IsDlgButtonChecked(m_hwnd, IDC_ITALICS)) + cf.dwEffects |= CFE_ITALIC; + if (IsDlgButtonChecked(m_hwnd, IDC_UNDERLINE)) + cf.dwEffects |= CFE_UNDERLINE; + + m_message.SendMsg(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); +} + +void CChatRoomDlg::OnClick_Color(CCtrlButton *pButton) +{ + if (!pButton->Enabled()) + return; + + CHARFORMAT2 cf; + cf.cbSize = sizeof(CHARFORMAT2); + cf.dwEffects = 0; + + if (IsDlgButtonChecked(m_hwnd, IDC_COLOR)) { + if (M.GetByte(CHAT_MODULE, "RightClickFilter", 0) == 0) + SendMessage(m_hwnd, GC_SHOWCOLORCHOOSER, 0, IDC_COLOR); + else if (si->bFGSet) { + cf.dwMask = CFM_COLOR; + cf.crTextColor = pci->MM_FindModule(si->pszModule)->crColors[si->iFG]; + m_message.SendMsg(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } + } + else { + COLORREF cr; + LoadLogfont(MSGFONTID_MESSAGEAREA, NULL, &cr, FONTMODULE); + cf.dwMask = CFM_COLOR; + cf.crTextColor = cr; + m_message.SendMsg(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } +} + +void CChatRoomDlg::OnClick_BkColor(CCtrlButton *pButton) +{ + if (!pButton->Enabled()) + return; + + CHARFORMAT2 cf; + cf.cbSize = sizeof(CHARFORMAT2); + cf.dwEffects = 0; + + if (IsDlgButtonChecked(m_hwnd, IDC_BKGCOLOR)) { + if (M.GetByte(CHAT_MODULE, "RightClickFilter", 0) == 0) + SendMessage(m_hwnd, GC_SHOWCOLORCHOOSER, 0, IDC_BKGCOLOR); + else if (si->bBGSet) { + cf.dwMask = CFM_BACKCOLOR; + cf.crBackColor = pci->MM_FindModule(si->pszModule)->crColors[si->iBG]; + m_message.SendMsg(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } + } + else { + cf.dwMask = CFM_BACKCOLOR; + cf.crBackColor = (COLORREF)M.GetDword(FONTMODULE, "inputbg", SRMSGDEFSET_BKGCOLOUR); + m_message.SendMsg(EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf); + } +} + +void CChatRoomDlg::OnChange_Message(CCtrlEdit*) +{ + if (m_pContainer->hwndActive == m_hwnd) + UpdateReadChars(); + m_dwLastActivity = GetTickCount(); + m_pContainer->dwLastActivity = m_dwLastActivity; + m_btnOk.SendMsg(BUTTONSETASNORMAL, GetRichTextLength(m_message.GetHwnd()) != 0, 0); + m_btnOk.Enable(GetRichTextLength(m_message.GetHwnd()) != 0); + + // Typing support for GCW_PRIVMESS sessions + if (si->iType == GCW_PRIVMESS) { + if (!(GetKeyState(VK_CONTROL) & 0x8000)) { + m_nLastTyping = GetTickCount(); + if (GetWindowTextLength(m_message.GetHwnd())) { + if (m_nTypeMode == PROTOTYPE_SELFTYPING_OFF) { + if (!(m_dwFlags & MWF_INITMODE)) + DM_NotifyTyping(PROTOTYPE_SELFTYPING_ON); + } + } + else if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON) + DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); + } + } +} + +void CChatRoomDlg::OnDblClick_List(CCtrlListBox*) +{ + TVHITTESTINFO hti; + hti.pt.x = (short)LOWORD(GetMessagePos()); + hti.pt.y = (short)HIWORD(GetMessagePos()); + ScreenToClient(m_list.GetHwnd(), &hti.pt); + + int item = LOWORD(m_list.SendMsg(LB_ITEMFROMPOINT, 0, MAKELPARAM(hti.pt.x, hti.pt.y))); + USERINFO *ui = pci->UM_FindUserFromIndex(si->pUsers, item); + if (ui == nullptr) + return; + + bool bShift = (GetKeyState(VK_SHIFT) & 0x8000) != 0; + if (g_Settings.bDoubleClick4Privat ? bShift : !bShift) { + int selStart = LOWORD(m_message.SendMsg(EM_GETSEL, 0, 0)); + CMStringW tszName(ui->pszNick); + if (selStart == 0) + tszName.AppendChar(':'); + tszName.AppendChar(' '); + + m_message.SendMsg(EM_REPLACESEL, FALSE, (LPARAM)tszName.GetString()); + PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); + SetFocus(m_message.GetHwnd()); + } + else pci->DoEventHookAsync(m_hwnd, si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui, NULL, 0); +} + +INT_PTR CChatRoomDlg::DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (si == NULL && (uMsg == WM_ACTIVATE || uMsg == WM_SETFOCUS)) + return 0; + + POINT pt, tmp, cur; + RECT rc; + MODULEINFO *pInfo; + + switch (uMsg) { + case WM_SETFOCUS: + if (CMimAPI::m_shutDown) + break; + + UpdateWindowState(WM_SETFOCUS); + SetFocus(m_message.GetHwnd()); + return 1; + + case WM_TIMECHANGE: + PostMessage(m_hwnd, GC_REDRAWLOG, 0, 0); + break; + + case WM_CBD_LOADICONS: + Srmm_UpdateToolbarIcons(m_hwnd); + return 0; + + case GC_SETWNDPROPS: + pInfo = si ? pci->MM_FindModule(si->pszModule) : NULL; + if (pInfo) { + m_btnBold.Enable(pInfo->bBold); + m_btnItalic.Enable(pInfo->bItalics); + m_btnUnderline.Enable(pInfo->bUnderline); + m_btnColor.Enable(pInfo->bColor); + m_btnBkColor.Enable(pInfo->bBkgColor); + if (si->iType == GCW_CHATROOM) + m_btnChannelMgr.Enable(pInfo->bChanMgr); + } + m_log.SendMsg(EM_SETBKGNDCOLOR, 0, M.GetDword(FONTMODULE, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR)); + + DM_InitRichEdit(); + m_btnOk.SendMsg(BUTTONSETASNORMAL, TRUE, 0); + + m_list.SetItemHeight(0, g_Settings.iNickListFontHeight); + InvalidateRect(m_list.GetHwnd(), NULL, TRUE); + + m_btnFilter.SendMsg(BUTTONSETOVERLAYICON, (LPARAM)(si->bFilterEnabled ? PluginConfig.g_iconOverlayEnabled : PluginConfig.g_iconOverlayDisabled), 0); + SendMessage(m_hwnd, WM_SIZE, 0, 0); + SendMessage(m_hwnd, GC_REDRAWLOG2, 0, 0); + break; + + case DM_UPDATETITLE: + case GC_UPDATETITLE: + if (!m_bWasDeleted) { + m_wStatus = si->wStatus; + + const wchar_t *szNick = m_cache->getNick(); + if (mir_wstrlen(szNick) > 0) { + if (M.GetByte("cuttitle", 0)) + CutContactName(szNick, m_wszTitle, _countof(m_wszTitle)); + else + wcsncpy_s(m_wszTitle, szNick, _TRUNCATE); + } + + wchar_t szTemp[100]; + HICON hIcon = 0; + + switch (si->iType) { + case GCW_CHATROOM: + hIcon = Skin_LoadProtoIcon(si->pszModule, (m_wStatus <= ID_STATUS_OFFLINE) ? ID_STATUS_OFFLINE : m_wStatus); + mir_snwprintf(szTemp, + (si->nUsersInNicklist == 1) ? TranslateT("%s: chat room (%u user%s)") : TranslateT("%s: chat room (%u users%s)"), + szNick, si->nUsersInNicklist, si->bFilterEnabled ? TranslateT(", event filter active") : L""); + break; + case GCW_PRIVMESS: + hIcon = Skin_LoadProtoIcon(si->pszModule, (m_wStatus <= ID_STATUS_OFFLINE) ? ID_STATUS_OFFLINE : m_wStatus); + if (si->nUsersInNicklist == 1) + mir_snwprintf(szTemp, TranslateT("%s: message session"), szNick); + else + mir_snwprintf(szTemp, TranslateT("%s: message session (%u users)"), szNick, si->nUsersInNicklist); + break; + case GCW_SERVER: + mir_snwprintf(szTemp, L"%s: Server", szNick); + hIcon = LoadIconEx("window"); + break; + } + + if (m_pWnd) { + m_pWnd->updateTitle(m_wszTitle); + m_pWnd->updateIcon(hIcon); + } + m_hTabStatusIcon = hIcon; + + if (lParam) + m_hTabIcon = m_hTabStatusIcon; + + if (m_cache->getStatus() != m_cache->getOldStatus()) { + wcsncpy_s(m_wszStatus, pcli->pfnGetStatusModeDescription(m_wStatus, 0), _TRUNCATE); + + TCITEM item = {}; + item.mask = TCIF_TEXT; + item.pszText = m_wszTitle; + TabCtrl_SetItem(m_hwndParent, m_iTabID, &item); + } + SetWindowText(m_hwnd, szTemp); + if (m_pContainer->hwndActive == m_hwnd) { + SendMessage(m_pContainer->hwnd, DM_UPDATETITLE, (WPARAM)m_hwnd, 1); + SendMessage(m_hwnd, GC_UPDATESTATUSBAR, 0, 0); + } + } + break; + + case GC_UPDATESTATUSBAR: + if (m_bWasDeleted) + return 0; + + if (m_pContainer->hwndActive != m_hwnd || m_pContainer->hwndStatus == 0 || CMimAPI::m_shutDown || m_wszStatusBar[0]) + break; + + if (si->pszModule != NULL) { + wchar_t szFinalStatusBarText[512]; + + //Mad: strange rare crash here... + MODULEINFO *mi = pci->MM_FindModule(si->pszModule); + if (!mi) + break; + + if (!mi->ptszModDispName) + break; + + int x = 12; + x += GetTextPixelSize(mi->ptszModDispName, (HFONT)SendMessage(m_pContainer->hwndStatus, WM_GETFONT, 0, 0), TRUE); + x += GetSystemMetrics(SM_CXSMICON); + + if (m_pPanel.isActive()) { + time_t now = time(0); + DWORD diff = (now - mi->idleTimeStamp) / 60; + + if ((diff >= 1 && diff != mi->lastIdleCheck) || lParam) { + mi->lastIdleCheck = diff; + if (diff == 0) + mi->tszIdleMsg[0] = 0; + else if (diff > 59) { + DWORD hours = diff / 60; + DWORD minutes = diff % 60; + mir_snwprintf(mi->tszIdleMsg, TranslateT(", %d %s, %d %s idle"), hours, hours > 1 ? + TranslateT("hours") : TranslateT("hour"), + minutes, minutes > 1 ? TranslateT("minutes") : TranslateT("minute")); + } + else mir_snwprintf(mi->tszIdleMsg, TranslateT(", %d %s idle"), diff, diff > 1 ? TranslateT("minutes") : TranslateT("minute")); + } + mir_snwprintf(szFinalStatusBarText, TranslateT("%s on %s%s"), m_wszMyNickname, mi->ptszModDispName, mi->tszIdleMsg); + } + else { + if (si->ptszStatusbarText) + mir_snwprintf(szFinalStatusBarText, L"%s %s", mi->ptszModDispName, si->ptszStatusbarText); + else + wcsncpy_s(szFinalStatusBarText, mi->ptszModDispName, _TRUNCATE); + } + SendMessage(m_pContainer->hwndStatus, SB_SETTEXT, 0, (LPARAM)szFinalStatusBarText); + UpdateStatusBar(); + m_pPanel.Invalidate(); + if (m_pWnd) + m_pWnd->Invalidate(); + return TRUE; + } + break; + + case WM_SIZE: + if (m_ipFieldHeight == 0) + m_ipFieldHeight = CInfoPanel::m_ipConfig.height1; + + if (wParam == SIZE_MAXIMIZED) + PostMessage(m_hwnd, GC_SCROLLTOBOTTOM, 0, 0); + + if (!IsIconic(m_hwnd)) { + int panelHeight = m_pPanel.getHeight() + 1; + + GetClientRect(m_hwnd, &rc); + int cx = rc.right; + + CTabBaseDlg::DlgProc(uMsg, 0, 0); // call basic window resizer + + BB_SetButtonsPos(); + + rc.left = panelHeight <= CInfoPanel::LEFT_OFFSET_LOGO ? panelHeight : CInfoPanel::LEFT_OFFSET_LOGO; + rc.right = cx; + rc.top = 1; + rc.bottom = (panelHeight > CInfoPanel::DEGRADE_THRESHOLD ? rc.top + m_ipFieldHeight - 2 : panelHeight - 1); + m_rcNick = rc; + + rc.left = panelHeight <= CInfoPanel::LEFT_OFFSET_LOGO ? panelHeight : CInfoPanel::LEFT_OFFSET_LOGO; + rc.right = cx; + rc.bottom = panelHeight - 2; + rc.top = m_rcNick.bottom + 1; + m_rcUIN = rc; + + if (m_hwndIEView || m_hwndHPP) + ResizeIeView(); + DetermineMinHeight(); + } + return 0; + + case GC_REDRAWWINDOW: + InvalidateRect(m_hwnd, NULL, TRUE); + break; + + case GC_REDRAWLOG: + si->LastTime = 0; + if (si->pLog) { + LOGINFO * pLog = si->pLog; + if (si->iEventCount > 60) { + int index = 0; + while (index < 59) { + if (pLog->next == NULL) + break; + pLog = pLog->next; + if ((si->iType != GCW_CHATROOM && si->iType != GCW_PRIVMESS) || !si->bFilterEnabled || (si->iLogFilterFlags&pLog->iType) != 0) + index++; + } + StreamInEvents(pLog, si, TRUE); + mir_forkthread(phase2, si); + } + else StreamInEvents(si->pLogEnd, si, TRUE); + } + else SendMessage(m_hwnd, GC_CONTROL_MSG, WINDOW_CLEARLOG, 0); + break; + + case GC_REDRAWLOG2: + si->LastTime = 0; + if (si->pLog) + StreamInEvents(si->pLogEnd, si, TRUE); + break; + + case GC_ADDLOG: + if (PluginConfig.m_bUseDividers) { + if (PluginConfig.m_bDividersUsePopupConfig) { + if (!MessageWindowOpened(0, (LPARAM)m_hwnd)) + DM_AddDivider(); + } + else { + bool bInactive = (GetForegroundWindow() != m_pContainer->hwnd || GetActiveWindow() != m_pContainer->hwnd); + if (bInactive) + DM_AddDivider(); + else if (m_pContainer->hwndActive != m_hwnd) + DM_AddDivider(); + } + } + + if (si->pLogEnd) + StreamInEvents(si->pLog, si, FALSE); + else + SendMessage(m_hwnd, GC_CONTROL_MSG, WINDOW_CLEARLOG, 0); + break; + + case DM_TYPING: + // Typing support for GCW_PRIVMESS sessions + if (si->iType == GCW_PRIVMESS) { + int preTyping = m_nTypeSecs != 0; + m_nTypeSecs = (int)lParam > 0 ? (int)lParam : 0; + + if (m_nTypeSecs) + m_bShowTyping = 0; + + SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, preTyping); + } + return TRUE; + + case WM_CTLCOLORLISTBOX: + SetBkColor((HDC)wParam, g_Settings.crUserListBGColor); + return (INT_PTR)pci->hListBkgBrush; + + case WM_MEASUREITEM: + { + MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam; + if (mis->CtlType == ODT_MENU) { + if (m_pPanel.isHovered()) { + mis->itemHeight = 0; + mis->itemWidth = 6; + return TRUE; + } + return Menu_MeasureItem(lParam); + } + mis->itemHeight = g_Settings.iNickListFontHeight; + } + return TRUE; + + case WM_DRAWITEM: + { + DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam; + if (dis->CtlType == ODT_MENU) { + if (m_pPanel.isHovered()) { + DrawMenuItem(dis, (HICON)dis->itemData, 0); + return TRUE; + } + return Menu_DrawItem(lParam); + } + + if (dis->CtlID == IDC_LIST) { + int x_offset = 0; + int index = dis->itemID; + + USERINFO *ui = pci->UM_FindUserFromIndex(si->pUsers, index); + if (ui == NULL) + return TRUE; + + int height = dis->rcItem.bottom - dis->rcItem.top; + if (height & 1) + height++; + int offset = (height == 10) ? 0 : height / 2; + + HICON hIcon = pci->SM_GetStatusIcon(si, ui); + HFONT hFont = g_Settings.UserListFonts[ui->iStatusEx]; + HFONT hOldFont = (HFONT)SelectObject(dis->hDC, hFont); + SetBkMode(dis->hDC, TRANSPARENT); + + int nickIndex = 0; + for (int i = 0; i < STATUSICONCOUNT; i++) { + if (hIcon == pci->hIcons[ICON_STATUS0 + i]) { + nickIndex = i; + break; + } + } + + if (dis->itemState & ODS_SELECTED) { + FillRect(dis->hDC, &dis->rcItem, g_Settings.SelectionBGBrush); + SetTextColor(dis->hDC, g_Settings.nickColors[6]); + } + else { + FillRect(dis->hDC, &dis->rcItem, pci->hListBkgBrush); + if (g_Settings.bColorizeNicks && nickIndex != 0) + SetTextColor(dis->hDC, g_Settings.nickColors[nickIndex - 1]); + else + SetTextColor(dis->hDC, g_Settings.UserListColors[ui->iStatusEx]); + } + x_offset = 2; + + if (g_Settings.bShowContactStatus && g_Settings.bContactStatusFirst && ui->ContactStatus) { + HICON icon = Skin_LoadProtoIcon(si->pszModule, ui->ContactStatus); + DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 8, icon, 16, 16, 0, NULL, DI_NORMAL); + IcoLib_ReleaseIcon(icon); + x_offset += 18; + } + + if (g_Settings.bClassicIndicators) { + char szTemp[3]; + szTemp[1] = 0; + szTemp[0] = szIndicators[nickIndex]; + if (szTemp[0]) { + SIZE szUmode; + GetTextExtentPoint32A(dis->hDC, szTemp, 1, &szUmode); + TextOutA(dis->hDC, x_offset, dis->rcItem.top, szTemp, 1); + x_offset += szUmode.cx + 2; + } + else x_offset += 8; + } + else { + DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 5, hIcon, 10, 10, 0, NULL, DI_NORMAL); + x_offset += 12; + } + + if (g_Settings.bShowContactStatus && !g_Settings.bContactStatusFirst && ui->ContactStatus) { + HICON icon = Skin_LoadProtoIcon(si->pszModule, ui->ContactStatus); + DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 8, icon, 16, 16, 0, NULL, DI_NORMAL); + IcoLib_ReleaseIcon(icon); + x_offset += 18; + } + + SIZE sz; + if (m_iSearchItem != -1 && m_iSearchItem == index && m_wszSearch[0]) { + COLORREF clr_orig = GetTextColor(dis->hDC); + GetTextExtentPoint32(dis->hDC, ui->pszNick, (int)mir_wstrlen(m_wszSearch), &sz); + SetTextColor(dis->hDC, RGB(250, 250, 0)); + TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick, (int)mir_wstrlen(m_wszSearch)); + SetTextColor(dis->hDC, clr_orig); + x_offset += sz.cx; + TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick + mir_wstrlen(m_wszSearch), int(mir_wstrlen(ui->pszNick) - mir_wstrlen(m_wszSearch))); + } + else { + GetTextExtentPoint32(dis->hDC, ui->pszNick, (int)mir_wstrlen(ui->pszNick), &sz); + TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick, (int)mir_wstrlen(ui->pszNick)); + SelectObject(dis->hDC, hOldFont); + } + return TRUE; + } + } + break; + + case WM_CONTEXTMENU: + { + DWORD idFrom = GetDlgCtrlID((HWND)wParam); + if (idFrom >= MIN_CBUTTONID && idFrom <= MAX_CBUTTONID) + Srmm_ClickToolbarIcon(m_hContact, idFrom, (HWND)wParam, 1); + } + break; + + case GC_UPDATENICKLIST: + { + int i = m_list.SendMsg(LB_GETTOPINDEX, 0, 0); + m_list.SendMsg(LB_SETCOUNT, si->nUsersInNicklist, 0); + m_list.SendMsg(LB_SETTOPINDEX, i, 0); + SendMessage(m_hwnd, GC_UPDATETITLE, 0, 0); + } + break; + + case GC_CONTROL_MSG: + switch (wParam) { + case SESSION_OFFLINE: + SendMessage(m_hwnd, GC_UPDATESTATUSBAR, 0, 0); + SendMessage(si->hWnd, GC_UPDATENICKLIST, 0, 0); + return TRUE; + + case SESSION_ONLINE: + SendMessage(m_hwnd, GC_UPDATESTATUSBAR, 0, 0); + return TRUE; + + case WINDOW_HIDDEN: + SendMessage(m_hwnd, GC_CLOSEWINDOW, 0, 1); + return TRUE; + + case WINDOW_CLEARLOG: + SetDlgItemText(m_hwnd, IDC_LOG, L""); + return TRUE; + + case SESSION_TERMINATE: + if (pcli->pfnGetEvent(si->hContact, 0)) + pcli->pfnRemoveEvent(si->hContact, GC_FAKE_EVENT); + + si->wState &= ~STATE_TALK; + m_bWasDeleted = true; + db_set_w(si->hContact, si->pszModule, "ApparentMode", 0); + SendMessage(m_hwnd, GC_CLOSEWINDOW, 0, lParam == 2 ? lParam : 1); + return TRUE; + + case WINDOW_MINIMIZE: + ShowWindow(m_hwnd, SW_MINIMIZE); +LABEL_SHOWWINDOW: + SendMessage(m_hwnd, WM_SIZE, 0, 0); + SendMessage(m_hwnd, GC_REDRAWLOG, 0, 0); + SendMessage(m_hwnd, GC_UPDATENICKLIST, 0, 0); + SendMessage(m_hwnd, GC_UPDATESTATUSBAR, 0, 0); + ShowWindow(m_hwnd, SW_SHOW); + SendMessage(m_hwnd, WM_SIZE, 0, 0); + SetForegroundWindow(m_hwnd); + return TRUE; + + case WINDOW_MAXIMIZE: + ShowWindow(m_hwnd, SW_MAXIMIZE); + goto LABEL_SHOWWINDOW; + + case SESSION_INITDONE: + if (M.GetByte(CHAT_MODULE, "PopupOnJoin", 0) != 0) + return TRUE; + + // fall through + case WINDOW_VISIBLE: + if (IsIconic(m_hwnd)) + ShowWindow(m_hwnd, SW_NORMAL); + goto LABEL_SHOWWINDOW; + } + break; + + case DM_SPLITTERMOVED: + RECT rcLog; + { + GetWindowRect(m_log.GetHwnd(), &rcLog); + if ((HWND)lParam == GetDlgItem(m_hwnd, IDC_SPLITTERX)) { + GetClientRect(m_hwnd, &rc); + pt.x = wParam, pt.y = 0; + ScreenToClient(m_hwnd, &pt); + + int iSplitterX = rc.right - pt.x + 1; + if (iSplitterX < 35) + iSplitterX = 35; + if (iSplitterX > rc.right - rc.left - 35) + iSplitterX = rc.right - rc.left - 35; + m_pContainer->settings->iSplitterX = iSplitterX; + SendMessage(m_hwnd, WM_SIZE, 0, 0); + } + else if ((HWND)lParam == GetDlgItem(m_hwnd, IDC_SPLITTERY) || lParam == -1) { + GetClientRect(m_hwnd, &rc); + rc.top += (m_pPanel.isActive() ? m_pPanel.getHeight() + 40 : 30); + pt.x = 0, pt.y = wParam; + ScreenToClient(m_hwnd, &pt); + + m_iSplitterY = rc.bottom - pt.y + DPISCALEY_S(1); + if (m_iSplitterY < DPISCALEY_S(23)) + m_iSplitterY = DPISCALEY_S(23); + if (m_iSplitterY > rc.bottom - rc.top - DPISCALEY_S(40)) + m_iSplitterY = rc.bottom - rc.top - DPISCALEY_S(40); + m_pContainer->settings->iSplitterY = m_iSplitterY; + UpdateToolbarBG(); + SendMessage(m_hwnd, WM_SIZE, 0, 0); + } + else if ((HWND)lParam == GetDlgItem(m_hwnd, IDC_PANELSPLITTER)) { + pt.x = 0, pt.y = wParam; + ScreenToClient(m_hwnd, &pt); + GetClientRect(m_log.GetHwnd(), &rc); + if ((pt.y + 2 >= MIN_PANELHEIGHT + 2) && (pt.y + 2 < 100) && (pt.y + 2 < rc.bottom - 30)) + m_pPanel.setHeight(pt.y + 2); + RedrawWindow(m_hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); + if (M.isAero()) + InvalidateRect(m_hwndParent, NULL, FALSE); + SendMessage(m_hwnd, WM_SIZE, DM_SPLITTERMOVED, 0); + break; + } + } + break; + + case GC_FIREHOOK: + if (lParam) { + GCHOOK *gch = (GCHOOK*)lParam; + NotifyEventHooks(pci->hSendEvent, 0, (WPARAM)gch); + if (gch->pDest) { + mir_free((void*)gch->pDest->ptszID); + mir_free((void*)gch->pDest->pszModule); + mir_free(gch->pDest); + } + mir_free(gch->ptszText); + mir_free(gch->ptszUID); + mir_free(gch); + } + break; + + case GC_CHANGEFILTERFLAG: + if (si->iLogFilterFlags == 0 && si->bFilterEnabled) + SendMessage(m_hwnd, WM_COMMAND, IDC_FILTER, 0); + break; + + case GC_SHOWFILTERMENU: + m_hwndFilter = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_FILTER), m_pContainer->hwnd, FilterWndProc, (LPARAM)si); + TranslateDialogDefault(m_hwndFilter); + + RECT rcFilter; + GetClientRect(m_hwndFilter, &rcFilter); + GetWindowRect(m_log.GetHwnd(), &rcLog); + + pt.x = rcLog.right; pt.y = rcLog.bottom; + ScreenToClient(m_pContainer->hwnd, &pt); + + SetWindowPos(m_hwndFilter, HWND_TOP, pt.x - rcFilter.right, pt.y - rcFilter.bottom, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW); + break; + + case GC_SHOWCOLORCHOOSER: + pci->ColorChooser(si, lParam == IDC_COLOR, m_hwnd, m_message.GetHwnd(), GetDlgItem(m_hwnd, lParam)); + break; + + case GC_SCROLLTOBOTTOM: + DM_ScrollToBottom(wParam, lParam); + return 0; + + case WM_TIMER: + if (wParam == TIMERID_FLASHWND) + if (m_bCanFlashTab) + FlashTab(true); + + // Typing support for GCW_PRIVMESS sessions + if (si->iType == GCW_PRIVMESS && wParam == TIMERID_TYPE) + DM_Typing(false); + break; + + case WM_ACTIVATE: + if (LOWORD(wParam) != WA_ACTIVE) { + m_pContainer->hwndSaved = 0; + break; + } + // fall through + + case WM_MOUSEACTIVATE: + UpdateWindowState(WM_ACTIVATE); + return 1; + + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->code) { + case EN_MSGFILTER: + bool isShift, isCtrl, isMenu; + { + UINT msg = ((MSGFILTER *)lParam)->msg; + WPARAM wp = ((MSGFILTER *)lParam)->wParam; + LPARAM lp = ((MSGFILTER *)lParam)->lParam; + + KbdState(isShift, isCtrl, isMenu); + + MSG message; + message.hwnd = m_hwnd; + message.message = msg; + message.lParam = lp; + message.wParam = wp; + + if (msg == WM_SYSKEYUP) { + if (wp == VK_MENU) + if (!m_fkeyProcessed && !(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000) && !(lp & (1 << 24))) + m_pContainer->MenuBar->autoShow(); + + return _dlgReturn(m_hwnd, 0); + } + + if (msg == WM_MOUSEMOVE) { + GetCursorPos(&pt); + DM_DismissTip(pt); + m_pPanel.trackMouse(pt); + break; + } + if (msg == WM_KEYDOWN) { + if ((wp == VK_INSERT && isShift && !isCtrl && !isMenu) || (wp == 'V' && !isShift && !isMenu && isCtrl)) { + m_message.SendMsg(EM_PASTESPECIAL, CF_UNICODETEXT, 0); + ((MSGFILTER*)lParam)->msg = WM_NULL; + ((MSGFILTER*)lParam)->wParam = 0; + ((MSGFILTER*)lParam)->lParam = 0; + return _dlgReturn(m_hwnd, 1); + } + } + + if (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN || msg == WM_MBUTTONDOWN) + m_pContainer->MenuBar->Cancel(); + + if ((msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) && !(GetKeyState(VK_RMENU) & 0x8000)) { + if (DM_GenericHotkeysCheck(&message)) { + m_fkeyProcessed = true; + return _dlgReturn(m_hwnd, 1); + } + + LRESULT mim_hotkey_check = CallService(MS_HOTKEY_CHECK, (WPARAM)&message, (LPARAM)(TABSRMM_HK_SECTION_GC)); + if (mim_hotkey_check) + m_fkeyProcessed = true; + + switch (mim_hotkey_check) { + case TABSRMM_HK_CHANNELMGR: + OnClick_ChanMgr(&m_btnChannelMgr); + return _dlgReturn(m_hwnd, 1); + case TABSRMM_HK_FILTERTOGGLE: + OnClick_Filter(&m_btnFilter); + InvalidateRect(m_btnFilter.GetHwnd(), NULL, TRUE); + return _dlgReturn(m_hwnd, 1); + case TABSRMM_HK_LISTTOGGLE: + OnClick_ShowNickList(&m_btnNickList); + return _dlgReturn(m_hwnd, 1); + case TABSRMM_HK_MUC_SHOWSERVER: + if (si->iType != GCW_SERVER) + pci->DoEventHookAsync(m_hwnd, si->ptszID, si->pszModule, GC_USER_MESSAGE, NULL, L"/servershow", 0); + return _dlgReturn(m_hwnd, 1); + } + } + + if (msg == WM_KEYDOWN && ((NMHDR*)lParam)->idFrom != IDC_MESSAGE) { + if ((wp == VK_NEXT && isCtrl && !isShift) || (wp == VK_TAB && isCtrl && !isShift)) // CTRL-TAB (switch tab/window) + SendMessage(m_pContainer->hwnd, DM_SELECTTAB, DM_SELECT_NEXT, 0); + else if ((wp == VK_PRIOR && isCtrl && !isShift) || (wp == VK_TAB && isCtrl && isShift)) // CTRL_SHIFT-TAB (switch tab/window) + SendMessage(m_pContainer->hwnd, DM_SELECTTAB, DM_SELECT_PREV, 0); + } + + if (msg == WM_KEYDOWN && wp == VK_TAB) { + if (((NMHDR*)lParam)->idFrom == IDC_LOG) { + SetFocus(m_message.GetHwnd()); + return _dlgReturn(m_hwnd, 1); + } + } + + if (((LPNMHDR)lParam)->idFrom == IDC_LOG && ((MSGFILTER *)lParam)->msg == WM_RBUTTONUP) { + CHARRANGE sel, all = { 0, -1 }; + + pt.x = LOWORD(((ENLINK*)lParam)->lParam), pt.y = HIWORD(((ENLINK*)lParam)->lParam); + ClientToScreen(((LPNMHDR)lParam)->hwndFrom, &pt); + + // fixing stuff for searches + wchar_t *pszWord = (wchar_t*)_alloca(8192); + pszWord[0] = '\0'; + POINTL ptl = { pt.x, pt.y }; + ScreenToClient(m_log.GetHwnd(), (LPPOINT)&ptl); + int iCharIndex = m_log.SendMsg(EM_CHARFROMPOS, 0, (LPARAM)&ptl); + if (iCharIndex < 0) + break; + + int start = m_log.SendMsg(EM_FINDWORDBREAK, WB_LEFT, iCharIndex); + int end = m_log.SendMsg(EM_FINDWORDBREAK, WB_RIGHT, iCharIndex); + + if (end - start > 0) { + static char szTrimString[] = ":;,.!?\'\"><()[]- \r\n"; + + CHARRANGE cr; + cr.cpMin = start; + cr.cpMax = end; + + TEXTRANGE tr = { 0 }; + tr.chrg = cr; + tr.lpstrText = (wchar_t*)pszWord; + int iRes = m_log.SendMsg(EM_GETTEXTRANGE, 0, (LPARAM)&tr); + + if (iRes > 0) { + size_t iLen = mir_wstrlen(pszWord) - 1; + while (strchr(szTrimString, pszWord[iLen])) { + pszWord[iLen] = '\0'; + iLen--; + } + } + } + + HMENU hMenu = 0; + UINT uID = CreateGCMenu(m_hwnd, &hMenu, 1, pt, si, NULL, pszWord); + switch (uID) { + case 0: + PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); + break; + + case ID_COPYALL: + SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_EXGETSEL, 0, (LPARAM)&sel); + SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM)&all); + SendMessage(((LPNMHDR)lParam)->hwndFrom, WM_COPY, 0, 0); + SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM)&sel); + PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); + break; + + case ID_CLEARLOG: + ClearLog(); + break; + + case ID_SEARCH_GOOGLE: + if (pszWord[0]) + Utils_OpenUrlW(CMStringW(FORMAT, L"http://www.google.com/search?q=%s", pszWord)); + + PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); + break; + + case ID_SEARCH_WIKIPEDIA: + if (pszWord[0]) + Utils_OpenUrlW(CMStringW(FORMAT, L"http://en.wikipedia.org/wiki/%s", pszWord)); + + PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); + break; + + default: + PostMessage(m_hwnd, WM_MOUSEACTIVATE, 0, 0); + pci->DoEventHookAsync(m_hwnd, si->ptszID, si->pszModule, GC_USER_LOGMENU, NULL, NULL, (LPARAM)uID); + break; + } + + DestroyGCMenu(&hMenu, 5); + } + } + break; + + case EN_REQUESTRESIZE: + if (((LPNMHDR)lParam)->idFrom == IDC_MESSAGE) + DM_HandleAutoSizeRequest((REQRESIZE *)lParam); + break; + + case EN_LINK: + if (((LPNMHDR)lParam)->idFrom == IDC_LOG) { + switch (((ENLINK*)lParam)->msg) { + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + case WM_LBUTTONDBLCLK: + CHARRANGE sel; + SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin == sel.cpMax) { + UINT msg = ((ENLINK*)lParam)->msg; + m_pContainer->MenuBar->Cancel(); + + TEXTRANGE tr; + tr.lpstrText = NULL; + tr.chrg = ((ENLINK*)lParam)->chrg; + tr.lpstrText = (wchar_t*)mir_alloc(sizeof(wchar_t) * (tr.chrg.cpMax - tr.chrg.cpMin + 2)); + SendMessage(((LPNMHDR)lParam)->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&tr); + + BOOL isLink = IsStringValidLink(tr.lpstrText); + if (isLink) // handled by core + break; + + // clicked a nick name + if (g_Settings.bClickableNicks) { + if (msg == WM_RBUTTONDOWN) { + HMENU hMenu = 0; + USERINFO uiNew; + for (USERINFO *ui = si->pUsers; ui; ui = ui->next) { + if (mir_wstrcmp(ui->pszNick, tr.lpstrText)) + continue; + + pt.x = (short)LOWORD(((ENLINK*)lParam)->lParam); + pt.y = (short)HIWORD(((ENLINK*)lParam)->lParam); + ClientToScreen(((NMHDR*)lParam)->hwndFrom, &pt); + memcpy(&uiNew, ui, sizeof(USERINFO)); + UINT uID = CreateGCMenu(m_hwnd, &hMenu, 0, pt, si, uiNew.pszUID, uiNew.pszNick); + switch (uID) { + case 0: + break; + + case ID_MESS: + pci->DoEventHookAsync(m_hwnd, si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui, NULL, 0); + break; + + default: + pci->DoEventHookAsync(m_hwnd, si->ptszID, si->pszModule, GC_USER_NICKLISTMENU, ui, NULL, (LPARAM)uID); + break; + } + DestroyGCMenu(&hMenu, 1); + return TRUE; + } + return TRUE; + } + + if (msg == WM_LBUTTONUP) { + CHARRANGE chr; + m_message.SendMsg(EM_EXGETSEL, 0, (LPARAM)&chr); + + wchar_t tszAplTmpl[] = L"%s:"; + size_t bufSize = mir_wstrlen(tr.lpstrText) + mir_wstrlen(tszAplTmpl) + 3; + wchar_t *tszTmp = (wchar_t*)mir_alloc(bufSize * sizeof(wchar_t)), *tszAppeal = tszTmp; + + TEXTRANGE tr2; + tr2.lpstrText = (LPTSTR)mir_alloc(sizeof(wchar_t) * 2); + if (chr.cpMin) { + // prepend nick with space if needed + tr2.chrg.cpMin = chr.cpMin - 1; + tr2.chrg.cpMax = chr.cpMin; + m_message.SendMsg(EM_GETTEXTRANGE, 0, (LPARAM)&tr2); + if (!iswspace(*tr2.lpstrText)) + *tszTmp++ = ' '; + mir_wstrcpy(tszTmp, tr.lpstrText); + } + else // in the beginning of the message window + mir_snwprintf(tszAppeal, bufSize, tszAplTmpl, tr.lpstrText); + + size_t st = mir_wstrlen(tszAppeal); + if (chr.cpMax != -1) { + tr2.chrg.cpMin = chr.cpMax; + tr2.chrg.cpMax = chr.cpMax + 1; + // if there is no space after selection, + // or there is nothing after selection at all... + if (!m_message.SendMsg(EM_GETTEXTRANGE, 0, (LPARAM)&tr2) || !iswspace(*tr2.lpstrText)) { + tszAppeal[st++] = ' '; + tszAppeal[st++] = '\0'; + } + } + else { + tszAppeal[st++] = ' '; + tszAppeal[st++] = '\0'; + } + m_message.SendMsg(EM_REPLACESEL, FALSE, (LPARAM)tszAppeal); + mir_free((void*)tr2.lpstrText); + mir_free((void*)tszAppeal); + } + } + SetFocus(m_message.GetHwnd()); + mir_free(tr.lpstrText); + return TRUE; + } + } + break; + } + break; + } + break; + + case WM_LBUTTONDOWN: + GetCursorPos(&tmp); + if (!m_pPanel.isHovered()) { + cur.x = (SHORT)tmp.x; + cur.y = (SHORT)tmp.y; + SendMessage(m_pContainer->hwnd, WM_NCLBUTTONDOWN, HTCAPTION, *((LPARAM*)(&cur))); + } + break; + + case WM_LBUTTONUP: + GetCursorPos(&tmp); + if (m_pPanel.isHovered()) + m_pPanel.handleClick(tmp); + else { + cur.x = (SHORT)tmp.x; + cur.y = (SHORT)tmp.y; + SendMessage(m_pContainer->hwnd, WM_NCLBUTTONUP, HTCAPTION, *((LPARAM*)(&cur))); + } + break; + + case WM_MOUSEMOVE: + GetCursorPos(&pt); + DM_DismissTip(pt); + m_pPanel.trackMouse(pt); + break; + + case WM_APPCOMMAND: + { + DWORD cmd = GET_APPCOMMAND_LPARAM(lParam); + if (cmd == APPCOMMAND_BROWSER_BACKWARD || cmd == APPCOMMAND_BROWSER_FORWARD) { + SendMessage(m_pContainer->hwnd, DM_SELECTTAB, cmd == APPCOMMAND_BROWSER_BACKWARD ? DM_SELECT_PREV : DM_SELECT_NEXT, 0); + return 1; + } + } + break; + + case WM_COMMAND: + if (LOWORD(wParam) >= MIN_CBUTTONID && LOWORD(wParam) <= MAX_CBUTTONID){ + Srmm_ClickToolbarIcon(m_hContact, LOWORD(wParam), GetDlgItem(m_hwnd, LOWORD(wParam)), 0); + break; + } + + switch (LOWORD(wParam)) { + case IDC_TOGGLESIDEBAR: + SendMessage(m_pContainer->hwnd, WM_COMMAND, IDC_TOGGLESIDEBAR, 0); + break; + + case IDCANCEL: + ShowWindow(m_pContainer->hwnd, SW_MINIMIZE); + return FALSE; + + case IDC_CLOSE: + SendMessage(m_hwnd, WM_CLOSE, 0, 1); + break; + + case IDC_SELFTYPING: + // Typing support for GCW_PRIVMESS sessions + if (si->iType == GCW_PRIVMESS) { + if (m_hContact) { + int iCurrentTypingMode = db_get_b(m_hContact, SRMSGMOD, SRMSGSET_TYPING, M.GetByte(SRMSGMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW)); + + if (m_nTypeMode == PROTOTYPE_SELFTYPING_ON && iCurrentTypingMode) { + DM_NotifyTyping(PROTOTYPE_SELFTYPING_OFF); + m_nTypeMode = PROTOTYPE_SELFTYPING_OFF; + } + db_set_b(m_hContact, SRMSGMOD, SRMSGSET_TYPING, (BYTE)!iCurrentTypingMode); + } + } + break; + } + break; + + case WM_KEYDOWN: + SetFocus(m_message.GetHwnd()); + break; + + case WM_ERASEBKGND: + RECT rcClient, rcWindow; + { + HDC hdc = (HDC)wParam; + UINT item_ids[3] = { ID_EXTBKUSERLIST, ID_EXTBKHISTORY, ID_EXTBKINPUTAREA }; + UINT ctl_ids[3] = { IDC_LIST, IDC_LOG, IDC_MESSAGE }; + HANDLE hbp = 0; + HDC hdcMem = 0; + HBITMAP hbm, hbmOld; + + GetClientRect(m_hwnd, &rcClient); + LONG cx = rcClient.right - rcClient.left; + LONG cy = rcClient.bottom - rcClient.top; + + if (CMimAPI::m_haveBufferedPaint) { + hbp = CSkin::InitiateBufferedPaint(hdc, rcClient, hdcMem); + hbm = hbmOld = 0; + } + else { + hdcMem = CreateCompatibleDC(hdc); + hbm = CSkin::CreateAeroCompatibleBitmap(rcClient, hdc); + hbmOld = (HBITMAP)SelectObject(hdcMem, hbm); + } + + if (CSkin::m_skinEnabled && !M.isAero()) { + CSkin::SkinDrawBG(m_hwnd, m_pContainer->hwnd, m_pContainer, &rcClient, hdcMem); + for (int i = 0; i < 3; i++) { + CSkinItem *item = &SkinItems[item_ids[i]]; + if (!item->IGNORED) { + GetWindowRect(GetDlgItem(m_hwnd, ctl_ids[i]), &rcWindow); + pt.x = rcWindow.left; + pt.y = rcWindow.top; + ScreenToClient(m_hwnd, &pt); + rc.left = pt.x - item->MARGIN_LEFT; + rc.top = pt.y - item->MARGIN_TOP; + rc.right = rc.left + item->MARGIN_RIGHT + (rcWindow.right - rcWindow.left) + item->MARGIN_LEFT; + rc.bottom = rc.top + item->MARGIN_BOTTOM + (rcWindow.bottom - rcWindow.top) + item->MARGIN_TOP; + CSkin::DrawItem(hdcMem, &rc, item); + } + } + } + else { + CSkin::FillBack(hdcMem, &rcClient); + + if (M.isAero()) { + LONG temp = rcClient.bottom; + rcClient.bottom = m_pPanel.isActive() ? m_pPanel.getHeight() + 5 : 5; + FillRect(hdcMem, &rcClient, (HBRUSH)GetStockObject(BLACK_BRUSH)); + rcClient.bottom = temp; + } + } + + GetClientRect(m_hwnd, &rc); + m_pPanel.renderBG(hdcMem, rc, &SkinItems[ID_EXTBKINFOPANELBG], M.isAero()); + m_pPanel.renderContent(hdcMem); + + if (!CSkin::m_skinEnabled) + RenderToolbarBG(hdcMem, rcClient); + + if (hbp) + CSkin::FinalizeBufferedPaint(hbp, &rcClient); + else { + BitBlt(hdc, 0, 0, cx, cy, hdcMem, 0, 0, SRCCOPY); + SelectObject(hdcMem, hbmOld); + DeleteObject(hbm); + DeleteDC(hdcMem); + } + if (!m_fLimitedUpdate) + SetAeroMargins(m_pContainer); + } + return TRUE; + + case WM_NCPAINT: + if (CSkin::m_skinEnabled) + return 0; + break; + + case WM_PAINT: + PAINTSTRUCT ps; + BeginPaint(m_hwnd, &ps); + EndPaint(m_hwnd, &ps); + return 0; + + case WM_RBUTTONUP: + GetCursorPos(&pt); + if (!m_pPanel.invokeConfigDialog(pt)) { + HMENU subMenu = GetSubMenu(PluginConfig.g_hMenuContext, 0); + + MsgWindowUpdateMenu(subMenu, MENU_TABCONTEXT); + + int iSelection = TrackPopupMenu(subMenu, TPM_RETURNCMD, pt.x, pt.y, 0, m_hwnd, NULL); + if (iSelection >= IDM_CONTAINERMENU) { + char szIndex[10]; + _itoa_s(iSelection - IDM_CONTAINERMENU, szIndex, 10); + ptrW wszContainer(db_get_wsa(NULL, "TAB_ContainersW", szIndex)); + if (wszContainer != nullptr) + SendMessage(m_hwnd, DM_CONTAINERSELECTED, 0, wszContainer); + break; + } + MsgWindowMenuHandler(iSelection, MENU_TABCONTEXT); + } + break; + + case WM_LBUTTONDBLCLK: + if (LOWORD(lParam) < 30) + PostMessage(m_hwnd, GC_SCROLLTOBOTTOM, 0, 0); + break; + + case WM_CLOSE: + if (wParam == 0 && lParam == 0) { + if (PluginConfig.m_EscapeCloses == 1) { + SendMessage(m_pContainer->hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); + return TRUE; + } + if (PluginConfig.m_bHideOnClose && PluginConfig.m_EscapeCloses == 2) { + ShowWindow(m_pContainer->hwnd, SW_HIDE); + return TRUE; + } + _dlgReturn(m_hwnd, TRUE); + } + SendMessage(m_hwnd, GC_CLOSEWINDOW, 0, 1); + return 0; + + case GC_CLOSEWINDOW: + { + bool bForced = (lParam == 2); + + int iTabs = TabCtrl_GetItemCount(m_hwndParent); + if (iTabs == 1 && CMimAPI::m_shutDown == 0) { + SendMessage(m_pContainer->hwnd, WM_CLOSE, 0, 1); + return 1; + } + + m_pContainer->iChilds--; + int i = GetTabIndexFromHWND(m_hwndParent, m_hwnd); + + // after closing a tab, we need to activate the tab to the left side of + // the previously open tab. + // normally, this tab has the same index after the deletion of the formerly active tab + // unless, of course, we closed the last (rightmost) tab. + if (!m_pContainer->bDontSmartClose && iTabs > 1 && !bForced) { + if (i == iTabs - 1) + i--; + else + i++; + TabCtrl_SetCurSel(m_hwndParent, i); + + TCITEM item = {}; + item.mask = TCIF_PARAM; + TabCtrl_GetItem(m_hwndParent, i, &item); // retrieve dialog hwnd for the now active tab... + m_pContainer->hwndActive = (HWND)item.lParam; + + SendMessage(m_pContainer->hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)&rc); + SetWindowPos(m_pContainer->hwndActive, HWND_TOP, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), SWP_SHOWWINDOW); + ShowWindow((HWND)item.lParam, SW_SHOW); + SetForegroundWindow(m_pContainer->hwndActive); + SetFocus(m_pContainer->hwndActive); + SendMessage(m_pContainer->hwnd, WM_SIZE, 0, 0); + } + + if (iTabs == 1) + SendMessage(m_pContainer->hwnd, WM_CLOSE, 0, 1); + else { + PostMessage(m_pContainer->hwnd, WM_SIZE, 0, 0); + DestroyWindow(m_hwnd); + } + } + return 0; + + case DM_SAVESIZE: + if (m_dwFlags & MWF_NEEDCHECKSIZE) + lParam = 0; + + m_dwFlags &= ~MWF_NEEDCHECKSIZE; + if (m_dwFlags & MWF_WASBACKGROUNDCREATE) + m_dwFlags &= ~MWF_INITMODE; + + SendMessage(m_pContainer->hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)&rcClient); + MoveWindow(m_hwnd, rcClient.left, rcClient.top, (rcClient.right - rcClient.left), (rcClient.bottom - rcClient.top), TRUE); + + if (m_dwFlags & MWF_WASBACKGROUNDCREATE) { + m_dwFlags &= ~MWF_WASBACKGROUNDCREATE; + SendMessage(m_hwnd, WM_SIZE, 0, 0); + + pt.x = pt.y = 0; + m_log.SendMsg(EM_SETSCROLLPOS, 0, (LPARAM)&pt); + if (PluginConfig.m_bAutoLocaleSupport) { + if (hkl == 0) + DM_LoadLocale(); + else + PostMessage(m_hwnd, DM_SETLOCALE, 0, 0); + } + } + else { + SendMessage(m_hwnd, WM_SIZE, 0, 0); + if (lParam == 0) + PostMessage(m_hwnd, GC_SCROLLTOBOTTOM, 1, 1); + } + return 0; + + case DM_REFRESHTABINDEX: + m_iTabID = GetTabIndexFromHWND(m_hwndParent, m_hwnd); + return 0; + + case WM_CBD_UPDATED: + if (lParam) + CB_ChangeButton((CustomButtonData*)lParam); + else + BB_InitDlgButtons(); + + BB_SetButtonsPos(); + return 0; + + case WM_CBD_REMOVED: + if (lParam) + CB_DestroyButton((DWORD)wParam, (DWORD)lParam); + else + CB_DestroyAllButtons(); + break; + + case DM_CONFIGURETOOLBAR: + SendMessage(m_hwnd, WM_SIZE, 0, 0); + break; + + case DM_SMILEYOPTIONSCHANGED: + SendMessage(m_hwnd, GC_REDRAWLOG, 0, 1); + break; + + case EM_THEMECHANGED: + DM_FreeTheme(); + DM_ThemeChanged(); + return 0; + + case WM_DWMCOMPOSITIONCHANGED: + BB_RefreshTheme(); + memset(&m_pContainer->mOld, -1000, sizeof(MARGINS)); + CProxyWindow::verify(this); + break; + } + return CTabBaseDlg::DlgProc(uMsg, wParam, lParam); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// chat session creator + +void ShowRoom(SESSION_INFO *si) +{ + if (si == nullptr) + return; + + if (si->hWnd != nullptr) { + ActivateExistingTab(si->dat->m_pContainer, si->hWnd); + return; + } + + wchar_t szName[CONTAINER_NAMELEN + 2]; szName[0] = 0; + TContainerData *pContainer = nullptr; + if (si->dat != nullptr) + pContainer = si->dat->m_pContainer; + if (pContainer == nullptr) { + GetContainerNameForContact(si->hContact, szName, CONTAINER_NAMELEN); + if (!g_Settings.bOpenInDefault && !mir_wstrcmp(szName, L"default")) + wcsncpy(szName, L"Chat Rooms", CONTAINER_NAMELEN); + szName[CONTAINER_NAMELEN] = 0; + pContainer = FindContainerByName(szName); + } + if (pContainer == nullptr) + pContainer = CreateContainer(szName, FALSE, si->hContact); + if (pContainer == nullptr) + return; // smth went wrong, nothing to do here + + MCONTACT hContact = si->hContact; + if (M.FindWindow(hContact) != 0) + return; + + if (hContact != 0 && M.GetByte("limittabs", 0) && !wcsncmp(pContainer->szName, L"default", 6)) { + if ((pContainer = FindMatchingContainer(L"default")) == NULL) { + wchar_t szName[CONTAINER_NAMELEN + 1]; + mir_snwprintf(szName, L"default"); + if ((pContainer = CreateContainer(szName, CNT_CREATEFLAG_CLONED, hContact)) == NULL) + return; + } + } + + wchar_t *contactName = pcli->pfnGetContactDisplayName(hContact, 0); + + // cut nickname if larger than x chars... + wchar_t newcontactname[128]; + if (mir_wstrlen(contactName) > 0) { + if (M.GetByte("cuttitle", 0)) + CutContactName(contactName, newcontactname, _countof(newcontactname)); + else + wcsncpy_s(newcontactname, contactName, _TRUNCATE); + } + else wcsncpy_s(newcontactname, L"_U_", _TRUNCATE); + + HWND hwndTab = GetDlgItem(pContainer->hwnd, IDC_MSGTABS); + + // hide the active tab + if (pContainer->hwndActive) + ShowWindow(pContainer->hwndActive, SW_HIDE); + + int iTabIndex_wanted = M.GetDword(hContact, "tabindex", pContainer->iChilds * 100); + int iCount = TabCtrl_GetItemCount(hwndTab); + + pContainer->iTabIndex = iCount; + if (iCount > 0) { + TCITEM item = {}; + for (int i = iCount - 1; i >= 0; i--) { + item.mask = TCIF_PARAM; + TabCtrl_GetItem(hwndTab, i, &item); + HWND hwnd = (HWND)item.lParam; + CSrmmWindow *dat = (CSrmmWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + if (dat) { + int relPos = M.GetDword(dat->m_hContact, "tabindex", i * 100); + if (iTabIndex_wanted <= relPos) + pContainer->iTabIndex = i; + } + } + } + + TCITEM item = {}; + item.pszText = newcontactname; + item.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM; + int iTabId = TabCtrl_InsertItem(hwndTab, pContainer->iTabIndex, &item); + + SendMessage(hwndTab, EM_REFRESHWITHOUTCLIP, 0, 0); + TabCtrl_SetCurSel(hwndTab, iTabId); + pContainer->iChilds++; + + CChatRoomDlg *pDlg = new CChatRoomDlg(si); + pDlg->m_iTabID = iTabId; + pDlg->m_pContainer = pContainer; + pDlg->SetParent(hwndTab); + pDlg->Create(); + + HWND hwndNew = pDlg->GetHwnd(); + item.lParam = (LPARAM)hwndNew; + TabCtrl_SetItem(hwndTab, iTabId, &item); + + if (pContainer->dwFlags & CNT_SIDEBAR) + pContainer->SideBar->addSession(pDlg, pContainer->iTabIndex); + + SendMessage(pContainer->hwnd, WM_SIZE, 0, 0); + // if the container is minimized, then pop it up... + if (IsIconic(pContainer->hwnd)) { + SendMessage(pContainer->hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); + SetFocus(pContainer->hwndActive); + } + + if (PluginConfig.m_bHideOnClose && !IsWindowVisible(pContainer->hwnd)) { + WINDOWPLACEMENT wp = { 0 }; + wp.length = sizeof(wp); + GetWindowPlacement(pContainer->hwnd, &wp); + + BroadCastContainer(pContainer, DM_CHECKSIZE, 0, 0); // make sure all tabs will re-check layout on activation + if (wp.showCmd == SW_SHOWMAXIMIZED) + ShowWindow(pContainer->hwnd, SW_SHOWMAXIMIZED); + else { + ShowWindow(pContainer->hwnd, SW_SHOWNORMAL); + } + SendMessage(pContainer->hwndActive, WM_SIZE, 0, 0); + SetFocus(hwndNew); + } + else { + SetFocus(hwndNew); + RedrawWindow(pContainer->hwnd, NULL, NULL, RDW_INVALIDATE); + UpdateWindow(pContainer->hwnd); + if (GetForegroundWindow() != pContainer->hwnd) + SetForegroundWindow(pContainer->hwnd); + } + + if (PluginConfig.m_bIsWin7 && PluginConfig.m_useAeroPeek && CSkin::m_skinEnabled && !M.GetByte("forceAeroPeek", 0)) + CWarning::show(CWarning::WARN_AEROPEEK_SKIN, MB_ICONWARNING | MB_OK); +} diff --git a/plugins/TabSRMM/src/muchighlight.cpp b/plugins/TabSRMM/src/muchighlight.cpp new file mode 100644 index 0000000000..167fb5a9e5 --- /dev/null +++ b/plugins/TabSRMM/src/muchighlight.cpp @@ -0,0 +1,336 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Miranda NG: the free IM client for Microsoft* Windows* +// +// Copyright (ñ) 2012-17 Miranda NG project, +// Copyright (c) 2000-09 Miranda ICQ/IM project, +// all portions of this codebase are copyrighted to the people +// listed in contributors.txt. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// you should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// part of tabSRMM messaging plugin for Miranda. +// +// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors +// +// highlighter class for multi user chats + +#include "stdafx.h" + +void CMUCHighlight::cleanup() +{ + mir_free(m_NickPatternString); + mir_free(m_TextPatternString); + m_TextPatternString = m_NickPatternString = 0; + + mir_free(m_NickPatterns); + mir_free(m_TextPatterns); + m_iNickPatterns = m_iTextPatterns = 0; + m_NickPatterns = m_TextPatterns = 0; +} + +void CMUCHighlight::init() +{ + DBVARIANT dbv = { 0 }; + + if (m_fInitialized) + cleanup(); // clean up first, if we were already initialized + + m_fInitialized = true; + + if (0 == db_get_ws(0, CHAT_MODULE, "HighlightWords", &dbv)) { + m_TextPatternString = dbv.ptszVal; + _wsetlocale(LC_ALL, L""); + wcslwr(m_TextPatternString); + } + + if (0 == db_get_ws(0, CHAT_MODULE, "HighlightNames", &dbv)) + m_NickPatternString = dbv.ptszVal; + + m_dwFlags = M.GetByte(CHAT_MODULE, "HighlightEnabled", MATCH_TEXT); + m_fHighlightMe = (M.GetByte(CHAT_MODULE, "HighlightMe", 1) ? true : false); + + tokenize(m_TextPatternString, m_TextPatterns, m_iTextPatterns); + tokenize(m_NickPatternString, m_NickPatterns, m_iNickPatterns); +} + +void CMUCHighlight::tokenize(wchar_t *tszString, wchar_t**& patterns, UINT& nr) +{ + if (tszString == 0) + return; + + wchar_t *p = tszString; + + if (*p == 0) + return; + + nr = 0; + + if (*p != ' ') + nr++; + + while (*p) { + if (*p == ' ') { + p++; + while (*p && iswspace(*p)) + p++; + if (*p) + nr++; + } + p++; + } + patterns = (wchar_t **)mir_alloc(nr * sizeof(wchar_t*)); + + p = tszString; + nr = 0; + + if (*p != ' ') + patterns[nr++] = p; + + while (*p) { + if (*p == ' ') { + *p++ = 0; + while (*p && iswspace(*p)) + p++; + if (*p) + patterns[nr++] = p; + } + p++; + } +} + +bool CMUCHighlight::match(const GCEVENT *pgce, const SESSION_INFO *psi, DWORD dwFlags) +{ + int result = 0, nResult = 0; + + if (pgce == 0 || m_Valid == false) + return false; + + if ((m_dwFlags & MATCH_TEXT) && (dwFlags & MATCH_TEXT) && (m_fHighlightMe || m_iTextPatterns > 0) && psi != 0) { + wchar_t *p = pci->RemoveFormatting(pgce->ptszText); + p = NEWWSTR_ALLOCA(p); + if (p == NULL) + return false; + CharLower(p); + + wchar_t *tszMe = ((psi && psi->pMe) ? NEWWSTR_ALLOCA(psi->pMe->pszNick) : 0); + if (tszMe) + CharLower(tszMe); + + if (m_fHighlightMe && tszMe) { + result = wcsstr(p, tszMe) ? MATCH_TEXT : 0; + if (0 == m_iTextPatterns) + goto skip_textpatterns; + } + + while (p && !result) { + while (*p && (*p == ' ' || *p == ',' || *p == '.' || *p == ':' || *p == ';' || *p == '?' || *p == '!')) + p++; + + if (*p == 0) + break; + + wchar_t *p1 = p; + while (*p1 && *p1 != ' ' && *p1 != ',' && *p1 != '.' && *p1 != ':' && *p1 != ';' && *p1 != '?' && *p1 != '!') + p1++; + + if (*p1) + *p1 = 0; + else + p1 = 0; + + for (UINT i = 0; i < m_iTextPatterns && !result; i++) + result = wildcmpw(p, m_TextPatterns[i]) ? MATCH_TEXT : 0; + + if (p1) { + *p1 = ' '; + p = p1 + 1; + } + else p = 0; + } + } + +skip_textpatterns: + + // optionally, match the nickname against the list of nicks to highlight + if ((m_dwFlags & MATCH_NICKNAME) && (dwFlags & MATCH_NICKNAME) && pgce->ptszNick && m_iNickPatterns > 0) { + for (UINT i = 0; i < m_iNickPatterns && !nResult; i++) { + if (pgce->ptszNick) + nResult = wildcmpw(pgce->ptszNick, m_NickPatterns[i]) ? MATCH_NICKNAME : 0; + if ((m_dwFlags & MATCH_UIN) && pgce->ptszUserInfo) + nResult = wildcmpw(pgce->ptszUserInfo, m_NickPatterns[i]) ? MATCH_NICKNAME : 0; + } + } + + return result || nResult; +} + +/** + * Dialog procedure to handle global highlight settings + * + * @param Standard Windows dialog procedure parameters + */ +INT_PTR CALLBACK CMUCHighlight::dlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + DBVARIANT dbv = { 0 }; + if (!db_get_ws(0, CHAT_MODULE, "HighlightWords", &dbv)) { + ::SetDlgItemText(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN, dbv.ptszVal); + ::db_free(&dbv); + } + + if (!db_get_ws(0, CHAT_MODULE, "HighlightNames", &dbv)) { + ::SetDlgItemText(hwndDlg, IDC_HIGHLIGHTNICKPATTERN, dbv.ptszVal); + ::db_free(&dbv); + } + + DWORD dwFlags = M.GetByte(CHAT_MODULE, "HighlightEnabled", MATCH_TEXT); + + ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTNICKENABLE, dwFlags & MATCH_NICKNAME ? BST_CHECKED : BST_UNCHECKED); + ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTNICKUID, dwFlags & MATCH_UIN ? BST_CHECKED : BST_UNCHECKED); + ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTTEXTENABLE, dwFlags & MATCH_TEXT ? BST_CHECKED : BST_UNCHECKED); + ::CheckDlgButton(hwndDlg, IDC_HIGHLIGHTME, M.GetByte(CHAT_MODULE, "HighlightMe", 1) ? BST_CHECKED : BST_UNCHECKED); + + ::SendMessage(hwndDlg, WM_USER + 100, 0, 0); + } + return TRUE; + + case WM_USER + 100: + Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN, + ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTTEXTENABLE) ? TRUE : FALSE); + + Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTNICKPATTERN, + ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKENABLE) ? TRUE : FALSE); + + Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTNICKUID, + ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKENABLE) ? TRUE : FALSE); + + Utils::enableDlgControl(hwndDlg, IDC_HIGHLIGHTME, + ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTTEXTENABLE) ? TRUE : FALSE); + return FALSE; + + case WM_COMMAND: + if ((LOWORD(wParam) == IDC_HIGHLIGHTNICKPATTERN + || LOWORD(wParam) == IDC_HIGHLIGHTTEXTPATTERN) + && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != ::GetFocus())) + return 0; + + ::SendMessage(hwndDlg, WM_USER + 100, 0, 0); + if (lParam != 0) + ::SendMessage(::GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_APPLY: + { + wchar_t* szBuf = 0; + int iLen = ::GetWindowTextLength(::GetDlgItem(hwndDlg, IDC_HIGHLIGHTNICKPATTERN)); + if (iLen) { + szBuf = reinterpret_cast(mir_alloc((iLen + 2) * sizeof(wchar_t))); + ::GetDlgItemText(hwndDlg, IDC_HIGHLIGHTNICKPATTERN, szBuf, iLen + 1); + db_set_ws(0, CHAT_MODULE, "HighlightNames", szBuf); + } + + iLen = ::GetWindowTextLength(::GetDlgItem(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN)); + if (iLen) { + szBuf = reinterpret_cast(mir_realloc(szBuf, sizeof(wchar_t) * (iLen + 2))); + ::GetDlgItemText(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN, szBuf, iLen + 1); + db_set_ws(0, CHAT_MODULE, "HighlightWords", szBuf); + } + else db_set_ws(0, CHAT_MODULE, "HighlightWords", L""); + + mir_free(szBuf); + BYTE dwFlags = (::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKENABLE) ? MATCH_NICKNAME : 0) | + (::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTTEXTENABLE) ? MATCH_TEXT : 0); + + if (dwFlags & MATCH_NICKNAME) + dwFlags |= (::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTNICKUID) ? MATCH_UIN : 0); + + db_set_b(0, CHAT_MODULE, "HighlightEnabled", dwFlags); + db_set_b(0, CHAT_MODULE, "HighlightMe", ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTME) ? 1 : 0); + g_Settings.Highlight->init(); + } + return TRUE; + } + } + break; + } + return FALSE; +} + +/** + * dialog procedure for the small "add user to highlight list" dialog box + * TODO: finish it + */ +INT_PTR CALLBACK CMUCHighlight::dlgProcAdd(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + { + HFONT hFont = (HFONT)::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTTITLE, WM_GETFONT, 0, 0); + + THighLightEdit *the = reinterpret_cast(lParam); + ::SetWindowLongPtr(hwndDlg, GWLP_USERDATA, the->uCmd); + + LOGFONT lf = { 0 }; + ::GetObject(hFont, sizeof(lf), &lf); + lf.lfWeight = FW_BOLD; + lf.lfHeight = (int)(lf.lfHeight * 1.2); + hFont = ::CreateFontIndirect(&lf); + + ::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTTITLE, WM_SETFONT, (WPARAM)hFont, FALSE); + if (the->uCmd == THighLightEdit::CMD_ADD) { + Utils::showDlgControl(hwndDlg, IDC_ADDHIGHLIGHTEDITLIST, SW_HIDE); + ::SetDlgItemText(hwndDlg, IDC_ADDHIGHLIGHTTITLE, TranslateT("Add user to highlight list")); + ::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTNAME, CB_INSERTSTRING, -1, (LPARAM)the->ui->pszNick); + if (mir_wstrcmp(the->ui->pszNick, the->ui->pszUID)) + ::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTNAME, CB_INSERTSTRING, -1, (LPARAM)the->ui->pszUID); + ::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTNAME, CB_SETCURSEL, 0, 0); + } + else { + Utils::showDlgControl(hwndDlg, IDC_ADDHIGHLIGHTNAME, SW_HIDE); + Utils::showDlgControl(hwndDlg, IDC_ADDHIGHLIGHTEXPLAIN, SW_HIDE); + ::SetDlgItemText(hwndDlg, IDC_ADDHIGHLIGHTTITLE, TranslateT("Edit user highlight list")); + } + } + break; + + case WM_CTLCOLOREDIT: + case WM_CTLCOLORSTATIC: + { + HWND hwndChild = (HWND)lParam; + if (hwndChild == ::GetDlgItem(hwndDlg, IDC_ADDHIGHLIGHTTITLE)) + ::SetTextColor((HDC)wParam, RGB(60, 60, 150)); + ::SetBkColor((HDC)wParam, ::GetSysColor(COLOR_WINDOW)); + return (INT_PTR)::GetSysColorBrush(COLOR_WINDOW); + } + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) + ::DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + HFONT hFont = (HFONT)::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTTITLE, WM_GETFONT, 0, 0); + ::DeleteObject(hFont); + break; + } + return FALSE; +} diff --git a/plugins/TabSRMM/src/muchighlight.h b/plugins/TabSRMM/src/muchighlight.h new file mode 100644 index 0000000000..9ca56c95d0 --- /dev/null +++ b/plugins/TabSRMM/src/muchighlight.h @@ -0,0 +1,87 @@ +///////////////////////////////////////////////////////////////////////////////////////// +// Miranda NG: the free IM client for Microsoft* Windows* +// +// Copyright (ñ) 2012-17 Miranda NG project, +// Copyright (c) 2000-09 Miranda ICQ/IM project, +// all portions of this codebase are copyrighted to the people +// listed in contributors.txt. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// you should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// part of tabSRMM messaging plugin for Miranda. +// +// (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors +// +// highlighter class for multi user chats + +class CMUCHighlight { + +public: + + enum { + MATCH_TEXT = 1, + MATCH_NICKNAME = 2, + MATCH_UIN = 4, + }; + + CMUCHighlight() + { + m_fInitialized = false; + m_TextPatternString = m_NickPatternString = 0; + m_NickPatterns = m_TextPatterns = 0; + m_iNickPatterns = m_iTextPatterns = 0; + m_dwFlags = 0; + m_Valid = true; + init(); + } + + ~CMUCHighlight() + { + cleanup(); + } + + void init(); + void cleanup(); + bool match(const GCEVENT *pgce, const SESSION_INFO *psi, DWORD dwFlags = MATCH_NICKNAME); + + static INT_PTR CALLBACK dlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); // option page dlg proc + static INT_PTR CALLBACK dlgProcAdd(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); // for the "add to" dialog + +private: + void tokenize(wchar_t *tszString, wchar_t**& patterns, UINT& nr); + + DWORD m_dwFlags; + bool m_fInitialized; + wchar_t** m_NickPatterns; + wchar_t** m_TextPatterns; + UINT m_iNickPatterns; + UINT m_iTextPatterns; + wchar_t *m_NickPatternString; + wchar_t *m_TextPatternString; + bool m_Valid; + bool m_fHighlightMe; +}; + +struct THighLightEdit +{ + enum { + CMD_ADD = 1, + CMD_EDIT = 2 + }; + + UINT uCmd; + SESSION_INFO *si; + USERINFO *ui; +}; diff --git a/plugins/TabSRMM/src/stdafx.h b/plugins/TabSRMM/src/stdafx.h index 74b9f2b7ea..14d2eb220f 100644 --- a/plugins/TabSRMM/src/stdafx.h +++ b/plugins/TabSRMM/src/stdafx.h @@ -120,7 +120,7 @@ typedef struct _DWM_THUMBNAIL_PROPERTIES #include "typingnotify.h" #include "nen.h" #include "functions.h" -#include "chat/chat.h" +#include "chat.h" #include "contactcache.h" #include "translator.h" #include "themes.h" @@ -133,7 +133,7 @@ typedef struct _DWM_THUMBNAIL_PROPERTIES #include "utils.h" #include "sendlater.h" #include "ImageDataObject.h" -#include "chat/muchighlight.h" +#include "muchighlight.h" /* diff --git a/plugins/TabSRMM/tabsrmm.vcxproj b/plugins/TabSRMM/tabsrmm.vcxproj index de20ecf765..76cba54dd6 100644 --- a/plugins/TabSRMM/tabsrmm.vcxproj +++ b/plugins/TabSRMM/tabsrmm.vcxproj @@ -30,12 +30,4 @@ Sync - - - ..\stdafx.h - - - - - \ No newline at end of file -- cgit v1.2.3