summaryrefslogtreecommitdiff
path: root/plugins/TabSRMM/src
diff options
context:
space:
mode:
authorKirill Volinsky <mataes2007@gmail.com>2012-10-14 13:35:25 +0000
committerKirill Volinsky <mataes2007@gmail.com>2012-10-14 13:35:25 +0000
commit50feaa0ffc1b2e120eb6b22b2970f5bc2f7dc7a4 (patch)
tree369eb024d7b0b851f0d34482c93a994fec80d728 /plugins/TabSRMM/src
parentab290eb57836929b5b87a796ac4dfa06292515c8 (diff)
TabSRMM: folders restructurization
git-svn-id: http://svn.miranda-ng.org/main/trunk@1923 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/TabSRMM/src')
-rw-r--r--plugins/TabSRMM/src/ImageDataObject.cpp2
-rw-r--r--plugins/TabSRMM/src/chat/chat.h369
-rw-r--r--plugins/TabSRMM/src/chat/chat_resource.h161
-rw-r--r--plugins/TabSRMM/src/chat/chatprototypes.h174
-rw-r--r--plugins/TabSRMM/src/chat/clist.cpp325
-rw-r--r--plugins/TabSRMM/src/chat/colorchooser.cpp281
-rw-r--r--plugins/TabSRMM/src/chat/log.cpp1340
-rw-r--r--plugins/TabSRMM/src/chat/main.cpp142
-rw-r--r--plugins/TabSRMM/src/chat/manager.cpp1544
-rw-r--r--plugins/TabSRMM/src/chat/message.cpp341
-rw-r--r--plugins/TabSRMM/src/chat/muchighlight.cpp427
-rw-r--r--plugins/TabSRMM/src/chat/muchighlight.h94
-rw-r--r--plugins/TabSRMM/src/chat/options.cpp1493
-rw-r--r--plugins/TabSRMM/src/chat/services.cpp882
-rw-r--r--plugins/TabSRMM/src/chat/tools.cpp1353
-rw-r--r--plugins/TabSRMM/src/chat/window.cpp3833
-rw-r--r--plugins/TabSRMM/src/commonheaders.h52
-rw-r--r--plugins/TabSRMM/src/include/ImageDataObject.h136
-rw-r--r--plugins/TabSRMM/src/include/buttonbar.h54
-rw-r--r--plugins/TabSRMM/src/include/contactcache.h167
-rw-r--r--plugins/TabSRMM/src/include/controls.h136
-rw-r--r--plugins/TabSRMM/src/include/functions.h199
-rw-r--r--plugins/TabSRMM/src/include/generic_msghandlers.h67
-rw-r--r--plugins/TabSRMM/src/include/globals.h245
-rw-r--r--plugins/TabSRMM/src/include/infopanel.h220
-rw-r--r--plugins/TabSRMM/src/include/m_cln_skinedit.h147
-rw-r--r--plugins/TabSRMM/src/include/mim.h301
-rw-r--r--plugins/TabSRMM/src/include/msgdlgutils.h103
-rw-r--r--plugins/TabSRMM/src/include/msgs.h1062
-rw-r--r--plugins/TabSRMM/src/include/nen.h169
-rw-r--r--plugins/TabSRMM/src/include/resource.h796
-rw-r--r--plugins/TabSRMM/src/include/sendlater.h155
-rw-r--r--plugins/TabSRMM/src/include/sendqueue.h123
-rw-r--r--plugins/TabSRMM/src/include/sidebar.h239
-rw-r--r--plugins/TabSRMM/src/include/taskbar.h197
-rw-r--r--plugins/TabSRMM/src/include/templates.h50
-rw-r--r--plugins/TabSRMM/src/include/themes.h415
-rw-r--r--plugins/TabSRMM/src/include/translator.h63
-rw-r--r--plugins/TabSRMM/src/include/typingnotify.h76
-rw-r--r--plugins/TabSRMM/src/include/utils.h268
-rw-r--r--plugins/TabSRMM/src/include/version.h15
-rw-r--r--plugins/TabSRMM/src/modplus.cpp276
-rw-r--r--plugins/TabSRMM/src/msgoptions_plus.cpp189
43 files changed, 18654 insertions, 27 deletions
diff --git a/plugins/TabSRMM/src/ImageDataObject.cpp b/plugins/TabSRMM/src/ImageDataObject.cpp
index 90fb804622..65e8e8d4dd 100644
--- a/plugins/TabSRMM/src/ImageDataObject.cpp
+++ b/plugins/TabSRMM/src/ImageDataObject.cpp
@@ -35,7 +35,7 @@
*/
#include "commonheaders.h"
-#include "../include/ImageDataObject.h"
+#include "include\ImageDataObject.h"
extern void ReleaseRichEditOle(IRichEditOle *ole)
{
diff --git a/plugins/TabSRMM/src/chat/chat.h b/plugins/TabSRMM/src/chat/chat.h
new file mode 100644
index 0000000000..97224cef53
--- /dev/null
+++ b/plugins/TabSRMM/src/chat/chat.h
@@ -0,0 +1,369 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda NG, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: chat.h 12272 2010-08-04 08:24:08Z silvercircle $
+ *
+ */
+
+#ifndef _CHAT_H_
+#define _CHAT_H_
+
+#pragma warning( disable : 4786 ) // limitation in MSVC's debugger.
+#pragma warning( disable : 4996 ) // limitation in MSVC's debugger.
+
+#define WIN32_LEAN_AND_MEAN
+
+#include "m_stdhdr.h"
+
+//defines
+#define OPTIONS_FONTCOUNT 20
+#define GC_UPDATETITLE (WM_USER+100)
+#define GC_CLOSEWINDOW (WM_USER+103)
+#define GC_GETITEMDATA (WM_USER+104)
+#define GC_SETITEMDATA (WM_USER+105)
+#define GC_UPDATESTATUSBAR (WM_USER+106)
+#define GC_SETVISIBILITY (WM_USER+107)
+#define GC_SETWNDPROPS (WM_USER+108)
+#define GC_REDRAWLOG (WM_USER+109)
+#define GC_FIREHOOK (WM_USER+110)
+#define GC_FILTERFIX (WM_USER+111)
+#define GC_CHANGEFILTERFLAG (WM_USER+112)
+#define GC_SHOWFILTERMENU (WM_USER+113)
+//#define GC_NICKLISTCLEAR (WM_USER+117)
+#define GC_REDRAWWINDOW (WM_USER+118)
+#define GC_SHOWCOLORCHOOSER (WM_USER+119)
+#define GC_ADDLOG (WM_USER+120)
+#define GC_ACKMESSAGE (WM_USER+121)
+//#define GC_ADDUSER (WM_USER+122)
+//#define GC_REMOVEUSER (WM_USER+123)
+//#define GC_NICKCHANGE (WM_USER+124)
+#define GC_UPDATENICKLIST (WM_USER+125)
+//#define GC_MODECHANGE (WM_USER+126)
+#define GC_SCROLLTOBOTTOM (WM_USER+129)
+#define GC_SESSIONNAMECHANGE (WM_USER+131)
+#define GC_SETMESSAGEHIGHLIGHT (WM_USER+139)
+#define GC_REDRAWLOG2 (WM_USER+140)
+#define GC_REDRAWLOG3 (WM_USER+141)
+
+#define EM_ACTIVATE (WM_USER+202)
+
+#define GC_EVENT_HIGHLIGHT 0x1000
+#define STATE_TALK 0x0001
+
+#define ICON_ACTION 0
+#define ICON_ADDSTATUS 1
+#define ICON_HIGHLIGHT 2
+#define ICON_INFO 3
+#define ICON_JOIN 4
+#define ICON_KICK 5
+#define ICON_MESSAGE 6
+#define ICON_MESSAGEOUT 7
+#define ICON_NICK 8
+#define ICON_NOTICE 9
+#define ICON_PART 10
+#define ICON_QUIT 11
+#define ICON_REMSTATUS 12
+#define ICON_TOPIC 13
+
+#define ICON_STATUS1 14
+#define ICON_STATUS2 15
+#define ICON_STATUS3 16
+#define ICON_STATUS4 17
+#define ICON_STATUS0 18
+#define ICON_STATUS5 19
+
+// special service for tweaking performance
+#define MS_GC_GETEVENTPTR "GChat/GetNewEventPtr"
+typedef INT_PTR (*GETEVENTFUNC)(WPARAM wParam, LPARAM lParam);
+typedef struct {
+ GETEVENTFUNC pfnAddEvent;
+}GCPTRS;
+
+class CMUCHighlight;
+
+//structs
+
+typedef struct MODULE_INFO_TYPE
+{
+ char* pszModule;
+ TCHAR* ptszModDispName;
+ char* pszHeader;
+ BOOL bBold;
+ BOOL bUnderline;
+ BOOL bItalics;
+ BOOL bColor;
+ BOOL bBkgColor;
+ BOOL bChanMgr;
+ BOOL bAckMsg;
+ int nColorCount;
+ COLORREF* crColors;
+ /*
+ HICON hOnlineIcon;
+ HICON hOfflineIcon;
+ HICON hOnlineTalkIcon;
+ HICON hOfflineTalkIcon;
+ int OnlineIconIndex;
+ int OfflineIconIndex;
+ */
+ int iMaxText;
+ DWORD idleTimeStamp;
+ DWORD lastIdleCheck;
+ TCHAR tszIdleMsg[60];
+ CMUCHighlight* Highlight;
+ struct MODULE_INFO_TYPE *next;
+}
+ MODULEINFO;
+
+typedef struct COMMAND_INFO_TYPE
+{
+ char* lpCommand;
+ struct COMMAND_INFO_TYPE *last, *next;
+}
+ COMMAND_INFO;
+
+typedef struct
+{
+ LOGFONT lf;
+ COLORREF color;
+}
+ FONTINFO;
+
+typedef struct LOG_INFO_TYPE
+{
+ TCHAR* ptszText;
+ TCHAR* ptszNick;
+ TCHAR* ptszUID;
+ TCHAR* ptszStatus;
+ TCHAR* ptszUserInfo;
+ BOOL bIsMe;
+ BOOL bIsHighlighted;
+ time_t time;
+ int iType;
+ DWORD dwFlags;
+ struct LOG_INFO_TYPE *next;
+ struct LOG_INFO_TYPE *prev;
+}
+ LOGINFO;
+
+typedef struct STATUSINFO_TYPE
+{
+ TCHAR* pszGroup;
+ HICON hIcon;
+ WORD Status;
+ struct STATUSINFO_TYPE *next;
+}
+ STATUSINFO;
+
+typedef struct USERINFO_TYPE
+{
+ TCHAR* pszNick;
+ TCHAR* pszUID;
+ WORD Status;
+ int iStatusEx;
+ WORD ContactStatus;
+ struct USERINFO_TYPE *next;
+}
+ USERINFO;
+
+typedef struct SESSIONINFO_TYPE
+{
+ HWND hWnd;
+
+ BOOL bFGSet;
+ BOOL bBGSet;
+ BOOL bFilterEnabled;
+ BOOL bNicklistEnabled;
+ BOOL bInitDone;
+
+ char* pszModule;
+ TCHAR* ptszID;
+ TCHAR* ptszName;
+ TCHAR* ptszStatusbarText;
+ TCHAR* ptszTopic;
+ TCHAR pszLogFileName[MAX_PATH + 50];
+
+ char* pszID; // ugly fix for returning static ANSI strings in GC_INFO
+ char* pszName; // just to fix a bug quickly, should die after porting IRC to Unicode
+
+ int iType;
+ int iFG;
+ int iBG;
+ int iSplitterY;
+ int iSplitterX;
+ int iLogFilterFlags;
+ int iLogPopupFlags;
+ int iLogTrayFlags;
+ int iDiskLogFlags;
+ int nUsersInNicklist;
+ int iEventCount;
+ int iStatusCount;
+
+ WORD wStatus;
+ WORD wState;
+ WORD wCommandsNum;
+ DWORD dwItemData;
+ DWORD dwFlags;
+ HANDLE hContact;
+ HWND hwndFilter;
+ time_t LastTime;
+ TCHAR szSearch[255];
+ int iSearchItem;
+ CMUCHighlight* Highlight;
+ COMMAND_INFO* lpCommands;
+ COMMAND_INFO* lpCurrentCommand;
+ LOGINFO* pLog;
+ LOGINFO* pLogEnd;
+ USERINFO* pUsers;
+ USERINFO* pMe;
+ STATUSINFO* pStatuses;
+ TContainerData *pContainer;
+ TWindowData *dat;
+ int wasTrimmed;
+ SESSIONINFO_TYPE* next;
+} SESSION_INFO;
+
+typedef struct
+{
+ char* buffer;
+ int bufferOffset, bufferLen;
+ HWND hwnd;
+ LOGINFO* lin;
+ BOOL bStripFormat;
+ BOOL bRedraw;
+ SESSION_INFO* si;
+ int crCount;
+ TWindowData* dat;
+}
+ LOGSTREAMDATA;
+
+struct TMUCSettings {
+ HICON hIconOverlay;
+ BOOL ShowTime;
+ BOOL ShowTimeIfChanged;
+ BOOL LoggingEnabled;
+ BOOL FlashWindow;
+ BOOL FlashWindowHightlight;
+ BOOL OpenInDefault;
+ BOOL HighlightEnabled;
+ BOOL LogIndentEnabled;
+ BOOL StripFormat;
+ BOOL BBCodeInPopups;
+ BOOL TrayIconInactiveOnly;
+ BOOL AddColonToAutoComplete;
+ BOOL LogLimitNames;
+ BOOL TimeStampEventColour;
+ DWORD dwIconFlags;
+ int LogTextIndent;
+ long LoggingLimit;
+ int iEventLimit;
+ int iEventLimitThreshold;
+ int iPopupStyle;
+ int iPopupTimeout;
+ int iSplitterX;
+ int iSplitterY;
+ TCHAR* pszTimeStamp;
+ TCHAR* pszTimeStampLog;
+ TCHAR* pszIncomingNick;
+ TCHAR* pszOutgoingNick;
+ TCHAR pszLogDir[MAX_PATH + 20];
+ LONG iNickListFontHeight;
+ HFONT UserListFont, UserListHeadingsFont;
+ HFONT NameFont;
+ COLORREF crUserListColor;
+ COLORREF crUserListBGColor;
+ COLORREF crUserListHeadingsColor;
+ COLORREF crPUTextColour;
+ COLORREF crPUBkgColour;
+ BYTE ClassicIndicators;
+ //MAD
+ BYTE LogClassicIndicators;
+ BYTE AlternativeSorting;
+ BYTE AnnoyingHighlight;
+ BYTE CreateWindowOnHighlight;
+ //MAD_
+ BYTE LogSymbols;
+ BYTE ClickableNicks;
+ BYTE ColorizeNicks;
+ BYTE ColorizeNicksInLog;
+ BYTE ScaleIcons;
+ BYTE UseDividers;
+ BYTE DividersUsePopupConfig;
+ BYTE MathMod;
+ COLORREF nickColors[8];
+ HBRUSH SelectionBGBrush;
+ BOOL DoubleClick4Privat;
+ BOOL ShowContactStatus;
+ BOOL ContactStatusFirst;
+ HANDLE hGroup;
+ CMUCHighlight* Highlight;
+};
+
+struct FLASH_PARAMS {
+ HANDLE hContact;
+ const char* sound;
+ int iEvent;
+ HICON hNotifyIcon;
+ BOOL bActiveTab, bHighlight, bInactive, bMustFlash, bMustAutoswitch;
+ HWND hWnd;
+};
+
+extern TMUCSettings g_Settings;
+
+typedef struct{
+ MODULEINFO* pModule;
+ int xPosition;
+ int yPosition;
+ HWND hWndTarget;
+ BOOL bForeground;
+ SESSION_INFO* si;
+} COLORCHOOSER;
+
+#pragma comment(lib,"comctl32.lib")
+
+//////////////////////////////////////////////////////////////////////////////////
+
+#include "chatprototypes.h"
+#include "chat_resource.h"
+
+#define mir_tstrdup mir_wstrdup
+
+TCHAR* a2t(const char* str);
+char* t2a(const TCHAR* str, DWORD codepage);
+TCHAR* a2tf(const TCHAR* str, int flags, DWORD cp = 0);
+TCHAR* replaceStr(TCHAR** dest, const TCHAR* src);
+char* replaceStrA(char** dest, const char* src);
+
+extern char *szChatIconString;
+
+#define DEFLOGFILENAME _T("%miranda_logpath%\\%proto%\\%userid%.log")
+
+#endif
diff --git a/plugins/TabSRMM/src/chat/chat_resource.h b/plugins/TabSRMM/src/chat/chat_resource.h
new file mode 100644
index 0000000000..07a9bb8ba4
--- /dev/null
+++ b/plugins/TabSRMM/src/chat/chat_resource.h
@@ -0,0 +1,161 @@
+//{{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_COLORCHOOSER 406
+#define IDD_OPTIONS3 407
+#define IDD_OPTIONS4 408
+#define IDD_ADDHIGHLIGHT 409
+#define IDC_CHAT_LOG 1005
+#define IDC_SPLITTERX 1006
+#define IDC_SMILEY 1007
+#define IDC_SPLITTERY 1008
+#define IDC_CHAT_MESSAGE 1009
+#define IDC_FILTER 1013
+#define IDC_CHANMGR 1014
+#define IDC_SHOWNICKLIST 1015
+#define IDC_BKGCOLOR 1019
+#define IDC_CHECKBOXES 1021
+#define IDC_NICKROW2 1023
+#define IDC_NICKROW 1024
+#define IDC_LOGLIMIT 1024
+#define IDC_CHAT_CLOSE 1025
+#define IDC_CHAT_SPIN1 1028
+#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_CHAT_RADIO1 1061
+#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_COLORTEXT 1070
+#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_STATIC_MESSAGE 1081
+#define IDC_STATIC110 1082
+#define IDC_STATIC112 1085
+#define IDC_TRAYONLYFORINACTIVE 1086
+#define IDC_NOPOPUPSFORCLOSEDWINDOWS 1087
+#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_CHAT_BOLD 1106
+#define IDC_ITALICS 1107
+#define IDC_CHAT_UNDERLINE 1108
+#define IDC_COLOR 1110
+#define IDC_CHAT_HISTORY 1111
+#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_CHAT_TOGGLESIDEBAR 1277
+#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/chatprototypes.h b/plugins/TabSRMM/src/chat/chatprototypes.h
new file mode 100644
index 0000000000..c304b38cec
--- /dev/null
+++ b/plugins/TabSRMM/src/chat/chatprototypes.h
@@ -0,0 +1,174 @@
+/*
+Chat module plugin for Miranda NG
+
+Copyright (C) 2003-2009 Joergen Persson and others
+
+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.
+
+$Id: chatprototypes.h 13184 2010-12-07 14:16:58Z silvercircle $
+
+*/
+
+void LoadIcons(void);
+void LoadLogIcons(void);
+void FreeIcons(void);
+void UpgradeCheck(void);
+
+//colorchooser.c
+INT_PTR CALLBACK DlgProcColorToolWindow(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+//log.c
+void Log_StreamInEvent(HWND hwndDlg, LOGINFO* lin, SESSION_INFO* si, BOOL bRedraw, BOOL bPhaseTwo);
+void LoadMsgLogBitmaps(void);
+void FreeMsgLogBitmaps(void);
+TCHAR* GetChatLogsFilename(SESSION_INFO *si, time_t tTime);
+TCHAR* MakeTimeStamp(TCHAR* pszStamp, time_t time);
+char* Log_CreateRtfHeader(MODULEINFO * mi);
+
+//window.c
+INT_PTR CALLBACK RoomWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
+int GetTextPixelSize( TCHAR* pszText, HFONT hFont, BOOL bWidth);
+
+//options.c
+enum { FONTSECTION_AUTO, FONTSECTION_CHAT, FONTSECTION_IM, FONTSECTION_IP };
+int OptionsInit(void);
+int OptionsUnInit(void);
+void LoadMsgDlgFont(int section, int i, LOGFONT * lf, COLORREF * colour, char* szMod );
+void LoadGlobalSettings(void);
+void AddIcons(void);
+HICON LoadIconEx(int iIndex, char * pszIcoLibName, int iX, int iY);
+
+//services.c
+void HookEvents(void);
+void UnhookEvents(void);
+int CreateServiceFunctions(void);
+void DestroyServiceFunctions(void);
+void DestroyHookableEvents(void);
+void CreateHookableEvents(void);
+void TabsInit(void);
+int ModulesLoaded(WPARAM wParam,LPARAM lParam);
+int SmileyOptionsChanged(WPARAM wParam,LPARAM lParam);
+int PreShutdown(WPARAM wParam,LPARAM lParam);
+int IconsChanged(WPARAM wParam,LPARAM lParam);
+void ShowRoom(SESSION_INFO* si, WPARAM wp, BOOL bSetForeground);
+INT_PTR Service_AddEvent(WPARAM wParam, LPARAM lParam);
+int Service_ItemData(WPARAM wParam, LPARAM lParam);
+int Service_SetSBText(WPARAM wParam, LPARAM lParam);
+int Service_SetVisibility(WPARAM wParam, LPARAM lParam);
+INT_PTR Service_GetCount(WPARAM wParam,LPARAM lParam);
+
+HWND CreateNewRoom(TContainerData *pContainer, SESSION_INFO *si, BOOL bActivateTab, BOOL bPopupContainer, BOOL bWantPopup);
+
+//manager.c
+void SetActiveSession(const TCHAR* pszID, const char* pszModule);
+void SetActiveSessionEx(SESSION_INFO* si);
+SESSION_INFO* GetActiveSession(void);
+SESSION_INFO* SM_AddSession(const TCHAR* pszID, const char* pszModule);
+int SM_RemoveSession(const TCHAR* pszID, const char* pszModule, bool removeContact);
+SESSION_INFO* SM_FindSession(const TCHAR* pszID, const char* pszModule);
+USERINFO* SM_AddUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszNick, WORD wStatus);
+SESSION_INFO* SM_FindSessionAutoComplete(const char* pszModule, SESSION_INFO* currSession, SESSION_INFO* prevSession, const TCHAR* pszOriginal, const TCHAR* pszCurrent);
+BOOL SM_ChangeUID(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszNewUID);
+BOOL SM_ChangeNick(const TCHAR* pszID, const char* pszModule, GCEVENT * gce);
+BOOL SM_RemoveUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID);
+BOOL SM_SetOffline(const TCHAR* pszID, const char* pszModule);
+HICON SM_GetStatusIcon(SESSION_INFO* si, USERINFO* ui, char* szIndicator);
+BOOL SM_SetStatus(const TCHAR* pszID, const char* pszModule, int wStatus);
+BOOL SM_SetStatusEx(const TCHAR* pszID, const char* pszModule, const TCHAR* pszText, int flags );
+BOOL SM_SendUserMessage(const TCHAR* pszID, const char* pszModule, const TCHAR* pszText);
+STATUSINFO* SM_AddStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszStatus);
+BOOL SM_AddEventToAllMatchingUID(GCEVENT * gce, BOOL bisHighLight = FALSE);
+BOOL SM_AddEvent(const TCHAR* pszID, const char* pszModule, GCEVENT * gce, BOOL bIsHighlighted);
+LRESULT SM_SendMessage(const TCHAR* pszID, const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam);
+BOOL SM_PostMessage(const TCHAR* pszID, const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam);
+BOOL SM_BroadcastMessage(const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam, BOOL bAsync);
+BOOL SM_RemoveAll (void);
+BOOL SM_GiveStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszStatus);
+BOOL SM_SetContactStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, WORD pszStatus);
+BOOL SM_TakeStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszStatus);
+BOOL SM_MoveUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID);
+void SM_AddCommand(const TCHAR* pszID, const char* pszModule, const char* lpNewCommand);
+char* SM_GetPrevCommand(const TCHAR* pszID, const char* pszModule);
+char* SM_GetNextCommand(const TCHAR* pszID, const char* pszModule);
+int SM_GetCount(const char* pszModule);
+SESSION_INFO* SM_FindSessionByHWND(HWND h);
+SESSION_INFO* SM_FindSessionByHCONTACT(HANDLE h);
+SESSION_INFO* SM_FindSessionByIndex(const char* pszModule, int iItem);
+char* SM_GetUsers(SESSION_INFO* si);
+USERINFO* SM_GetUserFromIndex(const TCHAR* pszID, const char* pszModule, int index);
+BOOL SM_ReconfigureFilters();
+BOOL SM_InvalidateLogDirectories();
+MODULEINFO* MM_AddModule(const char* pszModule);
+MODULEINFO* MM_FindModule(const char* pszModule);
+void MM_FixColors();
+void MM_FontsChanged(void);
+void MM_IconsChanged(void);
+BOOL MM_RemoveAll (void);
+BOOL TabM_AddTab(const TCHAR* pszID, const char* pszModule);
+BOOL TabM_RemoveAll (void);
+STATUSINFO* TM_AddStatus(STATUSINFO** ppStatusList, const TCHAR* pszStatus, int* iCount);
+STATUSINFO* TM_FindStatus(STATUSINFO* pStatusList, const TCHAR* pszStatus);
+WORD TM_StringToWord(STATUSINFO* pStatusList, const TCHAR* pszStatus);
+TCHAR* TM_WordToString(STATUSINFO* pStatusList, WORD Status);
+BOOL TM_RemoveAll (STATUSINFO** pStatusList);
+BOOL UM_SetStatusEx(USERINFO* pUserList,const TCHAR* pszText, int onlyMe );
+USERINFO* UM_AddUser(STATUSINFO* pStatusList, USERINFO** pUserList, const TCHAR* pszUID, const TCHAR* pszNick, WORD wStatus);
+USERINFO* UM_SortUser(USERINFO** ppUserList, const TCHAR* pszUID);
+USERINFO* UM_FindUser(USERINFO* pUserList, const TCHAR* pszUID);
+USERINFO* UM_FindUserFromIndex(USERINFO* pUserList, int index);
+USERINFO* UM_GiveStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status);
+USERINFO* UM_SetContactStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status);
+USERINFO* UM_TakeStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status);
+TCHAR* UM_FindUserAutoComplete(USERINFO* pUserList, const TCHAR* pszOriginal, const TCHAR* pszCurrent);
+BOOL UM_RemoveUser(USERINFO** pUserList, const TCHAR* pszUID);
+BOOL UM_RemoveAll (USERINFO** ppUserList);
+LOGINFO* LM_AddEvent(LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd);
+BOOL LM_TrimLog(LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd, int iCount);
+BOOL LM_RemoveAll (LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd);
+
+//clist.c
+HANDLE CList_AddRoom(const char* pszModule, const TCHAR* pszRoom, const TCHAR* pszDisplayName, int iType);
+BOOL CList_SetOffline(HANDLE hContact, BOOL bHide);
+BOOL CList_SetAllOffline(BOOL bHide, const char *pszModule);
+int CList_RoomDoubleclicked(WPARAM wParam,LPARAM lParam);
+INT_PTR CList_EventDoubleclicked(WPARAM wParam,LPARAM lParam);
+INT_PTR CList_JoinChat(WPARAM wParam, LPARAM lParam);
+INT_PTR CList_LeaveChat(WPARAM wParam, LPARAM lParam);
+int CList_PrebuildContactMenu(WPARAM wParam, LPARAM lParam);
+INT_PTR CList_PrebuildContactMenuSvc(WPARAM wParam, LPARAM lParam);
+void CList_CreateGroup(TCHAR* group);
+BOOL CList_AddEvent(HANDLE hContact, HICON Icon, HANDLE event, int type, const TCHAR* fmt, ... ) ;
+HANDLE CList_FindRoom (const char* pszModule, const TCHAR* pszRoom) ;
+int WCCmp(TCHAR* wild, TCHAR*string);
+
+//tools.c
+TCHAR* RemoveFormatting(const TCHAR* pszText, bool fLower = false, bool fStripCR = false, TCHAR* buf = 0, const size_t len = 0);
+BOOL DoSoundsFlashPopupTrayStuff(SESSION_INFO* si, GCEVENT * gce, BOOL bHighlight, int bManyFix);
+int Chat_GetColorIndex(const char* pszModule, COLORREF cr);
+void CheckColorsInModule(const char* pszModule);
+TCHAR* my_strstri(const TCHAR* s1, const TCHAR* s2) ;
+int GetRichTextLength(HWND hwnd);
+BOOL IsHighlighted(SESSION_INFO* si, const TCHAR* pszText);
+UINT CreateGCMenu(HWND hwndDlg, HMENU *hMenu, int iIndex, POINT pt, SESSION_INFO* si, TCHAR* pszUID, TCHAR* pszWordText);
+void DestroyGCMenu(HMENU *hMenu, int iIndex);
+BOOL DoEventHookAsync(HWND hwnd, const TCHAR* pszID, const char* pszModule, int iType, TCHAR* pszUID, TCHAR* pszText, DWORD dwItem);
+BOOL DoEventHook(const TCHAR* pszID, const char* pszModule, int iType, const TCHAR* pszUID, const TCHAR* pszText, DWORD dwItem);
+BOOL IsEventSupported(int eventType);
+BOOL LogToFile(SESSION_INFO* si, GCEVENT * gce);
+void Chat_SetFilters(SESSION_INFO *si);
+void TSAPI DoFlashAndSoundWorker(FLASH_PARAMS* p);
+// message.c
+char* Chat_Message_GetFromStream(HWND hwndDlg, SESSION_INFO* si);
+TCHAR* Chat_DoRtfToTags( char* pszRtfText, SESSION_INFO* si);
diff --git a/plugins/TabSRMM/src/chat/clist.cpp b/plugins/TabSRMM/src/chat/clist.cpp
new file mode 100644
index 0000000000..8e095e1585
--- /dev/null
+++ b/plugins/TabSRMM/src/chat/clist.cpp
@@ -0,0 +1,325 @@
+/*
+astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ --pad=oper --one-line=keep-blocks --unpad=paren
+
+Chat module plugin for Miranda NG
+
+Copyright (C) 2003 Jörgen Persson
+
+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.
+
+Group chat module: contact list support functions. Add chat rooms as
+contacts and handle default action for such contacts.
+
+This code was taken in almost unmodified from from the chat.dll
+plugin, originally written by Jörgen Persson
+
+$Id: clist.c 10402 2009-07-24 00:35:21Z silvercircle $
+
+*/
+
+/*
+ * handles interaction of the group chat implementation with the contact list plugin
+ */
+
+#include "..\commonheaders.h"
+
+char *szChatIconString = "chaticon";
+
+extern HANDLE hJoinMenuItem, hLeaveMenuItem;
+
+static HANDLE Clist_GroupExists(TCHAR *tszGroup)
+{
+ unsigned int i = 0;
+ TCHAR* _t = 0;
+ char str[10];
+ INT_PTR result = 0;
+ DBVARIANT dbv = {0};
+ int match;
+
+ do {
+ _itoa(i, str, 10);
+ result = M->GetTString(0, "CListGroups", str, &dbv);
+ if (!result) {
+ match = (!_tcscmp(tszGroup, &dbv.ptszVal[1]) && (lstrlen(tszGroup) == lstrlen(&dbv.ptszVal[1])));
+ DBFreeVariant(&dbv);
+ if (match)
+ return((HANDLE)(i + 1));
+ }
+ i++;
+ }
+ while(result == 0);
+ return 0;
+}
+
+HANDLE CList_AddRoom(const char* pszModule, const TCHAR* pszRoom, const TCHAR* pszDisplayName, int iType)
+{
+ HANDLE hContact = CList_FindRoom(pszModule, pszRoom);
+ DBVARIANT dbv;
+ TCHAR pszGroup[50];
+
+ *pszGroup = '\0';
+ if (!M->GetTString(NULL, "Chat", "AddToGroup", &dbv)) {
+ if (lstrlen(dbv.ptszVal) > 0)
+ lstrcpyn(pszGroup, dbv.ptszVal, 50);
+ DBFreeVariant(&dbv);
+ } else
+ lstrcpyn(pszGroup, _T("Chat rooms"), 50);
+
+ if (pszGroup[0])
+ CList_CreateGroup(pszGroup);
+
+ if (hContact)
+ return hContact;
+
+ // here we create a new one since no one is to be found
+
+ if ((hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0)) == NULL)
+ return NULL;
+
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM) hContact, (LPARAM) pszModule);
+ if (pszGroup && lstrlen(pszGroup) > 0)
+ CallService(MS_CLIST_CONTACTCHANGEGROUP, (WPARAM)hContact, (LPARAM)g_Settings.hGroup);
+ else
+ DBDeleteContactSetting(hContact, "CList", "Group");
+
+ M->WriteTString(hContact, pszModule, "Nick", pszDisplayName);
+ M->WriteTString(hContact, pszModule, "ChatRoomID", pszRoom);
+ M->WriteByte(hContact, pszModule, "ChatRoom", (BYTE)iType);
+ DBWriteContactSettingWord(hContact, pszModule, "Status", ID_STATUS_OFFLINE);
+ return hContact;
+}
+
+BOOL CList_SetOffline(HANDLE hContact, BOOL bHide)
+{
+ if (hContact) {
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ int i = M->GetByte(hContact, szProto, "ChatRoom", 0);
+ DBWriteContactSettingWord(hContact, szProto, "ApparentMode", (LPARAM) 0);
+ DBWriteContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL CList_SetAllOffline(BOOL bHide, const char *pszModule)
+{
+ HANDLE hContact;
+ char* szProto;
+
+ hContact = db_find_first();
+ while (hContact) {
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (MM_FindModule(szProto)) {
+ if (!pszModule || (pszModule && !strcmp(pszModule, szProto))) {
+ int i = M->GetByte(hContact, szProto, "ChatRoom", 0);
+ if (i != 0) {
+ DBWriteContactSettingWord(hContact, szProto, "ApparentMode", (LPARAM)(WORD) 0);
+ DBWriteContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ }
+ }
+ }
+
+ hContact = db_find_next(hContact);
+ }
+ return TRUE;
+}
+
+int CList_RoomDoubleclicked(WPARAM wParam, LPARAM lParam)
+{
+ DBVARIANT dbv;
+ char *szProto;
+ BOOL bRedrawFlag = FALSE;
+ bool fCreate = false;
+
+ HANDLE hContact = (HANDLE)wParam;
+ if (!hContact)
+ return 0;
+
+ szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (MM_FindModule(szProto)) {
+ if (M->GetByte(hContact, szProto, "ChatRoom", 0) == 0)
+ return 0;
+
+ if (!M->GetTString(hContact, szProto, "ChatRoomID", &dbv)) {
+ SESSION_INFO* si = SM_FindSession(dbv.ptszVal, szProto);
+ if (si) {
+ // is the "toggle visibility option set, so we need to close the window?
+ if (si->hWnd != NULL
+ && M->GetByte("Chat", "ToggleVisibility", 0) == 1
+ && !CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, 0)
+ && IsWindowVisible(si->hWnd)
+ && !IsIconic(si->pContainer->hwnd)) {
+ PostMessage(si->hWnd, GC_CLOSEWINDOW, 0, 0);
+ DBFreeVariant(&dbv);
+ return 1;
+ }
+ else
+ fCreate = true;
+
+ ShowRoom(si, WINDOW_VISIBLE, TRUE);
+ if (lParam && fCreate) {
+ SendMessage(si->hWnd, DM_ACTIVATEME, 0, 0);
+ if (si->dat)
+ SetForegroundWindow(si->dat->pContainer->hwnd);
+ }
+ }
+ DBFreeVariant(&dbv);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+INT_PTR CList_EventDoubleclicked(WPARAM wParam, LPARAM lParam)
+{
+ return CList_RoomDoubleclicked((WPARAM)((CLISTEVENT*)lParam)->hContact, (LPARAM) 0);
+}
+
+INT_PTR CList_JoinChat(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ if ( hContact ) {
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if ( szProto ) {
+ if ( DBGetContactSettingWord( hContact, szProto, "Status", 0 ) == ID_STATUS_OFFLINE )
+ CallProtoService( szProto, PS_JOINCHAT, wParam, lParam );
+ else
+ CList_RoomDoubleclicked( wParam, 0 );
+ } }
+
+ return 0;
+}
+
+INT_PTR CList_LeaveChat(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ if ( hContact ) {
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if ( szProto )
+ CallProtoService( szProto, PS_LEAVECHAT, wParam, lParam );
+ }
+ return 0;
+}
+
+int CList_PrebuildContactMenu(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ if ( hContact ) {
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+
+ CLISTMENUITEM clmi = {0};
+ clmi.cbSize = sizeof(CLISTMENUITEM);
+ clmi.flags = CMIM_FLAGS | CMIF_DEFAULT | CMIF_HIDDEN;
+
+ if ( szProto ) {
+ // display this menu item only for chats
+ if ( M->GetByte(hContact, szProto, "ChatRoom", 0 )) {
+ // still hide it for offline protos
+ if ( CallProtoService( szProto, PS_GETSTATUS, 0, 0 ) != ID_STATUS_OFFLINE ) {
+ clmi.flags &= ~CMIF_HIDDEN;
+ clmi.flags |= CMIM_NAME;
+
+ if ( DBGetContactSettingWord( hContact, szProto, "Status", 0 ) == ID_STATUS_OFFLINE )
+ clmi.pszName = ( char* )LPGEN("Join chat");
+ else
+ clmi.pszName = ( char* )LPGEN("Open chat window");
+ } } }
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hJoinMenuItem, ( LPARAM )&clmi );
+
+ clmi.flags &= ~(CMIM_NAME | CMIF_DEFAULT);
+ clmi.flags |= CMIF_NOTOFFLINE;
+ CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hLeaveMenuItem, ( LPARAM )&clmi );
+ }
+ return 0;
+}
+
+INT_PTR CList_PrebuildContactMenuSvc(WPARAM wParam, LPARAM lParam)
+{
+ return CList_PrebuildContactMenu(wParam, lParam);
+}
+
+
+void CList_CreateGroup(TCHAR* group)
+{
+ if (!group)
+ return;
+
+ g_Settings.hGroup = Clist_GroupExists(group);
+
+ if (g_Settings.hGroup == 0) {
+ g_Settings.hGroup = (HANDLE)CallService(MS_CLIST_GROUPCREATE, 0, (LPARAM)group);
+
+ if (g_Settings.hGroup) {
+ CallService(MS_CLUI_GROUPADDED, (WPARAM)g_Settings.hGroup, 0);
+ CallService(MS_CLIST_GROUPSETEXPANDED, (WPARAM)g_Settings.hGroup, 1);
+ }
+ }
+}
+
+BOOL CList_AddEvent(HANDLE hContact, HICON Icon, HANDLE event, int type, const TCHAR* fmt, ...)
+{
+ CLISTEVENT cle;
+ va_list marker;
+ TCHAR* szBuf = (TCHAR*)alloca(4096 * sizeof(TCHAR));
+
+ if (!fmt || lstrlen(fmt) < 1 || lstrlen(fmt) > 2000)
+ return FALSE;
+
+ va_start(marker, fmt);
+ _vstprintf(szBuf, fmt, marker);
+ va_end(marker);
+
+ cle.cbSize = sizeof(cle);
+ cle.hContact = (HANDLE)hContact;
+ cle.hDbEvent = (HANDLE)event;
+ cle.flags = type + CLEF_TCHAR;
+ cle.hIcon = Icon;
+ cle.pszService = "GChat/DblClickEvent" ;
+ cle.ptszTooltip = TranslateTS(szBuf);
+ if (type) {
+ if (!CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, (LPARAM)0))
+ CallService(MS_CLIST_ADDEVENT, (WPARAM) hContact, (LPARAM) &cle);
+ } else {
+ if (CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)hContact, (LPARAM)"chaticon");
+ CallService(MS_CLIST_ADDEVENT, (WPARAM) hContact, (LPARAM) &cle);
+ }
+ return TRUE;
+}
+
+HANDLE CList_FindRoom(const char* pszModule, const TCHAR* pszRoom)
+{
+ HANDLE hContact = db_find_first();
+ while (hContact) {
+ char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if (szProto && !lstrcmpiA(szProto, pszModule)) {
+ if (M->GetByte(hContact, szProto, "ChatRoom", 0) != 0) {
+ DBVARIANT dbv;
+ if (!M->GetTString(hContact, szProto, "ChatRoomID", &dbv)) {
+ if (!lstrcmpi(dbv.ptszVal, pszRoom)) {
+ DBFreeVariant(&dbv);
+ return hContact;
+ }
+ DBFreeVariant(&dbv);
+ }
+ }
+ }
+
+ hContact = db_find_next(hContact);
+ }
+ return 0;
+}
diff --git a/plugins/TabSRMM/src/chat/colorchooser.cpp b/plugins/TabSRMM/src/chat/colorchooser.cpp
new file mode 100644
index 0000000000..72366db24b
--- /dev/null
+++ b/plugins/TabSRMM/src/chat/colorchooser.cpp
@@ -0,0 +1,281 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda NG, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * $Id: colorchooser.cpp 10670 2009-09-11 03:28:50Z silvercircle $
+ *
+ * Color chooser for group chats
+ *
+ */
+
+#include "..\commonheaders.h"
+#include <math.h>
+
+static int CalculateCoordinatesToButton(COLORCHOOSER * pCC, POINT pt)
+{
+ int iSquareRoot = (int)sqrt(static_cast<float>(pCC->pModule->nColorCount));
+ int nCols = iSquareRoot * iSquareRoot < pCC->pModule->nColorCount ? iSquareRoot + 1 : iSquareRoot;
+
+ int col = pt.x / 25;
+ int row = (pt.y - 20) / 20;
+ int pos = nCols * row + col;
+
+ if (pt.y < 20 && pos >= pCC->pModule->nColorCount)
+ pos = -1;
+
+ return pos;
+}
+
+static RECT CalculateButtonToCoordinates(COLORCHOOSER * pCC, int buttonPosition)
+{
+ RECT pt;
+ int iSquareRoot = (int)sqrt(static_cast<float>(pCC->pModule->nColorCount));
+ int nCols = iSquareRoot * iSquareRoot < pCC->pModule->nColorCount ? iSquareRoot + 1 : iSquareRoot;
+
+ int row = buttonPosition / nCols;
+ int col = buttonPosition % nCols;
+
+ pt.left = col * 25 + 1;
+ pt.top = row * 20 + 20;
+ pt.right = pt.left + 25 - 1;
+ pt.bottom = pt.top + 20;
+
+ return pt;
+}
+
+INT_PTR CALLBACK DlgProcColorToolWindow(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static COLORCHOOSER* pCC = NULL;
+ static int iCurrentHotTrack;
+ static BOOL bChoosing;
+ static int iRows;
+ static int iColumns;
+ static HWND hPreviousActiveWindow;
+
+ switch (msg) {
+ case WM_INITDIALOG: {
+ RECT rc;
+ int iSquareRoot;
+ int width ;
+ int height;
+
+ TranslateDialogDefault(hwndDlg);
+ pCC = (COLORCHOOSER*) lParam;
+
+ iCurrentHotTrack = -2;
+ bChoosing = FALSE;
+
+ iSquareRoot = (int)sqrt(static_cast<float>(pCC->pModule->nColorCount));
+
+ iColumns = iSquareRoot * iSquareRoot == pCC->pModule->nColorCount ? iSquareRoot : iSquareRoot + 1;
+ iRows = iSquareRoot;
+
+ rc.top = rc.left = 100;
+ rc.right = 100 + iColumns * 25 + 1;
+ rc.bottom = iRows * 20 + 100 + 20;
+
+ AdjustWindowRectEx(&rc, GetWindowLongPtr(hwndDlg, GWL_STYLE), FALSE, GetWindowLongPtr(hwndDlg, GWL_EXSTYLE));
+
+ width = rc.right - rc.left;
+ height = rc.bottom - rc.top;
+
+ pCC->yPosition -= height;
+
+
+ SetDlgItemText(hwndDlg, IDC_COLORTEXT, pCC->bForeground ? TranslateT("Text color") :
+ TranslateT("Background color"));
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_COLORTEXT), NULL, 0, 0, width, 20, 0);
+ SetWindowPos(hwndDlg, NULL, pCC->xPosition, pCC->yPosition, width, height, SWP_SHOWWINDOW);
+ }
+ break;
+
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_COLORTEXT)) {
+ SetTextColor((HDC)wParam, RGB(60, 60, 150));
+ SetBkColor((HDC)wParam, GetSysColor(COLOR_WINDOW));
+ return (INT_PTR)GetSysColorBrush(COLOR_WINDOW);
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ if (iCurrentHotTrack >= 0)
+ PostMessage(hwndDlg, WM_LBUTTONUP, 0, 0);
+ break;
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ if (iCurrentHotTrack >= 0 && iCurrentHotTrack < pCC->pModule->nColorCount && pCC->hWndTarget != NULL) {
+ HWND hWindow;
+ CHARFORMAT2 cf;
+ cf.cbSize = sizeof(CHARFORMAT2);
+ cf.dwMask = 0;
+ cf.dwEffects = 0;
+ hWindow = GetParent(pCC->hWndTarget);
+
+ if (pCC->bForeground) {
+ pCC->si->bFGSet = TRUE;
+ pCC->si->iFG = iCurrentHotTrack;
+ if (IsDlgButtonChecked(hWindow, IDC_COLOR)) {
+ cf.dwMask = CFM_COLOR;
+ cf.crTextColor = pCC->pModule->crColors[iCurrentHotTrack];
+ SendMessage(pCC->hWndTarget, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ } else {
+ pCC->si->bBGSet = TRUE;
+ pCC->si->iBG = iCurrentHotTrack;
+ if (IsDlgButtonChecked(hWindow, IDC_BKGCOLOR)) {
+ cf.dwMask = CFM_BACKCOLOR;
+ cf.crBackColor = pCC->pModule->crColors[iCurrentHotTrack];
+ SendMessage(pCC->hWndTarget, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ }
+ }
+ PostMessage(hwndDlg, WM_CLOSE, 0, 0);
+ break;
+
+ case WM_ACTIVATE:
+ if (wParam == WA_INACTIVE)
+ PostMessage(hwndDlg, WM_CLOSE, 0, 0);
+ else if ((wParam == WA_ACTIVE) || (wParam == WA_CLICKACTIVE))
+ hPreviousActiveWindow = (HWND)lParam;
+ break;
+
+ case WM_MOUSEMOVE: {
+ HDC hdc = GetDC(hwndDlg);
+ POINT pt;
+ RECT rect;
+ int but;
+
+ pt.x = LOWORD(lParam);
+ pt.y = HIWORD(lParam);
+
+ if (iCurrentHotTrack == -2)
+ return 0; // prevent focussing when not drawn yet!
+
+ but = CalculateCoordinatesToButton(pCC, pt);
+
+ // weird stuff
+ if (but != iCurrentHotTrack) {
+ if (iCurrentHotTrack >= 0) {
+ rect = CalculateButtonToCoordinates(pCC, iCurrentHotTrack);
+ DrawFocusRect(hdc, &rect);
+ iCurrentHotTrack = -1;
+ }
+ iCurrentHotTrack = but;
+
+ if (iCurrentHotTrack >= 0) {
+ rect = CalculateButtonToCoordinates(pCC, iCurrentHotTrack);
+ DrawFocusRect(hdc, &rect);
+ }
+ }
+ ReleaseDC(hwndDlg, hdc);
+ }
+ break;
+
+ case WM_PAINT: {
+ PAINTSTRUCT ps;
+ HDC hdc;
+ RECT rc;
+ int i = 0;
+ int iThisRow = 1;
+ int iThisColumn = 0;
+
+ GetClientRect(hwndDlg, &rc);
+
+ rc.top += 20;
+
+ hdc = BeginPaint(hwndDlg, &ps);
+
+ // fill background
+ FillRect(hdc, &rc, GetSysColorBrush(COLOR_WINDOW));
+
+ for (i; i < pCC->pModule->nColorCount; i++) {
+ HBRUSH hbr;
+
+ // decide place to draw the color block in the window
+ iThisColumn ++;
+ if (iThisColumn > iColumns) {
+ iThisColumn = 1;
+ iThisRow++;
+ }
+
+ if (pCC->bForeground && pCC->si->bFGSet && pCC->si->iFG == i ||
+ !pCC->bForeground && pCC->si->bBGSet && pCC->si->iBG == i) {
+ rc.top = (iThisRow - 1) * 20 + 1 + 20 ;
+ rc.left = (iThisColumn - 1) * 25 + 1 + 1 ;
+ rc.bottom = iThisRow * 20 - 1 + 20 ;
+ rc.right = iThisColumn * 25 - 1 ;
+
+ DrawEdge(hdc, &rc, EDGE_RAISED, BF_TOP | BF_LEFT | BF_RIGHT | BF_BOTTOM);
+ }
+
+ rc.top = (iThisRow - 1) * 20 + 3 + 20 ;
+ rc.left = (iThisColumn - 1) * 25 + 3 + 1 ;
+ rc.bottom = iThisRow * 20 - 3 + 20 ;
+ rc.right = iThisColumn * 25 - 3 ;
+
+ FillRect(hdc, &rc, CSkin::m_BrushBack);
+
+ hbr = CreateSolidBrush(pCC->pModule->crColors[i]);
+
+ rc.top = (iThisRow - 1) * 20 + 4 + 20;
+ rc.left = (iThisColumn - 1) * 25 + 4 + 1;
+ rc.bottom = iThisRow * 20 - 4 + 20;
+ rc.right = iThisColumn * 25 - 4;
+
+ FillRect(hdc, &rc, hbr);
+ DeleteObject(hbr);
+ }
+
+ EndPaint(hwndDlg, &ps);
+ iCurrentHotTrack = -1;
+ }
+ break;
+
+ case WM_CLOSE:
+ SetFocus(pCC->hWndTarget);
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ mir_free(pCC);
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/plugins/TabSRMM/src/chat/log.cpp b/plugins/TabSRMM/src/chat/log.cpp
new file mode 100644
index 0000000000..bdadea5bf5
--- /dev/null
+++ b/plugins/TabSRMM/src/chat/log.cpp
@@ -0,0 +1,1340 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda NG, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: log.cpp 13614 2011-04-22 13:16:21Z borkra $
+ *
+ * Implements the richedit-based message history display for the group
+ * chat window.
+ *
+ */
+
+#include "..\commonheaders.h"
+#include <math.h>
+#include <mbstring.h>
+#include <shlwapi.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.
+ */
+
+extern FONTINFO aFonts[OPTIONS_FONTCOUNT];
+extern HICON hIcons[30];
+
+static PBYTE pLogIconBmpBits[14];
+static int logIconBmpSize[ SIZEOF(pLogIconBmpBits)];
+
+static int logPixelSY = 0;
+static int logPixelSX = 0;
+static char *szDivider = "\\strike----------------------------------------------------------------------------\\strike0";
+static char CHAT_rtfFontsGlobal[OPTIONS_FONTCOUNT + 2][RTFCACHELINESIZE];
+static char *CHAT_rtffonts = 0;
+
+/*
+ * 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 TCHAR* src, int codepage ) {
+ return u2a( src, codepage );
+}
+
+static TCHAR *a2tcp(const char *text, int cp) {
+ if ( text != NULL ) {
+ int cbLen = MultiByteToWideChar( cp, 0, text, -1, NULL, 0 );
+ TCHAR* result = ( TCHAR* )mir_alloc( sizeof(TCHAR)*( 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, TCHAR **buffer, int *cbBufferEnd, int *cbBufferAlloced, const TCHAR *fmt, ...)
+{
+ va_list va;
+ int lineLen, textCharsCount=0;
+ TCHAR* line = (TCHAR*)alloca( 8001 * sizeof(TCHAR));
+ TCHAR* d;
+ MODULEINFO *mi = MM_FindModule(streamData->si->pszModule);
+
+ va_start(va, fmt);
+ lineLen = _vsntprintf( 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 = (TCHAR *) mir_realloc(*buffer, *cbBufferAlloced * sizeof(TCHAR));
+ }
+
+ d = *buffer + *cbBufferEnd;
+
+ for (; *line; line++, textCharsCount++) {
+ if (*line == '%' && !simpleMode ) {
+ TCHAR szTemp[200];
+
+ szTemp[0] = '\0';
+ switch ( *++line ) {
+ case '\0':
+ case '%':
+ *d++ = '%';
+ break;
+
+ case 'c':
+ case 'f':
+ if (!g_Settings.StripFormat && !streamData->bStripFormat) {
+ if ( line[1] != '\0' && line[2] != '\0') {
+ TCHAR szTemp3[3], c = *line;
+ int col;
+ szTemp3[0] = line[1];
+ szTemp3[1] = line[2];
+ szTemp3[2] = '\0';
+ col = _ttoi(szTemp3);
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%%%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.StripFormat && !streamData->bStripFormat) {
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%%%c"), *line );
+ }
+ break;
+ case 'b':
+ case 'u':
+ case 'i':
+ case 'B':
+ case 'U':
+ case 'I':
+ case 'r':
+ if ( !streamData->bStripFormat ) {
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%%%c"), *line );
+ }
+ break;
+ }
+
+ if ( szTemp[0] ) {
+ size_t iLen = lstrlen(szTemp);
+ memcpy( d, szTemp, iLen * sizeof(TCHAR));
+ d += iLen;
+ }
+ }
+ else if (*line == '%') {
+ *d++ = '%';
+ *d++ = (char) *line;
+ }
+ else {
+ *d++ = (TCHAR) *line;
+ }
+ }
+ *d = '\0';
+ *cbBufferEnd = (int) (d - *buffer);
+ return textCharsCount;
+}
+
+static void AddEventTextToBufferIEView(TCHAR **buffer, int *bufferEnd, int *bufferAlloced, LOGSTREAMDATA *streamData)
+{
+ if (streamData->lin->ptszText)
+ Log_AppendIEView(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T(": %s"), streamData->lin->ptszText);
+}
+
+static void AddEventToBufferIEView(TCHAR **buffer, int *bufferEnd, int *bufferAlloced, LOGSTREAMDATA *streamData, TCHAR *pszNick)
+{
+
+ if ( streamData && streamData->lin ) {
+ switch ( streamData->lin->iType ) {
+ case GC_EVENT_MESSAGE:
+ if ( streamData->lin->ptszText ) {
+ TCHAR *ptszTemp = NULL;
+ TCHAR *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, buffer, bufferEnd, bufferAlloced, _T("%s"), ptszText );
+ mir_free(ptszTemp);
+ }
+ break;
+ case GC_EVENT_ACTION:
+ if ( pszNick && streamData->lin->ptszText) {
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, _T("%s "), streamData->lin->ptszNick);
+ Log_AppendIEView(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T("%s"), streamData->lin->ptszText);
+ }
+ break;
+ case GC_EVENT_JOIN:
+ if (pszNick) {
+ if (!streamData->lin->bIsMe)
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s has joined"), pszNick);
+ else
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("You have joined %s"), streamData->si->ptszName);
+ }
+ break;
+ case GC_EVENT_PART:
+ if (pszNick)
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s has left"), pszNick);
+ AddEventTextToBufferIEView(buffer, bufferEnd, bufferAlloced, streamData);
+ break;
+ case GC_EVENT_QUIT:
+ if (pszNick)
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s has disconnected"), pszNick);
+ AddEventTextToBufferIEView(buffer, bufferEnd, bufferAlloced, streamData);
+ break;
+ case GC_EVENT_NICK:
+ if (pszNick && streamData->lin->ptszText) {
+ if (!streamData->lin->bIsMe)
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s is now known as %s"), pszNick, streamData->lin->ptszText);
+ else
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("You are now known as %s"), streamData->lin->ptszText);
+ }
+ break;
+ case GC_EVENT_KICK:
+ if (pszNick && streamData->lin->ptszStatus)
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s kicked %s"), streamData->lin->ptszStatus, streamData->lin->ptszNick);
+ AddEventTextToBufferIEView(buffer, bufferEnd, bufferAlloced, streamData);
+ break;
+ case GC_EVENT_NOTICE:
+ if (pszNick && streamData->lin->ptszText) {
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("Notice from %s"), pszNick );
+ AddEventTextToBufferIEView(buffer, bufferEnd, bufferAlloced, streamData);
+ }
+ break;
+ case GC_EVENT_TOPIC:
+ if (streamData->lin->ptszText)
+ Log_AppendIEView(streamData, FALSE, buffer, bufferEnd, bufferAlloced, TranslateT("The topic is \'%s%s\'"), streamData->lin->ptszText, _T("%r"));
+ if (pszNick)
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced,
+ 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, buffer, bufferEnd, bufferAlloced, (streamData->lin->bIsMe) ? _T("--> %s") : _T("%s"), streamData->lin->ptszText);
+ break;
+ case GC_EVENT_ADDSTATUS:
+ if (pszNick && streamData->lin->ptszText && streamData->lin->ptszStatus)
+ Log_AppendIEView(streamData, TRUE, buffer, bufferEnd, bufferAlloced, 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, buffer, bufferEnd, bufferAlloced, TranslateT("%s disables \'%s\' status for %s"), streamData->lin->ptszText , streamData->lin->ptszStatus, streamData->lin->ptszNick);
+ break;
+ }
+ }
+}
+
+static void LogEventIEView(LOGSTREAMDATA *streamData, TCHAR *ptszNick)
+{
+ TCHAR *buffer = NULL;
+ int bufferEnd = 0;
+ int bufferAlloced = 0;
+ IEVIEWEVENTDATA ied;
+ IEVIEWEVENT event;
+ ZeroMemory(&event, sizeof(event));
+ event.cbSize = sizeof(event);
+ event.dwFlags = 0;
+ event.hwnd = streamData->dat->hwndIEView ? streamData->dat->hwndIEView : streamData->dat->hwndHPP;
+ event.hContact = streamData->dat->hContact;
+ event.codepage = streamData->dat->codePage;
+ event.pszProto = streamData->si->pszModule;
+ event.iType = IEE_LOG_MEM_EVENTS;
+ event.eventData = &ied;
+ event.count = 1;
+
+ ZeroMemory(&ied, sizeof(ied));
+ AddEventToBufferIEView(&buffer, &bufferEnd, &bufferAlloced, 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.ShowTime ? 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->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;
+}
+
+/* replace pattern `ptrn' with the string `rplc' in string `src' points to */
+static TCHAR * _tcsrplc(TCHAR **src, const TCHAR *ptrn, const TCHAR *rplc)
+{
+ size_t lSrc, lPtrn, lRplc;
+ TCHAR *tszFound, *tszTail;
+
+ lSrc = lstrlen(*src);
+ lPtrn = lstrlen(ptrn);
+ lRplc = lstrlen(rplc);
+ if (lPtrn && lSrc && lSrc >= lPtrn && (tszFound = _tcsstr(*src, ptrn)) != NULL) {
+ if (lRplc > lPtrn)
+ *src = (TCHAR *) realloc((void *) * src,
+ sizeof(TCHAR) * (lSrc + lRplc - lPtrn + 1));
+ if (tszTail = (TCHAR *) malloc(sizeof(TCHAR) *
+ (lSrc - (tszFound - *src) - lPtrn + 1))) {
+ /* save tail */
+ _tcscpy(tszTail, tszFound + lPtrn);
+ /* write replacement string */
+ _tcscpy(tszFound, rplc);
+ /* write tail */
+ _tcscpy(tszFound + lRplc, tszTail);
+ free((void *) tszTail);
+ }
+ }
+ return *src;
+}
+
+/*
+ * replace pattern `ptrn' with the string `rplc' in string `src',
+ * `src' is supposed to be `n' character long (or no checking is done if n < 0).
+ * This function is useful for statically allocated buffers
+ */
+static TCHAR * _tcsnrplc(TCHAR *src, size_t n, const TCHAR *ptrn, const TCHAR *rplc)
+{
+ size_t lSrc, lPtrn, lRplc;
+ TCHAR *tszFound, *tszTail;
+
+ lSrc = lstrlen(src);
+ lPtrn = lstrlen(ptrn);
+ lRplc = lstrlen(rplc);
+ if (lPtrn && lSrc && lSrc >= lPtrn && /* lengths are ok */
+ (tszFound = _tcsstr(src, ptrn)) != NULL && /* pattern was found in string */
+ (n < 0 || lSrc - lPtrn + lRplc < n) && /* there is enough room in the string */
+ (tszTail = (TCHAR *) malloc(sizeof(TCHAR) *
+ (lSrc - (tszFound - src) - lPtrn + 1))) != NULL) {
+ /* save tail */
+ _tcscpy(tszTail, tszFound + lPtrn);
+ /* write replacement string */
+ _tcscpy(tszFound, rplc);
+ /* write tail */
+ _tcscpy(tszFound + lRplc, tszTail);
+ free((void *) tszTail);
+ }
+ return src;
+}
+
+static char *Log_SetStyle(int style, int fontindex)
+{
+ if (style < OPTIONS_FONTCOUNT)
+ return CHAT_rtffonts + (style * RTFCACHELINESIZE);
+
+ return "";
+}
+
+static void Log_Append(char **buffer, int *cbBufferEnd, int *cbBufferAlloced, const char *fmt, ...)
+{
+ va_list va;
+ int charsDone = 0;
+
+ va_start(va, fmt);
+ for (;;) {
+ charsDone = mir_vsnprintf(*buffer + *cbBufferEnd, *cbBufferAlloced - *cbBufferEnd, fmt, va);
+ if (charsDone >= 0)
+ break;
+ *cbBufferAlloced += 4096;
+ *buffer = (char *) mir_realloc(*buffer, *cbBufferAlloced);
+ }
+ va_end(va);
+ *cbBufferEnd += charsDone;
+}
+
+static int Log_AppendRTF(LOGSTREAMDATA* streamData, BOOL simpleMode, char **buffer, int *cbBufferEnd, int *cbBufferAlloced, const TCHAR *fmt, ...)
+{
+ va_list va;
+ int lineLen, textCharsCount = 0;
+ TCHAR* line = (TCHAR*)alloca(8001 * sizeof(TCHAR));
+ char* d;
+
+ va_start(va, fmt);
+ lineLen = _vsntprintf(line, 8000, fmt, va);
+ if (lineLen < 0) lineLen = 8000;
+ line[lineLen] = 0;
+ va_end(va);
+
+ lineLen = lineLen * 20 + 8;
+ if (*cbBufferEnd + lineLen > *cbBufferAlloced) {
+ cbBufferAlloced[0] += (lineLen + 1024 - lineLen % 1024);
+ if ((d = (char *) mir_realloc(*buffer, *cbBufferAlloced)) == 0)
+ return 0;
+ *buffer = d;
+ }
+
+ d = *buffer + *cbBufferEnd;
+
+ for (; *line; line++, textCharsCount++) {
+ if (*line == '\r' && line[1] == '\n') {
+ CopyMemory(d, "\\par ", 5);
+ line++;
+ d += 5;
+ } else if (*line == '\n') {
+ CopyMemory(d, "\\line ", 6);
+ d += 6;
+ } else if (*line == '%' && !simpleMode) {
+ char szTemp[200];
+
+ szTemp[0] = '\0';
+ switch (*++line) {
+ case '\0':
+ case '%':
+ *d++ = '%';
+ break;
+
+ case 'c':
+ case 'f':
+ if (g_Settings.StripFormat || streamData->bStripFormat)
+ line += 2;
+
+ else if (line[1] != '\0' && line[2] != '\0') {
+ TCHAR szTemp3[3], c = *line;
+ int col;
+ szTemp3[0] = line[1];
+ szTemp3[1] = line[2];
+ szTemp3[2] = '\0';
+ line += 2;
+
+ col = _ttoi(szTemp3);
+ col += (OPTIONS_FONTCOUNT + 1);
+ mir_snprintf(szTemp, SIZEOF(szTemp), (c == 'c') ? "\\cf%u " : "\\highlight%u ", col);
+ }
+ break;
+ case 'C':
+ case 'F':
+ if (!g_Settings.StripFormat && !streamData->bStripFormat) {
+ int j = streamData->lin->bIsHighlighted ? 16 : EventToIndex(streamData->lin);
+ if (*line == 'C')
+ mir_snprintf(szTemp, SIZEOF(szTemp), "\\cf%u ", j + 1);
+ else
+ mir_snprintf(szTemp, SIZEOF(szTemp), "\\highlight0 ");
+ }
+ break;
+ case 'b':
+ case 'u':
+ case 'i':
+ if (!streamData->bStripFormat)
+ mir_snprintf(szTemp, SIZEOF(szTemp), (*line == 'u') ? "\\%cl " : "\\%c ", *line);
+ break;
+
+ case 'B':
+ case 'U':
+ case 'I':
+ if (!streamData->bStripFormat) {
+ mir_snprintf(szTemp, SIZEOF(szTemp), (*line == 'U') ? "\\%cl0 " : "\\%c0 ", *line);
+ CharLowerA(szTemp);
+ }
+ break;
+
+ case 'r':
+ if (!streamData->bStripFormat) {
+ int index = EventToIndex(streamData->lin);
+ mir_snprintf(szTemp, SIZEOF(szTemp), "%s ", Log_SetStyle(index, index));
+ }
+ break;
+ }
+
+ if (szTemp[0]) {
+ int iLen = lstrlenA(szTemp);
+ memcpy(d, szTemp, iLen);
+ d += iLen;
+ }
+ } else if (*line == '\t' && !streamData->bStripFormat) {
+ CopyMemory(d, "\\tab ", 5);
+ d += 5;
+ } else if ((*line == '\\' || *line == '{' || *line == '}') && !streamData->bStripFormat) {
+ *d++ = '\\';
+ *d++ = (char) * line;
+ } else if (*line > 0 && *line < 128) {
+ *d++ = (char) * line;
+ }
+ else d += sprintf(d, "\\u%u ?", (WORD) * line);
+ }
+
+ *cbBufferEnd = (int)(d - *buffer);
+ return textCharsCount;
+}
+
+static void AddEventToBuffer(char **buffer, int *bufferEnd, int *bufferAlloced, LOGSTREAMDATA *streamData)
+{
+ TCHAR szTemp[512], szTemp2[512];
+ TCHAR* pszNick = NULL;
+
+ if (streamData == NULL)
+ return;
+
+ if (streamData->lin == NULL)
+ return;
+
+ if (streamData->lin->ptszNick) {
+ if (g_Settings.LogLimitNames && lstrlen(streamData->lin->ptszNick) > 20) {
+ lstrcpyn(szTemp, streamData->lin->ptszNick, 20);
+ lstrcpyn(szTemp + 20, _T("..."), 4);
+ } else lstrcpyn(szTemp, streamData->lin->ptszNick, 511);
+
+ if (g_Settings.ClickableNicks)
+ mir_sntprintf(szTemp2, SIZEOF(szTemp2), _T("~~++#%s#++~~"), szTemp);
+ else
+ _tcscpy(szTemp2, szTemp);
+
+ if (streamData->lin->ptszUserInfo && streamData->lin->iType != GC_EVENT_TOPIC)
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s (%s)"), szTemp2, streamData->lin->ptszUserInfo);
+ else
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s"), szTemp2);
+ pszNick = szTemp;
+ }
+
+ switch (streamData->lin->iType) {
+ case GC_EVENT_MESSAGE:
+ if (streamData->lin->ptszText)
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T("%s"), streamData->lin->ptszText);
+ break;
+ case GC_EVENT_ACTION:
+ if (streamData->lin->ptszNick && streamData->lin->ptszText) {
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, _T("%s "), streamData->lin->ptszNick);
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T("%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, buffer, bufferEnd, bufferAlloced, TranslateT("%s has joined"), pszNick);
+ else
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("You have joined %s"), streamData->si->ptszName);
+ }
+ break;
+ case GC_EVENT_PART:
+ if (pszNick)
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s has left"), pszNick);
+ if (streamData->lin->ptszText)
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T(": %s"), streamData->lin->ptszText);
+ break;
+ case GC_EVENT_QUIT:
+ if (pszNick)
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s has disconnected"), pszNick);
+ if (streamData->lin->ptszText)
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T(": %s"), streamData->lin->ptszText);
+ break;
+ case GC_EVENT_NICK:
+ if (pszNick && streamData->lin->ptszText) {
+ if (!streamData->lin->bIsMe)
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s is now known as %s"), pszNick, streamData->lin->ptszText);
+ else
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("You are now known as %s"), streamData->lin->ptszText);
+ }
+ break;
+ case GC_EVENT_KICK:
+ if (pszNick && streamData->lin->ptszStatus)
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced,
+ TranslateT("%s kicked %s"), streamData->lin->ptszStatus, pszNick);
+
+ if (streamData->lin->ptszText)
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T(": %s"), streamData->lin->ptszText);
+ break;
+ case GC_EVENT_NOTICE:
+ if (pszNick && streamData->lin->ptszText) {
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("Notice from %s: "), pszNick);
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T("%s"), streamData->lin->ptszText);
+ }
+ break;
+ case GC_EVENT_TOPIC:
+ if (streamData->lin->ptszText)
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, TranslateT("The topic is \'%s%s\'"), streamData->lin->ptszText, _T("%r"));
+ if (pszNick)
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced,
+ (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, buffer, bufferEnd, bufferAlloced, (streamData->lin->bIsMe) ? _T("--> %s") : _T("%s"), streamData->lin->ptszText);
+ break;
+ case GC_EVENT_ADDSTATUS:
+ if (pszNick && streamData->lin->ptszText && streamData->lin->ptszStatus)
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced,
+ 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, buffer, bufferEnd, bufferAlloced,
+ TranslateT("%s disables \'%s\' status for %s"),
+ streamData->lin->ptszText , streamData->lin->ptszStatus, pszNick);
+ }
+ break;
+ }
+}
+
+TCHAR* MakeTimeStamp(TCHAR* pszStamp, time_t time)
+{
+ static TCHAR szTime[30];
+ _tcsftime(szTime, 29, pszStamp, localtime(&time));
+ return szTime;
+}
+
+static char* Log_CreateRTF(LOGSTREAMDATA *streamData)
+{
+ char *buffer, *header;
+ int bufferAlloced, bufferEnd, i, me = 0;
+ LOGINFO * lin = streamData->lin;
+ MODULEINFO *mi = MM_FindModule(streamData->si->pszModule);
+
+ // guesstimate amount of memory for the RTF
+ bufferEnd = 0;
+ bufferAlloced = streamData->bRedraw ? 2048 * (streamData->si->iEventCount + 2) : 2048;
+ buffer = (char *) mir_alloc(bufferAlloced);
+ buffer[0] = '\0';
+
+ // ### RTF HEADER
+
+ if (0 == mi->pszHeader)
+ mi->pszHeader = Log_CreateRtfHeader(mi);
+
+ header = mi->pszHeader;
+ streamData->crCount = mi->nColorCount;
+
+ if (header)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, header);
+
+
+ // ### RTF BODY (one iteration per event that should be streamed in)
+ while (lin) {
+ // filter
+ if (streamData->si->iType != GCW_CHATROOM || !streamData->si->bFilterEnabled || (streamData->si->iLogFilterFlags&lin->iType) != 0) {
+ if (lin->next != NULL)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\par ");
+
+ if (streamData->dat->dwFlags & MWF_DIVIDERWANTED || lin->dwFlags & MWF_DIVIDERWANTED) {
+ static char szStyle_div[128] = "\0";
+ if (szStyle_div[0] == 0)
+ mir_snprintf(szStyle_div, 128, "\\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)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\qc\\sl-1\\highlight%d %s ---------------------------------------------------------------------------------------\\par ", 18, szStyle_div);
+ streamData->dat->dwFlags &= ~MWF_DIVIDERWANTED;
+ }
+ // create new line, and set font and color
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\ql\\sl0%s ", Log_SetStyle(0, 0));
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\v~-+%d+-~\\v0 ", lin);
+
+ // Insert icon
+ if (g_Settings.LogSymbols) // use symbols
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s %c", Log_SetStyle(17, 17), EventToSymbol(lin));
+ else if (g_Settings.dwIconFlags) {
+ int iIndex = lin->bIsHighlighted ? ICON_HIGHLIGHT : EventToIcon(lin);
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\f0\\fs14");
+ while (bufferAlloced - bufferEnd < (logIconBmpSize[0] + 20))
+ bufferAlloced += 4096;
+ buffer = (char *) mir_realloc(buffer, bufferAlloced);
+ CopyMemory(buffer + bufferEnd, pLogIconBmpBits[iIndex], logIconBmpSize[iIndex]);
+ bufferEnd += logIconBmpSize[iIndex];
+ }
+
+ if (g_Settings.TimeStampEventColour) {
+ // colored timestamps
+ static char szStyle[256];
+ int iii;
+ if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) {
+ iii = lin->bIsHighlighted ? 16 : (lin->bIsMe ? 2 : 1);
+ mir_snprintf(szStyle, SIZEOF(szStyle), "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\ul%d\\fs%u", iii + 1, aFonts[0].lf.lfWeight >= FW_BOLD ? 1 : 0,aFonts[0].lf.lfItalic,aFonts[0].lf.lfUnderline, 2 * abs(aFonts[0].lf.lfHeight) * 74 / logPixelSY);
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s ", szStyle);
+ } else {
+ iii = lin->bIsHighlighted ? 16 : EventToIndex(lin);
+ mir_snprintf(szStyle, SIZEOF(szStyle), "\\f0\\cf%u\\ul0\\highlight0\\b%d\\i%d\\ul%d\\fs%u", iii + 1, aFonts[0].lf.lfWeight >= FW_BOLD ? 1 : 0, aFonts[0].lf.lfItalic,aFonts[0].lf.lfUnderline ,2 * abs(aFonts[0].lf.lfHeight) * 74 / logPixelSY);
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s ", szStyle);
+ }
+ } else
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s ", Log_SetStyle(0, 0));
+ // insert a TAB if necessary to put the timestamp in the right position
+ if (g_Settings.dwIconFlags)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\tab ");
+
+ //insert timestamp
+ if (g_Settings.ShowTime) {
+ TCHAR szTimeStamp[30], szOldTimeStamp[30];
+
+ lstrcpyn(szTimeStamp, MakeTimeStamp(g_Settings.pszTimeStamp, lin->time), 30);
+ lstrcpyn(szOldTimeStamp, MakeTimeStamp(g_Settings.pszTimeStamp, streamData->si->LastTime), 30);
+ if (!g_Settings.ShowTimeIfChanged || streamData->si->LastTime == 0 || lstrcmp(szTimeStamp, szOldTimeStamp)) {
+ streamData->si->LastTime = lin->time;
+ Log_AppendRTF(streamData, TRUE, &buffer, &bufferEnd, &bufferAlloced, _T("%s"), szTimeStamp);
+ }
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\tab ");
+ }
+
+ // Insert the nick
+ if (lin->ptszNick && lin->iType == GC_EVENT_MESSAGE) {
+ TCHAR pszTemp[300], *p1;
+ STATUSINFO *ti;
+ char pszIndicator[3] = "\0\0";
+ int crNickIndex = 0;
+ //mad
+ if (g_Settings.LogClassicIndicators/*g_Settings.ClassicIndicators */||g_Settings.ColorizeNicksInLog) {
+ USERINFO *ui = streamData->si->pUsers;
+ while (ui) {
+ if (!lstrcmp(ui->pszNick, lin->ptszNick)) {
+ ti = TM_FindStatus(streamData->si->pStatuses, TM_WordToString(streamData->si->pStatuses, ui->Status));
+ if (ti && (int)ti->hIcon < streamData->si->iStatusCount) {
+ int id = streamData->si->iStatusCount - (int)ti->hIcon - 1;
+ switch (id) {
+ case 1:
+ pszIndicator[0] = '+';
+ crNickIndex = 2;
+ break;
+ case 2:
+ pszIndicator[0] = '%';
+ crNickIndex = 1;
+ break;
+ case 3:
+ pszIndicator[0] = '@';
+ crNickIndex = 0;
+ break;
+ case 4:
+ pszIndicator[0] = '!';
+ crNickIndex = 3;
+ break;
+ case 5:
+ pszIndicator[0] = '*';
+ crNickIndex = 4;
+ break;
+ default:
+ pszIndicator[0] = 0;
+ }
+ }
+ break;
+ }
+ ui = ui->next;
+ }
+ }
+
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s ", Log_SetStyle(lin->bIsMe ? 2 : 1, lin->bIsMe ? 2 : 1));
+ //MAD
+ if (g_Settings.LogClassicIndicators /*g_Settings.ClassicIndicators*/)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s", pszIndicator);
+
+ lstrcpyn(pszTemp, lin->bIsMe ? g_Settings.pszOutgoingNick : g_Settings.pszIncomingNick, 299);
+ p1 = _tcsstr(pszTemp, _T("%n"));
+ if (p1)
+ p1[1] = 's';
+
+ if (!lin->bIsMe) {
+ if (g_Settings.ClickableNicks) {
+ _tcsnrplc(pszTemp, 300, _T("%s"), _T("~~++#%s#++~~"));
+ pszTemp[299] = 0;
+ }
+ //Log_Append(&buffer, &bufferEnd, &bufferAlloced, "~~++#");
+ if (g_Settings.ColorizeNicksInLog && pszIndicator[0])
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\cf%u ", OPTIONS_FONTCOUNT + streamData->crCount + crNickIndex + 1);
+ }
+
+ Log_AppendRTF(streamData, TRUE, &buffer, &bufferEnd, &bufferAlloced, pszTemp, lin->ptszNick);
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, " ");
+ }
+
+ // Insert the message
+ {
+ i = lin->bIsHighlighted ? 16 : EventToIndex(lin);
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "%s ", Log_SetStyle(i, i));
+ streamData->lin = lin;
+ AddEventToBuffer(&buffer, &bufferEnd, &bufferAlloced, streamData);
+ }
+ }
+ lin = lin->prev;
+ }
+
+ // ### RTF END
+ if (streamData->bRedraw)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\par}");
+ else
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "}");
+ return buffer;
+}
+
+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 = lstrlenA(lstrdat->buffer);
+ }
+
+ // give the RTF to the RE control
+ *pcb = min(cb, lstrdat->bufferLen - lstrdat->bufferOffset);
+ CopyMemory(pbBuff, lstrdat->buffer + lstrdat->bufferOffset, *pcb);
+ lstrdat->bufferOffset += *pcb;
+
+ // free stuff if the streaming operation is complete
+ if (lstrdat->bufferOffset == lstrdat->bufferLen) {
+ mir_free(lstrdat->buffer);
+ lstrdat->buffer = NULL;
+ }
+ }
+
+ return 0;
+}
+
+void Log_StreamInEvent(HWND hwndDlg, LOGINFO* lin, SESSION_INFO* si, BOOL bRedraw, BOOL bPhaseTwo)
+{
+ EDITSTREAM stream;
+ LOGSTREAMDATA streamData;
+ CHARRANGE oldsel, sel, newsel;
+ POINT point = {0};
+ SCROLLINFO scroll;
+ WPARAM wp;
+ HWND hwndRich;
+ TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ if (hwndDlg == 0 || lin == 0 || si == 0 || dat == 0)
+ return;
+
+ hwndRich = GetDlgItem(hwndDlg, IDC_CHAT_LOG);
+ ZeroMemory(&streamData, sizeof(LOGSTREAMDATA));
+ streamData.hwnd = hwndRich;
+ streamData.si = si;
+ streamData.lin = lin;
+ streamData.bStripFormat = FALSE;
+ streamData.dat = dat;
+
+ // bPhaseTwo = bRedraw && bPhaseTwo;
+
+ if (bRedraw || si->iType != GCW_CHATROOM || !si->bFilterEnabled || (si->iLogFilterFlags&lin->iType) != 0) {
+ BOOL bFlag = FALSE, fDoReplace;
+
+ ZeroMemory(&stream, sizeof(stream));
+ stream.pfnCallback = Log_StreamCallback;
+ stream.dwCookie = (DWORD_PTR) & streamData;
+ scroll.cbSize = sizeof(SCROLLINFO);
+ scroll.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
+ GetScrollInfo(GetDlgItem(hwndDlg, IDC_CHAT_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
+ wp = bRedraw ? SF_RTF : SFF_SELECTION | SF_RTF;
+
+ //get the number of pixels per logical inch
+ if (bRedraw) {
+ HDC hdc;
+ hdc = GetDC(NULL);
+ logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY);
+ 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);
+
+
+ //SendMessage(hwndRich, EM_EXGETSEL, (WPARAM)0, (LPARAM)&newsel);
+ /*
+ * 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)));
+
+
+ /*
+ * use mathmod to replace formulas
+ */
+ if (g_Settings.MathMod && fDoReplace) {
+ TMathRicheditInfo mathReplaceInfo;
+ CHARRANGE mathNewSel;
+ mathNewSel.cpMin = sel.cpMin;
+
+ if (mathNewSel.cpMin < 0)
+ mathNewSel.cpMin = 0;
+
+ mathNewSel.cpMax = -1;
+
+ mathReplaceInfo.hwndRichEditControl = hwndRich;
+
+ if (!bRedraw)
+ mathReplaceInfo.sel = &mathNewSel;
+ else
+ mathReplaceInfo.sel = 0;
+
+ mathReplaceInfo.disableredraw = TRUE;
+ CallService(MATH_RTF_REPLACE_FORMULAE, 0, (LPARAM)&mathReplaceInfo);
+ bFlag = TRUE;
+ }
+
+ /*
+ * replace marked nicknames with hyperlinks to make the nicks
+ * clickable
+ */
+
+ if (g_Settings.ClickableNicks) {
+ CHARFORMAT2 cf2;
+ FINDTEXTEX fi, fi2;
+
+ ZeroMemory(&cf2, sizeof(CHARFORMAT2));
+ fi2.lpstrText = _T("#++~~");
+ fi.chrg.cpMin = bRedraw ? 0 : sel.cpMin;
+ fi.chrg.cpMax = -1;
+ fi.lpstrText = _T("~~++#");
+ cf2.cbSize = sizeof(cf2);
+
+ 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)_T(""));
+ 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)_T(""));
+ 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) {
+ SMADD_RICHEDIT3 sm = {0};
+
+ newsel.cpMax = -1;
+ newsel.cpMin = sel.cpMin;
+ if (newsel.cpMin < 0)
+ newsel.cpMin = 0;
+ ZeroMemory(&sm, sizeof(sm));
+ sm.cbSize = 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->wasTrimmed) {
+ TCHAR szPattern[50];
+ FINDTEXTEX fi;
+
+ mir_sntprintf(szPattern, SIZEOF(szPattern), _T("~-+%d+-~"), si->pLogEnd);
+ fi.lpstrText = szPattern;
+ fi.chrg.cpMin = 0;
+ fi.chrg.cpMax = -1;
+ if (SendMessage(hwndRich, EM_FINDTEXTEX, FR_DOWN, (LPARAM)&fi) != 0) {
+ CHARRANGE sel;
+ sel.cpMin = 0;
+ sel.cpMax = 20;
+ SendMessage(hwndRich, EM_SETSEL, 0, fi.chrgText.cpMax + 1);
+ SendMessage(hwndRich, EM_REPLACESEL, TRUE, (LPARAM)_T(""));
+ }
+ si->wasTrimmed = 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);
+ }
+ }
+}
+
+char * Log_CreateRtfHeader(MODULEINFO * mi)
+{
+ char *buffer;
+ int bufferAlloced, bufferEnd, i = 0;
+
+ // guesstimate amount of memory for the RTF header
+ bufferEnd = 0;
+ bufferAlloced = 4096;
+ buffer = (char *) mir_realloc(mi->pszHeader, bufferAlloced);
+ buffer[0] = '\0';
+
+
+ //get the number of pixels per logical inch
+ if (logPixelSY == 0) {
+ HDC hdc;
+ hdc = GetDC(NULL);
+ logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY);
+ logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX);
+ ReleaseDC(NULL, hdc);
+ }
+
+ // ### RTF HEADER
+
+ // font table
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "{\\rtf1\\ansi\\deff0{\\fonttbl");
+ for (i=0; i < OPTIONS_FONTCOUNT ; i++)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "{\\f%u\\fnil\\fcharset%u" TCHAR_STR_PARAM ";}", i, aFonts[i].lf.lfCharSet, aFonts[i].lf.lfFaceName);
+
+ // colour table
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "}{\\colortbl ;");
+
+ for (i=0; i < OPTIONS_FONTCOUNT; i++)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(aFonts[i].color), GetGValue(aFonts[i].color), GetBValue(aFonts[i].color));
+
+ for (i=0; i < mi->nColorCount; i++)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(mi->crColors[i]), GetGValue(mi->crColors[i]), GetBValue(mi->crColors[i]));
+
+ for (i=0; i < 5; i++)
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(g_Settings.nickColors[i]), GetGValue(g_Settings.nickColors[i]), GetBValue(g_Settings.nickColors[i]));
+
+ // new paragraph
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "}\\pard\\sl%d", 1000);
+
+ // set tabs and indents
+ {
+ int iIndent = 0;
+
+ if (g_Settings.LogSymbols) {
+ TCHAR szString[2];
+ LOGFONT lf;
+ HFONT hFont;
+ int iText;
+
+ szString[1] = 0;
+ szString[0] = 0x28;
+ LoadMsgDlgFont(FONTSECTION_CHAT, 17, &lf, NULL, CHAT_FONTMODULE);
+ hFont = CreateFontIndirect(&lf);
+ iText = GetTextPixelSize(szString, hFont, TRUE) + 3;
+ DeleteObject(hFont);
+ iIndent += (iText * 1440) / logPixelSX;
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\tx%u", iIndent);
+ } else if (g_Settings.dwIconFlags) {
+ iIndent += ((g_Settings.ScaleIcons ? 14 : 20) * 1440) / logPixelSX;
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\tx%u", iIndent);
+ }
+ if (g_Settings.ShowTime) {
+ int iSize = (g_Settings.LogTextIndent * 1440) / logPixelSX;
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\tx%u", iIndent + iSize);
+ if (g_Settings.LogIndentEnabled)
+ iIndent += iSize;
+ }
+ Log_Append(&buffer, &bufferEnd, &bufferAlloced, "\\fi-%u\\li%u", iIndent, iIndent);
+ }
+ return buffer;
+}
+
+#define RTFPICTHEADERMAXSIZE 78
+void LoadMsgLogBitmaps(void)
+{
+ HICON hIcon;
+ HBITMAP hBmp, hoBmp;
+ HDC hdc, hdcMem;
+ BITMAPINFOHEADER bih = { 0 };
+ int widthBytes, i;
+ RECT rc;
+ HBRUSH hBkgBrush;
+ int rtfHeaderSize;
+ PBYTE pBmpBits;
+ int iIconSize;
+ int sizeX = 0, sizeY = 0;
+
+ if (hIcons[0])
+ Utils::getIconSize(hIcons[0], sizeX, sizeY);
+ else
+ sizeX = 16;
+
+ if (sizeX >= 12)
+ iIconSize = g_Settings.ScaleIcons ? 12 : 16;
+ else
+ iIconSize = sizeX;
+
+ hBkgBrush = CreateSolidBrush(M->GetDword(FONTMODULE, SRMSGSET_BKGCOLOUR_MUC, SRMSGDEFSET_BKGCOLOUR));
+ bih.biSize = sizeof(bih);
+ bih.biBitCount = 24;
+ bih.biCompression = BI_RGB;
+ bih.biHeight = iIconSize;
+ bih.biPlanes = 1;
+ bih.biWidth = iIconSize;
+ widthBytes = ((bih.biWidth * bih.biBitCount + 31) >> 5) * 4;
+ rc.top = rc.left = 0;
+ rc.right = iIconSize;
+ rc.bottom = iIconSize;
+ hdc = GetDC(NULL);
+ hBmp = CreateCompatibleBitmap(hdc, bih.biWidth, bih.biHeight);
+ hdcMem = CreateCompatibleDC(hdc);
+ pBmpBits = (PBYTE) mir_alloc(widthBytes * bih.biHeight);
+ for (i=0; i < SIZEOF(pLogIconBmpBits); i++) {
+ hIcon = hIcons[i];
+ pLogIconBmpBits[i] = (PBYTE) mir_alloc(RTFPICTHEADERMAXSIZE + (bih.biSize + widthBytes * bih.biHeight) * 2);
+ rtfHeaderSize = sprintf((char *)pLogIconBmpBits[i], "{\\pict\\dibitmap0\\wbmbitspixel%u\\wbmplanes1\\wbmwidthbytes%u\\picw%u\\pich%u ", bih.biBitCount, widthBytes, bih.biWidth, bih.biHeight);
+ hoBmp = (HBITMAP) SelectObject(hdcMem, hBmp);
+ FillRect(hdcMem, &rc, hBkgBrush);
+ DrawIconEx(hdcMem, 0, 1, hIcon, iIconSize, iIconSize, 0, NULL, DI_NORMAL);
+
+ SelectObject(hdcMem, hoBmp);
+ GetDIBits(hdc, hBmp, 0, bih.biHeight, pBmpBits, (BITMAPINFO *) & bih, DIB_RGB_COLORS);
+ {
+ int n;
+ for (n = 0; n < sizeof(BITMAPINFOHEADER); n++)
+ sprintf((char *)pLogIconBmpBits[i] + rtfHeaderSize + n * 2, "%02X", ((PBYTE) & bih)[n]);
+ for (n = 0; n < widthBytes * bih.biHeight; n += 4)
+ sprintf((char *)pLogIconBmpBits[i] + rtfHeaderSize + (bih.biSize + n) * 2, "%02X%02X%02X%02X", pBmpBits[n], pBmpBits[n + 1], pBmpBits[n + 2], pBmpBits[n + 3]);
+ }
+ logIconBmpSize[i] = rtfHeaderSize + (bih.biSize + widthBytes * bih.biHeight) * 2 + 1;
+ pLogIconBmpBits[i][logIconBmpSize[i] - 1] = '}';
+ }
+ mir_free(pBmpBits);
+ DeleteDC(hdcMem);
+ DeleteObject(hBmp);
+ ReleaseDC(NULL, hdc);
+ DeleteObject(hBkgBrush);
+
+ /* cache RTF font headers */
+
+ //get the number of pixels per logical inch
+ if (logPixelSY == 0) {
+ HDC hdc;
+ hdc = GetDC(NULL);
+ logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY);
+ logPixelSX = GetDeviceCaps(hdc, LOGPIXELSX);
+ ReleaseDC(NULL, hdc);
+ }
+
+ for (i=0; i < OPTIONS_FONTCOUNT; i++)
+ mir_snprintf(CHAT_rtfFontsGlobal[i], RTFCACHELINESIZE, "\\f%u\\cf%u\\ul0\\highlight0\\b%d\\i%d\\ul%d\\fs%u", i, i + 1, aFonts[i].lf.lfWeight >= FW_BOLD ? 1 : 0, aFonts[i].lf.lfItalic,aFonts[i].lf.lfUnderline ,2 * abs(aFonts[i].lf.lfHeight) * 74 / logPixelSY);
+ CHAT_rtffonts = &(CHAT_rtfFontsGlobal[0][0]);
+}
+
+void FreeMsgLogBitmaps(void)
+{
+ int i;
+ for (i=0; i < SIZEOF(pLogIconBmpBits); i++)
+ mir_free(pLogIconBmpBits[i]);
+}
diff --git a/plugins/TabSRMM/src/chat/main.cpp b/plugins/TabSRMM/src/chat/main.cpp
new file mode 100644
index 0000000000..56489a2fc9
--- /dev/null
+++ b/plugins/TabSRMM/src/chat/main.cpp
@@ -0,0 +1,142 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda NG, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: main.cpp 13132 2010-11-17 03:47:44Z silvercircle $
+ *
+ * chat module exports and functions to load/unload the plugin.
+ *
+ */
+
+#include "..\commonheaders.h"
+
+HANDLE g_hWindowList;
+HMENU g_hMenu = NULL;
+
+FONTINFO aFonts[OPTIONS_FONTCOUNT];
+HICON hIcons[30];
+HBRUSH hListBkgBrush = NULL;
+
+TMUCSettings g_Settings;
+
+TCHAR *pszActiveWndID = 0;
+char *pszActiveWndModule = 0;
+
+/*
+ * load the group chat module
+ */
+
+int Chat_Load()
+{
+ if (M->GetByte("forceDisableMUC", 0)) {
+ PluginConfig.m_chat_enabled = false;
+ return 0;
+ }
+ g_hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU));
+ if (CreateServiceFunctions()) {
+ HookEvents();
+ CreateHookableEvents();
+ OptionsInit();
+ }
+ return 0;
+}
+
+/*
+ * unload the module. final cleanup
+ */
+
+int Chat_Unload(void)
+{
+ if (!PluginConfig.m_chat_enabled)
+ return 0;
+
+ DBWriteContactSettingWord(NULL, "Chat", "SplitterX", (WORD)g_Settings.iSplitterX);
+ DBWriteContactSettingWord(NULL, "Chat", "splitY", (WORD)g_Settings.iSplitterY);
+
+ CList_SetAllOffline(TRUE, NULL);
+
+ mir_free(pszActiveWndID);
+ mir_free(pszActiveWndModule);
+
+ DestroyMenu(g_hMenu);
+ DestroyServiceFunctions();
+ DestroyHookableEvents();
+ FreeIcons();
+ OptionsUnInit();
+ UnhookEvents();
+ return 0;
+}
+
+void LoadLogIcons(void)
+{
+ ZeroMemory(hIcons, sizeof(HICON) * (ICON_STATUS5 - ICON_ACTION));
+ hIcons[ICON_ACTION] = LoadIconEx(IDI_ACTION, "log_action", 16, 16);
+ hIcons[ICON_ADDSTATUS] = LoadIconEx(IDI_ADDSTATUS, "log_addstatus", 16, 16);
+ hIcons[ICON_HIGHLIGHT] = LoadIconEx(IDI_HIGHLIGHT, "log_highlight", 16, 16);
+ hIcons[ICON_INFO] = LoadIconEx(IDI_INFO, "log_info", 16, 16);
+ hIcons[ICON_JOIN] = LoadIconEx(IDI_JOIN, "log_join", 16, 16);
+ hIcons[ICON_KICK] = LoadIconEx(IDI_KICK, "log_kick", 16, 16);
+ hIcons[ICON_MESSAGE] = LoadIconEx(IDI_MESSAGE, "log_message_in", 16, 16);
+ hIcons[ICON_MESSAGEOUT] = LoadIconEx(IDI_MESSAGEOUT, "log_message_out", 16, 16);
+ hIcons[ICON_NICK] = LoadIconEx(IDI_NICK, "log_nick", 16, 16);
+ hIcons[ICON_NOTICE] = LoadIconEx(IDI_NOTICE, "log_notice", 16, 16);
+ hIcons[ICON_PART] = LoadIconEx(IDI_PART, "log_part", 16, 16);
+ hIcons[ICON_QUIT] = LoadIconEx(IDI_QUIT, "log_quit", 16, 16);
+ hIcons[ICON_REMSTATUS] = LoadIconEx(IDI_REMSTATUS, "log_removestatus", 16, 16);
+ hIcons[ICON_TOPIC] = LoadIconEx(IDI_TOPIC, "log_topic", 16, 16);
+ hIcons[ICON_STATUS1] = LoadIconEx(IDI_STATUS1, "status1", 16, 16);
+ hIcons[ICON_STATUS2] = LoadIconEx(IDI_STATUS2, "status2", 16, 16);
+ hIcons[ICON_STATUS3] = LoadIconEx(IDI_STATUS3, "status3", 16, 16);
+ hIcons[ICON_STATUS4] = LoadIconEx(IDI_STATUS4, "status4", 16, 16);
+ hIcons[ICON_STATUS0] = LoadIconEx(IDI_STATUS0, "status0", 16, 16);
+ hIcons[ICON_STATUS5] = LoadIconEx(IDI_STATUS5, "status5", 16, 16);
+
+ return;
+}
+
+void LoadIcons(void)
+{
+ int i;
+
+ for (i=0; i < 20; i++)
+ hIcons[i] = NULL;
+
+ LoadLogIcons();
+ g_Settings.hIconOverlay = LoadIconEx(IDI_OVERLAY, "overlay", 16, 16);
+ LoadMsgLogBitmaps();
+ return ;
+}
+
+void FreeIcons(void)
+{
+ FreeMsgLogBitmaps();
+ return;
+}
diff --git a/plugins/TabSRMM/src/chat/manager.cpp b/plugins/TabSRMM/src/chat/manager.cpp
new file mode 100644
index 0000000000..0dfa59a470
--- /dev/null
+++ b/plugins/TabSRMM/src/chat/manager.cpp
@@ -0,0 +1,1544 @@
+/*
+astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ --pad=oper --one-line=keep-blocks --unpad=paren
+
+Chat module plugin for Miranda NG
+
+Copyright (C) 2003 Jörgen Persson
+
+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.
+
+$Id: manager.cpp 14208 2012-03-26 13:56:42Z silvercircle $
+*/
+
+#include "..\commonheaders.h"
+
+extern TCHAR *pszActiveWndID ;
+extern char *pszActiveWndModule ;
+extern HICON hIcons[30];
+
+#define WINDOWS_COMMANDS_MAX 30
+#define STATUSICONCOUNT 6
+
+SESSION_INFO *m_WndList = 0;
+MODULEINFO *m_ModList = 0;
+
+extern CRITICAL_SECTION cs;
+
+void SetActiveSession(const TCHAR* pszID, const char* pszModule)
+{
+ SESSION_INFO* si = SM_FindSession(pszID, pszModule);
+ if (si)
+ SetActiveSessionEx(si);
+}
+
+void SetActiveSessionEx(SESSION_INFO* si)
+{
+ if (si) {
+ replaceStr(&pszActiveWndID, si->ptszID);
+ replaceStrA(&pszActiveWndModule, si->pszModule);
+ }
+}
+
+SESSION_INFO* GetActiveSession(void)
+{
+ SESSION_INFO* si = SM_FindSession(pszActiveWndID, pszActiveWndModule);
+ if (si)
+ return si;
+
+ return m_WndList;
+}
+
+//---------------------------------------------------
+// Session Manager functions
+//
+// Keeps track of all sessions and its windows
+//---------------------------------------------------
+
+SESSION_INFO* SM_AddSession(const TCHAR* pszID, const char* pszModule)
+{
+ if (!pszID || !pszModule)
+ return NULL;
+
+ if (!SM_FindSession(pszID, pszModule)) {
+ SESSION_INFO*node = (SESSION_INFO*) mir_alloc(sizeof(SESSION_INFO));
+ ZeroMemory(node, sizeof(SESSION_INFO));
+ node->ptszID = mir_tstrdup(pszID);
+ node->pszModule = mir_strdup(pszModule);
+
+ MODULEINFO *mi = MM_FindModule(pszModule);
+
+ if (mi) {
+ mi->idleTimeStamp = time(0);
+ SM_BroadcastMessage(pszModule, GC_UPDATESTATUSBAR, 0, 1, TRUE);
+ }
+
+ if (m_WndList == NULL) { // list is empty
+ m_WndList = node;
+ node->next = NULL;
+ } else {
+ node->next = m_WndList;
+ m_WndList = node;
+ }
+ node->Highlight = g_Settings.Highlight;
+ return node;
+ }
+ return NULL;
+}
+
+int SM_RemoveSession(const TCHAR* pszID, const char* pszModule, bool removeContact)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID && pTemp->iType != GCW_SERVER || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) { // match
+ COMMAND_INFO *pCurComm;
+ DWORD dw = pTemp->dwItemData;
+
+ if (pTemp->hWnd)
+ SendMessage(pTemp->hWnd, GC_EVENT_CONTROL + WM_USER + 500, SESSION_TERMINATE, 0);
+
+ DoEventHook(pTemp->ptszID, pTemp->pszModule, GC_SESSION_TERMINATE, NULL, NULL, (DWORD)pTemp->dwItemData);
+
+ if (pLast == NULL)
+ m_WndList = pTemp->next;
+ else
+ pLast->next = pTemp->next;
+
+ UM_RemoveAll(&pTemp->pUsers);
+ TM_RemoveAll(&pTemp->pStatuses);
+ LM_RemoveAll(&pTemp->pLog, &pTemp->pLogEnd);
+ pTemp->iStatusCount = 0;
+ pTemp->nUsersInNicklist = 0;
+
+ if (pTemp->hContact) {
+ CList_SetOffline(pTemp->hContact, pTemp->iType == GCW_CHATROOM ? TRUE : FALSE);
+ //if (pTemp->iType != GCW_SERVER)
+ //DBWriteContactSettingByte(pTemp->hContact, "CList", "Hidden", 1);
+ }
+ DBWriteContactSettingString(pTemp->hContact, pTemp->pszModule , "Topic", "");
+ DBWriteContactSettingString(pTemp->hContact, pTemp->pszModule, "StatusBar", "");
+ DBDeleteContactSetting(pTemp->hContact, "CList", "StatusMsg");
+
+ if (removeContact)
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)pTemp->hContact, 0);
+
+ mir_free(pTemp->pszModule);
+ mir_free(pTemp->ptszID);
+ mir_free(pTemp->ptszName);
+ mir_free(pTemp->ptszStatusbarText);
+ mir_free(pTemp->ptszTopic);
+ mir_free(pTemp->pszID);
+ mir_free(pTemp->pszName);
+
+ // delete commands
+ pCurComm = pTemp->lpCommands;
+ while (pCurComm != NULL) {
+ COMMAND_INFO *pNext = pCurComm->next;
+ mir_free(pCurComm->lpCommand);
+ mir_free(pCurComm);
+ pCurComm = pNext;
+ }
+
+ mir_free(pTemp);
+ if (pszID)
+ return (int)dw;
+ if (pLast)
+ pTemp = pLast->next;
+ else
+ pTemp = m_WndList;
+ } else {
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ }
+ return FALSE;
+}
+
+SESSION_INFO* SM_FindSession(const TCHAR* pszID, const char* pszModule)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule))
+ return pTemp;
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return NULL;
+}
+
+BOOL SM_SetOffline(const TCHAR* pszID, const char* pszModule)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ UM_RemoveAll(&pTemp->pUsers);
+ pTemp->nUsersInNicklist = 0;
+ if (pTemp->iType != GCW_SERVER)
+ pTemp->bInitDone = FALSE;
+
+ if (pszID)
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+BOOL SM_SetStatusEx(const TCHAR* pszID, const char* pszModule, const TCHAR* pszText, int flags)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ UM_SetStatusEx(pTemp->pUsers, pszText, flags);
+ if (pTemp->hWnd)
+ RedrawWindow(GetDlgItem(pTemp->hWnd, IDC_LIST), NULL, NULL, RDW_INVALIDATE);
+ if (pszID)
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+HICON SM_GetStatusIcon(SESSION_INFO* si, USERINFO* ui, char *szIndicator)
+{
+ STATUSINFO * ti;
+ if (!ui || !si)
+ return NULL;
+
+ *szIndicator = 0;
+
+ ti = TM_FindStatus(si->pStatuses, TM_WordToString(si->pStatuses, ui->Status));
+ if (ti) {
+ if ((INT_PTR)ti->hIcon < STATUSICONCOUNT) {
+ int id = si->iStatusCount - (int)ti->hIcon - 1;
+ if (id == 0) {
+ *szIndicator = 0;
+ return hIcons[ICON_STATUS0];
+ }
+ if (id == 1) {
+ *szIndicator = '+';
+ return hIcons[ICON_STATUS1];
+ }
+ if (id == 2) {
+ *szIndicator = '%';
+ return hIcons[ICON_STATUS2];
+ }
+ if (id == 3) {
+ *szIndicator = '@';
+ return hIcons[ICON_STATUS3];
+ }
+ if (id == 4) {
+ *szIndicator = '!';
+ return hIcons[ICON_STATUS4];
+ }
+ if (id == 5) {
+ *szIndicator = '*';
+ return hIcons[ICON_STATUS5];
+ }
+ } else
+ return ti->hIcon;
+ }
+ return hIcons[ICON_STATUS0];
+}
+
+BOOL SM_AddEventToAllMatchingUID(GCEVENT * gce, BOOL bIsHighLight)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+ int bManyFix = 0;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpiA(pTemp->pszModule, gce->pDest->pszModule)) {
+ if (UM_FindUser(pTemp->pUsers, gce->ptszUID)) {
+ if (pTemp->bInitDone) {
+ if (SM_AddEvent(pTemp->ptszID, pTemp->pszModule, gce, FALSE) && pTemp->hWnd && pTemp->bInitDone) {
+ SendMessage(pTemp->hWnd, GC_ADDLOG, 0, 0);
+ } else if (pTemp->hWnd && pTemp->bInitDone) {
+ SendMessage(pTemp->hWnd, GC_REDRAWLOG2, 0, 0);
+ }
+ DoSoundsFlashPopupTrayStuff(pTemp, gce, bIsHighLight, bManyFix);
+ bManyFix ++;
+ if ((gce->dwFlags & GCEF_ADDTOLOG) && g_Settings.LoggingEnabled)
+ LogToFile(pTemp, gce);
+ }
+ }
+ }
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ return 0;
+}
+
+BOOL SM_AddEvent(const TCHAR* pszID, const char* pszModule, GCEVENT * gce, BOOL bIsHighlighted)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return TRUE;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ LOGINFO * li = LM_AddEvent(&pTemp->pLog, &pTemp->pLogEnd);
+ pTemp->iEventCount += 1;
+
+ li->iType = gce->pDest->iType;
+ li->ptszNick = mir_tstrdup(gce->ptszNick);
+ li->ptszText = mir_tstrdup(gce->ptszText);
+ li->ptszStatus = mir_tstrdup(gce->ptszStatus);
+ li->ptszUserInfo = mir_tstrdup(gce->ptszUserInfo);
+
+ li->bIsMe = gce->bIsMe;
+ li->time = gce->time;
+ li->bIsHighlighted = bIsHighlighted;
+
+ if (g_Settings.iEventLimit > 0 && pTemp->iEventCount > g_Settings.iEventLimit + g_Settings.iEventLimitThreshold) {
+ LM_TrimLog(&pTemp->pLog, &pTemp->pLogEnd, pTemp->iEventCount - g_Settings.iEventLimit);
+ pTemp->wasTrimmed = TRUE;
+ pTemp->iEventCount = g_Settings.iEventLimit;
+ }
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+USERINFO * SM_AddUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszNick, WORD wStatus)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ USERINFO * p = UM_AddUser(pTemp->pStatuses, &pTemp->pUsers, pszUID, pszNick, wStatus);
+ pTemp->nUsersInNicklist++;
+ return p;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ return 0;
+}
+
+BOOL SM_MoveUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID)
+{
+ SESSION_INFO* pTemp = m_WndList;
+
+ if (!pszID || !pszModule || !pszUID)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ UM_SortUser(&pTemp->pUsers, pszUID);
+ return TRUE;
+ }
+ pTemp = pTemp->next;
+ }
+
+ return FALSE;
+}
+
+BOOL SM_RemoveUser(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule || !pszUID)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ DWORD dw;
+ USERINFO * ui = UM_FindUser(pTemp->pUsers, pszUID);
+ if (ui) {
+ pTemp->nUsersInNicklist--;
+
+ dw = UM_RemoveUser(&pTemp->pUsers, pszUID);
+
+ if (pTemp->hWnd)
+ SendMessage(pTemp->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0);
+
+ if (pszID)
+ return TRUE;
+ }
+ }
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ return 0;
+}
+
+USERINFO * SM_GetUserFromIndex(const TCHAR* pszID, const char* pszModule, int index)
+{
+ SESSION_INFO* pTemp = m_WndList;
+
+ if (!pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule))
+ return UM_FindUserFromIndex(pTemp->pUsers, index);
+ pTemp = pTemp->next;
+ }
+
+ return NULL;
+}
+
+
+STATUSINFO * SM_AddStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszStatus)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ STATUSINFO* ti = TM_AddStatus(&pTemp->pStatuses, pszStatus, &pTemp->iStatusCount);
+ if (ti)
+ pTemp->iStatusCount++;
+ return ti;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ return 0;
+}
+
+BOOL SM_GiveStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszStatus)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ USERINFO * ui = UM_GiveStatus(pTemp->pUsers, pszUID, TM_StringToWord(pTemp->pStatuses, pszStatus));
+ if (ui) {
+ SM_MoveUser(pTemp->ptszID, pTemp->pszModule, ui->pszUID);
+ if (pTemp->hWnd)
+ SendMessage(pTemp->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0);
+ }
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ return FALSE;
+}
+
+BOOL SM_SetContactStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, WORD wStatus)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ USERINFO * ui = UM_SetContactStatus(pTemp->pUsers, pszUID, wStatus);
+ if (ui) {
+ SM_MoveUser(pTemp->ptszID, pTemp->pszModule, ui->pszUID);
+ if (pTemp->hWnd)
+ SendMessage(pTemp->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0);
+ }
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ return FALSE;
+}
+
+BOOL SM_TakeStatus(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszStatus)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ USERINFO* ui = UM_TakeStatus(pTemp->pUsers, pszUID, TM_StringToWord(pTemp->pStatuses, pszStatus));
+ if (ui) {
+ SM_MoveUser(pTemp->ptszID, pTemp->pszModule, ui->pszUID);
+ if (pTemp->hWnd)
+ SendMessage(pTemp->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0);
+ }
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ return FALSE;
+}
+LRESULT SM_SendMessage(const TCHAR* pszID, const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ while (pTemp && pszModule) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ if (pTemp->hWnd) {
+ LRESULT i = SendMessage(pTemp->hWnd, msg, wParam, lParam);
+ if (pszID)
+ return i;
+ }
+ if (pszID)
+ return 0;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+BOOL SM_PostMessage(const TCHAR* pszID, const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszID || !pszModule)
+ return 0;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->ptszID, pszID) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ if (pTemp->hWnd)
+ return PostMessage(pTemp->hWnd, msg, wParam, lParam);
+
+ return FALSE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return FALSE;
+}
+
+BOOL SM_BroadcastMessage(const char* pszModule, UINT msg, WPARAM wParam, LPARAM lParam, BOOL bAsync)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ while (pTemp != NULL) {
+ if (!pszModule || !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ if (pTemp->hWnd) {
+ if (bAsync)
+ PostMessage(pTemp->hWnd, msg, wParam, lParam);
+ else
+ SendMessage(pTemp->hWnd, msg, wParam, lParam);
+ }
+
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+BOOL SM_ReconfigureFilters()
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ while (pTemp != NULL) {
+ Chat_SetFilters(pTemp);
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+BOOL SM_InvalidateLogDirectories()
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ EnterCriticalSection(&cs);
+
+ while (pTemp != NULL) {
+ pTemp->pszLogFileName[0] = 0;
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ LeaveCriticalSection(&cs);
+ return TRUE;
+}
+
+BOOL SM_SetStatus(const TCHAR* pszID, const char* pszModule, int wStatus)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ pTemp->wStatus = wStatus;
+
+ if (pTemp->hContact) {
+ if (pTemp->iType != GCW_SERVER && wStatus != ID_STATUS_OFFLINE)
+ DBDeleteContactSetting(pTemp->hContact, "CList", "Hidden");
+
+ DBWriteContactSettingWord(pTemp->hContact, pTemp->pszModule, "Status", (WORD)wStatus);
+ }
+
+ if (pszID)
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+BOOL SM_SendUserMessage(const TCHAR* pszID, const char* pszModule, const TCHAR* pszText)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule || !pszText)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ if (pTemp->iType == GCW_CHATROOM)
+ DoEventHook(pTemp->ptszID, pTemp->pszModule, GC_USER_MESSAGE, NULL, pszText, (LPARAM)NULL);
+ if (pszID)
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+BOOL SM_ChangeUID(const TCHAR* pszID, const char* pszModule, const TCHAR* pszUID, const TCHAR* pszNewUID)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ USERINFO* ui = UM_FindUser(pTemp->pUsers, pszUID);
+ if (ui)
+ replaceStr(&ui->pszUID, pszNewUID);
+
+ if (pszID)
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+BOOL SM_ChangeNick(const TCHAR* pszID, const char* pszModule, GCEVENT * gce)
+{
+ SESSION_INFO* pTemp = m_WndList, *pLast = NULL;
+
+ if (!pszModule)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if ((!pszID || !lstrcmpi(pTemp->ptszID, pszID)) && !lstrcmpiA(pTemp->pszModule, pszModule)) {
+ USERINFO* ui = UM_FindUser(pTemp->pUsers, gce->ptszUID);
+ if (ui) {
+ replaceStr(&ui->pszNick, gce->ptszText);
+ SM_MoveUser(pTemp->ptszID, pTemp->pszModule, ui->pszUID);
+ if (pTemp->hWnd) {
+ SendMessage(pTemp->hWnd, GC_UPDATENICKLIST, 0, 0);
+ if (pTemp->dat)
+ GetMyNick(pTemp->dat);
+ SendMessage(pTemp->hWnd, GC_UPDATESTATUSBAR, 0, 0);
+ }
+ }
+ if (pszID)
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+BOOL SM_RemoveAll(void)
+{
+ while (m_WndList) {
+ SESSION_INFO*pLast = m_WndList->next;
+
+ if (m_WndList->hWnd)
+ SendMessage(m_WndList->hWnd, GC_EVENT_CONTROL + WM_USER + 500, SESSION_TERMINATE, 0);
+ DoEventHook(m_WndList->ptszID, m_WndList->pszModule, GC_SESSION_TERMINATE, NULL, NULL, (DWORD)m_WndList->dwItemData);
+ if (m_WndList->hContact)
+ CList_SetOffline(m_WndList->hContact, m_WndList->iType == GCW_CHATROOM ? TRUE : FALSE);
+ DBWriteContactSettingString(m_WndList->hContact, m_WndList->pszModule , "Topic", "");
+ DBDeleteContactSetting(m_WndList->hContact, "CList", "StatusMsg");
+ DBWriteContactSettingString(m_WndList->hContact, m_WndList->pszModule, "StatusBar", "");
+
+ UM_RemoveAll(&m_WndList->pUsers);
+ TM_RemoveAll(&m_WndList->pStatuses);
+ LM_RemoveAll(&m_WndList->pLog, &m_WndList->pLogEnd);
+ m_WndList->iStatusCount = 0;
+ m_WndList->nUsersInNicklist = 0;
+
+ mir_free(m_WndList->pszModule);
+ mir_free(m_WndList->ptszID);
+ mir_free(m_WndList->ptszName);
+ mir_free(m_WndList->ptszStatusbarText);
+ mir_free(m_WndList->ptszTopic);
+
+ while (m_WndList->lpCommands != NULL) {
+ COMMAND_INFO *pNext = m_WndList->lpCommands->next;
+ mir_free(m_WndList->lpCommands->lpCommand);
+ mir_free(m_WndList->lpCommands);
+ m_WndList->lpCommands = pNext;
+ }
+
+ mir_free(m_WndList);
+ m_WndList = pLast;
+ }
+ m_WndList = NULL;
+ return TRUE;
+}
+
+void SM_AddCommand(const TCHAR* pszID, const char* pszModule, const char* lpNewCommand)
+{
+ SESSION_INFO* pTemp = m_WndList;
+ while (pTemp != NULL) {
+ if (lstrcmpi(pTemp->ptszID, pszID) == 0 && lstrcmpiA(pTemp->pszModule, pszModule) == 0) { // match
+ COMMAND_INFO *node = (COMMAND_INFO *)mir_alloc(sizeof(COMMAND_INFO));
+ node->lpCommand = mir_strdup(lpNewCommand);
+ node->last = NULL; // always added at beginning!
+ // new commands are added at start
+ if (pTemp->lpCommands == NULL) {
+ node->next = NULL;
+ pTemp->lpCommands = node;
+ } else {
+ node->next = pTemp->lpCommands;
+ pTemp->lpCommands->last = node; // hmm, weird
+ pTemp->lpCommands = node;
+ }
+ pTemp->lpCurrentCommand = NULL; // current command
+ pTemp->wCommandsNum++;
+
+ if (pTemp->wCommandsNum > WINDOWS_COMMANDS_MAX) {
+ COMMAND_INFO *pCurComm = pTemp->lpCommands;
+ COMMAND_INFO *pLast;
+ while (pCurComm->next != NULL) {
+ pCurComm = pCurComm->next;
+ }
+ pLast = pCurComm->last;
+ mir_free(pCurComm->lpCommand);
+ mir_free(pCurComm);
+ pLast->next = NULL;
+ // done
+ pTemp->wCommandsNum--;
+ }
+ }
+ pTemp = pTemp->next;
+ }
+}
+
+char* SM_GetPrevCommand(const TCHAR* pszID, const char* pszModule) // get previous command. returns NULL if previous command does not exist. current command remains as it was.
+{
+ SESSION_INFO* pTemp = m_WndList;
+ while (pTemp != NULL) {
+ if (lstrcmpi(pTemp->ptszID, pszID) == 0 && lstrcmpiA(pTemp->pszModule, pszModule) == 0) { // match
+ COMMAND_INFO *pPrevCmd = NULL;
+ if (pTemp->lpCurrentCommand != NULL) {
+ if (pTemp->lpCurrentCommand->next != NULL) // not NULL
+ pPrevCmd = pTemp->lpCurrentCommand->next; // next command (newest at beginning)
+ else
+ pPrevCmd = pTemp->lpCurrentCommand;
+ } else pPrevCmd = pTemp->lpCommands;
+
+ pTemp->lpCurrentCommand = pPrevCmd; // make it the new command
+ return(((pPrevCmd) ? (pPrevCmd->lpCommand) : (NULL)));
+ }
+ pTemp = pTemp->next;
+ }
+ return(NULL);
+}
+
+char* SM_GetNextCommand(const TCHAR* pszID, const char* pszModule) // get next command. returns NULL if next command does not exist. current command becomes NULL (a prev command after this one will get you the last command)
+{
+ SESSION_INFO* pTemp = m_WndList;
+ while (pTemp != NULL) {
+ if (lstrcmpi(pTemp->ptszID, pszID) == 0 && lstrcmpiA(pTemp->pszModule, pszModule) == 0) { // match
+ COMMAND_INFO *pNextCmd = NULL;
+ if (pTemp->lpCurrentCommand != NULL)
+ pNextCmd = pTemp->lpCurrentCommand->last; // last command (newest at beginning)
+
+ pTemp->lpCurrentCommand = pNextCmd; // make it the new command
+ return(((pNextCmd) ? (pNextCmd->lpCommand) : (NULL)));
+ }
+ pTemp = pTemp->next;
+ }
+ return(NULL);
+}
+
+int SM_GetCount(const char* pszModule)
+{
+ SESSION_INFO* pTemp = m_WndList;
+ int count = 0;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpiA(pszModule, pTemp->pszModule))
+ count++;
+
+ pTemp = pTemp->next;
+ }
+ return count;
+}
+
+SESSION_INFO* SM_FindSessionByHWND(HWND hWnd)
+{
+ SESSION_INFO *pTemp = m_WndList;
+
+ while (pTemp) {
+ if (pTemp->hWnd == hWnd)
+ return pTemp;
+ pTemp = pTemp->next;
+ }
+ return NULL;
+}
+
+SESSION_INFO * SM_FindSessionByHCONTACT(HANDLE h)
+{
+ SESSION_INFO *pTemp = m_WndList;
+
+ while (pTemp) {
+ if (pTemp->hContact == h)
+ return pTemp;
+ pTemp = pTemp->next;
+ }
+ return NULL;
+}
+
+SESSION_INFO* SM_FindSessionByIndex(const char* pszModule, int iItem)
+{
+ SESSION_INFO* pTemp = m_WndList;
+ int count = 0;
+ while (pTemp != NULL) {
+ if (!lstrcmpiA(pszModule, pTemp->pszModule)) {
+ if (iItem == count)
+ return pTemp;
+ else
+ count++;
+ }
+
+ pTemp = pTemp->next;
+ }
+ return NULL;
+
+}
+
+SESSION_INFO* SM_FindSessionAutoComplete(const char* pszModule, SESSION_INFO* currSession, SESSION_INFO* prevSession, const TCHAR* pszOriginal, const TCHAR* pszCurrent)
+{
+ SESSION_INFO* pResult = NULL;
+ if (prevSession == NULL && my_strstri(currSession->ptszName, pszOriginal) == currSession->ptszName) {
+ pResult = currSession;
+ } else {
+ TCHAR* pszName = NULL;
+ SESSION_INFO* pTemp = m_WndList;
+ if (currSession == prevSession) {
+ pszCurrent = pszOriginal;
+ }
+ while (pTemp != NULL) {
+ if (pTemp != currSession && !lstrcmpiA(pszModule, pTemp->pszModule)) {
+ if (my_strstri(pTemp->ptszName, pszOriginal) == pTemp->ptszName) {
+ if (prevSession != pTemp && lstrcmpi(pTemp->ptszName, pszCurrent) > 0 && (!pszName || lstrcmpi(pTemp->ptszName, pszName) < 0)) {
+ pResult = pTemp;
+ pszName = pTemp->ptszName;
+ }
+ }
+ }
+ pTemp = pTemp->next;
+ }
+ }
+ return pResult;
+
+}
+
+char* SM_GetUsers(SESSION_INFO* si)
+{
+ SESSION_INFO* pTemp = m_WndList;
+ USERINFO* utemp;
+ int count = 0;
+ char* p = NULL;
+ int alloced = 0;
+
+ if (si == NULL)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (si == pTemp) {
+ if ((utemp = pTemp->pUsers) == NULL)
+ return NULL;
+
+ break;
+ }
+ pTemp = pTemp->next;
+ }
+
+ do {
+ int pLen = lstrlenA(p), nameLen = lstrlen(utemp->pszUID);
+ if (pLen + nameLen + 2 > alloced)
+ p = (char *)mir_realloc(p, alloced += 4096);
+ WideCharToMultiByte(CP_ACP, 0, utemp->pszUID, -1, p + pLen, nameLen + 1, 0, 0);
+ lstrcpyA(p + pLen + nameLen, " ");
+ utemp = utemp->next;
+ } while (utemp != NULL);
+ return p;
+}
+
+
+
+
+
+
+//---------------------------------------------------
+// Module Manager functions
+//
+// Necessary to keep track of all modules
+// that has registered with the plugin
+//---------------------------------------------------
+
+MODULEINFO* MM_AddModule(const char* pszModule)
+{
+ if (!pszModule)
+ return NULL;
+ if (!MM_FindModule(pszModule)) {
+ MODULEINFO *node = (MODULEINFO*) mir_alloc(sizeof(MODULEINFO));
+ ZeroMemory(node, sizeof(MODULEINFO));
+
+ node->pszModule = (char*)mir_alloc(lstrlenA(pszModule) + 1);
+ lstrcpyA(node->pszModule, pszModule);
+ node->idleTimeStamp = time(0);
+ if (m_ModList == NULL) { // list is empty
+ m_ModList = node;
+ node->next = NULL;
+ } else {
+ node->next = m_ModList;
+ m_ModList = node;
+ }
+ return node;
+ }
+ return FALSE;
+}
+
+/*
+void MM_IconsChanged(void)
+{
+ MODULEINFO *pTemp = m_ModList, *pLast = NULL;
+ while (pTemp != NULL) {
+ if (pTemp->hOfflineIcon)
+ DestroyIcon(pTemp->hOfflineIcon);
+ if (pTemp->hOnlineIcon)
+ DestroyIcon(pTemp->hOnlineIcon);
+ if (pTemp->hOnlineTalkIcon)
+ DestroyIcon(pTemp->hOnlineTalkIcon);
+ if (pTemp->hOfflineTalkIcon)
+ DestroyIcon(pTemp->hOfflineTalkIcon);
+
+ pTemp->hOfflineIcon = ImageList_GetIcon(hIconsList, pTemp->OfflineIconIndex, ILD_TRANSPARENT);
+ pTemp->hOnlineIcon = ImageList_GetIcon(hIconsList, pTemp->OnlineIconIndex, ILD_TRANSPARENT);
+
+ pTemp->hOnlineTalkIcon = ImageList_GetIcon(hIconsList, pTemp->OnlineIconIndex, ILD_TRANSPARENT|INDEXTOOVERLAYMASK(1));
+ ImageList_ReplaceIcon(hIconsList, pTemp->OnlineIconIndex+1, pTemp->hOnlineTalkIcon);
+
+ pTemp->hOfflineTalkIcon = ImageList_GetIcon(hIconsList, pTemp->OfflineIconIndex, ILD_TRANSPARENT|INDEXTOOVERLAYMASK(1));
+ ImageList_ReplaceIcon(hIconsList, pTemp->OfflineIconIndex+1, pTemp->hOfflineTalkIcon);
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return;
+}
+*/
+
+void MM_FontsChanged(void)
+{
+ MODULEINFO *pTemp = m_ModList;
+ while (pTemp != NULL) {
+ pTemp->pszHeader = Log_CreateRtfHeader(pTemp);
+ pTemp = pTemp->next;
+ }
+ return;
+}
+MODULEINFO* MM_FindModule(const char* pszModule)
+{
+ MODULEINFO *pTemp = m_ModList, *pLast = NULL;
+
+ if (!pszModule)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (lstrcmpiA(pTemp->pszModule, pszModule) == 0)
+ return pTemp;
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+// stupid thing..
+void MM_FixColors()
+{
+ MODULEINFO *pTemp = m_ModList;
+
+ while (pTemp != NULL) {
+ CheckColorsInModule(pTemp->pszModule);
+ pTemp = pTemp->next;
+ }
+ return;
+}
+
+BOOL MM_RemoveAll(void)
+{
+ while (m_ModList != NULL) {
+ MODULEINFO *pLast = m_ModList->next;
+ mir_free(m_ModList->pszModule);
+ mir_free(m_ModList->ptszModDispName);
+ if (m_ModList->pszHeader)
+ mir_free(m_ModList->pszHeader);
+ mir_free(m_ModList->crColors);
+
+ mir_free(m_ModList);
+ m_ModList = pLast;
+ }
+ m_ModList = NULL;
+ return TRUE;
+}
+
+//---------------------------------------------------
+// Status manager functions
+//
+// Necessary to keep track of what user statuses
+// per window nicklist that is available
+//---------------------------------------------------
+
+STATUSINFO * TM_AddStatus(STATUSINFO** ppStatusList, const TCHAR* pszStatus, int* iCount)
+{
+ if (!ppStatusList || !pszStatus)
+ return NULL;
+
+ if (!TM_FindStatus(*ppStatusList, pszStatus)) {
+ STATUSINFO *node = (STATUSINFO*) mir_alloc(sizeof(STATUSINFO));
+ ZeroMemory(node, sizeof(STATUSINFO));
+ replaceStr(&node->pszGroup, pszStatus);
+ node->hIcon = (HICON)(*iCount);
+ while ((int)node->hIcon > STATUSICONCOUNT - 1)
+ node->hIcon--;
+
+ if (*ppStatusList == NULL) { // list is empty
+ node->Status = 1;
+ *ppStatusList = node;
+ node->next = NULL;
+ } else {
+ node->Status = ppStatusList[0]->Status * 2;
+ node->next = *ppStatusList;
+ *ppStatusList = node;
+ }
+ return node;
+
+ }
+ return FALSE;
+}
+
+STATUSINFO * TM_FindStatus(STATUSINFO* pStatusList, const TCHAR* pszStatus)
+{
+ STATUSINFO *pTemp = pStatusList, *pLast = NULL;
+
+ if (!pStatusList || !pszStatus)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (lstrcmpi(pTemp->pszGroup, pszStatus) == 0)
+ return pTemp;
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+WORD TM_StringToWord(STATUSINFO* pStatusList, const TCHAR* pszStatus)
+{
+ STATUSINFO *pTemp = pStatusList, *pLast = NULL;
+
+ if (!pStatusList || !pszStatus)
+ return 0;
+
+ while (pTemp != NULL) {
+ if (lstrcmpi(pTemp->pszGroup, pszStatus) == 0)
+ return pTemp->Status;
+
+ if (pTemp->next == NULL)
+ return pStatusList->Status;
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+TCHAR* TM_WordToString(STATUSINFO* pStatusList, WORD Status)
+{
+ STATUSINFO *pTemp = pStatusList, *pLast = NULL;
+
+ if (!pStatusList)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (pTemp->Status&Status) {
+ Status -= pTemp->Status;
+ if (Status == 0)
+ return pTemp->pszGroup;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+BOOL TM_RemoveAll(STATUSINFO** ppStatusList)
+{
+
+ if (!ppStatusList)
+ return FALSE;
+
+ while (*ppStatusList != NULL) {
+ STATUSINFO *pLast = ppStatusList[0]->next;
+ mir_free(ppStatusList[0]->pszGroup);
+ if ((int)ppStatusList[0]->hIcon > 10)
+ DestroyIcon(ppStatusList[0]->hIcon);
+ mir_free(*ppStatusList);
+ *ppStatusList = pLast;
+ }
+ *ppStatusList = NULL;
+ return TRUE;
+}
+
+//---------------------------------------------------
+// User manager functions
+//
+// Necessary to keep track of the users
+// in a window nicklist
+//---------------------------------------------------
+
+//MAD: alternative sorting by Nullbie
+static int sttCompareNicknames(const TCHAR *s1, const TCHAR *s2)
+{
+ // skip rubbish
+ while (*s1 && !_istalpha(*s1)) ++s1;
+ while (*s2 && !_istalpha(*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 lstrcmpi(s1, s2);
+}
+//
+
+static int UM_CompareItem(USERINFO * u1, const TCHAR* pszNick, WORD wStatus)
+{
+ int i;
+
+ WORD dw1 = u1->Status;
+ WORD dw2 = wStatus;
+
+ for (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.AlternativeSorting)
+ return sttCompareNicknames(u1->pszNick, pszNick);
+ else
+ return lstrcmp(u1->pszNick, pszNick);
+ }//
+ dw1 = dw1 >> 1;
+ dw2 = dw2 >> 1;
+ }
+ if (g_Settings.AlternativeSorting)
+ //
+ return sttCompareNicknames(u1->pszNick, pszNick);
+ else
+ return lstrcmp(u1->pszNick, pszNick);
+ //
+}
+
+USERINFO * UM_SortUser(USERINFO** ppUserList, const TCHAR* pszUID)
+{
+ USERINFO * pTemp = *ppUserList, *pLast = NULL;
+ USERINFO * node = NULL;
+
+ if (!pTemp || !pszUID)
+ return NULL;
+
+ while (pTemp && lstrcmpi(pTemp->pszUID, pszUID)) {
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ if (pTemp) {
+ node = pTemp;
+ if (pLast)
+ pLast->next = pTemp->next;
+ else
+ *ppUserList = pTemp->next;
+ pTemp = *ppUserList;
+
+ pLast = NULL;
+
+ while (pTemp && UM_CompareItem(pTemp, node->pszNick, node->Status) <= 0) {
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ if (*ppUserList == NULL) { // list is empty
+ *ppUserList = node;
+ node->next = NULL;
+ } else {
+ if (pLast) {
+ node->next = pTemp;
+ pLast->next = node;
+ } else {
+ node->next = *ppUserList;
+ *ppUserList = node;
+ }
+ }
+
+ return node;
+ }
+ return NULL;
+}
+
+USERINFO* UM_AddUser(STATUSINFO* pStatusList, USERINFO** ppUserList, const TCHAR* pszUID, const TCHAR* pszNick, WORD wStatus)
+{
+ USERINFO * pTemp = *ppUserList, *pLast = NULL;
+
+ if (!pStatusList || !ppUserList || !ppUserList)
+ return NULL;
+
+ while (pTemp && UM_CompareItem(pTemp, pszNick, wStatus) <= 0) {
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+
+ // if (!UM_FindUser(*ppUserList, pszUI, wStatus)
+ {
+ USERINFO *node = (USERINFO*) mir_alloc(sizeof(USERINFO));
+ ZeroMemory(node, sizeof(USERINFO));
+ replaceStr(&node->pszUID, pszUID);
+
+ if (*ppUserList == NULL) { // list is empty
+ *ppUserList = node;
+ node->next = NULL;
+ } else {
+ if (pLast) {
+ node->next = pTemp;
+ pLast->next = node;
+ } else {
+ node->next = *ppUserList;
+ *ppUserList = node;
+ }
+ }
+
+ return node;
+ }
+ return NULL;
+}
+
+USERINFO* UM_FindUser(USERINFO* pUserList, const TCHAR* pszUID)
+{
+ USERINFO *pTemp = pUserList, *pLast = NULL;
+
+ if (!pUserList || !pszUID)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->pszUID, pszUID))
+ return pTemp;
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+USERINFO* UM_FindUserFromIndex(USERINFO* pUserList, int index)
+{
+ int i = 0;
+ USERINFO *pTemp = pUserList;
+
+ if (!pUserList)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (i == index) {
+ return pTemp;
+ }
+ pTemp = pTemp->next;
+ i++;
+ }
+ return NULL;
+}
+
+USERINFO* UM_GiveStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status)
+{
+ USERINFO *pTemp = pUserList, *pLast = NULL;
+
+ if (!pUserList || !pszUID)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->pszUID, pszUID)) {
+ pTemp->Status |= status;
+ return pTemp;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+USERINFO* UM_SetContactStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status)
+{
+ USERINFO *pTemp = pUserList, *pLast = NULL;
+
+ if (!pUserList || !pszUID)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->pszUID, pszUID)) {
+ pTemp->ContactStatus = status;
+ return pTemp;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+BOOL UM_SetStatusEx(USERINFO* pUserList, const TCHAR* pszText, int flags)
+{
+ USERINFO *pTemp = pUserList, *pLast = NULL;
+ int bOnlyMe = (flags & GC_SSE_ONLYLISTED) != 0, bSetStatus = (flags & GC_SSE_ONLINE) != 0;
+ char cDelimiter = (flags & GC_SSE_TABDELIMITED) ? '\t' : ' ';
+
+ while (pTemp != NULL) {
+ if (!bOnlyMe)
+ pTemp->iStatusEx = 0;
+
+ if (pszText != NULL) {
+ TCHAR* s = (TCHAR *)_tcsstr(pszText, pTemp->pszUID);
+ if (s) {
+ pTemp->iStatusEx = 0;
+ if (s == pszText || s[-1] == cDelimiter) {
+ int len = lstrlen(pTemp->pszUID);
+ if (s[len] == cDelimiter || s[len] == '\0')
+ pTemp->iStatusEx = (!bOnlyMe || bSetStatus) ? 1 : 0;
+ }
+ }
+ }
+
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+USERINFO* UM_TakeStatus(USERINFO* pUserList, const TCHAR* pszUID, WORD status)
+{
+ USERINFO *pTemp = pUserList, *pLast = NULL;
+
+ if (!pUserList || !pszUID)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->pszUID, pszUID)) {
+ pTemp->Status &= ~status;
+ return pTemp;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return 0;
+}
+
+TCHAR* UM_FindUserAutoComplete(USERINFO* pUserList, const TCHAR* pszOriginal, const TCHAR* pszCurrent)
+{
+ TCHAR* pszName = NULL;
+ USERINFO *pTemp = pUserList;
+
+ if (!pUserList || !pszOriginal || !pszCurrent)
+ return NULL;
+
+ while (pTemp != NULL) {
+ if (my_strstri(pTemp->pszNick, pszOriginal) == pTemp->pszNick)
+ if (lstrcmpi(pTemp->pszNick, pszCurrent) > 0 && (!pszName || lstrcmpi(pTemp->pszNick, pszName) < 0))
+ pszName = pTemp->pszNick;
+
+ pTemp = pTemp->next;
+ }
+ return pszName;
+}
+
+BOOL UM_RemoveUser(USERINFO** ppUserList, const TCHAR* pszUID)
+{
+ USERINFO *pTemp = *ppUserList, *pLast = NULL;
+
+ if (!ppUserList || !pszUID)
+ return FALSE;
+
+ while (pTemp != NULL) {
+ if (!lstrcmpi(pTemp->pszUID, pszUID)) {
+ if (pLast == NULL)
+ *ppUserList = pTemp->next;
+ else
+ pLast->next = pTemp->next;
+ mir_free(pTemp->pszNick);
+ mir_free(pTemp->pszUID);
+ mir_free(pTemp);
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return FALSE;
+}
+
+BOOL UM_RemoveAll(USERINFO** ppUserList)
+{
+ if (!ppUserList)
+ return FALSE;
+
+ while (*ppUserList != NULL) {
+ USERINFO *pLast = ppUserList[0]->next;
+ mir_free(ppUserList[0]->pszUID);
+ mir_free(ppUserList[0]->pszNick);
+ mir_free(*ppUserList);
+ *ppUserList = pLast;
+ }
+ *ppUserList = NULL;
+ return TRUE;
+}
+
+//---------------------------------------------------
+// Log manager functions
+//
+// Necessary to keep track of events
+// in a window log
+//---------------------------------------------------
+
+LOGINFO * LM_AddEvent(LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd)
+{
+
+ LOGINFO *node = NULL;
+
+ if (!ppLogListStart || !ppLogListEnd)
+ return NULL;
+
+ node = (LOGINFO*) mir_alloc(sizeof(LOGINFO));
+ ZeroMemory(node, sizeof(LOGINFO));
+
+
+ if (*ppLogListStart == NULL) { // list is empty
+ *ppLogListStart = node;
+ *ppLogListEnd = node;
+ node->next = NULL;
+ node->prev = NULL;
+ } else {
+ ppLogListStart[0]->prev = node;
+ node->next = *ppLogListStart;
+ *ppLogListStart = node;
+ ppLogListStart[0]->prev = NULL;
+ }
+
+ return node;
+}
+
+BOOL LM_TrimLog(LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd, int iCount)
+{
+ LOGINFO *pTemp = *ppLogListEnd;
+ while (pTemp != NULL && iCount > 0) {
+ *ppLogListEnd = pTemp->prev;
+ if (*ppLogListEnd == NULL)
+ *ppLogListStart = NULL;
+
+ mir_free(pTemp->ptszNick);
+ mir_free(pTemp->ptszUserInfo);
+ mir_free(pTemp->ptszText);
+ mir_free(pTemp->ptszStatus);
+ mir_free(pTemp);
+ pTemp = *ppLogListEnd;
+ iCount--;
+ }
+ ppLogListEnd[0]->next = NULL;
+
+ return TRUE;
+}
+
+BOOL LM_RemoveAll(LOGINFO** ppLogListStart, LOGINFO** ppLogListEnd)
+{
+ while (*ppLogListStart != NULL) {
+ LOGINFO *pLast = ppLogListStart[0]->next;
+ mir_free(ppLogListStart[0]->ptszText);
+ mir_free(ppLogListStart[0]->ptszNick);
+ mir_free(ppLogListStart[0]->ptszStatus);
+ mir_free(ppLogListStart[0]->ptszUserInfo);
+ mir_free(*ppLogListStart);
+ *ppLogListStart = pLast;
+ }
+ *ppLogListStart = NULL;
+ *ppLogListEnd = NULL;
+ return TRUE;
+}
diff --git a/plugins/TabSRMM/src/chat/message.cpp b/plugins/TabSRMM/src/chat/message.cpp
new file mode 100644
index 0000000000..71fbba7276
--- /dev/null
+++ b/plugins/TabSRMM/src/chat/message.cpp
@@ -0,0 +1,341 @@
+/*
+astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ --pad=oper --one-line=keep-blocks --unpad=paren
+
+Chat module plugin for Miranda NG
+
+Copyright (C) 2003 Jörgen Persson
+
+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.
+
+$Id: message.c 10402 2009-07-24 00:35:21Z silvercircle $
+*/
+
+#include "..\commonheaders.h"
+#include <math.h>
+
+static int RTFColorToIndex(int *pIndex, int iCol, SESSION_INFO* si)
+{
+ int i;
+ MODULEINFO * pMod = MM_FindModule(si->pszModule);
+
+ for (i=0; i < pMod->nColorCount ; i++)
+ if (pIndex[i] == iCol)
+ return i;
+
+ return -1;
+}
+
+static void CreateColorMap(char* Text, int *pIndex, SESSION_INFO* si)
+{
+ char *p1, *p2, *pEnd;
+ int iIndex = 1;
+
+ static const char* lpszFmt = "\\red%[^ \x5b\\]\\green%[^ \x5b\\]\\blue%[^ \x5b;];";
+ char szRed[10], szGreen[10], szBlue[10];
+
+ p1 = strstr(Text, "\\colortbl");
+ if (!p1)
+ return;
+
+ pEnd = strchr(p1, '}');
+ p2 = strstr(p1, "\\red");
+
+ while (p2 && p2 < pEnd) {
+ if (sscanf(p2, lpszFmt, &szRed, &szGreen, &szBlue) > 0) {
+ int i;
+ MODULEINFO * pMod = MM_FindModule(si->pszModule);
+ for (i=0; i < pMod->nColorCount ; i ++)
+ if (pMod->crColors[i] == RGB(atoi(szRed), atoi(szGreen), atoi(szBlue)))
+ pIndex[i] = iIndex;
+ }
+ iIndex++;
+ p1 = p2;
+ p1 ++;
+ p2 = strstr(p1, "\\red");
+ }
+}
+
+static int ReadInteger(const char* p, int* result)
+{
+ char temp[10];
+ int i = 0;
+ while (isdigit(*p) && i < 9)
+ temp[i++] = *p++;
+ temp[i] = 0;
+
+ if (result != NULL)
+ *result = atoi(temp);
+
+ return i;
+}
+
+TCHAR* Chat_DoRtfToTags(char* pszText, SESSION_INFO* si)
+{
+ char *p1;
+ int* pIndex;
+ int i, iRemoveChars, cp = CP_ACP;
+ char InsertThis[50];
+ BOOL bJustRemovedRTF = TRUE;
+ BOOL bTextHasStarted = FALSE;
+ TCHAR *ptszResult; //, *d;
+ int iUcMode = 0;
+
+ if (!pszText)
+ return FALSE;
+
+ // create an index of colors in the module and map them to
+ // corresponding colors in the RTF color table
+ pIndex = (int *)mir_alloc(sizeof(int) * MM_FindModule(si->pszModule)->nColorCount);
+ for (i=0; i < MM_FindModule(si->pszModule)->nColorCount ; i++)
+ pIndex[i] = -1;
+
+ CreateColorMap(pszText, pIndex, si);
+
+ // scan the file for rtf commands and remove or parse them
+ p1 = strstr(pszText, "\\pard");
+ if (p1 == NULL) {
+ mir_free(pIndex);
+ return FALSE;
+ }
+
+ p1 += 5;
+
+ MoveMemory(pszText, p1, lstrlenA(p1) + 1);
+ p1 = pszText;
+
+ // iterate through all characters, if rtf control character found then take action
+ while (*p1 != '\0') {
+ InsertThis[0] = 0;
+ iRemoveChars = 0;
+
+ switch (*p1) {
+ case '\\':
+ if (!memcmp(p1, "\\cf", 3)) { // foreground color
+ int iCol, iInd;
+ iRemoveChars = 3 + ReadInteger(p1 + 3, &iCol);
+ iInd = RTFColorToIndex(pIndex, iCol, si);
+ bJustRemovedRTF = TRUE;
+
+ if (bTextHasStarted || iInd >= 0)
+ mir_snprintf(InsertThis, SIZEOF(InsertThis), (iInd >= 0) ? "%%c%02u" : "%%C", iInd);
+ } else if (!memcmp(p1, "\\highlight", 10)) { //background color
+ int iCol, iInd;
+ iRemoveChars = 10 + ReadInteger(p1 + 10, &iCol);
+ iInd = RTFColorToIndex(pIndex, iCol, si);
+ bJustRemovedRTF = TRUE;
+
+ if (bTextHasStarted || iInd >= 0)
+ mir_snprintf(InsertThis, SIZEOF(InsertThis), (iInd >= 0) ? "%%f%02u" : "%%F", iInd);
+ } else if (!memcmp(p1, "\\lang", 5)) { // language id
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = 5 + ReadInteger(p1 + 5, NULL);
+ } else if (!memcmp(p1, "\\par", 4)) { // newline
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = 4;
+ strcpy(InsertThis, "\n");
+ } else if (!memcmp(p1, "\\endash", 7)) {
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = 7;
+ strcpy(InsertThis, "\xE2\x80\x93");
+ } else if (!memcmp(p1, "\\emdash", 7)) {
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = 7;
+ strcpy(InsertThis, "\xE2\x80\x94");
+ } else if (!memcmp(p1, "\\bullet", 7)) {
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = 7;
+ strcpy(InsertThis, "\xE2\x80\xA2");
+ } else if (!memcmp(p1, "\\line", 5)) { // newline
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = 5;
+ strcpy(InsertThis, "\n");
+ } else if (!memcmp(p1, "\\b", 2)) { //bold
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = (p1[2] != '0') ? 2 : 3;
+ strcpy(InsertThis, (p1[2] != '0') ? "%b" : "%B");
+ } else if (!memcmp(p1, "\\i", 2)) { // italics
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = (p1[2] != '0') ? 2 : 3;
+ strcpy(InsertThis, (p1[2] != '0') ? "%i" : "%I");
+ } else if (!memcmp(p1, "\\uc", 3)) { // number of Unicode chars
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iUcMode = p1[3] - '0';
+ iRemoveChars = 4;
+ } else if (!memcmp(p1, "\\ul", 3)) { // underlined
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ if (p1[3] == 'n')
+ iRemoveChars = 7;
+ else if (p1[3] == '0')
+ iRemoveChars = 4;
+ else
+ iRemoveChars = 3;
+ mir_snprintf(InsertThis, SIZEOF(InsertThis), (p1[3] != '0' && p1[3] != 'n') ? "%%u" : "%%U");
+ } else if (p1[1] == 'f' && isdigit(p1[2])) { // unicode char
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = 2 + ReadInteger(p1 + 2, NULL);
+ } else if (p1[1] == '\\' || p1[1] == '{' || p1[1] == '}') { // escaped characters
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = FALSE;
+ iRemoveChars = 2;
+ mir_snprintf(InsertThis, SIZEOF(InsertThis), "%c", p1[1]);
+ } else if (p1[1] == '~') { // non-breaking space
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = FALSE;
+ iRemoveChars = 2;
+ strcpy(InsertThis, "\xC2\xA0");
+ }
+
+
+ else if (!memcmp(p1, "\\tab",4)) { // tab
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 4;
+ strcpy(InsertThis, "\x09");
+ }
+ else if (!memcmp(p1, "\\ldblquote",10)) {
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 10;
+ strcpy(InsertThis, "\xe2\x80\x9c");
+ }
+ else if (!memcmp(p1, "\\rdblquote",10)) {
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 10;
+ strcpy(InsertThis, "\xe2\x80\x9d");
+ }
+ else if (!memcmp(p1, "\\lquote",7)) {
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 7;
+ strcpy(InsertThis, "\xE2\x80\x98");
+ }
+ else if (!memcmp(p1, "\\rquote",7)) {
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 7;
+ strcpy(InsertThis, "\xE2\x80\x99");
+ }
+
+ else if (p1[1] == '\'') { // special character
+ char tmp[4], *p3 = tmp;
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = FALSE;
+ if (p1[2] != ' ' && p1[2] != '\\') {
+ *p3++ = p1[2];
+ iRemoveChars = 3;
+ if (p1[3] != ' ' && p1[3] != '\\') {
+ *p3++ = p1[3];
+ iRemoveChars++;
+ }
+ *p3 = 0;
+ sscanf(tmp, "%x", InsertThis);
+
+ InsertThis[1] = 0;
+ } else iRemoveChars = 2;
+ } else if (bJustRemovedRTF) { // remove unknown RTF command
+ int j = 1;
+ bJustRemovedRTF = TRUE;
+ while (p1[j] != ' ' && p1[j] != '\\' && p1[j] != '\0')
+ j++;
+ iRemoveChars = j;
+ }
+ break;
+
+ case '{': // other RTF control characters
+ case '}':
+ iRemoveChars = 1;
+ break;
+
+ case '\r': case '\n':
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = FALSE;
+ iRemoveChars = 1;
+ break;
+
+ case '%': // escape chat -> protocol control character
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = FALSE;
+ iRemoveChars = 1;
+ strcpy(InsertThis, "%%");
+ break;
+ case ' ': // remove spaces following a RTF command
+ if (bJustRemovedRTF)
+ iRemoveChars = 1;
+ bJustRemovedRTF = FALSE;
+ bTextHasStarted = TRUE;
+ break;
+
+ default: // other text that should not be touched
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = FALSE;
+ break;
+ }
+
+ // move the memory and paste in new commands instead of the old RTF
+ if (InsertThis[0] || iRemoveChars) {
+ MoveMemory(p1 + lstrlenA(InsertThis) , p1 + iRemoveChars, lstrlenA(p1) - iRemoveChars + 1);
+ CopyMemory(p1, InsertThis, lstrlenA(InsertThis));
+ p1 += lstrlenA(InsertThis);
+ } else p1++;
+ }
+
+ mir_free(pIndex);
+ ptszResult = mir_utf8decodeW(pszText);
+ return ptszResult;
+}
+
+static DWORD CALLBACK Chat_Message_StreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb)
+{
+ static DWORD dwRead;
+ char ** ppText = (char **) dwCookie;
+
+ if (*ppText == NULL) {
+ *ppText = (char *)mir_alloc(cb + 1);
+ memcpy(*ppText, pbBuff, cb);
+ (*ppText)[cb] = 0;
+ *pcb = cb;
+ dwRead = cb;
+ } else {
+ char *p = (char *)mir_alloc(dwRead + cb + 1);
+ memcpy(p, *ppText, dwRead);
+ memcpy(p + dwRead, pbBuff, cb);
+ p[dwRead + cb] = 0;
+ mir_free(*ppText);
+ *ppText = p;
+ *pcb = cb;
+ dwRead += cb;
+ }
+ return 0;
+}
+
+char* Chat_Message_GetFromStream(HWND hwndDlg, SESSION_INFO* si)
+{
+ EDITSTREAM stream;
+ char* pszText = NULL;
+ DWORD dwFlags;
+
+ if (hwndDlg == 0 || si == 0)
+ return NULL;
+
+ ZeroMemory(&stream, sizeof(stream));
+ stream.pfnCallback = Chat_Message_StreamCallback;
+ stream.dwCookie = (DWORD_PTR) & pszText; // pass pointer to pointer
+
+ dwFlags = SF_RTFNOOBJS | SFF_PLAINRTF | SF_USECODEPAGE | (CP_UTF8 << 16);
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), EM_STREAMOUT, dwFlags, (LPARAM) & stream);
+ return pszText; // pszText contains the text
+}
diff --git a/plugins/TabSRMM/src/chat/muchighlight.cpp b/plugins/TabSRMM/src/chat/muchighlight.cpp
new file mode 100644
index 0000000000..7b05b5b81b
--- /dev/null
+++ b/plugins/TabSRMM/src/chat/muchighlight.cpp
@@ -0,0 +1,427 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: muchighlight.cpp 13184 2010-12-07 14:16:58Z silvercircle $
+ *
+ * highlighter class for multi user chats
+ *
+ */
+
+#include "..\commonheaders.h"
+
+//#define __HLT_PERFSTATS 0
+
+void CMUCHighlight::cleanup()
+{
+ if (m_NickPatternString)
+ mir_free(m_NickPatternString);
+ if (m_TextPatternString)
+ mir_free(m_TextPatternString);
+
+ m_TextPatternString = m_NickPatternString = 0;
+
+ if (m_NickPatterns)
+ mir_free(m_NickPatterns);
+ if (m_TextPatterns)
+ 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 == M->GetTString(0, "Chat", "HighlightWords", &dbv)) {
+ m_TextPatternString = dbv.ptszVal;
+ _wsetlocale(LC_ALL, L"");
+ wcslwr(m_TextPatternString);
+ }
+
+ if (0 == M->GetTString(0, "Chat", "HighlightNames", &dbv))
+ m_NickPatternString = dbv.ptszVal;
+
+ m_dwFlags = M->GetByte("Chat", "HighlightEnabled", MATCH_TEXT);
+ m_fHighlightMe = (M->GetByte("Chat", "HighlightMe", 1) ? true : false);
+
+ __try {
+ tokenize(m_TextPatternString, m_TextPatterns, m_iTextPatterns);
+ tokenize(m_NickPatternString, m_NickPatterns, m_iNickPatterns);
+ }
+ __except(CGlobals::Ex_ShowDialog(GetExceptionInformation(), __FILE__, __LINE__, L"MUC_HLT_TOKENIZER", false)) {
+ m_Valid = false;
+ }
+}
+
+void CMUCHighlight::tokenize(TCHAR *tszString, TCHAR**& patterns, UINT& nr)
+{
+ if (tszString == 0)
+ return;
+
+ TCHAR *p = tszString;
+
+ if (*p == 0)
+ return;
+
+ nr = 0;
+
+ if (*p != ' ')
+ nr++;
+
+ while(*p) {
+ if (*p == ' ') {
+ p++;
+ while(*p && _istspace(*p))
+ p++;
+ if (*p)
+ nr++;
+ }
+ p++;
+ }
+ patterns = (TCHAR **)mir_alloc(nr * sizeof(TCHAR *));
+
+ p = tszString;
+ nr = 0;
+
+ if (*p != ' ')
+ patterns[nr++] = p;
+
+ while(*p) {
+ if (*p == ' ') {
+ *p++ = 0;
+ while(*p && _istspace(*p))
+ p++;
+ if (*p)
+ patterns[nr++] = p;
+ }
+ p++;
+ }
+}
+
+int CMUCHighlight::match(const GCEVENT *pgce, const SESSION_INFO *psi, DWORD dwFlags)
+{
+ int result = 0, nResult = 0;
+
+ if (pgce == 0 || m_Valid == false)
+ return 0;
+
+ __try {
+ if ((m_dwFlags & MATCH_TEXT) && (dwFlags & MATCH_TEXT) && (m_fHighlightMe || m_iTextPatterns > 0) && psi != 0) {
+ #ifdef __HLT_PERFSTATS
+ int words = 0;
+ M->startTimer();
+ #endif
+ TCHAR *tszCleaned = ::RemoveFormatting(pgce->ptszText, true, true);
+ TCHAR *p = tszCleaned;
+ TCHAR *p1;
+ UINT i = 0;
+
+ TCHAR *tszMe = ((psi && psi->pMe) ? mir_tstrdup(psi->pMe->pszNick) : 0);
+ if (tszMe) {
+ _wsetlocale(LC_ALL, L"");
+ wcslwr(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) {
+ p1 = p;
+ while(*p1 && *p1 != ' ' && *p1 != ',' && *p1 != '.' && *p1 != ':' && *p1 != ';' && *p1 != '?' && *p1 != '!')
+ p1++;
+
+ if (*p1)
+ *p1 = 0;
+ else
+ p1 = 0;
+
+ for (i=0; i < m_iTextPatterns && !result; i++)
+ result = wildmatch(m_TextPatterns[i], p) ? MATCH_TEXT : 0;
+
+ if (p1) {
+ *p1 = ' ';
+ p = p1 + 1;
+ }
+ else
+ p = 0;
+ #ifdef __HLT_PERFSTATS
+ words++;
+ #endif
+ }
+ else
+ break;
+ }
+skip_textpatterns:
+
+ #ifdef __HLT_PERFSTATS
+ M->stopTimer(0);
+ if (psi && psi->dat) {
+ mir_sntprintf(psi->dat->szStatusBar, 100, _T("PERF text match: %d ticks = %f msec (%d words, %d patterns)"), (int)M->getTicks(), M->getMsec(), words, m_iTextPatterns);
+ if (psi->dat->pContainer->hwndStatus)
+ ::SendMessage(psi->dat->pContainer->hwndStatus, SB_SETTEXT, 0, (LPARAM)psi->dat->szStatusBar);
+ }
+ #endif
+ if (tszMe)
+ mir_free(tszMe);
+ }
+
+ /*
+ * optinally, 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 = wildmatch(m_NickPatterns[i], pgce->ptszNick) ? MATCH_NICKNAME : 0;
+ if ((m_dwFlags & MATCH_UIN) && pgce->ptszUserInfo)
+ nResult = wildmatch(m_NickPatterns[i], pgce->ptszUserInfo) ? MATCH_NICKNAME : 0;
+ }
+ }
+
+ return(result | nResult);
+ }
+ __except(CGlobals::Ex_ShowDialog(GetExceptionInformation(), __FILE__, __LINE__, L"MUC_HIGHLIGHT_EXCEPTION", false)) {
+ m_Valid = false;
+ return 0;
+ }
+ return 0;
+}
+
+int CMUCHighlight::wildmatch(const TCHAR *pattern, const TCHAR *tszString) {
+
+ const TCHAR *cp = 0, *mp = 0;
+
+ while ((*tszString) && (*pattern != '*')) {
+ if ((*pattern != *tszString) && (*pattern != '?')) {
+ return 0;
+ }
+ pattern++;
+ tszString++;
+ }
+
+ while (*tszString) {
+ if (*pattern == '*') {
+ if (!*++pattern)
+ return 1;
+ mp = pattern;
+ cp = tszString + 1;
+ }
+ else if ((*pattern == *tszString) || (*pattern == '?')) {
+ pattern++;
+ tszString++;
+ }
+ else {
+ pattern = mp;
+ tszString = cp++;
+ }
+ }
+
+ while (*pattern == '*')
+ pattern++;
+
+ return(!*pattern);
+}
+
+/**
+ * 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: {
+ DBVARIANT dbv = {0};
+
+ TranslateDialogDefault(hwndDlg);
+
+ if (0 == M->GetTString(0, "Chat", "HighlightWords", &dbv)) {
+ ::SetDlgItemTextW(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN, dbv.ptszVal);
+ ::DBFreeVariant(&dbv);
+ }
+
+ if (0 == M->GetTString(0, "Chat", "HighlightNames", &dbv)) {
+ ::SetDlgItemTextW(hwndDlg, IDC_HIGHLIGHTNICKPATTERN, dbv.ptszVal);
+ ::DBFreeVariant(&dbv);
+ }
+
+ DWORD dwFlags = M->GetByte("Chat", "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", "HighlightMe", 1) ? BST_CHECKED : BST_UNCHECKED);
+
+ ::SendMessageW(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 != (LPARAM)NULL)
+ ::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 = ::GetWindowTextLengthW(::GetDlgItem(hwndDlg, IDC_HIGHLIGHTNICKPATTERN));
+
+ if (iLen) {
+ szBuf = reinterpret_cast<wchar_t *>(mir_alloc((iLen + 2) * sizeof(wchar_t)));
+ ::GetDlgItemTextW(hwndDlg, IDC_HIGHLIGHTNICKPATTERN, szBuf, iLen + 1);
+ M->WriteTString(0, "Chat", "HighlightNames",szBuf);
+ }
+
+ iLen = ::GetWindowTextLengthW(::GetDlgItem(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN));
+ if (iLen) {
+ szBuf = reinterpret_cast<TCHAR *>(mir_realloc(szBuf, sizeof(wchar_t) * (iLen + 2)));
+ ::GetDlgItemTextW(hwndDlg, IDC_HIGHLIGHTTEXTPATTERN, szBuf, iLen + 1);
+ M->WriteTString(0, "Chat", "HighlightWords", szBuf);
+ }
+ else
+ M->WriteTString(0, "Chat", "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);
+
+ M->WriteByte("Chat", "HighlightEnabled", dwFlags);
+ M->WriteByte("Chat", "HighlightMe", ::IsDlgButtonChecked(hwndDlg, IDC_HIGHLIGHTME) ? 1 : 0);
+ g_Settings.Highlight->init();
+ }
+ return TRUE;
+ }
+ default:
+ break;
+ }
+ 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)
+{
+ UINT uCmd = ::GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+
+ switch(msg) {
+ case WM_INITDIALOG: {
+ HFONT hFont = (HFONT)::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTTITLE, WM_GETFONT, 0, 0);
+ LOGFONTW lf = {0};
+
+ THighLightEdit *the = reinterpret_cast<THighLightEdit *>(lParam);
+ ::SetWindowLongPtr(hwndDlg, GWLP_USERDATA, the->uCmd);
+
+ ::GetObject(hFont, sizeof(lf), &lf);
+ lf.lfWeight = FW_BOLD;
+ lf.lfHeight = (int)(lf.lfHeight * 1.2);
+ hFont = ::CreateFontIndirectW(&lf);
+
+ ::SendDlgItemMessage(hwndDlg, IDC_ADDHIGHLIGHTTITLE, WM_SETFONT, (WPARAM)hFont, FALSE);
+ if (the->uCmd == THighLightEdit::CMD_ADD) {
+ Utils::showDlgControl(hwndDlg, IDC_ADDHIGHLIGHTEDITLIST, SW_HIDE);
+ ::SetDlgItemTextW(hwndDlg, IDC_ADDHIGHLIGHTTITLE, TranslateT("Add user to highlight list"));
+ ::SendDlgItemMessageW(hwndDlg, IDC_ADDHIGHLIGHTNAME, CB_INSERTSTRING, -1, (LPARAM)the->ui->pszNick);
+ ::SendDlgItemMessageW(hwndDlg, IDC_ADDHIGHLIGHTNAME, CB_INSERTSTRING, -1, (LPARAM)the->ui->pszUID);
+ ::SendDlgItemMessageW(hwndDlg, IDC_ADDHIGHLIGHTNAME, CB_SETCURSEL, 1, 0);
+ } else {
+ Utils::showDlgControl(hwndDlg, IDC_ADDHIGHLIGHTNAME, SW_HIDE);
+ Utils::showDlgControl(hwndDlg, IDC_ADDHIGHLIGHTEXPLAIN, SW_HIDE);
+ ::SetDlgItemTextW(hwndDlg, IDC_ADDHIGHLIGHTTITLE, TranslateT("Edit user highlight list"));
+ }
+ break;
+ }
+
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ {
+ HWND hwndChild = (HWND)lParam;
+ UINT id = ::GetDlgCtrlID(hwndChild);
+
+ 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
new file mode 100644
index 0000000000..e6e403a040
--- /dev/null
+++ b/plugins/TabSRMM/src/chat/muchighlight.h
@@ -0,0 +1,94 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: muchighlight.h 12299 2010-08-10 02:39:36Z silvercircle $
+ *
+ * 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 ();
+ int 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(TCHAR *tszString, TCHAR**& patterns, UINT& nr);
+ int wildmatch (const TCHAR *pattern, const TCHAR *tszString);
+ DWORD m_dwFlags;
+ bool m_fInitialized;
+ TCHAR** m_NickPatterns;
+ TCHAR** m_TextPatterns;
+ UINT m_iNickPatterns;
+ UINT m_iTextPatterns;
+ TCHAR* m_NickPatternString;
+ TCHAR* 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
new file mode 100644
index 0000000000..9d2fec8b48
--- /dev/null
+++ b/plugins/TabSRMM/src/chat/options.cpp
@@ -0,0 +1,1493 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda NG, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: options.cpp 13412 2011-03-08 19:13:11Z george.hazan $
+ *
+ * group chat options and generic font handling
+ *
+ */
+
+#include "..\commonheaders.h"
+#undef Translate
+
+#define TranslateA(s) ((char*)CallService(MS_LANGPACK_TRANSLATESTRING,0,(LPARAM)(s)))
+#include <shlobj.h>
+#include <shlwapi.h>
+
+extern HBRUSH hListBkgBrush;
+extern HICON hIcons[30];
+extern FONTINFO aFonts[OPTIONS_FONTCOUNT];
+extern HMODULE g_hIconDLL;
+
+extern HIMAGELIST CreateStateImageList();
+
+HANDLE g_hOptions = NULL;
+
+
+#define FONTF_BOLD 1
+#define FONTF_ITALIC 2
+
+struct FontOptionsList {
+ TCHAR* szDescr;
+ COLORREF defColour;
+ TCHAR* szDefFace;
+ BYTE defCharset, defStyle;
+ char defSize;
+ COLORREF colour;
+ TCHAR szFace[LF_FACESIZE];
+ BYTE charset, style;
+ char size;
+};
+
+struct ColorOptionsList {
+ int order;
+ TCHAR* tszGroup;
+ TCHAR* 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, LPGENT("TabSRMM/Group Chats"), LPGENT("Group chat log background"), SRMSGSET_BKGCOLOUR_MUC, SRMSGDEFSET_BKGCOLOUR,
+ 1, LPGENT("TabSRMM"), LPGENT("Input area background"), "inputbg", SRMSGDEFSET_BKGCOLOUR,
+ 2, LPGENT("TabSRMM"), LPGENT("Log background"), SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR,
+ 0, LPGENT("TabSRMM/Single Messaging"), LPGENT("Outgoing background"), "outbg", SRMSGDEFSET_BKGOUTCOLOUR,
+ 1, LPGENT("TabSRMM/Single Messaging"), LPGENT("Incoming background"), "inbg", SRMSGDEFSET_BKGINCOLOUR,
+ 2, LPGENT("TabSRMM/Single Messaging"), LPGENT("Status background"), "statbg", SRMSGDEFSET_BKGCOLOUR,
+ 3, LPGENT("TabSRMM/Single Messaging"), LPGENT("Incoming background(old)"), "oldinbg", SRMSGDEFSET_BKGINCOLOUR,
+ 4, LPGENT("TabSRMM/Single Messaging"), LPGENT("Outgoing background(old)"), "oldoutbg", SRMSGDEFSET_BKGOUTCOLOUR,
+ 5, LPGENT("TabSRMM/Single Messaging"), LPGENT("Horizontal Grid Lines"), "hgrid", RGB(224, 224, 224),
+ 0, LPGENT("TabSRMM/Info Panel"), LPGENT("Panel background low"), "ipfieldsbg", 0x62caff,
+ 1, LPGENT("TabSRMM/Info Panel"), LPGENT("Panel background high"), "ipfieldsbgHigh", 0xf0f0f0,
+ 0, LPGENT("TabSRMM/Common colors"), LPGENT("Toolbar background high"), "tbBgHigh", 0,
+ 1, LPGENT("TabSRMM/Common colors"), LPGENT("Toolbar background low"), "tbBgLow", 0,
+ 2, LPGENT("TabSRMM/Common colors"), LPGENT("Window fill color"), "fillColor", 0,
+ 3, LPGENT("TabSRMM/Common colors"), LPGENT("Text area borders"), "cRichBorders", 0,
+ 4, LPGENT("TabSRMM/Common colors"), LPGENT("Aero glow effect"), "aeroGlow", RGB(40, 40, 255),
+ 4, LPGENT("TabSRMM/Common colors"), LPGENT("Generic text color (only when fill color is set)"), "genericTxtClr", 0xff000000 | COLOR_BTNTEXT,
+};
+
+static ColorOptionsList _tabclrs[] = {
+ 0, LPGENT("TabSRMM/Tabs"), LPGENT("Normal text"), "tab_txt_normal", 0xff000000 | COLOR_BTNTEXT,
+ 1, LPGENT("TabSRMM/Tabs"), LPGENT("Active text"), "tab_txt_active", 0xff000000 | COLOR_BTNTEXT,
+ 2, LPGENT("TabSRMM/Tabs"), LPGENT("Hovered text"), "tab_txt_hottrack", 0xff000000 | COLOR_HOTLIGHT,
+ 3, LPGENT("TabSRMM/Tabs"), LPGENT("Unread text"), "tab_txt_unread", 0xff000000 | COLOR_HOTLIGHT,
+
+ 4, LPGENT("TabSRMM/Tabs"), LPGENT("Normal background"), "tab_bg_normal", 0xff000000 | COLOR_3DFACE,
+ 5, LPGENT("TabSRMM/Tabs"), LPGENT("Active background"), "tab_bg_active", 0xff000000 | COLOR_3DFACE,
+ 6, LPGENT("TabSRMM/Tabs"), LPGENT("Hovered background"), "tab_bg_hottrack", 0xff000000 | COLOR_3DFACE,
+ 7, LPGENT("TabSRMM/Tabs"), LPGENT("Unread background"), "tab_bg_unread", 0xff000000 | COLOR_3DFACE
+};
+
+extern LOGFONT lfDefault;
+
+//remember to put these in the Translate( ) template file too
+static FontOptionsList CHAT_fontOptionsList[] = {
+ {LPGENT("Timestamp"), RGB(50, 50, 240), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Others nicknames"), RGB(0, 0, 192), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT("Your nickname"), RGB(0, 0, 192), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT("User has joined"), RGB(90, 160, 90), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User has left"), RGB(160, 160, 90), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User has disconnected"), RGB(160, 90, 90), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User kicked ..."), RGB(100, 100, 100), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User is now known as ..."), RGB(90, 90, 160), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Notice from user"), RGB(160, 130, 60), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Incoming message"), RGB(90, 90, 90), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Outgoing message"), RGB(90, 90, 90), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("The topic is ..."), RGB(70, 70, 160), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Information messages"), RGB(130, 130, 195), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User enables status for ..."), RGB(70, 150, 70), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User disables status for ..."), RGB(150, 70, 70), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Action message"), RGB(160, 90, 160), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Highlighted message"), RGB(180, 150, 80), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Chat log symbols (Webdings)"), RGB(170, 170, 170), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User list members (Online)"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("User list members (away)"), RGB(170, 170, 170), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+};
+
+const int msgDlgFontCount = SIZEOF(CHAT_fontOptionsList);
+
+static FontOptionsList IM_fontOptionsList[] = {
+ {LPGENT(">> Outgoing messages"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT(">> Outgoing misc events"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("<< Incoming messages"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("<< Incoming misc events"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT(">> Outgoing name"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT(">> Outgoing timestamp"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT("<< Incoming name"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT("<< Incoming timestamp"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT(">> Outgoing messages (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT(">> Outgoing misc events (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("<< Incoming messages (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("<< Incoming misc events (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT(">> Outgoing name (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT(">> Outgoing timestamp (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT("<< Incoming name (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT("<< Incoming timestamp (old)"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, FONTF_BOLD, -12},
+ {LPGENT("* Message Input Area"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("* Status changes"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("* Dividers"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("* Error and warning Messages"), RGB(50, 50, 50), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("* Symbols (incoming)"), RGB(50, 50, 50), _T("Webdings"), SYMBOL_CHARSET, 0, -12},
+ {LPGENT("* Symbols (outgoing)"), RGB(50, 50, 50), _T("Webdings"), SYMBOL_CHARSET, 0, -12},
+};
+
+static FontOptionsList IP_fontOptionsList[] = {
+ {LPGENT("Nickname"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("UIN"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Status"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Protocol"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("Contacts local time"), RGB(0, 0, 0), lfDefault.lfFaceName, DEFAULT_CHARSET, 0, -12},
+ {LPGENT("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 {
+ TCHAR* szDescr;
+ char* szDBName;
+ int iMode;
+ BYTE bDefault;
+ HTREEITEM hItem;
+};
+static struct branch_t branch1[] = {
+ {LPGENT("Open new chat rooms in the default container"), "DefaultContainer", 0, 1, NULL},
+ {LPGENT("Flash window when someone speaks"), "FlashWindow", 0, 0, NULL},
+ {LPGENT("Flash window when a word is highlighted"), "FlashWindowHighlight", 0, 1, NULL},
+//TODO Fix for 3.0 !!!
+
+#if !defined(__DELAYED_FOR_3_1)
+ {LPGENT("Create tabs or windows for highlight events"), "CreateWindowOnHighlight", 0,0, NULL},
+ {LPGENT("Activate chat window on highlight"), "AnnoyingHighlight", 0,0, NULL},
+#endif
+
+ {LPGENT("Show list of users in the chat room"), "ShowNicklist", 0, 1, NULL},
+ {LPGENT("Colorize nicknames in member list"), "ColorizeNicks", 0, 1, NULL},
+ {LPGENT("Show button menus when right clicking the buttons"), "RightClickFilter", 0, 1, NULL},
+ {LPGENT("Show topic as status message on the contact list"), "TopicOnClist", 0, 1, NULL},
+ {LPGENT("Do not pop up the window when joining a chat room"), "PopupOnJoin", 0, 0, NULL},
+ {LPGENT("Hide or show the window by double click in the contact list"), "ToggleVisibility", 0, 0, NULL},
+ {LPGENT("Sync splitter position with standard IM sessions"), "SyncSplitter", 0, 0, NULL},
+ {LPGENT("Show contact's status modes if supported by the protocol"), "ShowContactStatus", 0, 1, NULL},
+ {LPGENT("Display contact's status icon before user role icon"), "ContactStatusFirst", 0, 0, NULL},
+ //MAD: simple customization improvement
+ {LPGENT("Use IRC style status indicators in the user list"), "ClassicIndicators", 0, 0, NULL},
+ {LPGENT("Use alternative sorting method in member list"), "AlternativeSorting", 0, 1, NULL},
+
+};
+static struct branch_t branch2[] = {
+ {LPGENT("Prefix all events with a timestamp"), "ShowTimeStamp", 0, 1, NULL},
+ {LPGENT("Timestamp only when event time differs"), "ShowTimeStampIfChanged", 0, 0, NULL},
+ {LPGENT("Timestamp has same color as the event"), "TimeStampEventColour", 0, 0, NULL},
+ {LPGENT("Indent the second line of a message"), "LogIndentEnabled", 0, 1, NULL},
+ {LPGENT("Limit user names in the message log to 20 characters"), "LogLimitNames", 0, 1, NULL},
+ {LPGENT("Add a colon (:) to auto-completed user names"), "AddColonToAutoComplete", 0, 1, NULL},
+ {LPGENT("Start private conversation on doubleclick in nick list (insert nick if unchecked)"), "DoubleClick4Privat", 0, 0, NULL},
+ {LPGENT("Strip colors from messages in the log"), "StripFormatting", 0, 0, NULL},
+ {LPGENT("Enable the \'event filter\' for new rooms"), "FilterEnabled", 0, 0, NULL},
+//MAD: simple customization improvement
+ {LPGENT("Use IRC style status indicators in the log"), "LogClassicIndicators", 0,0, NULL},
+//
+ {LPGENT("Allow clickable user names in the message log"), "ClickableNicks", 0, 1, NULL},
+ {LPGENT("Colorize user names in message log"), "ColorizeNicksInLog", 0, 1, NULL},
+ {LPGENT("Scale down icons to 10x10 pixels in the chat log"), "ScaleIcons", 0, 1, NULL},
+ {LPGENT("Place a separator in the log after a window lost its foreground status"), "UseDividers", 0, 1, NULL},
+ {LPGENT("Only place a separator when an incoming event is announced with a popup"), "DividersUsePopupConfig", 0, 1, NULL},
+ {LPGENT("Support the math module plugin"), "MathModSupport", 0, 0, NULL}
+};
+
+static HWND hPathTip = 0;
+
+void LoadMsgDlgFont(int section, int i, LOGFONT *lf, COLORREF* colour, char *szMod)
+{
+ char str[32];
+ int style;
+ DBVARIANT dbv;
+ int j = (i >= 100 ? i - 100 : i);
+
+ struct FontOptionsList *fol = fontOptionsList;
+ switch (section)
+ {
+ case FONTSECTION_CHAT: fol = CHAT_fontOptionsList; break;
+ case FONTSECTION_IM: fol = IM_fontOptionsList; break;
+ case FONTSECTION_IP: fol = IP_fontOptionsList; break;
+ }
+
+ if (colour) {
+ wsprintfA(str, "Font%dCol", i);
+ *colour = M->GetDword(szMod, str, fol[j].defColour);
+ }
+ if (lf) {
+ wsprintfA(str, "Font%dSize", i);
+ lf->lfHeight = (char) M->GetByte(szMod, str, fol[j].defSize);
+ lf->lfWidth = 0;
+ lf->lfEscapement = 0;
+ lf->lfOrientation = 0;
+ wsprintfA(str, "Font%dSty", i);
+ style = M->GetByte(szMod, str, fol[j].defStyle);
+ if (i == MSGFONTID_MESSAGEAREA && section == FONTSECTION_IM && M->GetByte(0, SRMSGMOD_T, "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;
+ }
+ wsprintfA(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;
+ wsprintfA(str, "Font%d", i);
+ if ((i == 17 && !strcmp(szMod, CHAT_FONTMODULE)) || ((i == 20 || i == 21) && !strcmp(szMod, FONTMODULE))) {
+ lf->lfCharSet = SYMBOL_CHARSET;
+ lstrcpyn(lf->lfFaceName, _T("Webdings"), SIZEOF(lf->lfFaceName));
+ } else {
+ if (M->GetTString(NULL, szMod, str, &dbv)) {
+ lstrcpy(lf->lfFaceName, fol[j].szDefFace);
+ } else {
+ lstrcpyn(lf->lfFaceName, dbv.ptszVal, SIZEOF(lf->lfFaceName));
+ DBFreeVariant(&dbv);
+ }
+ }
+ }
+}
+
+static HTREEITEM InsertBranch(HWND hwndTree, TCHAR* pszDescr, BOOL bExpanded)
+{
+ TVINSERTSTRUCT tvis;
+
+ tvis.hParent = NULL;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_TEXT | TVIF_STATE;
+ tvis.item.pszText = TranslateTS(pszDescr);
+ tvis.item.stateMask = (bExpanded ? TVIS_STATEIMAGEMASK | TVIS_EXPANDED : TVIS_STATEIMAGEMASK) | TVIS_BOLD;
+ tvis.item.state = (bExpanded ? INDEXTOSTATEIMAGEMASK(0) | TVIS_EXPANDED : INDEXTOSTATEIMAGEMASK(0)) | TVIS_BOLD;
+ return TreeView_InsertItem(hwndTree, &tvis);
+}
+
+static void FillBranch(HWND hwndTree, HTREEITEM hParent, struct branch_t *branch, int nValues, DWORD defaultval)
+{
+ TVINSERTSTRUCT tvis;
+ int i;
+ int iState;
+
+ if (hParent == 0)
+ return;
+
+ tvis.hParent = hParent;
+ tvis.hInsertAfter = TVI_LAST;
+ tvis.item.mask = TVIF_TEXT | TVIF_STATE;
+ for (i=0;i < nValues;i++) {
+ tvis.item.pszText = TranslateTS(branch[i].szDescr);
+ tvis.item.stateMask = TVIS_STATEIMAGEMASK;
+ if (branch[i].iMode)
+ iState = ((M->GetDword("Chat", branch[i].szDBName, defaultval) & branch[i].iMode) & branch[i].iMode) != 0 ? 3 : 2;
+ else
+ iState = M->GetByte("Chat", branch[i].szDBName, branch[i].bDefault) != 0 ? 3 : 2;
+ tvis.item.state = INDEXTOSTATEIMAGEMASK(iState);
+ branch[i].hItem = TreeView_InsertItem(hwndTree, &tvis);
+ }
+}
+
+static void SaveBranch(HWND hwndTree, struct branch_t *branch, int nValues)
+{
+ TVITEM tvi;
+ BYTE bChecked;
+ int i;
+ int iState = 0;
+
+ tvi.mask = TVIF_HANDLE | TVIF_STATE;
+ for (i=0;i < nValues;i++) {
+ tvi.hItem = branch[i].hItem;
+ TreeView_GetItem(hwndTree, &tvi);
+ bChecked = ((tvi.state & TVIS_STATEIMAGEMASK) >> 12 == 2) ? 0 : 1;
+ if (branch[i].iMode) {
+ if (bChecked)
+ iState |= branch[i].iMode;
+ if (iState & GC_EVENT_ADDSTATUS)
+ iState |= GC_EVENT_REMOVESTATUS;
+ M->WriteDword("Chat", branch[i].szDBName, (DWORD)iState);
+ } else M->WriteByte("Chat", branch[i].szDBName, bChecked);
+ }
+}
+
+static void CheckHeading(HWND hwndTree, HTREEITEM hHeading)
+{
+ BOOL bChecked = TRUE;
+ TVITEM tvi;
+
+ if (hHeading == 0)
+ return;
+
+ tvi.mask = TVIF_HANDLE | TVIF_STATE;
+ tvi.hItem = TreeView_GetNextItem(hwndTree, hHeading, TVGN_CHILD);
+ while (tvi.hItem && bChecked) {
+ if (tvi.hItem != branch1[0].hItem && tvi.hItem != branch1[1].hItem) {
+ TreeView_GetItem(hwndTree, &tvi);
+ if (((tvi.state&TVIS_STATEIMAGEMASK) >> 12 == 2))
+ bChecked = FALSE;
+ }
+ tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem);
+ }
+ tvi.stateMask = TVIS_STATEIMAGEMASK;
+ tvi.state = INDEXTOSTATEIMAGEMASK(1); //bChecked ? 3 : 2);
+ tvi.hItem = hHeading;
+ TreeView_SetItem(hwndTree, &tvi);
+}
+
+static void CheckBranches(HWND hwndTree, HTREEITEM hHeading)
+{
+ BOOL bChecked = TRUE;
+ TVITEM tvi;
+
+ if (hHeading == 0)
+ return;
+
+ tvi.mask = TVIF_HANDLE | TVIF_STATE;
+ tvi.hItem = hHeading;
+ TreeView_GetItem(hwndTree, &tvi);
+ if (((tvi.state&TVIS_STATEIMAGEMASK) >> 12 == 3)||((tvi.state & TVIS_STATEIMAGEMASK) >> 12 == 1))
+ bChecked = FALSE;
+
+ tvi.stateMask = TVIS_STATEIMAGEMASK;
+ tvi.state = INDEXTOSTATEIMAGEMASK(bChecked ? 2 : 1);
+ TreeView_SetItem(hwndTree, &tvi);
+ tvi.hItem = TreeView_GetNextItem(hwndTree, hHeading, TVGN_CHILD);
+ while (tvi.hItem) {
+ tvi.state = INDEXTOSTATEIMAGEMASK(bChecked ? 3:2);
+ if (tvi.hItem != branch1[0].hItem && tvi.hItem != branch1[1].hItem)
+ TreeView_SetItem(hwndTree, &tvi);
+ tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem);
+ }
+}
+
+static INT CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData)
+{
+ char szDir[MAX_PATH];
+ switch (uMsg) {
+ case BFFM_INITIALIZED: {
+ const TCHAR *szData = M->getUserDir();
+ SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)szData);
+ break;
+ }
+ case BFFM_SELCHANGED:
+ if (SHGetPathFromIDListA((LPITEMIDLIST) lp , szDir))
+ SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)szDir);
+ break;
+ }
+ return 0;
+}
+
+static void LoadLogFonts(void)
+{
+ int i;
+
+ for (i=0; i < OPTIONS_FONTCOUNT; i++)
+ LoadMsgDlgFont(FONTSECTION_CHAT, i, &aFonts[i].lf, &aFonts[i].color, CHAT_FONTMODULE);
+}
+
+struct { char *szDesc; char *szName; int id; UINT size;} static _icons[] =
+{
+ { LPGEN("Window Icon"), "chat_window", IDI_CHANMGR, 16 },
+ { LPGEN("Icon overlay"), "chat_overlay", IDI_OVERLAY, 16 },
+
+ { LPGEN("Status 1 (10x10)"), "chat_status0", IDI_STATUS0, 16 },
+ { LPGEN("Status 2 (10x10)"), "chat_status1", IDI_STATUS1, 16 },
+ { LPGEN("Status 3 (10x10)"), "chat_status2", IDI_STATUS2, 16 },
+ { LPGEN("Status 4 (10x10)"), "chat_status3", IDI_STATUS3, 16 },
+ { LPGEN("Status 5 (10x10)"), "chat_status4", IDI_STATUS4, 16 },
+ { LPGEN("Status 6 (10x10)"), "chat_status5", IDI_STATUS5, 16 },
+};
+
+struct { char *szDesc; char *szName; int id; UINT size;} static _logicons[] =
+{
+ { LPGEN("Message in (10x10)"), "chat_log_message_in", IDI_MESSAGE, 16 },
+ { LPGEN("Message out (10x10)"), "chat_log_message_out", IDI_MESSAGEOUT, 16 },
+ { LPGEN("Action (10x10)"), "chat_log_action", IDI_ACTION, 16 },
+ { LPGEN("Add Status (10x10)"), "chat_log_addstatus", IDI_ADDSTATUS, 16 },
+ { LPGEN("Remove Status (10x10)"), "chat_log_removestatus", IDI_REMSTATUS, 16 },
+ { LPGEN("Join (10x10)"), "chat_log_join", IDI_JOIN, 16 },
+ { LPGEN("Leave (10x10)"), "chat_log_part", IDI_PART, 16 },
+ { LPGEN("Quit (10x10)"), "chat_log_quit", IDI_QUIT, 16 },
+ { LPGEN("Kick (10x10)"), "chat_log_kick", IDI_KICK, 16 },
+ { LPGEN("Notice (10x10)"), "chat_log_notice", IDI_NOTICE, 16 },
+ { LPGEN("Nickchange (10x10)"), "chat_log_nick", IDI_NICK, 16 },
+ { LPGEN("Topic (10x10)"), "chat_log_topic", IDI_TOPIC, 16 },
+ { LPGEN("Highlight (10x10)"), "chat_log_highlight", IDI_HIGHLIGHT, 16 },
+ { LPGEN("Information (10x10)"), "chat_log_info", IDI_INFO, 16 }
+};
+
+// add icons to the skinning module
+void Chat_AddIcons(void)
+{
+ int i;
+ TCHAR szFile[MAX_PATH];
+ GetModuleFileName(g_hIconDLL, szFile, SIZEOF(szFile));
+
+ // 16x16 icons
+ SKINICONDESC sid = {0};
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.pszSection = "TabSRMM/Group chat windows";
+ sid.ptszDefaultFile = szFile;
+ sid.flags = SIDF_PATH_TCHAR;
+
+ for (i=0; i < SIZEOF(_icons); i++) {
+ sid.cx = sid.cy = _icons[i].size;
+ sid.pszDescription = _icons[i].szDesc;
+ sid.pszName = _icons[i].szName;
+ sid.iDefaultIndex = -_icons[i].id;
+ Skin_AddIcon(&sid);
+ }
+
+ sid.pszSection = "TabSRMM/Group chat log";
+ for (i=0; i < SIZEOF(_logicons); i++) {
+ sid.cx = sid.cy = _logicons[i].size;
+ sid.pszDescription = _logicons[i].szDesc;
+ sid.pszName = _logicons[i].szName;
+ sid.iDefaultIndex = -_logicons[i].id;
+ Skin_AddIcon(&sid);
+ }
+}
+
+/*
+ * get icon by name from the core icon library service
+ */
+
+HICON LoadIconEx(int iIndex, char * pszIcoLibName, int iX, int iY)
+{
+ char szTemp[256];
+ mir_snprintf(szTemp, sizeof(szTemp), "chat_%s", pszIcoLibName);
+ return (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM)szTemp);
+}
+
+static void InitSetting(TCHAR** ppPointer, char* pszSetting, TCHAR* pszDefault)
+{
+ DBVARIANT dbv;
+ if (!M->GetTString(NULL, "Chat", pszSetting, &dbv)) {
+ replaceStr(ppPointer, dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ } else
+ replaceStr(ppPointer, pszDefault);
+}
+
+#define OPT_FIXHEADINGS (WM_USER+1)
+
+static UINT _o1controls[] = {IDC_CHECKBOXES, IDC_GROUP, IDC_STATIC_ADD, 0};
+
+HWND CreateToolTip(HWND hwndParent, LPTSTR ptszText, LPTSTR ptszTitle)
+{
+ TOOLINFO ti = { 0 };
+ HWND hwndTT;
+ 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);
+
+ 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 =- 85;
+
+ SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
+ SendMessage(hwndTT, TTM_SETTITLE, 1, (LPARAM)ptszTitle);
+ 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);
+ if (PluginConfig.m_chat_enabled) {
+ HIMAGELIST himlOptions;
+
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHECKBOXES), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHECKBOXES), GWL_STYLE) | TVS_NOHSCROLL | TVS_CHECKBOXES);
+
+ himlOptions = (HIMAGELIST)SendDlgItemMessage(hwndDlg, IDC_CHECKBOXES, TVM_SETIMAGELIST, TVSIL_STATE, (LPARAM)CreateStateImageList());
+ ImageList_Destroy(himlOptions);
+
+ 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, SIZEOF(branch1), 0x0000);
+ FillBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2, branch2, SIZEOF(branch2), 0x0000);
+
+ {
+ TCHAR* pszGroup = NULL;
+ InitSetting(&pszGroup, "AddToGroup", _T("Chat rooms"));
+ SetWindowText(GetDlgItem(hwndDlg, IDC_GROUP), pszGroup);
+ mir_free(pszGroup);
+ Utils::showDlgControl(hwndDlg, IDC_STATIC_MESSAGE, SW_HIDE);
+ }
+ } else {
+ int i = 0;
+
+ while (_o1controls[i])
+ Utils::showDlgControl(hwndDlg, _o1controls[i++], SW_HIDE);
+ }
+ break;
+
+ case WM_COMMAND:
+ if ((LOWORD(wParam) == IDC_GROUP)
+ && (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0;
+
+ if (lParam != (LPARAM)NULL)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY: {
+ switch (((LPNMHDR)lParam)->idFrom) {
+ case IDC_CHECKBOXES:
+ if (((LPNMHDR)lParam)->code == NM_CLICK || (((LPNMHDR)lParam)->code == TVN_KEYDOWN && ((LPNMTVKEYDOWN)lParam)->wVKey == VK_SPACE)) {
+ TVHITTESTINFO hti;
+ hti.pt.x = (short)LOWORD(GetMessagePos());
+ hti.pt.y = (short)HIWORD(GetMessagePos());
+ ScreenToClient(((LPNMHDR)lParam)->hwndFrom, &hti.pt);
+ if (TreeView_HitTest(((LPNMHDR)lParam)->hwndFrom, &hti) || ((LPNMHDR)lParam)->code == TVN_KEYDOWN) {
+ if (((LPNMHDR)lParam)->code == TVN_KEYDOWN)
+ hti.flags |= TVHT_ONITEMSTATEICON;
+ if (hti.flags&TVHT_ONITEMSTATEICON) {
+ TVITEM tvi = {0};
+
+ tvi.mask = TVIF_HANDLE | TVIF_STATE;
+ tvi.stateMask = TVIS_STATEIMAGEMASK | TVIS_BOLD;
+
+ if (((LPNMHDR)lParam)->code == TVN_KEYDOWN)
+ tvi.hItem = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
+ else
+ tvi.hItem = (HTREEITEM)hti.hItem;
+
+ TreeView_GetItem(((LPNMHDR)lParam)->hwndFrom, &tvi);
+
+ if (tvi.state & TVIS_BOLD && hti.flags & TVHT_ONITEMSTATEICON) {
+ tvi.state = INDEXTOSTATEIMAGEMASK(0) | TVIS_BOLD;
+ SendDlgItemMessageA(hwndDlg, IDC_CHECKBOXES, TVM_SETITEMA, 0, (LPARAM)&tvi);
+ } else if (hti.flags&TVHT_ONITEMSTATEICON) {
+ if (((tvi.state & TVIS_STATEIMAGEMASK) >> 12) == 3) {
+ tvi.state = INDEXTOSTATEIMAGEMASK(1);
+ SendDlgItemMessageA(hwndDlg, IDC_CHECKBOXES, TVM_SETITEMA, 0, (LPARAM)&tvi);
+ }
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+ }
+
+ break;
+
+ case 0:
+ switch (((LPNMHDR)lParam)->code) {
+ case PSN_APPLY: {
+ if (PluginConfig.m_chat_enabled) {
+ int iLen;
+ TCHAR *pszText = NULL;
+ BYTE b;
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_GROUP));
+ if (iLen > 0) {
+ pszText = (TCHAR *)realloc(pszText, (iLen + 2) * sizeof(TCHAR));
+ GetDlgItemText(hwndDlg, IDC_GROUP, pszText, iLen + 1);
+ M->WriteTString(NULL, "Chat", "AddToGroup", pszText);
+ } else
+ M->WriteTString(NULL, "Chat", "AddToGroup", _T(""));
+
+ g_Settings.hGroup = 0;
+
+ if (pszText)
+ free(pszText);
+
+ b = M->GetByte("Chat", "Tabs", 1);
+ SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch1, sizeof(branch1) / sizeof(branch1[0]));
+ SaveBranch(GetDlgItem(hwndDlg, IDC_CHECKBOXES), branch2, sizeof(branch2) / sizeof(branch2[0]));
+
+ LoadGlobalSettings();
+ MM_FontsChanged();
+ FreeMsgLogBitmaps();
+ LoadMsgLogBitmaps();
+ 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;
+ M->WriteByte("Chat", "Branch1Exp", b);
+ b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHECKBOXES), hListHeading2, TVIS_EXPANDED) & TVIS_EXPANDED ? 1 : 0;
+ M->WriteByte("Chat", "Branch2Exp", b);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+static TCHAR* chatcolorsnames[] ={
+// LPGENT("Your nickname"),
+ LPGENT("Channel operators"),
+ LPGENT("Half operators"),
+ LPGENT("Voiced"),
+// LPGENT("Others nicknames"),
+ LPGENT("Extended mode 1"),
+ LPGENT("Extended mode 2"),
+ LPGENT("Selection background"),
+ LPGENT("Selected text"),
+ LPGENT("Incremental search highlight")
+ };
+
+void RegisterFontServiceFonts() {
+ int i;
+ char szTemp[100];
+ LOGFONT lf;
+ FontIDT fid = {0};
+ ColourIDT cid = {0};
+
+ fid.cbSize = sizeof(FontIDT);
+ cid.cbSize = sizeof(ColourIDT);
+
+ strncpy(fid.dbSettingsGroup, FONTMODULE, SIZEOF(fid.dbSettingsGroup));
+
+ for (i=0; i < SIZEOF(IM_fontOptionsList); i++) {
+ fid.flags = FIDF_DEFAULTVALID|FIDF_ALLOWEFFECTS;
+ LoadMsgDlgFont(FONTSECTION_IM, i , &lf, &fontOptionsList[i].colour, FONTMODULE);
+ mir_snprintf(szTemp, SIZEOF(szTemp), "Font%d", i);
+ strncpy(fid.prefix, szTemp, SIZEOF(fid.prefix));
+ fid.order = i;
+ _tcsncpy(fid.name, fontOptionsList[i].szDescr, SIZEOF(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);
+ _tcsncpy(fid.deffontsettings.szFace, lf.lfFaceName, LF_FACESIZE);
+ _tcsncpy(fid.backgroundGroup, _T("TabSRMM/Single Messaging"), SIZEOF(fid.backgroundGroup));
+ _tcsncpy(fid.group, _T("TabSRMM/Single Messaging"), SIZEOF(fid.group));
+ switch (i) {
+ case MSGFONTID_MYMSG:
+ case 1:
+ case MSGFONTID_MYNAME:
+ case MSGFONTID_MYTIME:
+ case 21:
+ _tcsncpy(fid.backgroundName, _T("Outgoing background"), SIZEOF(fid.backgroundName));
+ break;
+ case 8:
+ case 9:
+ case 12:
+ case 13:
+ _tcsncpy(fid.backgroundName, _T("Outgoing background(old)"), SIZEOF(fid.backgroundName));
+ break;
+ case 10:
+ case 11:
+ case 14:
+ case 15:
+ _tcsncpy(fid.backgroundName, _T("Incoming background(old)"), SIZEOF(fid.backgroundName));
+ break;
+ case MSGFONTID_MESSAGEAREA:
+ _tcsncpy(fid.group, _T("TabSRMM"), SIZEOF(fid.group));
+ _tcsncpy(fid.backgroundGroup, _T("TabSRMM"), SIZEOF(fid.backgroundGroup));
+ _tcsncpy(fid.backgroundName, _T("Input area background"), SIZEOF(fid.backgroundName));
+ fid.flags |= FIDF_DISABLESTYLES;
+ fid.flags &= ~FIDF_ALLOWEFFECTS;
+ break;
+ case 17:
+ _tcsncpy(fid.backgroundName, _T("Status background"), SIZEOF(fid.backgroundName));
+ break;
+ case 18:
+ _tcsncpy(fid.backgroundGroup, _T("TabSRMM"), SIZEOF(fid.backgroundGroup));
+ _tcsncpy(fid.backgroundName, _T("Log background"), SIZEOF(fid.backgroundName));
+ break;
+ case 19:
+ _tcsncpy(fid.backgroundName, _T(""), SIZEOF(fid.backgroundName));
+ break;
+ default:
+ _tcsncpy(fid.backgroundName, _T("Incoming background"), SIZEOF(fid.backgroundName));
+ break;
+ }
+ FontRegisterT(&fid);
+ }
+
+ fontOptionsList = IP_fontOptionsList;
+ fid.flags = FIDF_DEFAULTVALID|FIDF_ALLOWEFFECTS;
+ //fid.flags|=FIDF_SAVEPOINTSIZE;
+ _tcsncpy(fid.group, _T("TabSRMM/Info Panel"), SIZEOF(fid.group));
+ _tcsncpy(fid.backgroundGroup, _T("TabSRMM/Info Panel"), SIZEOF(fid.backgroundGroup));
+ _tcsncpy(fid.backgroundName, _T("Fields background"), SIZEOF(fid.backgroundName));
+ for (i =0; i < IPFONTCOUNT; i++) {
+ LoadMsgDlgFont(FONTSECTION_IP, i + 100 , &lf, &fontOptionsList[i].colour, FONTMODULE);
+ mir_snprintf(szTemp, SIZEOF(szTemp), "Font%d", i + 100);
+ strncpy(fid.prefix, szTemp, SIZEOF(fid.prefix));
+ fid.order = i + 100 ;
+ _tcsncpy(fid.name, fontOptionsList[i].szDescr, SIZEOF(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;
+ _tcsncpy(fid.deffontsettings.szFace, lf.lfFaceName, LF_FACESIZE);
+ if (i==IPFONTCOUNT-1){
+ _tcsncpy(fid.backgroundGroup, _T(""), SIZEOF(fid.backgroundGroup));
+ _tcsncpy(fid.backgroundName, _T(""), SIZEOF(fid.backgroundName));
+ _tcsncpy(fid.group, _T("TabSRMM"), SIZEOF(fid.group));
+ }
+ FontRegisterT(&fid);
+ }
+
+ fontOptionsList = CHAT_fontOptionsList;
+ fid.flags = FIDF_DEFAULTVALID|FIDF_ALLOWEFFECTS;
+ fid.flags&=~FIDF_SAVEPOINTSIZE;
+ _tcsncpy(fid.group, _T("TabSRMM/Group Chats"), SIZEOF(fid.group));
+ strncpy(fid.dbSettingsGroup, CHAT_FONTMODULE, SIZEOF(fid.dbSettingsGroup));
+ for (i=0; i < msgDlgFontCount; i++) {
+ LoadMsgDlgFont(FONTSECTION_CHAT, i , &lf, &fontOptionsList[i].colour, CHAT_FONTMODULE);
+ mir_snprintf(szTemp, SIZEOF(szTemp), "Font%d", i);
+ strncpy(fid.prefix, szTemp, SIZEOF(fid.prefix));
+ fid.order = i;
+ _tcsncpy(fid.name, fontOptionsList[i].szDescr, SIZEOF(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.flags = fid.flags & ~FIDF_CLASSMASK | (fid.deffontsettings.style&FONTF_BOLD ? FIDF_CLASSHEADER : FIDF_CLASSGENERAL);
+ fid.deffontsettings.charset = lf.lfCharSet;
+ _tcsncpy(fid.deffontsettings.szFace, lf.lfFaceName, LF_FACESIZE);
+ _tcsncpy(fid.backgroundGroup, _T("TabSRMM/Group Chats"), SIZEOF(fid.backgroundGroup));
+ _tcsncpy(fid.backgroundName, _T("Group chat log background"), SIZEOF(fid.backgroundName));
+ if (i == 18 || i == 19)
+ _tcsncpy(fid.backgroundName, _T("Userlist background"), SIZEOF(fid.backgroundName));
+ FontRegisterT(&fid);
+ }
+
+ _tcsncpy(cid.group, _T("TabSRMM/Group Chats"), SIZEOF(cid.group));
+ strncpy(cid.dbSettingsGroup, "Chat", SIZEOF(cid.dbSettingsGroup));
+ for (i=0; i <= 7; i++) {
+ mir_snprintf(szTemp, SIZEOF(szTemp), "NickColor%d", i);
+ _tcsncpy(cid.name, chatcolorsnames[i], SIZEOF(cid.name));
+ cid.order=i+1;
+ strncpy(cid.setting, szTemp, SIZEOF(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;
+ }
+ ColourRegisterT(&cid);
+ }
+ cid.order=8;
+ _tcsncpy(cid.name, _T("Userlist background"), SIZEOF(cid.name));
+ strncpy(cid.setting, "ColorNicklistBG", SIZEOF(cid.setting));
+ cid.defcolour = SRMSGDEFSET_BKGCOLOUR;
+ ColourRegisterT(&cid);
+
+ /*
+ * static colors (info panel, tool bar background etc...)
+ */
+ strncpy(fid.dbSettingsGroup, FONTMODULE, SIZEOF(fid.dbSettingsGroup));
+ strncpy(cid.dbSettingsGroup, FONTMODULE, SIZEOF(fid.dbSettingsGroup));
+
+ for (i=0; i < (sizeof(_clrs) / sizeof(_clrs[0])); i++) {
+ cid.order = _clrs[i].order;
+ _tcsncpy(cid.group, _clrs[i].tszGroup, SIZEOF(fid.group));
+ _tcsncpy(cid.name, _clrs[i].tszName, SIZEOF(cid.name));
+ strncpy(cid.setting, _clrs[i].szSetting, SIZEOF(cid.setting));
+ if (_clrs[i].def & 0xff000000)
+ cid.defcolour = GetSysColor(_clrs[i].def & 0x000000ff);
+ else
+ cid.defcolour = _clrs[i].def;
+ ColourRegisterT(&cid);
+ }
+
+ strncpy(cid.dbSettingsGroup, SRMSGMOD_T, SIZEOF(fid.dbSettingsGroup));
+
+ /*
+ * text and background colors for tabs
+ */
+ for (i=0; i < (sizeof(_tabclrs) / sizeof(_tabclrs[0])); i++) {
+ cid.order = _tabclrs[i].order;
+ _tcsncpy(cid.group, _tabclrs[i].tszGroup, SIZEOF(fid.group));
+ _tcsncpy(cid.name, _tabclrs[i].tszName, SIZEOF(cid.name));
+ strncpy(cid.setting, _tabclrs[i].szSetting, SIZEOF(cid.setting));
+ if (_tabclrs[i].def & 0xff000000)
+ cid.defcolour = GetSysColor(_tabclrs[i].def & 0x000000ff);
+ else
+ cid.defcolour = _tabclrs[i].def;
+
+ ColourRegisterT(&cid);
+ }
+}
+
+int FontServiceFontsChanged(WPARAM wParam, LPARAM lParam)
+{
+ if (PluginConfig.m_chat_enabled) {
+ LOGFONT lf;
+ HFONT hFont;
+ int iText;
+
+ LoadLogFonts();
+ FreeMsgLogBitmaps();
+ LoadMsgLogBitmaps();
+
+ LoadMsgDlgFont(FONTSECTION_CHAT, 0, &lf, NULL, CHAT_FONTMODULE);
+ hFont = CreateFontIndirect(&lf);
+ iText = GetTextPixelSize(MakeTimeStamp(g_Settings.pszTimeStamp, time(NULL)), hFont, TRUE);
+ DeleteObject(hFont);
+ g_Settings.LogTextIndent = iText;
+ g_Settings.LogTextIndent = g_Settings.LogTextIndent * 12 / 10;
+ g_Settings.LogIndentEnabled = (M->GetByte("Chat", "LogIndentEnabled", 1) != 0) ? TRUE : FALSE;
+
+ LoadGlobalSettings();
+ MM_FontsChanged();
+ MM_FixColors();
+ SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE);
+ }
+
+ 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);
+
+ if (PluginConfig.m_chat_enabled) {
+
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN2, UDM_SETRANGE, 0, MAKELONG(5000, 0));
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN2, UDM_SETPOS, 0, MAKELONG(DBGetContactSettingWord(NULL, "Chat", "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", "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.LoggingEnabled);
+ SetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, g_Settings.pszLogDir);
+ Utils::enableDlgControl(hwndDlg, IDC_LOGDIRECTORY, g_Settings.LoggingEnabled ? TRUE : FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_FONTCHOOSE, g_Settings.LoggingEnabled ? TRUE : FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN4, UDM_SETRANGE, 0, MAKELONG(10000, 0));
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN4, UDM_SETPOS, 0, MAKELONG(DBGetContactSettingWord(NULL, "Chat", "LoggingLimit", 100), 0));
+ Utils::enableDlgControl(hwndDlg, IDC_LIMIT, g_Settings.LoggingEnabled ? TRUE : FALSE);
+
+ if (ServiceExists(MS_UTILS_REPLACEVARS)) {
+ TCHAR tszTooltipText[2048];
+
+ mir_sntprintf(tszTooltipText, SIZEOF(tszTooltipText),
+ _T("%s - %s\n%s - %s\n%s - %s\n\n")
+ _T("%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")
+ _T("%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
+ _T("%nick%"), TranslateT("nick of current contact (if defined)"),
+ _T("%proto%"), TranslateT("protocol name of current contact (if defined). Account name is used when protocol supports multiaccounts"),
+ _T("%userid%"), TranslateT("UserID of current contact (if defined). It is like UIN Number for ICQ, JID for Jabber, etc."),
+ // global vars
+ _T("%miranda_path%"), TranslateT("path to root miranda folder"),
+ _T("%miranda_profile%"), TranslateT("path to current miranda profile"),
+ _T("%miranda_profilename%"), TranslateT("name of current miranda profile (filename, without extension)"),
+ _T("%miranda_userdata%"), TranslateT("will return parsed string %miranda_profile%\\Profiles\\%miranda_profilename%"),
+ _T("%appdata%"), TranslateT("same as environment variable %APPDATA% for currently logged-on Windows user"),
+ _T("%username%"), TranslateT("username for currently logged-on Windows user"),
+ _T("%mydocuments%"), TranslateT("\"My Documents\" folder for currently logged-on Windows user"),
+ _T("%desktop%"), TranslateT("\"Desktop\" folder for currently logged-on Windows user"),
+ _T("%xxxxxxx%"), TranslateT("any environment variable defined in current Windows session (like %systemroot%, %allusersprofile%, etc.)"),
+ // date/time vars
+ _T("%d%"), TranslateT("day of month, 1-31"),
+ _T("%dd%"), TranslateT("day of month, 01-31"),
+ _T("%m%"), TranslateT("month number, 1-12"),
+ _T("%mm%"), TranslateT("month number, 01-12"),
+ _T("%mon%"), TranslateT("abbreviated month name"),
+ _T("%month%"), TranslateT("full month name"),
+ _T("%yy%"), TranslateT("year without century, 01-99"),
+ _T("%yyyy%"), TranslateT("year with century, 1901-9999"),
+ _T("%wday%"), TranslateT("abbreviated weekday name"),
+ _T("%weekday%"), TranslateT("full weekday name"));
+ hPathTip = CreateToolTip(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY), tszTooltipText, TranslateT("Variables"));
+ }
+
+ } else {
+ int i = 0;
+
+ while (_o2chatcontrols[i])
+ Utils::enableDlgControl(hwndDlg, _o2chatcontrols[i++], FALSE);
+ }
+ 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;
+
+ switch (LOWORD(wParam)) {
+ /*
+ * 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.
+ */
+ case IDC_MUC_OPENLOGBASEDIR: {
+ OPENFILENAME ofn = {0};
+ SESSION_INFO si = {0};
+ TCHAR tszReturnName[MAX_PATH];
+ TCHAR tszInitialDir[_MAX_DRIVE + _MAX_PATH + 10];
+ TCHAR tszTemp[MAX_PATH + 20], *p = 0, *p1 = 0;
+
+ mir_sntprintf(tszTemp, MAX_PATH + 20, _T("%s"), g_Settings.pszLogDir);
+
+ p = tszTemp;
+ while(*p && (*p == '\\' || *p == '.'))
+ p++;
+
+ if (*p) {
+ if ((p1 = _tcschr(p, '\\')))
+ *p1 = 0;
+ }
+
+ mir_sntprintf(tszInitialDir, MAX_PATH, _T("%s%s"), M->getChatLogPath(), p);
+ if (PathFileExists(tszInitialDir))
+ ofn.lpstrInitialDir = tszInitialDir;
+ else {
+ mir_sntprintf(tszInitialDir, MAX_PATH, _T("%s"), M->getChatLogPath());
+ ofn.lpstrInitialDir = tszInitialDir;
+ }
+
+ tszReturnName[0] = 0;
+ mir_sntprintf(tszTemp, SIZEOF(tszTemp), _T("%s%c*.*%c%c"), TranslateT("All Files"), 0, 0, 0);
+
+ ofn.lpstrFilter = tszTemp;
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+ ofn.hwndOwner = 0;
+ ofn.lpstrFile = tszReturnName;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.nMaxFileTitle = MAX_PATH;
+ ofn.Flags = OFN_HIDEREADONLY | OFN_DONTADDTORECENT;
+ ofn.lpstrDefExt = _T("log");
+ GetOpenFileName(&ofn);
+ break;
+ }
+
+ case IDC_FONTCHOOSE: {
+ TCHAR tszDirectory[MAX_PATH];
+ LPITEMIDLIST idList;
+ LPMALLOC psMalloc;
+ BROWSEINFO bi = {0};
+
+ if (SUCCEEDED(CoGetMalloc(1, &psMalloc))) {
+ TCHAR tszTemp[MAX_PATH];
+ 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;
+
+
+ idList = SHBrowseForFolder(&bi);
+ if (idList) {
+ const TCHAR *szUserDir = M->getUserDir();
+ SHGetPathFromIDList(idList, tszDirectory);
+ lstrcat(tszDirectory, _T("\\"));
+ M->pathToRelative(tszDirectory, tszTemp, const_cast<TCHAR *>(szUserDir));
+ SetWindowText(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY), lstrlen(tszTemp) > 1 ? tszTemp : DEFLOGFILENAME);
+ }
+ psMalloc->Free(idList);
+ psMalloc->Release();
+ }
+ break;
+ }
+
+ case IDC_LOGGING:
+ if (PluginConfig.m_chat_enabled) {
+ 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 != (LPARAM)NULL)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->idFrom == 0 && ((LPNMHDR)lParam)->code == PSN_APPLY) {
+ int iLen;
+ TCHAR *p2 = NULL;
+ char *pszText = NULL;
+ TCHAR *ptszPath = NULL;
+
+ if (PluginConfig.m_chat_enabled) {
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOGDIRECTORY));
+ if (iLen > 0) {
+ TCHAR *pszText1 = (TCHAR *)malloc(iLen*sizeof(TCHAR) + 2);
+ GetDlgItemText(hwndDlg, IDC_LOGDIRECTORY, pszText1, iLen + 1);
+ M->WriteTString(NULL, "Chat", "LogDirectory", pszText1);
+ free(pszText1);
+ g_Settings.LoggingEnabled = IsDlgButtonChecked(hwndDlg, IDC_LOGGING) == BST_CHECKED ? TRUE : FALSE;
+ M->WriteByte("Chat", "LoggingEnabled", (BYTE)g_Settings.LoggingEnabled);
+ } else {
+ DBDeleteContactSetting(NULL, "Chat", "LogDirectory");
+ M->WriteByte("Chat", "LoggingEnabled", 0);
+ }
+ SM_InvalidateLogDirectories();
+
+ iLen = SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN4, UDM_GETPOS, 0, 0);
+ DBWriteContactSettingWord(NULL, "Chat", "LoggingLimit", (WORD)iLen);
+
+ iLen = SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN3, UDM_GETPOS, 0, 0);
+ if (iLen > 0)
+ M->WriteByte("Chat", "NicklistRowDist", (BYTE)iLen);
+ else
+ DBDeleteContactSetting(NULL, "Chat", "NicklistRowDist");
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_LOGTIMESTAMP));
+ if (iLen > 0) {
+ pszText = (char *)realloc(pszText, iLen + 1);
+ GetDlgItemTextA(hwndDlg, IDC_LOGTIMESTAMP, pszText, iLen + 1);
+ DBWriteContactSettingString(NULL, "Chat", "LogTimestamp", pszText);
+ } else DBDeleteContactSetting(NULL, "Chat", "LogTimestamp");
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_TIMESTAMP));
+ if (iLen > 0) {
+ pszText = (char *)realloc(pszText, iLen + 1);
+ GetDlgItemTextA(hwndDlg, IDC_TIMESTAMP, pszText, iLen + 1);
+ DBWriteContactSettingString(NULL, "Chat", "HeaderTime", pszText);
+ } else DBDeleteContactSetting(NULL, "Chat", "HeaderTime");
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_INSTAMP));
+ if (iLen > 0) {
+ pszText = (char *)realloc(pszText, iLen + 1);
+ GetDlgItemTextA(hwndDlg, IDC_INSTAMP, pszText, iLen + 1);
+ DBWriteContactSettingString(NULL, "Chat", "HeaderIncoming", pszText);
+ } else DBDeleteContactSetting(NULL, "Chat", "HeaderIncoming");
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_OUTSTAMP));
+ if (iLen > 0) {
+ pszText = (char *)realloc(pszText, iLen + 1);
+ GetDlgItemTextA(hwndDlg, IDC_OUTSTAMP, pszText, iLen + 1);
+ DBWriteContactSettingString(NULL, "Chat", "HeaderOutgoing", pszText);
+ } else DBDeleteContactSetting(NULL, "Chat", "HeaderOutgoing");
+
+ iLen = SendDlgItemMessage(hwndDlg, IDC_CHAT_SPIN2, UDM_GETPOS, 0, 0);
+ DBWriteContactSettingWord(NULL, "Chat", "LogLimit", (WORD)iLen);
+ }
+
+
+ if (pszText != NULL)
+ free(pszText);
+ if (hListBkgBrush)
+ DeleteObject(hListBkgBrush);
+ hListBkgBrush = CreateSolidBrush(M->GetDword("Chat", "ColorNicklistBG", SRMSGDEFSET_BKGCOLOUR));
+
+
+ if (PluginConfig.m_chat_enabled) {
+ LOGFONT lf;
+ HFONT hFont;
+ int iText;
+
+ LoadLogFonts();
+ FreeMsgLogBitmaps();
+ LoadMsgLogBitmaps();
+
+ LoadMsgDlgFont(FONTSECTION_CHAT, 0, &lf, NULL, CHAT_FONTMODULE);
+ hFont = CreateFontIndirect(&lf);
+ iText = GetTextPixelSize(MakeTimeStamp(g_Settings.pszTimeStamp, time(NULL)), hFont, TRUE);
+ DeleteObject(hFont);
+ g_Settings.LogTextIndent = iText;
+ g_Settings.LogTextIndent = g_Settings.LogTextIndent * 12 / 10;
+ g_Settings.LogIndentEnabled = (M->GetByte("Chat", "LogIndentEnabled", 1) != 0) ? TRUE : FALSE;
+
+ LoadGlobalSettings();
+ MM_FontsChanged();
+ MM_FixColors();
+ 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,
+ 0
+};
+
+#define GC_EVENT_ALL (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)
+
+/**
+ * Dialog procedure for group chat options tab #3 (event filter configuration)
+ *
+ * @return
+ */
+INT_PTR CALLBACK DlgProcOptions3(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg) {
+ case WM_INITDIALOG: {
+
+ TranslateDialogDefault(hwndDlg);
+
+ if (PluginConfig.m_chat_enabled) {
+ DWORD dwFilterFlags = M->GetDword("Chat", "FilterFlags", GC_EVENT_ALL);
+ DWORD dwTrayFlags = M->GetDword("Chat", "TrayIconFlags", GC_EVENT_ALL);
+ DWORD dwPopupFlags = M->GetDword("Chat", "PopupFlags", GC_EVENT_ALL);
+ DWORD dwLogFlags = M->GetDword("Chat", "DiskLogFlags", GC_EVENT_ALL);
+
+ for (int i = 0; _eventorder[i]; 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.LogSymbols ? 2 : (g_Settings.dwIconFlags ? 1 : 0)), 0);
+
+ CheckDlgButton(hwndDlg, IDC_NOPOPUPSFORCLOSEDWINDOWS, M->GetByte("Chat", "SkipWhenNoWindow", 0) ? BST_CHECKED : BST_UNCHECKED);
+ CheckDlgButton(hwndDlg, IDC_TRAYONLYFORINACTIVE, M->GetByte("Chat", "TrayIconInactiveOnly", 0) ? BST_CHECKED : BST_UNCHECKED);
+ }
+ break;
+ }
+ case WM_COMMAND:
+ if (lParam != (LPARAM)NULL)
+ 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; _eventorder[i]; 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);
+ }
+ M->WriteDword("Chat", "FilterFlags", dwFilterFlags);
+ M->WriteDword("Chat", "PopupFlags", dwPopupFlags);
+ M->WriteDword("Chat", "TrayIconFlags", dwTrayFlags);
+ M->WriteDword("Chat", "DiskLogFlags", dwLogFlags);
+
+ LRESULT lr = SendDlgItemMessage(hwndDlg, IDC_LOGICONTYPE, CB_GETCURSEL, 0, 0);
+
+ M->WriteDword("Chat", "IconFlags", lr == 1 ? 1 : 0);
+ M->WriteByte("Chat", "LogSymbols", lr == 2 ? 1 : 0);
+
+ M->WriteByte("Chat", "SkipWhenNoWindow", IsDlgButtonChecked(hwndDlg, IDC_NOPOPUPSFORCLOSEDWINDOWS) ? 1 : 0);
+ M->WriteByte("Chat", "TrayIconInactiveOnly", IsDlgButtonChecked(hwndDlg, IDC_TRAYONLYFORINACTIVE) ? 1 : 0);
+ LoadGlobalSettings();
+ MM_FontsChanged();
+ SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE);
+ SM_ReconfigureFilters();
+ break;
+ }
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ break;
+
+ }
+ return FALSE;
+}
+
+void LoadGlobalSettings(void)
+{
+ LOGFONT lf;
+ int i;
+ char szBuf[40];
+
+ g_Settings.LogLimitNames = M->GetByte("Chat", "LogLimitNames", 1);
+ g_Settings.ShowTime = M->GetByte("Chat", "ShowTimeStamp", 1);
+ g_Settings.ShowTimeIfChanged = (BOOL)M->GetByte("Chat", "ShowTimeStampIfChanged", 0);
+ g_Settings.TimeStampEventColour = (BOOL)M->GetByte("Chat", "TimeStampEventColour", 0);
+ g_Settings.iEventLimit = DBGetContactSettingWord(NULL, "Chat", "LogLimit", 100);
+ g_Settings.iEventLimitThreshold = DBGetContactSettingWord(NULL, "Chat", "LogLimitThreshold", 20);
+ g_Settings.dwIconFlags = M->GetDword("Chat", "IconFlags", 0x0000);
+ g_Settings.LoggingLimit = (size_t)DBGetContactSettingWord(NULL, "Chat", "LoggingLimit", 100);
+ g_Settings.LoggingEnabled = (BOOL)M->GetByte("Chat", "LoggingEnabled", 0);
+ g_Settings.OpenInDefault = (BOOL)M->GetByte("Chat", "DefaultContainer", 1);
+ g_Settings.FlashWindow = (BOOL)M->GetByte("Chat", "FlashWindow", 0);
+ g_Settings.FlashWindowHightlight = (BOOL)M->GetByte("Chat", "FlashWindowHighlight", 0);
+ g_Settings.HighlightEnabled = (BOOL)M->GetByte("Chat", "HighlightEnabled", 1);
+ g_Settings.crUserListColor = (BOOL)M->GetDword(CHAT_FONTMODULE, "Font18Col", RGB(0, 0, 0));
+ g_Settings.crUserListBGColor = (BOOL)M->GetDword("Chat", "ColorNicklistBG", SRMSGDEFSET_BKGCOLOUR);
+ g_Settings.crUserListHeadingsColor = (BOOL)M->GetDword(CHAT_FONTMODULE, "Font19Col", RGB(170, 170, 170));
+ g_Settings.StripFormat = (BOOL)M->GetByte("Chat", "StripFormatting", 0);
+ g_Settings.TrayIconInactiveOnly = (BOOL)M->GetByte("Chat", "TrayIconInactiveOnly", 1);
+ g_Settings.BBCodeInPopups = (BOOL)M->GetByte("Chat", "BBCodeInPopups", 0);
+ g_Settings.AddColonToAutoComplete = (BOOL)M->GetByte("Chat", "AddColonToAutoComplete", 1);
+ g_Settings.iPopupStyle = M->GetByte("Chat", "PopupStyle", 1);
+ g_Settings.iPopupTimeout = DBGetContactSettingWord(NULL, "Chat", "PopupTimeout", 3);
+ g_Settings.crPUBkgColour = M->GetDword("Chat", "PopupColorBG", GetSysColor(COLOR_WINDOW));
+ g_Settings.crPUTextColour = M->GetDword("Chat", "PopupColorText", 0);
+ g_Settings.ClassicIndicators = M->GetByte("Chat", "ClassicIndicators", 0);
+ //MAD
+ g_Settings.LogClassicIndicators = M->GetByte("Chat", "LogClassicIndicators", 0);
+ g_Settings.AlternativeSorting = M->GetByte("Chat", "AlternativeSorting", 1);
+ g_Settings.AnnoyingHighlight = M->GetByte("Chat", "AnnoyingHighlight", 0);
+ g_Settings.CreateWindowOnHighlight = M->GetByte("Chat", "CreateWindowOnHighlight", 1);
+ //MAD_
+ g_Settings.LogSymbols = M->GetByte("Chat", "LogSymbols", 1);
+ g_Settings.ClickableNicks = M->GetByte("Chat", "ClickableNicks", 1);
+ g_Settings.ColorizeNicks = M->GetByte("Chat", "ColorizeNicks", 1);
+ g_Settings.ColorizeNicksInLog = M->GetByte("Chat", "ColorizeNicksInLog", 1);
+ g_Settings.ScaleIcons = M->GetByte("Chat", "ScaleIcons", 1);
+ g_Settings.UseDividers = M->GetByte("Chat", "UseDividers", 1);
+ g_Settings.DividersUsePopupConfig = M->GetByte("Chat", "DividersUsePopupConfig", 1);
+ g_Settings.MathMod = ServiceExists(MATH_RTF_REPLACE_FORMULAE) && M->GetByte("Chat", "MathModSupport", 0);
+
+ g_Settings.DoubleClick4Privat = (BOOL)M->GetByte("Chat", "DoubleClick4Privat", 0);
+ g_Settings.ShowContactStatus = M->GetByte("Chat", "ShowContactStatus", 1);
+ g_Settings.ContactStatusFirst = M->GetByte("Chat", "ContactStatusFirst", 0);
+
+
+ if (hListBkgBrush)
+ DeleteObject(hListBkgBrush);
+ hListBkgBrush = CreateSolidBrush(M->GetDword("Chat", "ColorNicklistBG", SRMSGDEFSET_BKGCOLOUR));
+
+ InitSetting(&g_Settings.pszTimeStamp, "HeaderTime", _T("[%H:%M]"));
+ InitSetting(&g_Settings.pszTimeStampLog, "LogTimestamp", _T("[%d %b %y %H:%M]"));
+ InitSetting(&g_Settings.pszIncomingNick, "HeaderIncoming", _T("%n:"));
+ InitSetting(&g_Settings.pszOutgoingNick, "HeaderOutgoing", _T("%n:"));
+
+ DBVARIANT dbv;
+
+ if (!M->GetTString(NULL, "Chat", "LogDirectory", &dbv)) {
+ lstrcpyn(g_Settings.pszLogDir, dbv.ptszVal, MAX_PATH);
+ DBFreeVariant(&dbv);
+ } else
+ lstrcpyn(g_Settings.pszLogDir, DEFLOGFILENAME, MAX_PATH);
+
+ g_Settings.pszLogDir[MAX_PATH - 1] = 0;
+
+ g_Settings.LogIndentEnabled = (M->GetByte("Chat", "LogIndentEnabled", 1) != 0) ? TRUE : FALSE;
+
+
+ // nicklist
+
+ if (g_Settings.UserListFont) {
+ DeleteObject(g_Settings.UserListFont);
+ DeleteObject(g_Settings.UserListHeadingsFont);
+ }
+
+ LoadMsgDlgFont(FONTSECTION_CHAT, 18, &lf, NULL, CHAT_FONTMODULE);
+ g_Settings.UserListFont = CreateFontIndirect(&lf);
+
+ LoadMsgDlgFont(FONTSECTION_CHAT, 19, &lf, NULL, CHAT_FONTMODULE);
+ g_Settings.UserListHeadingsFont = CreateFontIndirect(&lf);
+
+ int ih;
+ int ih2;
+
+ ih = GetTextPixelSize(_T("AQGglo"), g_Settings.UserListFont, FALSE);
+ ih2 = GetTextPixelSize(_T("AQGglo"), g_Settings.UserListHeadingsFont, FALSE);
+ g_Settings.iNickListFontHeight = max(M->GetByte("Chat", "NicklistRowDist", 12), (ih > ih2 ? ih : ih2));
+
+ for (i=0; i < 7; i++) {
+ mir_snprintf(szBuf, 20, "NickColor%d", i);
+ g_Settings.nickColors[i] = M->GetDword("Chat", szBuf, g_Settings.crUserListColor);
+ }
+ g_Settings.nickColors[5] = M->GetDword("Chat", "NickColor5", GetSysColor(COLOR_HIGHLIGHT));
+ g_Settings.nickColors[6] = M->GetDword("Chat", "NickColor6", GetSysColor(COLOR_HIGHLIGHTTEXT));
+ if (g_Settings.SelectionBGBrush)
+ DeleteObject(g_Settings.SelectionBGBrush);
+ g_Settings.SelectionBGBrush = CreateSolidBrush(g_Settings.nickColors[5]);
+}
+
+static void FreeGlobalSettings(void)
+{
+ mir_free(g_Settings.pszTimeStamp);
+ mir_free(g_Settings.pszTimeStampLog);
+ mir_free(g_Settings.pszIncomingNick);
+ mir_free(g_Settings.pszOutgoingNick);
+ if (g_Settings.UserListFont) {
+ DeleteObject(g_Settings.UserListFont);
+ DeleteObject(g_Settings.UserListHeadingsFont);
+ }
+ if (g_Settings.SelectionBGBrush)
+ DeleteObject(g_Settings.SelectionBGBrush);
+
+ delete g_Settings.Highlight;
+}
+
+int OptionsInit(void)
+{
+ LOGFONT lf;
+ HFONT hFont;
+ int iText;
+
+ LoadLogFonts();
+ LoadMsgDlgFont(FONTSECTION_CHAT, 17, &lf, NULL, CHAT_FONTMODULE);
+ lstrcpy(lf.lfFaceName, _T("MS Shell Dlg"));
+ lf.lfUnderline = lf.lfItalic = lf.lfStrikeOut = 0;
+ lf.lfHeight = -17;
+ lf.lfWeight = FW_BOLD;
+ ZeroMemory(&g_Settings, sizeof(TMUCSettings));
+ g_Settings.NameFont = CreateFontIndirect(&lf);
+ g_Settings.iSplitterX = DBGetContactSettingWord(NULL, "Chat", "SplitterX", 105);
+ if (g_Settings.iSplitterX <= 50)
+ g_Settings.iSplitterX = 105;
+ g_Settings.iSplitterY = DBGetContactSettingWord(NULL, "Chat", "splitY", 50);
+ if (g_Settings.iSplitterY <= 20)
+ g_Settings.iSplitterY = 50;
+ g_Settings.hGroup = 0;
+ LoadGlobalSettings();
+ g_Settings.Highlight = new CMUCHighlight();
+
+ SkinAddNewSoundEx("ChatMessage", LPGEN("Group chats"), LPGEN("Incoming message"));
+ SkinAddNewSoundEx("ChatSent", LPGEN("Group chats"), LPGEN("Outgoing message"));
+ SkinAddNewSoundEx("ChatHighlight", LPGEN("Group chats"), LPGEN("Message is highlighted"));
+ SkinAddNewSoundEx("ChatAction", LPGEN("Group chats"), LPGEN("User has performed an action"));
+ SkinAddNewSoundEx("ChatJoin", LPGEN("Group chats"), LPGEN("User has joined"));
+ SkinAddNewSoundEx("ChatPart", LPGEN("Group chats"), LPGEN("User has left"));
+ SkinAddNewSoundEx("ChatKick", LPGEN("Group chats"), LPGEN("User has kicked some other user"));
+ SkinAddNewSoundEx("ChatMode", LPGEN("Group chats"), LPGEN("User's status was changed"));
+ SkinAddNewSoundEx("ChatNick", LPGEN("Group chats"), LPGEN("User has changed name"));
+ SkinAddNewSoundEx("ChatNotice", LPGEN("Group chats"), LPGEN("User has sent a notice"));
+ SkinAddNewSoundEx("ChatQuit", LPGEN("Group chats"), LPGEN("User has disconnected"));
+ SkinAddNewSoundEx("ChatTopic", LPGEN("Group chats"), LPGEN("The topic has been changed"));
+
+ LoadMsgDlgFont(FONTSECTION_CHAT, 0, &lf, NULL, CHAT_FONTMODULE);
+ hFont = CreateFontIndirect(&lf);
+ iText = GetTextPixelSize(MakeTimeStamp(g_Settings.pszTimeStamp, time(NULL)), hFont, TRUE);
+ DeleteObject(hFont);
+ g_Settings.LogTextIndent = iText;
+ g_Settings.LogTextIndent = g_Settings.LogTextIndent * 12 / 10;
+ return 0;
+}
+
+
+int OptionsUnInit(void)
+{
+ FreeGlobalSettings();
+ UnhookEvent(g_hOptions);
+ DeleteObject(hListBkgBrush);
+ DeleteObject(g_Settings.NameFont);
+ return 0;
+}
diff --git a/plugins/TabSRMM/src/chat/services.cpp b/plugins/TabSRMM/src/chat/services.cpp
new file mode 100644
index 0000000000..edd9f25d79
--- /dev/null
+++ b/plugins/TabSRMM/src/chat/services.cpp
@@ -0,0 +1,882 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda NG, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: services.cpp 13046 2010-10-28 10:02:50Z silvercircle $
+ *
+ * This implements the services that form the group chat API
+ *
+ */
+
+#include "..\commonheaders.h"
+
+// defs
+extern HICON hIcons[30];
+
+CRITICAL_SECTION cs;
+
+HANDLE hSendEvent;
+HANDLE hBuildMenuEvent;
+HANDLE hJoinMenuItem, hLeaveMenuItem;
+HANDLE g_hHookPrebuildMenu;
+
+static HANDLE
+ hServiceRegister = NULL,
+ hServiceNewChat = NULL,
+ hServiceAddEvent = NULL,
+ hServiceGetAddEventPtr = NULL,
+ hServiceGetInfo = NULL,
+ hServiceGetCount = NULL,
+ hEventPrebuildMenu = NULL,
+ hEventDoubleclicked = NULL,
+ hEventJoinChat = NULL,
+ hEventLeaveChat = NULL;
+
+int Chat_ModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ if (!PluginConfig.m_chat_enabled)
+ return 0;
+
+ char * mods[3] = {"Chat", CHAT_FONTMODULE};
+ CallService("DBEditorpp/RegisterModule", (WPARAM)mods, (LPARAM)2);
+
+ LoadIcons();
+
+ CLISTMENUITEM mi = { 0 };
+ mi.cbSize = sizeof(mi);
+ mi.position = -2000090001;
+ mi.flags = CMIF_DEFAULT | CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle( SKINICON_CHAT_JOIN );
+ mi.pszName = LPGEN("&Join");
+ mi.pszService = "GChat/JoinChat";
+ hJoinMenuItem = Menu_AddContactMenuItem(&mi);
+
+ mi.position = -2000090000;
+ mi.flags = CMIF_NOTOFFLINE | CMIF_ICONFROMICOLIB;
+ mi.icolibItem = LoadSkinnedIconHandle( SKINICON_CHAT_LEAVE );
+ mi.pszName = LPGEN("&Leave");
+ mi.pszService = "GChat/LeaveChat";
+ hLeaveMenuItem = Menu_AddContactMenuItem(&mi);
+
+ CList_SetAllOffline(TRUE, NULL);
+
+ g_Settings.MathMod = ServiceExists(MATH_RTF_REPLACE_FORMULAE) && M->GetByte("Chat", "MathModSupport", 0);
+ return 0;
+}
+
+int Chat_PreShutdown()
+{
+ SM_RemoveAll();
+ MM_RemoveAll();
+ return 0;
+}
+
+int Chat_IconsChanged(WPARAM wParam, LPARAM lParam)
+{
+ FreeMsgLogBitmaps();
+
+ LoadLogIcons();
+ LoadMsgLogBitmaps();
+ //MM_IconsChanged();
+ SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, FALSE);
+ return 0;
+}
+
+INT_PTR Service_GetCount(WPARAM wParam, LPARAM lParam)
+{
+ int i;
+
+ if (!lParam)
+ return -1;
+
+ EnterCriticalSection(&cs);
+
+ i = SM_GetCount((char *)lParam);
+
+ LeaveCriticalSection(&cs);
+ return i;
+}
+
+INT_PTR Service_GetInfo(WPARAM wParam, LPARAM lParam)
+{
+ GC_INFO * gci = (GC_INFO *) lParam;
+ SESSION_INFO* si = NULL;
+
+ if (!gci || !gci->pszModule)
+ return 1;
+
+ EnterCriticalSection(&cs);
+
+ if (gci->Flags&BYINDEX)
+ si = SM_FindSessionByIndex(gci->pszModule, gci->iItem);
+ else
+ si = SM_FindSession(gci->pszID, gci->pszModule);
+
+ if (si) {
+ if (gci->Flags & DATA) gci->dwItemData = si->dwItemData;
+ if (gci->Flags & HCONTACT) gci->hContact = si->hContact;
+ if (gci->Flags & TYPE) gci->iType = si->iType;
+ if (gci->Flags & COUNT) gci->iCount = si->nUsersInNicklist;
+ if (gci->Flags & USERS) gci->pszUsers = SM_GetUsers(si);
+
+ if (si->dwFlags & GC_UNICODE) {
+ if (gci->Flags & ID) gci->pszID = si->ptszID;
+ if (gci->Flags & NAME) gci->pszName = si->ptszName;
+ }
+ else {
+ if (gci->Flags & ID) gci->pszID = (TCHAR*)si->pszID;
+ if (gci->Flags & NAME) gci->pszName = (TCHAR*)si->pszName;
+ }
+ LeaveCriticalSection(&cs);
+ return 0;
+ }
+
+ LeaveCriticalSection(&cs);
+ return 1;
+}
+
+INT_PTR Service_Register(WPARAM wParam, LPARAM lParam)
+{
+ GCREGISTER *gcr = (GCREGISTER *)lParam;
+ MODULEINFO * mi = NULL;
+ if (gcr == NULL)
+ return GC_REGISTER_ERROR;
+
+ if (gcr->cbSize != sizeof(GCREGISTER))
+ return GC_REGISTER_WRONGVER;
+
+ EnterCriticalSection(&cs);
+
+ mi = MM_AddModule(gcr->pszModule);
+ if (mi) {
+ mi->ptszModDispName = a2tf( gcr->ptszModuleDispName, gcr->dwFlags);
+ mi->bBold = gcr->dwFlags & GC_BOLD;
+ mi->bUnderline = gcr->dwFlags & GC_UNDERLINE ;
+ mi->bItalics = gcr->dwFlags & GC_ITALICS ;
+ mi->bColor = gcr->dwFlags & GC_COLOR ;
+ mi->bBkgColor = gcr->dwFlags & GC_BKGCOLOR ;
+ mi->bAckMsg = gcr->dwFlags & GC_ACKMSG ;
+ mi->bChanMgr = gcr->dwFlags & GC_CHANMGR ;
+ mi->iMaxText = gcr->iMaxText;
+ mi->nColorCount = gcr->nColors;
+ if (gcr->nColors > 0) {
+ mi->crColors = (COLORREF *)mir_alloc(sizeof(COLORREF) * gcr->nColors);
+ memcpy(mi->crColors, gcr->pColors, sizeof(COLORREF) * gcr->nColors);
+ }
+ mi->pszHeader = 0;
+
+ CheckColorsInModule((char*)gcr->pszModule);
+ CList_SetAllOffline(TRUE, gcr->pszModule);
+
+ LeaveCriticalSection(&cs);
+ return 0;
+ }
+
+ LeaveCriticalSection(&cs);
+ return GC_REGISTER_ERROR;
+}
+
+INT_PTR Service_NewChat(WPARAM wParam, LPARAM lParam)
+{
+ MODULEINFO* mi;
+ GCSESSION *gcw = (GCSESSION *)lParam;
+ if (gcw == NULL)
+ return GC_NEWSESSION_ERROR;
+
+ if (gcw->cbSize != sizeof(GCSESSION))
+ return GC_NEWSESSION_WRONGVER;
+
+ EnterCriticalSection(&cs);
+
+ if ((mi = MM_FindModule(gcw->pszModule)) != NULL) {
+ TCHAR* ptszID = a2tf(gcw->ptszID, gcw->dwFlags);
+ SESSION_INFO* si = SM_AddSession(ptszID, gcw->pszModule);
+
+ // create a new session and set the defaults
+ if (si != NULL) {
+ TCHAR szTemp[256];
+
+ si->dwItemData = gcw->dwItemData;
+ if (gcw->iType != GCW_SERVER)
+ si->wStatus = ID_STATUS_ONLINE;
+ si->iType = gcw->iType;
+ si->dwFlags = gcw->dwFlags;
+ si->ptszName = a2tf(gcw->ptszName, gcw->dwFlags);
+ si->ptszStatusbarText = a2tf(gcw->ptszStatusbarText, gcw->dwFlags);
+ si->iSplitterX = g_Settings.iSplitterX;
+ si->bFilterEnabled = M->GetByte(si->hContact, "Chat", "FilterEnabled", M->GetByte("Chat", "FilterEnabled", 0));
+ si->bNicklistEnabled = M->GetByte("Chat", "ShowNicklist", 1);
+ if (!(gcw->dwFlags & GC_UNICODE)) {
+ si->pszID = mir_strdup(gcw->pszID);
+ si->pszName = mir_strdup(gcw->pszName);
+ }
+
+ if (mi->bColor) {
+ si->iFG = 4;
+ si->bFGSet = TRUE;
+ }
+ if (mi->bBkgColor) {
+ si->iBG = 2;
+ si->bBGSet = TRUE;
+ }
+ if (si->iType == GCW_SERVER)
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("Server: %s"), si->ptszName);
+ else
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s"), si->ptszName);
+ si->hContact = CList_AddRoom(gcw->pszModule, ptszID, szTemp, si->iType);
+ DBWriteContactSettingString(si->hContact, si->pszModule , "Topic", "");
+ DBDeleteContactSetting(si->hContact, "CList", "StatusMsg");
+ if (si->ptszStatusbarText)
+ M->WriteTString(si->hContact, si->pszModule, "StatusBar", si->ptszStatusbarText);
+ else
+ DBWriteContactSettingString(si->hContact, si->pszModule, "StatusBar", "");
+ if (si->hContact)
+ Chat_SetFilters(si);
+ }
+ else {
+ SESSION_INFO* si2 = SM_FindSession(ptszID, gcw->pszModule);
+ if (si2) {
+
+ UM_RemoveAll(&si2->pUsers);
+ TM_RemoveAll(&si2->pStatuses);
+
+ si2->iStatusCount = 0;
+ si2->nUsersInNicklist = 0;
+
+ if (si2->hContact)
+ Chat_SetFilters(si2);
+ if (si2->hWnd)
+ RedrawWindow(GetDlgItem(si2->hWnd, IDC_LIST), NULL, NULL, RDW_INVALIDATE);
+ }
+ }
+
+ LeaveCriticalSection(&cs);
+ mir_free(ptszID);
+ return 0;
+ }
+
+ LeaveCriticalSection(&cs);
+ return GC_NEWSESSION_ERROR;
+}
+
+static int DoControl(GCEVENT * gce, WPARAM wp)
+{
+ SESSION_INFO* si;
+
+ switch(gce->pDest->iType) {
+ case GC_EVENT_CONTROL:
+ switch (wp) {
+ case WINDOW_HIDDEN:
+ si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ si->bInitDone = TRUE;
+ SetActiveSession(si->ptszID, si->pszModule);
+ if (si->hWnd)
+ ShowRoom(si, wp, FALSE);
+ }
+ return 0;
+
+ case WINDOW_MINIMIZE:
+ case WINDOW_MAXIMIZE:
+ case WINDOW_VISIBLE:
+ case SESSION_INITDONE:
+ si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ si->bInitDone = TRUE;
+ if (wp != SESSION_INITDONE || M->GetByte("Chat", "PopupOnJoin", 0) == 0)
+ ShowRoom(si, wp, TRUE);
+ return 0;
+ }
+ break;
+
+ case SESSION_OFFLINE:
+ SM_SetOffline(gce->pDest->ptszID, gce->pDest->pszModule);
+ // fall through
+
+ case SESSION_ONLINE:
+ SM_SetStatus(gce->pDest->ptszID, gce->pDest->pszModule, wp == SESSION_ONLINE ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE);
+ break;
+
+ case WINDOW_CLEARLOG:
+ si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ LM_RemoveAll(&si->pLog, &si->pLogEnd);
+ si->iEventCount = 0;
+ si->LastTime = 0;
+ }
+ break;
+
+ case SESSION_TERMINATE:
+ return SM_RemoveSession(gce->pDest->ptszID, gce->pDest->pszModule, (gce->dwFlags & GCEF_REMOVECONTACT) != 0);
+ }
+ SM_SendMessage(gce->pDest->ptszID, gce->pDest->pszModule, GC_EVENT_CONTROL + WM_USER + 500, wp, 0);
+ break;
+
+ case GC_EVENT_CHUID:
+ if (gce->pszText)
+ SM_ChangeUID(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszNick, gce->ptszText);
+ break;
+
+ case GC_EVENT_CHANGESESSIONAME:
+ if (gce->pszText) {
+ si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ replaceStr(&si->ptszName, gce->ptszText);
+ if (si->hWnd)
+ SendMessage(si->hWnd, GC_UPDATETITLE, 0, 0);
+ }
+ }
+ break;
+
+ case GC_EVENT_SETITEMDATA:
+ si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si)
+ si->dwItemData = gce->dwItemData;
+ break;
+
+ case GC_EVENT_GETITEMDATA:
+ si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ gce->dwItemData = si->dwItemData;
+ return si->dwItemData;
+ }
+ return 0;
+
+ case GC_EVENT_SETSBTEXT:
+ si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ replaceStr(&si->ptszStatusbarText, gce->ptszText);
+ if (si->ptszStatusbarText)
+ M->WriteTString(si->hContact, si->pszModule, "StatusBar", si->ptszStatusbarText);
+ else
+ DBWriteContactSettingString(si->hContact, si->pszModule, "StatusBar", "");
+ if (si->hWnd)
+ SendMessage(si->hWnd, GC_UPDATESTATUSBAR, 0, 0);
+ }
+ break;
+
+ case GC_EVENT_ACK:
+ SM_SendMessage(gce->pDest->ptszID, gce->pDest->pszModule, GC_ACKMESSAGE, 0, 0);
+ break;
+
+ case GC_EVENT_SENDMESSAGE:
+ if (gce->pszText)
+ SM_SendUserMessage(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszText);
+ break;
+
+ case GC_EVENT_SETSTATUSEX:
+ SM_SetStatusEx(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszText, gce->dwItemData);
+ break;
+
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+static void AddUser(GCEVENT * gce)
+{
+ SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ WORD status = TM_StringToWord(si->pStatuses, gce->ptszStatus);
+ USERINFO * ui = SM_AddUser(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID, gce->ptszNick, status);
+ if (ui) {
+ ui->pszNick = mir_tstrdup(gce->ptszNick);
+
+ if (gce->bIsMe)
+ si->pMe = ui;
+
+ ui->Status = status;
+ ui->Status |= si->pStatuses->Status;
+
+ if (si->hWnd) {
+ SendMessage(si->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0);
+ if (si->dat)
+ GetMyNick(si->dat);
+ }
+ }
+ }
+}
+
+HWND CreateNewRoom(TContainerData *pContainer, SESSION_INFO *si, BOOL bActivateTab, BOOL bPopupContainer, BOOL bWantPopup)
+{
+ HANDLE hContact = si->hContact;
+ if (M->FindWindow(hContact) != 0)
+ return 0;
+
+ if (hContact != 0 && M->GetByte("limittabs", 0) && !_tcsncmp(pContainer->szName, _T("default"), 6)) {
+ if ((pContainer = FindMatchingContainer(_T("default"), hContact)) == NULL) {
+ TCHAR szName[CONTAINER_NAMELEN + 1];
+
+ _sntprintf(szName, CONTAINER_NAMELEN, _T("default"));
+ pContainer = CreateContainer(szName, CNT_CREATEFLAG_CLONED, hContact);
+ }
+ }
+
+ TNewWindowData newData = { 0 };
+ newData.hContact = hContact;
+ newData.isWchar = 0;
+ newData.szInitialText = NULL;
+ memset(&newData.item, 0, sizeof(newData.item));
+
+ TCHAR *contactName = (TCHAR *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) newData.hContact, GCDNF_TCHAR);
+
+ /*
+ * cut nickname if larger than x chars...
+ */
+
+ TCHAR newcontactname[128];
+ if ( lstrlen(contactName) > 0) {
+ if (M->GetByte("cuttitle", 0))
+ CutContactName(contactName, newcontactname, safe_sizeof(newcontactname));
+ else {
+ lstrcpyn(newcontactname, contactName, safe_sizeof(newcontactname));
+ newcontactname[127] = 0;
+ }
+ }
+ else lstrcpyn(newcontactname, _T("_U_"), SIZEOF(newcontactname));
+
+ char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) newData.hContact, 0);
+ WORD wStatus = szProto == NULL ? ID_STATUS_OFFLINE : DBGetContactSettingWord((HANDLE) newData.hContact, szProto, "Status", ID_STATUS_OFFLINE);
+ char *szStatus = (char *) CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, szProto == NULL ? ID_STATUS_OFFLINE : DBGetContactSettingWord((HANDLE)newData.hContact, szProto, "Status", ID_STATUS_OFFLINE), 0);
+
+ newData.item.pszText = newcontactname;
+ newData.item.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM;
+ newData.item.iImage = 0;
+
+ HWND hwndTab = GetDlgItem(pContainer->hwnd, 1159);
+
+ // hide the active tab
+ if (pContainer->hwndActive && bActivateTab)
+ ShowWindow(pContainer->hwndActive, SW_HIDE);
+
+ {
+ int iTabIndex_wanted = M->GetDword(hContact, "tabindex", pContainer->iChilds * 100);
+ int iCount = TabCtrl_GetItemCount(hwndTab);
+ TCITEM item = {0};
+ HWND hwnd;
+ struct TWindowData *dat;
+ int relPos;
+ int i;
+
+ pContainer->iTabIndex = iCount;
+ if (iCount > 0) {
+ for (i = iCount - 1; i >= 0; i--) {
+ item.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwndTab, i, &item);
+ hwnd = (HWND)item.lParam;
+ dat = (struct TWindowData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ if (dat) {
+ relPos = M->GetDword(dat->hContact, "tabindex", i * 100);
+ if (iTabIndex_wanted <= relPos)
+ pContainer->iTabIndex = i;
+ }
+ }
+ }
+ }
+
+ int newItem = TabCtrl_InsertItem(hwndTab, pContainer->iTabIndex, &newData.item);
+ SendMessage(hwndTab, EM_REFRESHWITHOUTCLIP, 0, 0);
+ if (bActivateTab)
+ TabCtrl_SetCurSel(hwndTab, newItem);
+ newData.iTabID = newItem;
+ newData.iTabImage = newData.item.iImage;
+ newData.pContainer = pContainer;
+ newData.iActivate = (int) bActivateTab;
+ pContainer->iChilds++;
+ newData.bWantPopup = bWantPopup;
+ newData.hdbEvent = (HANDLE)si;
+ HWND hwndNew = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_CHANNEL), GetDlgItem(pContainer->hwnd, 1159), RoomWndProc, (LPARAM) & newData);
+ if (pContainer->dwFlags & CNT_SIDEBAR) {
+ TWindowData *dat = (TWindowData *)GetWindowLongPtr(hwndNew, GWLP_USERDATA);
+ if (dat)
+ pContainer->SideBar->addSession(dat, pContainer->iTabIndex);
+ }
+ SendMessage(pContainer->hwnd, WM_SIZE, 0, 0);
+ // if the container is minimized, then pop it up...
+ if (IsIconic(pContainer->hwnd)) {
+ if (bPopupContainer) {
+ SendMessage(pContainer->hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
+ SetFocus(pContainer->hwndActive);
+ }
+ else {
+ if (pContainer->dwFlags & CNT_NOFLASH)
+ SendMessage(pContainer->hwnd, DM_SETICON, 0, (LPARAM)LoadSkinnedIcon(SKINICON_EVENT_MESSAGE));
+ else
+ FlashContainer(pContainer, 1, 0);
+ }
+ }
+ if (bActivateTab) {
+ if (PluginConfig.m_HideOnClose && !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 {
+ if (bPopupContainer)
+ ShowWindow(pContainer->hwnd, SW_SHOWNORMAL);
+ else
+ ShowWindow(pContainer->hwnd, SW_SHOWMINNOACTIVE);
+ }
+ 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 && bPopupContainer == TRUE)
+ 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);
+ return hwndNew; // return handle of the new dialog
+}
+
+void ShowRoom(SESSION_INFO* si, WPARAM wp, BOOL bSetForeground)
+{
+ if (!si)
+ return;
+
+ if (si->hWnd != NULL) {
+ ActivateExistingTab(si->pContainer, si->hWnd);
+ return;
+ }
+
+ TCHAR szName[CONTAINER_NAMELEN + 2];
+ TContainerData *pContainer = si->pContainer;
+
+ szName[0] = 0;
+ if (pContainer == NULL) {
+ GetContainerNameForContact(si->hContact, szName, CONTAINER_NAMELEN);
+ if (!g_Settings.OpenInDefault && !_tcscmp(szName, _T("default")))
+ _tcsncpy(szName, _T("Chat Rooms"), CONTAINER_NAMELEN);
+ szName[CONTAINER_NAMELEN] = 0;
+ pContainer = FindContainerByName(szName);
+ }
+ if (pContainer == NULL)
+ pContainer = CreateContainer(szName, FALSE, si->hContact);
+ si->hWnd = CreateNewRoom(pContainer, si, TRUE, TRUE, FALSE);
+}
+
+INT_PTR Service_AddEvent(WPARAM wParam, LPARAM lParam)
+{
+ GCEVENT *gce = (GCEVENT*)lParam;
+ GCDEST *gcd = NULL;
+ GCEVENT save_gce;
+ GCDEST save_gcd;
+ TCHAR* pWnd = NULL;
+ char* pMod = NULL;
+ BOOL bIsHighlighted = FALSE;
+ BOOL bRemoveFlag = FALSE;
+ int iRetVal = GC_EVENT_ERROR;
+ SESSION_INFO *si = NULL;
+ BOOL fFreeText = FALSE;
+
+ if (CMimAPI::m_shutDown)
+ return 0;
+
+ if (gce == NULL)
+ return GC_EVENT_ERROR;
+
+ gcd = gce->pDest;
+ if (gcd == NULL)
+ return GC_EVENT_ERROR;
+
+ if (gce->cbSize != sizeof(GCEVENT))
+ return GC_EVENT_WRONGVER;
+
+ if (!IsEventSupported(gcd->iType))
+ return GC_EVENT_ERROR;
+
+ if (!(gce->dwFlags & GC_UNICODE)) {
+ save_gce = *gce;
+ save_gcd = *gce->pDest;
+ gce->pDest->ptszID = a2tf(gce->pDest->ptszID, gce->dwFlags);
+ gce->ptszUID = a2tf(gce->ptszUID, gce->dwFlags);
+ gce->ptszNick = a2tf(gce->ptszNick, gce->dwFlags);
+ gce->ptszStatus = a2tf(gce->ptszStatus, gce->dwFlags);
+ if (gcd->iType != GC_EVENT_MESSAGE && gcd->iType != GC_EVENT_ACTION) {
+ gce->ptszText = a2tf(gce->ptszText, gce->dwFlags);
+ fFreeText = TRUE;
+ }
+ gce->ptszUserInfo = a2tf(gce->ptszUserInfo, gce->dwFlags);
+ }
+
+ EnterCriticalSection(&cs);
+
+ // Do different things according to type of event
+ switch (gcd->iType) {
+ case GC_EVENT_ADDGROUP:
+ {
+ STATUSINFO* si = SM_AddStatus(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszStatus);
+ if (si && gce->dwItemData)
+ si->hIcon = CopyIcon((HICON)gce->dwItemData);
+ }
+ iRetVal = 0;
+ goto LBL_Exit;
+
+ case GC_EVENT_CHUID:
+ case GC_EVENT_CHANGESESSIONAME:
+ case GC_EVENT_SETITEMDATA:
+ case GC_EVENT_GETITEMDATA:
+ case GC_EVENT_CONTROL:
+ case GC_EVENT_SETSBTEXT:
+ case GC_EVENT_ACK:
+ case GC_EVENT_SENDMESSAGE :
+ case GC_EVENT_SETSTATUSEX :
+ iRetVal = DoControl(gce, wParam);
+ goto LBL_Exit;
+
+ case GC_EVENT_SETCONTACTSTATUS:
+ iRetVal = SM_SetContactStatus(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID, (WORD)gce->dwItemData);
+ goto LBL_Exit;
+
+ case GC_EVENT_TOPIC:
+ si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ if (gce->pszText) {
+ replaceStr(&si->ptszTopic, RemoveFormatting(gce->ptszText));
+ M->WriteTString(si->hContact, si->pszModule , "Topic", /*RemoveFormatting*/(si->ptszTopic));
+ if (M->GetByte("Chat", "TopicOnClist", 1))
+ M->WriteTString(si->hContact, "CList" , "StatusMsg", /*RemoveFormatting*/(si->ptszTopic));
+ if (si->hWnd)
+ SendMessage(si->hWnd, DM_INVALIDATEPANEL, 0, 0);
+ }
+ }
+ break;
+
+ case GC_EVENT_ADDSTATUS:
+ SM_GiveStatus(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID, gce->ptszStatus);
+ if (!gce->bIsMe)
+ bIsHighlighted = g_Settings.Highlight->match(gce, 0, CMUCHighlight::MATCH_NICKNAME);
+ break;
+
+ case GC_EVENT_REMOVESTATUS:
+ SM_TakeStatus(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID, gce->ptszStatus);
+ if (!gce->bIsMe)
+ bIsHighlighted = g_Settings.Highlight->match(gce, 0, CMUCHighlight::MATCH_NICKNAME);
+ break;
+
+ case GC_EVENT_MESSAGE:
+ case GC_EVENT_ACTION:
+ si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (!(gce->dwFlags & GC_UNICODE)) {
+ fFreeText = TRUE;
+ if (si)
+ gce->ptszText = a2tf(gce->ptszText, gce->dwFlags, M->GetDword(si->hContact, "ANSIcodepage", 0));
+ else
+ gce->ptszText = a2tf(gce->ptszText, gce->dwFlags);
+ }
+ if (!gce->bIsMe && gce->pDest->pszID && gce->pszText && si)
+ bIsHighlighted = si->Highlight->match(gce, si, CMUCHighlight::MATCH_TEXT | CMUCHighlight::MATCH_NICKNAME);
+ break;
+
+ case GC_EVENT_NICK:
+ SM_ChangeNick(gce->pDest->ptszID, gce->pDest->pszModule, gce);
+ if (!gce->bIsMe)
+ bIsHighlighted = g_Settings.Highlight->match(gce, 0, CMUCHighlight::MATCH_NICKNAME);
+ break;
+
+ case GC_EVENT_JOIN:
+ AddUser(gce);
+ if (!gce->bIsMe)
+ bIsHighlighted = g_Settings.Highlight->match(gce, 0, CMUCHighlight::MATCH_NICKNAME);
+ break;
+
+ case GC_EVENT_PART:
+ case GC_EVENT_QUIT:
+ case GC_EVENT_KICK:
+ bRemoveFlag = TRUE;
+ if (!gce->bIsMe)
+ bIsHighlighted = g_Settings.Highlight->match(gce, 0, CMUCHighlight::MATCH_NICKNAME);
+ break;
+ }
+
+ // Decide which window (log) should have the event
+ if (gcd->pszID) {
+ pWnd = gcd->ptszID;
+ pMod = gcd->pszModule;
+ }
+ else if ( gcd->iType == GC_EVENT_NOTICE || gcd->iType == GC_EVENT_INFORMATION ) {
+ SESSION_INFO* si = GetActiveSession();
+ if (si && !lstrcmpA(si->pszModule, gcd->pszModule)) {
+ pWnd = si->ptszID;
+ pMod = si->pszModule;
+ }
+ else {
+ iRetVal = 0;
+ goto LBL_Exit;
+ }
+ }
+ else {
+ // Send the event to all windows with a user pszUID. Used for broadcasting QUIT etc
+ SM_AddEventToAllMatchingUID(gce, bIsHighlighted);
+ if (!bRemoveFlag) {
+ iRetVal = 0;
+ goto LBL_Exit;
+ } }
+
+ // add to log
+ if (pWnd) {
+ if (si == NULL)
+ si = SM_FindSession(pWnd, pMod);
+
+ // fix for IRC's old stuyle mode notifications. Should not affect any other protocol
+ if ((gce->pDest->iType == GC_EVENT_ADDSTATUS || gce->pDest->iType == GC_EVENT_REMOVESTATUS) && !(gce->dwFlags & GCEF_ADDTOLOG)) {
+ iRetVal = 0;
+ goto LBL_Exit;
+ }
+
+ if (gce && gce->pDest->iType == GC_EVENT_JOIN && gce->time == 0) {
+ iRetVal = 0;
+ goto LBL_Exit;
+ }
+
+ if (si && (si->bInitDone || gce->pDest->iType == GC_EVENT_TOPIC || (gce->pDest->iType == GC_EVENT_JOIN && gce->bIsMe))) {
+ if (SM_AddEvent(pWnd, pMod, gce, bIsHighlighted) && si->hWnd) {
+ SendMessage(si->hWnd, GC_ADDLOG, 0, 0);
+ }
+ else if (si->hWnd) {
+ SendMessage(si->hWnd, GC_REDRAWLOG2, 0, 0);
+ }
+ DoSoundsFlashPopupTrayStuff(si, gce, bIsHighlighted, 0);
+ if ((gce->dwFlags & GCEF_ADDTOLOG) && g_Settings.LoggingEnabled)
+ LogToFile(si, gce);
+ }
+
+ if (!bRemoveFlag) {
+ iRetVal = 0;
+ goto LBL_Exit;
+ } }
+
+ if (bRemoveFlag)
+ iRetVal = (SM_RemoveUser(gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID) == 0) ? 1 : 0;
+
+LBL_Exit:
+ LeaveCriticalSection(&cs);
+
+ if (!(gce->dwFlags & GC_UNICODE)) {
+ if (fFreeText)
+ mir_free((void*)gce->ptszText);
+ mir_free((void*)gce->ptszNick);
+ mir_free((void*)gce->ptszUID);
+ mir_free((void*)gce->ptszStatus);
+ mir_free((void*)gce->ptszUserInfo);
+ mir_free((void*)gce->pDest->ptszID);
+ *gce = save_gce;
+ *gce->pDest = save_gcd;
+ }
+ return iRetVal;
+}
+
+static INT_PTR Service_GetAddEventPtr(WPARAM wParam, LPARAM lParam)
+{
+ GCPTRS * gp = (GCPTRS *) lParam;
+
+ EnterCriticalSection(&cs);
+
+ gp->pfnAddEvent = Service_AddEvent;
+ LeaveCriticalSection(&cs);
+ return 0;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Service creation
+
+void HookEvents(void)
+{
+ InitializeCriticalSection(&cs);
+ g_hHookPrebuildMenu = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, CList_PrebuildContactMenu); // MIRANDAHOOK should return INT_PTR too
+}
+
+void UnhookEvents(void)
+{
+ UnhookEvent(g_hHookPrebuildMenu);
+ DeleteCriticalSection(&cs);
+}
+
+int CreateServiceFunctions(void)
+{
+ PluginConfig.m_chat_enabled = false;
+
+ if (ServiceExists(MS_GC_REGISTER)) {
+ LRESULT result = CWarning::show(CWarning::WARN_CHAT_ENABLED, CWarning::CWF_NOALLOWHIDE | MB_YESNOCANCEL | MB_ICONQUESTION);
+ if (result == IDYES)
+ M->WriteByte("PluginDisable", "chat.dll", 1);
+ return 0;
+ }
+ PluginConfig.m_chat_enabled = true;
+
+ hServiceRegister = CreateServiceFunction(MS_GC_REGISTER, Service_Register);
+ hServiceNewChat = CreateServiceFunction(MS_GC_NEWSESSION, Service_NewChat);
+ hServiceAddEvent = CreateServiceFunction(MS_GC_EVENT, Service_AddEvent);
+ hServiceGetAddEventPtr = CreateServiceFunction(MS_GC_GETEVENTPTR, Service_GetAddEventPtr);
+ hServiceGetInfo = CreateServiceFunction(MS_GC_GETINFO, Service_GetInfo);
+ hServiceGetCount = CreateServiceFunction(MS_GC_GETSESSIONCOUNT, Service_GetCount);
+
+ hEventDoubleclicked = CreateServiceFunction("GChat/DblClickEvent", CList_EventDoubleclicked);
+ hEventPrebuildMenu = CreateServiceFunction("GChat/PrebuildMenuEvent", CList_PrebuildContactMenuSvc);
+ hEventJoinChat = CreateServiceFunction("GChat/JoinChat", CList_JoinChat);
+ hEventLeaveChat = CreateServiceFunction("GChat/LeaveChat", CList_LeaveChat);
+ return 1;
+}
+
+void DestroyServiceFunctions(void)
+{
+ DestroyServiceFunction(hServiceRegister);
+ DestroyServiceFunction(hServiceNewChat);
+ DestroyServiceFunction(hServiceAddEvent);
+ DestroyServiceFunction(hServiceGetAddEventPtr);
+ DestroyServiceFunction(hServiceGetInfo);
+ DestroyServiceFunction(hServiceGetCount);
+ DestroyServiceFunction(hEventDoubleclicked);
+ DestroyServiceFunction(hEventPrebuildMenu);
+ DestroyServiceFunction(hEventJoinChat);
+ DestroyServiceFunction(hEventLeaveChat);
+}
+
+void CreateHookableEvents(void)
+{
+ hSendEvent = CreateHookableEvent(ME_GC_EVENT);
+ hBuildMenuEvent = CreateHookableEvent(ME_GC_BUILDMENU);
+}
+
+void DestroyHookableEvents(void)
+{
+ DestroyHookableEvent(hSendEvent);
+ DestroyHookableEvent(hBuildMenuEvent);
+}
diff --git a/plugins/TabSRMM/src/chat/tools.cpp b/plugins/TabSRMM/src/chat/tools.cpp
new file mode 100644
index 0000000000..7662aaf722
--- /dev/null
+++ b/plugins/TabSRMM/src/chat/tools.cpp
@@ -0,0 +1,1353 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda NG, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: tools.cpp 13650 2011-05-30 11:53:13Z silvercircle@gmail.com $
+ *
+ * Helper functions for the group chat module.
+ *
+ */
+
+#include "..\commonheaders.h"
+
+// externs
+extern HICON hIcons[30];
+extern FONTINFO aFonts[OPTIONS_FONTCOUNT];
+extern HMENU g_hMenu;
+extern HANDLE hBuildMenuEvent ;
+extern HANDLE hSendEvent;
+
+int GetRichTextLength(HWND hwnd)
+{
+ GETTEXTLENGTHEX gtl;
+
+ gtl.flags = GTL_PRECISE;
+ gtl.codepage = CP_ACP ;
+ return (int) SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
+}
+
+/**
+ * @param pszWord string to strip of any IRC-style
+ * formatting
+ * @param fToLower convert to lowercase
+ * @param fStripCR strip cr/lf sequences (only for highlighter, defaults to false)
+ * @param buf caller-provided buffer, use a static one
+ * when the caller does not provide a
+ * buffer
+ * caller provided buffer is NEEDED to make
+ * this thread-safe.
+ *
+ * @return TCHAR* the stripped string
+ */
+TCHAR* RemoveFormatting(const TCHAR* pszWord, bool fToLower, bool fStripCR, TCHAR* buf, const size_t len)
+{
+ static TCHAR _szTemp[20000];
+ TCHAR* szTemp = 0;
+ size_t _buflen = 0;
+
+ if (0 == buf) {
+ szTemp = _szTemp;
+ _buflen = 20000;
+ } else {
+ szTemp = buf;
+ _buflen = len;
+ szTemp[len - 1] = 0;
+ }
+
+ size_t i = 0;
+ size_t j = 0;
+
+ if (pszWord == 0)
+ return NULL;
+
+ size_t wordlen = lstrlen(pszWord);
+
+ while (j < _buflen && i <= wordlen) {
+ if (pszWord[i] == '%') {
+ switch (pszWord[i+1]) {
+ case '%':
+ szTemp[j] = '%';
+ j++;
+ i++;
+ i++;
+ break;
+ case 'b':
+ case 'u':
+ case 'i':
+ case 'B':
+ case 'U':
+ case 'I':
+ case 'r':
+ case 'C':
+ case 'F':
+ i++;
+ i++;
+ break;
+
+ case 'c':
+ case 'f':
+ i += 4;
+ break;
+
+ default:
+ szTemp[j] = pszWord[i];
+ j++;
+ i++;
+ break;
+ }
+ } else {
+ if (fStripCR) {
+ if (0x0a == pszWord[i] || 0x0c == pszWord[i]) {
+ szTemp[j++] = ' ';
+ i++;
+ continue;
+ }
+ }
+ szTemp[j] = pszWord[i];
+ j++;
+ i++;
+ }
+ }
+ if (fToLower) {
+ _wsetlocale(LC_ALL, L"");
+ wcslwr(szTemp);
+ }
+ return(szTemp);
+}
+
+static void __stdcall ShowRoomFromPopup(void * pi)
+{
+ SESSION_INFO* si = (SESSION_INFO*) pi;
+ ShowRoom(si, WINDOW_VISIBLE, TRUE);
+}
+
+static void TSAPI Chat_OpenPopup(SESSION_INFO* si, HWND hwndPopup)
+{
+ CallFunctionAsync(ShowRoomFromPopup, si);
+ PUDeletePopUp(hwndPopup);
+}
+
+static void TSAPI Chat_DismissPopup(const SESSION_INFO* si, HWND hwndPopup)
+{
+ if (si->hContact)
+ if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->hContact, (LPARAM)szChatIconString);
+
+ if (si->hWnd && KillTimer(si->hWnd, TIMERID_FLASHWND))
+ FlashWindow(si->hWnd, FALSE);
+
+ PUDeletePopUp(hwndPopup);
+}
+
+static INT_PTR CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message) {
+ case WM_COMMAND:
+ if (HIWORD(wParam) == STN_CLICKED) {
+ SESSION_INFO* si = (SESSION_INFO*)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd, (LPARAM)0);;
+
+ if (si) {
+ if (nen_options.maskActL & MASK_OPEN)
+ Chat_OpenPopup(si, hWnd);
+ else
+ Chat_DismissPopup(si, hWnd);
+ }
+ return TRUE;
+ }
+ break;
+ case WM_CONTEXTMENU: {
+ SESSION_INFO* si = (SESSION_INFO*)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd, (LPARAM)0);
+
+ if (si && si->hContact) {
+ if (nen_options.maskActR & MASK_OPEN)
+ Chat_OpenPopup(si, hWnd);
+ else
+ Chat_DismissPopup(si, hWnd);
+ }
+ }
+ break;
+ }
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+static int ShowPopup(HANDLE hContact, SESSION_INFO* si, HICON hIcon, char* pszProtoName, TCHAR* pszRoomName, COLORREF crBkg, const TCHAR* fmt, ...)
+{
+ POPUPDATAT_V2 pd = {0};
+ va_list marker;
+ static TCHAR szBuf[4*1024];
+
+ if (!fmt || lstrlen(fmt) == 0 || lstrlen(fmt) > 2000)
+ return 0;
+
+ va_start(marker, fmt);
+ _vstprintf(szBuf, fmt, marker);
+ va_end(marker);
+
+ pd.lchContact = hContact;
+
+ if (hIcon)
+ pd.lchIcon = hIcon ;
+ else
+ pd.lchIcon = LoadIconEx(IDI_CHANMGR, "window", 0, 0);
+
+ mir_sntprintf(pd.lptzContactName, MAX_CONTACTNAME - 1, _T(TCHAR_STR_PARAM) _T(" - %s"),
+ pszProtoName, CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR));
+ lstrcpyn(pd.lptzText, TranslateTS(szBuf), MAX_SECONDLINE - 1);
+ pd.iSeconds = g_Settings.iPopupTimeout;
+
+ if (g_Settings.iPopupStyle == 2) {
+ pd.colorBack = 0;
+ pd.colorText = 0;
+ } else if (g_Settings.iPopupStyle == 3) {
+ pd.colorBack = g_Settings.crPUBkgColour;
+ pd.colorText = g_Settings.crPUTextColour;
+ } else {
+ pd.colorBack = M->GetDword(FONTMODULE, SRMSGSET_BKGCOLOUR_MUC, SRMSGDEFSET_BKGCOLOUR);
+ pd.colorText = crBkg;
+ }
+
+ pd.PluginWindowProc = (WNDPROC)PopupDlgProc;
+ pd.PluginData = si;
+ return PUAddPopUpT(&pd);
+}
+
+static BOOL DoTrayIcon(SESSION_INFO* si, GCEVENT * gce)
+{
+ int iEvent = gce->pDest->iType;
+
+ if (si && (iEvent & si->iLogTrayFlags)) {
+ switch (iEvent) {
+ case GC_EVENT_MESSAGE | GC_EVENT_HIGHLIGHT :
+ case GC_EVENT_ACTION | GC_EVENT_HIGHLIGHT :
+ CList_AddEvent(si->hContact, PluginConfig.g_IconMsgEvent, szChatIconString, 0,
+ TranslateT("%s wants your attention in %s"), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_MESSAGE :
+ CList_AddEvent(si->hContact, hIcons[ICON_MESSAGE], szChatIconString, CLEF_ONLYAFEW,
+ TranslateT("%s speaks in %s"), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_ACTION:
+ CList_AddEvent(si->hContact, hIcons[ICON_ACTION], szChatIconString, CLEF_ONLYAFEW,
+ TranslateT("%s speaks in %s"), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_JOIN:
+ CList_AddEvent(si->hContact, hIcons[ICON_JOIN], szChatIconString, CLEF_ONLYAFEW,
+ TranslateT("%s has joined %s"), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_PART:
+ CList_AddEvent(si->hContact, hIcons[ICON_PART], szChatIconString, CLEF_ONLYAFEW,
+ TranslateT("%s has left %s"), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_QUIT:
+ CList_AddEvent(si->hContact, hIcons[ICON_QUIT], szChatIconString, CLEF_ONLYAFEW,
+ TranslateT("%s has disconnected"), gce->ptszNick);
+ break;
+ case GC_EVENT_NICK:
+ CList_AddEvent(si->hContact, hIcons[ICON_NICK], szChatIconString, CLEF_ONLYAFEW,
+ TranslateT("%s is now known as %s"), gce->ptszNick, gce->pszText);
+ break;
+ case GC_EVENT_KICK:
+ CList_AddEvent(si->hContact, hIcons[ICON_KICK], szChatIconString, CLEF_ONLYAFEW,
+ TranslateT("%s kicked %s from %s"), gce->pszStatus, gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_NOTICE:
+ CList_AddEvent(si->hContact, hIcons[ICON_NOTICE], szChatIconString, CLEF_ONLYAFEW,
+ TranslateT("Notice from %s"), gce->ptszNick);
+ break;
+ case GC_EVENT_TOPIC:
+ CList_AddEvent(si->hContact, hIcons[ICON_TOPIC], szChatIconString, CLEF_ONLYAFEW,
+ TranslateT("Topic change in %s"), si->ptszName);
+ break;
+ case GC_EVENT_INFORMATION:
+ CList_AddEvent(si->hContact, hIcons[ICON_INFO], szChatIconString, CLEF_ONLYAFEW,
+ TranslateT("Information in %s"), si->ptszName);
+ break;
+ case GC_EVENT_ADDSTATUS:
+ CList_AddEvent(si->hContact, hIcons[ICON_ADDSTATUS], szChatIconString, CLEF_ONLYAFEW,
+ TranslateT("%s enables \'%s\' status for %s in %s"), gce->pszText, gce->pszStatus, gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ CList_AddEvent(si->hContact, hIcons[ICON_REMSTATUS], szChatIconString, CLEF_ONLYAFEW,
+ TranslateT("%s disables \'%s\' status for %s in %s"), gce->pszText, gce->pszStatus, gce->ptszNick, si->ptszName);
+ break;
+ }
+ }
+ return TRUE;
+}
+
+static BOOL DoPopup(SESSION_INFO* si, GCEVENT* gce, struct TWindowData* dat)
+{
+ int iEvent = gce->pDest->iType;
+ struct TContainerData *pContainer = dat ? dat->pContainer : NULL;
+ char *szProto = dat ? dat->szProto : si->pszModule;
+
+ TCHAR *bbStart, *bbEnd;
+ if (g_Settings.BBCodeInPopups)
+ {
+ bbStart = _T("[b]");
+ bbEnd = _T("[/b]");
+ } else
+ {
+ bbStart = bbEnd = _T("");
+ }
+
+ if (si && (iEvent & si->iLogPopupFlags)) {
+
+ if (nen_options.iMUCDisable) // no popups at all. Period
+ return 0;
+ /*
+ * check the status mode against the status mask
+ */
+
+ if (nen_options.dwStatusMask != -1) {
+ DWORD dwStatus = 0;
+ if (szProto != NULL) {
+ dwStatus = (DWORD)CallProtoService(szProto, PS_GETSTATUS, 0, 0);
+ if (!(dwStatus == 0 || dwStatus <= ID_STATUS_OFFLINE || ((1 << (dwStatus - ID_STATUS_ONLINE)) & nen_options.dwStatusMask))) // should never happen, but...
+ return 0;
+ }
+ }
+ if (dat && pContainer != 0) { // message window is open, need to check the container config if we want to see a popup nonetheless
+ if (nen_options.bWindowCheck) { // no popups at all for open windows... no exceptions
+ if (!PluginConfig.m_HideOnClose)
+ return 0;
+ if (pContainer->fHidden)
+ goto passed;
+ return 0;
+ }
+ if (pContainer->dwFlags & CNT_DONTREPORT && IsIconic(pContainer->hwnd)) // in tray counts as "minimised"
+ goto passed;
+ if (pContainer->dwFlags & CNT_DONTREPORTUNFOCUSED) {
+ if (!IsIconic(pContainer->hwnd) && GetForegroundWindow() != pContainer->hwnd && GetActiveWindow() != pContainer->hwnd)
+ goto passed;
+ }
+ if (pContainer->dwFlags & CNT_ALWAYSREPORTINACTIVE) {
+ if (pContainer->dwFlags & CNT_DONTREPORTFOCUSED)
+ goto passed;
+
+ if (pContainer->hwndActive == si->hWnd)
+ return 0;
+
+ goto passed;
+ }
+ return 0;
+ }
+passed:
+ int iNewEvent = iEvent;
+ COLORREF clr = 0;
+
+ if ((iNewEvent & GC_EVENT_HIGHLIGHT)) {
+ clr = aFonts[16].color;
+ iNewEvent &= ~GC_EVENT_HIGHLIGHT;
+ }
+ switch (iNewEvent) {
+ case GC_EVENT_MESSAGE :
+ ShowPopup(si->hContact, si, hIcons[ICON_MESSAGE], si->pszModule, si->ptszName, clr ? clr : aFonts[9].color,
+ TranslateT("%s%s says:%s %s"), bbStart, gce->ptszNick, bbEnd, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_ACTION:
+ ShowPopup(si->hContact, si, hIcons[ICON_ACTION], si->pszModule, si->ptszName, clr ? clr : aFonts[15].color, _T("%s %s"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_JOIN:
+ ShowPopup(si->hContact, si, hIcons[ICON_JOIN], si->pszModule, si->ptszName, clr ? clr : aFonts[3].color,
+ TranslateT("%s has joined"), gce->ptszNick);
+ break;
+ case GC_EVENT_PART:
+ if (!gce->pszText)
+ ShowPopup(si->hContact, si, hIcons[ICON_PART], si->pszModule, si->ptszName, clr ? clr : aFonts[4].color,
+ TranslateT("%s has left"), gce->ptszNick);
+ else
+ ShowPopup(si->hContact, si, hIcons[ICON_PART], si->pszModule, si->ptszName, clr ? clr : aFonts[4].color,
+ TranslateT("%s has left (%s)"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_QUIT:
+ if (!gce->pszText)
+ ShowPopup(si->hContact, si, hIcons[ICON_QUIT], si->pszModule, si->ptszName, clr ? clr : aFonts[5].color,
+ TranslateT("%s has disconnected"), gce->ptszNick);
+ else
+ ShowPopup(si->hContact, si, hIcons[ICON_QUIT], si->pszModule, si->ptszName, clr ? clr : aFonts[5].color,
+ TranslateT("%s has disconnected (%s)"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_NICK:
+ ShowPopup(si->hContact, si, hIcons[ICON_NICK], si->pszModule, si->ptszName, clr ? clr : aFonts[7].color,
+ TranslateT("%s is now known as %s"), gce->ptszNick, gce->ptszText);
+ break;
+ case GC_EVENT_KICK:
+ if (!gce->pszText)
+ ShowPopup(si->hContact, si, hIcons[ICON_KICK], si->pszModule, si->ptszName, clr ? clr : aFonts[6].color,
+ TranslateT("%s kicked %s"), (char *)gce->pszStatus, gce->ptszNick);
+ else
+ ShowPopup(si->hContact, si, hIcons[ICON_KICK], si->pszModule, si->ptszName, clr ? clr : aFonts[6].color,
+ TranslateT("%s kicked %s (%s)"), (char *)gce->pszStatus, gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_NOTICE:
+ ShowPopup(si->hContact, si, hIcons[ICON_NOTICE], si->pszModule, si->ptszName, clr ? clr : aFonts[8].color,
+ TranslateT("Notice from %s: %s"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_TOPIC:
+ if (!gce->ptszNick)
+ ShowPopup(si->hContact, si, hIcons[ICON_TOPIC], si->pszModule, si->ptszName, clr ? clr : aFonts[11].color,
+ TranslateT("The topic is \'%s\'"), RemoveFormatting(gce->ptszText));
+ else
+ ShowPopup(si->hContact, si, hIcons[ICON_TOPIC], si->pszModule, si->ptszName, clr ? clr : aFonts[11].color,
+ TranslateT("The topic is \'%s\' (set by %s)"), RemoveFormatting(gce->ptszText), gce->ptszNick);
+ break;
+ case GC_EVENT_INFORMATION:
+ ShowPopup(si->hContact, si, hIcons[ICON_INFO], si->pszModule, si->ptszName, clr ? clr : aFonts[12].color, _T("%s"), RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_ADDSTATUS:
+ ShowPopup(si->hContact, si, hIcons[ICON_ADDSTATUS], si->pszModule, si->ptszName, clr ? clr : aFonts[13].color,
+ TranslateT("%s enables \'%s\' status for %s"), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick);
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ ShowPopup(si->hContact, si, hIcons[ICON_REMSTATUS], si->pszModule, si->ptszName, clr ? clr : aFonts[14].color,
+ TranslateT("%s disables \'%s\' status for %s"), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick);
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+void TSAPI DoFlashAndSoundWorker(FLASH_PARAMS* p)
+{
+ SESSION_INFO* si = SM_FindSessionByHCONTACT(p->hContact);
+ TWindowData* dat = 0;
+
+ if (si == 0)
+ return;
+
+ if (si->hWnd) {
+ dat = si->dat;
+ if (dat) {
+ p->bInactive = dat->pContainer->hwnd != GetForegroundWindow();
+ p->bActiveTab = (dat->pContainer->hwndActive == si->hWnd);
+ }
+ if (p->sound && Utils::mustPlaySound(si->dat))
+ SkinPlaySound(p->sound);
+ }
+ else if (p->sound)
+ SkinPlaySound(p->sound);
+
+ if (dat) {
+ HWND hwndTab = GetParent(si->hWnd);
+ BOOL bForcedIcon = (p->hNotifyIcon == hIcons[ICON_HIGHLIGHT] || p->hNotifyIcon == hIcons[ICON_MESSAGE]);
+
+ if ((p->iEvent & si->iLogTrayFlags) || bForcedIcon) {
+ if (!p->bActiveTab) {
+ if (p->hNotifyIcon == hIcons[ICON_HIGHLIGHT])
+ dat->iFlashIcon = p->hNotifyIcon;
+ else {
+ if (dat->iFlashIcon != hIcons[ICON_HIGHLIGHT] && dat->iFlashIcon != hIcons[ICON_MESSAGE])
+ dat->iFlashIcon = p->hNotifyIcon;
+ }
+ dat->mayFlashTab = TRUE;
+ SetTimer(si->hWnd, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL);
+ }
+ }
+ if (dat->pWnd) {
+ dat->pWnd->updateIcon(p->hNotifyIcon);
+ dat->pWnd->setOverlayIcon(p->hNotifyIcon, true);
+ }
+
+ // autoswitch tab..
+ if (p->bMustAutoswitch) {
+ if ((IsIconic(dat->pContainer->hwnd)) && !IsZoomed(dat->pContainer->hwnd) && PluginConfig.haveAutoSwitch() && dat->pContainer->hwndActive != si->hWnd) {
+ int iItem = GetTabIndexFromHWND(hwndTab, si->hWnd);
+ if (iItem >= 0) {
+ TabCtrl_SetCurSel(hwndTab, iItem);
+ ShowWindow(dat->pContainer->hwndActive, SW_HIDE);
+ dat->pContainer->hwndActive = si->hWnd;
+ SendMessage(dat->pContainer->hwnd, DM_UPDATETITLE, (WPARAM)dat->hContact, 0);
+ dat->pContainer->dwFlags |= CNT_DEFERREDTABSELECT;
+ }
+ }
+ }
+
+ /*
+ * flash window if it is not focused
+ */
+ if (p->bMustFlash && p->bInactive)
+ if (!(dat->pContainer->dwFlags & CNT_NOFLASH))
+ FlashContainer(dat->pContainer, 1, 0);
+
+ if (p->hNotifyIcon && p->bInactive && ((p->iEvent & si->iLogTrayFlags) || bForcedIcon)) {
+ HICON hIcon;
+
+ if (p->bMustFlash)
+ dat->hTabIcon = p->hNotifyIcon;
+ else if (dat->iFlashIcon) {
+ TCITEM item = {0};
+
+ dat->hTabIcon = dat->iFlashIcon;
+ item.mask = TCIF_IMAGE;
+ item.iImage = 0;
+ TabCtrl_SetItem(GetParent(si->hWnd), dat->iTabID, &item);
+ }
+ hIcon = (HICON)SendMessage(dat->pContainer->hwnd, WM_GETICON, ICON_BIG, 0);
+ if (p->hNotifyIcon == hIcons[ICON_HIGHLIGHT] || (hIcon != hIcons[ICON_MESSAGE] && hIcon != hIcons[ICON_HIGHLIGHT])) {
+ SendMessage(dat->pContainer->hwnd, DM_SETICON, (WPARAM)dat, (LPARAM)p->hNotifyIcon);
+ dat->pContainer->dwFlags |= CNT_NEED_UPDATETITLE;
+ }
+ }
+
+ if (p->bMustFlash && p->bInactive)
+ UpdateTrayMenu(dat, si->wStatus, si->pszModule, dat ? dat->szStatus : NULL, si->hContact, p->bHighlight ? 1 : 1);
+ }
+
+ free(p);
+}
+
+BOOL DoSoundsFlashPopupTrayStuff(SESSION_INFO* si, GCEVENT * gce, BOOL bHighlight, int bManyFix)
+{
+ FLASH_PARAMS* params;
+ struct TWindowData *dat = 0;
+ bool fFlagUnread = false;
+ WPARAM wParamForHighLight = 0;
+
+ if (gce == 0 || si == 0 || gce->bIsMe || si->iType == GCW_SERVER)
+ return FALSE;
+
+ params = (FLASH_PARAMS*)calloc(1, sizeof(FLASH_PARAMS));
+ params->hContact = si->hContact;
+ params->bInactive = TRUE;
+ if (si->hWnd && si->dat) {
+ dat = si->dat;
+ if ((si->hWnd == si->dat->pContainer->hwndActive) && GetForegroundWindow() == si->dat->pContainer->hwnd)
+ params->bInactive = FALSE;
+ }
+ params->bActiveTab = params->bMustFlash = params->bMustAutoswitch = FALSE;
+
+ params->iEvent = gce->pDest->iType;
+
+ if (bHighlight) {
+ gce->pDest->iType |= GC_EVENT_HIGHLIGHT;
+ params->sound = "ChatHighlight";
+ if (M->GetByte(si->hContact, "CList", "Hidden", 0) != 0)
+ DBDeleteContactSetting(si->hContact, "CList", "Hidden");
+ if (params->bInactive) {
+ fFlagUnread = true;
+ DoTrayIcon(si, gce);
+ }
+
+ /* TODO fix for 3.0 final !!! */
+#if !defined(__DELAYED_FOR_3_1)
+ if (g_Settings.CreateWindowOnHighlight && 0 == dat)
+ wParamForHighLight = 1;
+
+ if (dat && g_Settings.AnnoyingHighlight && params->bInactive && dat->pContainer->hwnd != GetForegroundWindow()) {
+ wParamForHighLight = 2;
+ params->hWnd = dat->hwnd;
+ }
+#endif
+ if (dat || !nen_options.iMUCDisable)
+ DoPopup(si, gce, dat);
+ if (params->bInactive && si && si->hWnd)
+ SendMessage(si->hWnd, GC_SETMESSAGEHIGHLIGHT, 0, (LPARAM) si);
+ if (g_Settings.FlashWindowHightlight && params->bInactive)
+ params->bMustFlash = TRUE;
+ params->bMustAutoswitch = TRUE;
+ params->hNotifyIcon = hIcons[ICON_HIGHLIGHT];
+ } else {
+ // do blinking icons in tray
+ if (params->bInactive || !g_Settings.TrayIconInactiveOnly) {
+ DoTrayIcon(si, gce);
+ if (params->iEvent == GC_EVENT_MESSAGE)
+ fFlagUnread = true;
+ }
+ // stupid thing to not create multiple popups for a QUIT event for instance
+ if (bManyFix == 0) {
+ // do popups
+ if (dat || !nen_options.iMUCDisable)
+ DoPopup(si, gce, dat);
+
+ // do sounds and flashing
+ switch (params->iEvent) {
+ case GC_EVENT_JOIN:
+ params->sound = "ChatJoin";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_JOIN];
+ break;
+ case GC_EVENT_PART:
+ params->sound = "ChatPart";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_PART];
+ break;
+ case GC_EVENT_QUIT:
+ params->sound = "ChatQuit";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_QUIT];
+ break;
+ case GC_EVENT_ADDSTATUS:
+ case GC_EVENT_REMOVESTATUS:
+ params->sound = "ChatMode";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[params->iEvent == GC_EVENT_ADDSTATUS ? ICON_ADDSTATUS : ICON_REMSTATUS];
+ break;
+ case GC_EVENT_KICK:
+ params->sound = "ChatKick";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_KICK];
+ break;
+ case GC_EVENT_MESSAGE:
+ params->sound = "ChatMessage";
+ if (params->bInactive && !(si->wState&STATE_TALK)) {
+ si->wState |= STATE_TALK;
+ DBWriteContactSettingWord(si->hContact, si->pszModule, "ApparentMode", (LPARAM)(WORD) 40071);
+ }
+ break;
+ case GC_EVENT_ACTION:
+ params->sound = "ChatAction";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_ACTION];
+ break;
+ case GC_EVENT_NICK:
+ params->sound = "ChatNick";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_NICK];
+ break;
+ case GC_EVENT_NOTICE:
+ params->sound = "ChatNotice";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_NOTICE];
+ break;
+ case GC_EVENT_TOPIC:
+ params->sound = "ChatTopic";
+ if (params->bInactive)
+ params->hNotifyIcon = hIcons[ICON_TOPIC];
+ break;
+ }
+ } else {
+ switch (params->iEvent) {
+ case GC_EVENT_JOIN:
+ params->hNotifyIcon = hIcons[ICON_JOIN];
+ break;
+ case GC_EVENT_PART:
+ params->hNotifyIcon = hIcons[ICON_PART];
+ break;
+ case GC_EVENT_QUIT:
+ params->hNotifyIcon = hIcons[ICON_QUIT];
+ break;
+ case GC_EVENT_KICK:
+ params->hNotifyIcon = hIcons[ICON_KICK];
+ break;
+ case GC_EVENT_ACTION:
+ params->hNotifyIcon = hIcons[ICON_ACTION];
+ break;
+ case GC_EVENT_NICK:
+ params->hNotifyIcon = hIcons[ICON_NICK];
+ break;
+ case GC_EVENT_NOTICE:
+ params->hNotifyIcon = hIcons[ICON_NOTICE];
+ break;
+ case GC_EVENT_TOPIC:
+ params->hNotifyIcon = hIcons[ICON_TOPIC];
+ break;
+ case GC_EVENT_ADDSTATUS:
+ params->hNotifyIcon = hIcons[ICON_ADDSTATUS];
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ params->hNotifyIcon = hIcons[ICON_REMSTATUS];
+ break;
+ }
+ }
+
+ if (params->iEvent == GC_EVENT_MESSAGE) {
+ params->bMustAutoswitch = TRUE;
+ if (g_Settings.FlashWindow)
+ params->bMustFlash = TRUE;
+ params->hNotifyIcon = hIcons[ICON_MESSAGE];
+ }
+ }
+ if (dat && fFlagUnread) {
+ dat->dwUnread++;
+ if (dat->pWnd)
+ dat->pWnd->Invalidate();
+ }
+ PostMessage(PluginConfig.g_hwndHotkeyHandler, DM_MUCFLASHWORKER, wParamForHighLight, (LPARAM)params);
+ return TRUE;
+}
+
+int Chat_GetColorIndex(const char* pszModule, COLORREF cr)
+{
+ MODULEINFO * pMod = MM_FindModule(pszModule);
+ int i = 0;
+
+ if (!pMod || pMod->nColorCount == 0)
+ return -1;
+
+ for (i=0; i < pMod->nColorCount; i++)
+ if (pMod->crColors[i] == cr)
+ return i;
+
+ return -1;
+}
+
+// obscure function that is used to make sure that any of the colors
+// passed by the protocol is used as fore- or background color
+// in the messagebox. THis is to vvercome limitations in the richedit
+// that I do not know currently how to fix
+
+void CheckColorsInModule(const char* pszModule)
+{
+ MODULEINFO * pMod = MM_FindModule(pszModule);
+ int i = 0;
+ COLORREF crFG;
+ COLORREF crBG = (COLORREF)M->GetDword(FONTMODULE, "inputbg", SRMSGDEFSET_BKGCOLOUR);
+
+ LoadLogfont(MSGFONTID_MESSAGEAREA, NULL, &crFG, FONTMODULE);
+
+ if (!pMod)
+ return;
+
+ for (i=0; i < pMod->nColorCount; i++) {
+ if (pMod->crColors[i] == crFG || pMod->crColors[i] == crBG) {
+ if (pMod->crColors[i] == RGB(255, 255, 255))
+ pMod->crColors[i]--;
+ else
+ pMod->crColors[i]++;
+ }
+ }
+}
+
+TCHAR* my_strstri(const TCHAR* s1, const TCHAR* s2)
+{
+ int i, j, k;
+
+ _tsetlocale(LC_ALL, _T(""));
+ for (i=0;s1[i];i++)
+ for (j = i, k = 0; _totlower(s1[j]) == _totlower(s2[k]);j++, k++)
+ if (!s2[k+1])
+ return (TCHAR*)(s1 + i);
+
+ return NULL;
+}
+
+/*
+ * log the event to the log file
+ * allows selective logging of wanted events
+ */
+BOOL LogToFile(SESSION_INFO* si, GCEVENT * gce)
+{
+ MODULEINFO * mi = NULL;
+ TCHAR szBuffer[4096];
+ TCHAR szLine[4096];
+ TCHAR szTime[100];
+ FILE *hFile = NULL;
+ TCHAR tszFolder[MAX_PATH];
+ TCHAR p = '\0';
+ BOOL bFileJustCreated = TRUE;
+
+ if (!si || !gce)
+ return FALSE;
+
+ mi = MM_FindModule(si->pszModule);
+ if (!mi)
+ return FALSE;
+
+ /*
+ * check whether we have to log this event
+ */
+ if (!(gce->pDest->iType & si->iDiskLogFlags))
+ return FALSE;
+
+ szBuffer[0] = '\0';
+
+ GetChatLogsFilename(si, gce->time);
+ bFileJustCreated = !PathFileExists(si->pszLogFileName);
+ _tcscpy(tszFolder, si->pszLogFileName);
+ PathRemoveFileSpec(tszFolder);
+ if (!PathIsDirectory(tszFolder))
+ CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)tszFolder);
+
+ lstrcpyn(szTime, MakeTimeStamp(g_Settings.pszTimeStampLog, gce->time), 99);
+
+ hFile = _tfopen(si->pszLogFileName, _T("ab+"));
+ if (hFile) {
+ TCHAR szTemp[512], szTemp2[512];
+ TCHAR* pszNick = NULL;
+ if (bFileJustCreated)
+ fputws((const wchar_t*)"\377\376", hFile); //UTF-16 LE BOM == FF FE
+ if (gce->ptszNick) {
+ if (g_Settings.LogLimitNames && lstrlen(gce->ptszNick) > 20) {
+ lstrcpyn(szTemp2, gce->ptszNick, 20);
+ lstrcpyn(szTemp2 + 20, _T("..."), 4);
+ } else lstrcpyn(szTemp2, gce->ptszNick, 511);
+
+ if (gce->pszUserInfo)
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s (%s)"), szTemp2, gce->pszUserInfo);
+ else
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s"), szTemp2);
+ pszNick = szTemp;
+ }
+ switch (gce->pDest->iType) {
+ case GC_EVENT_MESSAGE:
+ case GC_EVENT_MESSAGE | GC_EVENT_HIGHLIGHT:
+ p = '*';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s: %s"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_ACTION:
+ case GC_EVENT_ACTION | GC_EVENT_HIGHLIGHT:
+ p = '*';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s %s"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_JOIN:
+ p = '>';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s has joined"), (char *)pszNick);
+ break;
+ case GC_EVENT_PART:
+ p = '<';
+ if (!gce->pszText)
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s has left"), (char *)pszNick);
+ else
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s has left (%s)"), (char *)pszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_QUIT:
+ p = '<';
+ if (!gce->pszText)
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s has disconnected"), (char *)pszNick);
+ else
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s has disconnected (%s)"), (char *)pszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_NICK:
+ p = '^';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s is now known as %s"), gce->ptszNick, gce->ptszText);
+ break;
+ case GC_EVENT_KICK:
+ p = '~';
+ if (!gce->pszText)
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s kicked %s"), (char *)gce->pszStatus, gce->ptszNick);
+ else
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s kicked %s (%s)"), (char *)gce->pszStatus, gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_NOTICE:
+ p = 'o';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("Notice from %s: %s"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_TOPIC:
+ p = '#';
+ if (!gce->pszNick)
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("The topic is \'%s\'"), RemoveFormatting(gce->ptszText));
+ else
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("The topic is \'%s\' (set by %s)"), RemoveFormatting(gce->ptszText), gce->ptszNick);
+ break;
+ case GC_EVENT_INFORMATION:
+ p = '!';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), _T("%s"), RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_ADDSTATUS:
+ p = '+';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s enables \'%s\' status for %s"), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick);
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ p = '-';
+ mir_sntprintf(szBuffer, SIZEOF(szBuffer), TranslateT("%s disables \'%s\' status for %s"), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick);
+ break;
+ }
+ /*
+ * formatting strings don't need to be translatable - changing them via language pack would
+ * only screw up the log format.
+ */
+ if (p)
+ mir_sntprintf(szLine, SIZEOF(szLine), _T("%s %c %s\r\n"), szTime, p, szBuffer);
+ else
+ mir_sntprintf(szLine, SIZEOF(szLine), _T("%s %s\r\n"), szTime, szBuffer);
+
+ if (szLine[0]) {
+ _fputts(szLine, hFile);
+
+ if (g_Settings.LoggingLimit > 0) {
+ long dwSize;
+ long trimlimit;
+
+ fseek(hFile, 0, SEEK_END);
+ dwSize = ftell(hFile);
+ rewind(hFile);
+
+ trimlimit = g_Settings.LoggingLimit * 1024;
+ if (dwSize > trimlimit) {
+ TCHAR tszDrive[_MAX_DRIVE];
+ TCHAR tszDir[_MAX_DIR];
+ TCHAR tszName[_MAX_FNAME];
+ TCHAR tszExt[_MAX_EXT];
+ TCHAR tszNewName[_MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 20];
+ TCHAR tszNewPath[_MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 20];
+ TCHAR tszTimestamp[20];
+ time_t now = time(0);
+
+ _tcsftime(tszTimestamp, 20, _T("%Y%m%d-%H%M%S"), _localtime32((__time32_t *)&now));
+ tszTimestamp[19] = 0;
+ /*
+ * max size reached, rotate the log
+ * move old logs to /archived sub folder just inside the log root folder.
+ * add a time stamp to the file name.
+ */
+ _tsplitpath(si->pszLogFileName, tszDrive, tszDir, tszName, tszExt);
+
+ mir_sntprintf(tszNewPath, _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 20, _T("%s%sarchived\\"),
+ tszDrive, tszDir);
+
+ CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)tszNewPath);
+ mir_sntprintf(tszNewName, _MAX_DRIVE + _MAX_DIR + _MAX_FNAME + _MAX_EXT + 20, _T("%s%s-%s%s"), tszNewPath, tszName, tszTimestamp, tszExt);
+ fclose(hFile);
+ hFile = 0;
+ if (!PathFileExists(tszNewName))
+ CopyFile(si->pszLogFileName, tszNewName, TRUE);
+ DeleteFile(si->pszLogFileName);
+ }
+ }
+ }
+
+ if (hFile)
+ fclose(hFile);
+ hFile = NULL;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+UINT CreateGCMenu(HWND hwndDlg, HMENU *hMenu, int iIndex, POINT pt, SESSION_INFO* si, TCHAR* pszUID, TCHAR* pszWordText)
+{
+ GCMENUITEMS gcmi = {0};
+ int i;
+ HMENU hSubMenu = 0;
+ DWORD codepage = M->GetDword(si->hContact, "ANSIcodepage", 0);
+ int pos;
+
+ *hMenu = GetSubMenu(g_hMenu, iIndex);
+ TranslateMenu(*hMenu);
+ gcmi.pszID = si->ptszID;
+ gcmi.pszModule = si->pszModule;
+ gcmi.pszUID = pszUID;
+
+ if (iIndex == 1) {
+ int i = GetRichTextLength(GetDlgItem(hwndDlg, IDC_CHAT_LOG));
+
+ EnableMenuItem(*hMenu, ID_CLEARLOG, MF_ENABLED);
+ EnableMenuItem(*hMenu, ID_COPYALL, MF_ENABLED);
+ ModifyMenu(*hMenu, 4, MF_GRAYED | MF_BYPOSITION, 4, NULL);
+ if (!i) {
+ EnableMenuItem(*hMenu, ID_COPYALL, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem(*hMenu, ID_CLEARLOG, MF_BYCOMMAND | MF_GRAYED);
+ if (pszWordText && pszWordText[0])
+ ModifyMenu(*hMenu, 4, MF_ENABLED | MF_BYPOSITION, 4, NULL);
+ }
+
+ if (pszWordText && pszWordText[0]) {
+ TCHAR szMenuText[4096];
+ mir_sntprintf(szMenuText, 4096, 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) {
+ TCHAR szTemp[30], szTemp2[30];
+ lstrcpyn(szTemp, TranslateT("&Message"), 24);
+ if (pszUID)
+ mir_sntprintf(szTemp2, SIZEOF(szTemp2), _T("%s %s"), szTemp, pszUID);
+ else
+ lstrcpyn(szTemp2, szTemp, 24);
+
+ if (lstrlen(szTemp2) > 22)
+ lstrcpyn(szTemp2 + 22, _T("..."), 4);
+ ModifyMenu(*hMenu, ID_MESS, MF_STRING | MF_BYCOMMAND, ID_MESS, szTemp2);
+ gcmi.Type = MENU_ON_NICKLIST;
+ }
+
+ NotifyEventHooks(hBuildMenuEvent, 0, (WPARAM)&gcmi);
+
+ if (gcmi.nItems > 0)
+ AppendMenu(*hMenu, MF_SEPARATOR, 0, 0);
+
+ for (i=0; i < gcmi.nItems; i++) {
+ TCHAR* ptszDescr = a2tf(gcmi.Item[i].pszDesc, si->dwFlags);
+ TCHAR* ptszText = TranslateTS(ptszDescr);
+ 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);
+
+ mir_free(ptszDescr);
+ }
+
+#if !defined(__DELAYED_FOR_3_1)
+ if (iIndex == 0) {
+ AppendMenu(*hMenu, MF_SEPARATOR, 0, 0);
+ pos = GetMenuItemCount(*hMenu);
+ InsertMenu(*hMenu, pos, MF_BYPOSITION, (UINT_PTR)20020, TranslateT("Highlight User..."));
+ InsertMenu(*hMenu, pos, MF_BYPOSITION, (UINT_PTR)20021, TranslateT("Edit Highlight List..."));
+ }
+#endif
+ if (iIndex == 1 && si->iType != GCW_SERVER && !(si->dwFlags & GC_UNICODE)) {
+ AppendMenu(*hMenu, MF_SEPARATOR, 0, 0);
+ InsertMenu(PluginConfig.g_hMenuEncoding, 1, MF_BYPOSITION | MF_STRING, (UINT_PTR)CP_UTF8, TranslateT("UTF-8"));
+ pos = GetMenuItemCount(*hMenu);
+ InsertMenu(*hMenu, pos, MF_BYPOSITION | MF_POPUP, (UINT_PTR) PluginConfig.g_hMenuEncoding, TranslateT("Character Encoding"));
+ for (i=0; i < GetMenuItemCount(PluginConfig.g_hMenuEncoding); i++)
+ CheckMenuItem(PluginConfig.g_hMenuEncoding, i, MF_BYPOSITION | MF_UNCHECKED);
+ if (codepage == CP_ACP)
+ CheckMenuItem(PluginConfig.g_hMenuEncoding, 0, MF_BYPOSITION | MF_CHECKED);
+ else
+ CheckMenuItem(PluginConfig.g_hMenuEncoding, codepage, MF_BYCOMMAND | MF_CHECKED);
+
+ }
+
+ return TrackPopupMenu(*hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL);
+}
+
+void DestroyGCMenu(HMENU *hMenu, int iIndex)
+{
+ MENUITEMINFO mi;
+ mi.cbSize = sizeof(mi);
+ mi.fMask = MIIM_SUBMENU;
+ while (GetMenuItemInfo(*hMenu, iIndex, TRUE, &mi)) {
+ if (mi.hSubMenu != NULL)
+ DestroyMenu(mi.hSubMenu);
+ RemoveMenu(*hMenu, iIndex, MF_BYPOSITION);
+ }
+}
+
+BOOL DoEventHookAsync(HWND hwnd, const TCHAR* pszID, const char* pszModule, int iType, TCHAR* pszUID, TCHAR* pszText, DWORD dwItem)
+{
+ SESSION_INFO* si;
+ GCHOOK* gch = (GCHOOK*)mir_alloc(sizeof(GCHOOK));
+ GCDEST* gcd = (GCDEST*)mir_alloc(sizeof(GCDEST));
+
+ memset(gch, 0, sizeof(GCHOOK));
+ memset(gcd, 0, sizeof(GCDEST));
+
+ replaceStrA(&gcd->pszModule, pszModule);
+ if ((si = SM_FindSession(pszID, pszModule)) == NULL)
+ return FALSE;
+
+ if (!(si->dwFlags & GC_UNICODE)) {
+ DWORD dwCP = M->GetDword(si->hContact, "ANSIcodepage", 0);
+ gcd->pszID = t2a(pszID, 0);
+ gch->pszUID = t2a(pszUID, 0);
+ gch->pszText = t2a(pszText, dwCP);
+ } else {
+ replaceStr(&gcd->ptszID, pszID);
+ replaceStr(&gch->ptszUID, pszUID);
+ replaceStr(&gch->ptszText, pszText);
+ }
+ gcd->iType = iType;
+ gch->dwData = dwItem;
+ gch->pDest = gcd;
+ PostMessage(hwnd, GC_FIREHOOK, 0, (LPARAM) gch);
+ return TRUE;
+}
+
+BOOL DoEventHook(const TCHAR* pszID, const char* pszModule, int iType, const TCHAR* pszUID, const TCHAR* pszText, DWORD dwItem)
+{
+ SESSION_INFO* si;
+ GCHOOK gch = {0};
+ GCDEST gcd = {0};
+
+ gcd.pszModule = (char*)pszModule;
+ if ((si = SM_FindSession(pszID, pszModule)) == NULL)
+ return FALSE;
+
+ if (!(si->dwFlags & GC_UNICODE)) {
+ DWORD dwCP = M->GetDword(si->hContact, "ANSIcodepage", 0);
+ gcd.pszID = t2a(pszID, 0);
+ gch.pszUID = t2a(pszUID, 0);
+ gch.pszText = t2a(pszText, dwCP);
+ } else {
+ gcd.ptszID = mir_tstrdup(pszID);
+ gch.ptszUID = mir_tstrdup(pszUID);
+ gch.ptszText = mir_tstrdup(pszText);
+ }
+ gcd.iType = iType;
+ gch.dwData = dwItem;
+ gch.pDest = &gcd;
+ NotifyEventHooks(hSendEvent, 0, (WPARAM)&gch);
+
+ mir_free(gcd.pszID);
+ mir_free(gch.ptszUID);
+ mir_free(gch.ptszText);
+ return TRUE;
+}
+
+BOOL IsEventSupported(int eventType)
+{
+ switch (eventType) {
+ // Supported events
+ case GC_EVENT_JOIN:
+ case GC_EVENT_PART:
+ case GC_EVENT_QUIT:
+ case GC_EVENT_KICK:
+ case GC_EVENT_NICK:
+ case GC_EVENT_NOTICE:
+ case GC_EVENT_MESSAGE:
+ case GC_EVENT_TOPIC:
+ case GC_EVENT_INFORMATION:
+ case GC_EVENT_ACTION:
+ case GC_EVENT_ADDSTATUS:
+ case GC_EVENT_REMOVESTATUS:
+ case GC_EVENT_CHUID:
+ case GC_EVENT_CHANGESESSIONAME:
+ case GC_EVENT_ADDGROUP:
+ case GC_EVENT_SETITEMDATA:
+ case GC_EVENT_GETITEMDATA:
+ case GC_EVENT_SETSBTEXT:
+ case GC_EVENT_ACK:
+ case GC_EVENT_SENDMESSAGE:
+ case GC_EVENT_SETSTATUSEX:
+ case GC_EVENT_CONTROL:
+ case GC_EVENT_SETCONTACTSTATUS:
+ return TRUE;
+ }
+
+ // Other events
+ return FALSE;
+}
+
+TCHAR* a2tf(const TCHAR* str, int flags, DWORD cp)
+{
+ if (str == NULL)
+ return NULL;
+
+ if (flags & GC_UNICODE)
+ return mir_tstrdup(str);
+ else {
+ int cbLen;
+ TCHAR *result;
+
+ if (cp == CP_UTF8)
+ return(mir_utf8decodeW((char *)str));
+
+ if (cp == 0)
+ cp = PluginConfig.m_LangPackCP; // CallService( MS_LANGPACK_GETCODEPAGE, 0, 0 );
+ cbLen = MultiByteToWideChar(cp, 0, (char*)str, -1, 0, 0);
+ result = (TCHAR*)mir_alloc(sizeof(TCHAR) * (cbLen + 1));
+ if (result == NULL)
+ return NULL;
+
+ MultiByteToWideChar(cp, 0, (char*)str, -1, result, cbLen);
+ result[ cbLen ] = 0;
+ return result;
+ }
+}
+
+static char* u2a(const wchar_t* src, DWORD cp)
+{
+ int cbLen;
+ char *result;
+
+ if (cp == 0)
+ cp = PluginConfig.m_LangPackCP;
+ else if (cp == CP_UTF8)
+ return(mir_utf8encodeT(src));
+
+ cbLen = WideCharToMultiByte(cp, 0, src, -1, NULL, 0, NULL, NULL);
+ result = (char*)mir_alloc(cbLen + 1);
+ if (result == NULL)
+ return NULL;
+
+ WideCharToMultiByte(cp, 0, src, -1, result, cbLen, NULL, NULL);
+ result[ cbLen ] = 0;
+ return result;
+}
+
+char* t2a(const TCHAR* src, DWORD cp)
+{
+ return u2a(src, cp);
+}
+
+TCHAR* replaceStr(TCHAR** dest, const TCHAR* src)
+{
+ mir_free(*dest);
+ *dest = mir_tstrdup(src);
+ return *dest;
+}
+
+char* replaceStrA(char** dest, const char* src)
+{
+ mir_free(*dest);
+ *dest = mir_strdup(src);
+ return *dest;
+}
+
+/*
+ * set all filters and notification config for a session
+ * uses per channel mask + filterbits, default config as backup
+ */
+
+void Chat_SetFilters(SESSION_INFO *si)
+{
+ DWORD dwFlags_default = 0, dwMask = 0, dwFlags_local = 0;
+ int i;
+
+ if (si == NULL)
+ return;
+
+ dwFlags_default = M->GetDword("Chat", "FilterFlags", 0x03E0);
+ dwFlags_local = M->GetDword(si->hContact, "Chat", "FilterFlags", 0x03E0);
+ dwMask = M->GetDword(si->hContact, "Chat", "FilterMask", 0);
+
+ si->iLogFilterFlags = dwFlags_default;
+ for (i=0; i < 32; i++) {
+ if (dwMask & (1 << i))
+ si->iLogFilterFlags = (dwFlags_local & (1 << i) ? si->iLogFilterFlags | (1 << i) : si->iLogFilterFlags & ~(1 << i));
+ }
+
+ dwFlags_default = M->GetDword("Chat", "PopupFlags", 0x03E0);
+ dwFlags_local = M->GetDword(si->hContact, "Chat", "PopupFlags", 0x03E0);
+ dwMask = M->GetDword(si->hContact, "Chat", "PopupMask", 0);
+
+ si->iLogPopupFlags = dwFlags_default;
+ for (i=0; i < 32; i++) {
+ if (dwMask & (1 << i))
+ si->iLogPopupFlags = (dwFlags_local & (1 << i) ? si->iLogPopupFlags | (1 << i) : si->iLogPopupFlags & ~(1 << i));
+ }
+
+ dwFlags_default = M->GetDword("Chat", "TrayIconFlags", 0x03E0);
+ dwFlags_local = M->GetDword(si->hContact, "Chat", "TrayIconFlags", 0x03E0);
+ dwMask = M->GetDword(si->hContact, "Chat", "TrayIconMask", 0);
+
+ si->iLogTrayFlags = dwFlags_default;
+ for (i=0; i < 32; i++) {
+ if (dwMask & (1 << i))
+ si->iLogTrayFlags = (dwFlags_local & (1 << i) ? si->iLogTrayFlags | (1 << i) : si->iLogTrayFlags & ~(1 << i));
+ }
+
+ dwFlags_default = M->GetDword("Chat", "DiskLogFlags", 0xFFFF);
+ si->iDiskLogFlags = dwFlags_default;
+
+
+ if (si->iLogFilterFlags == 0)
+ si->bFilterEnabled = 0;
+}
+
+static TCHAR tszOldTimeStamp[30] = _T("\0");
+
+TCHAR* GetChatLogsFilename(SESSION_INFO *si, time_t tTime)
+{
+ REPLACEVARSARRAY rva[11];
+ REPLACEVARSDATA dat = {0};
+ TCHAR *p = 0, *tszParsedName = 0;
+ int i;
+ bool fReparse = false;
+
+ if (!tTime)
+ time(&tTime);
+
+ /*
+ * check whether relevant parts of the timestamp have changed and
+ * we have to reparse the filename
+ */
+
+ TCHAR *tszNow = MakeTimeStamp(_T("%a%d%m%Y"), tTime);
+
+ if (_tcscmp(tszOldTimeStamp, tszNow)) {
+ _tcsncpy(tszOldTimeStamp, tszNow, 30);
+ tszOldTimeStamp[29] = 0;
+ fReparse = true;
+ }
+
+ if (fReparse || 0 == si->pszLogFileName[0]) {
+ rva[0].lptzKey = _T("d");
+ rva[0].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%#d"), tTime));
+ // day 01-31
+ rva[1].lptzKey = _T("dd");
+ rva[1].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%d"), tTime));
+ // month 1-12
+ rva[2].lptzKey = _T("m");
+ rva[2].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%#m"), tTime));
+ // month 01-12
+ rva[3].lptzKey = _T("mm");
+ rva[3].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%m"), tTime));
+ // month text short
+ rva[4].lptzKey = _T("mon");
+ rva[4].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%b"), tTime));
+ // month text
+ rva[5].lptzKey = _T("month");
+ rva[5].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%B"), tTime));
+ // year 01-99
+ rva[6].lptzKey = _T("yy");
+ rva[6].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%y"), tTime));
+ // year 1901-9999
+ rva[7].lptzKey = _T("yyyy");
+ rva[7].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%Y"), tTime));
+ // weekday short
+ rva[8].lptzKey = _T("wday");
+ rva[8].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%a"), tTime));
+ // weekday
+ rva[9].lptzKey = _T("weekday");
+ rva[9].lptzValue = mir_tstrdup(MakeTimeStamp(_T("%A"), tTime));
+ // end of array
+ rva[10].lptzKey = NULL;
+ rva[10].lptzValue = NULL;
+
+ if (g_Settings.pszLogDir[lstrlen(g_Settings.pszLogDir)-1] == '\\')
+ _tcscat(g_Settings.pszLogDir, _T("%userid%.log"));
+
+ dat.cbSize = sizeof(dat);
+ dat.dwFlags = RVF_TCHAR;
+ dat.hContact = si->hContact;
+ dat.variables = rva;
+ tszParsedName = (TCHAR*) CallService(MS_UTILS_REPLACEVARS, (WPARAM)g_Settings.pszLogDir, (LPARAM)&dat);
+
+ if (!M->pathIsAbsolute(tszParsedName))
+ mir_sntprintf(si->pszLogFileName, MAX_PATH, _T("%s%s"), M->getChatLogPath(), tszParsedName);
+ else
+ mir_sntprintf(si->pszLogFileName, MAX_PATH, _T("%s"), tszParsedName);
+
+ mir_free(tszParsedName);
+
+ for (i=0; i < SIZEOF(rva);i++)
+ mir_free(rva[i].lptzValue);
+
+ for (p = si->pszLogFileName + 2; *p; ++p) {
+ if (*p == ':' || *p == '*' || *p == '?' || *p == '"' || *p == '<' || *p == '>' || *p == '|' )
+ *p = _T('_');
+ }
+ }
+
+ return si->pszLogFileName;
+}
diff --git a/plugins/TabSRMM/src/chat/window.cpp b/plugins/TabSRMM/src/chat/window.cpp
new file mode 100644
index 0000000000..77ee85f9b9
--- /dev/null
+++ b/plugins/TabSRMM/src/chat/window.cpp
@@ -0,0 +1,3833 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * This code is based on and still contains large parts of the the
+ * original chat module for Miranda NG, written and copyrighted
+ * by Joergen Persson in 2005.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: window.cpp 13631 2011-04-24 08:44:57Z silvercircle $
+ *
+ * This implements the group chat dialog window
+ *
+ */
+
+#include "..\commonheaders.h"
+
+#include <tom.h>
+
+//#include "../m_MathModule.h"
+
+// externs...
+extern LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+extern HRESULT(WINAPI *MyCloseThemeData)(HANDLE);
+extern REOLECallback *mREOLECallback;
+
+int g_cLinesPerPage=0;
+int g_iWheelCarryover=0;
+//
+
+extern HBRUSH hListBkgBrush;
+extern HANDLE hSendEvent;
+extern HICON hIcons[30];
+extern HMENU g_hMenu;
+extern WNDPROC OldSplitterProc;
+
+static WNDPROC OldMessageProc;
+static WNDPROC OldNicklistProc;
+static WNDPROC OldFilterButtonProc;
+static WNDPROC OldLogProc;
+static HKL hkl = NULL;
+static HCURSOR hCurHyperlinkHand;
+
+typedef struct
+{
+ time_t lastEnterTime;
+ TCHAR* szSearchQuery;
+ TCHAR* szSearchResult;
+ SESSION_INFO *lastSession;
+ TCHAR szTabSave[20];
+ BOOL iSavedSpaces;
+} MESSAGESUBDATA;
+
+static const CLSID IID_ITextDocument= { 0x8CC497C0,0xA1DF,0x11CE, { 0x80,0x98, 0x00,0xAA, 0x00,0x47,0xBE,0x5D} };
+extern WNDPROC OldIEViewProc;
+
+static void Chat_SetMessageLog(TWindowData *dat)
+{
+ unsigned int iLogMode = M->GetByte("Chat", "useIEView", 0);
+
+ if (iLogMode == WANT_IEVIEW_LOG && dat->hwndIEView == 0) {
+ IEVIEWWINDOW ieWindow;
+ IEVIEWEVENT iee;
+
+ //CheckAndDestroyHPP(dat);
+ ZeroMemory(&ieWindow, sizeof(ieWindow));
+ ZeroMemory(&iee, sizeof(iee));
+ ieWindow.cbSize = sizeof(ieWindow);
+ ieWindow.iType = IEW_CREATE;
+ ieWindow.dwFlags = 0;
+ ieWindow.dwMode = IEWM_TABSRMM;
+ ieWindow.parent = dat->hwnd;
+ ieWindow.x = 0;
+ ieWindow.y = 0;
+ ieWindow.cx = 200;
+ ieWindow.cy = 300;
+ CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow);
+ dat->hwndIEView = ieWindow.hwnd;
+ ZeroMemory(&iee, sizeof(iee));
+ iee.cbSize = sizeof(iee);
+ iee.iType = IEE_CLEAR_LOG;
+ iee.hwnd = dat->hwndIEView;
+ iee.hContact = dat->hContact;
+ iee.codepage = dat->codePage;
+
+ SESSION_INFO *si = (SESSION_INFO *)dat->si;
+
+ iee.pszProto = si->pszModule;
+ CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&iee);
+
+ Utils::showDlgControl(dat->hwnd, IDC_CHAT_LOG, SW_HIDE);
+ Utils::enableDlgControl(dat->hwnd, IDC_CHAT_LOG, FALSE);
+ } else if (iLogMode == WANT_HPP_LOG && dat->hwndHPP == 0) {
+ IEVIEWWINDOW ieWindow;
+
+ ZeroMemory(&ieWindow, sizeof(ieWindow));
+ //CheckAndDestroyIEView(dat);
+ ieWindow.cbSize = sizeof(IEVIEWWINDOW);
+ ieWindow.iType = IEW_CREATE;
+ ieWindow.dwFlags = 0;
+ ieWindow.dwMode = IEWM_MUCC;
+ ieWindow.parent = dat->hwnd;
+ ieWindow.x = 0;
+ ieWindow.y = 0;
+ ieWindow.cx = 10;
+ ieWindow.cy = 10;
+ CallService(MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow);
+ dat->hwndHPP = ieWindow.hwnd;
+ Utils::showDlgControl(dat->hwnd, IDC_CHAT_LOG, SW_HIDE);
+ Utils::enableDlgControl(dat->hwnd, IDC_CHAT_LOG, FALSE);
+ } else {
+ if (iLogMode != WANT_IEVIEW_LOG)
+ CheckAndDestroyIEView(dat);
+ Utils::showDlgControl(dat->hwnd, IDC_CHAT_LOG, SW_SHOW);
+ Utils::enableDlgControl(dat->hwnd, IDC_CHAT_LOG, TRUE);
+ dat->hwndIEView = 0;
+ dat->hwndIWebBrowserControl = 0;
+ dat->hwndHPP = 0;
+ }
+}
+
+
+/*
+ * 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_CHAT_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, (WPARAM)IDC_CHAT_LOG, (LPARAM)&enlink);
+ }
+ return bIsCustomLink;
+}
+
+static BOOL IsStringValidLink(TCHAR* pszText)
+{
+ TCHAR *p = pszText;
+
+ if (pszText == NULL)
+ return FALSE;
+ if (lstrlen(pszText) < 5)
+ return FALSE;
+
+ while (*p) {
+ if (*p == (TCHAR)'"')
+ return FALSE;
+ p++;
+ }
+ if (_totlower(pszText[0]) == 'w' && _totlower(pszText[1]) == 'w' && _totlower(pszText[2]) == 'w' && pszText[3] == '.' && _istalnum(pszText[4]))
+ return TRUE;
+
+ return(_tcsstr(pszText, _T("://")) == NULL ? FALSE : TRUE);
+}
+
+/*
+ * called whenever a group chat tab becomes active (either by switching tabs or activating a
+ * container window
+ */
+
+static void Chat_UpdateWindowState(TWindowData *dat, UINT msg)
+{
+ if (dat == NULL)
+ return;
+
+ HWND hwndDlg = dat->hwnd;
+ HWND hwndTab = GetParent(hwndDlg);
+ SESSION_INFO *si = (SESSION_INFO *)dat->si;
+
+ if (msg == WM_ACTIVATE) {
+ if (dat->pContainer->dwFlags & CNT_TRANSPARENCY && CMimAPI::m_pSetLayeredWindowAttributes != NULL) {
+ DWORD trans = LOWORD(dat->pContainer->settings->dwTransparency);
+ CMimAPI::m_pSetLayeredWindowAttributes(dat->pContainer->hwnd, CSkin::m_ContainerColorKey, (BYTE)trans, (dat->pContainer->dwFlags & CNT_TRANSPARENCY ? LWA_ALPHA : 0));
+ }
+ }
+
+ if (si->hwndFilter) {
+ POINT pt;
+ RECT rcFilter;
+
+ GetCursorPos(&pt);
+ GetWindowRect(si->hwndFilter, &rcFilter);
+ if (!PtInRect(&rcFilter, pt)) {
+ SendMessage(si->hwndFilter, WM_CLOSE, 1, 1);
+ si->hwndFilter = 0;
+ }
+ }
+
+#if defined(__FEAT_EXP_AUTOSPLITTER)
+ if (dat->fIsAutosizingInput && dat->iInputAreaHeight == -1) {
+ dat->iInputAreaHeight = 0;
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_REQUESTRESIZE, 0, 0);
+ }
+#endif
+ dat->Panel->dismissConfig();
+ dat->dwUnread = 0;
+ if (dat->pWnd) {
+ dat->pWnd->activateTab();
+ dat->pWnd->setOverlayIcon(0, true);
+ }
+
+ if (dat->pContainer->hwndSaved == hwndDlg || dat->bWasDeleted)
+ return;
+
+ dat->pContainer->hwndSaved = hwndDlg;
+
+ SetActiveSession(si->ptszID, si->pszModule);
+ dat->hTabIcon = dat->hTabStatusIcon;
+
+ if (dat->iTabID >= 0) {
+ if (DBGetContactSettingWord(si->hContact, si->pszModule , "ApparentMode", 0) != 0)
+ DBWriteContactSettingWord(si->hContact, si->pszModule , "ApparentMode", (LPARAM) 0);
+ if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->hContact, (LPARAM)szChatIconString);
+
+ SendMessage(hwndDlg, GC_UPDATETITLE, 0, 1);
+ dat->dwTickLastEvent = 0;
+ dat->dwFlags &= ~MWF_DIVIDERSET;
+ if (KillTimer(hwndDlg, TIMERID_FLASHWND) || dat->iFlashIcon) {
+ FlashTab(dat, hwndTab, dat->iTabID, &dat->bTabFlash, FALSE, dat->hTabIcon);
+ dat->mayFlashTab = FALSE;
+ dat->iFlashIcon = 0;
+ }
+ if (dat->pContainer->dwFlashingStarted != 0) {
+ FlashContainer(dat->pContainer, 0, 0);
+ dat->pContainer->dwFlashingStarted = 0;
+ }
+ dat->pContainer->dwFlags &= ~CNT_NEED_UPDATETITLE;
+
+ if (dat->dwFlags & MWF_NEEDCHECKSIZE)
+ PostMessage(hwndDlg, DM_SAVESIZE, 0, 0);
+
+ if (PluginConfig.m_AutoLocaleSupport) {
+ if (dat->hkl == 0)
+ DM_LoadLocale(dat);
+ else
+ SendMessage(hwndDlg, DM_SETLOCALE, 0, 0);
+ }
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ dat->dwLastActivity = GetTickCount();
+ dat->pContainer->dwLastActivity = dat->dwLastActivity;
+ dat->pContainer->MenuBar->configureMenu();
+ UpdateTrayMenuState(dat, FALSE);
+ DM_SetDBButtonStates(hwndDlg, dat);
+
+ if (g_Settings.MathMod) {
+ CallService(MTH_Set_ToolboxEditHwnd, 0, (LPARAM)GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ MTH_updateMathWindow(dat);
+ }
+
+ if (dat->dwFlagsEx & MWF_EX_DELAYEDSPLITTER) {
+ dat->dwFlagsEx &= ~MWF_EX_DELAYEDSPLITTER;
+ ShowWindow(dat->pContainer->hwnd, SW_RESTORE);
+ PostMessage(hwndDlg, DM_SPLITTERGLOBALEVENT, dat->wParam, dat->lParam);
+ PostMessage(hwndDlg, WM_SIZE, 0, 0);
+ dat->wParam = dat->lParam = 0;
+ }
+ /*
+ if (dat->hwndIEView) {
+ RECT rcRTF;
+ POINT pt;
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_CHAT_LOG), &rcRTF);
+ rcRTF.left += 20;
+ rcRTF.top += 20;
+ pt.x = rcRTF.left;
+ pt.y = rcRTF.top;
+ if (dat->hwndIEView) {
+ if (M->GetByte("subclassIEView", 0) && dat->oldIEViewProc == 0) {
+ WNDPROC wndProc = (WNDPROC)SetWindowLongPtr(dat->hwndIEView, GWLP_WNDPROC, (LONG_PTR)IEViewSubclassProc);
+ if (OldIEViewProc == 0)
+ OldIEViewProc = wndProc;
+ dat->oldIEViewProc = wndProc;
+ }
+ }
+ dat->hwndIWebBrowserControl = WindowFromPoint(pt);
+ }
+ */
+ }
+ if (M->isAero())
+ InvalidateRect(hwndTab, NULL, FALSE);
+ if (dat->pContainer->dwFlags & CNT_SIDEBAR)
+ dat->pContainer->SideBar->setActiveItem(dat);
+ BB_SetButtonsPos(dat);
+
+ if (dat->pWnd)
+ dat->pWnd->Invalidate();
+}
+
+/*
+ * initialize button bar, set all the icons and ensure proper button state
+ */
+
+static void InitButtons(HWND hwndDlg, SESSION_INFO* si)
+{
+ BOOL isFlat = M->GetByte("tbflat", 1);
+ BOOL isThemed = PluginConfig.m_bIsXP;
+ MODULEINFO *pInfo = si ? MM_FindModule(si->pszModule) : NULL;
+ BOOL bFilterEnabled = si ? si->bFilterEnabled : FALSE;
+
+ int i = 0;
+
+ if (pInfo) {
+ Utils::enableDlgControl(hwndDlg, IDC_CHAT_BOLD, pInfo->bBold);
+ Utils::enableDlgControl(hwndDlg, IDC_ITALICS, pInfo->bItalics);
+ Utils::enableDlgControl(hwndDlg, IDC_CHAT_UNDERLINE, pInfo->bUnderline);
+ Utils::enableDlgControl(hwndDlg, IDC_COLOR, pInfo->bColor);
+ Utils::enableDlgControl(hwndDlg, IDC_BKGCOLOR, pInfo->bBkgColor);
+ if (si->iType == GCW_CHATROOM)
+ Utils::enableDlgControl(hwndDlg, IDC_CHANMGR, pInfo->bChanMgr);
+ }
+}
+
+static void Chat_ResizeIeView(const TWindowData *dat)
+{
+ RECT rcRichEdit;
+ POINT pt;
+ IEVIEWWINDOW ieWindow;
+ int iMode = dat->hwndIEView ? 1 : 2;
+ HWND hwndDlg = dat->hwnd;
+
+ ZeroMemory(&ieWindow, sizeof(ieWindow));
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_CHAT_LOG), &rcRichEdit);
+ pt.x = rcRichEdit.left;
+ pt.y = rcRichEdit.top;
+ ScreenToClient(hwndDlg, &pt);
+ ieWindow.cbSize = sizeof(IEVIEWWINDOW);
+ ieWindow.iType = IEW_SETPOS;
+ ieWindow.parent = hwndDlg;
+ ieWindow.hwnd = iMode == 1 ? dat->hwndIEView : dat->hwndHPP;
+ ieWindow.x = pt.x;
+ ieWindow.y = pt.y;
+ ieWindow.cx = rcRichEdit.right - rcRichEdit.left;
+ ieWindow.cy = rcRichEdit.bottom - rcRichEdit.top;
+ if (ieWindow.cx != 0 && ieWindow.cy != 0) {
+ CallService(iMode == 1 ? MS_IEVIEW_WINDOW : MS_HPP_EG_WINDOW, 0, (LPARAM)&ieWindow);
+ }
+}
+
+/*
+ * resizer callback for the group chat session window. Called from Mirandas dialog
+ * resizing service
+ */
+
+static int RoomWndResize(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL *urc)
+{
+ RECT rc, rcTabs;
+ SESSION_INFO* si = (SESSION_INFO*)lParam;
+ struct TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ int TabHeight;
+ BOOL bToolbar = !(dat->pContainer->dwFlags & CNT_HIDETOOLBAR);
+ BOOL bBottomToolbar = dat->pContainer->dwFlags & CNT_BOTTOMTOOLBAR ? 1 : 0;
+ int panelHeight = dat->Panel->getHeight() + 1;
+
+ BOOL bNick = si->iType != GCW_SERVER && si->bNicklistEnabled;
+ int i = 0;
+ static int msgBottom = 0, msgTop = 0;
+ bool fInfoPanel = dat->Panel->isActive();
+
+ rc.bottom = rc.top = rc.left = rc.right = 0;
+
+ GetClientRect(hwndDlg, &rcTabs);
+ TabHeight = rcTabs.bottom - rcTabs.top;
+
+ if (dat->fIsAutosizingInput)
+ Utils::showDlgControl(hwndDlg, IDC_SPLITTERY, SW_HIDE);
+
+ if (si->iType != GCW_SERVER) {
+ Utils::showDlgControl(hwndDlg, IDC_LIST, si->bNicklistEnabled ? SW_SHOW : SW_HIDE);
+ Utils::showDlgControl(hwndDlg, IDC_SPLITTERX, si->bNicklistEnabled ? SW_SHOW : SW_HIDE);
+
+ Utils::enableDlgControl(hwndDlg, IDC_SHOWNICKLIST, TRUE);
+ Utils::enableDlgControl(hwndDlg, IDC_FILTER, TRUE);
+ if (si->iType == GCW_CHATROOM) {
+ MODULEINFO* tmp = MM_FindModule(si->pszModule);
+ if (tmp)
+ Utils::enableDlgControl(hwndDlg, IDC_CHANMGR, tmp->bChanMgr);
+ }
+ } else {
+ Utils::showDlgControl(hwndDlg, IDC_LIST, SW_HIDE);
+ Utils::showDlgControl(hwndDlg, IDC_SPLITTERX, SW_HIDE);
+ }
+
+ if (si->iType == GCW_SERVER) {
+ Utils::enableDlgControl(hwndDlg, IDC_SHOWNICKLIST, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_FILTER, FALSE);
+ Utils::enableDlgControl(hwndDlg, IDC_CHANMGR, FALSE);
+ }
+ //ShowWindow(GetDlgItem(hwndDlg, IDC_CHAT_TOGGLESIDEBAR), dat->pContainer->dwFlags & CNT_SIDEBAR ? SW_SHOW : SW_HIDE);
+
+ switch (urc->wId) {
+ case IDC_PANELSPLITTER:
+ urc->rcItem.bottom = panelHeight;
+ urc->rcItem.top = panelHeight - 2;
+ return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP;
+ case IDC_CHAT_LOG:
+ urc->rcItem.top = 0;
+ urc->rcItem.left = 0;
+ urc->rcItem.right = bNick ? urc->dlgNewSize.cx - si->iSplitterX : urc->dlgNewSize.cx;
+ urc->rcItem.bottom = (bToolbar&&!bBottomToolbar) ? (urc->dlgNewSize.cy - si->iSplitterY - (PluginConfig.g_DPIscaleY > 1.0 ? DPISCALEY_S(24) : DPISCALEY_S(23))) : (urc->dlgNewSize.cy - si->iSplitterY - DPISCALEY_S(2));
+ if (fInfoPanel)
+ 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 - si->iSplitterX + 2;
+ urc->rcItem.bottom = (bToolbar&&!bBottomToolbar) ? (urc->dlgNewSize.cy - si->iSplitterY - DPISCALEY_S(23)) : (urc->dlgNewSize.cy - si->iSplitterY - DPISCALEY_S(2));
+ if (fInfoPanel)
+ 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 - si->iSplitterX + 2;
+ urc->rcItem.left = urc->dlgNewSize.cx - si->iSplitterX;
+ urc->rcItem.bottom = (bToolbar&&!bBottomToolbar) ? (urc->dlgNewSize.cy - si->iSplitterY - DPISCALEY_S(23)) : (urc->dlgNewSize.cy - si->iSplitterY - DPISCALEY_S(2));
+ urc->rcItem.top = 0;
+ if (fInfoPanel)
+ urc->rcItem.top += panelHeight;
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM;
+
+ case IDC_SPLITTERY:
+ urc->rcItem.right = urc->dlgNewSize.cx;
+ urc->rcItem.top = (bToolbar&&!bBottomToolbar) ? urc->dlgNewSize.cy - si->iSplitterY : urc->dlgNewSize.cy - si->iSplitterY;
+ urc->rcItem.bottom = (bToolbar&&!bBottomToolbar) ? (urc->dlgNewSize.cy - si->iSplitterY + DPISCALEY_S(2)) : (urc->dlgNewSize.cy - si->iSplitterY + DPISCALEY_S(2));
+ urc->rcItem.left = 0;
+ urc->rcItem.bottom++;
+ urc->rcItem.top++;
+ return RD_ANCHORX_CUSTOM | RD_ANCHORY_CUSTOM;
+
+ case IDC_CHAT_MESSAGE:
+ urc->rcItem.right = urc->dlgNewSize.cx ;
+ urc->rcItem.top = urc->dlgNewSize.cy - si->iSplitterY + 3;
+ urc->rcItem.bottom = urc->dlgNewSize.cy; // - 1 ;
+ msgBottom = urc->rcItem.bottom;
+
+ if (dat->fIsAutosizingInput)
+ urc->rcItem.top -= DPISCALEY_S(1);
+
+ msgTop = urc->rcItem.top;
+ if (bBottomToolbar&&bToolbar)
+ urc->rcItem.bottom -= DPISCALEY_S(22);
+ 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 LRESULT CALLBACK MessageSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ MESSAGESUBDATA *dat;
+ SESSION_INFO* Parentsi;
+ struct TWindowData *mwdat;
+ HWND hwndParent = GetParent(hwnd);
+
+ mwdat = (struct TWindowData *)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+ Parentsi = (SESSION_INFO *)mwdat->si;
+
+ dat = (MESSAGESUBDATA *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ if (mwdat->fkeyProcessed && (msg == WM_KEYUP)) {
+ GetKeyboardState(mwdat->kstate);
+ if (mwdat->kstate[VK_CONTROL] & 0x80 || mwdat->kstate[VK_SHIFT] & 0x80)
+ return 0;
+ else {
+ mwdat->fkeyProcessed = false;
+ return 0;
+ }
+ }
+ switch (msg) {
+ case WM_NCCALCSIZE:
+ return(CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKINPUTAREA, msg, wParam, lParam, OldMessageProc));
+
+ case WM_NCPAINT:
+ return(CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKINPUTAREA, msg, wParam, lParam, OldMessageProc));
+
+ case EM_SUBCLASSED:
+ dat = (MESSAGESUBDATA *) mir_calloc(sizeof(MESSAGESUBDATA));
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) dat);
+ return 0;
+
+ case WM_CONTEXTMENU:
+ {
+ MODULEINFO* mi = MM_FindModule(Parentsi->pszModule);
+ HMENU hMenu, hSubMenu;
+ CHARRANGE sel, all = { 0, -1};
+ int iSelection;
+ int iPrivateBG = M->GetByte(mwdat->hContact, "private_bg", 0);
+ MessageWindowPopupData mwpd;
+ POINT pt;
+ int idFrom = IDC_CHAT_MESSAGE;
+
+ GetCursorPos(&pt);
+ hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT));
+ hSubMenu = GetSubMenu(hMenu, 2);
+ RemoveMenu(hSubMenu, 9, MF_BYPOSITION);
+ RemoveMenu(hSubMenu, 8, MF_BYPOSITION);
+ RemoveMenu(hSubMenu, 4, MF_BYPOSITION);
+ EnableMenuItem(hSubMenu, IDM_PASTEFORMATTED, MF_BYCOMMAND | ((mi && mi->bBold) ? MF_ENABLED : MF_GRAYED));
+ TranslateMenu(hSubMenu);
+
+ SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM) & sel);
+ if (sel.cpMin == sel.cpMax) {
+ EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED);
+ if (idFrom == IDC_CHAT_MESSAGE)
+ EnableMenuItem(hSubMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED);
+ }
+ mwpd.cbSize = sizeof(mwpd);
+ mwpd.uType = MSG_WINDOWPOPUP_SHOWING;
+ mwpd.uFlags = (idFrom == IDC_LOG ? MSG_WINDOWPOPUP_LOG : MSG_WINDOWPOPUP_INPUT);
+ mwpd.hContact = mwdat->hContact;
+ mwpd.hwnd = hwnd;
+ mwpd.hMenu = hSubMenu;
+ mwpd.selection = 0;
+ mwpd.pt = pt;
+ NotifyEventHooks(PluginConfig.m_event_MsgPopup, 0, (LPARAM)&mwpd);
+
+ 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:
+ if (idFrom == IDC_CHAT_MESSAGE)
+ SendMessage(hwnd, EM_PASTESPECIAL, (iSelection == IDM_PASTE) ? CF_TEXTT : 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 ( DM_MouseWheelHandler(hwnd, hwndParent, mwdat, wParam, lParam) == 0)
+ return 0;
+
+ dat->lastEnterTime = 0;
+ break;
+
+ case WM_SYSKEYUP:
+ if (wParam == VK_MENU) {
+ ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_CHAT_MESSAGE);
+ return 0;
+ }
+ break;
+
+ case WM_SYSKEYDOWN:
+ mwdat->fkeyProcessed = false;
+ if (ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_CHAT_MESSAGE)) {
+ mwdat->fkeyProcessed = true;
+ return 0;
+ }
+ break;
+
+ case WM_SYSCHAR:
+ if (mwdat->fkeyProcessed) {
+ mwdat->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;
+
+ if (bChar == '0')
+ iIndex = 10;
+ else
+ iIndex = bChar - (BYTE)'0';
+ SendMessage(mwdat->pContainer->hwnd, DM_SELECTTAB, DM_SELECT_BY_INDEX, (LPARAM)iIndex);
+ return 0;
+ }
+ break;
+
+ case WM_CHAR:
+ {
+ BOOL isShift, isAlt, isCtrl;
+ KbdState(mwdat, isShift, isCtrl, isAlt);
+
+ //MAD: sound on typing..
+ if (PluginConfig.g_bSoundOnTyping && !isAlt &&!isCtrl&&!(mwdat->pContainer->dwFlags&CNT_NOSOUND)&&wParam!=VK_ESCAPE&&!(wParam==VK_TAB&&PluginConfig.m_AllowTab))
+ SkinPlaySound("SoundOnTyping");
+ //MAD
+
+ if (wParam == 0x0d && isCtrl && PluginConfig.m_MathModAvail) {
+ TCHAR toInsert[100];
+ BYTE keyState[256];
+ size_t i;
+ size_t iLen = lstrlen(PluginConfig.m_MathModStartDelimiter);
+ ZeroMemory(keyState, 256);
+ _tcsncpy(toInsert, PluginConfig.m_MathModStartDelimiter, 30);
+ _tcsncat(toInsert, PluginConfig.m_MathModStartDelimiter, 30);
+ SendMessage(hwnd, EM_REPLACESEL, TRUE, (LPARAM)toInsert);
+ SetKeyboardState(keyState);
+ for (i=0; i < iLen; i++)
+ SendMessage(hwnd, WM_KEYDOWN, mwdat->dwFlags & MWF_LOG_RTL ? VK_RIGHT : VK_LEFT, 0);
+ return 0;
+ }
+ if (isCtrl && !isAlt && !isShift) {
+ MODULEINFO* mi = MM_FindModule(Parentsi->pszModule);
+
+ switch(wParam) {
+ case 0x09: // ctrl-i (italics)
+ if (mi && 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 && mi->bBold) {
+ CheckDlgButton(hwndParent, IDC_CHAT_BOLD, IsDlgButtonChecked(hwndParent, IDC_CHAT_BOLD) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED);
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_CHAT_BOLD, 0), 0);
+ }
+ return 0;
+ case 0x20: // ctrl-space clear formatting
+ if (mi && mi->bBold && mi->bItalics && mi->bUnderline) {
+ CheckDlgButton(hwndParent, IDC_BKGCOLOR, BST_UNCHECKED);
+ CheckDlgButton(hwndParent, IDC_COLOR, BST_UNCHECKED);
+ CheckDlgButton(hwndParent, IDC_CHAT_BOLD, BST_UNCHECKED);
+ CheckDlgButton(hwndParent, IDC_CHAT_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_CHAT_BOLD, 0), 0);
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_CHAT_UNDERLINE, 0), 0);
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_ITALICS, 0), 0);
+ }
+ return 0;
+ case 0x0c: // ctrl-l background color
+ if (mi && 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 && mi->bUnderline) {
+ CheckDlgButton(hwndParent, IDC_CHAT_UNDERLINE, IsDlgButtonChecked(hwndParent, IDC_CHAT_UNDERLINE) == BST_UNCHECKED ? BST_CHECKED : BST_UNCHECKED);
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(IDC_CHAT_UNDERLINE, 0), 0);
+ }
+ return 0; // ctrl-k color
+ case 0x0b:
+ if (mi && 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;
+ default:
+ break;
+ }
+ }
+ }
+ break;
+
+ case WM_KEYDOWN:
+ {
+ static size_t start, end;
+ BOOL isShift, isCtrl, isAlt;
+ KbdState(mwdat, isShift, isCtrl, isAlt);
+
+ //MAD: sound on typing..
+ if (PluginConfig.g_bSoundOnTyping&&!isAlt&&wParam == VK_DELETE)
+ SkinPlaySound("SoundOnTyping");
+ //
+ if (wParam == VK_INSERT && !isShift && !isCtrl && !isAlt) {
+ mwdat->fInsertMode = !mwdat->fInsertMode;
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM) hwnd);
+ }
+ if (wParam == VK_CAPITAL || wParam == VK_NUMLOCK)
+ SendMessage(hwndParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), EN_CHANGE), (LPARAM) hwnd);
+
+ if (isCtrl && isAlt && !isShift) {
+ switch (wParam) {
+ case VK_UP:
+ case VK_DOWN:
+ case VK_PRIOR:
+ case VK_NEXT:
+ case VK_HOME:
+ case VK_END: {
+ WPARAM wp = 0;
+
+ if (wParam == VK_UP)
+ wp = MAKEWPARAM(SB_LINEUP, 0);
+ else if (wParam == VK_PRIOR)
+ wp = MAKEWPARAM(SB_PAGEUP, 0);
+ else if (wParam == VK_NEXT)
+ wp = MAKEWPARAM(SB_PAGEDOWN, 0);
+ else if (wParam == VK_HOME)
+ wp = MAKEWPARAM(SB_TOP, 0);
+ else if (wParam == VK_END) {
+ DM_ScrollToBottom(mwdat, 0, 0);
+ return 0;
+ } else if (wParam == VK_DOWN)
+ wp = MAKEWPARAM(SB_LINEDOWN, 0);
+
+ SendMessage(GetDlgItem(hwndParent, IDC_CHAT_LOG), WM_VSCROLL, wp, 0);
+ return 0;
+ }
+ }
+ }
+
+ if (wParam == VK_RETURN) {
+ if (isShift) {
+ if (PluginConfig.m_SendOnShiftEnter) {
+ PostMessage(hwndParent, WM_COMMAND, IDOK, 0);
+ return 0;
+ } else
+ break;
+ }
+ if ((isCtrl && !isShift) ^(0 != PluginConfig.m_SendOnEnter)) {
+ PostMessage(hwndParent, WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ if (PluginConfig.m_SendOnEnter || PluginConfig.m_SendOnDblEnter) {
+ if (isCtrl)
+ break;
+ else {
+ if (PluginConfig.m_SendOnDblEnter) {
+ if (dat->lastEnterTime + 2 < time(NULL)) {
+ dat->lastEnterTime = time(NULL);
+ break;
+ } else {
+ SendMessage(hwnd, WM_KEYDOWN, VK_BACK, 0);
+ SendMessage(hwnd, WM_KEYUP, VK_BACK, 0);
+ PostMessage(hwndParent, WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ }
+ PostMessage(hwndParent, WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ } else
+ break;
+ } else
+ dat->lastEnterTime = 0;
+
+ if ((wParam == VK_NEXT && isCtrl && !isShift) || (wParam == VK_TAB && isCtrl && !isShift)) { // CTRL-TAB (switch tab/window)
+ SendMessage(mwdat->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->pContainer->hwnd, DM_SELECTTAB, DM_SELECT_PREV, 0);
+ return TRUE;
+ }
+ if (wParam == VK_TAB && !isCtrl && !isShift) { //tab-autocomplete
+ int iLen, end, topicStart;
+ BOOL isTopic = FALSE;
+ BOOL isRoom = FALSE;
+ wchar_t* pszText = NULL;
+ GETTEXTEX gt = {0};
+ LRESULT lResult = (LRESULT)SendMessage(hwnd, EM_GETSEL, (WPARAM)NULL, (LPARAM)NULL);
+ bool fCompleted = false;
+
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+ start = LOWORD(lResult);
+ end = HIWORD(lResult);
+ SendMessage(hwnd, EM_SETSEL, end, end);
+
+ gt.codepage = 1200;
+ gt.flags = GTL_DEFAULT | GTL_PRECISE;
+
+ iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gt, (LPARAM)0);
+ if (iLen > 0) {
+ wchar_t* pszName = NULL;
+ pszText = reinterpret_cast<wchar_t*>(Utils::safeMirCalloc((iLen + 10) * sizeof(wchar_t)));
+ gt.flags = GT_DEFAULT;
+ gt.cb = (iLen + 9) * sizeof(wchar_t);
+
+ SendMessage(hwnd, EM_GETTEXTEX, (WPARAM)&gt, (LPARAM)pszText);
+
+ if (start > 1 && pszText[start-1] == ' ' && pszText[start-2] == ':')
+ start--;
+
+ while( start > 0 && pszText[start-1] != ' ' && pszText[start-1] != 13 && pszText[start-1] != VK_TAB)
+ start--;
+
+ while (end < iLen && pszText[end] != ' ' && pszText[end] != 13 && pszText[end-1] != VK_TAB)
+ end ++;
+
+ if (pszText[start] == '#')
+ isRoom = TRUE;
+ else {
+ topicStart = (int)start;
+ while ( topicStart >0 && (pszText[topicStart-1] == ' ' || pszText[topicStart-1] == 13 || pszText[topicStart-1] == VK_TAB))
+ topicStart--;
+ if (topicStart > 5 && _tcsstr(&pszText[topicStart-6], _T("/topic")) == &pszText[topicStart-6])
+ isTopic = TRUE;
+ }
+ if (dat->szSearchQuery == NULL) {
+ size_t len = (end - start) + 1;
+ dat->szSearchQuery = reinterpret_cast<wchar_t*>(Utils::safeMirAlloc(sizeof(wchar_t) * len));
+ wcsncpy( dat->szSearchQuery, pszText + start, len);
+ dat->szSearchQuery[len - 1] = 0;
+ dat->szSearchResult = mir_tstrdup(dat->szSearchQuery);
+ dat->lastSession = NULL;
+ }
+ if (isTopic) {
+ pszName = Parentsi->ptszTopic;
+ } else if (isRoom) {
+ dat->lastSession = SM_FindSessionAutoComplete(Parentsi->pszModule, Parentsi, dat->lastSession, dat->szSearchQuery, dat->szSearchResult);
+ if (dat->lastSession != NULL)
+ pszName = dat->lastSession->ptszName;
+ } else
+ pszName = UM_FindUserAutoComplete(Parentsi->pUsers, dat->szSearchQuery, dat->szSearchResult);
+
+ mir_free(pszText);
+ pszText = NULL;
+ mir_free(dat->szSearchResult);
+ dat->szSearchResult = 0;
+ if (pszName == 0) {
+ if ((int)end != (int)start) {
+ SendMessage(hwnd, EM_SETSEL, start, end);
+ SendMessage(hwnd, EM_REPLACESEL, TRUE, (LPARAM) dat->szSearchQuery);
+ }
+ mir_free(dat->szSearchQuery);
+ dat->szSearchQuery = NULL;
+ } else {
+ pszText = 0;
+ dat->szSearchResult = mir_tstrdup(pszName);
+ if ((int)end != (int)start) {
+ if (!isRoom && !isTopic && g_Settings.AddColonToAutoComplete && start == 0) {
+ pszText = reinterpret_cast<wchar_t*>(Utils::safeMirAlloc((wcslen(pszName) + 4) * sizeof(wchar_t)));
+ wcscpy(pszText, pszName);
+ wcscat(pszText, L": ");
+ pszName = pszText;
+ }
+ SendMessage(hwnd, EM_SETSEL, start, end);
+ SendMessage(hwnd, EM_REPLACESEL, TRUE, (LPARAM)pszName);
+ }
+ if (pszText)
+ mir_free(pszText);
+ fCompleted = true;
+ }
+ }
+ SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE);
+ if (!fCompleted && !PluginConfig.m_AllowTab) {
+ if ((GetSendButtonState(mwdat->hwnd) != PBS_DISABLED))
+ SetFocus(GetDlgItem(mwdat->hwnd, IDOK));
+ else
+ SetFocus(GetDlgItem(mwdat->hwnd, IDC_CHAT_LOG));
+ }
+ return 0;
+ } else 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_CHAT_CLOSE, BN_CLICKED), 0);
+ return 0;
+ }
+
+ if (wParam == VK_NEXT || wParam == VK_PRIOR) {
+ HWND htemp = hwndParent;
+ SendDlgItemMessage(htemp, IDC_CHAT_LOG, msg, wParam, lParam);
+ dat->lastEnterTime = 0;
+ return 0;
+ }
+
+ if (wParam == VK_UP && isCtrl && !isAlt) {
+ int iLen;
+ GETTEXTLENGTHEX gtl = {0};
+ SETTEXTEX ste;
+ LOGFONTA lf;
+ char* lpPrevCmd = SM_GetPrevCommand(Parentsi->ptszID, Parentsi->pszModule);
+
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+
+ LoadLogfont(MSGFONTID_MESSAGEAREA, &lf, NULL, FONTMODULE);
+ ste.flags = ST_DEFAULT;
+ ste.codepage = CP_ACP;
+ if (lpPrevCmd)
+ SendMessage(hwnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM)lpPrevCmd);
+ else
+ SetWindowText(hwnd, _T(""));
+
+ gtl.flags = GTL_PRECISE;
+ gtl.codepage = CP_ACP;
+ iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM) & gtl, (LPARAM)NULL);
+ 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) {
+ int iLen;
+ GETTEXTLENGTHEX gtl = {0};
+ SETTEXTEX ste;
+
+ char* lpPrevCmd = SM_GetNextCommand(Parentsi->ptszID, Parentsi->pszModule);
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+
+ ste.flags = ST_DEFAULT;
+ ste.codepage = CP_ACP;
+ if (lpPrevCmd)
+ SendMessage(hwnd, EM_SETTEXTEX, (WPARAM)&ste, (LPARAM) lpPrevCmd);
+ else
+ SetWindowText(hwnd, _T(""));
+
+ gtl.flags = GTL_PRECISE;
+ gtl.codepage = CP_ACP;
+ iLen = SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM) & gtl, (LPARAM)NULL);
+ 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_RETURN)
+ break;
+ //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:
+ {
+ CHARFORMAT2 cf;
+ UINT u = 0;
+ UINT u2 = 0;
+ COLORREF cr;
+ MODULEINFO* mi = MM_FindModule(Parentsi->pszModule);
+
+ LoadLogfont(MSGFONTID_MESSAGEAREA, NULL, &cr, FONTMODULE);
+
+ 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);
+
+ if (mi && mi->bColor) {
+ int index = Chat_GetColorIndex(Parentsi->pszModule, cf.crTextColor);
+ u = IsDlgButtonChecked(GetParent(hwnd), IDC_COLOR);
+
+ if (index >= 0) {
+ Parentsi->bFGSet = TRUE;
+ Parentsi->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 && mi->bBkgColor) {
+ int index = Chat_GetColorIndex(Parentsi->pszModule, cf.crBackColor);
+ COLORREF crB = (COLORREF)M->GetDword(FONTMODULE, "inputbg", SRMSGDEFSET_BKGCOLOUR);
+ u = IsDlgButtonChecked(hwndParent, IDC_BKGCOLOR);
+
+ if (index >= 0) {
+ Parentsi->bBGSet = TRUE;
+ Parentsi->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 && mi->bBold) {
+ u = IsDlgButtonChecked(hwndParent, IDC_CHAT_BOLD);
+ u2 = cf.dwEffects;
+ u2 &= CFE_BOLD;
+ if (u == BST_UNCHECKED && u2)
+ CheckDlgButton(hwndParent, IDC_CHAT_BOLD, BST_CHECKED);
+ else if (u == BST_CHECKED && u2 == 0)
+ CheckDlgButton(hwndParent, IDC_CHAT_BOLD, BST_UNCHECKED);
+ }
+
+ if (mi && mi->bItalics) {
+ u = IsDlgButtonChecked(hwndParent, IDC_ITALICS);
+ 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 && mi->bUnderline) {
+ u = IsDlgButtonChecked(hwndParent, IDC_CHAT_UNDERLINE);
+ if (cf.dwEffects & CFE_UNDERLINE && (cf.bUnderlineType & CFU_UNDERLINE || cf.bUnderlineType & CFU_UNDERLINEWORD)) {
+ if (u == BST_UNCHECKED )
+ CheckDlgButton(hwndParent, IDC_CHAT_UNDERLINE, BST_CHECKED);
+ }
+ else {
+ if (u == BST_CHECKED)
+ CheckDlgButton(hwndParent, IDC_CHAT_UNDERLINE, BST_UNCHECKED);
+ }
+ }
+ }
+ break;
+
+ case WM_INPUTLANGCHANGE:
+ if (PluginConfig.m_AutoLocaleSupport && GetFocus() == hwnd && mwdat->pContainer->hwndActive == hwndParent && GetForegroundWindow() == mwdat->pContainer->hwnd && GetActiveWindow() == mwdat->pContainer->hwnd) {
+ DM_SaveLocale(mwdat, wParam, lParam);
+ SendMessage(hwnd, EM_SETLANGOPTIONS, 0, (LPARAM) SendMessage(hwnd, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD);
+ return 1;
+ }
+ break;
+
+ case WM_ERASEBKGND:
+ return CSkin::m_skinEnabled ? 0 : 1;
+
+ case EM_UNSUBCLASSED:
+ mir_free(dat);
+ return 0;
+ }
+
+ return CallWindowProc(OldMessageProc, hwnd, 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,
+ 0
+};
+
+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;
+ DWORD dwMask = M->GetDword(si->hContact, "Chat", "FilterMask", 0);
+ DWORD dwFlags = M->GetDword(si->hContact, "Chat", "FilterFlags", 0);
+
+ DWORD dwPopupMask = M->GetDword(si->hContact, "Chat", "PopupMask", 0);
+ DWORD dwPopupFlags = M->GetDword(si->hContact, "Chat", "PopupFlags", 0);
+
+ DWORD dwTrayMask = M->GetDword(si->hContact, "Chat", "TrayIconMask", 0);
+ DWORD dwTrayFlags = M->GetDword(si->hContact, "Chat", "TrayIconFlags", 0);
+
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)si);
+
+ for (int i = 0; _eventorder[i]; 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;
+ UINT result;
+ DWORD dwMask = 0, dwFlags = 0;
+
+ for (i=0; _eventorder[i]; i++) {
+ 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) {
+ DBDeleteContactSetting(si->hContact, "Chat", "FilterFlags");
+ DBDeleteContactSetting(si->hContact, "Chat", "FilterMask");
+ } else {
+ M->WriteDword(si->hContact, "Chat", "FilterFlags", iFlags);
+ M->WriteDword(si->hContact, "Chat", "FilterMask", dwMask);
+ }
+ }
+
+ dwMask = iFlags = 0;
+
+ for (i=0; _eventorder[i]; i++) {
+ 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) {
+ DBDeleteContactSetting(si->hContact, "Chat", "PopupFlags");
+ DBDeleteContactSetting(si->hContact, "Chat", "PopupMask");
+ } else {
+ M->WriteDword(si->hContact, "Chat", "PopupFlags", iFlags);
+ M->WriteDword(si->hContact, "Chat", "PopupMask", dwMask);
+ }
+ }
+
+ dwMask = iFlags = 0;
+
+ for (i=0; _eventorder[i]; i++) {
+ 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) {
+ DBDeleteContactSetting(si->hContact, "Chat", "TrayIconFlags");
+ DBDeleteContactSetting(si->hContact, "Chat", "TrayIconMask");
+ } else {
+ M->WriteDword(si->hContact, "Chat", "TrayIconFlags", iFlags);
+ M->WriteDword(si->hContact, "Chat", "TrayIconMask", dwMask);
+ }
+ Chat_SetFilters(si);
+ SendMessage(si->hWnd, GC_CHANGEFILTERFLAG, 0, (LPARAM)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)
+{
+ HWND hwndParent = GetParent(hwnd);
+
+ switch (msg) {
+ case WM_RBUTTONUP: {
+ HWND hFilter = GetDlgItem(hwndParent, IDC_FILTER);
+ HWND hColor = GetDlgItem(hwndParent, IDC_COLOR);
+ HWND hBGColor = GetDlgItem(hwndParent, IDC_BKGCOLOR);
+
+ if (M->GetByte("Chat", "RightClickFilter", 0) != 0) {
+ if (hFilter == hwnd)
+ SendMessage(hwndParent, GC_SHOWFILTERMENU, 0, 0);
+ if (hColor == hwnd)
+ SendMessage(hwndParent, GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_COLOR);
+ if (hBGColor == hwnd)
+ SendMessage(hwndParent, GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_BKGCOLOR);
+ }
+ }
+ break;
+ }
+
+ return CallWindowProc(OldFilterButtonProc, hwnd, 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);
+ struct TWindowData *mwdat = (struct TWindowData *)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+
+ switch (msg) {
+ case WM_NCCALCSIZE:
+ return(CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, OldLogProc));
+
+ case WM_NCPAINT:
+ return(CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKHISTORY, msg, wParam, lParam, OldLogProc));
+
+ case WM_COPY:
+ return(DM_WMCopyHandler(hwnd, OldLogProc, wParam, lParam));
+
+ case WM_SETCURSOR:
+ if (g_Settings.ClickableNicks && (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.ClickableNicks) {
+ POINT pt={LOWORD(lParam), HIWORD(lParam)};
+ CheckCustomLink(hwnd, &pt, msg, wParam, lParam, TRUE);
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ {
+ CHARRANGE sel;
+ if (g_Settings.ClickableNicks) {
+ POINT pt={LOWORD(lParam), HIWORD(lParam)};
+ CheckCustomLink(hwnd, &pt, msg, wParam, lParam, TRUE);
+ }
+ if (true || M->GetByte("autocopy", 0)) {
+ 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_CHAT_MESSAGE));
+ }
+ }
+ }
+ break;
+
+ case WM_KEYDOWN:
+ if (wParam == 0x57 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w (close window)
+ PostMessage(hwndParent, WM_CLOSE, 0, 1);
+ return TRUE;
+ }
+ break;
+
+ case WM_SYSKEYUP:
+ if (wParam == VK_MENU) {
+ ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_CHAT_LOG);
+ return 0;
+ }
+ break;
+
+ case WM_SYSKEYDOWN:
+ mwdat->fkeyProcessed = false;
+ if (ProcessHotkeysByMsgFilter(hwnd, msg, wParam, lParam, IDC_CHAT_LOG)) {
+ mwdat->fkeyProcessed = true;
+ return 0;
+ }
+ break;
+
+ case WM_SYSCHAR: {
+ if (mwdat->fkeyProcessed) {
+ mwdat->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:
+ SetFocus(GetDlgItem(hwndParent, IDC_CHAT_MESSAGE));
+ SendMessage(GetDlgItem(hwndParent, IDC_CHAT_MESSAGE), WM_CHAR, wParam, lParam);
+ break;
+ }
+
+ return CallWindowProc(OldLogProc, hwnd, msg, wParam, lParam);
+}
+
+
+/*
+ * process mouse - hovering for the nickname list. fires events so the protocol can
+ * show the userinfo - tooltip.
+ */
+
+static void ProcessNickListHovering(HWND hwnd, int hoveredItem, POINT * pt, SESSION_INFO * parentdat)
+{
+ static int currentHovered = -1;
+ static HWND hwndToolTip = NULL;
+ static HWND oldParent = NULL;
+ TOOLINFO ti = {0};
+ RECT clientRect;
+ BOOL bNewTip = FALSE;
+ USERINFO *ui1 = NULL;
+
+ if (hoveredItem == currentHovered) return;
+ currentHovered = hoveredItem;
+
+ if (oldParent != hwnd && hwndToolTip) {
+ SendMessage(hwndToolTip, TTM_DELTOOL, 0, 0);
+ DestroyWindow(hwndToolTip);
+ hwndToolTip = NULL;
+ }
+ if (hoveredItem == -1) {
+
+ SendMessage(hwndToolTip, TTM_ACTIVATE, 0, 0);
+
+ } else {
+
+ if (!hwndToolTip) {
+ hwndToolTip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL,
+ WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ hwnd, NULL, g_hInst, NULL);
+ bNewTip = TRUE;
+ }
+
+ GetClientRect(hwnd, &clientRect);
+ ti.cbSize = sizeof(TOOLINFO);
+ ti.uFlags = TTF_SUBCLASS;
+ ti.hinst = g_hInst;
+ ti.hwnd = hwnd;
+ ti.uId = 1;
+ ti.rect = clientRect;
+
+ ti.lpszText = NULL;
+
+ ui1 = SM_GetUserFromIndex(parentdat->ptszID, parentdat->pszModule, currentHovered);
+ if (ui1) {
+ char serviceName[256];
+ _snprintf(serviceName, SIZEOF(serviceName), "%s"MS_GC_PROTO_GETTOOLTIPTEXT, parentdat->pszModule);
+ if (ServiceExists(serviceName))
+ ti.lpszText = (TCHAR*)CallService(serviceName, (WPARAM)parentdat->ptszID, (LPARAM)ui1->pszUID);
+ else {
+ TCHAR ptszBuf[ 1024 ];
+ mir_sntprintf( ptszBuf, SIZEOF(ptszBuf), _T("%s: %s\r\n%s: %s\r\n%s: %s"),
+ TranslateT("Nick name"), ui1->pszNick,
+ TranslateT("Unique Id"), ui1->pszUID,
+ TranslateT("Status"), TM_WordToString( parentdat->pStatuses, ui1->Status ));
+ ti.lpszText = mir_tstrdup( ptszBuf );
+ }
+ }
+
+ SendMessage(hwndToolTip, bNewTip ? TTM_ADDTOOL : TTM_UPDATETIPTEXT, 0, (LPARAM) &ti);
+ SendMessage(hwndToolTip, TTM_ACTIVATE, (ti.lpszText != NULL) , 0);
+ SendMessage(hwndToolTip, TTM_SETMAXTIPWIDTH, 0 , 400);
+ if (ti.lpszText)
+ mir_free(ti.lpszText);
+ }
+}
+
+/*
+ * 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);
+ struct TWindowData *mwdat = (struct TWindowData *)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+
+ static BOOL isToolTip = NULL;
+ static int currentHovered = -1;
+
+ switch (msg) {
+ //MAD: attemp to fix weird bug, when combobox with hidden vscroll
+ //can't be scrolled with mouse-wheel.
+ case WM_NCCALCSIZE: {
+ if (CSkin::m_DisableScrollbars) {
+ RECT lpRect;
+ LONG itemHeight;
+
+ GetClientRect (hwnd, &lpRect);
+ itemHeight = SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0);
+ g_cLinesPerPage = (lpRect.bottom - lpRect.top) /itemHeight ;
+ }
+ return(CSkin::NcCalcRichEditFrame(hwnd, mwdat, ID_EXTBKUSERLIST, msg, wParam, lParam, OldNicklistProc));
+ }
+ //
+ case WM_NCPAINT:
+ return(CSkin::DrawRichEditFrame(hwnd, mwdat, ID_EXTBKUSERLIST, msg, wParam, lParam, OldNicklistProc));
+
+ case WM_ERASEBKGND: {
+ HDC dc = (HDC)wParam;
+ struct TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+ SESSION_INFO *parentdat = (SESSION_INFO *)dat->si;
+ if (dc) {
+ int height, index, items = 0;
+
+ index = SendMessage(hwnd, LB_GETTOPINDEX, 0, 0);
+ if (index == LB_ERR || parentdat->nUsersInNicklist <= 0)
+ return 0;
+
+ items = parentdat->nUsersInNicklist - index;
+ 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, hListBkgBrush);
+ }
+ }
+ }
+ }
+ return 1;
+
+ //MAD
+ case WM_MOUSEWHEEL: {
+ if (CSkin::m_DisableScrollbars) {
+ UINT uScroll;
+ int dLines;
+ 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 */
+
+ 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;
+ }
+//MAD_
+ 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 (mwdat && mwdat->si) {
+ SESSION_INFO *si = (SESSION_INFO *)mwdat->si;
+ si->szSearch[0] = 0;
+ si->iSearchItem = -1;
+ }
+ }
+ break;
+
+ case WM_SETFOCUS:
+ case WM_KILLFOCUS:
+ if (mwdat && mwdat->si) { // set/kill focus invalidates incremental search status
+ SESSION_INFO *si = (SESSION_INFO *)mwdat->si;
+ si->szSearch[0] = 0;
+ si->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 (mwdat && mwdat->si) {
+ SESSION_INFO *si = (SESSION_INFO *)mwdat->si;
+ if (wParam == 27 && si->szSearch[0]) { // escape - reset everything
+ si->szSearch[0] = 0;
+ si->iSearchItem = -1;
+ break;
+ } else if (wParam == '\b' && si->szSearch[0]) // backspace
+ si->szSearch[lstrlen(si->szSearch) - 1] = '\0';
+ else if (wParam < ' ')
+ break;
+ else {
+ TCHAR szNew[2];
+ szNew[0] = (TCHAR) wParam;
+ szNew[1] = '\0';
+ if (lstrlen(si->szSearch) >= SIZEOF(si->szSearch) - 2) {
+ MessageBeep(MB_OK);
+ break;
+ }
+ _tcscat(si->szSearch, szNew);
+ }
+ if (si->szSearch[0]) {
+ int iItems = SendMessage(hwnd, LB_GETCOUNT, 0, 0);
+ int i;
+ USERINFO *ui;
+
+ /*
+ * iterate over the (sorted) list of nicknames and search for the
+ * string we have
+ */
+
+ for (i=0; i < iItems; i++) {
+ ui = UM_FindUserFromIndex(si->pUsers, i);
+ if (ui) {
+ if (!_tcsnicmp(ui->pszNick, si->szSearch, lstrlen(si->szSearch))) {
+ SendMessage(hwnd, LB_SETSEL, FALSE, -1);
+ SendMessage(hwnd, LB_SETSEL, TRUE, i);
+ si->iSearchItem = i;
+ InvalidateRect(hwnd, NULL, FALSE);
+ return 0;
+ }
+ }
+ }
+ if (i == iItems) {
+ MessageBeep(MB_OK);
+ si->szSearch[lstrlen(si->szSearch) - 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 CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam);
+ return FALSE;
+ }
+
+ case WM_DRAWITEM: {
+ DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *) lParam;
+ if (dis->CtlType == ODT_MENU)
+ return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam);
+ return FALSE;
+ }
+ case WM_CONTEXTMENU: {
+ TVHITTESTINFO hti;
+ int item;
+ int height;
+ USERINFO * ui;
+ struct TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+ SESSION_INFO *parentdat = (SESSION_INFO *)dat->si;
+
+
+ hti.pt.x = (short) LOWORD(lParam);
+ hti.pt.y = (short) HIWORD(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);
+
+ item = (DWORD)(SendMessage(hwnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(hti.pt.x, hti.pt.y)));
+ if ( HIWORD( item ) == 1 )
+ item = (DWORD)(-1);
+ else
+ item &= 0xFFFF;
+
+ ui = SM_GetUserFromIndex(parentdat->ptszID, parentdat->pszModule, item);
+ // ui = (USERINFO *)SendMessage(GetDlgItem(hwndParent, IDC_LIST), LB_GETITEMDATA, item, 0);
+ if (ui) {
+ HMENU hMenu = 0;
+ UINT uID;
+ 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);
+ uID = CreateGCMenu(hwnd, &hMenu, 0, hti.pt, parentdat, uinew.pszUID, NULL);
+
+ switch (uID) {
+ case 0:
+ break;
+
+ case 20020: { // add to highlight...
+ RECT rc, rcWnd;
+ THighLightEdit the = {THighLightEdit::CMD_ADD, parentdat, ui};
+
+ if (parentdat && ui) {
+ HWND hwnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_ADDHIGHLIGHT), parentdat->dat->pContainer->hwnd, CMUCHighlight::dlgProcAdd, (LPARAM)&the);
+ TranslateDialogDefault(hwnd);
+ GetClientRect(parentdat->pContainer->hwnd, &rcWnd);
+ GetWindowRect(hwnd, &rc);
+
+ SetWindowPos(hwnd, 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:
+ DoEventHookAsync(GetParent(hwnd), parentdat->ptszID, parentdat->pszModule, GC_USER_PRIVMESS, ui->pszUID, NULL, (LPARAM)NULL);
+ 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 *)malloc(sizeof(int) * (iSelectedItems + 1));
+
+ if (pItems) {
+ if (SendMessage(hwnd, LB_GETSELITEMS, (WPARAM)iSelectedItems, (LPARAM)pItems) != LB_ERR) {
+ USERINFO *ui1 = NULL;
+ int i;
+
+ for (i=0; i < iSelectedItems; i++) {
+ ui1 = SM_GetUserFromIndex(parentdat->ptszID, parentdat->pszModule, pItems[i]);
+ if (ui1)
+ DoEventHookAsync(hwndParent, parentdat->ptszID, parentdat->pszModule, GC_USER_NICKLISTMENU, ui1->pszUID, NULL, (LPARAM)uID);
+ }
+ }
+ free(pItems);
+ }
+ }
+ }
+ //DoEventHookAsync(hwndParent, parentdat->ptszID, parentdat->pszModule, GC_USER_NICKLISTMENU, ui->pszUID, NULL, (LPARAM)uID);
+ break;
+ }
+ }
+ DestroyGCMenu(&hMenu, 1);
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_MOUSEMOVE: {
+ POINT pt;
+ RECT clientRect;
+ pt.x = LOWORD(lParam);
+ pt.y = HIWORD(lParam);
+ GetClientRect(hwnd, &clientRect);
+ if (PtInRect(&clientRect, pt)) {
+ //hit test item under mouse
+ struct TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+ SESSION_INFO *parentdat = (SESSION_INFO *)dat->si;
+
+ DWORD nItemUnderMouse = (DWORD)SendMessage(hwnd, LB_ITEMFROMPOINT, 0, lParam);
+ if (HIWORD(nItemUnderMouse) == 1)
+ nItemUnderMouse = (DWORD)(-1);
+ else
+ nItemUnderMouse &= 0xFFFF;
+
+ if (M->GetByte("adv_TipperTooltip", 1) && ServiceExists("mToolTip/HideTip")) {
+ if ((int)nItemUnderMouse == currentHovered) break;
+ currentHovered = (int)nItemUnderMouse;
+
+ KillTimer(hwnd, 1);
+
+ if (isToolTip) {
+ CallService("mToolTip/HideTip", 0, 0);
+ isToolTip = FALSE;
+ }
+
+ if (nItemUnderMouse != -1)
+ SetTimer(hwnd, 1, 450, 0);
+ }
+ else ProcessNickListHovering(hwnd, (int)nItemUnderMouse, &pt, parentdat);
+ }
+ else
+ {
+ if (M->GetByte("adv_TipperTooltip", 1) && ServiceExists("mToolTip/HideTip")) {
+ KillTimer(hwnd, 1);
+ if (isToolTip) {
+ CallService("mToolTip/HideTip", 0, 0);
+ isToolTip = FALSE;
+ }
+ }
+ else ProcessNickListHovering(hwnd, -1, &pt, NULL);
+ }
+ }
+ break;
+
+ case WM_TIMER:
+ {
+ CLCINFOTIP ti = {0};
+ USERINFO *ui1 = NULL;
+ TCHAR ptszBuf[1024];
+ char serviceName[256];
+ POINT pt;
+
+ struct TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
+ SESSION_INFO * parentdat = dat->si;
+
+ GetCursorPos(&pt);
+ ScreenToClient(hwnd, &pt);
+
+ DWORD nItemUnderMouse = (DWORD)SendMessage(GetDlgItem(dat->hwnd, IDC_LIST), LB_ITEMFROMPOINT, 0, MAKELPARAM(pt.x, pt.y));
+ if (HIWORD(nItemUnderMouse) == 1)
+ nItemUnderMouse = (DWORD)(-1);
+ else
+ nItemUnderMouse &= 0xFFFF;
+ if (((int)nItemUnderMouse != currentHovered) || (nItemUnderMouse == -1)) {
+ KillTimer(hwnd, 1);
+ break;
+ }
+
+ ui1 = SM_GetUserFromIndex(parentdat->ptszID, parentdat->pszModule, currentHovered);
+
+ if (ui1) {
+ ti.cbSize = sizeof(ti);
+ mir_snprintf(serviceName, SIZEOF(serviceName), "%s"MS_GC_PROTO_GETTOOLTIPTEXT, parentdat->pszModule);
+
+ if (ServiceExists(serviceName))
+ mir_sntprintf(ptszBuf, SIZEOF(ptszBuf), _T("%s"), (TCHAR*)CallService(serviceName, (WPARAM)parentdat->ptszID, (LPARAM)ui1->pszUID));
+ else
+ mir_sntprintf(ptszBuf, SIZEOF(ptszBuf), _T("<b>%s:</b>\t%s\n<b>%s:</b>\t%s\n<b>%s:</b>\t%s"),
+ TranslateT("Nick"), ui1->pszNick,
+ TranslateT("Unique id"), ui1->pszUID,
+ TranslateT("Status"), TM_WordToString(parentdat->pStatuses, ui1->Status));
+
+ if (ptszBuf != NULL)
+ if (CallService("mToolTip/ShowTipW", (WPARAM)mir_tstrdup(ptszBuf), (LPARAM)&ti))
+ isToolTip = TRUE;
+ }
+ KillTimer(hwnd, 1);
+ }
+ break;
+ }
+ return CallWindowProc(OldNicklistProc, hwnd, msg, wParam, lParam);
+}
+
+/*
+ * calculate the required rectangle for a string using the given font. This is more
+ * precise than using GetTextExtentPoint...()
+ */
+
+int GetTextPixelSize(TCHAR* pszText, HFONT hFont, BOOL bWidth)
+{
+ HDC hdc;
+ HFONT hOldFont;
+ RECT rc = {0};
+ int i;
+
+ if (!pszText || !hFont)
+ return 0;
+
+ hdc = GetDC(NULL);
+ hOldFont = (HFONT)SelectObject(hdc, hFont);
+ i = 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)
+{
+ SESSION_INFO* si = (SESSION_INFO*) lParam;
+ Sleep(30);
+ if (si && si->hWnd)
+ PostMessage(si->hWnd, GC_REDRAWLOG3, 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.
+ */
+
+INT_PTR CALLBACK RoomWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ SESSION_INFO * si = NULL;
+ HWND hwndTab = GetParent(hwndDlg);
+ struct TWindowData *dat = (struct TWindowData *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ if (dat)
+ si = (SESSION_INFO *)dat->si;
+
+ if (dat == NULL && (uMsg == WM_ACTIVATE || uMsg == WM_SETFOCUS))
+ return 0;
+
+ switch (uMsg) {
+ case WM_INITDIALOG: {
+ int mask;
+ struct TNewWindowData *newData = (struct TNewWindowData *) lParam;
+ struct TWindowData *dat;
+ SESSION_INFO *psi = (SESSION_INFO*)newData->hdbEvent;
+ RECT rc;
+
+ dat = (struct TWindowData *)malloc(sizeof(struct TWindowData));
+ ZeroMemory(dat, sizeof(struct TWindowData));
+ si = psi;
+ dat->si = psi;
+ dat->hContact = psi->hContact;
+ dat->szProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)psi->hContact, 0);
+ dat->bType = SESSIONTYPE_CHAT;
+ dat->Panel = new CInfoPanel(dat);
+
+ dat->cache = CContactCache::getContactCache(dat->hContact);
+ dat->cache->updateState();
+ dat->cache->updateUIN();
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
+ newData->item.lParam = (LPARAM) hwndDlg;
+ TabCtrl_SetItem(hwndTab, newData->iTabID, &newData->item);
+ dat->iTabID = newData->iTabID;
+ dat->pContainer = newData->pContainer;
+ psi->pContainer = newData->pContainer;
+ dat->hwnd = hwndDlg;
+ psi->hWnd = hwndDlg;
+ psi->dat = dat;
+ dat->fIsAutosizingInput = IsAutoSplitEnabled(dat);
+ dat->fLimitedUpdate = false;
+ dat->iInputAreaHeight = -1;
+ if (!dat->pContainer->settings->fPrivate)
+ psi->iSplitterY = g_Settings.iSplitterY;
+ else {
+ if (M->GetByte("Chat", "SyncSplitter", 0))
+ psi->iSplitterY = dat->pContainer->settings->splitterPos - DPISCALEY_S(23);
+ else
+ psi->iSplitterY = g_Settings.iSplitterY;
+ }
+#if defined(__FEAT_EXP_AUTOSPLITTER)
+ if (dat->fIsAutosizingInput)
+ psi->iSplitterY = GetDefaultMinimumInputHeight(dat);
+#endif
+ dat->pWnd = 0;
+ CProxyWindow::add(dat);
+
+ dat->fInsertMode = FALSE;
+
+ dat->codePage = M->GetDword(dat->hContact, "ANSIcodepage", CP_ACP);
+ dat->Panel->getVisibility();
+ dat->Panel->Configure();
+ M->AddWindow(hwndDlg, dat->hContact);
+ BroadCastContainer(dat->pContainer, DM_REFRESHTABINDEX, 0, 0);
+
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_SETOLECALLBACK, 0, (LPARAM) mREOLECallback);
+
+ BB_InitDlgButtons(dat);
+ DM_InitTip(dat);
+
+ SendMessage(GetDlgItem(hwndDlg,IDC_COLOR), BUTTONSETASPUSHBTN, TRUE, 0);
+
+ OldSplitterProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTERX), GWLP_WNDPROC, (LONG_PTR)SplitterSubclassProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTERY), GWLP_WNDPROC, (LONG_PTR)SplitterSubclassProc);
+ OldNicklistProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LIST), GWLP_WNDPROC, (LONG_PTR)NicklistSubclassProc);
+ OldLogProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHAT_LOG), GWLP_WNDPROC, (LONG_PTR)LogSubclassProc);
+ OldFilterButtonProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_FILTER), GWLP_WNDPROC, (LONG_PTR)ButtonSubclassProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_COLOR), GWLP_WNDPROC, (LONG_PTR)ButtonSubclassProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_BKGCOLOR), GWLP_WNDPROC, (LONG_PTR)ButtonSubclassProc);
+ OldMessageProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), GWLP_WNDPROC, (LONG_PTR)MessageSubclassProc);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SUBCLASSED, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_AUTOURLDETECT, 1, 0);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_PANELSPLITTER), GWLP_WNDPROC, (LONG_PTR) SplitterSubclassProc);
+ TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPENING, 0);
+
+ mask = (int)SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_GETEVENTMASK, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_SETEVENTMASK, 0, mask | ENM_LINK | ENM_MOUSEEVENTS | ENM_KEYEVENTS);
+
+#if defined(__FEAT_EXP_AUTOSPLITTER)
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETEVENTMASK, 0, ENM_REQUESTRESIZE | ENM_MOUSEEVENTS | ENM_SCROLL | ENM_KEYEVENTS | ENM_CHANGE);
+#else
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_SCROLL | ENM_KEYEVENTS | ENM_CHANGE);
+#endif
+
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_LIMITTEXT, (WPARAM)0x7FFFFFFF, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3));
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(3, 3));
+ dat->Panel->loadHeight();
+ Utils::enableDlgControl(hwndDlg, IDC_SMILEYBTN, TRUE);
+
+ if (PluginConfig.g_hMenuTrayUnread != 0 && dat->hContact != 0 && dat->szProto != NULL)
+ UpdateTrayMenu(0, dat->wStatus, dat->szProto, dat->szStatus, dat->hContact, FALSE);
+
+ DM_ThemeChanged(dat);
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_HIDESELECTION, TRUE, 0);
+
+ CreateWindowEx(0, _T("TSButtonClass"), _T(""), WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, 0, 6, DPISCALEY_S(20),
+ hwndDlg, (HMENU)IDC_CHAT_TOGGLESIDEBAR, g_hInst, NULL);
+
+ GetMYUIN(dat);
+ GetMyNick(dat);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_TOGGLESIDEBAR, BUTTONSETASTHEMEDBTN, PluginConfig.m_bIsXP, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_TOGGLESIDEBAR, BUTTONSETCONTAINER, (LPARAM)dat->pContainer, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_TOGGLESIDEBAR, BUTTONSETASFLATBTN, FALSE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_TOGGLESIDEBAR, BUTTONSETASTOOLBARBUTTON, TRUE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_TOGGLESIDEBAR, BUTTONADDTOOLTIP, (WPARAM)TranslateT("Expand or collapse the side bar"), 1);
+
+ dat->hwndIEView = dat->hwndHPP = 0;
+
+ //Chat_SetMessageLog(dat);
+
+ SendMessage(hwndDlg, GC_SETWNDPROPS, 0, 0);
+ SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0);
+ SendMessage(hwndDlg, GC_UPDATETITLE, 0, 1);
+ SendMessage(dat->pContainer->hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)&rc);
+ SetWindowPos(hwndDlg, HWND_TOP, rc.left, rc.top, (rc.right - rc.left), (rc.bottom - rc.top), 0);
+ ShowWindow(hwndDlg, SW_SHOW);
+ PostMessage(hwndDlg, GC_UPDATENICKLIST, 0, 0);
+ dat->pContainer->hwndActive = hwndDlg;
+ BB_SetButtonsPos(dat);
+ TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPEN, 0);
+ }
+ break;
+
+ case WM_SETFOCUS:
+ if (CMimAPI::m_shutDown)
+ break;
+
+ Chat_UpdateWindowState(dat, WM_SETFOCUS);
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ return 1;
+
+ case WM_TIMECHANGE:
+ PostMessage(hwndDlg, GC_REDRAWLOG, 0, 0);
+ break;
+
+ case DM_LOADBUTTONBARICONS: {
+ BB_UpdateIcons(hwndDlg, dat);
+ return 0;
+ }
+
+ case GC_SETWNDPROPS: {
+ //HICON hIcon;
+ COLORREF colour = M->GetDword(FONTMODULE, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR);
+ InitButtons(hwndDlg, si);
+ ConfigureSmileyButton(dat);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_SETBKGNDCOLOR, 0, colour);
+
+ DM_InitRichEdit(dat);
+ SendDlgItemMessage(hwndDlg, IDOK, BUTTONSETASNORMAL, TRUE, 0);
+ {
+ SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_SETITEMHEIGHT, 0, (LPARAM)g_Settings.iNickListFontHeight);
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_LIST), NULL, TRUE);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_FILTER, BUTTONSETOVERLAYICON,
+ (LPARAM)(si->bFilterEnabled ? PluginConfig.g_iconOverlayEnabled : PluginConfig.g_iconOverlayDisabled), 0);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ SendMessage(hwndDlg, GC_REDRAWLOG2, 0, 0);
+ }
+ break;
+
+ case DM_UPDATETITLE:
+ return(SendMessage(hwndDlg, GC_UPDATETITLE, wParam, lParam));
+
+ case GC_UPDATETITLE: {
+ TCHAR szTemp [100];
+ HICON hIcon;
+ BOOL fNoCopy = TRUE;
+ const TCHAR* szNick = dat->cache->getNick();
+
+ if (dat->bWasDeleted)
+ return 0;
+
+ dat->wStatus = si->wStatus;
+
+ if (lstrlen(szNick) > 0) {
+ if (M->GetByte("cuttitle", 0))
+ CutContactName(szNick, dat->newtitle, safe_sizeof(dat->newtitle));
+ else {
+ lstrcpyn(dat->newtitle, szNick, safe_sizeof(dat->newtitle));
+ dat->newtitle[129] = 0;
+ }
+ }
+
+ switch (si->iType) {
+ case GCW_CHATROOM:
+ hIcon = dat->wStatus <= ID_STATUS_OFFLINE ? LoadSkinnedProtoIcon(si->pszModule, ID_STATUS_OFFLINE) : LoadSkinnedProtoIcon(si->pszModule, dat->wStatus);
+ fNoCopy = FALSE;
+ mir_sntprintf(szTemp, SIZEOF(szTemp),
+ (si->nUsersInNicklist == 1) ? TranslateT("%s: Chat Room (%u user%s)") :
+ TranslateT("%s: Chat Room (%u users%s)"),
+ si->ptszName, si->nUsersInNicklist, si->bFilterEnabled ? TranslateT(", event filter active") : _T(""));
+ break;
+ case GCW_PRIVMESS:
+ mir_sntprintf(szTemp, SIZEOF(szTemp),
+ (si->nUsersInNicklist == 1) ? TranslateT("%s: Message Session") :
+ TranslateT("%s: Message Session (%u users)"), si->ptszName, si->nUsersInNicklist);
+ break;
+ case GCW_SERVER:
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s: Server"), si->ptszName);
+ hIcon = LoadIconEx(IDI_CHANMGR, "window", 16, 16);
+ break;
+ }
+
+ if (dat->pWnd) {
+ dat->pWnd->updateTitle(dat->newtitle);
+ dat->pWnd->updateIcon(hIcon);
+ }
+ dat->hTabStatusIcon = hIcon;
+
+ if (lParam)
+ dat->hTabIcon = dat->hTabStatusIcon;
+
+ if (dat->cache->getStatus() != dat->cache->getOldStatus()) {
+ TCITEM item;
+
+ ZeroMemory(&item, sizeof(item));
+ item.mask = TCIF_TEXT;
+
+ lstrcpyn(dat->szStatus, (TCHAR *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)dat->wStatus, GSMDF_TCHAR), 50);
+ dat->szStatus[49] = 0;
+ item.pszText = dat->newtitle;
+ item.cchTextMax = 120;
+ TabCtrl_SetItem(hwndTab, dat->iTabID, &item);
+ }
+ SetWindowText(hwndDlg, szTemp);
+ if (dat->pContainer->hwndActive == hwndDlg) {
+ SendMessage(dat->pContainer->hwnd, DM_UPDATETITLE, (WPARAM)hwndDlg, 1);
+ SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0);
+ }
+ }
+ break;
+
+ case GC_UPDATESTATUSBAR:
+ if (dat->bWasDeleted)
+ return 0;
+
+ if (dat->pContainer->hwndActive != hwndDlg || dat->pContainer->hwndStatus == 0 || CMimAPI::m_shutDown || dat->szStatusBar[0])
+ break;
+ if (si->pszModule != NULL) {
+ TCHAR szFinalStatusBarText[512];
+ MODULEINFO* mi=NULL;
+ int x = 12;
+
+ //Mad: strange rare crash here...
+ mi = MM_FindModule(si->pszModule);
+ if (!mi)
+ break;
+
+ if (!mi->ptszModDispName)
+ break;
+
+ x += GetTextPixelSize(mi->ptszModDispName, (HFONT)SendMessage(dat->pContainer->hwndStatus, WM_GETFONT, 0, 0), TRUE);
+ x += GetSystemMetrics(SM_CXSMICON);
+
+ if (dat->Panel->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_sntprintf(mi->tszIdleMsg, 60, TranslateT(", %d %s, %d %s idle"), hours, hours > 1 ?
+ TranslateT("hours") : TranslateT("hour"),
+ minutes, minutes > 1 ? TranslateT("minutes") : TranslateT("minute"));
+ }
+ else
+ mir_sntprintf(mi->tszIdleMsg, 60, TranslateT(", %d %s idle"),
+ diff, diff > 1 ? TranslateT("minutes") : TranslateT("minute"));
+ }
+ mir_sntprintf(szFinalStatusBarText, SIZEOF(szFinalStatusBarText), TranslateT("%s on %s%s"), dat->szMyNickname, mi->ptszModDispName, mi->tszIdleMsg);
+ } else {
+ if (si->ptszStatusbarText)
+ mir_sntprintf(szFinalStatusBarText, SIZEOF(szFinalStatusBarText), _T("%s %s"), mi->ptszModDispName, si->ptszStatusbarText);
+ else {
+ lstrcpyn(szFinalStatusBarText, mi->ptszModDispName, SIZEOF(szFinalStatusBarText));
+ szFinalStatusBarText[511] = 0;
+ }
+ }
+ SendMessage(dat->pContainer->hwndStatus, SB_SETTEXT, 0, (LPARAM)szFinalStatusBarText);
+ UpdateStatusBar(dat);
+ dat->Panel->Invalidate();
+ if (dat->pWnd)
+ dat->pWnd->Invalidate();
+ return TRUE;
+ }
+ break;
+
+ case WM_SIZE: {
+ UTILRESIZEDIALOG urd;
+ RECT rc;
+ int panelHeight = dat->Panel->getHeight() + 1;
+ LONG cx;
+
+ if (dat->ipFieldHeight == 0)
+ dat->ipFieldHeight = CInfoPanel::m_ipConfig.height1;
+
+ if (wParam == SIZE_MAXIMIZED)
+ PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0);
+
+ if (IsIconic(hwndDlg)) break;
+ ZeroMemory(&urd, sizeof(urd));
+ urd.cbSize = sizeof(urd);
+ urd.hInstance = g_hInst;
+ urd.hwndDlg = hwndDlg;
+ urd.lParam = (LPARAM)si;
+ urd.lpTemplate = MAKEINTRESOURCEA(IDD_CHANNEL);
+ urd.pfnResizer = RoomWndResize;
+ CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd);
+ //mad
+ BB_SetButtonsPos(dat);
+
+ GetClientRect(hwndDlg, &rc);
+ cx = rc.right;
+
+ 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 + dat->ipFieldHeight - 2 : panelHeight - 1);
+ dat->rcNick = rc;
+
+ rc.left = panelHeight <= CInfoPanel::LEFT_OFFSET_LOGO ? panelHeight : CInfoPanel::LEFT_OFFSET_LOGO;
+ rc.right = cx;
+ rc.bottom = panelHeight - 2;
+ rc.top = dat->rcNick.bottom + 1;
+ dat->rcUIN = rc;
+
+ if (dat->hwndIEView || dat->hwndHPP)
+ Chat_ResizeIeView(dat);
+ DetermineMinHeight(dat);
+ }
+ break;
+
+ case GC_REDRAWWINDOW:
+ InvalidateRect(hwndDlg, 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->bFilterEnabled || (si->iLogFilterFlags&pLog->iType) != 0)
+ index++;
+ }
+ Log_StreamInEvent(hwndDlg, pLog, si, TRUE, FALSE);
+ mir_forkthread(phase2, si);
+ } else Log_StreamInEvent(hwndDlg, si->pLogEnd, si, TRUE, FALSE);
+ } else SendMessage(hwndDlg, GC_EVENT_CONTROL + WM_USER + 500, WINDOW_CLEARLOG, 0);
+ break;
+
+ case GC_REDRAWLOG2:
+ si->LastTime = 0;
+ if (si->pLog)
+ Log_StreamInEvent(hwndDlg, si->pLogEnd, si, TRUE, FALSE);
+ break;
+
+ case GC_REDRAWLOG3:
+ si->LastTime = 0;
+ if (si->pLog)
+ Log_StreamInEvent(hwndDlg, si->pLogEnd, si, TRUE, TRUE);
+ break;
+
+ case GC_ADDLOG: {
+ BOOL fInactive = (GetForegroundWindow() != dat->pContainer->hwnd || GetActiveWindow() != dat->pContainer->hwnd);
+
+ if (g_Settings.UseDividers && g_Settings.DividersUsePopupConfig) {
+ if (!MessageWindowOpened(0, (LPARAM)hwndDlg))
+ SendMessage(hwndDlg, DM_ADDDIVIDER, 0, 0);
+ } else if (g_Settings.UseDividers) {
+ if (fInactive)
+ SendMessage(hwndDlg, DM_ADDDIVIDER, 0, 0);
+ else {
+ if (dat->pContainer->hwndActive != hwndDlg)
+ SendMessage(hwndDlg, DM_ADDDIVIDER, 0, 0);
+ }
+ }
+
+ if (si->pLogEnd)
+ Log_StreamInEvent(hwndDlg, si->pLog, si, FALSE, FALSE);
+ else
+ SendMessage(hwndDlg, GC_EVENT_CONTROL + WM_USER + 500, WINDOW_CLEARLOG, 0);
+ break;
+ }
+
+ case GC_ACKMESSAGE:
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETREADONLY, FALSE, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, WM_SETTEXT, 0, (LPARAM)_T(""));
+ return TRUE;
+
+ case WM_CTLCOLORLISTBOX:
+ SetBkColor((HDC) wParam, g_Settings.crUserListBGColor);
+ return (INT_PTR) hListBkgBrush;
+
+ case WM_MEASUREITEM: {
+ MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *) lParam;
+
+ if (mis->CtlType == ODT_MENU) {
+ if (dat->Panel->isHovered()) {
+ mis->itemHeight = 0;
+ mis->itemWidth = 6;
+ return(TRUE);
+ }
+ return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam);
+ }
+ else
+ mis->itemHeight = g_Settings.iNickListFontHeight;
+ return TRUE;
+ }
+
+ case WM_DRAWITEM: {
+ DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *) lParam;
+
+ if (dis->CtlType == ODT_MENU) {
+ if (dat->Panel->isHovered()) {
+ DrawMenuItem(dis, (HICON)dis->itemData, 0);
+ return(TRUE);
+ }
+ return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam);
+ }
+ else {
+ if (dis->CtlID == IDC_LIST) {
+ HFONT hFont, hOldFont;
+ HICON hIcon;
+ int offset, x_offset = 0;
+ int height;
+ int index = dis->itemID;
+ USERINFO * ui = UM_FindUserFromIndex(si->pUsers, index);
+ char szIndicator = 0;
+
+ if (ui) {
+ height = dis->rcItem.bottom - dis->rcItem.top;
+
+ if (height&1)
+ height++;
+ if (height == 10)
+ offset = 0;
+ else
+ offset = height / 2;
+ hIcon = SM_GetStatusIcon(si, ui, &szIndicator);
+ hFont = (ui->iStatusEx == 0) ? g_Settings.UserListFont : g_Settings.UserListHeadingsFont;
+ hOldFont = (HFONT) SelectObject(dis->hDC, hFont);
+ SetBkMode(dis->hDC, TRANSPARENT);
+
+ 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, hListBkgBrush);
+ if (g_Settings.ColorizeNicks && szIndicator != 0) {
+ COLORREF clr;
+
+ switch (szIndicator) {
+ case '@':
+ clr = g_Settings.nickColors[0];
+ break;
+ case '%':
+ clr = g_Settings.nickColors[1];
+ break;
+ case '+':
+ clr = g_Settings.nickColors[2];
+ break;
+ case '!':
+ clr = g_Settings.nickColors[3];
+ break;
+ case '*':
+ clr = g_Settings.nickColors[4];
+ break;
+ }
+ SetTextColor(dis->hDC, clr);
+ } else SetTextColor(dis->hDC, ui->iStatusEx == 0 ? g_Settings.crUserListColor : g_Settings.crUserListHeadingsColor);
+ }
+ x_offset = 2;
+
+ if (g_Settings.ShowContactStatus && g_Settings.ContactStatusFirst && ui->ContactStatus) {
+ HICON hIcon = LoadSkinnedProtoIcon(si->pszModule, ui->ContactStatus);
+ DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 8, hIcon, 16, 16, 0, NULL, DI_NORMAL);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ x_offset += 18;
+ }
+
+ if (g_Settings.ClassicIndicators) {
+ char szTemp[3];
+ SIZE szUmode;
+
+ szTemp[1] = 0;
+ szTemp[0] = szIndicator;
+ if (szTemp[0]) {
+ 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.ShowContactStatus && !g_Settings.ContactStatusFirst && ui->ContactStatus) {
+ HICON hIcon = LoadSkinnedProtoIcon(si->pszModule, ui->ContactStatus);
+ DrawIconEx(dis->hDC, x_offset, dis->rcItem.top + offset - 8, hIcon, 16, 16, 0, NULL, DI_NORMAL);
+ CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0);
+ x_offset += 18;
+ }
+
+ {
+ SIZE sz;
+
+ if (si->iSearchItem != -1 && si->iSearchItem == index && si->szSearch[0]) {
+ COLORREF clr_orig = GetTextColor(dis->hDC);
+ GetTextExtentPoint32(dis->hDC, ui->pszNick, lstrlen(si->szSearch), &sz);
+ SetTextColor(dis->hDC, RGB(250, 250, 0));
+ TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick, lstrlen(si->szSearch));
+ 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 + lstrlen(si->szSearch), lstrlen(ui->pszNick) - lstrlen(si->szSearch));
+ } else {
+ GetTextExtentPoint32(dis->hDC, ui->pszNick, lstrlen(ui->pszNick), &sz);
+ TextOut(dis->hDC, x_offset, (dis->rcItem.top + dis->rcItem.bottom - sz.cy) / 2, ui->pszNick, lstrlen(ui->pszNick));
+ SelectObject(dis->hDC, hOldFont);
+ }
+ }
+ }
+ return TRUE;
+ }
+ }
+ }
+ break;
+ case WM_CONTEXTMENU:{
+ //mad
+ DWORD idFrom=GetDlgCtrlID((HWND)wParam);
+ if (idFrom>=MIN_CBUTTONID&&idFrom<=MAX_CBUTTONID)
+ BB_CustomButtonClick(dat,idFrom,(HWND) wParam,1);
+ }break;
+ //
+ case GC_UPDATENICKLIST: {
+ int i = SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_GETTOPINDEX, 0, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_SETCOUNT, si->nUsersInNicklist, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_SETTOPINDEX, i, 0);
+ SendMessage(hwndDlg, GC_UPDATETITLE, 0, 0);
+ }
+ break;
+
+ case GC_EVENT_CONTROL + WM_USER + 500: {
+ switch (wParam) {
+ case SESSION_OFFLINE:
+ SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0);
+ SendMessage(si->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0);
+ return TRUE;
+
+ case SESSION_ONLINE:
+ SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0);
+ return TRUE;
+
+ case WINDOW_HIDDEN:
+ SendMessage(hwndDlg, GC_CLOSEWINDOW, 0, 1);
+ return TRUE;
+
+ case WINDOW_CLEARLOG:
+ SetDlgItemText(hwndDlg, IDC_CHAT_LOG, _T(""));
+ return TRUE;
+
+ case SESSION_TERMINATE:
+ if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->hContact, (LPARAM)szChatIconString);
+
+ si->wState &= ~STATE_TALK;
+ dat->bWasDeleted = 1;
+ DBWriteContactSettingWord(si->hContact, si->pszModule , "ApparentMode", (LPARAM) 0);
+ SendMessage(hwndDlg, GC_CLOSEWINDOW, 0, lParam == 2 ? lParam : 1);
+ return TRUE;
+
+ case WINDOW_MINIMIZE:
+ ShowWindow(hwndDlg, SW_MINIMIZE);
+ goto LABEL_SHOWWINDOW;
+
+ case WINDOW_MAXIMIZE:
+ ShowWindow(hwndDlg, SW_MAXIMIZE);
+ goto LABEL_SHOWWINDOW;
+
+ case SESSION_INITDONE:
+ if (M->GetByte("Chat", "PopupOnJoin", 0) != 0)
+ return TRUE;
+ // fall through
+ case WINDOW_VISIBLE:
+ if (IsIconic(hwndDlg))
+ ShowWindow(hwndDlg, SW_NORMAL);
+LABEL_SHOWWINDOW:
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ SendMessage(hwndDlg, GC_REDRAWLOG, 0, 0);
+ SendMessage(hwndDlg, GC_UPDATENICKLIST, 0, 0);
+ SendMessage(hwndDlg, GC_UPDATESTATUSBAR, 0, 0);
+ ShowWindow(hwndDlg, SW_SHOW);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ SetForegroundWindow(hwndDlg);
+ return TRUE;
+ }
+ }
+ break;
+
+ case DM_SPLITTERMOVED: {
+ POINT pt;
+ RECT rc;
+ RECT rcLog;
+ BOOL bFormat = TRUE; //IsWindowVisible(GetDlgItem(hwndDlg,IDC_SMILEY));
+
+ static int x = 0;
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_CHAT_LOG), &rcLog);
+ if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SPLITTERX)) {
+ int oldSplitterX;
+ GetClientRect(hwndDlg, &rc);
+ pt.x = wParam;
+ pt.y = 0;
+ ScreenToClient(hwndDlg, &pt);
+
+ oldSplitterX = si->iSplitterX;
+ si->iSplitterX = rc.right - pt.x + 1;
+ if (si->iSplitterX < 35)
+ si->iSplitterX = 35;
+ if (si->iSplitterX > rc.right - rc.left - 35)
+ si->iSplitterX = rc.right - rc.left - 35;
+ g_Settings.iSplitterX = si->iSplitterX;
+ SendMessage(dat->hwnd, WM_SIZE, 0, 0);
+ } else if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_SPLITTERY) || lParam == -1) {
+ int oldSplitterY;
+ GetClientRect(hwndDlg, &rc);
+ rc.top += (dat->Panel->isActive() ? dat->Panel->getHeight() + 40 : 30);
+ pt.x = 0;
+ pt.y = wParam;
+ ScreenToClient(hwndDlg, &pt);
+
+ oldSplitterY = si->iSplitterY;
+ si->iSplitterY = bFormat ? rc.bottom - pt.y + DPISCALEY_S(1) : rc.bottom - pt.y + DPISCALEY_S(20);
+ if (si->iSplitterY < DPISCALEY_S(23))
+ si->iSplitterY = DPISCALEY_S(23);
+ if (si->iSplitterY > rc.bottom - rc.top - DPISCALEY_S(40))
+ si->iSplitterY = rc.bottom - rc.top - DPISCALEY_S(40);
+ g_Settings.iSplitterY = si->iSplitterY;
+ CSkin::UpdateToolbarBG(dat, RDW_ALLCHILDREN);
+ SendMessage(dat->hwnd, WM_SIZE, 0, 0);
+ } else if ((HWND) lParam == GetDlgItem(hwndDlg, IDC_PANELSPLITTER)) {
+ RECT rc;
+ POINT pt;
+ pt.x = 0;
+ pt.y = wParam;
+ ScreenToClient(hwndDlg, &pt);
+ GetClientRect(GetDlgItem(hwndDlg, IDC_CHAT_LOG), &rc);
+ if ((pt.y + 2 >= MIN_PANELHEIGHT + 2) && (pt.y + 2 < 100) && (pt.y + 2 < rc.bottom - 30))
+ dat->Panel->setHeight(pt.y + 2);
+ dat->panelWidth = -1;
+ RedrawWindow(hwndDlg, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
+ if (M->isAero())
+ InvalidateRect(GetParent(hwndDlg), NULL, FALSE);
+ SendMessage(hwndDlg, WM_SIZE, DM_SPLITTERMOVED, 0);
+ break;
+ }
+ }
+ break;
+
+ case GC_FIREHOOK:
+ if (lParam) {
+ GCHOOK* gch = (GCHOOK *) lParam;
+ NotifyEventHooks(hSendEvent, 0, (WPARAM)gch);
+ if (gch->pDest) {
+ mir_free(gch->pDest->pszID);
+ mir_free(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(hwndDlg, WM_COMMAND, IDC_FILTER, 0);
+ break;
+
+ case GC_SHOWFILTERMENU: {
+ RECT rcFilter, rcLog;
+ POINT pt;
+
+ si->hwndFilter = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_FILTER), dat->pContainer->hwnd, FilterWndProc, (LPARAM)si);
+ TranslateDialogDefault(si->hwndFilter);
+
+ GetClientRect(si->hwndFilter, &rcFilter);
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_CHAT_LOG), &rcLog);
+ pt.x = rcLog.right;
+ pt.y = rcLog.bottom;
+ ScreenToClient(dat->pContainer->hwnd, &pt);
+
+ SetWindowPos(si->hwndFilter, HWND_TOP, pt.x - rcFilter.right, pt.y - rcFilter.bottom, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
+ }
+ break;
+
+ case DM_SPLITTERGLOBALEVENT: {
+ DM_SplitterGlobalEvent(dat, wParam, lParam);
+ return 0;
+ }
+
+ case GC_SHOWCOLORCHOOSER: {
+ HWND ColorWindow;
+ RECT rc;
+ BOOL bFG = lParam == IDC_COLOR ? TRUE : FALSE;
+ COLORCHOOSER *pCC = (COLORCHOOSER *)mir_alloc(sizeof(COLORCHOOSER));
+
+ GetWindowRect(GetDlgItem(hwndDlg, bFG ? IDC_COLOR : IDC_BKGCOLOR), &rc);
+ pCC->hWndTarget = GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE);
+ pCC->pModule = MM_FindModule(si->pszModule);
+ pCC->xPosition = rc.left + 3;
+ pCC->yPosition = IsWindowVisible(GetDlgItem(hwndDlg, IDC_COLOR)) ? rc.top - 1 : rc.top + 20;
+ pCC->bForeground = bFG;
+ pCC->si = si;
+
+ ColorWindow = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_COLORCHOOSER), hwndDlg, DlgProcColorToolWindow, (LPARAM) pCC);
+ }
+ break;
+
+ case GC_SCROLLTOBOTTOM: {
+ return(DM_ScrollToBottom(dat, wParam, lParam));
+ }
+
+ case WM_TIMER:
+ if (wParam == TIMERID_FLASHWND)
+ if (dat->mayFlashTab)
+ FlashTab(dat, hwndTab, dat->iTabID, &dat->bTabFlash, TRUE, dat->hTabIcon);
+ break;
+
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) != WA_ACTIVE) {
+ dat->pContainer->hwndSaved = 0;
+ break;
+ }
+
+ //fall through
+ case WM_MOUSEACTIVATE:
+ Chat_UpdateWindowState(dat, WM_ACTIVATE);
+ return 1;
+
+ case WM_NOTIFY: {
+ LPNMHDR pNmhdr = (LPNMHDR)lParam;
+ switch (pNmhdr->code) {
+ case EN_MSGFILTER: {
+ UINT msg = ((MSGFILTER *) lParam)->msg;
+ WPARAM wp = ((MSGFILTER *) lParam)->wParam;
+ LPARAM lp = ((MSGFILTER *) lParam)->lParam;
+
+ BOOL isShift, isCtrl, isMenu;
+ KbdState(dat, isShift, isCtrl, isMenu);
+
+ MSG message;
+ message.hwnd = hwndDlg;
+ message.message = msg;
+ message.lParam = lp;
+ message.wParam = wp;
+
+ if (msg == WM_SYSKEYUP) {
+ if (wp == VK_MENU) {
+ if (!dat->fkeyProcessed && !(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000) && !(lp & (1 << 24)))
+ dat->pContainer->MenuBar->autoShow();
+ }
+ return(_dlgReturn(hwndDlg, 0));
+ }
+
+ if (msg == WM_MOUSEMOVE) {
+ POINT pt;
+ GetCursorPos(&pt);
+ DM_DismissTip(dat, pt);
+ dat->Panel->trackMouse(pt);
+ break;
+ }
+ if (msg == WM_KEYDOWN) {
+ if ((wp == VK_INSERT && isShift && !isCtrl && !isMenu) || (wp == 'V' && !isShift && !isMenu && isCtrl)) {
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), EM_PASTESPECIAL, CF_TEXTT, 0);
+ ((MSGFILTER *) lParam)->msg = WM_NULL;
+ ((MSGFILTER *) lParam)->wParam = 0;
+ ((MSGFILTER *) lParam)->lParam = 0;
+ return(_dlgReturn(hwndDlg, 1));
+ }
+ }
+
+ if (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN || msg == WM_MBUTTONDOWN)
+ dat->pContainer->MenuBar->Cancel();
+
+ if ((msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) && !(GetKeyState(VK_RMENU) & 0x8000)) {
+
+ if (DM_GenericHotkeysCheck(&message, dat)) {
+ dat->fkeyProcessed = true;
+ return(_dlgReturn(hwndDlg, 1));
+ }
+
+ LRESULT mim_hotkey_check = CallService(MS_HOTKEY_CHECK, (WPARAM)&message, (LPARAM)(TABSRMM_HK_SECTION_GC));
+ if (mim_hotkey_check)
+ dat->fkeyProcessed = true;
+ switch(mim_hotkey_check) { // nothing (yet) FIXME
+ case TABSRMM_HK_CHANNELMGR:
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHANMGR, BN_CLICKED), 0);
+ return(_dlgReturn(hwndDlg, 1));
+ case TABSRMM_HK_FILTERTOGGLE:
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_FILTER, BN_CLICKED), 0);
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_FILTER), NULL, TRUE);
+ return(_dlgReturn(hwndDlg, 1));
+ case TABSRMM_HK_LISTTOGGLE:
+ SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_SHOWNICKLIST, BN_CLICKED), 0);
+ return(_dlgReturn(hwndDlg, 1));
+ case TABSRMM_HK_MUC_SHOWSERVER:
+ if (si->iType != GCW_SERVER)
+ DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_MESSAGE, NULL, L"/servershow", (LPARAM)NULL);
+ return(_dlgReturn(hwndDlg, 1));
+ default:
+ break;
+ }
+ }
+
+ if (msg == WM_KEYDOWN && wp == VK_TAB) {
+ if (((NMHDR *)lParam)->idFrom == IDC_CHAT_LOG) {
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ return(_dlgReturn(hwndDlg, 1));
+ }
+ }
+
+ if (pNmhdr->idFrom == IDC_CHAT_LOG && ((MSGFILTER *) lParam)->msg == WM_RBUTTONUP) {
+ CHARRANGE sel, all = { 0, -1 };
+ POINT pt;
+ UINT uID = 0;
+ HMENU hMenu = 0;
+ TCHAR pszWord[4096];
+ int pos;
+
+ pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam);
+ pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam);
+ ClientToScreen(pNmhdr->hwndFrom, &pt);
+
+ { // fixing stuff for searches
+ long iCharIndex, iLineIndex, iChars, start, end, iRes;
+ POINTL ptl;
+
+ pszWord[0] = '\0';
+ ptl.x = (LONG)pt.x;
+ ptl.y = (LONG)pt.y;
+ ScreenToClient(GetDlgItem(hwndDlg, IDC_CHAT_LOG), (LPPOINT)&ptl);
+ iCharIndex = SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_CHARFROMPOS, 0, (LPARAM) & ptl);
+ if (iCharIndex < 0)
+ break;
+ iLineIndex = SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_EXLINEFROMCHAR, 0, (LPARAM)iCharIndex);
+ iChars = SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_LINEINDEX, (WPARAM)iLineIndex, 0);
+ start = SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_FINDWORDBREAK, WB_LEFT, iCharIndex);//-iChars;
+ end = SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_FINDWORDBREAK, WB_RIGHT, iCharIndex);//-iChars;
+
+ if (end - start > 0) {
+ TEXTRANGE tr;
+ CHARRANGE cr;
+ static char szTrimString[] = ":;,.!?\'\"><()[]- \r\n";
+ ZeroMemory(&tr, sizeof(TEXTRANGE));
+
+ cr.cpMin = start;
+ cr.cpMax = end;
+ tr.chrg = cr;
+ tr.lpstrText = (TCHAR *)pszWord;
+ iRes = SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_GETTEXTRANGE, 0, (LPARAM) & tr);
+
+ if (iRes > 0) {
+ int iLen = lstrlen(pszWord) - 1;
+ while (iLen >= 0 && strchr(szTrimString, pszWord[iLen])) {
+ pszWord[iLen] = '\0';
+ iLen--;
+ }
+ }
+ }
+ }
+
+ uID = CreateGCMenu(hwndDlg, &hMenu, 1, pt, si, NULL, pszWord);
+
+ if ((uID > 800 && uID < 1400) || uID == CP_UTF8 || uID == 20866) {
+ dat->codePage = uID;
+ M->WriteDword(dat->hContact, SRMSGMOD_T, "ANSIcodepage", dat->codePage);
+ } else if (uID == 500) {
+ dat->codePage = CP_ACP;
+ DBDeleteContactSetting(dat->hContact, SRMSGMOD_T, "ANSIcodepage");
+ } else {
+ switch (uID) {
+ case 0:
+ PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0);
+ break;
+
+ case ID_COPYALL:
+ SendMessage(pNmhdr->hwndFrom, EM_EXGETSEL, 0, (LPARAM) & sel);
+ SendMessage(pNmhdr->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & all);
+ SendMessage(pNmhdr->hwndFrom, WM_COPY, 0, 0);
+ SendMessage(pNmhdr->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & sel);
+ PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0);
+ break;
+
+ case ID_CLEARLOG:
+ ClearLog(dat);
+ break;
+
+ case ID_SEARCH_GOOGLE: {
+ TCHAR szURL[4096];
+ if (pszWord[0]) {
+ mir_sntprintf(szURL, SIZEOF(szURL), _T("http://www.google.com/search?q=%s"), pszWord);
+ CallService(MS_UTILS_OPENURL, OUF_NEWWINDOW|OUF_TCHAR, (LPARAM) szURL);
+ }
+ PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0);
+ }
+ break;
+
+ case ID_SEARCH_WIKIPEDIA: {
+ TCHAR szURL[4096];
+ if (pszWord[0]) {
+ mir_sntprintf(szURL, SIZEOF(szURL), _T("http://en.wikipedia.org/wiki/%s"), pszWord);
+ CallService(MS_UTILS_OPENURL, OUF_NEWWINDOW|OUF_TCHAR, (LPARAM) szURL);
+ }
+ PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0);
+ }
+ break;
+
+ default:
+ PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0);
+ DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_LOGMENU, NULL, NULL, (LPARAM)uID);
+ break;
+ }
+ }
+ if (si->iType != GCW_SERVER && !(si->dwFlags & GC_UNICODE)) {
+ pos = GetMenuItemCount(hMenu);
+ RemoveMenu(hMenu, pos - 1, MF_BYPOSITION);
+ RemoveMenu(PluginConfig.g_hMenuEncoding, 1, MF_BYPOSITION);
+ }
+ DestroyGCMenu(&hMenu, 5);
+ }
+ break;
+ }
+
+ case EN_REQUESTRESIZE: {
+ if (pNmhdr->idFrom == IDC_CHAT_MESSAGE) {
+ REQRESIZE *rr = (REQRESIZE *)lParam;
+ DM_HandleAutoSizeRequest(dat, rr);
+ }
+ break;
+ }
+
+ case EN_LINK:
+ if (pNmhdr->idFrom == IDC_CHAT_LOG) {
+ switch (((ENLINK *) lParam)->msg) {
+ case WM_SETCURSOR:
+
+ if (g_Settings.ClickableNicks) {
+ if (!hCurHyperlinkHand)
+ hCurHyperlinkHand = LoadCursor(NULL, IDC_HAND);
+ if (hCurHyperlinkHand != GetCursor())
+ SetCursor(hCurHyperlinkHand);
+ return TRUE;
+ }
+ break;
+
+ case WM_RBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_LBUTTONDBLCLK: {
+ TEXTRANGE tr;
+ CHARRANGE sel;
+ BOOL isLink = FALSE;
+ UINT msg = ((ENLINK *) lParam)->msg;
+
+ dat->pContainer->MenuBar->Cancel();
+
+ tr.lpstrText = NULL;
+ SendMessage(pNmhdr->hwndFrom, EM_EXGETSEL, 0, (LPARAM) & sel);
+ if (sel.cpMin != sel.cpMax)
+ break;
+ tr.chrg = ((ENLINK *) lParam)->chrg;
+ tr.lpstrText = (TCHAR *)mir_alloc(sizeof(TCHAR) * (tr.chrg.cpMax - tr.chrg.cpMin + 2));
+ SendMessage(pNmhdr->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM) & tr);
+
+ isLink = IsStringValidLink(tr.lpstrText);
+
+ if (isLink) {
+ if (((ENLINK *) lParam)->msg == WM_RBUTTONDOWN) {
+ HMENU hSubMenu;
+ POINT pt;
+
+ hSubMenu = GetSubMenu(g_hMenu, 2);
+ TranslateMenu(hSubMenu);
+ pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam);
+ pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam);
+ ClientToScreen(((NMHDR *) lParam)->hwndFrom, &pt);
+ switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) {
+ case ID_NEW:
+ CallService(MS_UTILS_OPENURL, OUF_NEWWINDOW|OUF_TCHAR, (LPARAM) tr.lpstrText);
+ break;
+ case ID_CURR:
+ CallService(MS_UTILS_OPENURL, OUF_TCHAR, (LPARAM) tr.lpstrText);
+ break;
+ case ID_COPY: {
+ if (!OpenClipboard(hwndDlg))
+ break;
+ EmptyClipboard();
+ HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(TCHAR) * (lstrlen(tr.lpstrText) + 1));
+ lstrcpy((TCHAR*)GlobalLock(hData), tr.lpstrText);
+ GlobalUnlock(hData);
+ SetClipboardData(CF_UNICODETEXT, hData);
+ }
+ CloseClipboard();
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ break;
+ }
+ mir_free(tr.lpstrText);
+ return TRUE;
+ } else if (((ENLINK *) lParam)->msg == WM_LBUTTONUP) {
+ CallService(MS_UTILS_OPENURL, OUF_NEWWINDOW|OUF_TCHAR, (LPARAM) tr.lpstrText);
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ mir_free(tr.lpstrText);
+ return TRUE;
+ }
+ } else if (g_Settings.ClickableNicks) { // clicked a nick name
+ CHARRANGE chr;
+ TEXTRANGE tr2;
+ TCHAR tszAplTmpl[] = _T("%s:"),
+ *tszAppeal, *tszTmp;
+ size_t st;
+
+ if (msg == WM_RBUTTONDOWN) {
+ USERINFO *ui = si->pUsers;
+ HMENU hMenu = 0;
+ USERINFO uiNew;
+ while (ui) {
+ if (!lstrcmp(ui->pszNick, tr.lpstrText)) {
+ POINT pt;
+ UINT uID;
+
+ pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam);
+ pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam);
+ ClientToScreen(((NMHDR *) lParam)->hwndFrom, &pt);
+ CopyMemory(&uiNew, ui, sizeof(USERINFO));
+ uID = CreateGCMenu(hwndDlg, &hMenu, 0, pt, si, uiNew.pszUID, NULL);
+ switch (uID) {
+ case 0:
+ break;
+
+ case ID_MESS:
+ DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui->pszUID, NULL, (LPARAM)NULL);
+ break;
+
+ default:
+ DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_NICKLISTMENU, ui->pszUID, NULL, (LPARAM)uID);
+ break;
+ }
+ DestroyGCMenu(&hMenu, 1);
+ return TRUE;
+ }
+ ui = ui->next;
+ }
+ return TRUE;
+ }
+ else if (msg == WM_LBUTTONUP) {
+ USERINFO *ui = si->pUsers;
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_EXGETSEL, 0, (LPARAM) &chr);
+ tszTmp = tszAppeal = (TCHAR *) malloc((lstrlen(tr.lpstrText) + lstrlen(tszAplTmpl) + 3) * sizeof(TCHAR));
+ tr2.lpstrText = (LPTSTR) malloc(sizeof(TCHAR) * 2);
+ if (chr.cpMin) {
+ /* prepend nick with space if needed */
+ tr2.chrg.cpMin = chr.cpMin - 1;
+ tr2.chrg.cpMax = chr.cpMin;
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_GETTEXTRANGE, 0, (LPARAM) &tr2);
+ if (! _istspace(*tr2.lpstrText))
+ *tszTmp++ = _T(' ');
+ _tcscpy(tszTmp, tr.lpstrText);
+ }
+ else
+ /* in the beginning of the message window */
+ _stprintf(tszAppeal, tszAplTmpl, tr.lpstrText);
+ st = lstrlen(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 (! SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_GETTEXTRANGE, 0, (LPARAM) &tr2) || ! _istspace(*tr2.lpstrText)) {
+ tszAppeal[st++] = _T(' ');
+ tszAppeal[st++] = _T('\0');
+ }
+ }
+ else {
+ tszAppeal[st++] = _T(' ');
+ tszAppeal[st++] = _T('\0');
+ }
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_REPLACESEL, FALSE, (LPARAM)tszAppeal);
+ free((void *) tr2.lpstrText);
+ free((void *) tszAppeal);
+ }
+ }
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ mir_free(tr.lpstrText);
+ return TRUE;
+ }
+ }
+ return TRUE;
+ }
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_LBUTTONDOWN: {
+ POINT tmp; //+ Protogenes
+ POINTS cur; //+ Protogenes
+ GetCursorPos(&tmp); //+ Protogenes
+ if (!dat->Panel->isHovered()) {
+ cur.x = (SHORT)tmp.x; //+ Protogenes
+ cur.y = (SHORT)tmp.y; //+ Protogenes
+ SendMessage(dat->pContainer->hwnd, WM_NCLBUTTONDOWN, HTCAPTION, *((LPARAM*)(&cur))); //+ Protogenes
+ }
+ break;
+ }
+
+ case WM_LBUTTONUP: {
+ POINT tmp; //+ Protogenes
+ POINTS cur; //+ Protogenes
+ GetCursorPos(&tmp); //+ Protogenes
+ if (dat->Panel->isHovered())
+ dat->Panel->handleClick(tmp);
+ else {
+ cur.x = (SHORT)tmp.x; //+ Protogenes
+ cur.y = (SHORT)tmp.y; //+ Protogenes
+ SendMessage(dat->pContainer->hwnd, WM_NCLBUTTONUP, HTCAPTION, *((LPARAM*)(&cur))); //+ Protogenes
+ }
+ break;
+ }
+
+ case WM_MOUSEMOVE: {
+ POINT pt;
+ GetCursorPos(&pt);
+ DM_DismissTip(dat, pt);
+ dat->Panel->trackMouse(pt);
+ break;
+ }
+ case WM_APPCOMMAND: {
+ DWORD cmd = GET_APPCOMMAND_LPARAM(lParam);
+ if (cmd == APPCOMMAND_BROWSER_BACKWARD || cmd == APPCOMMAND_BROWSER_FORWARD) {
+ SendMessage(dat->pContainer->hwnd, DM_SELECTTAB, cmd == APPCOMMAND_BROWSER_BACKWARD ? DM_SELECT_PREV : DM_SELECT_NEXT, 0);
+ return 1;
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ //mad
+ if (LOWORD(wParam)>=MIN_CBUTTONID&&LOWORD(wParam)<=MAX_CBUTTONID){
+ BB_CustomButtonClick(dat,LOWORD(wParam) ,GetDlgItem(hwndDlg,LOWORD(wParam)),0);
+ break;
+ }
+ //
+ switch (LOWORD(wParam)) {
+ case IDC_LIST:
+ if (HIWORD(wParam) == LBN_DBLCLK) {
+ TVHITTESTINFO hti;
+ int item;
+ USERINFO * ui;
+
+ hti.pt.x = (short)LOWORD(GetMessagePos());
+ hti.pt.y = (short)HIWORD(GetMessagePos());
+ ScreenToClient(GetDlgItem(hwndDlg, IDC_LIST), &hti.pt);
+
+ item = LOWORD(SendMessage(GetDlgItem(hwndDlg, IDC_LIST), LB_ITEMFROMPOINT, 0, MAKELPARAM(hti.pt.x, hti.pt.y)));
+ ui = UM_FindUserFromIndex(si->pUsers, item);
+ //ui = SM_GetUserFromIndex(si->pszID, si->pszModule, item);
+ if (ui) {
+ if (g_Settings.DoubleClick4Privat ? GetKeyState(VK_SHIFT) & 0x8000 : !(GetKeyState(VK_SHIFT) & 0x8000)) {
+ LRESULT lResult = (LRESULT)SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), EM_GETSEL, (WPARAM)NULL, (LPARAM)NULL);
+ int start = LOWORD(lResult);
+ TCHAR* pszName = (TCHAR*)alloca(sizeof(TCHAR) * (lstrlen(ui->pszUID) + 3));
+ if (start == 0)
+ mir_sntprintf(pszName, lstrlen(ui->pszUID) + 3, _T("%s: "), ui->pszUID);
+ else
+ mir_sntprintf(pszName, lstrlen(ui->pszUID) + 2, _T("%s "), ui->pszUID);
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), EM_REPLACESEL, FALSE, (LPARAM) pszName);
+ PostMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 0);
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ } else DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui->pszUID, NULL, (LPARAM)NULL);
+ }
+
+ return TRUE;
+ } else if (HIWORD(wParam) == LBN_KILLFOCUS)
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_LIST), NULL, NULL, RDW_INVALIDATE);
+ break;
+
+ case IDC_CHAT_TOGGLESIDEBAR:
+ SendMessage(dat->pContainer->hwnd, WM_COMMAND, IDC_TOGGLESIDEBAR, 0);
+ break;
+
+ case IDCANCEL:
+ ShowWindow(dat->pContainer->hwnd, SW_MINIMIZE);
+ return FALSE;
+
+ case IDOK: {
+ char* pszRtf;
+ TCHAR* ptszText/*, *p1*/;
+ MODULEINFO* mi;
+ bool fSound = true;
+
+ if (GetSendButtonState(hwndDlg) == PBS_DISABLED)
+ break;
+
+ mi = MM_FindModule(si->pszModule);
+
+ pszRtf = Chat_Message_GetFromStream(hwndDlg, si);
+ SM_AddCommand(si->ptszID, si->pszModule, pszRtf);
+ ptszText = Chat_DoRtfToTags(pszRtf, si);
+ DoTrimMessage(ptszText);
+
+ if (mi && mi->bAckMsg) {
+ Utils::enableDlgControl(hwndDlg, IDC_CHAT_MESSAGE, FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETREADONLY, TRUE, 0);
+ } else SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, WM_SETTEXT, 0, (LPARAM)_T(""));
+
+ Utils::enableDlgControl(hwndDlg, IDOK, FALSE);
+
+ if (ptszText[0] == '/' || si->iType == GCW_SERVER)
+ fSound = false;
+ DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_MESSAGE, NULL, ptszText, (LPARAM)NULL);
+ mi->idleTimeStamp = time(0);
+ mi->lastIdleCheck = 0;
+ SM_BroadcastMessage(si->pszModule, GC_UPDATESTATUSBAR, 0, 1, TRUE);
+ if (dat && dat->pContainer) {
+ if (fSound && !nen_options.iNoSounds && !(dat->pContainer->dwFlags & CNT_NOSOUND))
+ SkinPlaySound("ChatSent");
+ }
+ mir_free(pszRtf);
+ mir_free(ptszText);
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ }
+ break;
+
+ case IDC_SHOWNICKLIST:
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_SHOWNICKLIST)))
+ break;
+ if (si->iType == GCW_SERVER)
+ break;
+
+ si->bNicklistEnabled = !si->bNicklistEnabled;
+
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ if (CSkin::m_skinEnabled)
+ InvalidateRect(hwndDlg, NULL, TRUE);
+ PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0);
+ break;
+
+ case IDC_CHAT_MESSAGE:
+ if (g_Settings.MathMod)
+ MTH_updateMathWindow(dat);
+
+ if (HIWORD(wParam) == EN_CHANGE) {
+ if (dat->pContainer->hwndActive == hwndDlg)
+ UpdateReadChars(dat);
+ dat->dwLastActivity = GetTickCount();
+ dat->pContainer->dwLastActivity = dat->dwLastActivity;
+ SendDlgItemMessage(hwndDlg, IDOK, BUTTONSETASNORMAL, GetRichTextLength(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE)) != 0, 0);
+ Utils::enableDlgControl(hwndDlg, IDOK, GetRichTextLength(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE)) != 0);
+ }
+ break;
+
+ case IDC_SMILEY:
+ case IDC_SMILEYBTN: {
+ SMADD_SHOWSEL3 smaddInfo = {0};
+ RECT rc;
+
+ if (lParam == 0)
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_SMILEYBTN), &rc);
+ else
+ GetWindowRect((HWND)lParam, &rc);
+ smaddInfo.cbSize = sizeof(SMADD_SHOWSEL3);
+ smaddInfo.hwndTarget = GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE);
+ smaddInfo.targetMessage = EM_REPLACESEL;
+ smaddInfo.targetWParam = TRUE;
+ smaddInfo.Protocolname = si->pszModule;
+ smaddInfo.Direction = 0;
+ smaddInfo.xPosition = rc.left;
+ smaddInfo.yPosition = rc.top + 24;
+ smaddInfo.hContact = si->hContact;
+ smaddInfo.hwndParent = dat->pContainer->hwnd;
+ if (PluginConfig.g_SmileyAddAvail)
+ CallService(MS_SMILEYADD_SHOWSELECTION, 0, (LPARAM) &smaddInfo);
+ }
+ break;
+
+ case IDC_CHAT_HISTORY: {
+ MODULEINFO * pInfo = MM_FindModule(si->pszModule);
+
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_CHAT_HISTORY)))
+ break;
+
+ 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(hwndDlg, NULL, GetChatLogsFilename(si, 0), NULL, NULL, SW_SHOW);
+ }
+ break;
+
+ case IDC_CHAT_CLOSE:
+ SendMessage(hwndDlg, WM_CLOSE, 0, 1);
+ break;
+
+ case IDC_CHANMGR:
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_CHANMGR)))
+ break;
+ DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_CHANMGR, NULL, NULL, (LPARAM)NULL);
+ break;
+
+ case IDC_FILTER:
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_FILTER)))
+ break;
+
+ if (si->iLogFilterFlags == 0 && !si->bFilterEnabled) {
+ MessageBox(0, TranslateT("The filter canoot 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;
+
+ SendDlgItemMessage(hwndDlg, IDC_FILTER, BUTTONSETOVERLAYICON,
+ (LPARAM)(si->bFilterEnabled ? PluginConfig.g_iconOverlayEnabled : PluginConfig.g_iconOverlayDisabled), 0);
+
+ if (si->bFilterEnabled && M->GetByte("Chat", "RightClickFilter", 0) == 0) {
+ SendMessage(hwndDlg, GC_SHOWFILTERMENU, 0, 0);
+ break;
+ }
+ SendMessage(hwndDlg, GC_REDRAWLOG, 0, 0);
+ SendMessage(hwndDlg, GC_UPDATETITLE, 0, 0);
+ M->WriteByte(si->hContact, "Chat", "FilterEnabled", (BYTE)si->bFilterEnabled);
+ break;
+
+ case IDC_BKGCOLOR: {
+ CHARFORMAT2 cf;
+
+ cf.cbSize = sizeof(CHARFORMAT2);
+ cf.dwEffects = 0;
+
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_BKGCOLOR)))
+ break;
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_BKGCOLOR)) {
+ if (M->GetByte("Chat", "RightClickFilter", 0) == 0)
+ SendMessage(hwndDlg, GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_BKGCOLOR);
+ else if (si->bBGSet) {
+ cf.dwMask = CFM_BACKCOLOR;
+ cf.crBackColor = MM_FindModule(si->pszModule)->crColors[si->iBG];
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ } else {
+ cf.dwMask = CFM_BACKCOLOR;
+ cf.crBackColor = (COLORREF)M->GetDword(FONTMODULE, "inputbg", SRMSGDEFSET_BKGCOLOUR);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ }
+ break;
+
+ case IDC_COLOR: {
+ CHARFORMAT2 cf;
+ cf.cbSize = sizeof(CHARFORMAT2);
+ cf.dwEffects = 0;
+
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDC_COLOR)))
+ break;
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_COLOR)) {
+ if (M->GetByte("Chat", "RightClickFilter", 0) == 0)
+ SendMessage(hwndDlg, GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_COLOR);
+ else if (si->bFGSet) {
+ cf.dwMask = CFM_COLOR;
+ cf.crTextColor = MM_FindModule(si->pszModule)->crColors[si->iFG];
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ } else {
+ COLORREF cr;
+
+ LoadLogfont(MSGFONTID_MESSAGEAREA, NULL, &cr, FONTMODULE);
+ cf.dwMask = CFM_COLOR;
+ cf.crTextColor = cr;
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ }
+ break;
+
+ case IDC_CHAT_BOLD:
+ case IDC_ITALICS:
+ case IDC_CHAT_UNDERLINE: {
+ CHARFORMAT2 cf;
+ cf.cbSize = sizeof(CHARFORMAT2);
+ cf.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE;
+ cf.dwEffects = 0;
+
+ if (LOWORD(wParam) == IDC_CHAT_BOLD && !IsWindowEnabled(GetDlgItem(hwndDlg, IDC_CHAT_BOLD)))
+ break;
+ if (LOWORD(wParam) == IDC_ITALICS && !IsWindowEnabled(GetDlgItem(hwndDlg, IDC_ITALICS)))
+ break;
+ if (LOWORD(wParam) == IDC_CHAT_UNDERLINE && !IsWindowEnabled(GetDlgItem(hwndDlg, IDC_CHAT_UNDERLINE)))
+ break;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_BOLD))
+ cf.dwEffects |= CFE_BOLD;
+ if (IsDlgButtonChecked(hwndDlg, IDC_ITALICS))
+ cf.dwEffects |= CFE_ITALIC;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_UNDERLINE))
+ cf.dwEffects |= CFE_UNDERLINE;
+
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ }
+ break;
+
+ case WM_KEYDOWN:
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ break;
+
+ case WM_MOVE:
+ break;
+
+ case WM_ERASEBKGND: {
+ HDC hdc = (HDC)wParam;
+ RECT rcClient, rcWindow, rc;
+ CSkinItem *item;
+ POINT pt;
+ UINT item_ids[3] = {ID_EXTBKUSERLIST, ID_EXTBKHISTORY, ID_EXTBKINPUTAREA};
+ UINT ctl_ids[3] = {IDC_LIST, IDC_CHAT_LOG, IDC_CHAT_MESSAGE};
+ int i;
+ bool fAero = M->isAero();
+ bool fInfoPanel = dat->Panel->isActive();
+ HANDLE hbp = 0;
+ HDC hdcMem = 0;
+ HBITMAP hbm, hbmOld;
+
+ GetClientRect(hwndDlg, &rcClient);
+ LONG cx = rcClient.right - rcClient.left;
+ LONG cy = rcClient.bottom - rcClient.top;
+
+ if (CMimAPI::m_haveBufferedPaint)
+ hbp = CSkin::InitiateBufferedPaint(hdc, rcClient, hdcMem);
+ else {
+ hdcMem = CreateCompatibleDC(hdc);
+ hbm = CSkin::CreateAeroCompatibleBitmap(rcClient, hdc);
+ hbmOld = (HBITMAP)SelectObject(hdcMem, hbm);
+ }
+
+ if (CSkin::m_skinEnabled && !fAero) {
+ CSkin::SkinDrawBG(hwndDlg, dat->pContainer->hwnd, dat->pContainer, &rcClient, hdcMem);
+ for (i=0; i < 3; i++) {
+ item = &SkinItems[item_ids[i]];
+ if (!item->IGNORED) {
+
+ GetWindowRect(GetDlgItem(hwndDlg, ctl_ids[i]), &rcWindow);
+ pt.x = rcWindow.left;
+ pt.y = rcWindow.top;
+ ScreenToClient(hwndDlg, &pt);
+ rc.left = pt.x - item->MARGIN_LEFT;
+ rc.top = pt.y - item->MARGIN_TOP;
+ rc.right = rc.left + item->MARGIN_RIGHT + (rcWindow.right - rcWindow.left) + item->MARGIN_LEFT;
+ rc.bottom = rc.top + item->MARGIN_BOTTOM + (rcWindow.bottom - rcWindow.top) + item->MARGIN_TOP;
+ CSkin::DrawItem(hdcMem, &rc, item);
+ }
+ }
+ }
+ else {
+ CSkin::FillBack(hdcMem, &rcClient);
+
+ if (M->isAero()) {
+ LONG temp = rcClient.bottom;
+ rcClient.bottom = dat->Panel->isActive() ? dat->Panel->getHeight() + 5 : 5;
+ FillRect(hdcMem, &rcClient, (HBRUSH)GetStockObject(BLACK_BRUSH));
+ rcClient.bottom = temp;
+ }
+ }
+
+ GetClientRect(hwndDlg, &rc);
+ dat->Panel->renderBG(hdcMem, rc, &SkinItems[ID_EXTBKINFOPANELBG], fAero);
+
+
+ dat->Panel->renderContent(hdcMem);
+
+ if (!CSkin::m_skinEnabled)
+ CSkin::RenderToolbarBG(dat, 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 (!dat->fLimitedUpdate)
+ SetAeroMargins(dat->pContainer);
+ return 1;
+ }
+
+ case WM_NCPAINT:
+ if (CSkin::m_skinEnabled)
+ return 0;
+ break;
+ case WM_PAINT: {
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(hwndDlg, &ps);
+ EndPaint(hwndDlg, &ps);
+ return 0;
+ }
+
+ case DM_SETINFOPANEL:
+ CInfoPanel::setPanelHandler(dat, wParam, lParam);
+ return 0;
+
+ case DM_INVALIDATEPANEL:
+ if (dat->Panel)
+ dat->Panel->Invalidate(true);
+ return 0;
+
+ case WM_RBUTTONUP: {
+ POINT pt;
+ int iSelection;
+ HMENU subMenu;
+ int isHandled;
+ int menuID = 0;
+
+ GetCursorPos(&pt);
+
+ if (dat->Panel->invokeConfigDialog(pt))
+ break;
+
+ subMenu = GetSubMenu(dat->pContainer->hMenuContext, 0);
+
+ MsgWindowUpdateMenu(dat, subMenu, MENU_TABCONTEXT);
+
+ iSelection = TrackPopupMenu(subMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL);
+ if (iSelection >= IDM_CONTAINERMENU) {
+ DBVARIANT dbv = {0};
+ char szIndex[10];
+ char *szKey = "TAB_ContainersW";
+ _snprintf(szIndex, 8, "%d", iSelection - IDM_CONTAINERMENU);
+ if (iSelection - IDM_CONTAINERMENU >= 0) {
+ if (!M->GetTString(NULL, szKey, szIndex, &dbv)) {
+ SendMessage(hwndDlg, DM_CONTAINERSELECTED, 0, (LPARAM)dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+
+ break;
+ }
+ isHandled = MsgWindowMenuHandler(dat, iSelection, MENU_TABCONTEXT);
+ break;
+ }
+
+ case WM_LBUTTONDBLCLK: {
+ if (LOWORD(lParam) < 30)
+ PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0);
+ break;
+ }
+
+ case WM_CLOSE:
+ if (wParam == 0 && lParam == 0) {
+ if (PluginConfig.m_EscapeCloses == 1) {
+ SendMessage(dat->pContainer->hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
+ return(TRUE);
+ } else if (PluginConfig.m_HideOnClose && PluginConfig.m_EscapeCloses == 2) {
+ ShowWindow(dat->pContainer->hwnd, SW_HIDE);
+ return(TRUE);
+ }
+ _dlgReturn(hwndDlg, TRUE);
+ }
+ SendMessage(hwndDlg, GC_CLOSEWINDOW, 0, 1);
+ break;
+
+ case DM_CONTAINERSELECTED: {
+ struct TContainerData *pNewContainer = 0;
+ TCHAR *szNewName = (TCHAR *)lParam;
+ if (!_tcscmp(szNewName, TranslateT("Default container")))
+ szNewName = CGlobals::m_default_container_name;
+ int iOldItems = TabCtrl_GetItemCount(hwndTab);
+ if (!_tcsncmp(dat->pContainer->szName, szNewName, CONTAINER_NAMELEN))
+ break;
+ pNewContainer = FindContainerByName(szNewName);
+ if (pNewContainer == NULL)
+ pNewContainer = CreateContainer(szNewName, FALSE, dat->hContact);
+ M->WriteTString(dat->hContact, SRMSGMOD_T, "containerW", szNewName);
+ PostMessage(PluginConfig.g_hwndHotkeyHandler, DM_DOCREATETAB_CHAT, (WPARAM)pNewContainer, (LPARAM)hwndDlg);
+ if (iOldItems > 1) // there were more than 1 tab, container is still valid
+ SendMessage(dat->pContainer->hwndActive, WM_SIZE, 0, 0);
+ SetForegroundWindow(pNewContainer->hwnd);
+ SetActiveWindow(pNewContainer->hwnd);
+ }
+ break;
+ // container API support functions
+
+ case DM_QUERYCONTAINER: {
+ struct TContainerData **pc = (struct TContainerData **) lParam;
+ if (pc)
+ *pc = dat->pContainer;
+ return 0;
+ }
+
+ case DM_QUERYHCONTACT: {
+ HANDLE *phContact = (HANDLE *) lParam;
+ if (phContact)
+ *phContact = dat->hContact;
+ return 0;
+ }
+
+ case GC_CLOSEWINDOW: {
+ int iTabs, i;
+ TCITEM item = {0};
+ RECT rc;
+ struct TContainerData *pContainer = dat->pContainer;
+ BOOL bForced = (lParam == 2);
+
+ iTabs = TabCtrl_GetItemCount(hwndTab);
+ if (iTabs == 1) {
+ if (/*!bForced && */CMimAPI::m_shutDown == 0) {
+ //DestroyWindow(GetParent(GetParent(hwndDlg)));
+ //PostMessage(hwndDlg, WM_CLOSE, 0, 1);
+ SendMessage(GetParent(GetParent(hwndDlg)), WM_CLOSE, 0, 1);
+ return 1;
+ }
+ }
+
+ dat->pContainer->iChilds--;
+ i = GetTabIndexFromHWND(hwndTab, hwndDlg);
+
+ /*
+ * after closing a tab, we need to activate the tab to the left side of
+ * the previously open tab.
+ * normally, this tab has the same index after the deletion of the formerly active tab
+ * unless, of course, we closed the last (rightmost) tab.
+ */
+ if (!dat->pContainer->bDontSmartClose && iTabs > 1 && !bForced) {
+ if (i == iTabs - 1)
+ i--;
+ else
+ i++;
+ TabCtrl_SetCurSel(hwndTab, i);
+ item.mask = TCIF_PARAM;
+ TabCtrl_GetItem(hwndTab, i, &item); // retrieve dialog hwnd for the now active tab...
+
+ dat->pContainer->hwndActive = (HWND) item.lParam;
+ SendMessage(dat->pContainer->hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)&rc);
+ SetWindowPos(dat->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(dat->pContainer->hwndActive);
+ SetFocus(dat->pContainer->hwndActive);
+ SendMessage(dat->pContainer->hwnd, WM_SIZE, 0, 0);
+ }
+ //SM_SetTabbedWindowHwnd(0, 0);
+ //DestroyWindow(hwndDlg);
+ if (iTabs == 1)
+ SendMessage(GetParent(GetParent(hwndDlg)), WM_CLOSE, 0, 1);
+ else {
+ PostMessage(pContainer->hwnd, WM_SIZE, 0, 0);
+ DestroyWindow(hwndDlg);
+ }
+ return 0;
+ }
+
+ case DM_SETLOCALE:
+ if (dat->dwFlags & MWF_WASBACKGROUNDCREATE)
+ break;
+ if (dat->pContainer->hwndActive == hwndDlg && PluginConfig.m_AutoLocaleSupport && dat->hContact != 0 && dat->pContainer->hwnd == GetForegroundWindow() && dat->pContainer->hwnd == GetActiveWindow()) {
+ if (lParam)
+ dat->hkl = (HKL)lParam;
+
+ if (dat->hkl)
+ ActivateKeyboardLayout(dat->hkl, 0);
+ }
+ return 0;
+
+ case DM_SAVESIZE: {
+ RECT rcClient;
+
+ if (dat->dwFlags & MWF_NEEDCHECKSIZE)
+ lParam = 0;
+
+ dat->dwFlags &= ~MWF_NEEDCHECKSIZE;
+ if (dat->dwFlags & MWF_WASBACKGROUNDCREATE)
+ dat->dwFlags &= ~MWF_INITMODE;
+
+ SendMessage(dat->pContainer->hwnd, DM_QUERYCLIENTAREA, 0, (LPARAM)&rcClient);
+ MoveWindow(hwndDlg, rcClient.left, rcClient.top, (rcClient.right - rcClient.left), (rcClient.bottom - rcClient.top), TRUE);
+ if (dat->dwFlags & MWF_WASBACKGROUNDCREATE) {
+ POINT pt = {0};;
+
+ dat->dwFlags &= ~MWF_WASBACKGROUNDCREATE;
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_SETSCROLLPOS, 0, (LPARAM)&pt);
+ if (PluginConfig.m_AutoLocaleSupport) {
+ if (dat->hkl == 0)
+ DM_LoadLocale(dat);
+ else
+ PostMessage(hwndDlg, DM_SETLOCALE, 0, 0);
+ }
+ } else {
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ if (lParam == 0)
+ PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 1, 1);
+ }
+ return 0;
+ }
+
+ case DM_GETWINDOWSTATE: {
+ UINT state = 0;
+
+ state |= MSG_WINDOW_STATE_EXISTS;
+ if (IsWindowVisible(hwndDlg))
+ state |= MSG_WINDOW_STATE_VISIBLE;
+ if (GetForegroundWindow() == dat->pContainer->hwnd)
+ state |= MSG_WINDOW_STATE_FOCUS;
+ if (IsIconic(dat->pContainer->hwnd))
+ state |= MSG_WINDOW_STATE_ICONIC;
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, state);
+ return TRUE;
+ }
+
+ case DM_ADDDIVIDER:
+ if (!(dat->dwFlags & MWF_DIVIDERSET) && g_Settings.UseDividers) {
+ if (GetWindowTextLengthA(GetDlgItem(hwndDlg, IDC_CHAT_LOG)) > 0) {
+ dat->dwFlags |= MWF_DIVIDERWANTED;
+ dat->dwFlags |= MWF_DIVIDERSET;
+ }
+ }
+ return 0;
+
+ case DM_CHECKSIZE:
+ dat->dwFlags |= MWF_NEEDCHECKSIZE;
+ return 0;
+
+ case DM_REFRESHTABINDEX:
+ dat->iTabID = GetTabIndexFromHWND(GetParent(hwndDlg), hwndDlg);
+ return 0;
+
+ case DM_STATUSBARCHANGED:
+ UpdateStatusBar(dat);
+ break;
+
+ //mad: bb-api
+ case DM_BBNEEDUPDATE:{
+ if (lParam)
+ CB_ChangeButton(hwndDlg,dat,(CustomButtonData*)lParam);
+ else
+ BB_InitDlgButtons(dat);
+
+ BB_SetButtonsPos(dat);
+ }break;
+
+ case DM_CBDESTROY:{
+ if (lParam)
+ CB_DestroyButton(hwndDlg,dat,(DWORD)wParam,(DWORD)lParam);
+ else
+ CB_DestroyAllButtons(hwndDlg,dat);
+ }break;
+ //
+
+ case DM_CONFIGURETOOLBAR:
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ break;
+
+ case DM_SMILEYOPTIONSCHANGED:
+ ConfigureSmileyButton(dat);
+ SendMessage(hwndDlg, GC_REDRAWLOG, 0, 1);
+ break;
+
+ case EM_THEMECHANGED:
+ DM_FreeTheme(dat);
+ return DM_ThemeChanged(dat);
+
+ case WM_DWMCOMPOSITIONCHANGED:
+ BB_RefreshTheme(dat);
+ memset((void *)&dat->pContainer->mOld, -1000, sizeof(MARGINS));
+ CProxyWindow::verify(dat);
+ break;
+
+ case DM_ACTIVATEME:
+ ActivateExistingTab(dat->pContainer, hwndDlg);
+ return 0;
+
+ case DM_ACTIVATETOOLTIP: {
+ if (IsIconic(dat->pContainer->hwnd) || dat->pContainer->hwndActive != hwndDlg)
+ break;
+
+ dat->Panel->showTip(wParam, lParam);
+ break;
+ }
+
+ case DM_SAVEMESSAGELOG:
+ DM_SaveLogAsRTF(dat);
+ return 0;
+
+ case DM_CHECKAUTOHIDE:
+ DM_CheckAutoHide(dat, wParam, lParam);
+ return 0;
+
+ case WM_NCDESTROY:
+ if (dat) {
+ memset((void *)&dat->pContainer->mOld, -1000, sizeof(MARGINS));
+ PostMessage(dat->pContainer->hwnd, WM_SIZE, 0, 1);
+ delete dat->Panel;
+ if (dat->pContainer->dwFlags & CNT_SIDEBAR)
+ dat->pContainer->SideBar->removeSession(dat);
+ free(dat);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ }
+ break;
+
+ case WM_DESTROY: {
+ int i;
+
+ if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->hContact, (LPARAM)szChatIconString);
+ si->wState &= ~STATE_TALK;
+ si->hWnd = NULL;
+ si->dat = 0;
+ si->pContainer = 0;
+
+ //SetWindowLongPtr(hwndDlg,GWLP_USERDATA,0);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTERX), GWLP_WNDPROC, (LONG_PTR)OldSplitterProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTERY), GWLP_WNDPROC, (LONG_PTR)OldSplitterProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LIST), GWLP_WNDPROC, (LONG_PTR)OldNicklistProc);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_UNSUBCLASSED, 0, 0);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), GWLP_WNDPROC, (LONG_PTR)OldMessageProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHAT_LOG), GWLP_WNDPROC, (LONG_PTR)OldLogProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_FILTER), GWLP_WNDPROC, (LONG_PTR)OldFilterButtonProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_COLOR), GWLP_WNDPROC, (LONG_PTR)OldFilterButtonProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_BKGCOLOR), GWLP_WNDPROC, (LONG_PTR)OldFilterButtonProc);
+
+ TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSING, 0);
+
+ if (!dat->fIsAutosizingInput)
+ DBWriteContactSettingWord(NULL, "Chat", "SplitterX", (WORD)g_Settings.iSplitterX);
+
+ if (dat->pContainer->settings->fPrivate && !IsAutoSplitEnabled(dat))
+ DBWriteContactSettingWord(NULL, "Chat", "splitY", (WORD)g_Settings.iSplitterY);
+
+ DM_FreeTheme(dat);
+
+ UpdateTrayMenuState(dat, FALSE); // remove me from the tray menu (if still there)
+ if (PluginConfig.g_hMenuTrayUnread)
+ DeleteMenu(PluginConfig.g_hMenuTrayUnread, (UINT_PTR)dat->hContact, MF_BYCOMMAND);
+
+ if (dat->hSmileyIcon)
+ DestroyIcon(dat->hSmileyIcon);
+
+ if (dat->hwndTip)
+ DestroyWindow(dat->hwndTip);
+
+ if (hCurHyperlinkHand)
+ DestroyCursor(hCurHyperlinkHand);
+
+ i = GetTabIndexFromHWND(hwndTab, hwndDlg);
+ if (i >= 0) {
+ SendMessage(hwndTab, WM_USER + 100, 0, 0); // clean up tooltip
+ TabCtrl_DeleteItem(hwndTab, i);
+ BroadCastContainer(dat->pContainer, DM_REFRESHTABINDEX, 0, 0);
+ dat->iTabID = -1;
+ }
+ if (dat->pWnd) {
+ delete dat->pWnd;
+ dat->pWnd = 0;
+ }
+ //MAD
+ M->RemoveWindow(hwndDlg);
+
+ TABSRMM_FireEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSE, 0);
+ break;
+ }
+ }
+ return(FALSE);
+}
diff --git a/plugins/TabSRMM/src/commonheaders.h b/plugins/TabSRMM/src/commonheaders.h
index 28a90ca0b9..83ccf13448 100644
--- a/plugins/TabSRMM/src/commonheaders.h
+++ b/plugins/TabSRMM/src/commonheaders.h
@@ -174,7 +174,7 @@
#include <vector>
#include <assert.h>
-#include "../include/resource.h"
+#include "include/resource.h"
/* State of icon with such flag will not be saved, and you must set it manually */
#define MBF_OWNERSTATE 0x04
@@ -211,7 +211,7 @@
#define safe_sizeof(a) (unsigned int)((sizeof((a)) / sizeof((a)[0])))
-#include "../include/version.h"
+#include "include/version.h"
#include "m_ieview.h"
#include "m_popup2.h"
#include "m_metacontacts.h"
@@ -225,31 +225,31 @@
#include "m_historyevents.h"
#include "m_smileyadd.h"
-#include "../include/m_cln_skinedit.h"
-#include "../include/buttonbar.h"
-#include "../include/msgs.h"
-#include "../include/msgdlgutils.h"
-#include "../include/typingnotify.h"
-#include "../include/generic_msghandlers.h"
-#include "../include/nen.h"
+#include "include/m_cln_skinedit.h"
+#include "include/buttonbar.h"
+#include "include/msgs.h"
+#include "include/msgdlgutils.h"
+#include "include/typingnotify.h"
+#include "include/generic_msghandlers.h"
+#include "include/nen.h"
extern NEN_OPTIONS nen_options;
-#include "../include/functions.h"
-#include "../chat/chat.h"
-
-#include "../include/contactcache.h"
-#include "../include/translator.h"
-#include "../include/themes.h"
-#include "../include/globals.h"
-#include "../include/mim.h"
-#include "../include/sendqueue.h"
-#include "../include/taskbar.h"
-#include "../include/controls.h"
-#include "../include/infopanel.h"
-#include "../include/sidebar.h"
-#include "../include/utils.h"
-#include "../include/sendlater.h"
-
-#include "../chat/muchighlight.h"
+#include "include/functions.h"
+#include "chat/chat.h"
+
+#include "include/contactcache.h"
+#include "include/translator.h"
+#include "include/themes.h"
+#include "include/globals.h"
+#include "include/mim.h"
+#include "include/sendqueue.h"
+#include "include/taskbar.h"
+#include "include/controls.h"
+#include "include/infopanel.h"
+#include "include/sidebar.h"
+#include "include/utils.h"
+#include "include/sendlater.h"
+
+#include "chat/muchighlight.h"
#if !defined(_WIN64) && !defined(_USE_32BIT_TIME_T)
#define _USE_32BIT_TIME_T
diff --git a/plugins/TabSRMM/src/include/ImageDataObject.h b/plugins/TabSRMM/src/include/ImageDataObject.h
new file mode 100644
index 0000000000..0e2c112827
--- /dev/null
+++ b/plugins/TabSRMM/src/include/ImageDataObject.h
@@ -0,0 +1,136 @@
+/*
+Miranda SmileyAdd Plugin
+Copyright (C) 2004 Rein-Peter de Boer (peacow)
+
+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.
+*/
+
+//code taken partly from public example on the internet, source unknown.
+
+//make sure <richedit.h> is include before this file
+#include <richedit.h>
+#include <richole.h>
+#include <ole2.h>
+
+class CImageDataObject : IDataObject
+{
+public:
+ // returns true on success, false on failure
+ static bool InsertBitmap(IRichEditOle* pRichEditOle, HBITMAP hBitmap);
+ // returns true on success, false on failure
+ //static bool InsertIcon(IRichEditOle* pRichEditOle, HICON hIcon,
+ //COLORREF backgroundColor, int sizeX = 0, int sizeY = 0);
+
+private:
+ ULONG m_ulRefCnt;
+ BOOL m_bRelease;
+
+ STGMEDIUM m_stgmed;
+ FORMATETC m_format;
+
+public:
+ CImageDataObject() : m_ulRefCnt(0)
+ {
+ m_bRelease = FALSE;
+ }
+
+ ~CImageDataObject()
+ {
+ if (m_bRelease)
+ ::ReleaseStgMedium(&m_stgmed);
+ }
+
+ // IUnknown interface
+ STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
+ {
+ if (iid == IID_IUnknown || iid == IID_IDataObject)
+ {
+ *ppvObject = this;
+ AddRef();
+ return S_OK;
+ }
+ else
+ return E_NOINTERFACE;
+ }
+
+ STDMETHOD_(ULONG, AddRef)(void)
+ {
+ m_ulRefCnt++;
+ return m_ulRefCnt;
+ }
+
+ STDMETHOD_(ULONG, Release)(void)
+ {
+ m_ulRefCnt--;
+ if (m_ulRefCnt == 0)
+ delete this;
+ return m_ulRefCnt;
+ }
+
+ // IDataObject Interface
+ STDMETHOD(GetData)(FORMATETC *pformatetcIn, STGMEDIUM *pmedium) {
+ HANDLE hDst;
+ hDst = ::OleDuplicateData(m_stgmed.hBitmap, CF_BITMAP, 0);
+ if (hDst == NULL)
+ return E_HANDLE;
+
+ pmedium->tymed = TYMED_GDI;
+ pmedium->hBitmap = (HBITMAP)hDst;
+ pmedium->pUnkForRelease = NULL;
+
+ return S_OK;
+ }
+
+ STDMETHOD(GetDataHere)(FORMATETC* pformatetc, STGMEDIUM* pmedium ) {
+ return E_NOTIMPL;
+ }
+
+ STDMETHOD(QueryGetData)(FORMATETC* pformatetc ) {
+ return E_NOTIMPL;
+ }
+
+ STDMETHOD(GetCanonicalFormatEtc)(FORMATETC* pformatectIn ,FORMATETC* pformatetcOut ) {
+ return E_NOTIMPL;
+ }
+
+ STDMETHOD(SetData)(FORMATETC* pformatetc , STGMEDIUM* pmedium , BOOL fRelease ) {
+ m_format = *pformatetc;
+ m_stgmed = *pmedium;
+
+ return S_OK;
+ }
+
+ STDMETHOD(EnumFormatEtc)(DWORD dwDirection , IEnumFORMATETC** ppenumFormatEtc ) {
+ return E_NOTIMPL;
+ }
+
+ STDMETHOD(DAdvise)(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink,
+ DWORD *pdwConnection) {
+ return E_NOTIMPL;
+ }
+
+ STDMETHOD(DUnadvise)(DWORD dwConnection) {
+ return E_NOTIMPL;
+ }
+
+ STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppenumAdvise) {
+ return E_NOTIMPL;
+ }
+
+ // Other
+ void SetBitmap(HBITMAP hBitmap);
+ IOleObject *GetOleObject(IOleClientSite *pOleClientSite, IStorage *pStorage);
+};
+
diff --git a/plugins/TabSRMM/src/include/buttonbar.h b/plugins/TabSRMM/src/include/buttonbar.h
new file mode 100644
index 0000000000..9be67e965b
--- /dev/null
+++ b/plugins/TabSRMM/src/include/buttonbar.h
@@ -0,0 +1,54 @@
+#ifndef _BUTTONSBAR_H
+#define _BUTTONSBAR_H
+
+#define MIN_CBUTTONID 4000
+#define MAX_CBUTTONID 5000
+
+#define BBSF_IMBUTTON (1<<0)
+#define BBSF_CHATBUTTON (1<<1)
+#define BBSF_CANBEHIDDEN (1<<2)
+#define BBSF_NTBSWAPED (1<<3)
+#define BBSF_NTBDESTRUCT (1<<4)
+
+typedef struct _tagCustomButtonData
+ {
+ DWORD dwButtonOrigID; // id of button used while button creation and to store button info in DB
+ char * pszModuleName; //module name without spaces and underline symbols (e.g. "tabsrmm")
+
+ DWORD dwButtonCID;
+ DWORD dwArrowCID; //only use with BBBF_ISARROWBUTTON flag
+
+ TCHAR * ptszTooltip; //button's tooltip
+
+ DWORD dwPosition; // default order pos of button, counted from window edge (left or right)
+ int iButtonWidth; //must be 22 for regular button and 33 for button with arrow
+ HANDLE hIcon; //Handle to icolib registred icon
+ BOOL bIMButton,bChatButton;
+ BOOL bCanBeHidden,bHidden,bAutoHidden,bDummy,bDisabled,bPushButton;
+ BOOL bLSided,bRSided;
+ BYTE opFlags;
+ }CustomButtonData;
+
+static INT_PTR CB_ModifyButton(WPARAM wParam, LPARAM lParam);
+static INT_PTR CB_RemoveButton(WPARAM wParam, LPARAM lParam);
+static INT_PTR CB_AddButton(WPARAM wParam, LPARAM lParam);
+static INT_PTR CB_GetButtonState(WPARAM wParam, LPARAM lParam);
+static INT_PTR CB_SetButtonState(WPARAM wParam, LPARAM lParam);
+static void CB_GetButtonSettings(HANDLE hContact,CustomButtonData *cbd);
+
+void CB_WriteButtonSettings(HANDLE hContact,CustomButtonData *cbd);
+int sstSortButtons(const void * vmtbi1, const void * vmtbi2);
+
+void CB_DeInitCustomButtons();
+void CB_InitCustomButtons();
+void CB_InitDefaultButtons();
+void CB_ReInitCustomButtons();
+
+/* MinGW doesn't like this struct declatations below */
+void BB_UpdateIcons(HWND hdlg,struct TWindowData *dat);
+void BB_RefreshTheme(const TWindowData *dat);
+void CB_DestroyAllButtons(HWND hwndDlg,struct TWindowData *dat);
+void CB_DestroyButton(HWND hwndDlg,struct TWindowData *dat,DWORD dwButtonCID,DWORD dwFlags);
+void CB_ChangeButton(HWND hwndDlg,struct TWindowData *dat,CustomButtonData* cbd);
+
+#endif
diff --git a/plugins/TabSRMM/src/include/contactcache.h b/plugins/TabSRMM/src/include/contactcache.h
new file mode 100644
index 0000000000..309e95131d
--- /dev/null
+++ b/plugins/TabSRMM/src/include/contactcache.h
@@ -0,0 +1,167 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: contactcache.h 12846 2010-10-01 03:26:02Z silvercircle $
+ *
+ * the contact cache
+ *
+ */
+
+#ifndef __CONTACTCACHE_H
+#define __CONTACTCACHE_H
+
+#define C_INVALID_PROTO "<proto error>"
+#define C_INVALID_ACCOUNT _T("<account error>")
+#define C_INVALID_PROTO_T _T("<proto error>")
+#define HISTORY_INITIAL_ALLOCSIZE 300
+
+
+struct TInputHistory {
+ TCHAR* szText;
+ size_t lLen;
+};
+
+struct TSessionStats {
+ enum {
+ BYTES_RECEIVED = 1,
+ BYTES_SENT = 2,
+ FAILURE = 3,
+ UPDATE_WITH_LAST_RCV= 4,
+ SET_LAST_RCV = 5,
+ INIT_TIMER = 6,
+ };
+
+ time_t started;
+ unsigned int iSent, iReceived, iSentBytes, iReceivedBytes;
+ unsigned int messageCount;
+ unsigned int iFailures;
+ unsigned int lastReceivedChars;
+ BOOL bWritten;
+};
+
+class CContactCache {
+public:
+
+ CContactCache () {}
+ CContactCache (const HANDLE hContact);
+ ~CContactCache ()
+ {
+ releaseAlloced();
+ }
+ void inc () { m_accessCount++; }
+ const bool isValid () const { return(m_Valid); }
+ const WORD getStatus () const { return(m_wStatus); }
+ const WORD getMetaStatus () const { return(m_wMetaStatus); }
+ const WORD getActiveStatus () const { return(m_isMeta ? m_wMetaStatus : m_wStatus); }
+ const WORD getOldStatus () const { return(m_wOldStatus); }
+ const TCHAR* getNick () const { return(m_szNick); }
+ const HANDLE getContact () const { return(m_hContact); }
+ const HANDLE getActiveContact () const { return(m_isMeta ? (m_hSubContact ? m_hSubContact : m_hContact) : m_hContact); }
+ const DWORD getIdleTS () const { return(m_idleTS); }
+ const char* getProto () const { return(m_szProto); }
+ const TCHAR* getProtoT () const { return(m_tszProto); }
+ const char* getMetaProto () const { return(m_szMetaProto ? m_szMetaProto : C_INVALID_PROTO); }
+ const TCHAR* getMetaProtoT () const { return(m_szMetaProto ? m_tszMetaProto : C_INVALID_PROTO_T); }
+ const char* getActiveProto () const { return(m_isMeta ? (m_szMetaProto ? m_szMetaProto : m_szProto) : m_szProto); }
+ const TCHAR* getActiveProtoT () const { return(m_isMeta ? (m_szMetaProto ? m_tszMetaProto : m_tszProto) : m_tszProto); }
+ bool isMeta () const { return(m_isMeta); }
+ bool isSubContact () const { return(m_isSubcontact); }
+ bool isFavorite () const { return(m_isFavorite); }
+ bool isRecent () const { return(m_isRecent); }
+ const TCHAR* getRealAccount () const { return(m_szAccount ? m_szAccount : C_INVALID_ACCOUNT); }
+ const TCHAR* getUIN () const { return(m_szUIN); }
+ const TCHAR* getStatusMsg () const { return(m_szStatusMsg); }
+ const TCHAR* getXStatusMsg () const { return(m_xStatusMsg); }
+ const TCHAR* getListeningInfo () const { return(m_ListeningInfo); }
+ BYTE getXStatusId () const { return(m_xStatus); }
+ const HWND getWindowData (TWindowData*& dat) const { dat = m_dat; return(m_hwnd); }
+ const HWND getHwnd () const { return(m_hwnd); }
+ int getMaxMessageLength ();
+
+ TWindowData* getDat () const { return(m_dat); }
+
+ void updateStats (int iType, size_t value = 0);
+ const DWORD getSessionStart () const { return(m_stats->started); }
+ const int getSessionMsgCount () const { return((int)m_stats->messageCount) ; }
+ void updateState ();
+ bool updateStatus ();
+ bool updateNick ();
+ void updateMeta (bool fForce = false);
+ bool updateUIN ();
+ void updateStatusMsg (const char *szKey = 0);
+ void setWindowData (const HWND hwnd = 0, TWindowData *dat = 0);
+ void resetMeta ();
+ void closeWindow ();
+ void deletedHandler ();
+ void updateFavorite ();
+ TCHAR* getNormalizedStatusMsg (const TCHAR *src, bool fStripAll = false);
+ HICON getIcon (int& iSize) const;
+
+ /*
+ * input history
+ */
+ void saveHistory (WPARAM wParam, LPARAM lParam);
+ void inputHistoryEvent (WPARAM wParam);
+
+ HANDLE m_hContact;
+ CContactCache* m_next;
+
+ static CContactCache* m_cCache;
+ static CContactCache* getContactCache(const HANDLE hContact);
+
+private:
+ void allocStats ();
+ void initPhaseTwo ();
+ void allocHistory ();
+ void releaseAlloced ();
+
+private:
+ size_t m_accessCount;
+ HANDLE m_hSubContact;
+ WORD m_wStatus, m_wMetaStatus;
+ WORD m_wOldStatus;
+ char* m_szProto, *m_szMetaProto;
+ TCHAR* m_tszProto, m_tszMetaProto[40];
+ TCHAR* m_szAccount;
+ TCHAR m_szNick[80], m_szUIN[80];
+ TCHAR* m_szStatusMsg, *m_xStatusMsg, *m_ListeningInfo;
+ BYTE m_xStatus;
+ DWORD m_idleTS;
+ bool m_isMeta, m_isSubcontact;
+ bool m_Valid;
+ bool m_isFavorite;
+ bool m_isRecent;
+ HWND m_hwnd;
+ int m_nMax;
+ int m_iHistoryCurrent, m_iHistoryTop, m_iHistorySize;
+ TWindowData* m_dat;
+ TSessionStats* m_stats;
+ TInputHistory* m_history;
+};
+
+#endif /* __CONTACTCACHE_H */
diff --git a/plugins/TabSRMM/src/include/controls.h b/plugins/TabSRMM/src/include/controls.h
new file mode 100644
index 0000000000..2f6e236ca3
--- /dev/null
+++ b/plugins/TabSRMM/src/include/controls.h
@@ -0,0 +1,136 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: controls.h 11635 2010-04-26 07:17:39Z silvercircle $
+ *
+ * menu bar and status bar classes for the container window.
+ *
+ */
+
+#ifndef __CONTROLS_H
+#define __CONTROLS_H
+
+extern LONG_PTR CALLBACK StatusBarSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+class CMenuBar
+{
+public:
+ enum {
+ NR_BUTTONS = 8
+ };
+
+ CMenuBar(HWND hwndParent, const TContainerData *pContainer);
+ ~CMenuBar();
+
+ const RECT& TSAPI getClientRect();
+ void TSAPI Resize(WORD wWidth, WORD wHeight, BOOL redraw) const
+ {
+ ::SetWindowPos(m_hwndToolbar, 0, 4, 0, wWidth, m_size_y, SWP_NOZORDER | SWP_NOACTIVATE |
+ SWP_NOCOPYBITS|SWP_NOREDRAW);
+
+ }
+ LONG TSAPI getHeight() const;
+ void TSAPI Show(int showCmd) const
+ {
+ ::ShowWindow(m_hwndToolbar, showCmd);
+ }
+ LONG_PTR TSAPI Handle(const NMTOOLBAR *nmtb);
+ void TSAPI Cancel();
+ LONG_PTR TSAPI processMsg(const UINT msg, const WPARAM wParam, const LPARAM lParam);
+ bool TSAPI isContactMenu() const { return(m_isContactMenu); }
+ bool TSAPI isMainMenu() const { return(m_isMainMenu); }
+ void TSAPI configureMenu(void) const;
+ void TSAPI setActive(HMENU hMenu)
+ {
+ m_activeSubMenu = hMenu;
+ }
+ void setAero(bool fState) { m_isAero = fState; }
+ const bool getAero(void) const { return(m_isAero); }
+
+ const LRESULT processAccelerator(TCHAR a, UINT& ctlId) const
+ {
+ UINT _ctlId;
+
+ const LRESULT result = ::SendMessage(m_hwndToolbar, TB_MAPACCELERATOR, (WPARAM)a, (LPARAM)&_ctlId);
+ ctlId = _ctlId;
+
+ return(result);
+ }
+ void TSAPI autoShow(const int showcmd = 1);
+
+ const int idToIndex(const int id) const
+ {
+ for (int i = 0; i < NR_BUTTONS; i++) {
+ if (m_TbButtons[i].idCommand == id )
+ return(i);
+ }
+ return(-1);
+ }
+public:
+ static HHOOK m_hHook;
+ static HBITMAP m_MimIcon;
+
+private:
+ HWND m_hwndToolbar;
+ RECT m_rcClient;
+ TContainerData *m_pContainer;
+ HMENU m_activeMenu, m_activeSubMenu;;
+ int m_activeID;
+ bool m_fTracking;
+ bool m_isContactMenu;
+ bool m_isMainMenu;
+ bool m_isAero;
+ bool m_mustAutoHide;
+ LONG m_size_y;
+ WNDPROC m_oldWndProc;
+ /*
+ * for custom drawing
+ */
+ RECT m_rcItem;
+ HDC m_hdcDraw;
+ HBITMAP m_hbmDraw, m_hbmOld;
+ HANDLE m_hTheme;
+ HFONT m_hOldFont;
+
+ static TBBUTTON m_TbButtons[8];
+ static bool m_buttonsInit;
+ static CMenuBar *m_Owner;
+ static int m_MimIconRefCount;
+private:
+ LONG_PTR TSAPI customDrawWorker(NMCUSTOMDRAW *nm);
+ void TSAPI updateState(const HMENU hMenu) const;
+ void TSAPI invoke(const int id);
+ void TSAPI cancel(const int id);
+ void TSAPI obtainHook();
+ void TSAPI releaseHook();
+
+ static LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); // subclassing for the toolbar control
+ static LRESULT CALLBACK MessageHook(int nCode, WPARAM wParam, LPARAM lParam); // message hook (only active when modal menus are active)
+};
+
+#endif /* __CONTROLS_H */
diff --git a/plugins/TabSRMM/src/include/functions.h b/plugins/TabSRMM/src/include/functions.h
new file mode 100644
index 0000000000..49ae0f79ab
--- /dev/null
+++ b/plugins/TabSRMM/src/include/functions.h
@@ -0,0 +1,199 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: functions.h 11636 2010-04-27 22:08:16Z silvercircle $
+ *
+ * Global function prototypes
+ *
+ */
+
+#ifndef _TABSRMM_FUNCTIONS_H
+#define _TABSRMM_FUNCTIONS_H
+
+int Chat_PreShutdown ();
+int Chat_ModulesLoaded (WPARAM wp, LPARAM lp);
+int AvatarChanged (WPARAM wParam, LPARAM lParam);
+int MyAvatarChanged (WPARAM wParam, LPARAM lParam);
+int IcoLibIconsChanged (WPARAM wParam, LPARAM lParam);
+int FontServiceFontsChanged (WPARAM wParam, LPARAM lParam);
+int SmileyAddOptionsChanged (WPARAM wParam, LPARAM lParam);
+int IEViewOptionsChanged (WPARAM wParam, LPARAM lParam);
+void RegisterFontServiceFonts ();
+int ModPlus_PreShutdown (WPARAM wparam, LPARAM lparam);
+int ModPlus_Init (WPARAM wparam, LPARAM lparam);
+LONG_PTR CALLBACK HotkeyHandlerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+/*
+ * nen / event popup stuff
+ */
+
+int TSAPI NEN_ReadOptions (NEN_OPTIONS *options);
+int TSAPI NEN_WriteOptions (NEN_OPTIONS *options);
+int TSAPI UpdateTrayMenu (const TWindowData *dat, WORD wStatus, const char *szProto,
+ const TCHAR *szStatus, HANDLE hContact, DWORD fromEvent);
+static int TSAPI PopupPreview (NEN_OPTIONS *pluginOptions);
+void TSAPI DeletePopupsForContact (HANDLE hContact, DWORD dwMask);
+
+/*
+ * tray stuff
+ */
+
+void TSAPI CreateSystrayIcon (int create);
+void TSAPI FlashTrayIcon (HICON hIcon);
+void TSAPI UpdateTrayMenuState (TWindowData *dat, BOOL bForced);
+void TSAPI LoadFavoritesAndRecent ();
+void TSAPI AddContactToFavorites (HANDLE hContact, const TCHAR *szNickname, const char *szProto, TCHAR *szStatus,
+ WORD wStatus, HICON hIcon, BOOL mode, HMENU hMenu);
+void TSAPI CreateTrayMenus (int mode);
+void TSAPI HandleMenuEntryFromhContact (int iSelection);
+
+/*
+ * gneric msgwindow functions (creation, container management etc.)
+ */
+
+BOOL TSAPI IsUtfSendAvailable (HANDLE hContact);
+HWND TSAPI CreateNewTabForContact (TContainerData *pContainer, HANDLE hContact, int isSend,
+ const char *pszInitialText, BOOL bActivateTAb, BOOL bPopupContainer, BOOL bWantPopup, HANDLE hdbEvent);
+int TSAPI ActivateTabFromHWND (HWND hwndTab, HWND hwnd);
+void TSAPI FlashContainer (TContainerData *pContainer, int iMode, int iNum);
+void TSAPI CreateImageList (BOOL bInitial);
+TContainerData* TSAPI FindMatchingContainer(const TCHAR *szName, HANDLE hContact);
+TContainerData* TSAPI CreateContainer (const TCHAR *name, int iTemp, HANDLE hContactFrom);
+TContainerData* TSAPI FindContainerByName (const TCHAR *name);
+int TSAPI GetTabIndexFromHWND (HWND hwndTab, HWND hwnd);
+int TSAPI GetTabItemFromMouse (HWND hwndTab, POINT *pt);
+int TSAPI ActivateTabFromHWND (HWND hwndTab, HWND hwnd);
+void TSAPI AdjustTabClientRect (TContainerData *pContainer, RECT *rc);
+void TSAPI ReflashContainer (TContainerData *pContainer);
+HMENU TSAPI BuildMCProtocolMenu (HWND hwndDlg);
+
+TContainerData* TSAPI AppendToContainerList(TContainerData *pContainer);
+TContainerData* TSAPI RemoveContainerFromList(TContainerData *pContainer);
+
+void TSAPI DeleteContainer (int iIndex);
+void TSAPI RenameContainer (int iIndex, const TCHAR *newName);
+int TSAPI GetContainerNameForContact (HANDLE hContact, TCHAR *szName, int iNameLen);
+HMENU TSAPI BuildContainerMenu ();
+void TSAPI BuildCodePageList ();
+void TSAPI PreTranslateDates ();
+void TSAPI ApplyContainerSetting (TContainerData *pContainer, DWORD flags, UINT mode, bool fForceResize);
+void TSAPI BroadCastContainer (const TContainerData *pContainer, UINT message, WPARAM wParam, LPARAM lParam, BYTE iType = 0);
+void TSAPI GetDefaultContainerTitleFormat();
+INT_PTR MessageWindowOpened(WPARAM wParam, LPARAM lParam);
+void TSAPI SetAeroMargins (TContainerData *pContainer);
+int TABSRMM_FireEvent (HANDLE hContact, HWND hwnd, unsigned int type, unsigned int subType);
+
+LRESULT CALLBACK IEViewSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+LRESULT CALLBACK HPPKFSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+/*
+ * skinning engine
+ */
+void TSAPI DrawAlpha (HDC hdcwnd, PRECT rc, DWORD basecolor, int alpha, DWORD basecolor2,
+ BYTE transparent, BYTE FLG_GRADIENT, BYTE FLG_CORNER, DWORD BORDERSTYLE, CImageItem *imageItem);
+// the cached message log icons
+
+void TSAPI CacheMsgLogIcons ();
+void TSAPI CacheLogFonts ();
+void TSAPI InitAPI ();
+void TSAPI LoadIconTheme ();
+int TSAPI LoadFromIconLib ();
+int TSAPI SetupIconLibConfig ();
+void TSAPI RTF_CTableInit ();
+
+INT_PTR CALLBACK DlgProcMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+int TSAPI InitOptions (void);
+INT_PTR CALLBACK DlgProcContainer (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+int TSAPI DbEventIsShown (TWindowData *dat, DBEVENTINFO *dbei);
+void TSAPI StreamInEvents (HWND hwndDlg,HANDLE hDbEventFirst,int count,int fAppend, DBEVENTINFO *dbei_s);
+void TSAPI LoadLogfont (int i,LOGFONTA *lf,COLORREF *colour, char *szModule);
+
+
+// custom tab control
+
+void TSAPI ReloadTabConfig ();
+void TSAPI FreeTabConfig ();
+int TSAPI RegisterTabCtrlClass (void);
+
+// buttons
+
+int TSAPI LoadTSButtonModule (void);
+int TSAPI UnloadTSButtonModule ();
+
+
+/*
+ * debugging support
+ */
+
+int _DebugTraceW(const wchar_t *fmt, ...);
+int _DebugTraceA(const char *fmt, ...);
+int _DebugPopup(HANDLE hContact, const TCHAR *fmt, ...);
+int _DebugMessage(HWND hwndDlg, struct TWindowData *dat, const char *fmt, ...);
+
+// themes
+
+const TCHAR* TSAPI GetThemeFileName (int iMode);
+void TSAPI LoadLogfontFromINI (int i, char *szKey, LOGFONTA *lf, COLORREF *colour, const char *szIniFilename);
+int TSAPI CheckThemeVersion (const TCHAR *szIniFilename);
+void TSAPI WriteThemeToINI (const TCHAR *szIniFilename, TWindowData *dat);
+void TSAPI ReadThemeFromINI (const TCHAR *szIniFilename, TContainerData *dat, int noAdvanced, DWORD dwFlags);
+
+// compatibility
+
+// user prefs
+
+int TSAPI LoadLocalFlags (HWND hwnd, TWindowData *dat);
+
+//TypingNotify
+int TN_ModuleInit ();
+int TN_OptionsInitialize (WPARAM wParam, LPARAM lParam);
+int TN_ModuleDeInit ();
+int TN_TypingMessage (WPARAM wParam, LPARAM lParam);
+
+// mod plus
+
+int ChangeClientIconInStatusBar (const TWindowData *dat);
+
+// hotkeys
+
+LRESULT ProcessHotkeysByMsgFilter (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR ctrlId);
+
+void TSAPI DrawMenuItem (DRAWITEMSTRUCT *dis, HICON hIcon, DWORD dwIdle);
+
+/*
+ * dialog procedures
+ */
+
+INT_PTR CALLBACK SelectContainerDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK DlgProcContainerOptions (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK DlgProcAbout (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+#endif /* _TABSRMM_FUNCTIONS_H */
diff --git a/plugins/TabSRMM/src/include/generic_msghandlers.h b/plugins/TabSRMM/src/include/generic_msghandlers.h
new file mode 100644
index 0000000000..4f756b24f0
--- /dev/null
+++ b/plugins/TabSRMM/src/include/generic_msghandlers.h
@@ -0,0 +1,67 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: generic_msghandlers.h 12058 2010-06-24 15:26:10Z silvercircle $
+ *
+ * prototypes from generic_msghandlers.c
+ *
+ */
+
+void TSAPI DM_SetDBButtonStates (HWND hwndChild, struct TWindowData *dat);
+int TSAPI BTN_GetStockItem (ButtonItem *item, const TCHAR *szName);
+HWND TSAPI DM_CreateClist (TWindowData *dat);
+
+void TSAPI DM_OptionsApplied (TWindowData *dat, WPARAM wParam, LPARAM lParam);
+void TSAPI DM_UpdateTitle (TWindowData *dat, WPARAM wParam, LPARAM lParam);
+LRESULT TSAPI DM_ScrollToBottom (TWindowData *dat, WPARAM wParam, LPARAM lParam);
+LRESULT TSAPI DM_LoadLocale (TWindowData *dat);
+LRESULT TSAPI DM_SaveLocale (TWindowData *dat, WPARAM wParam, LPARAM lParam);
+LRESULT TSAPI DM_UpdateLastMessage (const TWindowData *dat);
+LRESULT __stdcall DM_RecalcPictureSize (TWindowData *dat);
+LRESULT TSAPI DM_WMCopyHandler (HWND hwnd, WNDPROC oldWndProc, WPARAM wParam, LPARAM lParam);
+LRESULT TSAPI DM_MouseWheelHandler (HWND hwnd, HWND hwndParent, struct TWindowData *mwdat, WPARAM wParam, LPARAM lParam);
+LRESULT TSAPI DM_ThemeChanged (TWindowData *dat);
+void TSAPI DM_Typing (TWindowData *dat, bool fForceOff = false);
+void TSAPI DM_FreeTheme (TWindowData *dat);
+void TSAPI DM_NotifyTyping (TWindowData *dat, int mode);
+int TSAPI DM_SplitterGlobalEvent (TWindowData *dat, WPARAM wParam, LPARAM lParam);
+void TSAPI BB_InitDlgButtons (TWindowData *dat);
+
+BOOL TSAPI BB_SetButtonsPos (TWindowData *dat);
+void TSAPI BB_RedrawButtons (TWindowData *dat);
+void TSAPI BB_CustomButtonClick (TWindowData *dat,DWORD idFrom ,HWND hwndFrom, BOOL code) ;
+void TSAPI DM_EventAdded (TWindowData *dat, WPARAM wParam, LPARAM lParam);
+void TSAPI DM_InitRichEdit (TWindowData *dat);
+LRESULT TSAPI DM_ContainerCmdHandler (TContainerData *pContainer, UINT cmd, WPARAM wParam, LPARAM lParam);
+LRESULT TSAPI DM_MsgWindowCmdHandler (HWND hwndDlg, TContainerData *pContainer, TWindowData *dat, UINT cmd, WPARAM wParam, LPARAM lParam);
+LRESULT TSAPI DM_GenericHotkeysCheck (MSG *message, TWindowData *dat);
+void TSAPI DM_DismissTip (TWindowData *dat, const POINT& pt);
+void TSAPI DM_InitTip (TWindowData *dat);
+void TSAPI DM_HandleAutoSizeRequest(TWindowData *dat, REQRESIZE* rr);
+void TSAPI DM_SaveLogAsRTF (const TWindowData* dat);
+void TSAPI DM_CheckAutoHide (const TWindowData* dat, WPARAM wParam, LPARAM lParam);
diff --git a/plugins/TabSRMM/src/include/globals.h b/plugins/TabSRMM/src/include/globals.h
new file mode 100644
index 0000000000..69d62f66f7
--- /dev/null
+++ b/plugins/TabSRMM/src/include/globals.h
@@ -0,0 +1,245 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: globals.h 13046 2010-10-28 10:02:50Z silvercircle $
+ *
+ * Plugin configuration variables and functions. Implemented as a class
+ * though there will always be only a single instance.
+ *
+ */
+
+#ifndef __GLOBALS_H
+#define __GLOBALS_H
+
+struct TSplitterBroadCast {
+ TContainerData *pSrcContainer;
+ TWindowData *pSrcDat;
+ LONG pos, pos_chat;
+ LONG off_chat, off_im;
+ LPARAM lParam;
+ BYTE bSync;
+};
+
+typedef BOOL (WINAPI *pfnSetMenuInfo )( HMENU hmenu, LPCMENUINFO lpcmi );
+
+class CRTException : public std::runtime_error
+{
+public:
+ CRTException(const char *szMsg, const TCHAR *szParam);
+ ~CRTException() {}
+
+ void display() const;
+
+private:
+ TCHAR m_szParam[MAX_PATH];
+};
+
+
+class CGlobals
+{
+public:
+ enum {
+ H_MS_MSG_SENDMESSAGE = 0,
+ H_MS_MSG_SENDMESSAGEW = 1,
+ H_MS_MSG_FORWARDMESSAGE = 2,
+ H_MS_MSG_GETWINDOWAPI = 3,
+ H_MS_MSG_GETWINDOWCLASS = 4,
+ H_MS_MSG_GETWINDOWDATA = 5,
+ H_MS_MSG_READMESSAGE = 6,
+ H_MS_MSG_TYPINGMESSAGE = 7,
+ H_MS_MSG_MOD_MESSAGEDIALOGOPENED = 8,
+ H_MS_TABMSG_SETUSERPREFS = 9,
+ H_MS_TABMSG_TRAYSUPPORT = 10,
+ H_MSG_MOD_GETWINDOWFLAGS = 11,
+ H_MS_TABMSG_SLQMGR = 12,
+ SERVICE_LAST = 13
+ };
+
+ CGlobals()
+ {
+ ::ZeroMemory(this, sizeof(CGlobals));
+ m_TypingSoundAdded = false;
+ }
+
+ ~CGlobals()
+ {
+ if (m_MenuBar)
+ ::DestroyMenu(m_MenuBar);
+
+ CContactCache* c = CContactCache::m_cCache, *cTemp;
+ while(c) {
+ cTemp = c->m_next;
+ delete c;
+ c = cTemp;
+ }
+ }
+ void reloadAdv();
+ void reloadSystemStartup();
+ void reloadSystemModulesChanged();
+ void reloadSettings(bool fReloadSkins = true);
+
+ void hookSystemEvents();
+ bool haveAutoSwitch();
+
+ const HMENU getMenuBar();
+
+ HWND g_hwndHotkeyHandler;
+ HICON g_iconIn, g_iconOut, g_iconErr, g_iconContainer, g_iconStatus;
+ HICON g_iconOverlayDisabled, g_iconOverlayEnabled, g_iconClock;
+ HCURSOR hCurSplitNS, hCurSplitWE, hCurHyperlinkHand;
+ HBITMAP g_hbmUnknown;
+ int g_MetaContactsAvail, g_SmileyAddAvail, g_WantIEView, g_PopupAvail, g_PopupWAvail, g_WantHPP;
+ int g_FlashAvatarAvail;
+ HIMAGELIST g_hImageList;
+ HICON g_IconMsgEvent, g_IconTypingEvent, g_IconFileEvent, g_IconSend;
+ HICON g_IconMsgEventBig, g_IconTypingEventBig;
+ HICON g_IconFolder, g_IconChecked, g_IconUnchecked;
+ HMENU g_hMenuContext, g_hMenuContainer, g_hMenuEncoding, g_hMenuTrayUnread;
+ HMENU g_hMenuFavorites, g_hMenuRecent, g_hMenuTrayContext;
+ HICON g_buttonBarIcons[NR_BUTTONBARICONS];
+ HICON g_sideBarIcons[NR_SIDEBARICONS];
+ HANDLE g_buttonBarIconHandles[23];
+ // dynamic options, need reload when options change
+ int m_SendOnShiftEnter;
+ int m_SendOnEnter;
+ int m_SendOnDblEnter;
+ int m_AutoLocaleSupport;
+ int m_AutoSwitchTabs;
+ int m_CutContactNameOnTabs;
+ int m_CutContactNameTo;
+ int m_StatusOnTabs;
+ int m_LogStatusChanges;
+ int m_UseDividers;
+ int m_DividersUsePopupConfig;
+ int m_MsgTimeout;
+ int m_EscapeCloses;
+ int m_FlashOnClist;
+ int m_AlwaysFullToolbarWidth;
+ int m_LimitStaticAvatarHeight;
+ int m_SendFormat;
+ int m_FormatWholeWordsOnly;
+ int m_RTLDefault;
+ int m_MathModAvail;
+ TCHAR m_MathModStartDelimiter[40];
+ int m_UnreadInTray;
+ int m_TrayFlashes;
+ int m_TrayFlashState;
+ BOOL m_SuperQuiet;
+ HANDLE m_UserMenuItem;
+ double g_DPIscaleX;
+ double g_DPIscaleY;
+ BOOL m_HideOnClose;
+ BOOL g_bSoundOnTyping;
+ BOOL m_AllowTab;
+ BYTE m_AllowOfflineMultisend;
+ BOOL g_bDisableAniAvatars;
+ HBITMAP m_hbmMsgArea;
+ BYTE g_iButtonsBarGap;
+ BYTE m_WinVerMajor;
+ BYTE m_WinVerMinor;
+ bool m_bIsXP, m_bIsVista, m_bIsWin7;
+ HWND m_hwndClist;
+ int m_TabAppearance;
+ struct myTabCtrl tabConfig;
+ int m_panelHeight, m_MUCpanelHeight;
+ WINDOWPLACEMENT m_GlobalContainerWpos;
+ int m_IdleDetect;
+ int m_smcxicon, m_smcyicon;
+ int m_PasteAndSend;
+ TCHAR *m_szNoStatus;
+ COLORREF crIncoming, crOutgoing, crOldIncoming, crOldOutgoing, crStatus;
+ BOOL bUnicodeBuild;
+ HFONT hFontCaption;
+ DWORD m_LangPackCP;
+ BYTE m_SmileyButtonOverride;
+ NONCLIENTMETRICS m_ncm;
+ HICON m_AnimTrayIcons[4];
+ BOOL m_visualMessageSizeIndicator;
+ BOOL m_autoSplit;
+ BOOL m_FlashOnMTN;
+ DWORD dwThreadID;
+ char szMetaName[256];
+ BYTE bMetaEnabled;
+ HANDLE m_hMessageWindowList, hUserPrefsWindowList;
+ bool m_chat_enabled;
+ HMENU m_MenuBar;
+ COLORREF m_ipBackgroundGradient;
+ COLORREF m_ipBackgroundGradientHigh;
+ COLORREF m_tbBackgroundHigh, m_tbBackgroundLow, m_fillColor, m_cRichBorders, m_genericTxtColor;
+ BYTE g_bClientInStatusBar;
+ BYTE m_dontUseDefaultKbd;
+ HANDLE hSvc[SERVICE_LAST];
+ HANDLE m_event_MsgWin, m_event_MsgPopup;
+ HANDLE m_hMenuItem;
+ BYTE m_useAeroPeek;
+
+ TSplitterBroadCast lastSPlitterPos;
+ TContainerSettings globalContainerSettings;
+
+ static HANDLE m_event_FoldersChanged;
+ static TCHAR* m_default_container_name;
+ static void cacheUpdateMetaChanged();
+ static void logStatusChange(WPARAM wParam, const CContactCache *c);
+
+ static void Ex_CopyEditToClipboard(HWND hWnd);
+ static void Ex_Handler();
+ static int Ex_ShowDialog(EXCEPTION_POINTERS *ep, const char *szFile, int line, wchar_t* szReason, bool fAllowContinue);
+ static INT_PTR CALLBACK Ex_DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+private:
+ bool m_TypingSoundAdded;
+ static HANDLE m_event_ModulesLoaded, m_event_PrebuildMenu, m_event_SettingChanged;
+ static HANDLE m_event_ContactDeleted, m_event_Dispatch, m_event_EventAdded;
+ static HANDLE m_event_IconsChanged, m_event_TypingEvent, m_event_ProtoAck, m_event_PreShutdown, m_event_OkToExit;
+ static HANDLE m_event_IcoLibChanged, m_event_AvatarChanged, m_event_MyAvatarChanged, m_event_FontsChanged;
+ static HANDLE m_event_SmileyAdd, m_event_IEView;
+ static HANDLE m_event_ME_MC_SUBCONTACTSCHANGED, m_event_ME_MC_FORCESEND, m_event_ME_MC_UNFORCESEND;
+
+ static EXCEPTION_RECORD m_exRecord;
+ static CONTEXT m_exCtx;
+ static LRESULT m_exLastResult;
+ static char m_exSzFile[MAX_PATH];
+ static wchar_t m_exReason[256];
+ static int m_exLine;
+ static bool m_exAllowContinue;
+private:
+ static int ModulesLoaded(WPARAM wParam, LPARAM lParam);
+ static int DBSettingChanged(WPARAM wParam, LPARAM lParam);
+ static int DBContactDeleted(WPARAM wParam, LPARAM lParam);
+ static int PreshutdownSendRecv(WPARAM wParam, LPARAM lParam);
+ static int MetaContactEvent(WPARAM wParam, LPARAM lParam);
+ static int OkToExit(WPARAM wParam, LPARAM lParam);
+ static void RestoreUnreadMessageAlerts(void);
+};
+
+extern CGlobals PluginConfig;
+extern CGlobals *pConfig;
+
+#define DPISCALEY_S(argY) ((int) ((double)(argY) * PluginConfig.g_DPIscaleY))
+#define DPISCALEX_S(argX) ((int) ((double)(argX) * PluginConfig.g_DPIscaleX))
+
+#endif /* __GLOBALS_H */
diff --git a/plugins/TabSRMM/src/include/infopanel.h b/plugins/TabSRMM/src/include/infopanel.h
new file mode 100644
index 0000000000..3a2812444e
--- /dev/null
+++ b/plugins/TabSRMM/src/include/infopanel.h
@@ -0,0 +1,220 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: infopanel.h 12396 2010-08-22 17:17:05Z silvercircle $
+ *
+ * the info area for both im and chat sessions
+ */
+
+#ifndef __INFOPANEL_H
+#define __INFOPANEL_H
+
+/*
+ * configuration data for the info panel (fonts, colors)
+ * this is global for all panels
+ */
+
+#define IPFONTCOUNT 6 // # of fonts needed for the info panel
+
+/*
+ * command ids for the info panel contextual menus
+ */
+
+#define CMD_IP_USERDETAILS 20000
+#define CMD_IP_USERPREFS 20001
+#define CMD_IP_ROOMPREFS 20002
+#define CMD_IP_HISTORY 20003
+#define CMD_IP_COPY 21000
+
+struct TInfoPanelConfig {
+ HFONT hFonts[IPFONTCOUNT];
+ COLORREF clrs[IPFONTCOUNT];
+ UINT height1, height2;
+};
+
+extern TCHAR *xStatusDescr[];
+
+/**
+ * a simple tooltip class using a richedit control to display its content. Allows
+ * for formatted text and clickable hyperlinks
+ *
+ * Used by: Info panel to display status messages, topics etc.
+ */
+class CTip
+{
+public:
+ enum {
+ TOP_BORDER = 25,
+ LEFT_BORDER = 2,
+ RIGHT_BORDER = 2,
+ BOTTOM_BORDER = 1,
+ LEFT_BAR_WIDTH = 20
+ };
+
+ CTip (const HWND hwndParent, const HANDLE hContact, const TCHAR *pszText = 0, const CInfoPanel *panel = 0);
+ ~CTip()
+ {
+ if (m_pszText)
+ mir_free(m_pszText);
+ }
+ void show (const RECT& rc, POINT& pt, const HICON hIcon = 0, const TCHAR *szTitle = 0);
+ const HWND getHwnd () const { return(m_hwnd); }
+
+ static void registerClass ();
+private:
+
+ INT_PTR CALLBACK WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK WndProcStub (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK RichEditProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+ HWND m_hwnd; // our window handle
+ HWND m_hRich; // handle of the rich edit child
+ HWND m_hwndParent; // parent window (used for position calculations and to send notifications)
+ HANDLE m_hContact; // contact handle
+ char* m_pszText; // the richedit text
+ SIZE m_szRich; // size of the richedit control (height auto-calculated to make it fit the text)
+ RECT m_rcRich; // adjusted rectangle for the richedit control (client coordinates)
+ const CInfoPanel* m_panel; // the info panel parent (if any)
+ HICON m_hIcon; // optional icon to show in the title line
+ const TCHAR* m_szTitle; // optional text to show in the title
+ int m_leftWidth;
+
+private:
+ static WNDPROC m_OldMessageEditProc; // stores original richedit wnd proc
+
+};
+
+/**
+ * the info panel class definition. The panel itself is not a real window class - it
+ * is implemented as a drawing canvas on the message window background.
+ *
+ * Each message session has its own info panel object
+ */
+class CInfoPanel
+{
+public:
+ enum {
+ DEGRADE_THRESHOLD = 37, // defines the height at which the infopanel will do the transition from 1 to 2 lines
+ LEFT_OFFSET_LOGO = 3
+ };
+ enum {
+ HOVER_NICK = 1,
+ HOVER_STATUS = 2,
+ HOVER_UIN = 4
+ };
+ enum {
+ HTNICK = 1,
+ HTUIN = 2,
+ HTSTATUS = 3,
+ HTNIRVANA = 0
+ };
+ CInfoPanel(TWindowData *dat)
+ {
+ if (dat) {
+ m_dat = dat;
+ m_isChat = dat->bType == SESSIONTYPE_CHAT ? true : false;
+ }
+ m_defaultHeight = PluginConfig.m_panelHeight;
+ m_defaultMUCHeight = PluginConfig.m_MUCpanelHeight;
+ m_hwndConfig = 0;
+ m_hoverFlags = 0;
+ m_tip = 0;
+ }
+
+ ~CInfoPanel()
+ {
+ if (m_hwndConfig)
+ ::DestroyWindow(m_hwndConfig);
+ saveHeight(true);
+ }
+
+ const LONG getHeight () const { return(m_height); }
+ void setHeight (LONG newHeight, bool fBroadcast = false);
+ bool isActive () const { return(m_active); }
+ bool isPrivateHeight () const { return(m_fPrivateHeight); }
+ DWORD isHovered () const { return(m_active ? m_hoverFlags : 0); }
+ const TWindowData* getDat () const { return(m_dat); }
+ void setActive (const int newActive);
+ void loadHeight ();
+ void saveHeight (bool fFlush = false);
+
+ void Configure () const;
+ void showHide () const;
+ bool getVisibility ();
+ void renderBG (const HDC hdc, RECT& rc, CSkinItem *item, bool fAero, bool fAutoCalc = true) const;
+ void renderContent (const HDC hdcMem);
+ void Invalidate (BOOL fErase = FALSE) const;
+ void trackMouse (POINT& pt);
+ int hitTest (POINT pt);
+ void handleClick (const POINT& pt);
+ void showTip (UINT ctrlId, const LPARAM lParam);
+ void hideTip (const HWND hWndNew);
+ int invokeConfigDialog (const POINT& pt);
+ void dismissConfig (bool fForced = false);
+
+public:
+ static TInfoPanelConfig m_ipConfig;
+ static int setPanelHandler (TWindowData *dat, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK avatarParentSubclass (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+private:
+ void mapRealRect (const RECT& rcSrc, RECT& rcDest, const SIZE& sz);
+ HFONT setUnderlinedFont (const HDC hdc, HFONT hFontOrig);
+ void RenderIPNickname (const HDC hdc, RECT& rc);
+ void RenderIPUIN (const HDC hdc, RECT& rcItem);
+ void RenderIPStatus (const HDC hdc, RECT& rcItem);
+ void Chat_RenderIPNickname (const HDC hdc, RECT& rcItem);
+ void Chat_RenderIPSecondLine (const HDC hdc, RECT& rcItem);
+ LRESULT cmdHandler (UINT cmd);
+ HMENU constructContextualMenu () const;
+ INT_PTR CALLBACK ConfigDlgProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK ConfigDlgProcStub (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+private:
+ bool m_isChat; // is MUC session
+ bool m_active; // panel active and visible
+ bool m_fPrivateHeight;
+ bool m_fDialogCreated;
+ TWindowData* m_dat; // this one OWNS us...
+ LONG m_height; // height (determined by position of IDC_PANELSPLITTER)
+ LONG m_defaultHeight, m_defaultMUCHeight; // global values for the info bar height
+ HWND m_hwndConfig; // window handle of the config dialog window
+ HFONT m_configDlgFont, m_configDlgBoldFont;
+ SIZE m_szNick; // rectangle where the nick has been rendered,
+ /*
+ * these are used to store rectangles important to mouse tracking.
+ */
+ RECT m_rcNick;
+ RECT m_rcUIN;
+ RECT m_rcStatus;
+ DWORD m_hoverFlags;
+ CTip* m_tip;
+};
+
+#endif /* __INFOPANEL_H */
+
diff --git a/plugins/TabSRMM/src/include/m_cln_skinedit.h b/plugins/TabSRMM/src/include/m_cln_skinedit.h
new file mode 100644
index 0000000000..5ee66829c5
--- /dev/null
+++ b/plugins/TabSRMM/src/include/m_cln_skinedit.h
@@ -0,0 +1,147 @@
+
+/*
+ * services
+ */
+
+#define MS_CLNSE_INVOKE "CLN_Skinedit/Invoke"
+#define MS_CLNSE_FILLBYCURRENTSEL "CLN_Skinedit/FillByCurrentSel"
+
+/*
+ * data structs
+ */
+
+struct TWindowData;
+class CImageItem;
+
+struct ButtonItem {
+ TCHAR szName[40];
+ HWND hWnd;
+ LONG xOff, yOff;
+ LONG width, height;
+ CImageItem *imgNormal, *imgPressed, *imgHover;
+ LONG_PTR normalGlyphMetrics[4];
+ LONG_PTR hoverGlyphMetrics[4];
+ LONG_PTR pressedGlyphMetrics[4];
+ DWORD dwFlags, dwStockFlags;
+ DWORD uId;
+ TCHAR szTip[256];
+ char szService[256];
+ char szModule[256], szSetting[256];
+ BYTE bValuePush[256], bValueRelease[256];
+ DWORD type;
+ void (*pfnAction)(ButtonItem *item, HWND hwndDlg, TWindowData *dat, HWND hwndItem);
+ void (*pfnCallback)(ButtonItem *item, HWND hwndDlg, TWindowData *dat, HWND hwndItem);
+ TCHAR tszLabel[40];
+ ButtonItem* nextItem;
+ HANDLE hContact;
+ TWindowData *dat;
+};
+
+typedef struct _tagButtonSet {
+ ButtonItem *items;
+ LONG left, top, right, bottom; // client area offsets, calculated from button layout
+} ButtonSet;
+
+struct CSkinItem {
+ TCHAR szName[40];
+ char szDBname[40];
+ int statusID;
+
+ BYTE GRADIENT;
+ BYTE CORNER;
+
+ DWORD COLOR;
+ DWORD COLOR2;
+
+ BYTE COLOR2_TRANSPARENT;
+
+ DWORD TEXTCOLOR;
+
+ int ALPHA;
+
+ int MARGIN_LEFT;
+ int MARGIN_TOP;
+ int MARGIN_RIGHT;
+ int MARGIN_BOTTOM;
+ BYTE IGNORED;
+ DWORD BORDERSTYLE;
+ CImageItem *imageItem;
+};
+
+typedef struct _tagSkinDescription {
+ DWORD cbSize;
+ CSkinItem *StatusItems;
+ int lastItem;
+ int firstItem;
+ char szModule[100];
+ HWND hWndParent, hWndTab;
+ HWND hwndCLUI;
+ HWND hwndSkinEdit; /* out param */
+ HWND hwndImageEdit; /* out param */
+ HMENU hMenuItems;
+ void (*pfnSaveCompleteStruct)(void);
+ void (*pfnClcOptionsChanged )(void);
+ void* (*pfnMalloc)(unsigned int);
+ void (*pfnFree)(void);
+ void* (*pfnRealloc)(void *, unsigned int);
+ void* reserved[20];
+} SKINDESCRIPTION;
+
+// defines
+
+// FLAGS
+#define CORNER_NONE 0
+#define CORNER_ACTIVE 1
+#define CORNER_TL 2
+#define CORNER_TR 4
+#define CORNER_BR 8
+#define CORNER_BL 16
+#define CORNER_ALL (CORNER_TL | CORNER_TR | CORNER_BR | CORNER_BL | CORNER_ACTIVE)
+
+#define GRADIENT_NONE 0
+#define GRADIENT_ACTIVE 1
+#define GRADIENT_LR 2
+#define GRADIENT_RL 4
+#define GRADIENT_TB 8
+#define GRADIENT_BT 16
+
+#define IMAGE_PERPIXEL_ALPHA 1
+#define IMAGE_FLAG_DIVIDED 2
+#define IMAGE_FILLSOLID 4
+#define IMAGE_GLYPH 8
+
+#define IMAGE_STRETCH_V 1
+#define IMAGE_STRETCH_H 2
+#define IMAGE_STRETCH_B 4
+
+#define BUTTON_ISINTERNAL 1
+#define BUTTON_ISTOGGLE 2
+#define BUTTON_ISSERVICE 4
+#define BUTTON_ISPROTOSERVICE 8
+#define BUTTON_PASSHCONTACTW 16
+#define BUTTON_PASSHCONTACTL 32
+#define BUTTON_ISDBACTION 64
+#define BUTTON_ISCONTACTDBACTION 128
+#define BUTTON_DBACTIONONCONTACT 256
+#define BUTTON_ISSIDEBAR 512
+#define BUTTON_NORMALGLYPHISICON 1024
+#define BUTTON_PRESSEDGLYPHISICON 2048
+#define BUTTON_HOVERGLYPHISICON 4096
+#define BUTTON_HASLABEL 8192
+
+#define CLCDEFAULT_GRADIENT 0
+#define CLCDEFAULT_CORNER 0
+
+#define CLCDEFAULT_COLOR 0xd0d0d0
+#define CLCDEFAULT_COLOR2 0xd0d0d0
+
+#define CLCDEFAULT_TEXTCOLOR 0x000000
+
+#define CLCDEFAULT_COLOR2_TRANSPARENT 1
+
+#define CLCDEFAULT_ALPHA 100
+#define CLCDEFAULT_MRGN_LEFT 0
+#define CLCDEFAULT_MRGN_TOP 0
+#define CLCDEFAULT_MRGN_RIGHT 0
+#define CLCDEFAULT_MRGN_BOTTOM 0
+#define CLCDEFAULT_IGNORE 1
diff --git a/plugins/TabSRMM/src/include/mim.h b/plugins/TabSRMM/src/include/mim.h
new file mode 100644
index 0000000000..c971cb7fdf
--- /dev/null
+++ b/plugins/TabSRMM/src/include/mim.h
@@ -0,0 +1,301 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: mim.h 12272 2010-08-04 08:24:08Z silvercircle $
+ *
+ * wraps some parts of Miranda API
+ * Also, OS dependent stuff (visual styles api etc.)
+ *
+ */
+
+#ifndef __MIM_H
+#define __MIM_H
+
+
+extern FI_INTERFACE *FIF;
+
+/*
+ * Win32 API definitions of functions dynamically obtained via GetProcAddress()
+ * - uxtheme
+ * - dwmapi
+ * - some GDI functions (AlphaBlend()..)
+ */
+typedef BOOL (WINAPI *SMI)( HMENU hmenu, LPCMENUINFO lpcmi );
+typedef HRESULT (WINAPI *DEFICA)(HWND hwnd, const MARGINS *margins);
+typedef HRESULT (WINAPI *DICE)(BOOL *);
+typedef DWORD (WINAPI *PSLWA)(HWND, DWORD, BYTE, DWORD);
+typedef BOOL (WINAPI *PULW)(HWND, HDC, POINT *, SIZE *, HDC, POINT *, COLORREF, BLENDFUNCTION *, DWORD);
+typedef BOOL (WINAPI *PFWEX)(FLASHWINFO *);
+typedef BOOL (WINAPI *PAB)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION);
+typedef BOOL (WINAPI *PGF)(HDC, PTRIVERTEX, ULONG, PVOID, ULONG, ULONG);
+
+typedef BOOL (WINAPI *PITA)();
+typedef HANDLE (WINAPI *POTD)(HWND, LPCWSTR);
+typedef UINT (WINAPI *PDTB)(HANDLE, HDC, int, int, RECT *, RECT *);
+typedef UINT (WINAPI *PCTD)(HANDLE);
+typedef UINT (WINAPI *PDTT)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, DWORD, RECT *);
+typedef UINT (WINAPI *PDTTE)(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, RECT *, const DTTOPTS *);
+typedef BOOL (WINAPI *PITBPT)(HANDLE, int, int);
+typedef HRESULT (WINAPI *PDTPB)(HWND, HDC, RECT *);
+typedef HRESULT (WINAPI *PGTBCR)(HANDLE, HDC, int, int, const RECT *, const RECT *);
+
+typedef HMONITOR(WINAPI *MMFW)(HWND, DWORD);
+typedef BOOL (WINAPI *GMIA)(HMONITOR, LPMONITORINFO);
+typedef HRESULT (WINAPI *DRT)(HWND, HWND, PHTHUMBNAIL);
+typedef BOOL (WINAPI *ETDT)(HANDLE, DWORD);
+typedef HANDLE (WINAPI *BBP)(HDC, RECT *, BP_BUFFERFORMAT, BP_PAINTPARAMS *, HDC *);
+typedef HRESULT (WINAPI *EBP)(HANDLE, BOOL);
+typedef HRESULT (WINAPI *BPI)(void);
+typedef HRESULT (WINAPI *BPU)(void);
+typedef HRESULT (WINAPI *BBW)(HWND, DWM_BLURBEHIND *);
+typedef HRESULT (WINAPI *DGC)(DWORD *, BOOL *);
+typedef HRESULT (WINAPI *BPSA)(HANDLE, const RECT *, BYTE);
+typedef int (WINAPI *GLIX)(LPCWSTR, LCTYPE, LPCWSTR, int);
+typedef HRESULT (WINAPI *DWMSWA)(HWND, DWORD, LPCVOID, DWORD);
+typedef HRESULT (WINAPI *DWMIIB)(HWND);
+typedef HRESULT (WINAPI *DWMUT)(HTHUMBNAIL, DWM_THUMBNAIL_PROPERTIES *);
+typedef HRESULT (WINAPI *DURT)(HTHUMBNAIL);
+typedef HRESULT (WINAPI *DSIT)(HWND, HBITMAP, DWORD);
+typedef HRESULT (WINAPI *DSILP)(HWND, HBITMAP, POINT *, DWORD);
+
+/*
+ * used to encapsulate some parts of the Miranda API
+ * constructor does early time initialization - do NOT put anything
+ * here, except thngs that deal with the core and database API.
+ *
+ * it is UNSAFE to assume that any plugin provided services are available
+ * when the object is instantiated.
+ */
+
+class CMimAPI
+{
+public:
+ CMimAPI()
+ {
+ InitPaths();
+ InitAPI();
+ getAeroState();
+
+ LRESULT fi_version = CallService(MS_IMG_GETIFVERSION, 0, 0);
+ CallService(MS_IMG_GETINTERFACE, fi_version, (LPARAM)&FIF);
+
+ ::QueryPerformanceFrequency((LARGE_INTEGER *)&m_tFreq);
+ m_dFreq = (double)(1.0f / m_tFreq);
+ m_hChatLogLock = INVALID_HANDLE_VALUE;
+ }
+
+ ~CMimAPI() {
+ if (m_haveBufferedPaint)
+ m_pfnBufferedPaintUninit();
+ if (m_hUxTheme != 0)
+ FreeLibrary(m_hUxTheme);
+ if (m_hDwmApi != 0)
+ FreeLibrary(m_hDwmApi);
+
+ if (m_hChatLogLock != INVALID_HANDLE_VALUE)
+ CloseHandle(m_hChatLogLock);
+ }
+
+ /*
+ * database functions
+ */
+
+ DWORD FASTCALL GetDword (const HANDLE hContact, const char *szModule, const char *szSetting, DWORD uDefault) const;
+
+ DWORD FASTCALL GetDword (const char *szModule, const char *szSetting, DWORD uDefault) const;
+ DWORD FASTCALL GetDword (const char *szSetting, DWORD uDefault) const;
+ DWORD FASTCALL GetDword (const HANDLE hContact, const char *szSetting, DWORD uDefault) const;
+
+ int FASTCALL GetByte (const HANDLE hContact, const char *szModule, const char *szSetting, int uDefault) const;
+ int FASTCALL GetByte (const char *szModule, const char *szSetting, int uDefault) const;
+ int FASTCALL GetByte (const char *szSetting, int uDefault) const;
+ int FASTCALL GetByte (const HANDLE hContact, const char *szSetting, int uDefault) const;
+
+ INT_PTR FASTCALL GetTString (const HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) const;
+ INT_PTR FASTCALL GetString (const HANDLE hContact, const char *szModule, const char *szSetting, DBVARIANT *dbv) const;
+
+ INT_PTR FASTCALL WriteDword (const HANDLE hContact, const char *szModule, const char *szSetting, DWORD value) const;
+ INT_PTR FASTCALL WriteDword (const char *szModule, const char *szSetting, DWORD value) const;
+
+ INT_PTR FASTCALL WriteByte (const HANDLE hContact, const char *szModule, const char *szSetting, BYTE value) const;
+ INT_PTR FASTCALL WriteByte (const char *szModule, const char *szSetting, BYTE value) const;
+
+ INT_PTR FASTCALL WriteTString (const HANDLE hContact, const char *szModule, const char *szSetting, const TCHAR *st) const;
+
+ /*
+ * path utilities
+ */
+
+ int pathIsAbsolute (const TCHAR *path) const;
+ size_t pathToAbsolute (const TCHAR *pSrc, TCHAR *pOut, const TCHAR *szBase = 0) const;
+ size_t pathToRelative (const TCHAR *pSrc, TCHAR *pOut, const TCHAR *szBase = 0) const;
+
+ const TCHAR* getDataPath() const { return(m_szProfilePath); }
+ const TCHAR* getSkinPath() const { return(m_szSkinsPath); }
+ const TCHAR* getSavedAvatarPath() const { return(m_szSavedAvatarsPath); }
+ const TCHAR* getChatLogPath() const { return(m_szChatLogsPath); }
+ const bool haveFoldersPlugin() const { return(m_haveFolders); }
+
+ const TCHAR* getUserDir();
+ void configureCustomFolders();
+ INT_PTR foldersPathChanged();
+
+ void startTimer();
+ void stopTimer (const char *szMsg = 0);
+ void timerMsg (const char *szMsg);
+ __int64 getTimerStart() const { return(m_tStart); }
+ __int64 getTimerStop() const { return(m_tStop); }
+ __int64 getTicks() const { return(m_tStop - m_tStart); }
+ double getFreq() const { return(m_dFreq); }
+ double getMsec() const { return(1000 * ((double)(m_tStop - m_tStart) * m_dFreq)); }
+
+ /*
+ * os dependant stuff (aero, visual styles etc.)
+ */
+
+ const bool isVSAPIState() const { return m_VsAPI; }
+ /**
+ * return status of Vista Aero
+ *
+ * @return bool: true if aero active, false otherwise
+ */
+ const bool isAero() const { return(m_isAero); }
+ const bool isDwmActive() const { return(m_DwmActive); }
+
+ /**
+ * Refresh Aero status.
+ * Called on:
+ * * plugin init
+ * * WM_DWMCOMPOSITIONCHANGED message received
+ *
+ * @return
+ */
+ bool getAeroState();
+ /**
+ * return status of visual styles theming engine (Windows XP+)
+ *
+ * @return bool: themes are enabled
+ */
+ bool isVSThemed()
+ {
+ return(m_isVsThemed);
+ }
+ /*
+ * window lists
+ */
+
+ void BroadcastMessage (UINT msg, WPARAM wParam, LPARAM lParam);
+ void BroadcastMessageAsync (UINT msg, WPARAM wParam, LPARAM lParam);
+ INT_PTR AddWindow (HWND hWnd, HANDLE h);
+ INT_PTR RemoveWindow (HWND hWnd);
+ HWND FindWindow (HANDLE h) const;
+
+ static int FoldersPathChanged(WPARAM wParam, LPARAM lParam); // hook subscriber for folders plugin
+ static const TCHAR* TSAPI StriStr(const TCHAR *szString, const TCHAR *szSearchFor);
+ static int TypingMessage(WPARAM wParam, LPARAM lParam);
+ static int ProtoAck(WPARAM wParam, LPARAM lParam);
+ static int PrebuildContactMenu(WPARAM wParam, LPARAM lParam);
+ static int DispatchNewEvent(WPARAM wParam, LPARAM lParam);
+ static int MessageEventAdded(WPARAM wParam, LPARAM lParam);
+public:
+ HANDLE m_hMessageWindowList;
+ /*
+ various function pointers
+ */
+ static PITA m_pfnIsThemeActive;
+ static POTD m_pfnOpenThemeData;
+ static PDTB m_pfnDrawThemeBackground;
+ static PCTD m_pfnCloseThemeData;
+ static PDTT m_pfnDrawThemeText;
+ static PDTTE m_pfnDrawThemeTextEx;
+ static PITBPT m_pfnIsThemeBackgroundPartiallyTransparent;
+ static PDTPB m_pfnDrawThemeParentBackground;
+ static PGTBCR m_pfnGetThemeBackgroundContentRect;
+ static ETDT m_pfnEnableThemeDialogTexture;
+ static PSLWA m_pSetLayeredWindowAttributes;
+ static PFWEX m_MyFlashWindowEx;
+ static PAB m_MyAlphaBlend;
+ static PGF m_MyGradientFill;
+ static DEFICA m_pfnDwmExtendFrameIntoClientArea;
+ static DICE m_pfnDwmIsCompositionEnabled;
+ static MMFW m_pfnMonitorFromWindow;
+ static GMIA m_pfnGetMonitorInfoA;
+ static DRT m_pfnDwmRegisterThumbnail;
+ static BPI m_pfnBufferedPaintInit;
+ static BPU m_pfnBufferedPaintUninit;
+ static BBP m_pfnBeginBufferedPaint;
+ static EBP m_pfnEndBufferedPaint;
+ static BBW m_pfnDwmBlurBehindWindow;
+ static DGC m_pfnDwmGetColorizationColor;
+ static BPSA m_pfnBufferedPaintSetAlpha;
+ static GLIX m_pfnGetLocaleInfoEx;
+ static DWMSWA m_pfnDwmSetWindowAttribute;
+ static DWMIIB m_pfnDwmInvalidateIconicBitmaps;
+ static DWMUT m_pfnDwmUpdateThumbnailProperties;
+ static DURT m_pfnDwmUnregisterThumbnail;
+ static DSIT m_pfnDwmSetIconicThumbnail;
+ static DSILP m_pfnDwmSetIconicLivePreviewBitmap;
+ static bool m_shutDown, m_haveBufferedPaint;
+
+private:
+ TCHAR m_szProfilePath[MAX_PATH + 2], m_szSkinsPath[MAX_PATH + 2], m_szSavedAvatarsPath[MAX_PATH + 2], m_szChatLogsPath[MAX_PATH + 2];
+ HMODULE m_hUxTheme, m_hDwmApi;
+ bool m_VsAPI;
+ bool m_isAero;
+ bool m_DwmActive;
+ bool m_isVsThemed;
+ HANDLE m_hDataPath, m_hSkinsPath, m_hAvatarsPath, m_hChatLogsPath;
+ __int64 m_tStart, m_tStop, m_tFreq;
+ double m_dFreq;
+ char m_timerMsg[256];
+ bool m_haveFolders;
+ HANDLE m_hChatLogLock;
+
+ void InitAPI();
+ void InitPaths();
+
+private:
+ static TCHAR m_userDir[MAX_PATH + 2];
+};
+
+inline void CMimAPI::startTimer()
+{
+ ::QueryPerformanceCounter((LARGE_INTEGER *)&m_tStart);
+}
+
+inline void CMimAPI::stopTimer(const char *szMsg)
+{
+ ::QueryPerformanceCounter((LARGE_INTEGER *)&m_tStop);
+
+ if (szMsg)
+ timerMsg(szMsg);
+}
+
+extern CMimAPI *M;
+
+#endif /* __MIM_H */
diff --git a/plugins/TabSRMM/src/include/msgdlgutils.h b/plugins/TabSRMM/src/include/msgdlgutils.h
new file mode 100644
index 0000000000..59e349f07c
--- /dev/null
+++ b/plugins/TabSRMM/src/include/msgdlgutils.h
@@ -0,0 +1,103 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: msgdlgutils.h 12833 2010-09-27 23:45:55Z silvercircle $
+ *
+ *
+ */
+
+#ifndef _MSGDLGUTILS_H
+#define _MSGDLGUTILS_H
+
+#define WANT_IEVIEW_LOG 1
+#define WANT_HPP_LOG 2
+
+void TSAPI CalcDynamicAvatarSize (TWindowData *dat, BITMAP *bminfo);
+char* TSAPI GetCurrentMetaContactProto (TWindowData *dat);
+void TSAPI WriteStatsOnClose (TWindowData *dat);
+int TSAPI MsgWindowUpdateMenu (TWindowData *dat, HMENU submenu, int menuID);
+int TSAPI MsgWindowMenuHandler (TWindowData *dat, int selection, int menuId);
+int TSAPI GetAvatarVisibility (HWND hwndDlg, TWindowData *dat);
+void TSAPI UpdateStatusBar (const TWindowData *dat);
+int TSAPI CheckValidSmileyPack (const char *szProto, HANDLE hContact);
+TCHAR* TSAPI QuoteText (const TCHAR *text, int charsPerLine, int removeExistingQuotes);
+void TSAPI UpdateReadChars (const TWindowData *dat);
+void TSAPI ShowPicture (TWindowData *dat, BOOL showNewPic);
+void TSAPI AdjustBottomAvatarDisplay (TWindowData *dat);
+void TSAPI SetDialogToType (HWND hwndDlg);
+void TSAPI FlashOnClist (HWND hwndDlg, TWindowData *dat, HANDLE hEvent, DBEVENTINFO *dbei);
+char* TSAPI Message_GetFromStream (HWND hwndDlg, const TWindowData* dat, DWORD dwPassedFlags);
+BOOL TSAPI DoRtfToTags (TCHAR * pszText, const TWindowData *dat);
+void TSAPI DoTrimMessage (TCHAR *msg);
+void TSAPI GetMYUIN (TWindowData *dat);
+void TSAPI SetMessageLog (TWindowData *dat);
+void TSAPI SwitchMessageLog (TWindowData *dat, int iMode);
+UINT TSAPI GetIEViewMode (HWND hwndDlg, HANDLE hContact);
+void TSAPI FindFirstEvent (TWindowData *dat);
+void TSAPI SaveSplitter (TWindowData *dat);
+void TSAPI LoadSplitter (TWindowData *dat);
+void TSAPI PlayIncomingSound (const TWindowData *dat);
+void TSAPI GetSendFormat (TWindowData *dat, int mode);
+void TSAPI GetLocaleID (TWindowData *dat, const TCHAR *szKLName);
+void TSAPI LoadOwnAvatar (TWindowData *dat);
+void TSAPI LoadContactAvatar (TWindowData *dat);
+void TSAPI LoadTimeZone (TWindowData *dat);
+void TSAPI HandlePasteAndSend (const TWindowData *dat);
+int TSAPI MsgWindowDrawHandler (WPARAM wParam, LPARAM lParam, TWindowData *dat);
+void TSAPI LoadOverrideTheme (TContainerData *pContainer);
+void TSAPI LoadThemeDefaults (TContainerData *pContainer);
+void TSAPI ConfigureSmileyButton (TWindowData *dat);
+int TSAPI CutContactName (const TCHAR *szold, TCHAR *sznew, unsigned int size);
+void TSAPI SendNudge (const TWindowData *dat);
+void TSAPI EnableSendButton (const TWindowData *dat, int iMode);
+LRESULT TSAPI GetSendButtonState (HWND hwnd);
+HICON TSAPI GetXStatusIcon (const TWindowData *dat);
+void TSAPI FlashTab (TWindowData *dat, HWND hwndTab, int iTabindex, BOOL *bState, BOOL mode, HICON origImage);
+void TSAPI GetClientIcon (TWindowData *dat);
+void TSAPI RearrangeTab (HWND hwndDlg, const TWindowData *dat, int iMode, BOOL fSavePos);
+void TSAPI GetCachedStatusMsg (TWindowData *dat);
+BOOL TSAPI IsStatusEvent (int eventType);
+void TSAPI GetMyNick (TWindowData *dat);
+HICON TSAPI MY_GetContactIcon (const TWindowData *dat);
+void TSAPI CheckAndDestroyIEView (TWindowData *dat);
+void TSAPI KbdState (TWindowData *dat, BOOL& isShift, BOOL& isControl, BOOL& isAlt);
+void TSAPI ClearLog (TWindowData *dat);
+bool TSAPI IsAutoSplitEnabled (const TWindowData* dat);
+LONG TSAPI GetDefaultMinimumInputHeight (const TWindowData* dat);
+void TSAPI DetermineMinHeight (TWindowData* dat);
+// mathmod
+
+void TSAPI MTH_updateMathWindow (const TWindowData *dat);
+
+void TSAPI CleanTempFiles ();
+void TSAPI SendHBitmapAsFile (const TWindowData* dat, HBITMAP hbmp);
+
+extern INT_PTR CALLBACK SelectContainerDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+extern INT_PTR CALLBACK DlgProcContainerOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+#endif
diff --git a/plugins/TabSRMM/src/include/msgs.h b/plugins/TabSRMM/src/include/msgs.h
new file mode 100644
index 0000000000..5f4adef350
--- /dev/null
+++ b/plugins/TabSRMM/src/include/msgs.h
@@ -0,0 +1,1062 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: msgs.h 13587 2011-04-12 13:54:26Z george.hazan $
+ *
+ *
+ */
+
+#ifndef _MSGS_H
+#define _MSGS_H
+
+#ifdef _MSC_VER
+#if _MSC_VER < 1400
+#define uintptr_t UINT_PTR
+#define _localtime32 localtime
+#define __time32_t time_t
+#endif
+#endif
+/*
+ * required for MingW32 compatibility
+ */
+
+#define CF_TEXTT CF_UNICODETEXT
+
+#include <richedit.h>
+#include <richole.h>
+#include "m_avatars.h"
+#include "m_message.h"
+
+#define MSGERROR_CANCEL 0
+#define MSGERROR_RETRY 1
+#define MSGERROR_SENDLATER 2
+
+#define CONTAINER_NAMELEN 25
+#define TITLE_FORMATLEN 30
+
+#define MWF_SAVEBTN_SAV 2
+
+#define MWF_DEFERREDSCROLL 4
+#define MWF_NEEDHISTORYSAVE 8
+#define MWF_WASBACKGROUNDCREATE 16
+//#define MWF_MOUSEDOWN 32
+#define MWF_ERRORSTATE 128
+#define MWF_DEFERREDREMAKELOG 256
+
+#define MWF_LOG_NORMALTEMPLATES 512
+#define MWF_LOG_SHOWTIME 1024
+#define MWF_LOG_SHOWSECONDS 2048
+#define MWF_LOG_SHOWDATES 4096
+
+#define MWF_LOG_INDENT 16384
+#define MWF_LOG_RTL 32768
+
+//MAD: ieview still mistakenly uses these...
+#define MWF_LOG_NEWLINE 8192
+#define MWF_LOG_UNDERLINE 65536
+#define MWF_LOG_SWAPNICK 131072
+//
+//#define MWF_LOG_BBCODE 65536
+//#define MWF_LOG_STATUSCHANGES 131072
+//#define MWF_LOG_LOCALTIME 8192
+#define MWF_LOG_BBCODE 1
+#define MWF_LOG_STATUSCHANGES 32
+#define MWF_LOG_LOCALTIME 64
+
+#define MWF_LOG_SHOWICONS 262144
+#define MWF_LOG_SYMBOLS 0x200000
+#define MWF_INITMODE 0x400000
+#define MWF_NEEDCHECKSIZE 0x800000
+#define MWF_DIVIDERSET 0x1000000
+#define MWF_LOG_TEXTFORMAT 0x2000000
+#define MWF_LOG_GRID 0x4000000
+// #define MWF_LOG_INDIVIDUALBKG 0x8000000 * FREE *
+#define MWF_LOG_INOUTICONS 0x10000000
+#define MWF_SMBUTTONSELECTED 0x20000000
+#define MWF_DIVIDERWANTED 0x40000000
+#define MWF_LOG_GROUPMODE 0x80000000
+
+#define MWF_SHOW_URLEVENTS 1
+#define MWF_SHOW_FILEEVENTS 2
+//#define MWF_SHOW_PRIVATETHEME 4
+//#define MWF_SHOW_EMPTYLINEFIX 8
+//#define MWF_SHOW_MICROLF 16
+//#define MWF_SHOW_MARKFOLLOWUPTS 32
+#define MWF_SHOW_FLASHCLIST 64
+#define MWF_SHOW_SPLITTEROVERRIDE 128
+#define MWF_SHOW_SCROLLINGDISABLED 256
+//#define MWF_SHOW_INFONOTES ** FREE **
+#define MWF_SHOW_ISIDLE 4096
+#define MWF_SHOW_AWAYMSGTIMER 8192
+#define MWF_EX_DELAYEDSPLITTER 32768
+#define MWF_EX_AVATARCHANGED 65536
+#define MWF_EX_WARNCLOSE 0x20000
+
+#define SMODE_DEFAULT 0
+#define SMODE_MULTIPLE 1
+#define SMODE_CONTAINER 2
+#define SMODE_FORCEANSI 4
+#define SMODE_SENDLATER 8
+#define SMODE_NOACK 16
+
+#define SENDFORMAT_BBCODE 1
+#define SENDFORMAT_NONE 0
+
+#define AVATARMODE_DYNAMIC 0
+
+#define MSGDLGFONTCOUNT 22
+#define CHATFONTCOUNT 19
+
+#define TMPL_MSGIN 0
+#define TMPL_MSGOUT 1
+#define TMPL_GRPSTARTIN 2
+#define TMPL_GRPSTARTOUT 3
+#define TMPL_GRPINNERIN 4
+#define TMPL_GRPINNEROUT 5
+#define TMPL_STATUSCHG 6
+#define TMPL_ERRMSG 7
+
+#define TEMPLATE_LENGTH 150
+#define CUSTOM_COLORS 5
+
+struct TTemplateSet {
+ BOOL valid; // all templates populated (may still contain crap.. so it's only half-assed safety :)
+ TCHAR szTemplates[TMPL_ERRMSG + 1][TEMPLATE_LENGTH]; // the template strings
+ char szSetName[20]; // everything in this world needs a name. so does this poor template set.
+};
+
+struct TitleBtn {
+ BOOL isHot;
+ BOOL isPressed;
+};
+
+#define BTN_MIN 0
+#define BTN_MAX 1
+#define BTN_CLOSE 2
+
+#define NR_LOGICONS 8
+#define NR_BUTTONBARICONS 37//MaD: 29
+#define NR_SIDEBARICONS 2
+
+class CTaskbarInteract;
+class CMenuBar;
+class CInfoPanel;
+class CSideBar;
+class CContactCache;
+class CProxyWindow;
+
+#define STICK_ICON_MSG 10
+struct TLogTheme {
+ COLORREF inbg, outbg, bg, oldinbg, oldoutbg, statbg, inputbg;
+ COLORREF hgrid;
+ COLORREF custom_colors[5];
+ DWORD dwFlags;
+ DWORD left_indent, right_indent;
+ LOGFONTA* logFonts;
+ COLORREF* fontColors;
+ char* rtfFonts;
+ bool isPrivate;
+};
+
+struct TContainerSettings {
+ bool fPrivate;
+ DWORD dwFlags;
+ DWORD dwFlagsEx;
+ DWORD dwTransparency;
+ DWORD panelheight;
+ DWORD splitterPos;
+ TCHAR szTitleFormat[TITLE_FORMATLEN + 2];
+ WORD avatarMode;
+ WORD ownAvatarMode;
+ WORD autoCloseSeconds;
+ BYTE reserved[10];
+};
+
+struct TContainerData {
+ TContainerData *pNextContainer;
+ TCHAR szName[CONTAINER_NAMELEN + 4]; // container name
+ HWND hwndActive; // active message window
+ HWND hwnd; // the container handle
+ int iTabIndex; // next tab id
+ int iChilds;
+ int iContainerIndex;
+ bool fHidden;
+ HMENU hMenuContext;
+ HWND hwndTip; // tab - tooltips...
+ BOOL bDontSmartClose; // if set, do not search and select the next possible tab after closing one.
+ DWORD dwFlags;
+ DWORD dwFlagsEx;
+ LONG uChildMinHeight;
+ int tBorder;
+ int tBorder_outer_left, tBorder_outer_right, tBorder_outer_top, tBorder_outer_bottom;
+ HANDLE hContactFrom;
+ BOOL isCloned;
+ HWND hwndStatus;
+ int statusBarHeight;
+ DWORD dwLastActivity;
+ int hIcon; // current window icon stick indicator
+ HICON hIconTaskbarOverlay; // contains a "sticky" taskbar overlay (e.g. new message icon)
+ DWORD dwFlashingStarted;
+ HWND hWndOptions;
+ BOOL bSizingLoop;
+ TCHAR szRelThemeFile[MAX_PATH], szAbsThemeFile[MAX_PATH];
+ TTemplateSet *ltr_templates, *rtl_templates;
+ HDC cachedDC;
+ HBITMAP cachedHBM, oldHBM;
+ SIZE oldDCSize;
+ RECT rcClose, rcMin, rcMax;
+ struct TitleBtn buttons[3];
+ struct TitleBtn oldbuttons[3];
+ int ncActive;
+ HWND hwndSaved;
+ ButtonItem *buttonItems;
+ RECT rcSaved, rcLogSaved;
+ POINT ptLogSaved;
+ DWORD exFlags;
+ BOOL fPrivateThemeChanged;
+ MARGINS mOld;
+ HDC cachedToolbarDC;
+ HBITMAP hbmToolbarBG, oldhbmToolbarBG;
+ SIZE szOldToolbarSize;
+ SIZE oldSize, preSIZE;
+ WORD avatarMode, ownAvatarMode;
+ BYTE bTBRenderingMode;
+ TLogTheme theme;
+ TContainerSettings* settings;
+ CTaskbarInteract* TaskBar;
+ CMenuBar* MenuBar;
+ CSideBar* SideBar;
+};
+
+struct SESSIONINFO_TYPE;
+
+struct TWindowData {
+ UINT cbSize;
+ BYTE bType;
+ struct TContainerData *pContainer; // parent container description structure
+ HWND hwnd;
+ DWORD dwFlags;
+ DWORD dwFlagsEx;
+ HANDLE hContact;
+ char *szProto;
+ TCHAR szMyNickname[130];
+ TCHAR szStatusBar[100];
+ TCHAR newtitle[130]; // tab title...
+ TCHAR szStatus[50];
+ WORD wStatus;
+ char *sendBuffer;
+ int iSendBufferSize;
+ int iSendLength; // message length in utf-8 octets
+ HICON hTabIcon, hTabStatusIcon, hXStatusIcon, hClientIcon, hTaskbarIcon;
+ HICON iFlashIcon;
+ BOOL mayFlashTab;
+ BOOL bTabFlash;
+ HWND hwndIEView, hwndFlash, hwndIWebBrowserControl, hwndHPP;
+ HWND hwndContactPic, hwndPanelPic, hwndPanelPicParent;
+ UINT bbLSideWidth; //MAD
+ UINT bbRSideWidth; //MAD
+ BYTE kstate[256];
+ struct TStatusBarIconNode *pSINod;
+ SESSIONINFO_TYPE* si;
+
+ RECT rcNick, rcUIN, rcStatus, rcPic;
+ HANDLE hDbEventFirst, hDbEventLast;
+ int sendMode;
+ int splitterY, originalSplitterY, dynaSplitter, savedSplitter, savedSplitY, savedDynaSplit;
+ int multiSplitterX;
+ SIZE minEditBoxSize;
+ int showUIElements;
+ int nTypeSecs;
+ int nTypeMode;
+ DWORD nLastTyping;
+ int showTyping;
+ DWORD lastMessage;
+ int iTabID;
+ HKL hkl; // keyboard layout identifier
+ DWORD dwTickLastEvent, dwUnread;
+ HBITMAP hOwnPic;
+ SIZE pic;
+ int showPic, showInfoPic;
+ BOOL fMustOffset;
+ BOOL isHistory;
+ int doSmileys;
+ UINT codePage;
+ HICON hSmileyIcon;
+ int iLastEventType;
+ time_t lastEventTime;
+ int iRealAvatarHeight;
+ int iButtonBarReallyNeeds;
+ DWORD dwLastActivity;
+ int iOpenJobs;
+ int iCurrentQueueError;
+ BOOL bIsMeta;
+ HANDLE hFlashingEvent;
+ TCHAR myUin[80];
+ BOOL bNotOnList;
+ int SendFormat;
+ HANDLE *hQueuedEvents;
+ int iNextQueuedEvent;
+#define EVENT_QUEUE_SIZE 10
+ int iEventQueueSize;
+ LCID lcid;
+ TCHAR lcID[10];
+ int panelWidth;
+ DWORD idle;
+ HWND hwndTip;
+ TOOLINFO ti;
+ HANDLE hTimeZone;
+ DWORD panelStatusCX;
+ COLORREF inputbg;
+ struct avatarCacheEntry *ace, *ownAce;
+ HANDLE *hHistoryEvents;
+ int maxHistory, curHistory;
+ HANDLE hTheme, hThemeIP, hThemeToolbar;
+ char szMicroLf[128];
+ DWORD isAutoRTL;
+ int nMax; // max message size
+ int textLen; // current text len
+ LONG ipFieldHeight;
+ WNDPROC oldIEViewProc;
+ BOOL clr_added;
+ BOOL fIsReattach;
+ WPARAM wParam; // used for "delayed" actions like moved splitters in minimized windows
+ LPARAM lParam;
+ int iHaveRTLLang;
+ BOOL fInsertMode;
+ bool fkeyProcessed;
+ bool fEditNotesActive;
+ CInfoPanel *Panel;
+ CContactCache *cache;
+ CProxyWindow *pWnd; // proxy window object (win7+, for taskbar support).
+ // ALWAYS check this pointer before using it, it is not guaranteed to exist.
+ DWORD iSplitterSaved;
+ BYTE bWasDeleted;
+ BOOL bActualHistory;
+ POINT ptTipActivation;
+ LONG iInputAreaHeight;
+ bool fIsAutosizingInput;
+ bool fLimitedUpdate;
+};
+
+#define MESSAGE_WINDOW_DATA_SIZE offsetof(_MessageWindowData, hdbEventFirst);
+
+typedef struct _recentinfo {
+ DWORD dwFirst, dwMostRecent; // timestamps
+ int iFirstIndex, iMostRecent; // tab indices
+ HWND hwndFirst, hwndMostRecent; // client window handles
+} RECENTINFO;
+
+/*
+ * configuration data for custom tab ctrl
+ */
+
+struct myTabCtrl {
+ HPEN m_hPenShadow, m_hPenItemShadow, m_hPenLight;
+ HFONT m_hMenuFont;
+ COLORREF colors[10];
+ HBRUSH m_brushes[4];
+ DWORD m_fixedwidth;
+ int m_bottomAdjust;
+};
+
+struct TIconDesc {
+ char *szName;
+ char *szDesc;
+ HICON *phIcon; // where the handle is saved...
+ INT_PTR uId; // icon ID
+ BOOL bForceSmall; // true: force 16x16
+};
+
+struct TIconDescW {
+ TCHAR *szName;
+ TCHAR *szDesc;
+ HICON *phIcon; // where the handle is saved...
+ INT_PTR uId; // icon ID
+ BOOL bForceSmall; // true: force 16x16
+};
+
+// menu IDS
+
+#define MENU_LOGMENU 1
+#define MENU_PICMENU 2
+#define MENU_TABCONTEXT 3
+#define MENU_PANELPICMENU 4
+
+#define TABSRMM_SMILEYADD_BKGCOLORMODE 0x10000000
+#define ADDEDEVENTSQUEUESIZE 100
+
+/*
+ * tab config flags
+ */
+
+#define TCF_FLAT 1
+//#define TCF_STYLED 2
+#define TCF_CLOSEBUTTON 4
+#define TCF_FLASHICON 8
+#define TCF_FLASHLABEL 16
+#define TCF_SINGLEROWTABCONTROL 32
+//#define TCF_LABELUSEWINCOLORS 64
+//#define TCF_BKGUSEWINCOLORS 128
+#define TCF_SBARLEFT 256
+#define TCF_SBARRIGHT 512
+
+#define TCF_DEFAULT (TCF_FLASHICON)
+
+#define MIN_PANELHEIGHT 20
+
+struct TNewWindowData {
+ HANDLE hContact;
+ int isWchar;
+ const char* szInitialText;
+ int iTabID;
+ int iTabImage;
+ int iActivate;
+ TCITEM item;
+ TContainerData* pContainer;
+ BOOL bWantPopup;
+ HANDLE hdbEvent;
+ HKL hkl;
+};
+
+// flags for the container dwFlags
+#define CNT_MOUSEDOWN 1
+#define CNT_NOTITLE 2
+#define CNT_HIDETABS 4
+#define CNT_SIDEBAR 8
+#define CNT_NOFLASH 0x10
+#define CNT_STICKY 0x20
+#define CNT_DONTREPORT 0x40
+#define CNT_FLASHALWAYS 0x80
+#define CNT_TRANSPARENCY 0x100
+#define CNT_AUTOHIDE 0x200
+#define CNT_DONTREPORTFOCUSED 0x400
+//#define CNT_GLOBALSETTINGS 0x400
+#define CNT_GLOBALSIZE 0x800
+#define CNT_INFOPANEL 0x1000
+#define CNT_NOSOUND 0x2000
+#define CNT_AUTOSPLITTER 0x4000
+#define CNT_DEFERREDCONFIGURE 0x8000
+#define CNT_CREATE_MINIMIZED 0x10000
+#define CNT_NEED_UPDATETITLE 0x20000
+#define CNT_DEFERREDSIZEREQUEST 0x40000
+#define CNT_DONTREPORTUNFOCUSED 0x80000
+#define CNT_DONTREPORTFOCUSED 0x400
+#define CNT_ALWAYSREPORTINACTIVE 0x100000
+#define CNT_NEWCONTAINERFLAGS 0x200000
+#define CNT_DEFERREDTABSELECT 0x400000
+#define CNT_CREATE_CLONED 0x800000
+#define CNT_NOSTATUSBAR 0x1000000
+#define CNT_NOMENUBAR 0x2000000
+#define CNT_TABSBOTTOM 0x4000000
+#define CNT_AVATARSONTASKBAR 0x200
+#define CNT_BOTTOMTOOLBAR 0x10000000
+#define CNT_HIDETOOLBAR 0x20000000
+#define CNT_UINSTATUSBAR 0x40000000
+#define CNT_VERTICALMAX 0x80000000
+
+#define CNT_EX_SOUNDS_MINIMIZED 1024
+#define CNT_EX_SOUNDS_UNFOCUSED 2048
+#define CNT_EX_SOUNDS_INACTIVETABS 4096
+#define CNT_EX_SOUNDS_FOCUSED 8192
+
+#define CNT_FLAGS_DEFAULT (CNT_DONTREPORT | CNT_DONTREPORTUNFOCUSED | CNT_ALWAYSREPORTINACTIVE | CNT_HIDETABS | CNT_NEWCONTAINERFLAGS | CNT_NOMENUBAR | CNT_INFOPANEL)
+#define CNT_TRANS_DEFAULT 0x00ff00ff
+
+#define CNT_FLAGSEX_DEFAULT (TCF_FLASHICON | CNT_EX_SOUNDS_MINIMIZED | CNT_EX_SOUNDS_UNFOCUSED | CNT_EX_SOUNDS_INACTIVETABS | CNT_EX_SOUNDS_FOCUSED)
+
+#define CNT_CREATEFLAG_CLONED 1
+#define CNT_CREATEFLAG_MINIMIZED 2
+
+#define CNT_EX_CLOSEWARN 1
+
+#define MWF_LOG_ALL (MWF_LOG_NORMALTEMPLATES | MWF_LOG_SHOWTIME | MWF_LOG_SHOWSECONDS | \
+ MWF_LOG_SHOWDATES | MWF_LOG_INDENT | MWF_LOG_TEXTFORMAT | MWF_LOG_SYMBOLS | MWF_LOG_INOUTICONS | \
+ MWF_LOG_SHOWICONS | MWF_LOG_GRID | MWF_LOG_GROUPMODE | \
+ MWF_LOG_RTL | MWF_LOG_BBCODE | MWF_LOG_LOCALTIME/*MAD:*/ | \
+ MWF_LOG_STATUSCHANGES|MWF_LOG_NEWLINE|MWF_LOG_UNDERLINE|MWF_LOG_SWAPNICK /*_MAD*/)
+
+#define MWF_LOG_DEFAULT (MWF_LOG_SHOWTIME | MWF_LOG_NORMALTEMPLATES | MWF_LOG_SHOWDATES | MWF_LOG_SYMBOLS | MWF_LOG_GRID | MWF_LOG_STATUSCHANGES | MWF_LOG_INOUTICONS)
+
+/*
+ * custom dialog window messages
+ */
+#define EM_SUBCLASSED (WM_USER+0x101)
+#define EM_SEARCHSCROLLER (WM_USER+0x103)
+#define EM_VALIDATEBOTTOM (WM_USER+0x104)
+#define EM_THEMECHANGED (WM_USER+0x105)
+#define EM_UNSUBCLASSED (WM_USER+0x106)
+#define EM_REFRESHWITHOUTCLIP (WM_USER+0x107)
+
+#define HM_EVENTSENT (WM_USER+10)
+#define DM_REMAKELOG (WM_USER+11)
+#define HM_DBEVENTADDED (WM_USER+12)
+#define DM_SETINFOPANEL (WM_USER+13)
+#define DM_OPTIONSAPPLIED (WM_USER+14)
+#define DM_SPLITTERMOVED (WM_USER+15)
+#define DM_UPDATETITLE (WM_USER+16)
+#define DM_APPENDTOLOG (WM_USER+17)
+#define DM_ERRORDECIDED (WM_USER+18)
+#define DM_SPLITSENDACK (WM_USER+19)
+#define DM_TYPING (WM_USER+20)
+#define DM_UPDATEWINICON (WM_USER+21)
+#define DM_UPDATELASTMESSAGE (WM_USER+22)
+
+#define DM_SELECTTAB (WM_USER+23)
+#define DM_CLOSETABATMOUSE (WM_USER+24)
+#define DM_STATUSICONCHANGE (WM_USER+25)
+#define DM_SETLOCALE (WM_USER+26)
+#define DM_SESSIONLIST (WM_USER+27)
+#define DM_QUERYLASTUNREAD (WM_USER+28)
+#define DM_QUERYPENDING (WM_USER+29)
+#define DM_UPDATEPICLAYOUT (WM_USER+30)
+#define DM_QUERYCONTAINER (WM_USER+31)
+#define DM_MUCFLASHWORKER (WM_USER+32)
+#define DM_INVALIDATEPANEL (WM_USER+33)
+//#define DM_REPORTMINHEIGHT (WM_USER+34) // msg dialog reports its minimum height to the container
+#define DM_CHECKINFOTIP (WM_USER+35)
+#define DM_SAVESIZE (WM_USER+36)
+#define DM_CHECKSIZE (WM_USER+37)
+#define DM_FORCEREDRAW (WM_USER+38)
+#define DM_CONTAINERSELECTED (WM_USER+39)
+#define DM_CONFIGURECONTAINER (WM_USER+40)
+#define DM_QUERYHCONTACT (WM_USER+41)
+#define DM_DEFERREDREMAKELOG (WM_USER+42)
+#define DM_RESTOREWINDOWPOS (WM_USER+43)
+#define DM_FORCESCROLL (WM_USER+44)
+#define DM_QUERYCLIENTAREA (WM_USER+45)
+#define DM_QUERYRECENT (WM_USER+47)
+#define DM_ACTIVATEME (WM_USER+46)
+// #define DM_REMOVEFROMSENDLATER (WM_USER+48)
+#define DM_SENDLATER_RESEND (WM_USER+49)
+#define DM_ADDDIVIDER (WM_USER+50)
+#define DM_STATUSMASKSET (WM_USER+51)
+#define DM_CONTACTSETTINGCHANGED (WM_USER+52)
+#define DM_UPDATESTATUSMSG (WM_USER+53)
+#define DM_PROTOACK (WM_USER+54)
+#define DM_OWNNICKCHANGED (WM_USER+55)
+#define DM_CONFIGURETOOLBAR (WM_USER+56)
+#define DM_LOADBUTTONBARICONS (WM_USER+57)
+#define DM_ACTIVATETOOLTIP (WM_USER+58)
+#define DM_UINTOCLIPBOARD (WM_USER+59)
+//#define DM_SPLITTEREMERGENCY (WM_USER+60)
+#define DM_SENDMESSAGECOMMAND (WM_USER+61)
+#define DM_FORCEDREMAKELOG (WM_USER+62)
+//#define DM_QUERYFLAGS (WM_USER+63)
+#define DM_STATUSBARCHANGED (WM_USER+64)
+#define DM_SAVEMESSAGELOG (WM_USER+65)
+#define DM_CHECKAUTOCLOSE (WM_USER+66)
+#define DM_UPDATEMETACONTACTINFO (WM_USER+67)
+#define DM_SETICON (WM_USER+68)
+#define DM_CLOSEIFMETA (WM_USER+69)
+#define DM_CHECKQUEUEFORCLOSE (WM_USER+70)
+#define DM_CHECKAUTOHIDE (WM_USER+71)
+#define DM_SETPARENTDIALOG (WM_USER+72)
+#define DM_HANDLECLISTEVENT (WM_USER+73)
+#define DM_TRAYICONNOTIFY (WM_USER+74)
+#define DM_REMOVECLISTEVENT (WM_USER+75)
+#define DM_GETWINDOWSTATE (WM_USER+76)
+#define DM_DOCREATETAB (WM_USER+77)
+#define DM_DELAYEDSCROLL (WM_USER+78)
+#define DM_REPLAYQUEUE (WM_USER+79)
+#define DM_REFRESHTABINDEX (WM_USER+83)
+#define DM_PROTOAVATARCHANGED (WM_USER+84)
+#define DM_SMILEYOPTIONSCHANGED (WM_USER+85)
+#define DM_MYAVATARCHANGED (WM_USER+86)
+#define DM_PRINTCLIENT (WM_USER+87)
+#define DM_IEVIEWOPTIONSCHANGED (WM_USER+88)
+#define DM_SPLITTERGLOBALEVENT (WM_USER + 89)
+#define DM_DOCREATETAB_CHAT (WM_USER+90)
+#define DM_CLIENTCHANGED (WM_USER+91)
+#define DM_PLAYINCOMINGSOUND (WM_USER+92)
+#define DM_SENDMESSAGECOMMANDW (WM_USER+93)
+#define DM_REMOVEPOPUPS (WM_USER+94)
+#define DM_BBNEEDUPDATE (WM_USER+96)
+#define DM_CBDESTROY (WM_USER+97)
+#define DM_LOGSTATUSCHANGE (WM_USER+98)
+//#define DM_SPLITTERMOVEDGLOBAL_NOSYNC_IM (WM_USER+99)
+#define DM_SC_BUILDLIST (WM_USER+100)
+#define DM_SC_INITDIALOG (WM_USER+101)
+#define DM_SC_CONFIG (WM_USER+104)
+#define DM_SCROLLIEVIEW (WM_USER+102)
+#define DM_UPDATEUIN (WM_USER+103)
+
+#define MINSPLITTERY 42
+#define MINLOGHEIGHT 30
+#define ERRORPANEL_HEIGHT 51
+
+// wParam values for DM_SELECTTAB
+
+#define DM_SELECT_NEXT 1
+#define DM_SELECT_PREV 2
+
+#define DM_SELECT_BY_HWND 3 // lParam specifies hwnd
+#define DM_SELECT_BY_INDEX 4 // lParam specifies tab index
+
+#define DM_QUERY_NEXT 1
+#define DM_QUERY_MOSTRECENT 2
+
+/*
+ * implement a callback for the rich edit. Without it, no bitmaps
+ * can be added to the richedit control.
+ * this class has to implement the GetNewStorage() method
+ */
+
+class REOLECallback : IRichEditOleCallback
+{
+
+public:
+
+ REOLECallback()
+ {
+ mRefCounter = 0;
+ }
+
+ ~REOLECallback()
+ {}
+
+ STDMETHOD_(ULONG, AddRef)(void)
+ {
+ mRefCounter++;
+ return (mRefCounter);
+ }
+
+ STDMETHOD_(ULONG, Release)(void)
+ {
+ --mRefCounter;
+ //if (--mRefCounter == 0)
+ // delete this;
+ return (mRefCounter);
+ }
+
+ STDMETHOD(QueryInterface)(REFIID iid, void** ppvObject)
+ {
+ if ( iid == IID_IUnknown || iid == IID_IRichEditOleCallback ) {
+ *ppvObject = this; AddRef(); return (S_OK);
+ }
+ else
+ return (E_NOINTERFACE);
+ }
+
+ STDMETHOD(ContextSensitiveHelp) (BOOL fEnterMode) { return (E_NOTIMPL);}
+ STDMETHOD(DeleteObject) (LPOLEOBJECT lpoleobj) { return (E_NOTIMPL);}
+ STDMETHOD(GetClipboardData) (CHARRANGE FAR *lpchrg, DWORD reco, LPDATAOBJECT FAR *lplpdataobj) { return (E_NOTIMPL);}
+ STDMETHOD(GetContextMenu) (WORD seltype, LPOLEOBJECT lpoleobj, CHARRANGE FAR *lpchrg, HMENU FAR *lphmenu) { return (E_NOTIMPL);}
+ STDMETHOD(GetDragDropEffect) (BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect) { return (E_NOTIMPL);}
+ STDMETHOD(GetInPlaceContext) (LPOLEINPLACEFRAME FAR *lplpFrame, LPOLEINPLACEUIWINDOW FAR *lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo) { return (E_NOTIMPL);}
+ STDMETHOD(GetNewStorage) (LPSTORAGE FAR *lplpstg);
+ STDMETHOD(QueryAcceptData) (LPDATAOBJECT lpdataobj, CLIPFORMAT FAR *lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict) { return (E_NOTIMPL);}
+ STDMETHOD(QueryInsertObject) (LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp) { return (S_OK);}
+ STDMETHOD(ShowContainerUI) (BOOL fShow) { return (E_NOTIMPL);}
+private:
+ UINT mRefCounter;
+};
+
+#define MSGFONTID_MYMSG 0
+#define MSGFONTID_MYMISC 1
+#define MSGFONTID_YOURMSG 2
+#define MSGFONTID_YOURMISC 3
+#define MSGFONTID_MYNAME 4
+#define MSGFONTID_MYTIME 5
+#define MSGFONTID_YOURNAME 6
+#define MSGFONTID_YOURTIME 7
+#define H_MSGFONTID_MYMSG 8
+#define H_MSGFONTID_MYMISC 9
+#define H_MSGFONTID_YOURMSG 10
+#define H_MSGFONTID_YOURMISC 11
+#define H_MSGFONTID_MYNAME 12
+#define H_MSGFONTID_MYTIME 13
+#define H_MSGFONTID_YOURNAME 14
+#define H_MSGFONTID_YOURTIME 15
+#define MSGFONTID_MESSAGEAREA 16
+#define H_MSGFONTID_STATUSCHANGES 17
+#define H_MSGFONTID_DIVIDERS 18
+#define MSGFONTID_ERROR 19
+#define MSGFONTID_SYMBOLS_IN 20
+#define MSGFONTID_SYMBOLS_OUT 21
+
+#define IPFONTID_NICK 0
+#define IPFONTID_UIN 1
+#define IPFONTID_STATUS 2
+#define IPFONTID_PROTO 3
+#define IPFONTID_TIME 4
+
+extern const int msgDlgFontCount;
+
+#define LOADHISTORY_UNREAD 0
+#define LOADHISTORY_COUNT 1
+#define LOADHISTORY_TIME 2
+
+#define SRMSGSET_AUTOPOPUP "AutoPopup"
+#define SRMSGDEFSET_AUTOPOPUP 0
+#define SRMSGSET_AUTOMIN "AutoMin"
+#define SRMSGDEFSET_AUTOMIN 0
+#define SRMSGSET_SENDONENTER "SendOnEnter"
+#define SRMSGDEFSET_SENDONENTER 0
+#define SRMSGSET_MSGTIMEOUT "MessageTimeout"
+#define SRMSGDEFSET_MSGTIMEOUT 60000
+#define SRMSGSET_MSGTIMEOUT_MIN 30000 // minimum value (30 seconds)
+
+#define SRMSGSET_LOADHISTORY "LoadHistory"
+#define SRMSGDEFSET_LOADHISTORY LOADHISTORY_COUNT
+#define SRMSGSET_LOADCOUNT "LoadCount"
+#define SRMSGDEFSET_LOADCOUNT 10
+#define SRMSGSET_LOADTIME "LoadTime"
+#define SRMSGDEFSET_LOADTIME 10
+
+#define SRMSGSET_SHOWURLS "ShowURLs"
+#define SRMSGDEFSET_SHOWURLS 1
+#define SRMSGSET_SHOWFILES "ShowFiles"
+#define SRMSGDEFSET_SHOWFILES 1
+#define SRMSGSET_BKGCOLOUR "BkgColour"
+#define SRMSGSET_BKGCOLOUR_MUC "BkgColourMUC"
+
+#define SRMSGDEFSET_BKGCOLOUR RGB(250,250,250)
+//#define SRMSGDEFSET_BKGCOLOUR GetSysColor(COLOR_WINDOW)
+#define SRMSGDEFSET_BKGINCOLOUR RGB(245,255,245)
+#define SRMSGDEFSET_BKGOUTCOLOUR RGB(245,245,255)
+
+#define SRMSGSET_TYPING "SupportTyping"
+#define SRMSGSET_TYPINGNEW "DefaultTyping"
+#define SRMSGDEFSET_TYPINGNEW 1
+
+#define SRMSGSET_TYPINGUNKNOWN "UnknownTyping"
+#define SRMSGDEFSET_TYPINGUNKNOWN 0
+
+#define SRMSGSET_SHOWTYPING "ShowTyping"
+#define SRMSGDEFSET_SHOWTYPING 1
+
+#define SRMSGSET_SHOWTYPINGWINFLASH "ShowTypingWinFlash"
+#define SRMSGDEFSET_SHOWTYPINGWINFLASH 1
+
+#define SRMSGSET_SHOWTYPINGNOWINOPEN "ShowTypingNoWinOpen"
+
+#define SRMSGSET_SHOWTYPINGWINOPEN "ShowTypingWinOpen"
+
+#define SRMSGSET_SHOWTYPINGCLIST "ShowTypingClist"
+#define SRMSGDEFSET_SHOWTYPINGCLIST 1
+
+// rtl support
+#define SRMSGDEFSET_MOD_RTL 0
+
+#define TIMERID_FLASHWND 1
+#define TIMEOUT_FLASHWND 900
+#define TIMERID_HEARTBEAT 2
+#define TIMEOUT_HEARTBEAT 20000
+#define TIMERID_HOVER 10
+#define TIMERID_HOVER_T 11
+
+#define SRMSGMOD "SRMsg"
+#define SRMSGMOD_T "Tab_SRMsg"
+#define FONTMODULE "TabSRMM_Fonts"
+#define CHAT_FONTMODULE "TabSRMM_chat_Fonts"
+
+#define IDM_STAYONTOP (WM_USER + 1)
+#define IDM_NOTITLE (WM_USER + 2)
+#define IDM_MOREOPTIONS (WM_USER +4)
+
+// constants for the container management functions
+
+#define CNT_ENUM_DELETE 1 // delete the target container...
+#define CNT_ENUM_RENAME 2
+#define CNT_ENUM_WRITEFLAGS 4
+
+#define IDM_CONTAINERMENU 50500
+
+#define EVENTTYPE_STATUSCHANGE 25368
+#define EVENTTYPE_DIVIDER 25367
+#define EVENTTYPE_ERRMSG 25366
+
+// hotkey modifiers...
+
+#define HOTKEY_MODIFIERS_CTRLSHIFT 0
+#define HOTKEY_MODIFIERS_CTRLALT 1
+#define HOTKEY_MODIFIERS_ALTSHIFT 2
+
+struct TLogIcon {
+ HBITMAP hBmp, hoBmp;
+ HDC hdc, hdcMem;
+ HBRUSH hBkgBrush;
+};
+
+#include "..\TabSRMM_icons\resource.h" // icon pack values
+
+struct TCpTable {
+ UINT cpId;
+ TCHAR *cpName;
+};
+
+#define LOI_TYPE_FLAG 1
+#define LOI_TYPE_SETTING 2
+
+struct TOptionListGroup {
+ LRESULT handle;
+ TCHAR *szName;
+};
+
+struct TOptionListItem {
+ LRESULT handle;
+ TCHAR *szName;
+ UINT id;
+ UINT uType;
+ UINT_PTR lParam;
+ UINT uGroup;
+};
+
+// sidebar button flags
+
+#define SBI_TOP 1
+#define SBI_BOTTOM 2
+#define SBI_HIDDEN 4
+#define SBI_DISABLED 8
+#define SBI_TOGGLE 16
+#define SBI_HANDLEBYCLIENT 32
+
+// fixed stock button identifiers
+
+#define IDC_SBAR_SLIST 1111
+#define IDC_SBAR_FAVORITES 1112
+#define IDC_SBAR_RECENT 1113
+#define IDC_SBAR_SETUP 1114
+#define IDC_SBAR_USERPREFS 1115
+#define IDC_SBAR_TOGGLEFORMAT 1117
+#define IDC_SBAR_CANCEL 1118
+
+struct SIDEBARITEM {
+ UINT uId;
+ DWORD dwFlags;
+ HICON *hIcon, *hIconPressed, *hIconHover;
+ TCHAR *szName;
+ void (*pfnAction)(ButtonItem *item, HWND hwndDlg, struct TWindowData *dat, HWND hwndItem);
+ void (*pfnCallback)(ButtonItem *item, HWND hwndDlg, struct TWindowData *dat, HWND hwndItem);
+ TCHAR *tszTip;
+};
+
+#define FONTF_BOLD 1
+#define FONTF_ITALIC 2
+#define FONTF_UNDERLINE 4
+#define FONTF_STRIKEOUT 8
+
+#define RTFCACHELINESIZE 128
+
+#define ID_EXTBKCONTAINER 0
+#define ID_EXTBKBUTTONBAR 1
+#define ID_EXTBKBUTTONSPRESSED 2
+#define ID_EXTBKBUTTONSNPRESSED 3
+#define ID_EXTBKBUTTONSMOUSEOVER 4
+#define ID_EXTBKINFOPANEL 5
+#define ID_EXTBKTITLEBUTTON 6
+#define ID_EXTBKTITLEBUTTONMOUSEOVER 7
+#define ID_EXTBKTITLEBUTTONPRESSED 8
+#define ID_EXTBKTABPAGE 9
+#define ID_EXTBKTABITEM 10
+#define ID_EXTBKTABITEMACTIVE 11
+#define ID_EXTBKTABITEMBOTTOM 12
+#define ID_EXTBKTABITEMACTIVEBOTTOM 13
+#define ID_EXTBKFRAME 14
+#define ID_EXTBKHISTORY 15
+#define ID_EXTBKINPUTAREA 16
+#define ID_EXTBKFRAMEINACTIVE 17
+#define ID_EXTBKTABITEMHOTTRACK 18
+#define ID_EXTBKTABITEMHOTTRACKBOTTOM 19
+#define ID_EXTBKSTATUSBARPANEL 20
+#define ID_EXTBKSTATUSBAR 21
+#define ID_EXTBKUSERLIST 22
+#define ID_EXTBKINFOPANELBG 23
+#define ID_EXTBKSIDEBARBG 24
+#define ID_EXTBK_LAST 24
+
+#define SESSIONTYPE_ANY 0
+#define SESSIONTYPE_IM 1
+#define SESSIONTYPE_CHAT 2
+
+#define DEFAULT_SIDEBARWIDTH 30
+
+#define THEME_READ_FONTS 1
+#define THEME_READ_TEMPLATES 2
+#define THEME_READ_ALL (THEME_READ_FONTS | THEME_READ_TEMPLATES)
+
+#define IDC_TBFIRSTUID 10000 // first uId for custom buttons
+
+#include "templates.h"
+
+struct TStatusBarIconNode {
+ TStatusBarIconNode* next;
+ StatusIconData sid;
+};
+
+struct TABSRMM_SessionInfo {
+ unsigned int cbSize;
+ unsigned short evtCode;
+ HWND hwnd; // handle of the message dialog (tab)
+ HWND hwndContainer; // handle of the parent container
+ HWND hwndInput; // handle of the input area (rich edit)
+ UINT extraFlags;
+ UINT extraFlagsEX;
+ void *local;
+};
+
+typedef struct {
+ int cbSize;
+ HANDLE hContact;
+ int uFlags; // should be same as input data unless 0, then it will be the actual type
+ HWND hwndWindow; //top level window for the contact or NULL if no window exists
+ int uState; // see window states
+ void *local; // used to store pointer to custom data
+} MessageWindowOutputData;
+
+#define MS_MSG_GETWINDOWDATA "MessageAPI/GetWindowData"
+//wparam=(MessageWindowInputData*)
+//lparam=(MessageWindowData*)
+//returns 0 on success and returns non-zero (1) on error or if no window data exists for that hcontact
+
+// callback for the user menu entry
+
+#define MS_TABMSG_SETUSERPREFS "SRMsg_MOD/SetUserPrefs"
+#define MS_TABMSG_SLQMGR "SRMsg_MOD/InvokeQmgr"
+
+// show one of the tray menus
+// wParam = 0 -> session list
+// wParam = 1 -> tray menu
+// lParam must be 0
+#define MS_TABMSG_TRAYSUPPORT "SRMsg_MOD/Show_TrayMenu"
+
+/*
+ * the service which processes globally registered hotkeys
+ */
+#define MS_TABMSG_HOTKEYPROCESS "SRMsg_MOD/ProcessHotkey"
+
+#define MBF_DISABLED 0x01
+
+#define TEMPLATES_MODULE "tabSRMM_Templates"
+#define RTLTEMPLATES_MODULE "tabSRMM_RTLTemplates"
+
+//Checks if there is a message window opened
+//wParam=(LPARAM)(HANDLE)hContact - handle of the contact for which the window is searched. ignored if lParam
+//is not zero.
+//lParam=(LPARAM)(HWND)hwnd - a window handle - SET THIS TO 0 if you want to obtain the window handle
+//from the hContact.
+#define MS_MSG_MOD_MESSAGEDIALOGOPENED "SRMsg_MOD/MessageDialogOpened"
+
+//obtain the message window flags
+//wParam = hContact - ignored if lParam is given.
+//lParam = hwnd
+//returns struct MessageWindowData *dat, 0 if no window is found
+#define MS_MSG_MOD_GETWINDOWFLAGS "SRMsg_MOD/GetWindowFlags"
+
+// custom tabSRMM events
+
+#define tabMSG_WINDOW_EVT_CUSTOM_BEFORESEND 1
+
+
+/* temporary HPP API for emulating message log */
+
+#define MS_HPP_EG_WINDOW "History++/ExtGrid/NewWindow"
+#define MS_HPP_EG_EVENT "History++/ExtGrid/Event"
+#define MS_HPP_EG_UTILS "History++/ExtGrid/Utils"
+#define MS_HPP_EG_OPTIONSCHANGED "History++/ExtGrid/OptionsChanged"
+#define MS_HPP_EG_NOTIFICATION "History++/ExtGrid/Notification"
+
+#define SB_CHAR_WIDTH 45 // default width for status bar panel #2
+#define DEFAULT_CONTAINER_POS 0x00400040 // default container position and size
+#define DEFAULT_CONTAINER_SIZE 0x019001f4
+
+/*
+ * core hotkey service ids
+ */
+
+#define TABSRMM_HK_LASTUNREAD 2
+#define TABSRMM_HK_LASTRECENT 4
+#define TABSRMM_HK_PASTEANDSEND 8
+#define TABSRMM_HK_SETUSERPREFS 9
+#define TABSRMM_HK_CONTAINEROPTIONS 10
+#define TABSRMM_HK_NUDGE 11
+#define TABSRMM_HK_SENDFILE 12
+#define TABSRMM_HK_QUOTEMSG 13
+#define TABSRMM_HK_SEND 14
+#define TABSRMM_HK_EMOTICONS 15
+#define TABARMM_HK_TOGGLEINFOPANEL 16
+#define TABSRMM_HK_HISTORY 17
+#define TABSRMM_HK_TOGGLETOOLBAR 18
+#define TABSRMM_HK_TOGGLEMULTISEND 19
+#define TABSRMM_HK_TOGGLERTL 20
+#define TABSRMM_HK_USERMENU 21
+#define TABSRMM_HK_USERDETAILS 22
+#define TABSRMM_HK_TOGGLEINFOPANEL 23
+#define TABSRMM_HK_CLEARLOG 24
+#define TABSRMM_HK_EDITNOTES 25
+#define TABSRMM_HK_TOGGLESENDLATER 26
+#define TABSRMM_HK_TOGGLESIDEBAR 27
+#define TABSRMM_HK_CHANNELMGR 28
+#define TABSRMM_HK_FILTERTOGGLE 29
+#define TABSRMM_HK_LISTTOGGLE 30
+#define TABSRMM_HK_MUC_SHOWSERVER 31
+
+#define TABSRMM_HK_SECTION_IM "Message windows - IM"
+#define TABSRMM_HK_SECTION_GENERIC "Message windows - all"
+#define TABSRMM_HK_SECTION_GC "Message windows - groupchats"
+
+/*
+ * encryption status bar indicator
+ */
+
+// extern HANDLE hHookIconPressedEvt;
+extern int status_icon_list_size;
+
+int SI_InitStatusIcons();
+int SI_DeinitStatusIcons();
+
+int GetStatusIconsCount();
+void DrawStatusIcons(struct TWindowData *dat, HDC hdc, RECT r, int gap);
+void SI_CheckStatusIconClick(struct TWindowData *dat, HWND hwndFrom, POINT pt, RECT rc, int gap, int code);
+
+typedef struct _tagSKINDesc {
+ ULONG ulID; // resource id
+ TCHAR tszName[30];
+} SKINDESC;
+
+#define SKIN_NR_ELEMENTS 6
+#define SKIN_VERSION 2
+
+/*
+ * icon defintions (index into g_buttonBarIcons)
+ */
+
+#define ICON_DEFAULT_SOUNDS 22
+#define ICON_DEFAULT_PULLDOWN 16
+#define ICON_DEFAULT_LEFT 25
+#define ICON_DEFAULT_RIGHT 28
+#define ICON_DEFAULT_UP 26
+#define ICON_DEFAULT_TYPING 5
+
+#define ICON_BUTTON_ADD 0
+#define ICON_BUTTON_CANCEL 6
+#define ICON_BUTTON_SAVE 7
+
+#endif /* _MSGS_H */
+
+
diff --git a/plugins/TabSRMM/src/include/nen.h b/plugins/TabSRMM/src/include/nen.h
new file mode 100644
index 0000000000..106238b320
--- /dev/null
+++ b/plugins/TabSRMM/src/include/nen.h
@@ -0,0 +1,169 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: nen.h 13750 2011-08-03 20:10:43Z george.hazan $
+ *
+ * This implements the event notification module for tabSRMM. The code
+ * is largely based on the NewEventNotify plugin for Miranda NG. See
+ * notices below for original copyright
+ *
+ * Name: NewEventNotify - Plugin for Miranda ICQ
+ * Description: Notifies you when you receive a message
+ * Author: icebreaker, <icebreaker@newmail.net>
+ * Date: 18.07.02 13:59 / Update: 16.09.02 17:45
+ * Copyright: (C) 2002 Starzinger Michael
+ *
+ */
+
+#ifndef _NEN_H_
+#define _NEN_H_
+
+//#include "m_popup.h"
+//#include "m_popupw.h"
+
+#define MODULE "tabSRMM_NEN"
+
+int tabSRMM_ShowPopup(WPARAM wParam, LPARAM lParam, WORD eventType, int windowOpen, struct TContainerData *pContainer, HWND hwndChild, const char *szProto, struct TWindowData *dat);
+
+
+#define DEFAULT_COLBACK RGB(255,255,128)
+#define DEFAULT_COLTEXT RGB(0,0,0)
+#define DEFAULT_MASKNOTIFY (MASK_MESSAGE|MASK_URL|MASK_FILE|MASK_OTHER)
+#define DEFAULT_MASKACTL (MASK_OPEN|MASK_DISMISS)
+#define DEFAULT_MASKACTR (MASK_DISMISS)
+#define DEFAULT_DELAY -1
+
+#define MASK_MESSAGE 0x0001
+#define MASK_URL 0x0002
+#define MASK_FILE 0x0004
+#define MASK_OTHER 0x0008
+
+#define MASK_DISMISS 0x0001
+#define MASK_OPEN 0x0002
+#define MASK_REMOVE 0x0004
+
+#define PU_REMOVE_ON_FOCUS 1
+#define PU_REMOVE_ON_TYPE 2
+#define PU_REMOVE_ON_SEND 4
+
+#define SETTING_LIFETIME_MIN 1
+#define SETTING_LIFETIME_MAX 60
+#define SETTING_LIFETIME_DEFAULT 4
+
+//Entrys in the database, don't translate
+#define OPT_PREVIEW "Preview"
+#define OPT_COLDEFAULT_MESSAGE "DefaultColorMsg"
+#define OPT_COLBACK_MESSAGE "ColorBackMsg"
+#define OPT_COLTEXT_MESSAGE "ColorTextMsg"
+#define OPT_COLDEFAULT_OTHERS "DefaultColorOthers"
+#define OPT_COLDEFAULT_ERR "DefaultColorErr"
+#define OPT_COLBACK_OTHERS "ColorBackOthers"
+#define OPT_COLTEXT_OTHERS "ColorTextOthers"
+#define OPT_COLBACK_ERR "ColorBackErr"
+#define OPT_COLTEXT_ERR "ColorTextErr"
+#define OPT_MASKNOTIFY "Notify"
+#define OPT_MASKACTL "ActionLeft"
+#define OPT_MASKACTR "ActionRight"
+#define OPT_MASKACTTE "ActionTimeExpires"
+#define OPT_MERGEPOPUP "MergePopup"
+#define OPT_DELAY_MESSAGE "DelayMessage"
+#define OPT_DELAY_OTHERS "DelayOthers"
+#define OPT_DELAY_ERR "DelayErr"
+#define OPT_SHOW_HEADERS "ShowHeaders"
+#define OPT_NORSS "NoRSSAnnounces"
+#define OPT_DISABLE "Disabled"
+#define OPT_MUCDISABLE "MUCDisabled"
+#define OPT_WINDOWCHECK "WindowCheck"
+#define OPT_LIMITPREVIEW "LimitPreview"
+#define OPT_REMOVEMASK "removemask"
+
+struct NEN_OPTIONS {
+ BOOL bPreview;
+ BOOL bDefaultColorMsg;
+ BOOL bDefaultColorOthers;
+ BOOL bDefaultColorErr;
+ BOOL bDisableNonMessage;
+ COLORREF colBackMsg;
+ COLORREF colTextMsg;
+ COLORREF colBackOthers;
+ COLORREF colTextOthers;
+ COLORREF colBackErr;
+ COLORREF colTextErr;
+ UINT maskActL;
+ UINT maskActR;
+ UINT maskActTE;
+ int iDelayMsg;
+ int iDelayOthers;
+ int iDelayErr;
+ int iDelayDefault;
+ BOOL bMergePopup;
+ BOOL bShowHeaders;
+ BOOL bNoRSS;
+ int iDisable;
+ int iMUCDisable;
+ int dwStatusMask;
+ BOOL bTraySupport;
+ BOOL bTrayExist;
+ BOOL iNoSounds;
+ BOOL iNoAutoPopup;
+ BOOL bWindowCheck;
+ int iLimitPreview;
+ WORD wMaxRecent;
+ WORD wMaxFavorites;
+ DWORD dwRemoveMask;
+};
+
+typedef struct {
+ HANDLE hEvent;
+ TCHAR szText[MAX_SECONDLINE + 2];
+ DWORD timestamp;
+} EVENT_DATAT;
+
+typedef struct {
+ UINT eventType;
+ HANDLE hContact;
+ NEN_OPTIONS *pluginOptions;
+ POPUPDATAT_V2* pud;
+ HWND hWnd;
+ long iSeconds;
+ TCHAR szHeader[256];
+ int nrMerged;
+ EVENT_DATAT *eventData;
+ int nrEventsAlloced;
+ int iActionTaken;
+ HWND hContainer;
+} PLUGIN_DATAT;
+
+#define NR_MERGED 5
+
+#define TIMER_TO_ACTION 50685
+
+#define MAX_DATASIZE 50
+#define MAX_POPUPS 20
+
+#endif
diff --git a/plugins/TabSRMM/src/include/resource.h b/plugins/TabSRMM/src/include/resource.h
new file mode 100644
index 0000000000..25f9547d0f
--- /dev/null
+++ b/plugins/TabSRMM/src/include/resource.h
@@ -0,0 +1,796 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by C:\tabsrmm\trunk\miranda\plugins\tabsrmm\resource.rc
+//
+#define IDD_TEMPLATEEDIT 1
+#define IDD_USERPREFS 2
+#define IDOK2 2
+#define IDD_USERPREFS1 3
+#define IDD_TABCONFIG 4
+#define IDD_ABOUT 7
+#define IDD_INFOPANEL 8
+#define IDC_TESTVALUE 10
+#define IDB_BITMAP1 10
+#define IDB_LOGO 10
+#define IDD_USERPREFS_FRAME 11
+#define IDR_SKIN1 13
+#define IDR_SKIN_AERO 14
+#define IDR_SKIN_AERO_GLOW 15
+#define IDD_SENDLATER_QMGR 15
+#define IDR_SKIN_AERO_SWITCHBAR 16
+#define IDD_WARNING 16
+#define IDR_SKIN_LOGO 20
+#define IDI_IMGOPEN 102
+#define IDI_IMGCLOSE 103
+#define IDI_FEATURE_DISABLED 104
+#define IDI_FEATURE_ENABLED 105
+#define IDR_CONTEXT 180
+#define IDM_PASTEFORMATTED 181
+#define IDM_CUT 182
+#define IDM_PASTE 183
+#define IDD_MSGSPLITNEW 184
+#define IDM_QUOTE 185
+#define IDM_COPY 186
+#define IDM_COPYALL 187
+#define IDM_SELECTALL 188
+#define IDM_CLEAR 189
+#define IDM_OPENNEW 190
+#define IDM_OPENEXISTING 191
+#define IDM_COPYLINK 192
+#define IDM_STICKY 193
+#define IDM_REPORTALWAY 194
+#define IDM_REPORTNEVER 195
+#define IDM_DONTREPORTMINIMIZED 196
+#define IDD_OPT_MSGDLG 243
+#define IDD_OPT_MSGLOG 245
+#define IDD_OPT_MSGTYPE 275
+#define IDD_MSGCONTAINER 276
+#define IDD_OPT_TABBEDMSG 277
+#define IDD_POPUP_OPT 278
+#define IDR_ACCEL 283
+#define IDR_TABCONTEXT 286
+#define IDD_MODERNOPTS 288
+#define IDD_SELECTCONTAINER 299
+#define IDD_CONTAINEROPTIONS 300
+#define IDD_OPT_CONTAINERS 301
+#define IDD_OPT_TOOLBAR 304
+#define IDR_MENUBAR 308
+#define IDD_CHOOSESTATUSMODES 310
+#define IDD_SKINTABDIALOG 312
+#define IDD_OPT_SKIN 313
+#define IDD_OPTIONS_PLUS 333
+#define IDD_EXCEPTION 400
+#define IDC_QMGR_REMOVE 1000
+#define IDC_EXCEPTION_DETAILS 1000
+#define IDC_UNLOAD 1000
+#define IDC_READNEXT 1000
+#define IDC_MINIMIZE 1000
+#define IDC_COPY_EXCEPTION 1001
+#define IDC_RELOADSKIN 1001
+#define IDC_APPLY 1001
+#define IDC_MAXIMIZE 1001
+#define IDC_SKINFILE 1002
+#define IDC_MESSAGE 1002
+#define IDC_THEMEEXPORT 1002
+#define IDC_HYPERLINKHAND 1003
+#define IDC_THEMEEXPORT2 1003
+#define IDC_THEMEIMPORT 1003
+#define IDC_EXPORT 1005
+#define IDC_IMPORT 1006
+#define IDC_PREVIEW 1006
+#define IDC_LOG 1006
+#define IDC_CHKNOTIFY_MESSAGE 1007
+#define IDC_FASTGRADIENT 1008
+#define IDC_CHKNOTIFY_URL 1009
+#define IDC_USESKIN 1011
+#define IDC_AUTOCLOSE 1012
+#define IDC_CHKNOTIFY_OTHER 1013
+#define IDC_AUTOMIN 1014
+#define IDC_CHKMENUITEM 1015
+#define IDC_TIME 1016
+#define IDC_CHKDISABLE 1017
+#define IDC_SENDMENU 1018
+#define IDC_CHKACTL_DISMISS 1019
+#define IDC_QUOTE 1020
+#define IDC_CHKACTL_OPEN 1021
+#define IDC_NAME 1022
+#define IDC_CHKACTL_REMOVE 1023
+#define IDC_INFOPANELMENU 1023
+#define IDC_CLOSE 1024
+#define IDC_SAVE 1025
+#define IDC_CHKACTR_DISMISS 1026
+#define IDC_CHKACTR_OPEN 1028
+#define IDC_CONTACTPIC 1029
+#define IDC_ST_ENTERMSG 1031
+#define IDC_PANELNICK 1032
+#define IDC_CHKWINDOWCHECK 1032
+#define IDC_PANELUIN 1033
+#define IDC_CHKPREVIEW 1034
+#define IDC_CHKINFINITE 1035
+#define IDC_PANELSTATUS 1036
+#define IDC_SPLITTER 1037
+#define IDC_CHKDEFAULTCOL_MESSAGE 1038
+#define IDC_CHKDEFAULTCOL_MUC 1039
+#define IDC_CHKDEFAULTCOL_ERR 1040
+#define IDC_COLBACK_MESSAGE 1041
+#define IDC_COLTEXT_MESSAGE 1042
+#define IDC_COLTEXT_MUC 1043
+#define IDC_COLBACK_MUC 1044
+#define IDC_COLTEXT_ERR 1045
+#define IDC_COLBACK_ERR 1046
+#define IDC_SHOWNAMES 1047
+#define IDC_CHKDEFAULTCOL_OTHERS 1050
+#define IDC_COLBACK_OTHERS 1051
+#define IDC_CLOSEONREPLY 1052
+#define IDC_COLTEXT_OTHERS 1053
+#define IDC_SHOWFILES 1054
+#define IDC_MERGEPOPUP 1056
+#define IDC_CHKINFINITE_MESSAGE 1057
+#define IDC_CHKMERGEPOPUP 1058
+#define IDC_IMGTAG 1058
+#define IDC_SHOWURLS 1059
+#define IDC_ANIAVATAR 1059
+#define IDC_DELAY_MESSAGE 1060
+#define IDC_SCROLLFIX 1060
+#define IDC_CLIENTINSTATBAR 1061
+#define IDC_TYPINGSOUNDS 1062
+#define IDC_OFFLINEMULTI 1063
+#define IDC_CLIENTINSTATBAR2 1063
+#define IDC_ICONWARNINGS 1063
+#define IDC_AUTOCLOSEV2 1064
+#define IDC_RESTART 1065
+#define IDC_DELAY_OTHERS 1066
+#define IDC_CLIST 1067
+#define IDC_DELAY_MUC 1067
+#define IDC_NUMBERMSG 1068
+#define IDC_MULTISPLITTER 1069
+#define IDC_CHKSHOWDATE 1070
+#define IDC_SAVEPERCONTACT 1071
+#define IDC_CHKSHOWTIME 1072
+#define IDC_CHKSHOWHEADERS 1073
+#define IDC_LOADCOUNTN 1074
+#define IDC_RDNEW 1075
+#define IDC_LOADCOUNTSPIN 1076
+#define IDC_RDOLD 1077
+#define IDC_SHOWINFOLINE 1078
+#define IDC_LBNUMBERMSG 1079
+#define IDC_SHOWBUTTONLINE 1080
+#define IDC_CHKINFINITE_URL 1081
+#define IDC_LOADUNREAD 1082
+#define IDC_SENDONENTER 1083
+#define IDC_CHKINFINITE_FILE 1084
+#define IDC_LOADCOUNT 1085
+#define IDC_SENDONDBLENTER 1086
+#define IDC_CHKINFINITE_OTHERS 1087
+#define IDC_LOADTIMEN 1088
+#define IDC_LOADTIMESPIN 1089
+#define IDC_LOADTIME 1090
+#define IDC_CMDEDITHEADERS 1091
+#define IDC_TRIM 1091
+#define IDC_FONTLIST 1092
+#define IDC_TRIMSPIN 1092
+#define IDC_USEOSD 1093
+#define IDC_CHOOSEFONT 1094
+#define IDC_CHKACTTE_DISMISS 1095
+#define IDC_CHKACTTE_OPEN 1096
+#define IDC_STMINSOLD 1097
+#define IDC_CHKACTTE_REMOVE 1098
+#define IDC_NORSS 1099
+#define IDC_DETAILS 1100
+#define IDC_ADD 1101
+#define IDC_DELAY_ERR 1102
+#define IDC_RTL 1103
+#define IDC_PIC 1104
+#define IDC_SMILEYBTN 1105
+#define IDC_FONTBOLD 1106
+#define IDC_FONTITALIC 1107
+#define IDC_FONTUNDERLINE 1108
+#define IDC_FONTFACE 1110
+#define IDC_HISTORY 1111
+#define IDC_CANCELADD 1112
+#define IDC_FONTSTRIKEOUT 1113
+#define IDC_MATH_BKGCOLOUR 1124
+#define IDC_FONTCOLOR 1127
+#define IDC_LOGFROZENTEXT 1128
+#define IDC_FONTCOLOUR 1128
+#define IDC_STSIZETEXT 1135
+#define IDC_STCOLOURTEXT 1136
+#define IDC_PRESETSPLIT 1137
+#define IDC_PRESETSINGLE 1138
+#define IDC_STMSGLOGGROUP 1139
+#define IDC_PROTOCOL 1140
+#define IDC_STMSGLOGGROUP2 1140
+#define IDC_STMSGLOGGROUP3 1141
+#define IDC_PROTOMENU 1141
+#define IDC_TYPING 1143
+#define IDC_TOGGLETOOLBAR 1144
+#define IDC_ERRORTEXT 1145
+#define IDC_SHOWNOTIFY 1146
+#define IDC_STATUSWIN 1147
+#define IDC_TYPEFLASHWIN 1148
+#define IDC_CHARCOUNT 1149
+#define IDC_TYPENOWIN 1150
+#define IDC_TYPEWIN 1151
+#define IDC_CASCADE 1151
+#define IDC_SECONDS 1152
+#define IDC_NOTIFYTRAY 1153
+#define IDC_NOTIFYBALLOON 1154
+#define IDC_NOTIFYBALLOON2 1155
+#define IDC_NOTIFYPOPUP 1155
+#define IDC_MathSubst 1156
+#define IDC_INDENT 1157
+#define IDC_INDENTAMOUNT 1158
+#define IDC_MSGTABS 1159
+#define IDC_SIDEBARUP 1160
+#define IDC_SIDEBARDOWN 1161
+#define IDC_WARNONCLOSE 1162
+#define IDC_CUT_TABTITLE 1163
+#define IDC_CUT_TITLEMAX 1164
+#define IDC_SHOWTABTIP 1165
+#define IDC_SHOWSTATUSONTAB 1166
+#define IDC_SWAPTIMESTAMP 1167
+#define IDC_AUTOCREATETABS 1168
+#define IDC_LOCALTIME 1169
+#define IDC_O_HIDETITLE 1170
+#define IDC_STICKY 1171
+#define IDC_LOGSTATUS 1172
+#define IDC_DEBUGPOPUPS 1173
+#define IDC_CONTAINERGROUPMODE 1174
+#define IDC_SELFTYPING 1175
+#define IDC_LOGHOTKEYS 1176
+#define IDC_NOTITLE 1177
+#define IDC_TABPADDING 1178
+#define IDC_PADSPIN 1179
+#define IDC_HTABPADDING 1179
+#define IDC_BOTTOMTABADJUST 1180
+#define IDC_POPUPCONTAINER 1181
+#define IDC_TABWIDTH 1181
+#define IDC_PRIVATESPLITTER 1182
+#define IDC_CNTPRIVATE 1182
+#define IDC_NEWSPLITLAYOUT 1183
+#define IDC_O_NOTABS 1184
+#define IDC_DONTREPORTUNFOCUSED 1185
+#define IDC_ESC_MINIMIZE 1186
+#define IDC_USEDIVIDERS 1187
+#define IDC_DRAWGRID 1188
+#define IDC_LIMITTABS 1189
+#define IDC_WANTVERTICALGRID 1190
+#define IDC_LIMITPREVIEW 1191
+#define IDC_AUTOLOCALE 1192
+#define IDC_MUC_LOGCOLORS 1192
+#define IDC_DONTREPORTUNFOCUSED2 1193
+#define IDC_GCHECK 1194
+#define IDC_HIDETAB 1195
+#define IDC_O_DONTREPORT 1196
+#define IDC_USEDEFERRED 1197
+#define IDC_AUTOSWITCHTABS 1198
+#define IDC_USEINDIVIDUALBKG 1199
+#define IDC_SINGLEWINDOWMODE 1200
+#define IDC_FLATBUTTONS 1201
+#define IDC_O_STICKY 1202
+#define IDC_DIVIDERSUSEPOPUPCONFIG 1203
+#define IDC_FLASHFOREVER 1205
+#define IDC_DONTFLASH 1206
+#define IDC_O_FLASHDEFAULT 1208
+#define IDC_FLASHDEFAULT 1209
+#define IDC_DEFAULTCONTAINERMODE 1210
+#define IDC_ALWAYS 1211
+#define IDC_DONTREPORTFOCUSED2 1212
+#define IDC_TRANSPARENCY 1215
+#define IDC_PANELSPLITTER 1216
+#define IDC_AUTOCREATECONTAINER 1216
+#define IDC_LIMITAVATARS 1217
+#define IDC_DONTREPORT 1219
+#define IDC_SPIN1 1220
+#define IDC_CNTLIST 1221
+#define IDC_SPIN3 1221
+#define IDC_NEWCONTAINER 1222
+#define IDC_TABWIDTHSPIN 1222
+#define IDC_UPDATEPREVIEW 1223
+#define IDC_MODIFY 1223
+#define IDC_SAVESIZEASGLOBAL 1223
+#define IDC_REVERTGLOBAL 1223
+#define IDC_CREATENEW 1224
+#define IDC_RTLMODIFY 1224
+#define IDC_RESETALLTEMPLATES 1224
+#define IDC_SENDLATER 1226
+#define IDC_RETRY 1227
+#define IDC_SETUPAUTOCREATEMODES 1228
+#define IDC_POPUPSTATUSMODES 1229
+#define IDC_DELETECONTAINER 1230
+#define IDC_CANCELSEND 1231
+#define IDC_O_FLASHALWAYS 1232
+#define IDC_RENAMECONTAINER 1233
+#define IDC_RETRY2 1234
+#define IDC_MSGSENDLATER 1235
+#define IDC_O_FLASHNEVER 1236
+#define IDC_NEWCONTAINERNAME 1237
+#define IDC_O_TITLENEVER 1238
+#define IDC_O_TITLEFRONT 1239
+#define IDC_O_TITLESUFFIX 1240
+#define IDC_TRANSPARENCY_ACTIVE 1241
+#define IDC_TRANSPARENCY_INACTIVE 1242
+#define IDC_INDENTSPIN 1250
+#define IDC_TABBORDER 1251
+#define IDC_SPIN2 1252
+#define IDC_TABBORDERSPIN 1253
+#define IDC_FLASHINTERVALSPIN 1254
+#define IDC_HIDESBAR 1255
+#define IDC_TABBORDEROUTER 1256
+#define IDC_TABBORDEROUTERRIGHT 1257
+#define IDC_TABBORDERSPINOUTER 1258
+#define IDC_ALWAYSPOPUPSINACTIVE 1259
+#define IDC_TABBORDERSPINOUTER2 1259
+#define IDC_BOTTOMTABADJUSTSPIN 1259
+#define IDC_HISTORYSIZE 1260
+#define IDC_TABBORDERSPINOUTERRIGHT 1260
+#define IDC_HISTORYSIZESPIN 1261
+#define IDC_TABBORDEROUTERTOP 1261
+#define IDC_HOTKEYSAREGLOBAL 1262
+#define IDC_TABBORDERSPINOUTERTOP 1262
+#define IDC_SINGLEROWTAB 1263
+#define IDC_STREAMTHREADING 1264
+#define IDC_TABBORDEROUTERBOTTOM 1264
+#define IDC_IEVIEWMODE 1265
+#define IDC_TABBORDERSPINOUTERBOTTOM 1265
+#define IDC_TEXTFORMATTING 1266
+#define IDC_AVATARMODE 1267
+#define IDC_CODEPAGES 1268
+#define IDC_OWNAVATARMODE 1268
+#define IDC_EMPTYLINEFIX 1272
+#define IDC_SPLITTERSTATICEDGES 1273
+#define IDC_MAXAVATARHEIGHT 1275
+#define IDC_TABLIMIT 1276
+#define IDC_RIGHTINDENT 1277
+#define IDC_AVATARSPIN 1278
+#define IDC_TABLIMITSPIN 1279
+#define IDC_SHOWFORMATTING 1280
+#define IDC_AGGRESSIVEUPDATE 1283
+#define IDC_THINSEPARATORS 1284
+#define IDC_RINDENTSPIN 1285
+#define IDC_STATICERRORICON 1286
+#define IDC_STATICTEXT 1287
+#define IDC_GROUPMODE 1288
+#define IDC_ANIMATED 1289
+#define IDC_ISFAVORITE 1289
+#define IDC_ALWAYSTRIM 1289
+#define IDC_SKIN_LOADFONTS 1289
+#define IDC_PRESERVEAVATARSIZE 1289
+#define IDC_UPREFS_SHOWICONS 1289
+#define IDC_ALWAYSTRIM2 1290
+#define IDC_SKIN_LOADTEMPLATES 1290
+#define IDC_UPREFS_SHOWSYMBOLS 1290
+#define IDC_SKIN_LOADTEMPLATES2 1291
+#define IDC_UPREFS_INOUTICONS 1291
+#define IDC_AVADYNAMIC 1292
+#define IDC_UPREFS_SHOWTIMESTAMP 1292
+#define IDC_USESNAPPING 1293
+#define IDC_UPREFS_SHOWSECONDS 1293
+#define IDC_UPREFS_SHOWICONS3 1294
+#define IDC_UPREFS_SHOWDATES 1294
+#define IDC_SENDFORMAT 1295
+#define IDC_UPREFS_LOCALTIME 1295
+#define IDC_FLATMSGLOG 1296
+#define IDC_UPREFS_INDENT 1296
+#define IDC_UPREFS_GRID 1297
+#define IDC_UPREFS_GROUPING 1298
+#define IDC_TOGGLESIDEBAR 1299
+#define IDC_CNTNOSTATUSBAR 1299
+#define IDC_UPREFS_BBCODE 1299
+#define IDC_SECTIONTREE 1300
+#define IDC_UPREFS_RTL 1301
+#define IDC_CHECKICONDLL 1302
+#define IDC_UPREFS_LOGSTATUS 1302
+#define IDC_ENABLETRAYSUPPORT 1303
+#define IDC_UPREFS_LOGSTATUS2 1303
+#define IDC_UPREFS_NORMALTEMPLATES 1303
+#define IDC_HEADERSHADING 1304
+#define IDC_HIDEMENUBAR 1305
+#define IDC_STATICCONTROL 1307
+#define IDC_AUTOCLOSETABTIME 1308
+#define IDC_AUTOCLOSETABSPIN 1309
+#define IDC_SENDONSHIFTENTER 1310
+#define IDC_USEGLOBALSIZE 1311
+#define IDC_LOADONLYACTUAL 1311
+#define IDC_MICROLF 1312
+#define IDC_EVENTAPI 1313
+#define IDC_MINIMIZETOTRAY 1316
+#define IDC_DELETETEMP 1318
+#define IDC_FORMATTING 1319
+#define IDC_AUTOSELECTCOPY 1319
+#define IDC_HIDETOOLBAR 1320
+#define IDC_FLASHCLIST 1322
+#define IDC_MSGLOGPLUGIN 1323
+#define IDC_UIDSTATUSBAR 1324
+#define IDC_NRFLASH 1325
+#define IDC_NRFLASHSPIN 1326
+#define IDC_FLASHINTERVAL 1327
+#define IDC_USEKBDHOOK 1328
+#define IDC_STATIC111 1329
+#define IDC_TAB1 1330
+#define IDC_ALWAYSFULLWIDTHTOOLBAR 1335
+#define IDC_FORMATWHOLEWORDSONLY 1337
+#define IDC_STATUSGROUP 1338
+#define IDC_ALLOWSENDBUTTONHIDE 1340
+#define IDC_VERTICALMAX 1341
+#define IDC_AUTOSPLITTER 1342
+#define IDC_ICONDLLNAME 1343
+#define IDC_SAVETEMPLATE 1344
+#define IDC_SELECTICONDLL 1345
+#define IDC_RTLDEFAULT 1346
+#define IDC_MATHMODSUPPORT 1348
+#define IDC_MESSAGEPREVIEWLIMIT 1349
+#define IDC_MESSAGEPREVIEWLIMITSPIN 1350
+#define IDC_DELAY_MESSAGE_SPIN 1351
+#define IDC_DELAY_MESSAGE_MUC_SPIN 1352
+#define IDC_DELAY_ERR_SPIN 1353
+#define IDC_MESSAGEPREVIEWLIMITSPIN2 1354
+#define IDC_DELAY_OTHERS_SPIN 1354
+#define IDC_TEMPLATELIST 1361
+#define IDC_EDITTEMPLATE 1362
+#define IDC_REVERT 1363
+#define IDC_FORGET 1364
+#define IDC_COLOR1 1366
+#define IDC_COLOR2 1367
+#define IDC_COLOR3 1368
+#define IDC_COLOR4 1369
+#define IDC_COLOR5 1370
+#define IDC_FORCEANSI 1371
+#define IDC_TEMPLOVERRIDE 1372
+#define IDC_IGNORETIMEOUTS 1372
+#define IDC_RTLTEMPLOVERRIDE 1373
+#define IDC_SELECTTHEME 1376
+#define IDC_RELOAD 1376
+#define IDC_LOGOPTIONS 1377
+#define IDC_WINDOWOPTIONS 1378
+#define IDC_TRAYCONTAINER 1379
+#define IDC_EVENTOPTIONS 1380
+#define IDC_VARIABLESHELP 1381
+#define IDC_TABMSGOPTIONS 1384
+#define IDC_HELPTEXT 1392
+#define IDC_TITLEFORMAT 1393
+#define IDC_THEME 1394
+#define IDC_INFOPANEL 1395
+#define IDC_SUPPORT 1396
+#define IDC_SHOWAVATAR 1396
+#define IDC_NOPOPUPAVAIL 1398
+#define IDC_QHTM 1399
+#define IDC_TSLABEL_ACTIVE 1400
+#define IDC_TSLABEL_INACTIVE 1401
+#define IDC_TITLEBOX 1402
+#define IDC_DESC 1404
+#define IDC_LABEL_PRIVATETHEME 1405
+#define IDC_MSGLOGDIDSPLAY 1407
+#define IDC_IMCHECK 1410
+#define IDC_CHATCHECK 1411
+#define IDC_CANBEHIDDEN 1412
+#define IDC_BBRESET 1413
+#define IDC_BOTTOMTOOLBAR 1414
+#define IDC_BUTTON1 1415
+#define IDC_SEPARATOR 1415
+#define IDC_PLUS_REVERT 1415
+#define IDC_SIZECOMPACT 1415
+#define IDC_RESCANSKIN 1415
+#define IDC_RESETWARNINGS 1415
+#define IDC_TIMEOUTSPIN 1416
+#define IDC_SIZENORMAL 1416
+#define IDC_SIZELARGE 1417
+#define IDC_MTN_POPUPMODE 1418
+#define IDC_MTN_HELP 1419
+#define IDC_CUT_TITLEMAXSPIN 1420
+#define IDC_HELP_CONTAINERS 1421
+#define IDC_HELP_GENERAL 1422
+#define IDC_CLOSEONESC 1423
+#define IDC_ALWAYSPOPUP 1424
+#define IDC_AEROEFFECT 1424
+#define IDC_CREATEMIN 1425
+#define IDC_ESCMODE 1425
+#define IDC_CHECK5 1426
+#define IDC_TABMODE 1426
+#define IDC_SENDSHIFTENTER 1427
+#define IDC_O_TABMODE 1427
+#define IDC_SENDENTER 1428
+#define IDC_O_SBARLAYOUT 1428
+#define IDC_PANELVISIBILITY 1428
+#define IDC_SENDDBLENTER 1429
+#define IDC_SBARLAYOUT 1429
+#define IDC_PANELSIZE 1429
+#define IDC_MINSEND 1430
+#define IDC_IPCONFIG_TITLE 1430
+#define IDC_SENDCTRLENTER 1431
+#define IDC_NOSYNC 1431
+#define IDC_USETABS 1432
+#define IDC_IPCONFIG_FOOTER 1432
+#define IDC_NOOPENPOPUP 1433
+#define IDC_NOOPENNOTIFY 1433
+#define IDC_GROUP_SCOPE 1433
+#define IDC_CREATENOACTIVATE 1434
+#define IDC_GROUP_SIZE 1434
+#define IDC_NOTIFYMSG 1435
+#define IDC_GROUP_OTHER 1435
+#define IDC_POPUPONCREATE 1436
+#define IDC_SIZE_TIP 1436
+#define IDC_IPCONFIG_PRIVATECONTAINER 1437
+#define IDC_EXPLAINMSGLOGSETTINGS 1437
+#define IDC_NOTIFYFILE 1438
+#define IDC_PANELPICTUREVIS 1438
+#define IDC_SKINNAME 1438
+#define IDC_NOTIFYURL 1439
+#define IDC_SKINROOTFOLDER 1439
+#define IDC_NOTIFYOTHER 1440
+#define IDC_SKIN_WARN 1440
+#define IDC_QMGR_LIST 1441
+#define IDC_QMGR_FILTER 1442
+#define IDC_TOOLBARTREE 1444
+#define IDC_QMGR_HELP 1444
+#define IDC_QMGR_ERRORPOPUPS 1445
+#define IDC_QMGR_ERRORPOPUPS2 1446
+#define IDC_QMGR_SUCCESSPOPUPS 1446
+#define IDC_BUTTON2 1446
+#define IDC_SKIN_CLOSENOW 1446
+#define IDC_CHECK1 1447
+#define IDC_DONTSHOWAGAIN 1447
+#define IDC_CAPTION 1448
+#define IDC_WARNTEXT 1449
+#define IDC_WARNICON 1450
+#define IDC_WARNGROUP 1451
+#define IDC_EX_REASON 1452
+#define IDC_FLASHICON 1489
+#define IDC_FLASHLABEL 1490
+#define IDC_STATIC_VISIBILTY 1491
+#define IDC_BUTTONTABS 1492
+#define IDC_CLOSEBUTTONONTABS 1493
+#define IDC_O_STATIC_AVATAR 1501
+#define IDC_O_STATIC_OWNAVATAR 1502
+#define IDC_USEAERO 1531
+#define IDC_USEAEROPEEK 1532
+#define IDC_TXT_TITLE1 1617
+#define IDC_TXT_TITLE2 1618
+#define IDC_TXT_TITLE4 1620
+#define IDC_TXT_TITLE5 1622
+#define IDC_TXT_TITLE3 1623
+#define IDC_O_EXPLAINGLOBALNOTIFY 1624
+#define IDC_O_AUTOHIDE 1625
+#define IDC_O_AUTOHIDESECONDS 1626
+#define IDC_O_ENABLESOUNDS 1701
+#define IDC_O_SOUNDSMINIMIZED 1702
+#define IDC_O_SOUNDSUNFOCUSED 1703
+#define IDC_O_SOUNDSINACTIVE 1704
+#define IDC_O_SOUNDSFOCUSED 1705
+#define IDC_O_TITLEBARFORMAT 1706
+#define IDC_EDIT1 1720
+#define IDC_O_CNTPRIVATE 1901
+#define IDC_PLUS_CHECKTREE 2000
+#define IDC_COPYRIGHT 2002
+#define IDC_PLUS_HELP 2004
+#define IDC_O_HELP_TITLEFORMAT 2064
+#define IDC_OPTIONSTAB 2111
+#define IDC_HEADERBAR 2397
+#define IDC_AVATARSONTASKBAR 2735
+#define IDC_TSLABEL_EXPLAINTHEME 3123
+#define IDC_TSLABEL_REOPENWARN 3124
+#define IDD_OPT_TYPINGNOTIFYPOPUP 30159
+#define IDI_START1 30160
+#define IDI_STOP1 30161
+#define IDI_START2 30162
+#define IDI_STOP2 30163
+#define IDI_ENABLED 30164
+#define IDI_DISABLED 30165
+#define IDD_OPT 30166
+#define IDC_START 30167
+#define IDC_STOP 30168
+#define IDI_START3 30169
+#define IDI_STOP3 30170
+#define IDI_START4 30171
+#define IDI_STOP4 30172
+#define IDI_START5 30173
+#define IDI_STOP5 30174
+#define IDI_START6 30175
+#define IDI_STOP6 30176
+#define IDI_START7 30177
+#define IDI_STOP7 30178
+#define IDI_START8 30179
+#define IDI_STOP8 30180
+#define IDI_START9 30181
+#define IDI_STOP9 30182
+#define IDC_ICON1 31600
+#define IDC_ICON2 31601
+#define IDC_TIMEOUT_POPUP2 31602
+#define IDC_TIMEOUT_CUSTOM2 31603
+#define IDC_TIMEOUT_POPUP 31604
+#define IDC_TIMEOUT_PROTO 31605
+#define IDC_TIMEOUT_CUSTOM 31606
+#define IDC_TIMEOUT_VALUE 31607
+#define IDC_TIMEOUT_POPUP3 31608
+#define IDC_TIMEOUT_PERMANENT2 31608
+#define IDC_USEWINCOLORS 31609
+#define IDC_USEPOPUPCOLORS 31610
+#define IDC_TYPEON_BG 31611
+#define IDC_TYPEON_TX 31612
+#define IDC_TYPEOFF_BG 31613
+#define IDC_TYPEOFF_TX 31614
+#define IDC_INFO 31615
+#define IDC_INFO2 31616
+#define IDC_WO 31617
+#define IDC_TIMEOUT_PERMANENT1 31618
+#define IDC_TIMEOUT_PERMANENT 31618
+#define IDC_SHOWMENU 31619
+#define IDC_DISABLED 31620
+#define IDC_ONEPOPUP 31621
+#define IDC_WOCL 31622
+#define IDC_ICONS 31623
+#define IDC_TIMEOUT_VALUE2 31624
+#define IDC_PREVIEW_ALL 31625
+#define ID_CLOSETAB_DETACHTAB 40025
+#define ID_TABCONTEXT_NEXTTAB 40026
+#define ID_TABCONTEXT_ATTACH 40027
+#define ID_TABCONTEXT_CLOSECONTAINER 40028
+#define ID_TABCONTEXT_PREVTAB 40029
+#define ID_CLOSETAB 40030
+#define ID_TABMENU_CLOSETAB 40031
+#define ID_TABMENU_SAVELOCALESETTINGFORTHISCONTACT 40034
+#define ID_TABMENU_OPENWINDOWSERVICE 40035
+#define ID_TABMENU_ATTACHTOCONTAINER 40036
+#define ID_Menu 40037
+#define ID_PICMENU_TOGGLEAVATARDISPLAY 40041
+#define ID_PICMENU_SETTINGS 40042
+#define ID_LOG_CONTAINEROPTIONS 40045
+#define ID_TABMENU_CONTAINEROPTIONS 40046
+#define ID_LOGMENU_SHOWMESSAGEICONS 40056
+#define ID_LOGMENU_LOADDEFAULTS 40057
+#define ID_LOGMENU_ALWAYSUSEGLOBALSPLITTERPOSITION 40060
+#define ID_LOGMENU_TIMESTAMPSETTINGS 40061
+#define ID_LOGMENU_MESSAGELOGFORMATTING 40062
+#define ID_TABMENU_CLOSECONTAINER 40063
+#define ID_STATUSBARSETTINGS_USEGLOBALDEFAULT 40065
+#define ID_STATUSBARSETTINGS_SHOWTHESTATUSBAR 40066
+#define ID_STATUSBARSETTINGS_HIDETHESTATUSBAR 40067
+#define ID_VIEW_SHOWMENUBAR 40076
+#define ID_VIEW_SHOWSTATUSBAR 40077
+#define ID_VIEW_SHOWTOOLBAR 40078
+#define ID_TOOLBAR_SENDBUTTON 40079
+#define ID_TOOLBAR_USERINFORMATION 40080
+#define ID_TOOLBAR_EXTRABUTTONS 40081
+#define ID_VIEW_SHOWAVATAR 40082
+#define ID_VIEW_SHOWTITLEBAR 40083
+#define ID_FILE 40084
+#define ID_FILE_CLOSE 40085
+#define ID_FILE_CLOSEMESSAGESESSION 40086
+#define ID_VIEW_SHOWMULTISENDCONTACTLIST 40087
+#define ID_VIEW_TITLEBAR 40088
+#define ID_VIEW_TABSATBOTTOM 40093
+#define ID_VIEW_STAYONTOP 40095
+#define ID_HELP 40096
+#define ID_OPTIONS_EVENTPOPUPS 40097
+#define ID_EVENTPOPUPS_DISABLEALLEVENTPOPUPS 40098
+#define ID_OPTIONS_SOUNDS 40101
+#define ID_SOUNDS_DISABLEALLMESSAGESOUNDS 40102
+#define ID_SOUNDS_SYNCSOUNDSWITHEVENTPOPUPS 40103
+#define ID_SOUNDS_ENABLEALLMESSAGESOUNDS 40104
+#define ID_VIEW_FLASHING 40105
+#define ID_WINDOWFLASHING_USEDEFAULTVALUES 40106
+#define ID_WINDOWFLASHING_FLASHUNTILFOCUSED 40107
+#define ID_WINDOWFLASHING_DISABLEFLASHING 40108
+#define ID_FILE_SAVEMESSAGELOGAS 40109
+#define ID_EVENTPOPUPS_SHOWPOPUPSIFWINDOWISMINIMIZED 40110
+#define ID_EVENTPOPUPS_SHOWPOPUPSIFWINDOWISUNFOCUSED 40111
+#define ID_EVENTPOPUPS_SHOWPOPUPSFORALLINACTIVESESSIONS 40112
+#define ID_OPTIONS_SAVECURRENTWINDOWPOSITIONASDEFAULT 40113
+#define ID_CONTAINER_CONTAINEROPTIONS 40114
+#define ID_MESSAGELOG 40115
+#define ID_MESSAGELOG_LOGITEMSTOSHOW 40116
+#define ID_LOGITEMSTOSHOW_USETHINGRIDLINES 40117
+#define ID_MESSAGELOG_TIMESTAMPSETTINGS 40118
+#define ID_MESSAGELOG_MESSAGELOGFORMATTING 40119
+#define ID_EVENTPOPUPS_SHOWPOPUPSIFWINDOWISFOCUSED 40120
+#define ID_LOGMENU_MESSAGELOGSETTINGSAREGLOBAL 40124
+#define ID_USER 40125
+#define ID_TITLEBAR_USESTATICCONTAINERICON 40126
+#define ID_PICMENU_ALWAYSKEEPTHEBUTTONBARATFULLWIDTH 40134
+#define ID_SENDMENU_SENDDEFAULT 40135
+#define ID_SENDMENU_SENDTOMULTIPLEUSERS 40136
+#define ID_SENDMENU_SENDTOCONTAINER 40137
+#define ID_SENDMENU_FORCEANSISEND 40138
+#define ID_VIEW_VERTICALMAXIMIZE 40143
+#define ID_SENDMENU_SENDLATER 40144
+#define ID_PROTOMENU_SPLITTER 40145
+#define ID_MODE_GLOBAL 40148
+#define ID_MODE_PRIVATE 40150
+#define ID_UNREADMENU_TEST 40151
+#define ID_UNREADMENU_FOOBAR 40152
+#define ID_UNREADMENU_ 40153
+#define ID_TRAYCONTEXT_RECENTSESSIONS 40154
+#define ID_RECENTSESSIONS_1 40155
+#define ID_TRAYCONTEXT_FAVORITES 40156
+#define ID_FAVORITES_1 40157
+#define ID_TRAYCONTEXT_DISABLEALLPOPUPS 40158
+#define ID_TRAYCONTEXT_DON 40159
+#define ID_TRAYCONTEXT_HIDEALLMESSAGECONTAINERS 40160
+#define ID_TRAYCONTEXT_RESTOREALLMESSAGECONTAINERS 40161
+#define ID_TRAYCONTEXT_DON40223 40164
+#define ID_TRAYCONTEXT_BE 40165
+#define ID_RECENTSESSIONS_2 40166
+#define ID_PROTOMENU_SENDTEXTFORMATTING 40167
+#define ID_SENDTEXTFORMATTING_GLOBAL 40169
+#define ID_Menu40228 40170
+#define ID_VIEW_BOTTOMTOOLBAR 40171
+#define ID_GLOBAL_OFF 40172
+#define ID_SENDTEXTFORMATTING_THISCONTACT 40173
+#define ID_THISCONTACT_GLOBALSETTING 40174
+#define ID_THISCONTACT_BBCODE 40175
+#define ID_THISCONTACT_OFF 40177
+#define ID_GLOBAL_BBCODE 40178
+#define ID_PROTOMENU_FAVORITES 40179
+#define ID_FAVORITES_ADDCONTACTTOFAVORITES 40180
+#define ID_FAVORITES_REMOVECONTACTFROMFAVORITES 40181
+#define ID_FILE_HTTP 40182
+#define ID_LOG_FREEZELOG 40183
+#define ID_FONT_SIZE 40186
+#define ID_SIZE_LARGE 40187
+#define ID_SIZE_BIGGER 40188
+#define ID_SIZE_NORMAL 40189
+#define ID_SIZE_SMALLER 40190
+#define ID_SIZE_TINY 40191
+#define ID_FONT_RED 40192
+#define ID_FONT_GREEN 40193
+#define ID_FONT_BLUE 40194
+#define ID_FONT_MAGENTA 40195
+#define ID_FONT_YELLOW 40196
+#define ID_FONT_BLACK 40197
+#define ID_FONT_WHITE 40198
+#define ID_FONT_CLEARALLFORMATTING 40199
+#define ID_FONT_DEFAULTCOLOR 40200
+#define ID_FONT_CYAN 40201
+#define ID_SENDMENU_SENDWITHOUTTIMEOUTS 40201
+#define ID_DUMMY_NOMESSAGESESSIONSOPENED 40202
+#define ID_TRAYCONTEXT_SHOWTHETRAYICON 40204
+#define ID_INFOPANEL_QUICKTOGGLE 40206
+#define ID_INFOPANEL_GLOBAL 40207
+#define ID_VIEW_INFOPANEL 40208
+#define ID_GLOBAL_ENABLED 40208
+#define ID_GLOBAL_DISABLED 40209
+#define ID_INFOPANEL_THISCONTACT 40210
+#define ID_THISCONTACT_USEGLOBALSETTING 40211
+#define ID_THISCONTACT_ALWAYSON 40212
+#define ID_THISCONTACT_ALWAYSOFF 40213
+#define ID_PANELPICMENU_RESETTHEAVATAR 40218
+#define ID_EDITOR_PASTEANDSENDIMMEDIATELY 40221
+#define ID_HELP_ABOUTTABSRMM 40223
+#define ID_SENDMENU_SENDNUDGE 40228
+#define ID_SPLITTERCONTEXT_SAVEGLOBALFORALLSESSIONS 40229
+#define ID_SPLITTERCONTEXT_SAVEFORTHISCONTACTONLY 40230
+#define ID_SPLITTERCONTEXT_FORGETTHECHANGES 40231
+#define ID_SPLITTERCONTEXT_SETPOSITIONFORTHISSESSION 40232
+#define ID_FONT_CYAN40233 40233
+#define ID_TABMENU_LEAVECHATROOM 40234
+#define ID_PANELPICMENU_SAVETHISPICTUREAS 40235
+#define ID_PICMENU_SAVETHISPICTUREAS 40236
+#define ID_TABMENU_SAVETABPOSITION 40239
+#define ID_TABMENU_CLEARSAVEDTABPOSITION 40240
+#define ID_VISIBILITY_DEFAULT 40241
+#define ID_VISIBILITY_HIDDENFORTHISCONTACT 40242
+#define ID_VISIBILITY_VISIBLEFORTHISCONTACT 40243
+#define ID_LOGMENU_USEADVANCEDTEMPLATE 40244
+#define ID_MESSAGELOG_USESIMPLETEMPLATES 40246
+#define ID_EDITOR_SHOWMESSAGELENGTHINDICATOR 40248
+#define ID_LOGMENU_MESSAGELOGSETTINGS 40250
+#define ID_MESSAGELOGSETTINGS_GLOBAL 40251
+#define ID_MESSAGELOGSETTINGS_FORTHISCONTACT 40252
+#define ID_MESSAGELOG_MESSAGELOGSETTINGS 40253
+#define ID_QUEUEMANAGER_MARKSELECTEDFORREMOVAL 40256
+#define ID_QUEUEMANAGER_RESETSELECTED 40257
+#define ID_QUEUEMANAGER_HOLDSELECTED 40258
+#define ID_QUEUEMANAGER_RESUMESELECTED 40259
+#define ID_QUEUEMANAGER_CANCELALLMULTISENDJOBS 40260
+#define ID_QUEUEMANAGER_COPYMESSAGETOCLIPBOARD 40261
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 17
+#define _APS_NEXT_COMMAND_VALUE 40263
+#define _APS_NEXT_CONTROL_VALUE 1453
+#define _APS_NEXT_SYMED_VALUE 40283
+#endif
+#endif
diff --git a/plugins/TabSRMM/src/include/sendlater.h b/plugins/TabSRMM/src/include/sendlater.h
new file mode 100644
index 0000000000..a81c08f4ae
--- /dev/null
+++ b/plugins/TabSRMM/src/include/sendlater.h
@@ -0,0 +1,155 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: sendlater.h 11707 2010-05-05 13:53:11Z silvercircle $
+ *
+ * the sendlater class
+ */
+
+#ifndef __SENDLATER_H
+#define __SENDLATER_H
+
+#define TIMERID_SENDLATER 12000
+#define TIMERID_SENDLATER_TICK 13000
+
+#define TIMEOUT_SENDLATER 10000
+#define TIMEOUT_SENDLATER_TICK 200
+
+class CSendLaterJob {
+
+public:
+ /*
+ * job status/error codes
+ */
+ enum {
+ INVALID_CONTACT = 'I',
+ JOB_DEFERRED = 'D',
+ JOB_AGE = 'O',
+ JOB_MYSTATUS = 'M',
+ JOB_STATUS = 'S',
+ JOB_WAITACK = 'A',
+ JOB_REMOVABLE = 'R',
+ JOB_HOLD = 'H',
+ };
+ /*
+ * internal flags
+ */
+ enum {
+ SLF_SUSPEND = 1,
+ SLF_INVALID = 2
+ };
+ void readFlags();
+ void writeFlags();
+ void cleanDB();
+ bool isPersistentJob();
+ bool mustDelete();
+ CSendLaterJob();
+ ~CSendLaterJob();
+ char szId[20]; // database key name (time stamp of original send)
+ HANDLE hContact; // original contact where the message has been assigned
+ HANDLE hTargetContact; // *real* contact (can be different for metacontacts, e.g).
+ HANDLE hProcess; // returned from the protocols sending service. needed to find it in the ACK handler
+ time_t created; // job was created at this time (important to kill jobs, that are too old)
+ time_t lastSent; // time at which the delivery was initiated. used to handle timeouts
+ char *sendBuffer; // utf-8 send buffer
+ PBYTE pBuf; // conventional send buffer (for non-utf8 protocols)
+ DWORD dwFlags;
+ int iSendCount; // # of times we tried to send it...
+ bool fSuccess, fFailed;
+ BYTE bCode; // error/progress code (for the UI)
+};
+
+typedef std::vector<CSendLaterJob *>::iterator SendLaterJobIterator;
+
+class CSendLater {
+
+public:
+ enum {
+ SENDLATER_AGE_THRESHOLD = (86400 * 3), // 3 days, older messages will be removed from the db.
+ SENDLATER_RESEND_THRESHOLD = 180, // timeouted messages should be resent after that many seconds
+ SENDLATER_PROCESS_INTERVAL = 50 // process the list of waiting job every this many seconds
+ };
+
+ CSendLater();
+ ~CSendLater();
+ bool isAvail() const { return(m_fAvail); }
+ bool isInteractive() const { return(m_fIsInteractive); }
+ bool isJobListEmpty() const { return(m_sendLaterJobList.empty() ? true : false); }
+ bool haveErrorPopups() const { return(m_fErrorPopups); }
+ bool haveSuccessPopups() const { return(m_fSuccessPopups); }
+ void startJobListProcess();
+ time_t lastProcessed() const { return(m_last_sendlater_processed); }
+ void setLastProcessed(const time_t _t) { m_last_sendlater_processed = _t; }
+ void flushQueue() { m_last_sendlater_processed = 0; }
+ bool haveJobs() const
+ {
+ if (m_sendLaterJobList.empty() || m_jobIterator == m_sendLaterJobList.end())
+ return(false);
+ else
+ return(true);
+ }
+ bool processCurrentJob();
+ void processContacts();
+ int addJob(const char *szSetting, LPARAM lParam);
+ void addContact(const HANDLE hContact);
+ static int _cdecl addStub(const char *szSetting, LPARAM lParam);
+ HANDLE processAck(const ACKDATA *ack);
+
+ void invokeQueueMgrDlg();
+ void qMgrUpdate(bool fReEnable = false);
+ static INT_PTR svcQMgr(WPARAM wParam, LPARAM lParam);
+
+private:
+ void processSingleContact(const HANDLE hContact);
+ int sendIt(CSendLaterJob *job);
+
+ INT_PTR CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK DlgProcStub(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ void qMgrFillList(bool fClear = true);
+ void qMgrSetupColumns();
+ void qMgrSaveColumns();
+ LRESULT qMgrAddFilter(const HANDLE hContact, const TCHAR* tszNick);
+
+ std::vector<HANDLE> m_sendLaterContactList;
+ std::vector<CSendLaterJob *> m_sendLaterJobList;
+ bool m_fAvail;
+ bool m_fIsInteractive;
+ bool m_fErrorPopups;
+ bool m_fSuccessPopups;
+ time_t m_last_sendlater_processed;
+ SendLaterJobIterator m_jobIterator;
+
+ HWND m_hwndDlg;
+ HWND m_hwndList, m_hwndFilter;
+ HANDLE m_hFilter; // contact handle to filter the qmgr list (0 = no filter, show all)
+ LRESULT m_sel; // index of the combo box entry corresponding to the contact filter;
+};
+
+extern CSendLater* sendLater;
+
+#endif /* __SENDLATER_H */
diff --git a/plugins/TabSRMM/src/include/sendqueue.h b/plugins/TabSRMM/src/include/sendqueue.h
new file mode 100644
index 0000000000..8fdb8205d7
--- /dev/null
+++ b/plugins/TabSRMM/src/include/sendqueue.h
@@ -0,0 +1,123 @@
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+$Id: sendqueue.h 12065 2010-06-25 17:30:24Z silvercircle $
+
+*/
+
+#ifndef __SENDQUEUE_H
+#define __SENDQUEUE_H
+
+#define TIMERID_MSGSEND 100
+#define TIMERID_TYPE 3
+#define TIMERID_AWAYMSG 4
+//#define TIMERID_TOOLTIP 5
+#define TIMEOUT_TYPEOFF 10000 // send type off after 10 seconds of inactivity
+#define SB_CHAR_WIDTH 45
+#define SEND_FLAGS PREF_UNICODE
+
+/*
+ * send flags
+ */
+
+#define SENDJOBS_MAX_SENDS 100
+
+struct SendJob {
+ HANDLE hSendId;
+ char *sendBuffer;
+ int dwLen; // actual buffer length (checked for reallocs()
+ int iSendLength; // length of message in utf-8 octets (used to check maxlen)
+ int sendCount;
+ HANDLE hOwner;
+ HWND hwndOwner;
+ unsigned int iStatus;
+ TCHAR szErrorMsg[128];
+ DWORD dwFlags;
+ int iAcksNeeded;
+ HANDLE hEventSplit;
+ int chunkSize;
+ DWORD dwTime;
+};
+
+class SendQueue {
+public:
+ enum {
+ NR_SENDJOBS = 30,
+ SQ_ERROR = 2,
+ SQ_INPROGRESS = 1,
+ SQ_UNDEFINED = 0
+ };
+
+ SendQueue()
+ {
+ ZeroMemory(m_jobs, (sizeof(SendJob) * NR_SENDJOBS));
+ m_currentIndex = 0;
+ }
+
+ void inc() { m_currentIndex++; }
+ void dec() { m_currentIndex--; }
+
+ ~SendQueue()
+ {
+ for (int i = 0; i < NR_SENDJOBS; i++) {
+ if (m_jobs[i].sendBuffer)
+ free(m_jobs[i].sendBuffer);
+ }
+ }
+
+ SendJob *getJobByIndex(const int index) { return(&m_jobs[index]); }
+
+ void clearJob (const int index);
+ int findNextFailed (const TWindowData *dat) const;
+ void handleError (TWindowData *dat, const int iEntry) const;
+ int addTo (TWindowData *dat, const int iLen, int dwFlags);
+ int sendQueued (TWindowData *dat, const int iEntry);
+ int getSendLength (const int iEntry, const int sendMode);
+ void checkQueue (const TWindowData *dat) const;
+ void logError (const TWindowData *dat, int iSendJobIndex,
+ const TCHAR *szErrMsg) const;
+ void recallFailed (const TWindowData *dat, int iEntry) const;
+ void showErrorControls (TWindowData *dat, const int showCmd) const;
+ int ackMessage (TWindowData *dat, WPARAM wParam, LPARAM lParam);
+ int doSendLater (int iIndex, TWindowData *dat, HANDLE hContact = 0, bool fIsSendLater = true);
+ /*
+ * static members
+ */
+ static int TSAPI RTL_Detect (const wchar_t *pszwText);
+ static char* TSAPI MsgServiceName (const HANDLE hContact, const TWindowData *dat, int isUnicode);
+ static int TSAPI GetProtoIconFromList (const char *szProto, int iStatus);
+ static LRESULT TSAPI WarnPendingJobs (unsigned int uNrMessages);
+ static void TSAPI NotifyDeliveryFailure (const TWindowData *dat);
+ static void TSAPI UpdateSaveAndSendButton (TWindowData *dat);
+ static void TSAPI EnableSending (const TWindowData *dat, const int iMode);
+private:
+ SendJob m_jobs[NR_SENDJOBS];
+ int m_currentIndex;
+};
+
+extern SendQueue *sendQueue;
+
+int TSAPI ActivateExistingTab (TContainerData *pContainer, HWND hwndChild);
+void TSAPI ShowMultipleControls (const HWND hwndDlg, const UINT * controls, int cControls, int state);
+void TSAPI HandleIconFeedback (TWindowData *dat, HICON iIcon);
+
+#endif /* __SENDQUEUE_H */
diff --git a/plugins/TabSRMM/src/include/sidebar.h b/plugins/TabSRMM/src/include/sidebar.h
new file mode 100644
index 0000000000..415b96c5ac
--- /dev/null
+++ b/plugins/TabSRMM/src/include/sidebar.h
@@ -0,0 +1,239 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: sidebar.h 11744 2010-05-13 20:34:30Z silvercircle $
+ *
+ * the contact switch bar on the left (or right) side
+ *
+ */
+
+#ifndef __SIDEBAR_H
+#define __SIDEBAR_H
+
+struct TSideBarNotify {
+ NMHDR nmHdr;
+ const TWindowData* dat;
+};
+/* layout descrtiption structure */
+
+struct TSideBarLayout {
+ TCHAR szName[50]; // everything wants a name...
+ LONG width; // width of the switchbar element (a single button)
+ LONG height; // height of a single switchbar element
+ DWORD dwFlags; // flags, obviously :)
+
+ /*
+ * the following 4 items define pointers to the actual renderer functions for that sidebar layout
+ * a default is always provided, however, it has been designed to be easily extendible without
+ * rewriting lots of code just in order to change how the switchbar items look like.
+ */
+ void (__fastcall *pfnContentRenderer)(const HDC hdc, const RECT *rc, const CSideBarButton *item);
+ void (__fastcall *pfnBackgroundRenderer)(const HDC hdc, const RECT *rc, const CSideBarButton *item);
+ const SIZE& (__fastcall *pfnMeasureItem)(CSideBarButton *item);
+ void (__fastcall *pfnLayout)(const CSideBar *sideBar, RECT *rc);
+ UINT uId; // numeric id by which the layout is identified. basically, the index into the array.
+};
+
+class CSideBar;
+
+class CSideBarButton
+{
+public:
+ CSideBarButton(const UINT id, CSideBar *sideBar);
+ CSideBarButton(const TWindowData *dat, CSideBar *sideBar);
+ ~CSideBarButton();
+
+ LONG getHeight() const { return(m_sz.cy); }
+ const SIZE& getSize() const { return(m_sz); }
+ void setSize(const SIZE& newSize){ m_sz = newSize; }
+ const bool isTopAligned() const { return(m_isTopAligned); }
+ const HWND getHwnd() const { return(m_hwnd); }
+ const UINT getID() const { return(m_id); }
+ const HANDLE getContactHandle() const { return(m_dat->hContact); }
+ const TWindowData* getDat() const { return(m_dat); }
+ const TSideBarLayout* getLayout() const { return(m_sideBarLayout); }
+
+ void RenderThis (const HDC hdc) const;
+ void renderIconAndNick (const HDC hdc, const RECT *rcItem) const;
+ int testCloseButton() const;
+ void Show(const int showCmd) const;
+ void activateSession() const;
+ const SIZE& measureItem();
+ void setLayout(const TSideBarLayout *newLayout);
+ void invokeContextMenu();
+
+public:
+ CSideBar* m_sideBar;
+ const MButtonCtrl* m_buttonControl; // private data struct of the Win32 button object
+private:
+ void _create();
+private:
+ const TSideBarLayout* m_sideBarLayout;
+ HWND m_hwnd; // window handle for the TSButton object
+ const TWindowData* m_dat; // session data
+ UINT m_id; // control id
+ bool m_isTopAligned;
+ SIZE m_sz;
+};
+
+typedef std::vector<CSideBarButton *>::iterator ButtonIterator;
+
+class CSideBar
+{
+public:
+ enum {
+ NR_LAYOUTS = 4
+ };
+
+ enum {
+ /* layout ids. index into m_layouts[] */
+
+ SIDEBARLAYOUT_VERTICAL = 0,
+ SIDEBARLAYOUT_NORMAL = 1,
+ SIDEBARLAYOUT_COMPLEX = 2,
+ SIDEBARLAYOUT_LARGE = 3,
+
+ /* flags */
+
+ SIDEBARORIENTATION_LEFT = 8,
+ SIDEBARORIENTATION_RIGHT = 16,
+
+ SIDEBARLAYOUT_DYNHEIGHT = 32,
+ SIDEBARLAYOUT_VERTICALORIENTATION = 64,
+ SIDEBARLAYOUT_NOCLOSEBUTTONS = 128
+ };
+
+ enum {
+ SIDEBAR_GAP = 2 // gap between sidebar container window and content tab sheet border
+ };
+
+ CSideBar(TContainerData *pContainer);
+ ~CSideBar();
+
+ void Init (const bool fForce = false);
+ void addSession (const TWindowData *dat, int position = -1);
+ HRESULT removeSession (const TWindowData *dat);
+ void updateSession (const TWindowData *dat);
+
+ void processScrollerButtons (UINT cmd);
+ void Layout (const RECT *rc = 0, bool fOnlyCalc = false);
+ void setVisible (bool fNewVisibility);
+ void showAll (int showCmd);
+
+ const LONG getWidth() const { return(m_isVisible ? m_width + SIDEBAR_GAP : 0); }
+ const DWORD getFlags() const { return(m_dwFlags); }
+ const TContainerData* getContainer() const { return(m_pContainer); }
+ const bool isActive() const { return(m_isActive); }
+ const bool isVisible() const { return(m_isVisible); }
+ const CSideBarButton* getActiveItem() const { return(m_activeItem); }
+ const CSideBarButton* getScrollUp() const { return(m_up); }
+ const CSideBarButton* getScrollDown() const { return(m_down); }
+ bool isSkinnedContainer() const { return(CSkin::m_skinEnabled ? true : false); }
+ const UINT getLayoutId() const { return(m_uLayout); }
+ void invalidateButton (const TWindowData* dat);
+
+ const CSideBarButton* setActiveItem (const CSideBarButton *newItem)
+ {
+ CSideBarButton *oldItem = m_activeItem;
+ m_activeItem = const_cast<CSideBarButton *>(newItem);
+ if (oldItem)
+ ::InvalidateRect(oldItem->getHwnd(), NULL, FALSE);
+ ::InvalidateRect(m_activeItem->getHwnd(), NULL, FALSE);
+ scrollIntoView(m_activeItem);
+ return(oldItem);
+ }
+ /**
+ * this item has its close button currently hovered
+ * @param item: the CSideBarButton* which is hovered
+ */
+ void setHoveredClose (CSideBarButton* item)
+ {
+ m_hoveredClose = item;
+ }
+ HWND getScrollWnd() const { return(m_hwndScrollWnd); }
+ const CSideBarButton* getHoveredClose() const { return(m_hoveredClose); }
+ const CSideBarButton* setActiveItem (const TWindowData *dat);
+
+ static const TSideBarLayout* getLayouts (int& uLayoutCount)
+ {
+ uLayoutCount = NR_LAYOUTS;
+ return(m_layouts);
+ }
+ void scrollIntoView (const CSideBarButton *item = 0);
+ void resizeScrollWnd (LONG x, LONG y, LONG width, LONG height) const;
+ static LRESULT CALLBACK wndProcStub (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+private:
+ void createScroller();
+ void destroyScroller();
+ void populateAll();
+ void removeAll();
+ void Invalidate();
+ ButtonIterator findSession (const TWindowData *dat);
+ ButtonIterator findSession (const HANDLE hContact);
+
+ LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+private:
+ HWND m_hwndScrollWnd;
+ std::vector<CSideBarButton*> m_buttonlist; // our list of buttons
+ TContainerData* m_pContainer; // our master and commander...
+ LONG m_width; // required width of the bar (m_elementWidth + padding)
+ DWORD m_dwFlags;
+ CSideBarButton* m_up, *m_down; // the scroller buttons (up down)
+ CSideBarButton* m_activeItem; // active button item (for highlighting)
+ const CSideBarButton* m_hoveredClose; // item which must display an active close button
+ LONG m_topHeight, m_bottomHeight;
+ LONG m_firstVisibleOffset, m_totalItemHeight;
+ int m_iTopButtons, m_iBottomButtons;
+ LONG m_elementHeight, m_elementWidth; // width / height for a single element.
+ // can be dynamic (see measeureItem() in CSideBarButtonItem
+ bool m_isActive; // the sidebar is active (false, if it does _nothing at all_
+ bool m_isVisible; // visible aswell (not collapsed)
+ TSideBarLayout* m_currentLayout; // the layout in use. will be passed to new button items
+ UINT m_uLayout; // layout id number, currently in use
+
+private:
+ /*
+ * layouts. m_layouts[] is static and contains layout descriptions
+ * renderer functions are static aswell
+ */
+ static TSideBarLayout m_layouts[NR_LAYOUTS];
+ static void __fastcall m_DefaultBackgroundRenderer(const HDC hdc, const RECT *rc, const CSideBarButton *item);
+ static void __fastcall m_DefaultContentRenderer(const HDC hdc, const RECT *rc, const CSideBarButton *item);
+ static void __fastcall m_AdvancedContentRenderer(const HDC hdc, const RECT *rc, const CSideBarButton *item);
+
+ static const SIZE& __fastcall m_measureAdvancedVertical(CSideBarButton *item);
+};
+
+inline void CSideBarButton::setLayout(const TSideBarLayout *newLayout)
+{
+ m_sideBarLayout = newLayout;
+}
+
+#endif
diff --git a/plugins/TabSRMM/src/include/taskbar.h b/plugins/TabSRMM/src/include/taskbar.h
new file mode 100644
index 0000000000..9267f6a76a
--- /dev/null
+++ b/plugins/TabSRMM/src/include/taskbar.h
@@ -0,0 +1,197 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: taskbar.h 12227 2010-07-23 16:57:25Z silvercircle $
+ *
+ * - Windows 7 taskbar integration class
+ * - Proxy window class, needed to support custom aero peek tab
+ * thumbnails
+ * - Thumbnail classes to provide task bar thumbnails for Aero peek
+ * preview.
+ */
+
+#ifndef __TASKBAR_H
+#define __TASKBAR_H
+
+#define PROXYCLASSNAME _T("TabSRMM_DWMProxy")
+extern HINSTANCE g_hInst;
+
+class CProxyWindow;
+
+class CThumbBase {
+public:
+ CThumbBase (const CProxyWindow* pWnd);
+ virtual ~CThumbBase ();
+
+ const HBITMAP getHBM () const { return(m_hbmThumb); }
+ const bool isValid () const { return(m_isValid); }
+ virtual void setValid (const bool fNewValid) { m_isValid = fNewValid; }
+ virtual void update () = 0;
+
+protected:
+ HBITMAP m_hbmThumb, m_hbmOld;
+ const TWindowData* m_dat;
+ LONG m_width, m_height;
+ HDC m_hdc;
+ const CProxyWindow* m_pWnd;
+ RECT m_rc, m_rcTop, m_rcBottom, m_rcIcon;
+ DWORD m_dtFlags;
+ SIZE m_sz;
+ LONG m_cx, m_cy;
+ HFONT m_hOldFont;
+
+ virtual void renderBase ();
+
+private:
+ virtual void renderContent () = 0;
+ void setupRect ();
+
+private:
+ bool m_isValid;
+};
+
+class CThumbIM : public CThumbBase {
+
+public:
+ CThumbIM (const CProxyWindow* pWnd);
+ virtual ~CThumbIM () {};
+ void update ();
+
+private:
+ void renderContent ();
+};
+
+class CThumbMUC : public CThumbBase {
+
+public:
+ CThumbMUC (const CProxyWindow* pWnd);
+ virtual ~CThumbMUC () {};
+ void update ();
+
+private:
+ void renderContent ();
+};
+
+class CProxyWindow
+{
+public:
+ CProxyWindow(const TWindowData *dat);
+ ~CProxyWindow();
+
+ void updateIcon (const HICON hIcon) const;
+ void updateTitle (const TCHAR *tszTitle) const;
+ void setBigIcon (const HICON hIcon, bool fInvalidate = true);
+ void setOverlayIcon (const HICON hIcon, bool fInvalidate = true);
+ void activateTab () const;
+ void Invalidate () const;
+ const TWindowData* getDat () const { return(m_dat); }
+ const LONG getWidth () const { return(m_width); }
+ const LONG getHeight () const { return(m_height); }
+ const HWND getHwnd () const { return(m_hwndProxy); }
+ const HICON getBigIcon () const { return(m_hBigIcon); }
+ const HICON getOverlayIcon () const { return(m_hOverlayIcon); }
+ void verifyDwmState ();
+
+ static LRESULT CALLBACK stubWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static void add (TWindowData *dat);
+ static void verify (TWindowData *dat);
+
+private:
+ const TWindowData* m_dat;
+ HWND m_hwndProxy;
+ LONG m_width, m_height;
+ HICON m_hBigIcon, m_hOverlayIcon;
+
+ LRESULT CALLBACK wndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ void sendThumb (LONG width, LONG height);
+ void sendPreview ();
+ CThumbBase* m_thumb;
+};
+
+class CTaskbarInteract
+{
+public:
+ CTaskbarInteract()
+ {
+ m_pTaskbarInterface = 0;
+ m_IconSize = 0;
+ m_isEnabled = IsWinVer7Plus() ? true : false;
+
+ if (m_isEnabled) {
+ ::CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_ALL, IID_ITaskbarList3, (void**)&m_pTaskbarInterface);
+ updateMetrics();
+ if (0 == m_pTaskbarInterface)
+ m_isEnabled = false;
+ }
+
+ /*
+ * register proxy window class
+ */
+ WNDCLASSEX wcex = {0};
+ wcex.cbSize = sizeof(wcex);
+ wcex.lpfnWndProc = CProxyWindow::stubWndProc;
+ wcex.hInstance = g_hInst;
+ wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
+ wcex.lpszClassName = PROXYCLASSNAME;
+ ::RegisterClassEx(&wcex);
+ }
+
+ ~CTaskbarInteract()
+ {
+ if (m_isEnabled && m_pTaskbarInterface) {
+ m_pTaskbarInterface->Release();
+ m_pTaskbarInterface = 0;
+ m_isEnabled = false;
+ }
+ ::UnregisterClass(PROXYCLASSNAME, g_hInst);
+ }
+ const LONG getIconSize () const { return(m_IconSize); }
+ const bool haveAlwaysGroupingMode () const { return(m_fHaveAlwaysGrouping); }
+
+ bool setOverlayIcon (HWND hwndDlg, LPARAM lParam) const;
+ void clearOverlayIcon (HWND hwndDlg) const;
+ bool haveLargeIcons ();
+ LONG updateMetrics ();
+ void registerTab (const HWND hwndTab, const HWND hwndContainer) const;
+ void unRegisterTab (const HWND hwndTab) const;
+ void SetTabActive (const HWND hwndTab, const HWND hwndGroup) const;
+
+ //const TCHAR* getFileNameFromWindow (const HWND hWnd);
+private:
+ bool m_isEnabled;
+ ITaskbarList3* m_pTaskbarInterface;
+ bool m_fHaveLargeicons;
+ bool m_fHaveAlwaysGrouping;
+ LONG m_IconSize;
+};
+
+extern CTaskbarInteract* Win7Taskbar;
+
+#endif /* __TASKBAR_H */
+
diff --git a/plugins/TabSRMM/src/include/templates.h b/plugins/TabSRMM/src/include/templates.h
new file mode 100644
index 0000000000..c2b84b1cbd
--- /dev/null
+++ b/plugins/TabSRMM/src/include/templates.h
@@ -0,0 +1,50 @@
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2003 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.
+
+$Id: templates.h 11044 2009-12-11 09:16:30Z silvercircle $
+
+templates for the message log...
+
+*/
+
+struct TemplateEditorInfo {
+ BOOL rtl;
+ BOOL changed; // template in edit field is changed
+ BOOL selchanging;
+ int inEdit; // template currently in editor
+ BOOL updateInfo[TMPL_ERRMSG + 1]; // item states...
+ HWND hwndParent;
+ HANDLE hContact;
+};
+
+struct TemplateEditorNew {
+ HANDLE hContact;
+ BOOL rtl;
+ HWND hwndParent;
+};
+
+BOOL CALLBACK DlgProcTemplateEdit(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+static void LoadTemplatesFrom(TTemplateSet *tSet, HANDLE hContact, int rtl);
+void LoadDefaultTemplates();
+
+#define DM_UPDATETEMPLATEPREVIEW (WM_USER + 50)
+
diff --git a/plugins/TabSRMM/src/include/themes.h b/plugins/TabSRMM/src/include/themes.h
new file mode 100644
index 0000000000..ca899ffdb7
--- /dev/null
+++ b/plugins/TabSRMM/src/include/themes.h
@@ -0,0 +1,415 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: themes.h 11997 2010-06-14 20:12:34Z silvercircle $
+ *
+ * The class CSkin implements the skinning engine and loads skins from
+ * their skin definition files (.tsk).
+ *
+ * CImageItem implements a single rectangular skin item with an image
+ * and its rendering.
+ *
+ */
+
+#ifndef __THEMES_H
+#define __THEMES_H
+
+HBITMAP IMG_LoadLogo(const TCHAR *szName);
+
+class CSideBarButton;
+
+typedef struct {
+ HWND hwnd;
+ int stateId; // button state
+ int focus; // has focus (1 or 0)
+ HFONT hFont; // font
+ HICON arrow; // uses down arrow
+ int defbutton; // default button
+ HICON hIcon, hIconPrivate;
+ HBITMAP hBitmap;
+ int pushBtn;
+ int pbState;
+ HANDLE hThemeButton;
+ HANDLE hThemeToolbar;
+ BOOL bThemed;
+ BOOL bToolbarButton; // is a toolbar button (important for aero background rendering)
+ BOOL bTitleButton;
+ TCHAR cHot;
+ int flatBtn;
+ int dimmed;
+ HICON overlay;
+ struct TContainerData *pContainer;
+ CSideBarButton *sitem;
+} MButtonCtrl;
+
+#define BUTTONSETASDIMMED (BUTTONSETASFLATBTN + 11)
+#define BUTTONSETCONTAINER (BUTTONSETASFLATBTN + 12)
+#define BUTTONSETASTITLE (BUTTONSETASFLATBTN + 13)
+#define BUTTONSETASNORMAL (BUTTONSETASFLATBTN + 14)
+#define BUTTONGETSTATEID (BUTTONSETASFLATBTN + 15)
+#define BUTTONSETASTOOLBARBUTTON (BUTTONSETASFLATBTN + 21)
+#define BUTTONSETASSIDEBARBUTTON (BUTTONSETASFLATBTN + 22)
+#define BUTTONSETOVERLAYICON (BUTTONSETASFLATBTN + 23)
+
+struct AeroEffect {
+ TCHAR tszName[40];
+ DWORD m_baseColor;
+ DWORD m_gradientColor;
+ BYTE m_baseAlpha;
+ BYTE m_finalAlpha;
+ BYTE m_cornerType;
+ BYTE m_gradientType;
+ DWORD m_cornerRadius;
+ DWORD m_glowSize;
+ COLORREF m_clrBack;
+ COLORREF m_clrToolbar;
+ COLORREF m_clrToolbar2;
+ void (TSAPI *pfnEffectRenderer)(const HDC hdc, const RECT *rc, int iEffectArea);
+};
+/**
+ * CImageItem implementes image-based skin items. These items are loaded
+ * from a skin file definition (.tsk file) and are then linked to one or
+ * more skin items.
+ */
+class CImageItem
+{
+public:
+ CImageItem()
+ {
+ ZeroMemory(this, sizeof(CImageItem));
+ }
+ CImageItem(const CImageItem& From)
+ {
+ *this = From;
+ m_nextItem = 0;
+ }
+ CImageItem(const TCHAR *szName)
+ {
+ ZeroMemory(this, sizeof(CImageItem));
+ _sntprintf(m_szName, 40, szName);
+ m_szName[39] = 0;
+ }
+
+ CImageItem(BYTE bottom, BYTE left, BYTE top, BYTE right, HDC hdc, HBITMAP hbm, DWORD dwFlags,
+ HBRUSH brush, BYTE alpha, LONG inner_height, LONG inner_width, LONG height, LONG width)
+ {
+ m_bBottom = bottom;
+ m_bLeft = left,
+ m_bTop = top;
+ m_bRight = right;
+ m_hdc = hdc;
+ m_hbm = hbm;
+ m_dwFlags = dwFlags;
+ m_fillBrush = brush;
+ m_inner_height = inner_height;
+ m_inner_width = inner_width;
+ m_height = height;
+ m_width = width;
+
+ m_bf.SourceConstantAlpha = alpha;
+ m_bf.AlphaFormat = 0;
+ m_bf.BlendOp = AC_SRC_OVER;
+ m_bf.BlendFlags = 0;
+ }
+ ~CImageItem()
+ {
+ Free();
+ }
+
+ void Clear()
+ {
+ m_hdc = 0; m_hbm = 0; m_hbmOld = 0;
+ m_fillBrush = (HBRUSH)0;
+ }
+
+ void setBitmap(const HBITMAP hbm)
+ {
+ m_hbm = hbm;
+ }
+
+ void setAlphaFormat(const BYTE bFormat, const BYTE bConstantAlpha)
+ {
+ m_bf.AlphaFormat = bFormat;
+ m_bf.SourceConstantAlpha = bConstantAlpha;
+ }
+
+ void setMetrics(const LONG width, const LONG height)
+ {
+ m_height = height;
+ m_width = width;
+
+ m_inner_height = m_height - m_bBottom - m_bTop;
+ m_inner_width = m_width - m_bLeft - m_bRight;
+ if (!(m_dwFlags & IMAGE_FLAG_DIVIDED))
+ m_bStretch = IMAGE_STRETCH_B;
+ }
+
+ void Free();
+ CImageItem* getNextItem() const { return(m_nextItem); }
+ void setNextItem(CImageItem *item) { m_nextItem = item; }
+ HBITMAP getHbm() const { return(m_hbm); }
+ DWORD getFlags() const { return(m_dwFlags); }
+ HDC getDC() const { return(m_hdc); }
+ const BLENDFUNCTION& getBF() const
+ {
+ const BLENDFUNCTION &bf = m_bf;
+ return(bf);
+ }
+ const TCHAR* getName() const { return (m_szName); }
+ TCHAR* Read(const TCHAR *szFilename);
+ void Create(const TCHAR *szImageFile);
+ void __fastcall Render(const HDC hdc, const RECT *rc, bool fIgnoreGlyph) const;
+ static void TSAPI PreMultiply(HBITMAP hBitmap, int mode);
+ static void TSAPI SetBitmap32Alpha(HBITMAP hBitmap, BYTE bAlpha = 255);
+ static void TSAPI Colorize(HBITMAP hBitmap, BYTE dr, BYTE dg, BYTE db, BYTE alpha = 0);
+ static HBITMAP TSAPI LoadPNG(const TCHAR *szFilename);
+
+public:
+ bool m_fValid; // verified item, indicates that all parameters are valid
+private:
+ TCHAR m_szName[40]; // everything wants a name, an image item doesn't need one though
+ HBITMAP m_hbm; // the bitmap handle
+ BYTE m_bLeft, m_bRight, m_bTop, m_bBottom; // sizing margins for the outer 8 image parts
+ BYTE m_alpha; // constant alpha for the entire image, applied via m_bf. sums with perpixel alpha
+ DWORD m_dwFlags; // flags
+ HDC m_hdc; // *can* hold a pre-created hdc to speed up rendering
+ HBITMAP m_hbmOld; // old bitmap, needs to be selected into m_hdc before destroying it
+ LONG m_inner_height, m_inner_width; // dimensions of the inner image part
+ LONG m_width, m_height; // width and height of the image, in pixels
+ BLENDFUNCTION m_bf; // for AlphaBlend()
+ BYTE m_bStretch; // stretch mode (unused in tabSRMM
+ HBRUSH m_fillBrush; // brush to fill the inner part (faster) dwFlags & IMAGE_FILLSOLID must be set
+ LONG m_glyphMetrics[4]; // these coordinates point into the glyph image (if IMAGE_GLYPH is set)
+ CImageItem* m_nextItem; // next item in a set of image items (usually the skin set)
+};
+
+/**
+ * Implements the skinning engine. There is only one instance of this class and
+ * it always holds the currently loaded skin (if any).
+ */
+class CSkin
+{
+public:
+ enum {
+ AERO_EFFECT_NONE = 0,
+ AERO_EFFECT_MILK = 1,
+ AERO_EFFECT_CARBON = 2,
+ AERO_EFFECT_SOLID = 3,
+ AERO_EFFECT_WHITE = 4,
+ AERO_EFFECT_CUSTOM = 5,
+ AERO_EFFECT_LAST = 6
+ };
+ enum {
+ AERO_EFFECT_AREA_MENUBAR = 0,
+ AERO_EFFECT_AREA_STATUSBAR = 1,
+ AERO_EFFECT_AREA_INFOPANEL = 2,
+ AERO_EFFECT_AREA_TAB_ACTIVE = 3,
+ AERO_EFFECT_AREA_TAB_HOVER = 4,
+ AERO_EFFECT_AREA_TAB_NORMAL = 5,
+ AERO_EFFECT_AREA_SIDEBAR_LEFT = 6,
+ AERO_EFFECT_AREA_SIDEBAR_RIGHT = 7,
+ AERO_EFFECT_AREA_TAB_TOP = 0x1000,
+ AERO_EFFECT_AREA_TAB_BOTTOM = 0x2000
+ };
+
+ enum {
+ DEFAULT_GLOW_SIZE = 10
+ };
+
+ /*
+ * avatar border types (skinned mode only)
+ */
+ enum {
+ AVBORDER_NONE = 0,
+ AVBORDER_NORMAL = 1,
+ AVBORDER_ROUNDED = 2
+ };
+
+ CSkin()
+ {
+ ZeroMemory(this, sizeof(CSkin));
+ m_default_bf.SourceConstantAlpha = 255;
+ m_default_bf.AlphaFormat = AC_SRC_ALPHA;
+ m_default_bf.BlendOp = AC_SRC_OVER;
+ }
+
+ ~CSkin()
+ {
+ Unload();
+ }
+
+ void Init(bool fStartup = false);
+ void Load(void);
+ void Unload();
+ void UnloadAeroTabs();
+ void setFileName();
+ void ReadItem(const int id, const TCHAR *section);
+ void LoadItems();
+ void LoadIcon(const TCHAR *szSection, const TCHAR *name, HICON *hIcon);
+ void ReadImageItem(const TCHAR *szItemName);
+ void ReadButtonItem(const TCHAR *itemName) const;
+ bool haveGlyphItem() const { return(m_fHaveGlyph); }
+ int getNrIcons() const { return(m_nrSkinIcons); }
+ const DWORD getDwmColor() const { return(m_dwmColor); }
+
+ const TIconDescW* getIconDesc(const int id) const { return(&m_skinIcons[id]); }
+ /**
+ * get the glyph image item (a single PNG image, containing a number of textures
+ * for the skin.
+ *
+ * @return CImageItem&: reference to the glyph item. Cannot be
+ * modified.
+ *
+ */
+ const CImageItem* getGlyphItem() const
+ {
+ return(m_fHaveGlyph ? &m_glyphItem : 0);
+ }
+ bool warnToClose() const;
+ COLORREF getColorKey() const { return(m_ContainerColorKey); }
+
+ void setupAeroSkins();
+ void extractSkinsAndLogo(bool fForceOverwrite = false) const;
+ void setupTabCloseBitmap(bool fDeleteOnly = false);
+
+ /*
+ * static member functions
+ */
+ static void TSAPI SkinDrawBGFromDC(HWND hwndClient, HWND hwnd, RECT *rcClient, HDC hdcTarget);
+ static void TSAPI SkinDrawBG(HWND hwndClient, HWND hwnd, struct TContainerData *pContainer, RECT *rcClient, HDC hdcTarget);
+ static void TSAPI MY_AlphaBlend(HDC hdcDraw, DWORD left, DWORD top, int width, int height, int bmWidth, int bmHeight, HDC hdcMem);
+ static void TSAPI DrawDimmedIcon(HDC hdc, LONG left, LONG top, LONG dx, LONG dy, HICON hIcon, BYTE alpha);
+ static DWORD __fastcall HexStringToLong(const TCHAR *szSource);
+ static UINT TSAPI DrawRichEditFrame(HWND hwnd, const TWindowData *mwdat, UINT skinID, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC OldWndProc);
+ static UINT TSAPI NcCalcRichEditFrame(HWND hwnd, const TWindowData *mwdat, UINT skinID, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC OldWndProc);
+ static HBITMAP TSAPI CreateAeroCompatibleBitmap(const RECT &rc, HDC dc);
+ static int TSAPI RenderText(HDC hdc, HANDLE hTheme, const TCHAR *szText, RECT *rc, DWORD dtFlags, const int iGlowSize = DEFAULT_GLOW_SIZE, COLORREF clr = 0, bool fForceAero = false);
+ static void TSAPI MapClientToParent(HWND hwndClient, HWND hwndParent, RECT &rc);
+ static void TSAPI RenderToolbarBG(const TWindowData *dat, HDC hdc, const RECT &rcWindow);
+ static HBITMAP TSAPI ResizeBitmap(HBITMAP hBmpSrc, LONG width, LONG height, bool &mustFree);
+ static void TSAPI ApplyAeroEffect(const HDC hdc, const RECT* rc, int iEffectArea, HANDLE hbp = 0);
+ static void TSAPI setAeroEffect(const LRESULT effect);
+ static void TSAPI initAeroEffect();
+ static HANDLE TSAPI InitiateBufferedPaint(const HDC hdcSrc, RECT& rc, HDC& hdcOut);
+ static void TSAPI FinalizeBufferedPaint(HANDLE hbp, RECT *rc);
+ static bool __fastcall DrawItem(const HDC hdc, const RECT *rc, const CSkinItem *item);
+ static void TSAPI UpdateToolbarBG(TWindowData* dat, DWORD dwRdwOptFlags = 0);
+ static void TSAPI FillBack(const HDC hdc, RECT* rc);
+
+public:
+ static bool m_DisableScrollbars, m_bClipBorder;
+ static char m_SkinnedFrame_left, m_SkinnedFrame_right, m_SkinnedFrame_bottom, m_SkinnedFrame_caption;
+ static char m_realSkinnedFrame_left, m_realSkinnedFrame_right, m_realSkinnedFrame_bottom, m_realSkinnedFrame_caption;
+ static HPEN m_SkinLightShadowPen, m_SkinDarkShadowPen;
+ static int m_titleBarLeftOff, m_titleButtonTopOff, m_captionOffset, m_captionPadding,
+ m_titleBarRightOff, m_sidebarTopOffset, m_sidebarBottomOffset, m_bRoundedCorner;
+ static SIZE m_titleBarButtonSize;
+ static int m_bAvatarBorderType;
+ static COLORREF m_avatarBorderClr, m_tmp_tb_low, m_tmp_tb_high;
+ static COLORREF m_sideBarContainerBG;
+ static COLORREF m_ContainerColorKey, m_DefaultFontColor;
+ static HBRUSH m_ContainerColorKeyBrush, m_MenuBGBrush;
+ static bool m_skinEnabled;
+ static bool m_frameSkins;
+ static HICON m_closeIcon, m_minIcon, m_maxIcon;
+ static BLENDFUNCTION m_default_bf; // general purpose bf, dynamically modified when needed
+
+ /*
+ * cached bitmap for tab close button
+ */
+
+ static HBITMAP m_tabCloseBitmap, m_tabCloseOldBitmap;
+ static HDC m_tabCloseHDC;
+
+ /*
+ * controls the aero effect. Set by initAeroEffect()
+ */
+
+ static UINT m_aeroEffect; // effect id, initAeroEffect() is using it to set
+ // the parameters below.
+ static AeroEffect m_aeroEffects[AERO_EFFECT_LAST];
+ static AeroEffect m_currentAeroEffect;
+ static AeroEffect* m_pCurrentAeroEffect;
+ static DWORD m_glowSize;
+ static HBRUSH m_BrushBack, m_BrushFill;
+
+ static COLORREF m_dwmColorRGB;
+
+ static CImageItem *m_switchBarItem, *m_tabTop, *m_tabBottom, *m_tabGlowTop, *m_tabGlowBottom;
+ static bool m_fAeroSkinsValid;
+
+private:
+ TCHAR m_tszFileName[MAX_PATH]; // full path and filename of the currently loaded skin
+ CSkinItem* m_SkinItems;
+ CImageItem* m_ImageItems; // the list of image item objects
+ CImageItem m_glyphItem;
+
+ bool m_fLoadOnStartup; // load the skin on plugin initialization.
+ bool m_fHaveGlyph;
+ void SkinCalcFrameWidth();
+ TIconDescW *m_skinIcons;
+ int m_nrSkinIcons;
+ DWORD m_dwmColor;
+
+private:
+ static void TSAPI AeroEffectCallback_Milk(const HDC hdc, const RECT *rc, int iEffectArea);
+ static void TSAPI AeroEffectCallback_Carbon(const HDC hdc, const RECT *rc, int iEffectArea);
+ static void TSAPI AeroEffectCallback_Solid(const HDC hdc, const RECT *rc, int iEffectArea);
+};
+
+/*
+ * window data for the tab control window class
+ */
+
+struct TabControlData {
+ BOOL m_VisualStyles;
+ HWND hwnd;
+ DWORD dwStyle;
+ DWORD cx, cy;
+ HANDLE hTheme, hThemeButton, hbp;
+ BYTE m_xpad;
+ TContainerData *pContainer;
+ BOOL bDragging;
+ int iBeginIndex;
+ int iHoveredCloseIcon;
+ HWND hwndDrag;
+ TWindowData *dragDat;
+ HIMAGELIST himlDrag;
+ BOOL bRefreshWithoutClip;
+ BOOL fSavePos;
+ BOOL fTipActive;
+ BOOL fAeroTabs;
+ BOOL fCloseButton;
+ TWindowData* helperDat; // points to the client data of the active tab
+ CImageItem* helperItem, *helperGlowItem; // aero ui, holding the skin image for the tabs
+};
+
+extern CSkin *Skin;
+
+#endif /* __THEMES_H */
+
diff --git a/plugins/TabSRMM/src/include/translator.h b/plugins/TabSRMM/src/include/translator.h
new file mode 100644
index 0000000000..61590c6b16
--- /dev/null
+++ b/plugins/TabSRMM/src/include/translator.h
@@ -0,0 +1,63 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: translator.h 12299 2010-08-10 02:39:36Z silvercircle $
+ *
+ * string handling
+ *
+ */
+
+#ifndef __STRINGS_H
+#define __STRINGS_H
+
+class CTranslator {
+
+public:
+
+ /*
+ * identities for the option trees
+ */
+
+ enum {
+ TREE_MODPLUS = 0,
+ TREE_NEN = 1,
+ TREE_MSG = 2,
+ TREE_LOG = 3,
+ TREE_TAB = 4,
+ };
+
+ CTranslator();
+ ~CTranslator();
+
+ static TOptionListItem* getTree(UINT id);
+ static TOptionListGroup* getGroupTree(UINT id);
+};
+
+#endif
+
+
diff --git a/plugins/TabSRMM/src/include/typingnotify.h b/plugins/TabSRMM/src/include/typingnotify.h
new file mode 100644
index 0000000000..03fb9851b7
--- /dev/null
+++ b/plugins/TabSRMM/src/include/typingnotify.h
@@ -0,0 +1,76 @@
+#define UM_SETDLGITEMINT 5674
+
+#define TIMEOUT_MINVALUE -1
+#define TIMEOUT_MAXVALUE 99
+#define TIMEOUT_POPUP 1
+#define TIMEOUT_CUSTOM 2
+#define TIMEOUT_PROTO 3
+#define TIMEOUT_PERMANENT 4
+#define COLOR_OWN 1
+#define COLOR_WINDOWS 2
+#define COLOR_POPUP 3
+
+#define Module "TypingNotify"
+
+#define SET_WO "NotWhenFocused"
+#define DEF_WO 0
+#define SET_DISABLED "Disabled"
+#define DEF_DISABLED 0
+#define SET_TIMEOUT "Timeout"
+#define DEF_TIMEOUT 7
+#define SET_TIMEOUT2 "Timeout2"
+#define DEF_TIMEOUT2 7
+#define SET_TIMEOUT_MODE "TimeoutMode"
+#define DEF_TIMEOUT_MODE TIMEOUT_POPUP
+#define SET_TIMEOUT_MODE2 "TimeoutMode2"
+#define DEF_TIMEOUT_MODE2 TIMEOUT_POPUP
+#define SET_COLOR_MODE "ColorMode"
+#define DEF_COLOR_MODE COLOR_OWN
+#define SET_ICON_SETID "IconSet"
+#define DEF_ICON_SETID 0
+#define SET_SHOWDISABLEMENU "ShowDisableMenu"
+#define DEF_SHOWDISABLEMENU 1
+#define SET_ONEPOPUP "OnePopUp"
+#define DEF_ONEPOPUP 1
+
+
+static HANDLE hDisableMenu = NULL;
+static HANDLE hPopUpsList = NULL;
+
+static BYTE OnePopUp;
+static BYTE ShowMenu;
+static BYTE PopupService=0;
+static BYTE StartDisabled;
+static BYTE StopDisabled;
+static BYTE Disabled;
+static BYTE ColorMode;
+static BYTE TimeoutMode;
+static BYTE TimeoutMode2;
+static int Timeout;
+static int Timeout2;
+static int newTimeout;
+static int newTimeout2;
+static BYTE newTimeoutMode;
+static BYTE newTimeoutMode2;
+static BYTE newColorMode;
+static TCHAR szStart[128];
+static TCHAR szStop[128];
+
+static HANDLE hntfStarted = 0;
+static HANDLE hntfStopped = 0;
+
+
+struct colors_s
+{
+ int res;
+ char desc[10];
+ COLORREF color;
+};
+
+static struct colors_s colorPicker[4] =
+{
+ {IDC_TYPEON_BG, "ON_BG", RGB(255,255,255)},
+ {IDC_TYPEON_TX, "ON_TX", RGB(0,0,0)},
+ {IDC_TYPEOFF_BG, "OFF_BG", RGB(255,255,255)},
+ {IDC_TYPEOFF_TX, "OFF_TX", RGB(0,0,0)}
+};
diff --git a/plugins/TabSRMM/src/include/utils.h b/plugins/TabSRMM/src/include/utils.h
new file mode 100644
index 0000000000..b2f2dab659
--- /dev/null
+++ b/plugins/TabSRMM/src/include/utils.h
@@ -0,0 +1,268 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: utils.h 12833 2010-09-27 23:45:55Z silvercircle $
+ *
+ * utility functions for TabSRMM
+ *
+ */
+
+#ifndef __UTILS_H
+#define __UTILS_H
+
+#define RTF_CTABLE_DEFSIZE 8
+
+#define RTF_DEFAULT_HEADER _T("{\\rtf1\\ansi\\deff0\\pard\\li%u\\fi-%u\\ri%u\\tx%u")
+
+#define CNT_KEYNAME "CNTW_Def"
+#define CNT_BASEKEYNAME "CNTW_"
+
+struct TRTFColorTable {
+ TCHAR szName[10];
+ COLORREF clr;
+ int index;
+ int menuid;
+};
+
+static TRTFColorTable _rtf_ctable[] = {
+ _T("red"), RGB(255, 0, 0), 0, ID_FONT_RED,
+ _T("blue"), RGB(0, 0, 255), 0, ID_FONT_BLUE,
+ _T("green"), RGB(0, 255, 0), 0, ID_FONT_GREEN,
+ _T("magenta"), RGB(255, 0, 255), 0, ID_FONT_MAGENTA,
+ _T("yellow"), RGB(255, 255, 0), 0, ID_FONT_YELLOW,
+ _T("cyan"), RGB(0, 255, 255), 0, ID_FONT_CYAN,
+ _T("black"), 0, 0, ID_FONT_BLACK,
+ _T("white"), RGB(255, 255, 255), 0, ID_FONT_WHITE,
+ _T(""), 0, 0, 0
+};
+
+class Utils {
+
+public:
+ enum {
+ CMD_CONTAINER = 1,
+ CMD_MSGDIALOG = 2,
+ CMD_INFOPANEL = 4,
+ };
+ static int TSAPI FindRTLLocale (TWindowData *dat);
+ static TCHAR* TSAPI GetPreviewWithEllipsis (TCHAR *szText, size_t iMaxLen);
+ static TCHAR* TSAPI FilterEventMarkers (TCHAR *wszText);
+ static const TCHAR* TSAPI FormatRaw (TWindowData *dat, const TCHAR *msg, int flags, BOOL isSent);
+ static const TCHAR* TSAPI FormatTitleBar (const TWindowData *dat, const TCHAR *szFormat);
+ static char* TSAPI FilterEventMarkers (char *szText);
+ static const TCHAR* TSAPI DoubleAmpersands (TCHAR *pszText);
+ static void TSAPI RTF_CTableInit ();
+ static void TSAPI RTF_ColorAdd (const TCHAR *tszColname, size_t length);
+ static void TSAPI CreateColorMap (TCHAR *Text);
+ static int TSAPI RTFColorToIndex (int iCol);
+ static int TSAPI ReadContainerSettingsFromDB (const HANDLE hContact, TContainerSettings *cs, const char *szKey = 0);
+ static int TSAPI WriteContainerSettingsToDB (const HANDLE hContact, TContainerSettings *cs, const char *szKey = 0);
+ static void TSAPI SettingsToContainer (TContainerData *pContainer);
+ static void TSAPI ContainerToSettings (TContainerData *pContainer);
+ static void TSAPI ReadPrivateContainerSettings (TContainerData *pContainer, bool fForce = false);
+ static void TSAPI SaveContainerSettings (TContainerData *pContainer, const char *szSetting);
+ static DWORD CALLBACK StreamOut (DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb);
+ static LRESULT TSAPI CmdDispatcher (UINT uType, HWND hwndDlg, UINT cmd, WPARAM wParam, LPARAM lParam, TWindowData *dat = 0,
+ TContainerData *pContainer = 0);
+ static void TSAPI addMenuItem (const HMENU& m, MENUITEMINFO& mii, HICON hIcon,
+ const TCHAR *szText, UINT uID, UINT pos);
+ static void TSAPI enableDlgControl (const HWND hwnd, UINT id, BOOL fEnable = 1);
+ static void TSAPI showDlgControl (const HWND hwnd, UINT id, int showCmd);
+ static int TSAPI mustPlaySound (const TWindowData *dat);
+ static HICON TSAPI iconFromAvatar (const TWindowData *dat);
+ static void TSAPI getIconSize (HICON hIcon, int& sizeX, int& sizeY);
+
+ static void TSAPI extractResource (const HMODULE h, const UINT uID, const TCHAR *tszName, const TCHAR *tszPath,
+ const TCHAR *tszFilename, bool fForceOverwrite);
+ static void TSAPI scaleAvatarHeightLimited (const HBITMAP hBm, double& dNewWidth, double& dNewHeight, const LONG maxHeight);
+
+ static AVATARCACHEENTRY* TSAPI loadAvatarFromAVS (const HANDLE hContact);
+ static void TSAPI sanitizeFilename (wchar_t *tszFilename);
+ static void TSAPI ensureTralingBackslash (wchar_t *szPathname);
+
+ static void* TSAPI safeAlloc (const size_t size);
+ static void* TSAPI safeCalloc (const size_t size);
+ static void* TSAPI safeMirAlloc (const size_t size);
+ static void* TSAPI safeMirCalloc (const size_t size);
+
+ static HMODULE TSAPI loadSystemLibrary (const wchar_t* szFilename);
+
+ static INT_PTR CALLBACK PopupDlgProcError (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+ static const TCHAR* extractURLFromRichEdit (const ENLINK* _e, const HWND hwndRich);
+
+ template<typename T> static size_t TSAPI CopyToClipBoard(T* _t, const HWND hwndOwner)
+ {
+ HGLOBAL hData;
+
+ if (!OpenClipboard(hwndOwner) || _t == 0)
+ return 0;
+
+ std::basic_string<T> *s = new std::basic_string<T>(_t);
+ size_t _s = sizeof(T);
+ size_t i = _s * (s->length() + 1);
+
+ EmptyClipboard();
+ hData = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, i);
+
+ CopyMemory((void *)GlobalLock(hData), (void *)_t, i);
+ GlobalUnlock(hData);
+ SetClipboardData(_s == sizeof(char) ? CF_TEXT : CF_UNICODETEXT, hData);
+ CloseClipboard();
+ delete s;
+ return(i);
+ }
+
+ template<typename T> static void AddToFileList(T ***pppFiles, int *totalCount, const TCHAR* szFilename)
+ {
+ size_t _s = sizeof(T);
+
+ *pppFiles = (T**)mir_realloc(*pppFiles, (++*totalCount + 1) * sizeof(T*));
+ (*pppFiles)[*totalCount] = NULL;
+
+ if (_s == 1)
+ (*pppFiles)[*totalCount-1] = reinterpret_cast<T *>(mir_t2a(szFilename));
+ else
+ (*pppFiles)[*totalCount-1] = reinterpret_cast<T *>(mir_tstrdup(szFilename));
+
+ if (GetFileAttributes(szFilename) & FILE_ATTRIBUTE_DIRECTORY) {
+ WIN32_FIND_DATA fd;
+ HANDLE hFind;
+ TCHAR szPath[MAX_PATH];
+
+ lstrcpy(szPath, szFilename);
+ lstrcat(szPath, _T("\\*"));
+ if ((hFind = FindFirstFile(szPath, &fd)) != INVALID_HANDLE_VALUE) {
+ do {
+ if (!lstrcmp(fd.cFileName, _T(".")) || !lstrcmp(fd.cFileName, _T("..")))
+ continue;
+ lstrcpy(szPath, szFilename);
+ lstrcat(szPath, _T("\\"));
+ lstrcat(szPath, fd.cFileName);
+ AddToFileList(pppFiles, totalCount, szPath);
+ } while (FindNextFile(hFind, &fd));
+ FindClose(hFind);
+ }
+ }
+ }
+
+ /**
+ * safe strlen function - do not overflow the given buffer length
+ * if the buffer does not contain a valid (zero-terminated) string, it
+ * will return 0.
+ *
+ * careful: maxlen must be given in element counts!!
+ */
+ template<typename T> static size_t safe_strlen(const T* src, const size_t maxlen = 0)
+ {
+ size_t s = 0;
+
+ while(s < maxlen && *(src++))
+ s++;
+
+ if (s >= maxlen && *src != 0)
+ return 0;
+ else
+ return(s);
+ }
+
+public:
+ static TRTFColorTable* rtf_ctable;
+ static int rtf_ctable_size;
+};
+
+LRESULT TSAPI _dlgReturn(HWND hWnd, LRESULT result);
+
+
+
+/**
+ * implement a warning dialog with a "do not show this again" check
+ * box
+ */
+
+class CWarning {
+
+public:
+ /*
+ * the warning IDs
+ */
+ enum {
+ WARN_RELNOTES = 0,
+ WARN_ICONPACK_VERSION = 1,
+ WARN_EDITUSERNOTES = 2,
+ WARN_ICONPACKMISSING = 3,
+ WARN_AEROPEEK_SKIN = 4,
+ WARN_CHAT_ENABLED = 5,
+ WARN_SENDFILE = 6,
+ WARN_HPP_APICHECK = 7,
+ WARN_NO_SENDLATER = 8,
+ WARN_CLOSEWINDOW = 9,
+ WARN_OPTION_CLOSE = 10,
+ WARN_THEME_OVERWRITE = 11,
+ WARN_LAST = 12
+ };
+
+ /*
+ * the flags (low word is reserved for default windows flags like MB_OK etc.
+ */
+
+ enum {
+ CWF_UNTRANSLATED = 0x00010000, // do not translate the msg (useful for some error messages)
+ CWF_NOALLOWHIDE = 0x00020000 // critical message, hide the "do not show this again" check box
+ };
+
+ CWarning(const wchar_t* tszTitle, const wchar_t* tszText, const UINT uId, const DWORD dwFlags);
+ ~CWarning();
+
+public:
+ /*
+ * static function to construct and show the dialog, returns the
+ * user's choice
+ */
+ static LRESULT show (const int uId, DWORD dwFlags = 0, const wchar_t* tszTxt = 0);
+ static void destroyAll ();
+ LRESULT ShowDialog () const;
+
+private:
+ std::basic_string<wchar_t>* m_szTitle;
+ std::basic_string<wchar_t>* m_szText;
+ UINT m_uId;
+ HFONT m_hFontCaption;
+ DWORD m_dwFlags;
+ HWND m_hwnd;
+ bool m_fIsModal;
+
+ INT_PTR CALLBACK dlgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ //void resize () const;
+ static INT_PTR CALLBACK stubDlgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static __int64 getMask (); // get bit mask for disabled message classes
+
+private:
+ static HANDLE hWindowList;
+};
+
+#endif /* __UTILS_H */
diff --git a/plugins/TabSRMM/src/include/version.h b/plugins/TabSRMM/src/include/version.h
new file mode 100644
index 0000000000..4390ed33dc
--- /dev/null
+++ b/plugins/TabSRMM/src/include/version.h
@@ -0,0 +1,15 @@
+#define VER_PLAIN "3,1,99,8"
+#define _VER_MAJOR 3
+#define _VER_MINOR 1
+#define _VER_REVISION 99
+#define _VER_BUILD 8
+
+#if defined(_WIN64)
+ #define RES_FILE_DESC "TabSRMM (Unicode) x86_amd64"
+ #define ADDONS_UPDATE_URL "http://miranda-ng.org/"
+ #define ADDONS_DL_URL "http://miranda-ng.org/distr/x64/Plugins/tabsrmm.zip"
+#else
+ #define RES_FILE_DESC "TabSRMM (Unicode) x86"
+ #define ADDONS_UPDATE_URL "http://miranda-ng.org/"
+ #define ADDONS_DL_URL "http://miranda-ng.org/distr/x32/Plugins/tabsrmm.zip"
+#endif
diff --git a/plugins/TabSRMM/src/modplus.cpp b/plugins/TabSRMM/src/modplus.cpp
new file mode 100644
index 0000000000..3e9865f5f5
--- /dev/null
+++ b/plugins/TabSRMM/src/modplus.cpp
@@ -0,0 +1,276 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: modplus.cpp 11848 2010-05-27 14:57:22Z silvercircle $
+ *
+ * implements features of the tabSRMM "MADMOD" patch, developed by
+ * Mad Cluster in May 2008
+ *
+ * the "mad mod" patch added the following features:
+ *
+ * ) typing sounds
+ * ) support for animated avatars through ACC (avs)
+ * ) a fully customizable tool bar providing services useable by external plugins
+ * to add and change buttons
+ * ) toolbar on the bottom
+ * ) image tag button
+ * ) client icon in status bar
+ * ) close tab/window on send and the "hide container feature"
+ * ) bug fixes
+ *
+ */
+
+#include "commonheaders.h"
+
+static HANDLE hEventCBButtonPressed,hEventCBInit, hEventDbOptionsInit, hEventDbPluginsLoaded;
+
+int g_bStartup=0;
+
+BOOL g_bIMGtagButton;
+
+static char* getMirVer(HANDLE hContact)
+{
+ char *szProto = NULL;
+ char *msg = NULL;
+ DBVARIANT dbv = {0};
+
+ szProto = (char*) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ if ( !szProto )
+ return (NULL);
+
+ if ( !DBGetContactSettingString(hContact, szProto, "MirVer", &dbv)) {
+ msg=mir_strdup(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ return (msg);
+}
+
+static TCHAR* getMenuEntry(int i) {
+ TCHAR *msg = NULL;
+ char MEntry[256] = {'\0'};
+ DBVARIANT dbv = {0};
+
+ mir_snprintf(MEntry, 255, "MenuEntry_%u", i);
+ if ( !M->GetTString(NULL, "tabmodplus",MEntry, &dbv)) {
+ msg = mir_tstrdup(dbv.ptszVal);
+ DBFreeVariant(&dbv);
+ }
+ return (msg);
+}
+
+int ChangeClientIconInStatusBar(const TWindowData *dat)
+{
+ if (!ServiceExists(MS_FP_GETCLIENTICON))
+ return(S_FALSE);
+
+ char *msg = getMirVer(dat->hContact);
+
+ if ( !msg )
+ return (S_FALSE);
+
+ StatusIconData sid = {0};
+
+ sid.cbSize = sizeof(sid);
+ sid.szModule = (char *)"tabmodplus";
+ sid.hIcon = sid.hIconDisabled = dat->hClientIcon;
+ sid.dwId = 1;
+ sid.szTooltip = msg;
+ sid.flags = MBF_OWNERSTATE;
+ CallService(MS_MSG_MODIFYICON,(WPARAM)dat->hContact, (LPARAM)&sid);
+ mir_free(msg);
+ return (S_OK);
+}
+
+
+int ModPlus_PreShutdown(WPARAM wparam, LPARAM lparam)
+{
+ if ( hEventCBButtonPressed )
+ UnhookEvent(hEventCBButtonPressed);
+ if ( hEventCBInit )
+ UnhookEvent(hEventCBInit);
+ UnhookEvent(hEventDbPluginsLoaded);
+ UnhookEvent(hEventDbOptionsInit);
+
+ return (0);
+}
+
+static int RegisterCustomButton(WPARAM wParam,LPARAM lParam)
+{
+ if ( ServiceExists(MS_BB_ADDBUTTON)) {
+ BBButton bbd = {0};
+ bbd.cbSize = sizeof(BBButton);
+ bbd.bbbFlags = BBBF_ISIMBUTTON|BBBF_ISLSIDEBUTTON|BBBF_ISPUSHBUTTON;
+ bbd.dwButtonID = 1;
+ bbd.dwDefPos =200;
+ bbd.hIcon = PluginConfig.g_buttonBarIconHandles[3];
+ bbd.pszModuleName = (char *)"Tabmodplus";
+ bbd.ptszTooltip = TranslateT("Insert [img] tag / surround selected text with [img][/img]");
+
+ return (CallService(MS_BB_ADDBUTTON, 0, (LPARAM)&bbd));
+ }
+ return (1);
+}
+
+static int CustomButtonPressed(WPARAM wParam,LPARAM lParam)
+{
+ CustomButtonClickData *cbcd=(CustomButtonClickData *)lParam;
+
+ CHARRANGE cr;
+ TCHAR* pszMenu[256]={0};//=NULL;
+ int i=0;
+ TCHAR* pszText = (TCHAR *)_T("");
+ TCHAR* pszFormatedText=NULL;
+ UINT textlenght=0;
+ BBButton bbd={0};
+
+ int state=0;
+
+ if ( strcmp(cbcd->pszModule,"Tabmodplus")||cbcd->dwButtonId!=1 ) return (0);
+
+ bbd.cbSize=sizeof(BBButton);
+ bbd.dwButtonID=1;
+ bbd.pszModuleName = (char *)"Tabmodplus";
+ CallService(MS_BB_GETBUTTONSTATE, wParam, (LPARAM)&bbd);
+
+ cr.cpMin = cr.cpMax = 0;
+ SendDlgItemMessage(cbcd->hwndFrom,IDC_MESSAGE, EM_EXGETSEL, 0, (LPARAM)&cr);
+ textlenght=cr.cpMax-cr.cpMin;
+ if ( textlenght ) {
+ pszText = (TCHAR *)mir_alloc((textlenght+1)*sizeof(TCHAR));
+ ZeroMemory(pszText,(textlenght+1)*sizeof(TCHAR));
+ SendDlgItemMessage(cbcd->hwndFrom, IDC_MESSAGE,EM_GETSELTEXT, 0, (LPARAM)pszText);
+ }
+
+ if ( cbcd->flags & BBCF_RIGHTBUTTON )
+ state=1;
+ else if ( textlenght )
+ state = 2;
+ else if ( bbd.bbbFlags & BBSF_PUSHED )
+ state = 3;
+ else
+ state = 4;
+
+ switch ( state ) {
+ case 1:
+ {
+ int res=0;
+ int menunum;
+ int menulimit;
+ HMENU hMenu=NULL;
+
+ menulimit = M->GetByte("tabmodplus","MenuCount", 0);
+ if ( menulimit ) {
+ hMenu = CreatePopupMenu();
+ //pszMenu=malloc(menulimit*sizeof(TCHAR*));
+ } else break;
+ for ( menunum=0;menunum<menulimit;menunum++ ) {
+ pszMenu[menunum]=getMenuEntry(menunum);
+ AppendMenu(hMenu, MF_STRING,menunum+1, pszMenu[menunum]);
+ }
+ res = TrackPopupMenu(hMenu, TPM_RETURNCMD, cbcd->pt.x, cbcd->pt.y, 0, cbcd->hwndFrom, NULL);
+ if ( res==0 ) break;
+
+ pszFormatedText = (TCHAR *)mir_alloc((textlenght+lstrlen(pszMenu[res-1])+2)*sizeof(TCHAR));
+ ZeroMemory(pszFormatedText,(textlenght+lstrlen(pszMenu[res-1])+2)*sizeof(TCHAR));
+
+ mir_sntprintf(pszFormatedText,(textlenght+lstrlen(pszMenu[res-1])+2)*sizeof(TCHAR),pszMenu[res-1],pszText);
+
+ }break;
+ case 2:
+ {
+ pszFormatedText = (TCHAR *)mir_alloc((textlenght+12)*sizeof(TCHAR));
+ ZeroMemory(pszFormatedText,(textlenght+12)*sizeof(TCHAR));
+
+ SendDlgItemMessage(cbcd->hwndFrom, IDC_MESSAGE,EM_GETSELTEXT, 0, (LPARAM)pszText);
+ mir_sntprintf(pszFormatedText,(textlenght+12)*sizeof(TCHAR),_T("[img]%s[/img]"),pszText);
+
+ bbd.ptszTooltip=0;
+ bbd.hIcon=0;
+ bbd.bbbFlags=BBSF_RELEASED;
+ CallService(MS_BB_SETBUTTONSTATE, wParam, (LPARAM)&bbd);
+ }break;
+
+ case 3:
+ {
+ pszFormatedText = (TCHAR *)mir_alloc(6*sizeof(TCHAR));
+ ZeroMemory(pszFormatedText,6*sizeof(TCHAR));
+
+ _sntprintf(pszFormatedText,6*sizeof(TCHAR),_T("%s"),_T("[img]"));
+
+ bbd.ptszTooltip = TranslateT("Insert [img] tag / surround selected text with [img][/img]");
+ CallService(MS_BB_SETBUTTONSTATE, wParam, (LPARAM)&bbd);
+
+ }break;
+ case 4:
+ {
+
+ pszFormatedText = (TCHAR *)mir_alloc(7*sizeof(TCHAR));
+ ZeroMemory(pszFormatedText,7*sizeof(TCHAR));
+ _sntprintf(pszFormatedText,7*sizeof(TCHAR),_T("%s"),_T("[/img]"));
+
+ bbd.ptszTooltip = TranslateT("Insert [img] tag / surround selected text with [img][/img]");
+ CallService(MS_BB_SETBUTTONSTATE, wParam, (LPARAM)&bbd);
+
+ }break;
+ }
+
+ while ( pszMenu[i] ) {
+ mir_free(pszMenu[i]);
+ i++;
+ }
+
+ if ( pszFormatedText ) SendDlgItemMessage(cbcd->hwndFrom, IDC_MESSAGE, EM_REPLACESEL, TRUE, (LPARAM)pszFormatedText);
+
+ if ( textlenght ) mir_free(pszText);
+ if ( pszFormatedText ) mir_free(pszFormatedText);
+ return (1);
+
+}
+
+#define MBF_OWNERSTATE 0x04
+
+int ModPlus_Init(WPARAM wparam,LPARAM lparam)
+{
+ g_bStartup = 1;
+
+ hEventCBButtonPressed=HookEvent(ME_MSG_BUTTONPRESSED,CustomButtonPressed);
+ hEventCBInit=HookEvent(ME_MSG_TOOLBARLOADED,RegisterCustomButton);
+
+ if (PluginConfig.g_bClientInStatusBar&&ServiceExists(MS_MSG_ADDICON)) {
+ StatusIconData sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.szModule = (char *)"tabmodplus";
+ sid.flags = MBF_OWNERSTATE|MBF_HIDDEN;
+ sid.dwId = 1;
+ sid.szTooltip = 0;
+ sid.hIcon = sid.hIconDisabled = 0;
+ CallService(MS_MSG_ADDICON, 0, (LPARAM)&sid);
+ }
+ g_bStartup = 0;
+ return (0);
+}
diff --git a/plugins/TabSRMM/src/msgoptions_plus.cpp b/plugins/TabSRMM/src/msgoptions_plus.cpp
new file mode 100644
index 0000000000..e407f392d6
--- /dev/null
+++ b/plugins/TabSRMM/src/msgoptions_plus.cpp
@@ -0,0 +1,189 @@
+/*
+ * astyle --force-indent=tab=4 --brackets=linux --indent-switches
+ * --pad=oper --one-line=keep-blocks --unpad=paren
+ *
+ * Miranda NG: the free IM client for Microsoft* Windows*
+ *
+ * Copyright 2000-2009 Miranda ICQ/IM project,
+ * all portions of this codebase are copyrighted to the people
+ * listed in contributors.txt.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * you should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * part of tabSRMM messaging plugin for Miranda.
+ *
+ * (C) 2005-2009 by silvercircle _at_ gmail _dot_ com and contributors
+ *
+ * $Id: msgoptions_plus.cpp 13034 2010-10-24 20:39:04Z silvercircle $
+ *
+ * implements the "advanced tweak" option page
+ *
+ * originally developed by Mad Cluster for the tabSRMM "MADMOD" patch in
+ * May 2008.
+ *
+ */
+
+#include "commonheaders.h"
+
+extern HINSTANCE hinstance;
+extern BOOL g_bIMGtagButton;
+extern HIMAGELIST g_himlOptions, CreateStateImageList();
+
+static void FillDialog(HWND hwndDlg)
+{
+ TVINSERTSTRUCT tvi = {0};
+ int i;
+
+ TOptionListGroup *lvGroups = CTranslator::getGroupTree(CTranslator::TREE_MODPLUS);
+ for (i=0; lvGroups[i].szName != NULL; i++) {
+ tvi.hParent = 0;
+ tvi.hInsertAfter = TVI_LAST;
+ tvi.item.mask = TVIF_TEXT | TVIF_STATE;
+ tvi.item.pszText = TranslateTS(lvGroups[i].szName);
+ tvi.item.stateMask = TVIS_STATEIMAGEMASK | TVIS_EXPANDED | TVIS_BOLD;
+ tvi.item.state = INDEXTOSTATEIMAGEMASK(0) | TVIS_EXPANDED | TVIS_BOLD;
+ lvGroups[i].handle = (LRESULT)TreeView_InsertItem(GetDlgItem(hwndDlg, IDC_PLUS_CHECKTREE), &tvi);
+ }
+
+ TOptionListItem *lvItems = CTranslator::getTree(CTranslator::TREE_MODPLUS);
+ for (i=0; lvItems[i].szName != 0; i++) {
+ tvi.hParent = (HTREEITEM)lvGroups[lvItems[i].uGroup].handle;
+ tvi.hInsertAfter = TVI_LAST;
+ tvi.item.pszText = TranslateTS(lvItems[i].szName);
+ tvi.item.mask = TVIF_TEXT | TVIF_STATE | TVIF_PARAM;
+ tvi.item.lParam = i;
+ tvi.item.stateMask = TVIS_STATEIMAGEMASK;
+ if (lvItems[i].uType == LOI_TYPE_SETTING)
+ tvi.item.state = INDEXTOSTATEIMAGEMASK(M->GetByte((char *)lvItems[i].lParam, lvItems[i].id) ? 3 : 2); // NOTE: was 2 : 1 without state image mask
+ lvItems[i].handle = (LRESULT)TreeView_InsertItem(GetDlgItem(hwndDlg, IDC_PLUS_CHECKTREE), &tvi);
+ }
+
+ PluginConfig.g_bClientInStatusBar = M->GetByte("adv_ClientIconInStatusBar", 0);
+
+ SendDlgItemMessage(hwndDlg, IDC_TIMEOUTSPIN, UDM_SETRANGE, 0, MAKELONG(300, SRMSGSET_MSGTIMEOUT_MIN / 1000));
+ SendDlgItemMessage(hwndDlg, IDC_TIMEOUTSPIN, UDM_SETPOS, 0, PluginConfig.m_MsgTimeout / 1000);
+
+ SendDlgItemMessage(hwndDlg, IDC_HISTORYSIZESPIN, UDM_SETRANGE, 0, MAKELONG(255, 15));
+ SendDlgItemMessage(hwndDlg, IDC_HISTORYSIZESPIN, UDM_SETPOS, 0, (int)M->GetByte("historysize", 0));
+}
+
+INT_PTR CALLBACK PlusOptionsProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_PLUS_CHECKTREE), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_PLUS_CHECKTREE), GWL_STYLE) | (TVS_NOHSCROLL | TVS_CHECKBOXES));
+
+ g_himlOptions = (HIMAGELIST)SendDlgItemMessage(hwndDlg, IDC_PLUS_CHECKTREE, TVM_SETIMAGELIST, TVSIL_STATE, (LPARAM)CreateStateImageList());
+ ImageList_Destroy(g_himlOptions);
+
+ FillDialog(hwndDlg);
+ return TRUE;
+
+ case WM_NOTIFY:
+ switch (((LPNMHDR) lParam)->idFrom) {
+ case IDC_PLUS_CHECKTREE:
+ if (((LPNMHDR)lParam)->code == NM_CLICK || (((LPNMHDR)lParam)->code == TVN_KEYDOWN && ((LPNMTVKEYDOWN)lParam)->wVKey == VK_SPACE)) {
+ TVHITTESTINFO hti;
+ TVITEM item = {0};
+
+ item.mask = TVIF_HANDLE | TVIF_STATE;
+ item.stateMask = TVIS_STATEIMAGEMASK | TVIS_BOLD;
+ hti.pt.x = (short)LOWORD(GetMessagePos());
+ hti.pt.y = (short)HIWORD(GetMessagePos());
+ ScreenToClient(((LPNMHDR)lParam)->hwndFrom, &hti.pt);
+ if (TreeView_HitTest(((LPNMHDR)lParam)->hwndFrom, &hti) || ((LPNMHDR)lParam)->code == TVN_KEYDOWN) {
+ if (((LPNMHDR)lParam)->code == TVN_KEYDOWN) {
+ hti.flags |= TVHT_ONITEMSTATEICON;
+ item.hItem = TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom);
+ } else
+ item.hItem = (HTREEITEM)hti.hItem;
+ SendDlgItemMessageA(hwndDlg, IDC_PLUS_CHECKTREE, TVM_GETITEMA, 0, (LPARAM)&item);
+ if (item.state & TVIS_BOLD && hti.flags & TVHT_ONITEMSTATEICON) {
+ item.state = INDEXTOSTATEIMAGEMASK(0) | TVIS_BOLD;
+ SendDlgItemMessageA(hwndDlg, IDC_PLUS_CHECKTREE, TVM_SETITEMA, 0, (LPARAM)&item);
+ }
+ else if (hti.flags & TVHT_ONITEMSTATEICON) {
+ if (((item.state & TVIS_STATEIMAGEMASK) >> 12) == 3) {
+ item.state = INDEXTOSTATEIMAGEMASK(1);
+ SendDlgItemMessageA(hwndDlg, IDC_PLUS_CHECKTREE, TVM_SETITEMA, 0, (LPARAM)&item);
+ }
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ }
+ }
+ break;
+
+ default:
+ switch (((LPNMHDR) lParam)->code) {
+ case PSN_APPLY: {
+ TVITEM item = {0};
+ DWORD msgTimeout;
+ /*
+ * scan the tree view and obtain the options...
+ */
+ TOptionListItem* lvItems = CTranslator::getTree(CTranslator::TREE_MODPLUS);
+
+ for (int i=0; lvItems[i].szName != NULL; i++) {
+ item.mask = TVIF_HANDLE | TVIF_STATE;
+ item.hItem = (HTREEITEM)lvItems[i].handle;
+ item.stateMask = TVIS_STATEIMAGEMASK;
+
+ SendDlgItemMessageA(hwndDlg, IDC_PLUS_CHECKTREE, TVM_GETITEMA, 0, (LPARAM)&item);
+ if (lvItems[i].uType == LOI_TYPE_SETTING)
+ M->WriteByte(SRMSGMOD_T, (char *)lvItems[i].lParam, (BYTE)((item.state >> 12) == 3/*2*/ ? 1 : 0)); // NOTE: state image masks changed
+ }
+
+ msgTimeout = 1000 * GetDlgItemInt(hwndDlg, IDC_SECONDS, NULL, FALSE);
+ PluginConfig.m_MsgTimeout = msgTimeout >= SRMSGSET_MSGTIMEOUT_MIN ? msgTimeout : SRMSGSET_MSGTIMEOUT_MIN;
+ M->WriteDword(SRMSGMOD, SRMSGSET_MSGTIMEOUT, PluginConfig.m_MsgTimeout);
+
+ M->WriteByte(SRMSGMOD_T, "historysize", (BYTE)SendDlgItemMessage(hwndDlg, IDC_HISTORYSIZESPIN, UDM_GETPOS, 0, 0));
+ PluginConfig.reloadAdv();
+ return TRUE;
+ }
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDC_PLUS_HELP) {
+ CallService(MS_UTILS_OPENURL, 0, (LPARAM)"http://wiki.miranda.or.at/TabSRMM/AdvancedTweaks");
+ break;
+ }
+ else if (LOWORD(wParam) == IDC_PLUS_REVERT) { // revert to defaults...
+ TOptionListItem *lvItems = CTranslator::getTree(CTranslator::TREE_MODPLUS);
+
+ for (int i=0; lvItems[i].szName; i++)
+ if (lvItems[i].uType == LOI_TYPE_SETTING)
+ M->WriteByte(SRMSGMOD_T, (char *)lvItems[i].lParam, (BYTE)lvItems[i].id);
+
+ TreeView_DeleteAllItems(GetDlgItem(hwndDlg, IDC_PLUS_CHECKTREE));
+ FillDialog(hwndDlg);
+ break;
+ }
+ if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus())
+ return TRUE;
+
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hwndDlg,0);
+ return 0;
+ }
+ return 0;
+}