diff options
Diffstat (limited to 'plugins/TabSRMM/src/chat')
-rw-r--r-- | plugins/TabSRMM/src/chat/chat.h | 369 | ||||
-rw-r--r-- | plugins/TabSRMM/src/chat/chat_resource.h | 161 | ||||
-rw-r--r-- | plugins/TabSRMM/src/chat/chatprototypes.h | 174 | ||||
-rw-r--r-- | plugins/TabSRMM/src/chat/clist.cpp | 325 | ||||
-rw-r--r-- | plugins/TabSRMM/src/chat/colorchooser.cpp | 281 | ||||
-rw-r--r-- | plugins/TabSRMM/src/chat/log.cpp | 1340 | ||||
-rw-r--r-- | plugins/TabSRMM/src/chat/main.cpp | 142 | ||||
-rw-r--r-- | plugins/TabSRMM/src/chat/manager.cpp | 1544 | ||||
-rw-r--r-- | plugins/TabSRMM/src/chat/message.cpp | 341 | ||||
-rw-r--r-- | plugins/TabSRMM/src/chat/muchighlight.cpp | 427 | ||||
-rw-r--r-- | plugins/TabSRMM/src/chat/muchighlight.h | 94 | ||||
-rw-r--r-- | plugins/TabSRMM/src/chat/options.cpp | 1493 | ||||
-rw-r--r-- | plugins/TabSRMM/src/chat/services.cpp | 882 | ||||
-rw-r--r-- | plugins/TabSRMM/src/chat/tools.cpp | 1353 | ||||
-rw-r--r-- | plugins/TabSRMM/src/chat/window.cpp | 3833 |
15 files changed, 12759 insertions, 0 deletions
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)>l, 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)>, (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)>, (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);
+}
|