diff options
author | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-05-15 10:38:20 +0000 |
---|---|---|
committer | Vadim Dashevskiy <watcherhd@gmail.com> | 2012-05-15 10:38:20 +0000 |
commit | 48540940b6c28bb4378abfeb500ec45a625b37b6 (patch) | |
tree | 2ef294c0763e802f91d868bdef4229b6868527de /plugins/Scriver/chat | |
parent | 5c350913f011e119127baeb32a6aedeb4f0d33bc (diff) |
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/Scriver/chat')
-rw-r--r-- | plugins/Scriver/chat/chat.h | 440 | ||||
-rw-r--r-- | plugins/Scriver/chat/clist.c | 366 | ||||
-rw-r--r-- | plugins/Scriver/chat/colorchooser.c | 282 | ||||
-rw-r--r-- | plugins/Scriver/chat/log.c | 998 | ||||
-rw-r--r-- | plugins/Scriver/chat/m_uninstaller.h | 700 | ||||
-rw-r--r-- | plugins/Scriver/chat/main.c | 111 | ||||
-rw-r--r-- | plugins/Scriver/chat/manager.c | 1402 | ||||
-rw-r--r-- | plugins/Scriver/chat/message.c | 351 | ||||
-rw-r--r-- | plugins/Scriver/chat/options.c | 953 | ||||
-rw-r--r-- | plugins/Scriver/chat/services.c | 690 | ||||
-rw-r--r-- | plugins/Scriver/chat/tools.c | 976 | ||||
-rw-r--r-- | plugins/Scriver/chat/window.c | 2200 |
12 files changed, 9469 insertions, 0 deletions
diff --git a/plugins/Scriver/chat/chat.h b/plugins/Scriver/chat/chat.h new file mode 100644 index 0000000000..283adcdecd --- /dev/null +++ b/plugins/Scriver/chat/chat.h @@ -0,0 +1,440 @@ +/*
+Chat module plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+Copyright 2003-2009 Miranda ICQ/IM project,
+
+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.
+*/
+
+#ifndef _CHAT_H_
+#define _CHAT_H_
+
+#include <m_protomod.h>
+#include <m_chat.h>
+
+#ifndef TVM_GETITEMSTATE
+#define TVM_GETITEMSTATE (TV_FIRST + 39)
+#endif
+
+#ifndef TreeView_GetItemState
+#define TreeView_GetItemState(hwndTV, hti, mask) \
+ (UINT)SNDMSG((hwndTV), TVM_GETITEMSTATE, (WPARAM)(hti), (LPARAM)(mask))
+#endif
+
+#ifndef CFM_BACKCOLOR
+#define CFM_BACKCOLOR 0x04000000
+#endif
+
+//defines
+#define OPTIONS_FONTCOUNT 17
+#define GC_SPLITTERMOVED (WM_USER+101)
+#define GC_CLOSEWINDOW (WM_USER+103)
+#define GC_GETITEMDATA (WM_USER+104)
+#define GC_SETITEMDATA (WM_USER+105)
+#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_SETWINDOWPOS (WM_USER+114)
+//#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_TABCHANGE (WM_USER+127)
+#define GC_SCROLLTOBOTTOM (WM_USER+129)
+#define GC_FIXTABICONS (WM_USER+132)
+#define GC_SETTABHIGHLIGHT (WM_USER+138)
+#define GC_SETMESSAGEHIGHLIGHT (WM_USER+139)
+#define GC_REDRAWLOG2 (WM_USER+140)
+#define GC_REDRAWLOG3 (WM_USER+141)
+
+//#define EM_SUBCLASSED (WM_USER+200)
+//#define EM_UNSUBCLASSED (WM_USER+201)
+#define EM_ACTIVATE (WM_USER+202)
+
+#define GCW_TABROOM 10
+#define GCW_TABPRIVMSG 11
+
+#define GC_EVENT_HIGHLIGHT 0x1000
+#define STATE_TALK 0x0001
+
+
+// special service for tweaking performance
+#define MS_GC_GETEVENTPTR "GChat/GetNewEventPtr"
+typedef INT_PTR (*GETEVENTFUNC)(WPARAM wParam, LPARAM lParam);
+typedef struct {
+ GETEVENTFUNC pfnAddEvent;
+}GCPTRS;
+
+//structs
+
+typedef struct MODULE_INFO_TYPE
+{
+ char* pszModule;
+ TCHAR* ptszModDispName;
+ BOOL bBold;
+ BOOL bUnderline;
+ BOOL bItalics;
+ BOOL bColor;
+ BOOL bBkgColor;
+ BOOL bFontSize;
+ BOOL bChanMgr;
+ BOOL bAckMsg;
+ BOOL bSingleFormat;
+ int nColorCount;
+ COLORREF* crColors;
+ HICON hOnlineIcon;
+ HICON hOfflineIcon;
+ HICON hOnlineIconBig;
+ HICON hOfflineIconBig;
+ HICON hOnlineTalkIcon;
+ HICON hOfflineTalkIcon;
+ int iMaxText;
+ struct MODULE_INFO_TYPE *next;
+}
+ MODULEINFO;
+
+typedef struct COMMAND_INFO_TYPE
+{
+ char* lpCommand;
+ struct COMMAND_INFO_TYPE *prev, *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;
+ 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 TABLIST_TYPE
+{
+ TCHAR* pszID;
+ char* pszModule;
+ struct TABLIST_TYPE *next;
+}
+ TABLIST;
+
+typedef struct SESSION_INFO_TYPE
+{
+ HWND hWnd;
+
+ BOOL bFGSet;
+ BOOL bBGSet;
+ BOOL bFilterEnabled;
+ BOOL bNicklistEnabled;
+ BOOL bInitDone;
+
+ char* pszModule;
+ char* pszHeader;
+ TCHAR* ptszID;
+ TCHAR* ptszName;
+ TCHAR* ptszStatusbarText;
+ TCHAR* ptszTopic;
+
+ #if defined( _UNICODE )
+ 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
+ #endif
+
+ int iType;
+ int iFG;
+ int iBG;
+ int iSplitterY;
+ int desiredInputAreaHeight;
+ int iSplitterX;
+ int iLogFilterFlags;
+ int nUsersInNicklist;
+ int iEventCount;
+ int iStatusCount;
+
+ WORD wStatus;
+ WORD wState;
+ WORD wCommandsNum;
+ DWORD dwItemData;
+ DWORD dwFlags;
+ time_t LastTime;
+ CommonWindowData windowData;
+ LOGINFO* pLog;
+ LOGINFO* pLogEnd;
+ USERINFO* pUsers;
+ USERINFO* pMe;
+ STATUSINFO* pStatuses;
+ TCHAR szSearch[255];
+
+ struct SESSION_INFO_TYPE *next;
+
+}SESSION_INFO;
+
+typedef struct
+{
+ char* buffer;
+ int bufferOffset, bufferLen;
+ HWND hwnd;
+ LOGINFO* lin;
+ BOOL bStripFormat;
+ BOOL bRedraw;
+ BOOL isFirst;
+ SESSION_INFO* si;
+}
+ LOGSTREAMDATA;
+
+struct GlobalLogSettings_t {
+ BOOL ShowTime;
+ BOOL ShowTimeIfChanged;
+ BOOL LoggingEnabled;
+ BOOL FlashWindow;
+ BOOL HighlightEnabled;
+ BOOL LogIndentEnabled;
+ BOOL StripFormat;
+ BOOL SoundsFocus;
+ BOOL PopUpInactiveOnly;
+ BOOL TrayIconInactiveOnly;
+ BOOL AddColonToAutoComplete;
+ BOOL LogLimitNames;
+ BOOL TimeStampEventColour;
+ DWORD dwIconFlags;
+ DWORD dwTrayIconFlags;
+ DWORD dwPopupFlags;
+ int LogTextIndent;
+ int LoggingLimit;
+ int iEventLimit;
+ int iPopupStyle;
+ int iPopupTimeout;
+ int iSplitterX;
+ int iSplitterY;
+ TCHAR* pszTimeStamp;
+ TCHAR* pszTimeStampLog;
+ TCHAR* pszIncomingNick;
+ TCHAR* pszOutgoingNick;
+ TCHAR* pszHighlightWords;
+ TCHAR* pszLogDir;
+ HFONT UserListFont;
+ HFONT UserListHeadingsFont;
+ HFONT MessageBoxFont;
+ HFONT NameFont;
+ COLORREF crLogBackground;
+ COLORREF crUserListColor;
+ COLORREF crUserListBGColor;
+ COLORREF crUserListSelectedBGColor;
+ COLORREF crUserListHeadingsColor;
+ COLORREF crPUTextColour;
+ COLORREF crPUBkgColour;
+ BOOL ShowContactStatus;
+ BOOL ContactStatusFirst;
+};
+extern struct GlobalLogSettings_t g_Settings;
+
+typedef struct{
+ MODULEINFO* pModule;
+ int xPosition;
+ int yPosition;
+ HWND hWndTarget;
+ BOOL bForeground;
+ SESSION_INFO* si;
+}
+ COLORCHOOSER;
+
+//main.c
+void LoadIcons(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);
+void LoadMsgLogBitmaps(void);
+void FreeMsgLogBitmaps(void);
+TCHAR* GetChatLogsFilename (HANDLE hContact, time_t tTime);
+TCHAR* MakeTimeStamp(TCHAR* pszStamp, time_t time);
+char* Log_CreateRtfHeader(MODULEINFO * mi, SESSION_INFO* si);
+
+//window.c
+INT_PTR CALLBACK RoomWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
+int GetTextPixelSize( TCHAR* pszText, HFONT hFont, BOOL bWidth);
+
+//options.c
+int OptionsInit(void);
+int OptionsUnInit(void);
+void LoadGlobalSettings(void);
+void LoadLogFonts(void);
+void SetIndentSize();
+
+//services.c
+void HookEvents(void);
+void UnhookEvents(void);
+void CreateServiceFunctions(void);
+void DestroyServiceFunctions(void);
+void DestroyHookableEvents(void);
+void CreateHookableEvents(void);
+int Chat_ModulesLoaded(WPARAM wParam,LPARAM lParam);
+int Chat_FontsChanged(WPARAM wParam,LPARAM lParam);
+int Chat_SmileyOptionsChanged(WPARAM wParam,LPARAM lParam);
+int Chat_PreShutdown(WPARAM wParam,LPARAM lParam);
+int Chat_IconsChanged(WPARAM wParam,LPARAM lParam);
+void ShowRoom(SESSION_INFO* si, WPARAM wp, BOOL bSetForeground);
+
+//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);
+SESSION_INFO* SM_FindSession(const TCHAR* pszID, const char* pszModule);
+HWND SM_FindWindowByContact(HANDLE hContact);
+USERINFO* SM_AddUser(SESSION_INFO* si, const TCHAR* pszUID, const TCHAR* pszNick, WORD wStatus);
+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);
+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 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);
+int SM_GetCount(const char* pszModule);
+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);
+char SM_GetStatusIndicator(SESSION_INFO* si, USERINFO * ui);
+SESSION_INFO* SM_FindSessionAutoComplete(const char* pszModule, SESSION_INFO* currSession, SESSION_INFO* prevSession, const TCHAR* pszOriginal, const TCHAR* pszCurrent);
+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 CList_EventDoubleclicked(WPARAM wParam,LPARAM lParam);
+INT_PTR CList_EventDoubleclickedSvc(WPARAM wParam,LPARAM lParam);
+INT_PTR CList_JoinChat(WPARAM wParam, LPARAM lParam);
+INT_PTR CList_LeaveChat(WPARAM wParam, LPARAM lParam);
+INT_PTR CList_PrebuildContactMenuSvc(WPARAM wParam, LPARAM lParam);
+int CList_PrebuildContactMenu(WPARAM wParam, LPARAM lParam);
+void CList_CreateGroup(TCHAR* group);
+BOOL CList_AddEvent(HANDLE hContact, HICON Icon, HANDLE event, int type, 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 DoSoundsFlashPopupTrayStuff(SESSION_INFO* si, GCEVENT * gce, BOOL bHighlight, int bManyFix);
+int GetColorIndex(const char* pszModule, COLORREF cr);
+void CheckColorsInModule(const char* pszModule);
+TCHAR* my_strstri(const TCHAR* s1, const TCHAR* s2) ;
+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);
+
+// message.c
+TCHAR* DoRtfToTags( char* pszRtfText, SESSION_INFO* si);
+
+//////////////////////////////////////////////////////////////////////////////////
+
+TCHAR* a2tf( const TCHAR* str, int flags );
+TCHAR* replaceStr( TCHAR** dest, const TCHAR* src );
+char* replaceStrA( char** dest, const char* src );
+
+#define DEFLOGFILENAME _T("%miranda_logpath%\\%proto%\\%userid%.log")
+#endif
diff --git a/plugins/Scriver/chat/clist.c b/plugins/Scriver/chat/clist.c new file mode 100644 index 0000000000..7d43578a4b --- /dev/null +++ b/plugins/Scriver/chat/clist.c @@ -0,0 +1,366 @@ +/*
+Chat module plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+Copyright 2003-2009 Miranda ICQ/IM project,
+
+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.
+*/
+
+#include "../commonheaders.h"
+#include "chat.h"
+
+extern HINSTANCE g_hInst;
+
+extern HANDLE hJoinMenuItem, hLeaveMenuItem;
+
+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 ( !DBGetContactSettingTString( 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 ) { //contact exist, make sure it is in the right group
+ DBVARIANT dbv;
+ DBVARIANT dbv2;
+ char str[50];
+ int i;
+
+ if ( pszGroup[0] ) {
+ for (i = 0;; i++) {
+ _itoa(i, str, 10);
+ if ( DBGetContactSettingTString( NULL, "CListGroups", str, &dbv )) {
+ DBWriteContactSettingTString(hContact, "CList", "Group", pszGroup);
+ goto END_GROUPLOOP;
+ }
+
+ if ( !DBGetContactSettingTString( hContact, "CList", "Group", &dbv2 )) {
+ if ( dbv.ptszVal[0] != '\0' && dbv2.ptszVal[0] != '\0' && !lstrcmpi( dbv.ptszVal + 1, dbv2.ptszVal )) {
+ DBFreeVariant(&dbv);
+ DBFreeVariant(&dbv2);
+ goto END_GROUPLOOP;
+ }
+ DBFreeVariant(&dbv2);
+ }
+ DBFreeVariant(&dbv);
+ } }
+
+END_GROUPLOOP:
+ DBWriteContactSettingWord(hContact, pszModule, "Status", ID_STATUS_OFFLINE);
+ DBWriteContactSettingTString(hContact, pszModule, "Nick", pszDisplayName );
+/* if(iType != GCW_SERVER)
+ DBWriteContactSettingByte(hContact, "CList", "Hidden", 1);*/
+ 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 ( lstrlen( pszGroup ) > 0 )
+ DBWriteContactSettingTString(hContact, "CList", "Group", pszGroup );
+ else
+ DBDeleteContactSetting(hContact, "CList", "Group");
+ DBWriteContactSettingTString( hContact, pszModule, "Nick", pszDisplayName );
+ DBWriteContactSettingTString( hContact, pszModule, "ChatRoomID", pszRoom );
+ DBWriteContactSettingByte(hContact, pszModule, "ChatRoom", (BYTE)iType);
+ DBWriteContactSettingWord(hContact, pszModule, "Status", ID_STATUS_OFFLINE);
+// if(iType == GCW_SERVER)
+ // DBWriteContactSettingByte(hContact, "CList", "Hidden", 1);
+ return hContact;
+ }
+
+BOOL CList_SetOffline(HANDLE hContact, BOOL bHide)
+{
+ if ( hContact ) {
+ char * szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ DBWriteContactSettingWord(hContact, szProto,"ApparentMode",(LPARAM) 0);
+ DBWriteContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+/*
+ int i = DBGetContactSettingByte(hContact, szProto, "ChatRoom", 0);
+ if (bHide && i != GCW_SERVER)
+ DBWriteContactSettingByte(hContact, "CList", "Hidden", 1);*/
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL CList_SetAllOffline(BOOL bHide, const char *pszModule)
+{
+ HANDLE hContact;
+ char * szProto;
+
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while ( hContact ) {
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if ( MM_FindModule( szProto )) {
+ if (!pszModule || (pszModule && !strcmp(pszModule, szProto))) {
+ int i = DBGetContactSettingByte(hContact, szProto, "ChatRoom", 0);
+ if ( i != 0 ) {
+ DBWriteContactSettingWord(hContact, szProto,"ApparentMode",(LPARAM)(WORD) 0);
+ DBWriteContactSettingWord(hContact, szProto, "Status", ID_STATUS_OFFLINE);
+/* if (bHide && i == GCW_CHATROOM)
+ DBWriteContactSettingByte(hContact, "CList", "Hidden", 1);*/
+ }
+ }
+ }
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+ return TRUE;
+}
+
+int CList_RoomDoubleclicked(WPARAM wParam,LPARAM lParam)
+{
+ DBVARIANT dbv;
+ char *szProto;
+
+ HANDLE hContact = (HANDLE)wParam;
+ if (!hContact)
+ return 0;
+
+ szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0);
+ if ( MM_FindModule(szProto)) {
+ if(DBGetContactSettingByte(hContact, szProto, "ChatRoom", 0) == 0)
+ return 0;
+
+ if ( !DBGetContactSettingTString( 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
+ && DBGetContactSettingByte(NULL, "Chat", "ToggleVisibility", 0)==1
+ && !CallService(MS_CLIST_GETEVENT, (WPARAM)hContact, 0)
+ && IsWindowVisible(si->hWnd)
+ && !IsIconic(si->hWnd))
+ {
+ PostMessage(si->hWnd, GC_CLOSEWINDOW, 0, 0);
+ DBFreeVariant(&dbv);
+ return 1;
+ }
+ ShowRoom(si, WINDOW_VISIBLE, TRUE);
+ }
+ DBFreeVariant(&dbv);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int CList_EventDoubleclicked(WPARAM wParam,LPARAM lParam)
+{
+ return CList_RoomDoubleclicked((WPARAM) ((CLISTEVENT*)lParam)->hContact,(LPARAM) 0);
+}
+
+INT_PTR CList_EventDoubleclickedSvc(WPARAM wParam,LPARAM lParam)
+{
+ return CList_EventDoubleclicked(wParam, lParam);
+}
+
+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 ( DBGetContactSettingByte( 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)
+{
+ int i;
+ char str[50];
+ TCHAR name[256];
+ DBVARIANT dbv;
+
+ if (!group)
+ return;
+
+ for (i = 0;; i++)
+ {
+ _itoa(i, str, 10);
+ if ( DBGetContactSettingTString( NULL, "CListGroups", str, &dbv ))
+ break;
+
+ if ( dbv.pszVal[0] != '\0' && !lstrcmpi(dbv.ptszVal + 1, group)) {
+ DBFreeVariant(&dbv);
+ return;
+ }
+
+ DBFreeVariant(&dbv);
+ }
+
+ // CallService(MS_CLIST_GROUPCREATE, (WPARAM)group, 0);
+ name[0] = 1 | GROUPF_EXPANDED;
+ _tcsncpy(name + 1, group, SIZEOF(name) - 1);
+ name[ lstrlen(group) + 1] = '\0';
+ DBWriteContactSettingTString(NULL, "CListGroups", str, name);
+ CallService(MS_CLUI_GROUPADDED, i + 1, 0);
+}
+
+BOOL CList_AddEvent(HANDLE hContact, HICON Icon, HANDLE event, int type, 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);
+ _vsntprintf(szBuf, 4096, 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)event);
+ CallService(MS_CLIST_ADDEVENT,(WPARAM) hContact,(LPARAM) &cle);
+ }
+ return TRUE;
+}
+
+HANDLE CList_FindRoom ( const char* pszModule, const TCHAR* pszRoom)
+{
+ HANDLE hContact = ( HANDLE )CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact) {
+ char* szProto = ( char* )CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0 );
+ if ( szProto && !lstrcmpiA( szProto, pszModule )) {
+ if ( DBGetContactSettingByte( hContact, szProto, "ChatRoom", 0) != 0 ) {
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingTString( hContact, szProto, "ChatRoomID", &dbv )) {
+ if ( !lstrcmpi(dbv.ptszVal, pszRoom)) {
+ DBFreeVariant(&dbv);
+ return hContact;
+ }
+ DBFreeVariant(&dbv);
+ } } }
+
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+ return 0;
+}
+
+int WCCmp(TCHAR* wild, TCHAR* string)
+{
+ TCHAR *cp = NULL, *mp = NULL;
+ if ( wild == NULL || !lstrlen(wild) || string == NULL || !lstrlen(string))
+ return 0;
+
+ while ((*string) && (*wild != '*')) {
+ if ((*wild != *string) && (*wild != '?'))
+ return 0;
+
+ wild++;
+ string++;
+ }
+
+ while (*string) {
+ if (*wild == '*') {
+ if (!*++wild)
+ return 1;
+
+ mp = wild;
+ cp = string+1;
+ }
+ else if ((*wild == *string) || (*wild == '?')) {
+ wild++;
+ string++;
+ }
+ else {
+ wild = mp;
+ string = cp++;
+ } }
+
+ while (*wild == '*')
+ wild++;
+
+ return !*wild;
+}
diff --git a/plugins/Scriver/chat/colorchooser.c b/plugins/Scriver/chat/colorchooser.c new file mode 100644 index 0000000000..eb330bfe89 --- /dev/null +++ b/plugins/Scriver/chat/colorchooser.c @@ -0,0 +1,282 @@ +/*
+Chat module plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+Copyright 2003-2009 Miranda ICQ/IM project,
+
+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.
+*/
+
+// this color chooser window is inspired by PeaCow's smiley chooser window for the Smileyadd plugin
+
+#include "../commonheaders.h"
+#include "chat.h"
+#include <math.h>
+
+//globals, defined int main.cpp
+extern HINSTANCE g_hInst;
+
+static int CalculateCoordinatesToButton(COLORCHOOSER * pCC, POINT pt)
+{
+ int iSquareRoot = (int)sqrt(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(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(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, GetWindowLong(hwndDlg, GWL_STYLE), FALSE, GetWindowLong(hwndDlg, GWL_EXSTYLE));
+
+ width = rc.right - rc.left;
+ height = rc.bottom - rc.top;
+
+ pCC->yPosition -= height;
+
+
+ SetDlgItemText(hwndDlg, IDC_CHAT_COLORTEXT, pCC->bForeground?TranslateT("Text colour"):TranslateT("Background colour"));
+ SetWindowPos(GetDlgItem(hwndDlg, IDC_CHAT_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_CHAT_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_CHAT_COLOR )) {
+ cf.dwMask = CFM_COLOR;
+ cf.crTextColor = pCC->pModule->crColors[iCurrentHotTrack];
+ if (pCC->pModule->bSingleFormat) {
+ SendMessage(pCC->hWndTarget, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
+ } else {
+ SendMessage(pCC->hWndTarget, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ }
+ }
+ else {
+ pCC->si->bBGSet = TRUE;
+ pCC->si->iBG = iCurrentHotTrack;
+ if(IsDlgButtonChecked(hWindow, IDC_CHAT_BKGCOLOR)) {
+ cf.dwMask = CFM_BACKCOLOR;
+ cf.crBackColor = pCC->pModule->crColors[iCurrentHotTrack];
+ if (pCC->pModule->bSingleFormat) {
+ SendMessage(pCC->hWndTarget, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
+ } else {
+ 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;
+ 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=0; 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, GetStockObject(BLACK_BRUSH));
+
+ 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/Scriver/chat/log.c b/plugins/Scriver/chat/log.c new file mode 100644 index 0000000000..5887708957 --- /dev/null +++ b/plugins/Scriver/chat/log.c @@ -0,0 +1,998 @@ +/*
+Chat module plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+Copyright 2003-2009 Miranda ICQ/IM project,
+
+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.
+*/
+
+#include "../commonheaders.h"
+#include "chat.h"
+#include <math.h>
+#include <mbstring.h>
+#include <shlwapi.h>
+
+
+#ifndef EM_GETSCROLLPOS
+#define EM_GETSCROLLPOS (WM_USER+221)
+#endif
+// 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];
+
+static PBYTE pLogIconBmpBits[14];
+static const char *logIconNames[14] = {
+ "chat_log_action", "chat_log_addstatus", "chat_log_highlight", "chat_log_info", "chat_log_join",
+ "chat_log_kick", "chat_log_message_in", "chat_log_message_out", "chat_log_nick", "chat_log_notice",
+ "chat_log_part", "chat_log_quit", "chat_log_removestatus", "chat_log_topic"
+};
+static int logIconBmpSize[ SIZEOF(pLogIconBmpBits) ];
+
+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 int EventToIcon(LOGINFO * lin)
+{
+ switch (lin->iType) {
+ case GC_EVENT_MESSAGE:
+ if (lin->bIsMe)
+ return 7;
+ else
+ return 6;
+
+ case GC_EVENT_JOIN: return 4;
+ case GC_EVENT_PART: return 10;
+ case GC_EVENT_QUIT: return 11;
+ case GC_EVENT_NICK: return 8;
+ case GC_EVENT_KICK: return 5;
+ case GC_EVENT_NOTICE: return 9;
+ case GC_EVENT_TOPIC: return 13;
+ case GC_EVENT_INFORMATION:return 3;
+ case GC_EVENT_ADDSTATUS: return 1;
+ case GC_EVENT_REMOVESTATUS: return 12;
+ case GC_EVENT_ACTION: return 0;
+ }
+ return 0;
+}
+
+static char *Log_SetStyle(int style, int fontindex)
+{
+ static char szStyle[128];
+ mir_snprintf(szStyle, SIZEOF(szStyle), "\\f%u\\cf%u\\ul0\\highlight0\\b%d\\i%d\\fs%u", style, style+1, aFonts[fontindex].lf.lfWeight >= FW_BOLD ? 1 : 0, aFonts[fontindex].lf.lfItalic, 2 * abs(aFonts[fontindex].lf.lfHeight) * 74 / g_dat->logPixelSY);
+ return szStyle;
+}
+
+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);
+ *buffer = (char *) mir_realloc(*buffer, *cbBufferAlloced);
+ }
+
+ 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 {
+ #if defined( _UNICODE )
+ d += sprintf(d, "\\u%u ?", (WORD)*line);
+ #else
+ d += sprintf(d, "\\'%02x", (BYTE)*line);
+ #endif
+ }
+ }
+
+ *cbBufferEnd = (int) (d - *buffer);
+ return textCharsCount;
+}
+
+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 = _tcslen(szTemp);
+ memcpy( d, szTemp, iLen * sizeof(TCHAR));
+ d += iLen;
+ }
+ }
+ else if (*line == '%') {
+ *d++ = '%';
+ *d++ = (char) *line;
+ }
+ else {
+ *d++ = (char) *line;
+ }
+ }
+ *d = '\0';
+ *cbBufferEnd = (int) (d - *buffer);
+ return textCharsCount;
+}
+
+
+static void AddEventTextToBuffer(char **buffer, int *bufferEnd, int *bufferAlloced, LOGSTREAMDATA *streamData)
+{
+ if (streamData->lin->ptszText)
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T(": %s"), streamData->lin->ptszText);
+}
+
+static void AddEventToBuffer(char **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 defined( _UNICODE )
+ if (streamData->si->windowData.codePage != CP_ACP) {
+ char *aText = t2acp(streamData->lin->ptszText, CP_ACP);
+ ptszText = ptszTemp = a2tcp(aText, streamData->si->windowData.codePage);
+ mir_free(aText);
+ }
+ #endif
+ Log_AppendRTF( streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T("%s"), ptszText );
+ mir_free(ptszTemp);
+ }
+ break;
+ case GC_EVENT_ACTION:
+ if ( pszNick && streamData->lin->ptszText) {
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, _T("%s "), pszNick);
+ Log_AppendRTF(streamData, FALSE, buffer, bufferEnd, bufferAlloced, _T("%s"), streamData->lin->ptszText);
+ }
+ break;
+ case GC_EVENT_JOIN:
+ if (pszNick) {
+ if (!streamData->lin->bIsMe)
+ 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);
+ AddEventTextToBuffer(buffer, bufferEnd, bufferAlloced, streamData);
+ break;
+ case GC_EVENT_QUIT:
+ if (pszNick)
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("%s has disconnected"), pszNick);
+ AddEventTextToBuffer(buffer, bufferEnd, bufferAlloced, streamData);
+ 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);
+ AddEventTextToBuffer(buffer, bufferEnd, bufferAlloced, streamData);
+ break;
+ case GC_EVENT_NOTICE:
+ if (pszNick && streamData->lin->ptszText) {
+ Log_AppendRTF(streamData, TRUE, buffer, bufferEnd, bufferAlloced, TranslateT("Notice from %s"), pszNick );
+ AddEventTextToBuffer(buffer, bufferEnd, bufferAlloced, streamData);
+ }
+ 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;
+} } }
+
+
+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 defined( _UNICODE )
+ if (streamData->si->windowData.codePage != CP_ACP) {
+ char *aText = t2acp(streamData->lin->ptszText, CP_ACP);
+ ptszText = ptszTemp = a2tcp(aText, streamData->si->windowData.codePage);
+ mir_free(aText);
+ }
+ #endif
+ 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->si->windowData.hwndLog;
+ event.hContact = streamData->si->windowData.hContact;
+ event.codepage = streamData->si->windowData.codePage;
+ event.pszProto = streamData->si->pszModule;
+ /*
+ if (!fAppend) {
+ event.iType = IEE_CLEAR_LOG;
+ CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&event);
+ }
+ */
+ 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;
+#if defined( _UNICODE )
+ ied.dwFlags = IEEDF_UNICODE_TEXT | IEEDF_UNICODE_NICK | IEEDF_UNICODE_TEXT2;
+#endif
+ ied.next = NULL;
+ /*
+ ied.color = event->color;
+ ied.fontSize = event->iFontSize;
+ ied.fontStyle = event->dwFlags;
+ ied.fontName = getFontName(event->iFont);
+ */
+ CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&event);
+ mir_free(buffer);
+/*
+ iew.cbSize = sizeof(IEVIEWWINDOW);
+ iew.iType = IEW_SCROLLBOTTOM;
+ iew.hwnd = hWndLog;
+ CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&iew);
+*/
+}
+
+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, BOOL ieviewMode)
+{
+ char *buffer, *header;
+ int bufferAlloced, bufferEnd, i;
+ LOGINFO * lin = streamData->lin;
+
+ // guesstimate amount of memory for the RTF
+ bufferEnd = 0;
+ bufferAlloced = streamData->bRedraw ? 1024 * (streamData->si->iEventCount+2) : 2048;
+ buffer = (char *) mir_alloc(bufferAlloced);
+ buffer[0] = '\0';
+
+ // ### RTF HEADER
+ header = streamData->si->pszHeader;
+
+ if (header)
+ AppendToBuffer(&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)
+ {
+ TCHAR szTemp[512], szTemp2[512];
+ TCHAR* pszNick = NULL;
+ streamData->lin = lin;
+
+ if ( lin->ptszNick ) {
+ if ( g_Settings.LogLimitNames && lstrlen( lin->ptszNick ) > 20 ) {
+ lstrcpyn( szTemp2, lin->ptszNick, 20 );
+ lstrcpyn( szTemp2+20, _T("..."), 4);
+ }
+ else lstrcpyn( szTemp2, lin->ptszNick, 511 );
+
+ if ( lin->ptszUserInfo && lin->iType != GC_EVENT_TOPIC)
+ mir_sntprintf( szTemp, SIZEOF(szTemp), _T("%s (%s)"), szTemp2, lin->ptszUserInfo );
+ else
+ mir_sntprintf( szTemp, SIZEOF(szTemp), _T("%s"), szTemp2 );
+ pszNick = szTemp;
+ }
+
+ if (streamData->si->windowData.hwndLog != NULL) {
+ LogEventIEView(streamData, pszNick);
+ }
+ {
+ // create new line, and set font and color
+ if (!streamData->isFirst) {
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\par");
+ }
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "%s ", Log_SetStyle(0, 0));
+ // Insert icon
+ if ((lin->iType&g_Settings.dwIconFlags) || (lin->bIsHighlighted&&g_Settings.dwIconFlags&GC_EVENT_HIGHLIGHT))
+ {
+ int iIndex = (lin->bIsHighlighted&&g_Settings.dwIconFlags&GC_EVENT_HIGHLIGHT) ? 2 : EventToIcon(lin);
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\fs1 ");
+ while (bufferAlloced - bufferEnd < logIconBmpSize[0])
+ bufferAlloced += 4096;
+ buffer = (char *) mir_realloc(buffer, bufferAlloced);
+ CopyMemory(buffer + bufferEnd, pLogIconBmpBits[iIndex], logIconBmpSize[iIndex]);
+ bufferEnd += logIconBmpSize[iIndex];
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " ");
+ }
+
+ 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\\fs%u", iii+1, aFonts[0].lf.lfWeight >= FW_BOLD ? 1 : 0, aFonts[0].lf.lfItalic, 2 * abs(aFonts[0].lf.lfHeight) * 74 / g_dat->logPixelSY);
+ AppendToBuffer(&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\\fs%u", iii+1, aFonts[0].lf.lfWeight >= FW_BOLD ? 1 : 0, aFonts[0].lf.lfItalic, 2 * abs(aFonts[0].lf.lfHeight) * 74 / g_dat->logPixelSY);
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "%s ", szStyle);
+ }
+ }
+ else
+ AppendToBuffer(&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)
+// AppendToBuffer(&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 );
+ }
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\tab ");
+ }
+
+ // Insert the nick
+
+ if (pszNick && lin->iType == GC_EVENT_MESSAGE)
+ {
+ TCHAR pszTemp[300], *p1;
+
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "%s ", Log_SetStyle(lin->bIsMe ? 2 : 1, lin->bIsMe ? 2 : 1));
+ lstrcpyn(pszTemp, lin->bIsMe ? g_Settings.pszOutgoingNick : g_Settings.pszIncomingNick, 299);
+ p1 = _tcsstr(pszTemp, _T("%n"));
+ if (p1)
+ p1[1] = 's';
+
+ Log_AppendRTF(streamData, TRUE, &buffer, &bufferEnd, &bufferAlloced, pszTemp, pszNick);
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " ");
+ }
+
+ // Insert the message
+ i = lin->bIsHighlighted?16:EventToIndex(lin);
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "%s ", Log_SetStyle(i, i));
+ AddEventToBuffer(&buffer, &bufferEnd, &bufferAlloced, streamData, pszNick);
+ }
+ streamData->isFirst = FALSE;
+
+ }
+ lin = lin->prev;
+ }
+
+ // ### RTF END
+ AppendToBuffer(&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->si->windowData.hwndLog != NULL);
+ 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)
+{
+ EDITSTREAM stream;
+ LOGSTREAMDATA streamData;
+ CHARRANGE oldsel, sel, newsel;
+ POINT point ={0};
+ SCROLLINFO scroll;
+ WPARAM wp;
+ HWND hwndRich;
+
+ if (hwndDlg == 0 || lin == 0 || si == 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.isFirst = bRedraw ? 1 : (GetRichTextLength(hwndRich, CP_ACP, FALSE) == 0);
+
+ // bPhaseTwo = bRedraw && bPhaseTwo;
+
+ if (bRedraw || si->iType != GCW_CHATROOM || !si->bFilterEnabled || (si->iLogFilterFlags&lin->iType) != 0)
+ {
+ BOOL bFlag = FALSE;
+
+ 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(hwndRich, 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, CP_ACP, FALSE);
+ SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM) & sel);
+ SendMessage(hwndRich, EM_EXGETSEL, 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)
+ {
+ SendMessage(hwndRich, WM_SETREDRAW, FALSE, 0);
+ bFlag = TRUE;
+// SetCursor(LoadCursor(NULL, IDC_CHAT_ARROW));
+ }
+
+ // stream in the event(s)
+ streamData.lin = lin;
+ streamData.bRedraw = bRedraw;
+ SendMessage(hwndRich, EM_STREAMIN, wp, (LPARAM) & stream);
+
+ // do smileys
+ if (g_dat->smileyAddInstalled && (bRedraw
+ || (lin->ptszText
+ && lin->iType != GC_EVENT_JOIN
+ && lin->iType != GC_EVENT_NICK
+ && lin->iType != GC_EVENT_ADDSTATUS
+ && lin->iType != GC_EVENT_REMOVESTATUS )))
+ {
+ SMADD_RICHEDIT3 sm;
+
+ 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.flags = 0;
+ sm.disableRedraw = TRUE;
+ sm.hContact = si->windowData.hContact;
+ CallService(MS_SMILEYADD_REPLACESMILEYS, 0, (LPARAM)&sm);
+ }
+
+ // 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, CP_ACP, FALSE);
+ SendMessage(hwndRich, EM_EXSETSEL, 0, (LPARAM) & sel);
+ SendMessage(hwndRich, WM_SETREDRAW, TRUE, 0);
+ InvalidateRect(hwndRich, NULL, TRUE);
+} } }
+
+char * Log_CreateRtfHeader(MODULEINFO * mi, SESSION_INFO* si)
+{
+ char *buffer;
+ int bufferAlloced, bufferEnd, i = 0;
+ int charset = 0;
+ BOOL forceCharset = FALSE;
+
+#if !defined ( _UNICODE )
+ if (si->windowData.codePage != CP_ACP) {
+ CHARSETINFO csi;
+ if(TranslateCharsetInfo((DWORD*)si->windowData.codePage, &csi, TCI_SRCCODEPAGE)) {
+ forceCharset = TRUE;
+ charset = csi.ciCharset;
+ }
+ }
+#endif
+ // guesstimate amount of memory for the RTF header
+ bufferEnd = 0;
+ bufferAlloced = 4096;
+ buffer = (char *) mir_realloc(si->pszHeader, bufferAlloced);
+ buffer[0] = '\0';
+
+ // ### RTF HEADER
+
+ // font table
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "{\\rtf1\\ansi\\deff0{\\fonttbl");
+ for (i = 0; i < OPTIONS_FONTCOUNT; i++) {
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "{\\f%u\\fnil\\fcharset%u" TCHAR_STR_PARAM ";}", i, (!forceCharset) ? aFonts[i].lf.lfCharSet : charset, aFonts[i].lf.lfFaceName);
+ }
+ // colour table
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}{\\colortbl ;");
+
+ for (i = 0; i < OPTIONS_FONTCOUNT; i++)
+ AppendToBuffer(&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++)
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(mi->crColors[i]), GetGValue(mi->crColors[i]), GetBValue(mi->crColors[i]));
+
+ // new paragraph
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}\\pard");
+
+ // set tabs and indents
+ {
+ int iIndent = 0;
+
+ if (g_Settings.dwIconFlags)
+ {
+ iIndent += (14*1440)/g_dat->logPixelSX;
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\tx%u", iIndent);
+ }
+ if (g_Settings.ShowTime)
+ {
+ int iSize = (g_Settings.LogTextIndent*1440)/g_dat->logPixelSX;
+ AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\tx%u", iIndent + iSize );
+ if (g_Settings.LogIndentEnabled)
+ iIndent += iSize;
+ }
+ AppendToBuffer(&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;
+
+ hBkgBrush = CreateSolidBrush(DBGetContactSettingDword(NULL, "Chat", "ColorLogBG", GetSysColor(COLOR_WINDOW)));
+ bih.biSize = sizeof(bih);
+ bih.biBitCount = 24;
+ bih.biCompression = BI_RGB;
+ bih.biHeight = 10; //GetSystemMetrics(SM_CYSMICON);
+ bih.biPlanes = 1;
+ bih.biWidth = 10; //GetSystemMetrics(SM_CXSMICON);
+ widthBytes = ((bih.biWidth * bih.biBitCount + 31) >> 5) * 4;
+ rc.top = rc.left = 0;
+ rc.right = bih.biWidth;
+ rc.bottom = bih.biHeight;
+ 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 = GetCachedIcon(logIconNames[i]);
+ pLogIconBmpBits[i] = (PBYTE) mir_alloc(RTFPICTHEADERMAXSIZE + (bih.biSize + widthBytes * bih.biHeight) * 2);
+ rtfHeaderSize = sprintf(pLogIconBmpBits[i], "{\\pict\\dibitmap0\\wbmbitspixel%u\\wbmplanes1\\wbmwidthbytes%u\\picw%u\\pich%u ", bih.biBitCount, widthBytes, (unsigned int)bih.biWidth, (unsigned int)bih.biHeight);
+ hoBmp = (HBITMAP) SelectObject(hdcMem, hBmp);
+ FillRect(hdcMem, &rc, hBkgBrush);
+ DrawIconEx(hdcMem, 0, 0, hIcon, bih.biWidth, bih.biHeight, 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(pLogIconBmpBits[i] + rtfHeaderSize + n * 2, "%02X", ((PBYTE) & bih)[n]);
+ for (n = 0; n < widthBytes * bih.biHeight; n += 4)
+ sprintf(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);
+}
+
+void FreeMsgLogBitmaps(void)
+{
+ int i;
+ for (i = 0; i < SIZEOF(pLogIconBmpBits); i++)
+ mir_free(pLogIconBmpBits[i]);
+}
diff --git a/plugins/Scriver/chat/m_uninstaller.h b/plugins/Scriver/chat/m_uninstaller.h new file mode 100644 index 0000000000..15cd268452 --- /dev/null +++ b/plugins/Scriver/chat/m_uninstaller.h @@ -0,0 +1,700 @@ +/*
+
+ PluginUninstaller 1.1.2.1 for Miranda IM 0.3.3a and +
+ ------------------------------------------------------------------------
+ Developers - C/C++ Header File
+
+ Plugin Info: ----------------------------
+ | Version: 1.1.2.1
+ | Filename: uninstaller.dll
+ | Author: H. Herkenrath (hrathh@users.sourceforge.net)
+ | Description: Extends the plugin options and offers the possibility
+ | to directly remove plugins and delete all associated
+ | settings and files.
+
+ Contents: -------------------------------
+ | > General Info:
+ | - Uninstall Example/Template
+ | - Changing displayed icon
+ | - Changing displayed docs
+ | - Message boxes on uninstall
+ | - Service Accesibility
+ | - Including this file
+ |
+ | > Structs:
+ | - Uninstall Params (PLUGINUNINSTALLPARAMS)
+ |
+ | > Helpers:
+ | - Macro: Run service while uninstalling (PUICallService)
+ | - Function: Remove some files in directory (PUIRemoveFilesInDirectory)
+ |
+ | > Events:
+ | - Allow to uninstall a plugin (ME_PLUGINUNINSTALLER_OKTOUNINSTALL)
+ | - Plugin gets uninstalled (ME_PLUGINUNINSTALLER_UNINSTALL)
+ |
+ | > Services:
+ | - Remove database module (MS_PLUGINUNINSTALLER_REMOVEDBMODULE)
+ | - Remove a setting globally (MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY)
+ | - Remove skinned sound (MS_PLUGINUNINSTALLER_REMOVESKINSOUND)
+ | - Uninstall a plugin (MS_PLUGINUNISTALLER_UNISTALLPLUGIN)
+ | - Getting handles (MS_PLUGINUNINSTALLER_GETHANDLE)
+ |
+
+
+ This file is only thought for plugin developers.
+ If you only want to use "PluginUninstaller" and don't want to develop a plugin
+ or something with it you don't need this file.
+
+ If there are any problems or bugs with or in this file or something else
+ please mail me. My e-mail address is: hrathh@users.sourceforge.net
+ For more documentation you can use this address, too. :-)
+
+ If you have any whishes on some plugin uninstalling for your
+ plugin you can mail me, too. :-)
+
+*/
+#ifndef M_UNINSTALLER_H
+#define M_UNINSTALLER_H
+
+#ifndef CallService
+ #pragma message("Mistake Alert!: "m_uninstaller.h" needs to be included after "newpluginapi.h"!\n The following errors are resulting of this mistake.\n")
+#endif
+
+
+// | General Info
+// -----------------------------
+
+// Uninstall Example/Template
+// ---------------------------
+// Making your plugin uninstallable is very easy.
+// Just add the following "Uninstall" function near the "Unload" function
+// in your plugin.
+// A template plugin is available in the source code package.
+
+// Old:
+// int __declspec(dllexport) Uninstall(BOOL bIsMirandaRunning, BOOL bDoDeleteSettings, char* pszPluginPath);
+
+// New:
+//int __declspec(dllexport) UninstallEx(PLUGINUNINSTALLPARAMS* ppup)
+//{
+ // Available Variables:
+ // -----------------------------
+ // ppup->bIsMirandaRunning:
+ // Contains if Miranda is running
+ // (Currently this is always TRUE).
+
+ // ppup->bDoDeleteSettings:
+ // Contains if the users selected
+ // that he wants all settings be deleted.
+
+ // ppup->pszPluginsPath:
+ // Contains the plugins directory name.
+
+
+ // Notes:
+ // -----------------------------
+
+ // Run before "Unload" function:
+ // -> IMPORTANT: Be careful not to write to the database or to files in "Unload" again!!!
+ // -> Perhaps create a global BOOL variable which is set to TRUE when your plugin gets uninstalled
+ // or check of a database setting "IsInstalled" in Unload() or sth. like that
+
+ // All Miranda is still loaded
+
+ // Here you can do:
+ // - Delete settings group in database
+ // - Delete registry items
+ // - Delete ini-files and other settings files
+ // - Delete other files
+
+ // Your plugin dll gets automatically deleted
+
+ // Services to remove are offered:
+ // MS_PLUGINUNINSTALLER_REMOVEDBMODULE
+ // MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY
+ // MS_PLUGINUNINSTALLER_REMOVESKINSOUND
+
+
+ // Getting other useful paths:
+ // -----------------------------
+
+ // System directory:
+
+ //char szSysPath[MAX_PATH];
+ //GetSystemDirectory(szSysPath, MAX_PATH);
+
+
+ // Windows directory:
+
+ //char szWinPath[MAX_PATH];
+ //GetWindowsDirectory(szWinPath, MAX_PATH);
+
+
+ // Other directories:
+
+ // char szPath[MAX_PATH];
+ // SHGetSpecialFolderPath(NULL, szPath, CSIDL_* , FALSE);
+
+ // Some available dirs:
+ // CSIDL_APPDATA CSIDL_SENDTO CSIDL_FAVORITES
+ // CSIDL_STARTUP CSIDL_PROFILE CSIDL_DESKTOPDIRECTORY
+
+
+ // Delete Files
+ //const char* apszFiles[] = {"MyPlugin_Readme.txt", "MyPlugin_License.txt", "MyPlugin_Developer.txt", "MyPlugin_Translation.txt"};
+ //PUIRemoveFilesInPath(ppup->pszPluginsPath, apszFiles);
+
+ // Delete Settings
+ //if(ppup->bDoDeleteSettings == TRUE)
+ //{
+ //if (ppup->bIsMirandaRunning == TRUE) // Check if it is possible to access services
+ //{
+ // Remove plugin's module
+ //PUIRemoveDbModule("MyPlugin");
+
+ // Remove plugin's sounds
+ //PUIRemoveSkinSound("MySoundSetting1");
+ //PUIRemoveSkinSound("MySoundSetting2");
+ //}
+ //}
+
+ // Remember:
+ // Do not forget to remove your (eventually) created registry items here, too.
+
+
+ // The plugin's dll file gets deleted after returning.
+
+ // Remember:
+ // If your DLL file is additionally in use by another application (eg. Windows)
+ // you need to free the DLL *here* completely. Otherwise it can't be deleted.
+
+// return 0;
+//}
+
+
+
+// Changing displayed icon
+// ---------------------------
+// The icon that gets displayed on the options page is always the "first"
+// icon in your DLL file.
+// An icon in your DLL file is the first icon when it has the lowest recource ID.
+// If you would like to have an other icon shown in the options please change your
+// icon resource IDs so that the icon you would like to have has the lowest one.
+// For example if you use MS Visual C++, open "resource.h" and change the resource define
+// of your prefered icon to the lowest icon number.
+
+
+// Changing displayed docs
+// ---------------------------
+// The items "License" and "More Information" on the plugin details page
+// are created when the a license and/or a readme file for the plugin exists.
+// The files get detected automatically and need a special name
+// so that they get detected.
+// The text files need to be either placed in the "Plugins" directory or
+// in the "Docs" directory. Whereof the last one is the better one :-)
+//
+// For the license file the following file name formatings are possible:
+// PluginName-License.txt (I personally think that this is the best naming solution... :-) )
+// PluginName_License.txt,
+//
+// For the readme file the following ones are possible:
+// PluginName-Readme.txt (Again...I like this one :-D ),
+// PluginName_Readme.txt,
+
+// Message boxes on uninstall
+// ---------------------------
+// If you would like to ask the user for something to remove/uninstall
+// please hook the event ME_PLUGINUNINSTALLER_UNINSTALL and show your
+// message box there. Save the action the user chose in a
+// global BOOL variable and do the chosen action in "UninstallEx".
+// You can get the plugins options window handle with MS_PLUGINUNINSTALLER_GETHANDLE.
+
+
+// Service Accessibility
+// ---------------------------
+// Remember that you only can use these functions after the event ME_SYSTEM_MODULESLOADED
+// or later because "PluginUninstaller" needs to be loaded first.
+// Normally you only use them in your "UninstallEx" function.
+//
+// IMPORTANT!:
+// Please make sure that you always use the macro PUICallService
+// in the "UninstallEx" function instead of the CallService function.
+
+
+// Including this file
+// ---------------------------
+// To use some of the uninstalling functionality you have to include this file
+// into your project.
+//
+// IMPORTANT!:
+// Please make sure that you include the file "newpluginapi.h" before this one.
+// If this isn't the case there may some compile errors come up.
+
+ // -> Example:
+ // If your plugin is in the directory "Plugins/MyPlugin/" and
+ // this include file is in the directory "Plugins/PluginUninstaller"
+ // you can use the following:
+
+ //#include "../PluginUninstaller/m_uninstaller.h"
+
+ // If your plugin is in an directory that is different to that one just
+ // change the include path to the one you want.
+
+
+
+
+
+// | Structs
+// -----------------------------
+
+// ---------------------------------------------
+// -- Struct: Uninstall Params -----------------
+// ---------------------------------------------
+
+// Struct: PLUGINUNINSTALLPARAMS
+// (Gets passed to "UninstallEx" function)
+
+typedef int (*HELPERPROC)(const char*, WPARAM, LPARAM); // Used internally (for pHelperProcAddress)
+
+typedef struct {
+ BOOL bIsMirandaRunning; // Is TRUE when Miranda is loaded and services are available (Please use PUICallService instead of CallService)
+ BOOL bDoDeleteSettings; // Is TRUE when user wants to delete settings (If this is FALSE, please only delete your files)
+ char* pszPluginsPath; // Contains the plugin directory path
+ char* pszDocsPath; // Contains the document directory for plugins documentation (Added in version 1.1.1.0)
+ char* pszIconsPath; // Contains the icon directory for icon dlls (Added in version 1.1.2.0)
+ HELPERPROC pHelperProcAddress; // Used internally (Contains proc address for PUICallService)
+} PLUGINUNINSTALLPARAMS;
+
+
+
+
+
+// | Helper
+// -----------------------------
+
+
+// ---------------------------------------------
+// -- Macro: Run service while uninstalling ----
+// ---------------------------------------------
+
+// Macro: PUICallService
+
+#define PUICallService(service, wParam, lParam) (ppup->pHelperProcAddress) (service, wParam, lParam);
+
+// Description:
+// -------------
+// This service provides the possibility to call a Miranda
+// service in the "UninstallEx" function.
+// Important!: Use this macro always instead of "CallService",
+// because else a crash occurs when the plugin was decativated
+// and gets uninstalled
+
+// Parameters:
+// -------------
+// Same parameters as CallService of Miranda Core.
+
+// Return Values:
+// --------------
+// Return values are the same as the CallService function of Miranda Core.
+// Additionaly returns CALLSERVICE_NOTFOUND if Miranda is not loaded
+// which means the services are not accessable.
+
+
+ // Example:
+ // ----------------------------------
+
+ //if ( (bIsMirandaRunning == TRUE) && (bDoDeleteSettings == TRUE) )
+ //{
+ // Remove plugin's module
+ //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)"MyPlugin", 0);
+ //}
+
+
+
+
+// ---------------------------------------------
+// -- Function: Remove some files in directory -
+// ---------------------------------------------
+
+// Function: PUIRemoveFilesInDirectory
+
+static BOOL __inline PUIRemoveFilesInDirectory(char* pszPath, const char* apszFiles[]);
+
+// Description:
+// -------------
+// This helper provides the possibility to easily
+// remove specified files in a specified directory.
+
+// Note: The last version of this helper (PUIRemoveFilesInPath)
+// did not work correctly.
+// Please do now always append a NULL slot to the end of your array.
+
+// Parameters:
+// -------------
+// char* pszPath = Path to the files in array
+// const LPCSTR apszFiles[] = NULL-terminated array of files to be deleted.
+
+// Return Values:
+// --------------
+// Returns TRUE if the files could be deleted.
+// FALSE if the files could not be deleted or did not exist.
+
+
+static BOOL __inline PUIRemoveFilesInDirectory(char* pszPath, const char* apszFiles[])
+{
+ char szFile[MAX_PATH];
+ BOOL bReturn = FALSE;
+ int iFile = 0;
+
+ while (apszFiles[iFile] != NULL)
+ {
+ strncpy(szFile, pszPath, SIZEOF(szFile));
+ strncat(szFile, apszFiles[iFile], SIZEOF(szFile)-strlen(szFile));
+
+ if ((BOOL)DeleteFile(szFile) == TRUE) bReturn = TRUE;
+ iFile++;
+ }
+
+ return bReturn;
+}
+
+ // Example:
+ // ----------------------------------
+
+ //const char* apszFiles[] = {"File1.txt", "File2.txt", "File3.txt", NULL};
+ //PUIRemoveFilesInDirectory(ppup->pszPluginsPath, apszFiles);
+
+
+
+
+// | Events
+// -----------------------------
+
+
+// ---------------------------------------------
+// -- Event: Allow to uninstall a plugin -------
+// ---------------------------------------------
+
+// Event: ME_PLUGINUNINSTALLER_OKTOUNINSTALL
+
+#define ME_PLUGINUNINSTALLER_OKTOUNINSTALL "PluginUninstaller/OkToUninstall"
+
+// Submitted Values:
+// -----------------
+// wParam = pszPluginName (String containing the translated plugin name)
+// lParam = pszPluginFile (String containing the plugin dll file name in lower case)
+
+// Return Values:
+// -----------------
+// Returning 1 on this event causes the "Remove Plugin" button to be disabled.
+
+
+
+// ---------------------------------------------
+// -- Event: Plugin gets uninstalled -----------
+// ---------------------------------------------
+
+// Event: ME_PLUGINUNINSTALLER_UNINSTALL
+
+#define ME_PLUGINUNINSTALLER_UNINSTALL "PluginUninstaller/Uninstall"
+
+// Submitted Values:
+// -----------------
+// wParam = pszPluginName (String containing the translated plugin name)
+// lParam = pszPluginFile (String containing the plugin dll file name in lower case)
+
+// Return Values:
+// -----------------
+// Returning 1 on this event causes the uninstall process to be canceled.
+
+// Notice:
+// Hook this event if you would like to ask the user for something to remove/uninstall
+// and show your message box on this event. Save the action the user chose in a
+// global BOOL variable and do the chosen action in "UninstallEx".
+// You can get the plugins options window handle with MS_PLUGINUNINSTALLER_GETHANDLE.
+
+// Other plugins can use this event to be noticed that another plugin isn't installed anylonger.
+
+
+
+
+// | Services
+// -----------------------------
+
+
+// ---------------------------------------------
+// -- Service: Remove database module ----------
+// ---------------------------------------------
+
+// Service: MS_PLUGINUNINSTALLER_REMOVEDBMODULE
+
+#define MS_PLUGINUNINSTALLER_REMOVEDBMODULE "PluginUninstaller/RemoveDbModule"
+
+// Description:
+// -------------
+// This service provides the possibility to delete all database modules
+// associated to your plugin.
+// The specified database module will be removed in all contacts
+// including the NULL contact.
+// Remember to call it always with PUICallService in "UninstallEx" function.
+
+// Parameters:
+// -------------
+// wParam = (char*)pszModule // Pointer to a string containd module name. Can't be NULL
+// lParam = (const char*)apszIgnoreSettings // NULL terminated array of strings. Can be 0 if no settings should be ignored.
+ // See example 3 for more details
+
+// Return Values:
+// --------------
+// Returns 0 on success.
+// Nonzero if the module was not present in database.
+
+
+#ifndef UNINSTALLER_NOHELPERS
+
+// Can only be used in "UninstallEx" function
+#define PUIRemoveDbModule(pszModule) PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)pszModule, 0);
+
+#endif
+
+
+ // Example 1:
+ // ----------------------------------
+
+ //PUIRemoveDbModule("MyPlugin");
+
+
+ // Example 2:
+ // ----------------------------------
+
+ //char szModule[] = "MyModule";
+ //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)szModule, 0);
+
+
+ // Example 3:
+ // ----------------------------------
+
+ // This deletes all settings in the specified module exept
+ // the specified settings: "Setting1",..."Setting4"
+
+ // char szModule[] = "MyModule";
+ // const char* apszIgnoreSettings[] = {"Setting1", "Setting2", "Setting3", "Setting4", NULL};
+ // PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)szModule, (LPARAM)&apszIgnoreSettings);
+
+
+
+// ---------------------------------------------
+// -- Service: Remove a setting globally -------
+// ---------------------------------------------
+
+// Service: MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY
+
+#define MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY "PluginUninstaller/RemoveDbSettingGlobally"
+
+// Description:
+// -------------
+// This service provides the possibility to delete a specific
+// setting in database in all contacts including the NULL contact.
+// Remember to call it always with PUICallService in "UninstallEx" function.
+
+// Parameters:
+// -------------
+// wParam = (char*)pszModule
+// lParam = (char*)pszSetting
+
+// Return Values:
+// --------------
+// Returns 0 on success.
+// Nonzero if the setting was not present in database.
+
+
+#ifndef UNINSTALLER_NOHELPERS
+
+// Can only be used in "UninstallEx" function
+#define PUIRemoveDbSettingGlobally(pszModule, pszSetting) PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY, (WPARAM)pszModule, (LPARAM)pszSetting);
+
+
+#endif
+
+
+ // Example 1:
+ // ----------------------------------
+
+ //PUIRemoveDbSettingGlobally("MyPlugin", "MySetting");
+
+
+ // Example 2:
+ // ----------------------------------
+
+ //szModule[] = "MyPlugin";
+ //szSetting[] = "MySetting";
+ //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY, (WPARAM)szModule, (LPARAM)szSetting);
+
+
+
+
+
+
+// ---------------------------------------------
+// -- Service: Remove skinned sound ------------
+// ---------------------------------------------
+
+// Service: MS_PLUGINUNINSTALLER_REMOVESKINSOUND
+
+#define MS_PLUGINUNINSTALLER_REMOVESKINSOUND "PluginUninstaller/RemoveSkinSound"
+
+// Description:
+// -------------
+// This service provides the possibility to delete all your sound settings
+// associated to your plugin.
+// The specified sound will be be removed.
+// Remember to call it always with PUICallService in "UninstallEx" function.
+
+// Parameters:
+// -------------
+// wParam = (char*)pszSoundSetting
+// lParam = 0
+
+// Return Values:
+// --------------
+// Returns 0 on success.
+// Nonzero if the sound was not present in database.
+
+
+#ifndef UNINSTALLER_NOHELPERS
+
+// Can only be used in "UninstallEx" function
+#define PUIRemoveSkinSound(pszSoundSetting) PUICallService(MS_PLUGINUNINSTALLER_REMOVESKINSOUND, (WPARAM)pszSoundSetting, 0);
+
+#endif
+
+
+ // Example 1:
+ // ----------------------------------
+
+ //PUIRemoveSkinSound("MySoundSetting");
+
+
+ // Example 2:
+ // ----------------------------------
+
+ //szSoundModule[] = "MySoundSetting";
+ //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)szSoundSetting, 0);
+
+
+
+
+
+// ---------------------------------------------
+// -- Service: Uninstall a plugin --------------
+// ---------------------------------------------
+
+// Service: MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN
+
+#define MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN "PluginUninstaller/UninstallPlugin"
+
+// Description:
+// -------------
+// This service marks a plugin to be uninstalled at next restart of Miranda IM.
+// It uses the default value for "Delete all settings".
+// You can use this service for example when you want that your sub-plugin gets
+// also removed when your main-plugin is uninstalled.
+// Note: This service is not needed for the normal uninstalling functionality.
+
+// Parameters:
+// -------------
+// wParam = (char*)pszPluginName // do not translate this!
+// lParam = (char*)pszPluginFile // without path, only file name!
+
+// Return Values:
+// --------------
+// Returns always 0.
+
+
+#ifndef UNINSTALLER_NOHELPERS
+
+int __inline PUIUninstallPlugin(char* pszPluginName, char* pszPluginFile)
+{
+ return CallService(MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN, (WPARAM)pszPluginName, (LPARAM)pszPluginFile);
+}
+
+#endif
+
+
+ // Example 1:
+ // ----------------------------------
+
+ //PUIUninstallPlugin("PluginName", "plugin.dll");
+
+
+ // Example 2:
+ // ----------------------------------
+
+ // hInst => Handle of a specific (your?) plugin
+ // char szPluginName[] = "YourPluginName";
+
+ //char* pFileName;
+ //char szPath[MAX_PATH];
+
+ //GetModuleFileName(hInst, szPath, sizeof(szPath));
+ //pFileName = strrchr(szPath, '\\');
+ //pFileName = pFileName+1; // Pointer arithmetic
+
+ //CallService(MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN, (WPARAM)szPluginName, (LPARAM)pFileName);
+
+
+
+
+// ---------------------------------------------
+// -- Service: Getting handles -----------------
+// ---------------------------------------------
+
+// Service: MS_PLUGINUNINSTALLER_GETHANDLE
+
+#define MS_PLUGINUNINSTALLER_GETHANDLE "PluginUninstaller/GetHandle"
+
+// Description:
+// -------------
+// This service gets a specified window/instance handle.
+
+// Note: This service must not be used in "UninstallEx" function.
+// It is mainly thought for being used in ME_PLUGINUNINSTALLER_UNINSTALL event
+// to give out a MessageBox or something like that.
+
+// Parameters:
+// -------------
+// wParam = UINT uHandleType;
+// lParam = 0
+
+// Possible values for wParam:
+#define PUIHT_HINST_PLUGIN_INSTANCE 0 // HINSTANCE of the PluginUninstaller plugin
+#define PUIHT_HWND_PLUGIN_OPTIONS 1 // HWND of the plugin options dialog (if it is loaded; else NULL)
+
+// Return Values:
+// --------------
+// Returns the specified handle value.
+// If no handle type is specified it returns NULL.
+// The handle doesn't need to be destroyed.
+
+
+#ifndef UNINSTALLER_NOHELPERS
+
+HANDLE __inline PUIGetHandle(UINT uHandleType)
+{
+ return (HANDLE)CallService(MS_PLUGINUNINSTALLER_GETHANDLE, uHandleType, 0);
+}
+
+#endif
+
+
+ // Example
+ // ----------------------------------
+
+ //HWND hwndDlg;
+ //hwndDlg = (HWND)PUIGetHandle(PUIHT_HWND_PLUGIN_OPTIONS);
+
+
+
+
+
+#endif // M_UNINSTALLER_H
diff --git a/plugins/Scriver/chat/main.c b/plugins/Scriver/chat/main.c new file mode 100644 index 0000000000..115eca156d --- /dev/null +++ b/plugins/Scriver/chat/main.c @@ -0,0 +1,111 @@ +/*
+Chat module plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+Copyright 2003-2009 Miranda ICQ/IM project,
+
+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.
+*/
+
+#include "../commonheaders.h"
+#include "chat.h"
+
+void RegisterChatFonts( void );
+
+extern struct GlobalMessageData *g_dat;
+extern CRITICAL_SECTION cs;
+//globals
+HINSTANCE g_hInst;
+HMENU g_hMenu = NULL;
+HANDLE hJoinMenuItem, hLeaveMenuItem;
+
+FONTINFO aFonts[OPTIONS_FONTCOUNT];
+HBRUSH hListBkgBrush = NULL;
+HBRUSH hListSelectedBkgBrush = NULL;
+
+TCHAR* pszActiveWndID = 0;
+char* pszActiveWndModule = 0;
+
+struct GlobalLogSettings_t g_Settings;
+
+int Chat_Load()
+{
+ InitializeCriticalSection(&cs);
+ g_hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_MENU));
+ CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM) g_hMenu, 0);
+ HookEvents();
+ CreateServiceFunctions();
+ CreateHookableEvents();
+ return 0;
+}
+
+int Chat_Unload(void)
+{
+ DBWriteContactSettingWord(NULL, "Chat", "SplitterX", (WORD)g_Settings.iSplitterX);
+
+ CList_SetAllOffline(TRUE, NULL);
+
+ mir_free( pszActiveWndID );
+ mir_free( pszActiveWndModule );
+
+ DestroyHookableEvents();
+
+ DestroyMenu(g_hMenu);
+ FreeIcons();
+ OptionsUnInit();
+ DeleteCriticalSection(&cs);
+ return 0;
+}
+
+int Chat_ModulesLoaded(WPARAM wParam,LPARAM lParam)
+{
+ char* mods[3] = { "Chat", "ChatFonts" };
+ CallService( "DBEditorpp/RegisterModule", (WPARAM)mods, 2 );
+ RegisterChatFonts();
+ OptionsInit();
+ 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 = ( HANDLE )CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) & 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 = ( HANDLE )CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM) & mi);
+ }
+ CList_SetAllOffline(TRUE, NULL);
+ return 0;
+}
+
+
+void LoadIcons(void)
+{
+ LoadMsgLogBitmaps();
+ return ;
+}
+
+void FreeIcons(void)
+{
+ FreeMsgLogBitmaps();
+ return;
+}
diff --git a/plugins/Scriver/chat/manager.c b/plugins/Scriver/chat/manager.c new file mode 100644 index 0000000000..62542fd14a --- /dev/null +++ b/plugins/Scriver/chat/manager.c @@ -0,0 +1,1402 @@ +/*
+Chat module plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+Copyright 2003-2009 Miranda ICQ/IM project,
+
+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.
+*/
+
+#include "../commonheaders.h"
+#include "chat.h"
+
+extern TCHAR* pszActiveWndID ;
+extern char* pszActiveWndModule ;
+extern struct MM_INTERFACE mmi ;
+
+extern struct GlobalMessageData *g_dat;
+
+void LoadModuleIcons(MODULEINFO * mi);
+
+#define WINDOWS_COMMANDS_MAX 30
+#define STATUSICONCOUNT 6
+
+SESSION_INFO* m_WndList = 0;
+TABLIST * g_TabList = 0;
+MODULEINFO *m_ModList = 0;
+
+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 );
+ node->windowData.flags = CWDF_RTF_INPUT;
+
+ if (m_WndList == NULL) { // list is empty
+ m_WndList = node;
+ node->next = NULL;
+ }
+ else {
+ node->next = m_WndList;
+ m_WndList = node;
+ }
+ return node;
+ }
+ return NULL;
+}
+
+int SM_RemoveSession( const TCHAR* pszID, const char* pszModule)
+{
+ 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
+ {
+ 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->windowData.hContact)
+ {
+ CList_SetOffline(pTemp->windowData.hContact, pTemp->iType == GCW_CHATROOM?TRUE:FALSE);
+/* if (pTemp->iType != GCW_SERVER)
+ DBWriteContactSettingByte(pTemp->windowData.hContact, "CList", "Hidden", 1);*/
+ }
+ DBWriteContactSettingString(pTemp->windowData.hContact, pTemp->pszModule , "Topic", "");
+ DBWriteContactSettingString(pTemp->windowData.hContact, pTemp->pszModule, "StatusBar", "");
+ DBDeleteContactSetting(pTemp->windowData.hContact, "CList", "StatusMsg");
+
+ mir_free( pTemp->pszModule );
+ mir_free( pTemp->ptszID );
+ mir_free( pTemp->ptszName );
+ mir_free( pTemp->ptszStatusbarText );
+ mir_free( pTemp->ptszTopic );
+ mir_free( pTemp->pszHeader );
+ #if defined( _UNICODE )
+ mir_free( pTemp->pszID );
+ mir_free( pTemp->pszName );
+ #endif
+
+ // delete commands
+ tcmdlist_free(pTemp->windowData.cmdList);
+ 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;
+
+ if ( !pszID || !pszModule )
+ return NULL;
+
+ while ( pTemp != NULL ) {
+ if ( !lstrcmpi( pTemp->ptszID, pszID ) && !lstrcmpiA(pTemp->pszModule,pszModule))
+ return pTemp;
+
+ pTemp = pTemp->next;
+ }
+ return NULL;
+}
+
+HWND SM_FindWindowByContact(HANDLE hContact)
+{
+ SESSION_INFO *pTemp = m_WndList;
+
+ while ( pTemp != NULL ) {
+ if ( pTemp->windowData.hContact == hContact)
+ return pTemp->hWnd;
+
+ 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_CHAT_LIST), NULL, NULL, RDW_INVALIDATE);
+ if (pszID)
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+char SM_GetStatusIndicator(SESSION_INFO* si, USERINFO * ui)
+{
+ STATUSINFO * ti;
+ if (!ui || !si)
+ return '\0';
+
+ ti = TM_FindStatus(si->pStatuses, TM_WordToString(si->pStatuses, ui->Status));
+ if (ti)
+ {
+ if ((INT_PTR)ti->hIcon < STATUSICONCOUNT)
+ {
+ INT_PTR id = si->iStatusCount - (INT_PTR)ti->hIcon - 1;
+ if (id == 0)
+ return '\0';
+ if (id == 1)
+ return '+';
+ if (id == 2)
+ return '%';
+ if (id == 3)
+ return '@';
+ if (id == 4)
+ return '!';
+ if (id == 5)
+ return '*';
+ }
+ else
+ return '\0';
+ }
+ return '\0';
+}
+
+HICON SM_GetStatusIcon(SESSION_INFO* si, USERINFO * ui)
+{
+ STATUSINFO * ti;
+ if (!ui || !si)
+ return NULL;
+
+ ti = TM_FindStatus(si->pStatuses, TM_WordToString(si->pStatuses, ui->Status));
+ if (ti)
+ {
+ if ((INT_PTR)ti->hIcon < STATUSICONCOUNT)
+ {
+ INT_PTR id = si->iStatusCount - (INT_PTR)ti->hIcon - 1;
+ char name[128];
+ sprintf(name, "chat_status%d", id);
+ return GetCachedIcon(name);
+ }
+ else
+ return ti->hIcon;
+ }
+ return GetCachedIcon("chat_status0");
+}
+
+BOOL SM_AddEventToAllMatchingUID(GCEVENT * gce)
+{
+ 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, FALSE, 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 + 20) {
+ LM_TrimLog(&pTemp->pLog, &pTemp->pLogEnd, pTemp->iEventCount - g_Settings.iEventLimit);
+ pTemp->iEventCount = g_Settings.iEventLimit;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ pLast = pTemp;
+ pTemp = pTemp->next;
+ }
+ return TRUE;
+}
+
+USERINFO * SM_AddUser( SESSION_INFO * si, const TCHAR* pszUID, const TCHAR* pszNick, WORD wStatus)
+{
+ USERINFO * p = UM_AddUser( si->pStatuses, &si->pUsers, pszUID, pszNick, wStatus);
+ si->nUsersInNicklist++;
+ return p;
+}
+
+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_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->windowData.hContact ) {
+ if ( pTemp->iType != GCW_SERVER && wStatus != ID_STATUS_OFFLINE )
+ DBDeleteContactSetting(pTemp->windowData.hContact, "CList", "Hidden");
+
+ DBWriteContactSettingWord(pTemp->windowData.hContact, pTemp->pszModule, "Status", (WORD)wStatus);
+ }
+
+ PostMessage(pTemp->hWnd, GC_FIXTABICONS, 0, 0);
+
+ 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 (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->windowData.hContact)
+ CList_SetOffline(m_WndList->windowData.hContact, m_WndList->iType == GCW_CHATROOM?TRUE:FALSE);
+ DBWriteContactSettingString(m_WndList->windowData.hContact, m_WndList->pszModule , "Topic", "");
+ DBDeleteContactSetting(m_WndList->windowData.hContact, "CList", "StatusMsg");
+ DBWriteContactSettingString(m_WndList->windowData.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 );
+ mir_free( m_WndList->pszHeader);
+ tcmdlist_free(m_WndList->windowData.cmdList);
+ mir_free(m_WndList);
+ m_WndList = pLast;
+ }
+ m_WndList = NULL;
+ return TRUE;
+}
+
+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_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;
+
+}
+
+char* SM_GetUsers(SESSION_INFO* si)
+{
+ SESSION_INFO* pTemp = m_WndList;
+ USERINFO* utemp = NULL;
+ 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 = mir_realloc( p, alloced += 4096 );
+
+ #if !defined( _UNICODE )
+ lstrcpy( p + pLen, utemp->pszUID );
+ #else
+ WideCharToMultiByte( CP_ACP, 0, utemp->pszUID, -1, p + pLen, nameLen+1, 0, 0 );
+ #endif
+ lstrcpyA( p + pLen + nameLen, " " );
+ utemp = utemp->next;
+ }
+ while ( utemp != NULL );
+ return p;
+}
+
+
+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;
+
+}
+
+
+//---------------------------------------------------
+// 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_calloc(sizeof(MODULEINFO));
+
+ node->pszModule = mir_strdup(pszModule);
+
+ if (m_ModList == NULL) // list is empty
+ {
+ m_ModList = node;
+ }
+ else
+ {
+ node->next = m_ModList;
+ m_ModList = node;
+ }
+ return node;
+ }
+ return FALSE;
+}
+
+void MM_IconsChanged(void)
+{
+ MODULEINFO *pTemp = m_ModList;
+
+ while (pTemp != NULL)
+ {
+ if (pTemp->hOnlineTalkIcon)
+ DestroyIcon(pTemp->hOnlineTalkIcon);
+ if (pTemp->hOfflineTalkIcon)
+ DestroyIcon(pTemp->hOfflineTalkIcon);
+
+ LoadModuleIcons(pTemp);
+ pTemp = pTemp->next;
+ }
+ return;
+}
+void MM_FontsChanged(void)
+{
+ SESSION_INFO* pTemp = m_WndList;
+ SetIndentSize();
+ while (pTemp != NULL)
+ {
+ pTemp->pszHeader = Log_CreateRtfHeader(MM_FindModule(pTemp->pszModule), 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);
+ mir_free(m_ModList->crColors);
+
+ if (m_ModList->hOnlineTalkIcon)
+ DestroyIcon(m_ModList->hOnlineTalkIcon);
+ if (m_ModList->hOfflineTalkIcon)
+ DestroyIcon(m_ModList->hOfflineTalkIcon);
+
+ 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_PTR)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_PTR)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
+//---------------------------------------------------
+
+
+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 ))
+ return lstrcmp( u1->pszNick, pszNick );
+
+ dw1 = dw1 >> 1;
+ dw2 = dw2 >> 1;
+ }
+ 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 = _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/Scriver/chat/message.c b/plugins/Scriver/chat/message.c new file mode 100644 index 0000000000..2951cc3856 --- /dev/null +++ b/plugins/Scriver/chat/message.c @@ -0,0 +1,351 @@ +/*
+Chat module plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+Copyright 2003-2009 Miranda ICQ/IM project,
+
+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.
+*/
+
+#include "../commonheaders.h"
+#include "chat.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 ))
+ temp[i++] = *p++;
+ temp[i] = 0;
+
+ if ( result != NULL )
+ *result = atoi( temp );
+
+ return i;
+}
+
+TCHAR* DoRtfToTags( char* pszText, SESSION_INFO* si)
+{
+ char *p1;
+ int* pIndex;
+ int i, iRemoveChars;
+ char InsertThis[50];
+ BOOL bJustRemovedRTF = TRUE;
+ BOOL bTextHasStarted = FALSE;
+ #if defined(_UNICODE)
+ TCHAR *ptszResult;
+ #endif
+ 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 = 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, "\\line", 5 )) { // newline
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = 5;
+ strcpy(InsertThis, "\n" );
+ }
+ else if (!memcmp(p1, "\\bullet", 7)) {
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 7;
+#if defined(_UNICODE)
+ strcpy(InsertThis, "\xE2\x80\xA2");
+#else
+ strcpy(InsertThis, "\x95");
+#endif
+ }
+ else if ( !memcmp(p1, "\\b", 2 )) { //bold
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = (p1[2] != '0')?2:3;
+ mir_snprintf(InsertThis, SIZEOF(InsertThis), (p1[2] != '0') ? "%%b": "%%B" );
+ }
+ else if ( !memcmp(p1, "\\i", 2 )) { // italics
+ bTextHasStarted = bJustRemovedRTF = TRUE;
+ iRemoveChars = (p1[2] != '0')?2:3;
+ mir_snprintf(InsertThis, SIZEOF(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 ( !memcmp(p1, "\\tab", 4 )) { // tab
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 4;
+ strcpy(InsertThis, " " );
+ }
+ else if (!memcmp(p1, "\\endash", 7)) {
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 7;
+#if defined(_UNICODE)
+ strcpy(InsertThis, "\xE2\x80\x93");
+#else
+ strcpy(InsertThis, "\x96");
+#endif
+ }
+ else if (!memcmp(p1, "\\emdash", 7)) {
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 7;
+#if defined(_UNICODE)
+ strcpy(InsertThis, "\xE2\x80\x94");
+#else
+ strcpy(InsertThis, "\x97");
+#endif
+ }
+ else if (!memcmp(p1, "\\lquote",7)) {
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 7;
+#if defined(_UNICODE)
+ strcpy(InsertThis, "\xE2\x80\x98");
+#else
+ strcpy(InsertThis, "\x91");
+#endif
+ }
+ else if (!memcmp(p1, "\\rquote",7)) {
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 7;
+#if defined(_UNICODE)
+ strcpy(InsertThis, "\xE2\x80\x99");
+#else
+ strcpy(InsertThis, "\x92");
+#endif
+ }
+ else if (!memcmp(p1, "\\ldblquote",10)) {
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 10;
+#if defined(_UNICODE)
+ strcpy(InsertThis, "\xe2\x80\x9c");
+#else
+ strcpy(InsertThis, "\"");
+#endif
+ }
+ else if (!memcmp(p1, "\\rdblquote",10)) {
+ bTextHasStarted = TRUE;
+ bJustRemovedRTF = TRUE;
+ iRemoveChars = 10;
+#if defined(_UNICODE)
+ strcpy(InsertThis, "\xe2\x80\x9d");
+#else
+ strcpy(InsertThis, "\"");
+#endif
+ }
+ 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;
+#if defined(_UNICODE)
+ strcpy(InsertThis, "\xC2\xA0");
+#else
+ strcpy(InsertThis, "\xA0");
+#endif
+ }
+ 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;
+ mir_snprintf(InsertThis, SIZEOF(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);
+
+ #if !defined( _UNICODE )
+ return pszText;
+ #else
+ mir_utf8decode(pszText, &ptszResult);
+ return ptszResult;
+ #endif
+}
+
diff --git a/plugins/Scriver/chat/options.c b/plugins/Scriver/chat/options.c new file mode 100644 index 0000000000..bf768be19e --- /dev/null +++ b/plugins/Scriver/chat/options.c @@ -0,0 +1,953 @@ +/*
+Chat module plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+Copyright 2003-2009 Miranda ICQ/IM project,
+
+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.
+*/
+
+#include "../commonheaders.h"
+#include "chat.h"
+#include <shlobj.h>
+#include <shlwapi.h>
+
+#define UM_CHECKSTATECHANGE (WM_USER+100)
+
+extern HANDLE g_hInst;
+extern HBRUSH hListBkgBrush;
+extern HBRUSH hListSelectedBkgBrush;
+extern FONTINFO aFonts[OPTIONS_FONTCOUNT];
+
+HANDLE g_hOptions = NULL;
+static HWND hPathTip = 0;
+
+struct branch_t
+{
+ TCHAR* szDescr;
+ char* szDBName;
+ int iMode;
+ BYTE bDefault;
+ HTREEITEM hItem;
+};
+
+static struct branch_t branch1[] = {
+ {LPGENT("Flash when someone speaks"), "FlashWindow", 0,0, NULL},
+ {LPGENT("Flash when a word is highlighted"), "FlashWindowHighlight", 0,1, NULL},
+ {LPGENT("Show chat user list"), "ShowNicklist", 0,1, NULL},
+ {LPGENT("Enable button context menus"), "RightClickFilter", 0,0, NULL},
+ {LPGENT("Show topic on your contact list (if supported)"), "TopicOnClist", 0, 0, NULL},
+ {LPGENT("Do not play sounds when focused"), "SoundsFocus", 0, 0, NULL},
+ {LPGENT("Do not pop up when joining"), "PopupOnJoin", 0,0, NULL},
+ {LPGENT("Show and hide by double clicking in the contact list"), "ToggleVisibility", 0,0, NULL},
+ {LPGENT("Show contact statuses (if supported)"), "ShowContactStatus", 0,0, NULL},
+ {LPGENT("Display contact status icon before role icon"), "ContactStatusFirst", 0,0, NULL},
+ {LPGENT("Add \':\' to auto-completed names"), "AddColonToAutoComplete", 0, 1, NULL}
+};
+static struct branch_t branch2[] = {
+ {LPGENT("Show icons"), "IconFlags", GC_EVENT_TOPIC|GC_EVENT_JOIN|GC_EVENT_QUIT|
+ GC_EVENT_MESSAGE|GC_EVENT_ACTION|GC_EVENT_HIGHLIGHT|GC_EVENT_PART|
+ GC_EVENT_KICK|GC_EVENT_NOTICE|GC_EVENT_NICK|GC_EVENT_INFORMATION|GC_EVENT_ADDSTATUS, 0, NULL},
+ {LPGENT("Prefix all events with a timestamp"), "ShowTimeStamp", 0,1, NULL},
+ {LPGENT("Only prefix with timestamp if it has changed"), "ShowTimeStampIfChanged", 0,0, NULL},
+ {LPGENT("Timestamp has same colour as event"), "TimeStampEventColour", 0,0, NULL},
+ {LPGENT("Indent the second line of a message"), "LogIndentEnabled", 0,1, NULL},
+ {LPGENT("Limit user names to 20 characters"), "LogLimitNames", 0,1, NULL},
+ {LPGENT("Strip colors from messages"), "StripFormatting", 0, 0, NULL},
+ {LPGENT("Enable \'event filter\' for new rooms"), "FilterEnabled", 0,0, NULL}
+};
+static struct branch_t branch3[] = {
+ {LPGENT("Show topic changes"), "FilterFlags", GC_EVENT_TOPIC, 0, NULL},
+ {LPGENT("Show users joining"), "FilterFlags", GC_EVENT_JOIN, 0, NULL},
+ {LPGENT("Show users disconnecting"), "FilterFlags", GC_EVENT_QUIT, 0, NULL},
+ {LPGENT("Show messages"), "FilterFlags", GC_EVENT_MESSAGE, 1, NULL},
+ {LPGENT("Show actions"), "FilterFlags", GC_EVENT_ACTION, 1, NULL},
+ {LPGENT("Show users leaving"), "FilterFlags", GC_EVENT_PART, 0, NULL},
+ {LPGENT("Show users being kicked"), "FilterFlags", GC_EVENT_KICK, 1, NULL},
+ {LPGENT("Show notices"), "FilterFlags", GC_EVENT_NOTICE, 1, NULL},
+ {LPGENT("Show users changing name"), "FilterFlags", GC_EVENT_NICK, 0, NULL},
+ {LPGENT("Show information messages"), "FilterFlags", GC_EVENT_INFORMATION, 1, NULL},
+ {LPGENT("Show status changes of users"), "FilterFlags", GC_EVENT_ADDSTATUS, 0, NULL},
+};
+
+static struct branch_t branch4[] = {
+ {LPGENT("Show icons in tray only when the chat room is not active"), "TrayIconInactiveOnly", 0, 1, NULL},
+ {LPGENT("Show icon in tray for topic changes"), "TrayIconFlags", GC_EVENT_TOPIC, 0, NULL},
+ {LPGENT("Show icon in tray for users joining"), "TrayIconFlags", GC_EVENT_JOIN, 0, NULL},
+ {LPGENT("Show icon in tray for users disconnecting"), "TrayIconFlags", GC_EVENT_QUIT, 0, NULL},
+ {LPGENT("Show icon in tray for messages"), "TrayIconFlags", GC_EVENT_MESSAGE, 0, NULL},
+ {LPGENT("Show icon in tray for actions"), "TrayIconFlags", GC_EVENT_ACTION, 0, NULL},
+ {LPGENT("Show icon in tray for highlights"), "TrayIconFlags", GC_EVENT_HIGHLIGHT, 1, NULL},
+ {LPGENT("Show icon in tray for users leaving"), "TrayIconFlags", GC_EVENT_PART, 0, NULL},
+ {LPGENT("Show icon in tray for users kicking other user"), "TrayIconFlags", GC_EVENT_KICK, 0, NULL},
+ {LPGENT("Show icon in tray for notices "), "TrayIconFlags", GC_EVENT_NOTICE, 0, NULL},
+ {LPGENT("Show icon in tray for name changes"), "TrayIconFlags", GC_EVENT_NICK, 0, NULL},
+ {LPGENT("Show icon in tray for information messages"), "TrayIconFlags", GC_EVENT_INFORMATION, 0, NULL},
+ {LPGENT("Show icon in tray for status changes"), "TrayIconFlags", GC_EVENT_ADDSTATUS, 0, NULL},
+};
+
+static struct branch_t branch6[] = {
+ {LPGENT("Show pop-ups only when the chat room is not active"), "PopUpInactiveOnly", 0, 1, NULL},
+ {LPGENT("Show pop-up for topic changes"), "PopupFlags", GC_EVENT_TOPIC, 0, NULL},
+ {LPGENT("Show pop-up for users joining"), "PopupFlags", GC_EVENT_JOIN, 0, NULL},
+ {LPGENT("Show pop-up for users disconnecting"), "PopupFlags", GC_EVENT_QUIT, 0, NULL},
+ {LPGENT("Show pop-up for messages"), "PopupFlags", GC_EVENT_MESSAGE, 0, NULL},
+ {LPGENT("Show pop-up for actions"), "PopupFlags", GC_EVENT_ACTION, 0, NULL},
+ {LPGENT("Show pop-up for highlights"), "PopupFlags", GC_EVENT_HIGHLIGHT, 0, NULL},
+ {LPGENT("Show pop-up for users leaving"), "PopupFlags", GC_EVENT_PART, 0, NULL},
+ {LPGENT("Show pop-up for users kicking other user"), "PopupFlags", GC_EVENT_KICK, 0, NULL},
+ {LPGENT("Show pop-up for notices "), "PopupFlags", GC_EVENT_NOTICE, 0, NULL},
+ {LPGENT("Show pop-up for name changes"), "PopupFlags", GC_EVENT_NICK, 0, NULL},
+ {LPGENT("Show pop-up for information messages"), "PopupFlags", GC_EVENT_INFORMATION, 0, NULL},
+ {LPGENT("Show pop-up for status changes"), "PopupFlags", GC_EVENT_ADDSTATUS, 0, NULL},
+};
+
+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.item.state=bExpanded?INDEXTOSTATEIMAGEMASK(1)|TVIS_EXPANDED:INDEXTOSTATEIMAGEMASK(1);
+ 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;
+
+ 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 = ((DBGetContactSettingDword(NULL, "Chat", branch[i].szDBName, defaultval)&branch[i].iMode)&branch[i].iMode)!=0?2:1;
+ else
+ iState = DBGetContactSettingByte(NULL, "Chat", branch[i].szDBName, branch[i].bDefault)!=0?2:1;
+ 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==1)?0:1;
+ if(branch[i].iMode)
+ {
+ if (bChecked)
+ iState |= branch[i].iMode;
+ if (iState&GC_EVENT_ADDSTATUS)
+ iState |= GC_EVENT_REMOVESTATUS;
+ DBWriteContactSettingDword(NULL, "Chat", branch[i].szDBName, (DWORD)iState);
+ }
+ else DBWriteContactSettingByte(NULL, "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==1))
+ bChecked = FALSE;
+ }
+ tvi.hItem=TreeView_GetNextSibling(hwndTree,tvi.hItem);
+ }
+ tvi.stateMask = TVIS_STATEIMAGEMASK;
+ tvi.state=INDEXTOSTATEIMAGEMASK(bChecked?2:1);
+ 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==2))
+ bChecked = FALSE;
+ tvi.hItem=TreeView_GetNextItem(hwndTree, hHeading, TVGN_CHILD);
+ tvi.stateMask = TVIS_STATEIMAGEMASK;
+ while(tvi.hItem) {
+ tvi.state=INDEXTOSTATEIMAGEMASK(bChecked?2:1);
+ 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:
+ SendMessage(hwnd, BFFM_SETSELECTION, TRUE, pData);
+ break;
+ case BFFM_SELCHANGED:
+ if (SHGetPathFromIDListA((LPITEMIDLIST) lp ,szDir))
+ SendMessage(hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir);
+ break;
+ }
+ return 0;
+}
+
+void LoadLogFonts(void)
+{
+ int i;
+ for( i = 0; i<OPTIONS_FONTCOUNT; i++)
+ LoadMsgDlgFont(i, &aFonts[i].lf, &aFonts[i].color, TRUE);
+}
+
+
+static void InitSetting(TCHAR** ppPointer, char* pszSetting, TCHAR* pszDefault)
+{
+ DBVARIANT dbv;
+ if ( !DBGetContactSettingTString(NULL, "Chat", pszSetting, &dbv )) {
+ replaceStr( ppPointer, dbv.ptszVal );
+ DBFreeVariant(&dbv);
+ }
+ else replaceStr( ppPointer, pszDefault );
+ }
+
+#define OPT_FIXHEADINGS (WM_USER+1)
+
+
+INT_PTR CALLBACK DlgProcOptions1(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ static HTREEITEM hListHeading1 = 0;
+ static HTREEITEM hListHeading4= 0;
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLong(GetDlgItem(hwndDlg,IDC_CHAT_CHECKBOXES),GWL_STYLE,GetWindowLong(GetDlgItem(hwndDlg,IDC_CHAT_CHECKBOXES),GWL_STYLE)|TVS_NOHSCROLL|TVS_CHECKBOXES);
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_SPIN2,UDM_SETRANGE,0,MAKELONG(255,10));
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_SPIN2,UDM_SETPOS,0,MAKELONG(DBGetContactSettingByte(NULL,"Chat","NicklistRowDist",12),0));
+ hListHeading1 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), TranslateT("Appearance and functionality of chat windows"), DBGetContactSettingByte(NULL, "Chat", "Branch1Exp", 0)?TRUE:FALSE);
+ hListHeading4 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), TranslateT("Icons to display in the tray"), DBGetContactSettingByte(NULL, "Chat", "Branch5Exp", 0)?TRUE:FALSE);
+ FillBranch(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading1, branch1, SIZEOF(branch1), 0);
+ FillBranch(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading4, branch4, SIZEOF(branch4), 0x1000);
+ SendMessage(hwndDlg, OPT_FIXHEADINGS, 0, 0);
+ {
+ TCHAR* pszGroup = NULL;
+ InitSetting(&pszGroup, "AddToGroup", _T("Chat rooms"));
+ SetWindowText(GetDlgItem(hwndDlg, IDC_CHAT_GROUP), pszGroup);
+ mir_free(pszGroup);
+ }
+ break;
+
+ case OPT_FIXHEADINGS:
+ CheckHeading(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading1);
+ CheckHeading(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading4);
+ break;
+
+ case WM_COMMAND:
+ if ( (LOWORD(wParam) == IDC_CHAT_NICKROW
+ || LOWORD(wParam) == IDC_CHAT_GROUP)
+ && (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus())) return 0;
+
+ if(lParam != (LPARAM)NULL)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ case UM_CHECKSTATECHANGE:
+ {
+ TVITEM tvi = {0};
+ tvi.mask=TVIF_HANDLE|TVIF_STATE;
+ tvi.hItem=(HTREEITEM) lParam;
+ TreeView_GetItem((HWND)wParam,&tvi);
+ if (tvi.hItem == hListHeading1)
+ CheckBranches(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading1);
+ else if (tvi.hItem == hListHeading4)
+ CheckBranches(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading4);
+ else
+ PostMessage(hwndDlg, OPT_FIXHEADINGS, 0, 0);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+ case IDC_CHAT_CHECKBOXES:
+ if(((LPNMHDR)lParam)->code==NM_CLICK) {
+ 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))
+ if(hti.flags&TVHT_ONITEMSTATEICON) {
+ SendMessage(hwndDlg, UM_CHECKSTATECHANGE, (WPARAM)((LPNMHDR)lParam)->hwndFrom, (LPARAM)hti.hItem);
+ }
+
+ } else if (((LPNMHDR) lParam)->code == TVN_KEYDOWN) {
+ if (((LPNMTVKEYDOWN) lParam)->wVKey == VK_SPACE) {
+ SendMessage(hwndDlg, UM_CHECKSTATECHANGE, (WPARAM)((LPNMHDR)lParam)->hwndFrom,
+ (LPARAM)TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom));
+ }
+ }
+ break;
+
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ int iLen;
+ char * pszText = NULL;
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_CHAT_GROUP));
+ if(iLen > 0)
+ {
+ pszText = mir_realloc(pszText, iLen+1);
+ GetDlgItemTextA(hwndDlg, IDC_CHAT_GROUP, pszText,iLen+1);
+ DBWriteContactSettingString(NULL, "Chat", "AddToGroup", pszText);
+ }
+ else DBWriteContactSettingString(NULL, "Chat", "AddToGroup", "");
+ mir_free(pszText);
+
+ iLen = SendDlgItemMessage(hwndDlg,IDC_CHAT_SPIN2,UDM_GETPOS,0,0);
+ if(iLen > 0)
+ DBWriteContactSettingByte(NULL, "Chat", "NicklistRowDist", (BYTE)iLen);
+ else
+ DBDeleteContactSetting(NULL, "Chat", "NicklistRowDist");
+ SaveBranch(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), branch1, SIZEOF(branch1));
+ SaveBranch(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), branch4, SIZEOF(branch4));
+
+ SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE);
+ }
+ return TRUE;
+ }
+ }
+ }break;
+ case WM_DESTROY:
+ {
+ BYTE b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading1, TVIS_EXPANDED)&TVIS_EXPANDED?1:0;
+ DBWriteContactSettingByte(NULL, "Chat", "Branch1Exp", b);
+ b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading4, TVIS_EXPANDED)&TVIS_EXPANDED?1:0;
+ DBWriteContactSettingByte(NULL, "Chat", "Branch5Exp", b);
+ }break;
+
+ default:break;
+ }
+ return FALSE;
+}
+
+BOOL CALLBACK DlgProcOptions2(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ static HTREEITEM hListHeading2= 0;
+ static HTREEITEM hListHeading3= 0;
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ {
+ TCHAR tszTemp[MAX_PATH];
+
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLong(GetDlgItem(hwndDlg,IDC_CHAT_CHECKBOXES),GWL_STYLE,GetWindowLong(GetDlgItem(hwndDlg,IDC_CHAT_CHECKBOXES),GWL_STYLE)|TVS_NOHSCROLL|TVS_CHECKBOXES);
+ 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(10000,0));
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_SPIN3,UDM_SETPOS,0,MAKELONG(DBGetContactSettingWord(NULL,"Chat","LoggingLimit",100),0));
+ CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)g_Settings.pszLogDir, (LPARAM)tszTemp );
+ SetDlgItemText(hwndDlg, IDC_CHAT_LOGDIRECTORY, tszTemp);
+
+ if (ServiceExists(MS_UTILS_REPLACEVARS)) {
+ TCHAR tszTooltipText[2048];
+ RECT rect;
+
+ 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") );
+ GetClientRect (GetDlgItem(hwndDlg, IDC_CHAT_LOGDIRECTORY), &rect);
+ rect.left = -85;
+ hPathTip = CreateToolTip(GetDlgItem(hwndDlg, IDC_CHAT_LOGDIRECTORY), tszTooltipText, TranslateT("Variables"), &rect);
+ SetTimer(hwndDlg, 0, 3000, NULL);
+ }
+
+
+ SetDlgItemText(hwndDlg, IDC_CHAT_HIGHLIGHTWORDS, g_Settings.pszHighlightWords);
+ SetDlgItemText(hwndDlg, IDC_CHAT_LOGTIMESTAMP, g_Settings.pszTimeStampLog);
+ SetDlgItemText(hwndDlg, IDC_CHAT_TIMESTAMP, g_Settings.pszTimeStamp);
+ SetDlgItemText(hwndDlg, IDC_CHAT_OUTSTAMP, g_Settings.pszOutgoingNick);
+ SetDlgItemText(hwndDlg, IDC_CHAT_INSTAMP, g_Settings.pszIncomingNick);
+ CheckDlgButton(hwndDlg, IDC_CHAT_HIGHLIGHT, g_Settings.HighlightEnabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_HIGHLIGHTWORDS), g_Settings.HighlightEnabled?TRUE:FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHAT_LOGGING, g_Settings.LoggingEnabled);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_LOGDIRECTORY), g_Settings.LoggingEnabled?TRUE:FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_LOGDIRCHOOSE), g_Settings.LoggingEnabled?TRUE:FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_LIMIT), g_Settings.LoggingEnabled?TRUE:FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_LIMITTEXT2), g_Settings.LoggingEnabled?TRUE:FALSE);
+
+ hListHeading2 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), TranslateT("Appearance"), DBGetContactSettingByte(NULL, "Chat", "Branch2Exp", 0)?TRUE:FALSE);
+ hListHeading3 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), TranslateT("Default events to show in new chat rooms if the \'event filter\' is enabled"), DBGetContactSettingByte(NULL, "Chat", "Branch3Exp", 0)?TRUE:FALSE);
+ FillBranch(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading2, branch2, SIZEOF(branch2), 0x0);
+ FillBranch(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading3, branch3, SIZEOF(branch3), 0x03E0);
+ SendMessage(hwndDlg, OPT_FIXHEADINGS, 0, 0);
+
+ break;
+ }
+ case OPT_FIXHEADINGS:
+ CheckHeading(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading2);
+ CheckHeading(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading3);
+ break;
+ case WM_COMMAND:
+ if( (LOWORD(wParam) == IDC_CHAT_INSTAMP
+ || LOWORD(wParam) == IDC_CHAT_OUTSTAMP
+ || LOWORD(wParam) == IDC_CHAT_TIMESTAMP
+ || LOWORD(wParam) == IDC_CHAT_LOGLIMIT
+ || LOWORD(wParam) == IDC_CHAT_HIGHLIGHTWORDS
+ || LOWORD(wParam) == IDC_CHAT_LOGDIRECTORY
+ || LOWORD(wParam) == IDC_CHAT_LOGTIMESTAMP
+ || LOWORD(wParam) == IDC_CHAT_LIMIT)
+ && (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus())) return 0;
+
+ switch (LOWORD(wParam)) {
+ case IDC_CHAT_LOGGING:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_LOGDIRECTORY), IsDlgButtonChecked(hwndDlg, IDC_CHAT_LOGGING) == BST_CHECKED?TRUE:FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_LOGDIRCHOOSE), IsDlgButtonChecked(hwndDlg, IDC_CHAT_LOGGING) == BST_CHECKED?TRUE:FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_LIMIT), IsDlgButtonChecked(hwndDlg, IDC_CHAT_LOGGING) == BST_CHECKED?TRUE:FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_LIMITTEXT2), IsDlgButtonChecked(hwndDlg, IDC_CHAT_LOGGING) == BST_CHECKED?TRUE:FALSE);
+ break;
+ case IDC_CHAT_LOGDIRCHOOSE:
+ {
+ 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) {
+ SHGetPathFromIDList(idList,tszDirectory);
+ lstrcat(tszDirectory, _T("\\"));
+ CallService(MS_UTILS_PATHTORELATIVET, (WPARAM)tszDirectory, (LPARAM)tszTemp );
+ SetWindowText(GetDlgItem(hwndDlg, IDC_CHAT_LOGDIRECTORY), lstrlen(tszTemp) > 1?tszTemp:DEFLOGFILENAME);
+ }
+ psMalloc->lpVtbl->Free(psMalloc,idList);
+ psMalloc->lpVtbl->Release(psMalloc);
+ }
+ break;
+ }
+ case IDC_CHAT_HIGHLIGHT:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_HIGHLIGHTWORDS), IsDlgButtonChecked(hwndDlg, IDC_CHAT_HIGHLIGHT) == BST_CHECKED?TRUE:FALSE);
+ break;
+ }
+
+ if(lParam != (LPARAM)NULL)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+
+ case UM_CHECKSTATECHANGE:
+ {
+ TVITEM tvi = {0};
+ tvi.mask=TVIF_HANDLE|TVIF_STATE;
+ tvi.hItem=(HTREEITEM) lParam;
+ TreeView_GetItem((HWND)wParam,&tvi);
+ if (tvi.hItem == hListHeading2)
+ CheckBranches(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading2);
+ else if (tvi.hItem == hListHeading3)
+ CheckBranches(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading3);
+ else
+ PostMessage(hwndDlg, OPT_FIXHEADINGS, 0, 0);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->idFrom == IDC_CHAT_CHECKBOXES) {
+ if (((LPNMHDR)lParam)->code==NM_CLICK) {
+ 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))
+ if(hti.flags&TVHT_ONITEMSTATEICON) {
+ SendMessage(hwndDlg, UM_CHECKSTATECHANGE, (WPARAM)((LPNMHDR)lParam)->hwndFrom, (LPARAM)hti.hItem);
+ }
+
+ } else if (((LPNMHDR) lParam)->code == TVN_KEYDOWN) {
+ if (((LPNMTVKEYDOWN) lParam)->wVKey == VK_SPACE) {
+ SendMessage(hwndDlg, UM_CHECKSTATECHANGE, (WPARAM)((LPNMHDR)lParam)->hwndFrom,
+ (LPARAM)TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom));
+ }
+ }
+ } else if (((LPNMHDR)lParam)->idFrom == 0 && ((LPNMHDR)lParam)->code == PSN_APPLY ) {
+ char *pszText = NULL;
+ int iLen;
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_CHAT_HIGHLIGHTWORDS));
+ if ( iLen > 0 ) {
+ TCHAR *ptszText = mir_alloc((iLen+2) * sizeof(TCHAR));
+ TCHAR *p2 = NULL;
+
+ if(ptszText) {
+ GetDlgItemText(hwndDlg, IDC_CHAT_HIGHLIGHTWORDS, ptszText, iLen + 1);
+ p2 = _tcschr(ptszText, (TCHAR)',');
+ while ( p2 ) {
+ *p2 = ' ';
+ p2 = _tcschr(ptszText, (TCHAR)',');
+ }
+ DBWriteContactSettingTString(NULL, "Chat", "HighlightWords", ptszText);
+ mir_free(ptszText);
+ }
+ }
+ else DBDeleteContactSetting(NULL, "Chat", "HighlightWords");
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_CHAT_LOGDIRECTORY));
+ if ( iLen > 0 ) {
+ TCHAR *pszText1 = malloc(iLen*sizeof(TCHAR) + 2);
+ GetDlgItemText(hwndDlg, IDC_CHAT_LOGDIRECTORY, pszText1, iLen + 1);
+ DBWriteContactSettingTString(NULL, "Chat", "LogDirectory", pszText1);
+ CallService(MS_UTILS_PATHTOABSOLUTET, (WPARAM)pszText1, (LPARAM)g_Settings.pszLogDir);
+ free(pszText1);
+ }
+ else {
+ lstrcpyn(g_Settings.pszLogDir, DEFLOGFILENAME, MAX_PATH);
+ DBDeleteContactSetting(NULL, "Chat", "LogDirectory");
+ }
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_CHAT_LOGTIMESTAMP));
+ if ( iLen > 0 ) {
+ pszText = mir_realloc(pszText, iLen+1);
+ GetDlgItemTextA(hwndDlg, IDC_CHAT_LOGTIMESTAMP, pszText,iLen+1);
+ DBWriteContactSettingString(NULL, "Chat", "LogTimestamp", pszText);
+ }
+ else DBDeleteContactSetting(NULL, "Chat", "LogTimestamp");
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_CHAT_TIMESTAMP));
+ if( iLen > 0 ) {
+ pszText = mir_realloc(pszText, iLen+1);
+ GetDlgItemTextA(hwndDlg, IDC_CHAT_TIMESTAMP, pszText,iLen+1);
+ DBWriteContactSettingString(NULL, "Chat", "HeaderTime", pszText);
+ }
+ else DBDeleteContactSetting(NULL, "Chat", "HeaderTime");
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_CHAT_INSTAMP));
+ if ( iLen > 0 ) {
+ pszText = mir_realloc(pszText, iLen+1);
+ GetDlgItemTextA(hwndDlg, IDC_CHAT_INSTAMP, pszText,iLen+1);
+ DBWriteContactSettingString(NULL, "Chat", "HeaderIncoming", pszText);
+ }
+ else DBDeleteContactSetting(NULL, "Chat", "HeaderIncoming");
+
+ iLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_CHAT_OUTSTAMP));
+ if( iLen > 0 ) {
+ pszText = mir_realloc(pszText, iLen+1);
+ GetDlgItemTextA(hwndDlg, IDC_CHAT_OUTSTAMP, pszText,iLen+1);
+ DBWriteContactSettingString(NULL, "Chat", "HeaderOutgoing", pszText);
+ }
+ else DBDeleteContactSetting(NULL, "Chat", "HeaderOutgoing");
+
+ g_Settings.HighlightEnabled = IsDlgButtonChecked(hwndDlg, IDC_CHAT_HIGHLIGHT) == BST_CHECKED?TRUE:FALSE;
+ DBWriteContactSettingByte(NULL, "Chat", "HighlightEnabled", (BYTE)g_Settings.HighlightEnabled);
+
+ g_Settings.LoggingEnabled = IsDlgButtonChecked(hwndDlg, IDC_CHAT_LOGGING) == BST_CHECKED?TRUE:FALSE;
+ DBWriteContactSettingByte(NULL, "Chat", "LoggingEnabled", (BYTE)g_Settings.LoggingEnabled);
+
+ iLen = SendDlgItemMessage(hwndDlg,IDC_CHAT_SPIN2,UDM_GETPOS,0,0);
+ DBWriteContactSettingWord(NULL, "Chat", "LogLimit", (WORD)iLen);
+ iLen = SendDlgItemMessage(hwndDlg,IDC_CHAT_SPIN3,UDM_GETPOS,0,0);
+ DBWriteContactSettingWord(NULL, "Chat", "LoggingLimit", (WORD)iLen);
+
+ SaveBranch(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), branch2, SIZEOF(branch2));
+ SaveBranch(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), branch3, SIZEOF(branch3));
+
+ mir_free(pszText);
+
+ g_Settings.dwIconFlags = DBGetContactSettingDword(NULL, "Chat", "IconFlags", 0x0000);
+ g_Settings.dwTrayIconFlags = DBGetContactSettingDword(NULL, "Chat", "TrayIconFlags", 0x1000);
+ g_Settings.dwPopupFlags = DBGetContactSettingDword(NULL, "Chat", "PopupFlags", 0x0000);
+ g_Settings.StripFormat = (BOOL)DBGetContactSettingByte(NULL, "Chat", "TrimFormatting", 0);
+ g_Settings.TrayIconInactiveOnly = (BOOL)DBGetContactSettingByte(NULL, "Chat", "TrayIconInactiveOnly", 1);
+ g_Settings.PopUpInactiveOnly = (BOOL)DBGetContactSettingByte(NULL, "Chat", "PopUpInactiveOnly", 1);
+
+ g_Settings.LogIndentEnabled = (DBGetContactSettingByte(NULL, "Chat", "LogIndentEnabled", 1) != 0)?TRUE:FALSE;
+ MM_FontsChanged();
+ SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE);
+ 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;
+ }
+ {
+ BYTE b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading2, TVIS_EXPANDED)&TVIS_EXPANDED?1:0;
+ DBWriteContactSettingByte(NULL, "Chat", "Branch2Exp", b);
+ b = TreeView_GetItemState(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), hListHeading3, TVIS_EXPANDED)&TVIS_EXPANDED?1:0;
+ DBWriteContactSettingByte(NULL, "Chat", "Branch3Exp", b);
+ }
+ break;
+ }
+ return FALSE;
+}
+
+static INT_PTR CALLBACK DlgProcOptionsPopup(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+
+ SetWindowLong(GetDlgItem(hwndDlg,IDC_CHAT_CHECKBOXES),GWL_STYLE,GetWindowLong(GetDlgItem(hwndDlg,IDC_CHAT_CHECKBOXES),GWL_STYLE)|TVS_NOHSCROLL|TVS_CHECKBOXES);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_BKG, CPM_SETCOLOUR,0,g_Settings.crPUBkgColour);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_TEXT, CPM_SETCOLOUR,0,g_Settings.crPUTextColour);
+
+ if(g_Settings.iPopupStyle ==2)
+ CheckDlgButton(hwndDlg, IDC_CHAT_RADIO2, BST_CHECKED);
+ else if(g_Settings.iPopupStyle ==3)
+ CheckDlgButton(hwndDlg, IDC_CHAT_RADIO3, BST_CHECKED);
+ else
+ CheckDlgButton(hwndDlg, IDC_CHAT_RADIO1, BST_CHECKED);
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_BKG), IsDlgButtonChecked(hwndDlg, IDC_CHAT_RADIO3) ==BST_CHECKED?TRUE:FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_TEXT), IsDlgButtonChecked(hwndDlg, IDC_CHAT_RADIO3) ==BST_CHECKED?TRUE:FALSE);
+
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_SPIN1,UDM_SETRANGE,0,MAKELONG(100,-1));
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_SPIN1,UDM_SETPOS,0,MAKELONG(g_Settings.iPopupTimeout,0));
+ //hListHeading6 = InsertBranch(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), TranslateT("Pop-ups to display"), TRUE);
+ FillBranch(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), NULL, branch6, SIZEOF(branch6), 0x0000);
+ }break;
+
+ case WM_COMMAND:
+ if( (LOWORD(wParam) == IDC_CHAT_TIMEOUT)
+ && (HIWORD(wParam)!=EN_CHANGE || (HWND)lParam!=GetFocus())) return 0;
+
+ if(lParam != (LPARAM)NULL)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ switch (LOWORD(wParam)) {
+
+ case IDC_CHAT_RADIO1:
+ case IDC_CHAT_RADIO2:
+ case IDC_CHAT_RADIO3:
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_BKG), IsDlgButtonChecked(hwndDlg, IDC_CHAT_RADIO3) ==BST_CHECKED?TRUE:FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_TEXT), IsDlgButtonChecked(hwndDlg, IDC_CHAT_RADIO3) ==BST_CHECKED?TRUE:FALSE);
+ break;
+
+ default:break;
+ }
+
+ break;
+
+ case WM_NOTIFY:
+ {
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+ case IDC_CHAT_CHECKBOXES:
+ if(((LPNMHDR)lParam)->code==NM_CLICK) {
+ 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))
+ if(hti.flags&TVHT_ONITEMSTATEICON) {
+ SendMessage(hwndDlg, UM_CHECKSTATECHANGE, (WPARAM)((LPNMHDR)lParam)->hwndFrom, (LPARAM)hti.hItem);
+ }
+
+ } else if (((LPNMHDR) lParam)->code == TVN_KEYDOWN) {
+ if (((LPNMTVKEYDOWN) lParam)->wVKey == VK_SPACE) {
+ SendMessage(hwndDlg, UM_CHECKSTATECHANGE, (WPARAM)((LPNMHDR)lParam)->hwndFrom,
+ (LPARAM)TreeView_GetSelection(((LPNMHDR)lParam)->hwndFrom));
+ }
+ }
+ break;
+ case 0:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ int iLen;
+
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHAT_RADIO2) == BST_CHECKED)
+ iLen = 2;
+ else if(IsDlgButtonChecked(hwndDlg, IDC_CHAT_RADIO3) == BST_CHECKED)
+ iLen = 3;
+ else
+ iLen = 1;
+
+ g_Settings.iPopupStyle = iLen;
+ DBWriteContactSettingByte(NULL, "Chat", "PopupStyle", (BYTE)iLen);
+
+ iLen = SendDlgItemMessage(hwndDlg,IDC_CHAT_SPIN1,UDM_GETPOS,0,0);
+ g_Settings.iPopupTimeout = iLen;
+ DBWriteContactSettingWord(NULL, "Chat", "PopupTimeout", (WORD)iLen);
+
+ g_Settings.crPUBkgColour = SendDlgItemMessage(hwndDlg,IDC_CHAT_BKG,CPM_GETCOLOUR,0,0);
+ DBWriteContactSettingDword(NULL, "Chat", "PopupColorBG", (DWORD)SendDlgItemMessage(hwndDlg,IDC_CHAT_BKG,CPM_GETCOLOUR,0,0));
+ g_Settings.crPUTextColour = SendDlgItemMessage(hwndDlg,IDC_CHAT_TEXT,CPM_GETCOLOUR,0,0);
+ DBWriteContactSettingDword(NULL, "Chat", "PopupColorText", (DWORD)SendDlgItemMessage(hwndDlg,IDC_CHAT_TEXT,CPM_GETCOLOUR,0,0));
+ SaveBranch(GetDlgItem(hwndDlg, IDC_CHAT_CHECKBOXES), branch6, SIZEOF(branch6));
+ }
+ return TRUE;
+ }
+ }
+ }break;
+ case UM_CHECKSTATECHANGE:
+ {
+ PostMessage(hwndDlg, OPT_FIXHEADINGS, 0, 0);
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+
+ default:break;
+ }
+ return FALSE;
+}
+
+static int OptionsInitialize(WPARAM wParam, LPARAM lParam)
+{
+
+ OPTIONSDIALOGPAGE odp = {0};
+ if(g_dat->popupInstalled)
+ {
+ odp.cbSize = sizeof(odp);
+ odp.position = 910000002;
+ odp.hInstance = g_hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONSPOPUP);
+ odp.ptszTitle = LPGENT("Messaging");
+ odp.ptszGroup = LPGENT("Popups");
+ odp.pfnDlgProc = DlgProcOptionsPopup;
+ odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
+ odp.ptszTab = NULL;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp);
+ }
+
+ return 0;
+}
+
+void LoadGlobalSettings(void)
+{
+ LOGFONT lf;
+
+ g_Settings.LogLimitNames = DBGetContactSettingByte(NULL, "Chat", "LogLimitNames", 1);
+ g_Settings.ShowTime = DBGetContactSettingByte(NULL, "Chat", "ShowTimeStamp", 1);
+ g_Settings.SoundsFocus = DBGetContactSettingByte(NULL, "Chat", "SoundsFocus", 0);
+ g_Settings.ShowTimeIfChanged = (BOOL)DBGetContactSettingByte(NULL, "Chat", "ShowTimeStampIfChanged", 0);
+ g_Settings.TimeStampEventColour = (BOOL)DBGetContactSettingByte(NULL, "Chat", "TimeStampEventColour", 0);
+ g_Settings.iEventLimit = DBGetContactSettingWord(NULL, "Chat", "LogLimit", 100);
+ g_Settings.dwIconFlags = DBGetContactSettingDword(NULL, "Chat", "IconFlags", 0x0000);
+ g_Settings.dwTrayIconFlags = DBGetContactSettingDword(NULL, "Chat", "TrayIconFlags", 0x1000);
+ g_Settings.dwPopupFlags = DBGetContactSettingDword(NULL, "Chat", "PopupFlags", 0x0000);
+ g_Settings.LoggingLimit = DBGetContactSettingWord(NULL, "Chat", "LoggingLimit", 100);
+ g_Settings.LoggingEnabled = (BOOL)DBGetContactSettingByte(NULL, "Chat", "LoggingEnabled", 0);
+ g_Settings.FlashWindow = (BOOL)DBGetContactSettingByte(NULL, "Chat", "FlashWindow", 0);
+ g_Settings.HighlightEnabled = (BOOL)DBGetContactSettingByte(NULL, "Chat", "HighlightEnabled", 1);
+ g_Settings.crUserListColor = DBGetContactSettingDword(NULL, "ChatFonts", "Font18Col", RGB(0,0,0));
+ g_Settings.crUserListBGColor = DBGetContactSettingDword(NULL, "Chat", "ColorNicklistBG", GetSysColor(COLOR_WINDOW));
+ g_Settings.crUserListSelectedBGColor = DBGetContactSettingDword(NULL, "Chat", "ColorNicklistSelectedBG", GetSysColor(COLOR_HIGHLIGHT));
+ g_Settings.crUserListHeadingsColor = DBGetContactSettingDword(NULL, "ChatFonts", "Font19Col", RGB(170,170,170));
+ g_Settings.crLogBackground = DBGetContactSettingDword(NULL, "Chat", "ColorLogBG", GetSysColor(COLOR_WINDOW));
+ g_Settings.StripFormat = (BOOL)DBGetContactSettingByte(NULL, "Chat", "StripFormatting", 0);
+ g_Settings.TrayIconInactiveOnly = (BOOL)DBGetContactSettingByte(NULL, "Chat", "TrayIconInactiveOnly", 1);
+ g_Settings.PopUpInactiveOnly = (BOOL)DBGetContactSettingByte(NULL, "Chat", "PopUpInactiveOnly", 1);
+ g_Settings.AddColonToAutoComplete = (BOOL)DBGetContactSettingByte(NULL, "Chat", "AddColonToAutoComplete", 1);
+ g_Settings.iPopupStyle = DBGetContactSettingByte(NULL, "Chat", "PopupStyle", 1);
+ g_Settings.iPopupTimeout = DBGetContactSettingWord(NULL, "Chat", "PopupTimeout", 3);
+ g_Settings.crPUBkgColour = DBGetContactSettingDword(NULL, "Chat", "PopupColorBG", GetSysColor(COLOR_WINDOW));
+ g_Settings.crPUTextColour = DBGetContactSettingDword(NULL, "Chat", "PopupColorText", 0);
+ g_Settings.ShowContactStatus = DBGetContactSettingByte(NULL, "Chat", "ShowContactStatus", 0);
+ g_Settings.ContactStatusFirst = DBGetContactSettingByte(NULL, "Chat", "ContactStatusFirst", 0);
+
+ 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:"));
+ InitSetting( &g_Settings.pszHighlightWords, "HighlightWords", _T("%m"));
+
+ {
+ DBVARIANT dbv;
+ g_Settings.pszLogDir = (TCHAR *)mir_realloc(g_Settings.pszLogDir, MAX_PATH*sizeof(TCHAR));
+ if (!DBGetContactSettingTString(NULL, "Chat", "LogDirectory", &dbv)) {
+ lstrcpyn(g_Settings.pszLogDir, dbv.ptszVal, MAX_PATH);
+ DBFreeVariant(&dbv);
+ } else lstrcpyn(g_Settings.pszLogDir, DEFLOGFILENAME, MAX_PATH);
+ }
+
+ g_Settings.LogIndentEnabled = (DBGetContactSettingByte(NULL, "Chat", "LogIndentEnabled", 1) != 0)?TRUE:FALSE;
+
+ if(g_Settings.MessageBoxFont)
+ DeleteObject(g_Settings.MessageBoxFont);
+ LoadMsgDlgFont(MSGFONTID_MESSAGEAREA, &lf, NULL, FALSE);
+ g_Settings.MessageBoxFont = CreateFontIndirect(&lf);
+
+ if(g_Settings.UserListFont)
+ DeleteObject(g_Settings.UserListFont);
+ LoadMsgDlgFont(18, &lf, NULL, TRUE);
+ g_Settings.UserListFont = CreateFontIndirect(&lf);
+
+ if(g_Settings.UserListHeadingsFont)
+ DeleteObject(g_Settings.UserListHeadingsFont);
+ LoadMsgDlgFont(19, &lf, NULL, TRUE);
+ g_Settings.UserListHeadingsFont = CreateFontIndirect(&lf);
+ if (hListBkgBrush != NULL) {
+ DeleteObject(hListBkgBrush);
+ }
+ hListBkgBrush = CreateSolidBrush(DBGetContactSettingDword(NULL, "Chat", "ColorNicklistBG", GetSysColor(COLOR_WINDOW)));
+ if (hListSelectedBkgBrush != NULL) {
+ DeleteObject(hListSelectedBkgBrush);
+ }
+ hListSelectedBkgBrush = CreateSolidBrush(DBGetContactSettingDword(NULL, "Chat", "ColorNicklistSelectedBG", GetSysColor(COLOR_HIGHLIGHT)));
+}
+
+static void FreeGlobalSettings(void)
+{
+ mir_free(g_Settings.pszTimeStamp);
+ mir_free(g_Settings.pszTimeStampLog);
+ mir_free(g_Settings.pszIncomingNick);
+ mir_free(g_Settings.pszOutgoingNick);
+ mir_free(g_Settings.pszHighlightWords);
+ mir_free(g_Settings.pszLogDir);
+ if(g_Settings.MessageBoxFont)
+ DeleteObject(g_Settings.MessageBoxFont);
+ if(g_Settings.UserListFont)
+ DeleteObject(g_Settings.UserListFont);
+ if(g_Settings.UserListHeadingsFont)
+ DeleteObject(g_Settings.UserListHeadingsFont);
+}
+
+void SetIndentSize()
+{
+ if (g_Settings.ShowTime) {
+ LOGFONT lf;
+ HFONT hFont;
+ int iText;
+
+ LoadMsgDlgFont(0, &lf, NULL, TRUE);
+ hFont = CreateFontIndirect(&lf);
+ iText = GetTextPixelSize(MakeTimeStamp(g_Settings.pszTimeStamp, time(NULL)),hFont, TRUE);
+ DeleteObject(hFont);
+ g_Settings.LogTextIndent = iText*12/10;
+ } else {
+ g_Settings.LogTextIndent = 0;
+ }
+
+}
+
+int OptionsInit(void)
+{
+ LOGFONT lf;
+
+ g_hOptions = HookEvent(ME_OPT_INITIALISE, OptionsInitialize);
+
+ LoadLogFonts();
+ LoadMsgDlgFont(18, &lf, NULL, TRUE);
+ lstrcpy(lf.lfFaceName, _T("MS Shell Dlg"));
+ lf.lfUnderline = lf.lfItalic = lf.lfStrikeOut = 0;
+ lf.lfHeight = -17;
+ lf.lfWeight = FW_BOLD;
+ g_Settings.NameFont = CreateFontIndirect(&lf);
+ g_Settings.UserListFont = NULL;
+ g_Settings.UserListHeadingsFont = NULL;
+ g_Settings.MessageBoxFont = NULL;
+ g_Settings.iSplitterX = DBGetContactSettingWord(NULL, "Chat", "SplitterX", 105);
+ LoadGlobalSettings();
+
+ SkinAddNewSoundEx("ChatMessage", LPGEN("Group chats"), LPGEN("Incoming 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"));
+ SetIndentSize();
+ return 0;
+}
+
+
+int OptionsUnInit(void)
+{
+ FreeGlobalSettings();
+ UnhookEvent(g_hOptions);
+ DeleteObject(hListBkgBrush);
+ DeleteObject(hListSelectedBkgBrush);
+ DeleteObject(g_Settings.NameFont);
+ return 0;
+}
diff --git a/plugins/Scriver/chat/services.c b/plugins/Scriver/chat/services.c new file mode 100644 index 0000000000..1104aa262b --- /dev/null +++ b/plugins/Scriver/chat/services.c @@ -0,0 +1,690 @@ +/*
+Chat module plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+Copyright 2003-2009 Miranda ICQ/IM project,
+
+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.
+*/
+
+#include "../commonheaders.h"
+#include "chat.h"
+#include "../msgwindow.h"
+
+extern HANDLE g_hInst;
+extern HICON hIcons[30];
+
+HANDLE hSendEvent;
+HANDLE hBuildMenuEvent ;
+HANDLE g_hHookContactDblClick, g_hHookPrebuildMenu;
+CRITICAL_SECTION cs;
+
+#ifdef _WIN64
+
+#define SIZEOF_STRUCT_GCREGISTER_V1 40
+#define SIZEOF_STRUCT_GCWINDOW_V1 48
+#define SIZEOF_STRUCT_GCEVENT_V1 76
+#define SIZEOF_STRUCT_GCEVENT_V2 80
+
+#else
+
+#define SIZEOF_STRUCT_GCREGISTER_V1 28
+#define SIZEOF_STRUCT_GCWINDOW_V1 32
+#define SIZEOF_STRUCT_GCEVENT_V1 44
+#define SIZEOF_STRUCT_GCEVENT_V2 48
+
+#endif
+
+int Chat_SmileyOptionsChanged(WPARAM wParam,LPARAM lParam)
+{
+ SM_BroadcastMessage(NULL, GC_REDRAWLOG, 0, 1, FALSE);
+ return 0;
+}
+
+int Chat_PreShutdown(WPARAM wParam,LPARAM lParam)
+{
+ SM_BroadcastMessage(NULL, GC_CLOSEWINDOW, 0, 1, FALSE);
+
+ SM_RemoveAll();
+ MM_RemoveAll();
+ return 0;
+}
+
+int Chat_FontsChanged(WPARAM wParam,LPARAM lParam)
+{
+ LoadLogFonts();
+ LoadMsgLogBitmaps();
+ MM_FontsChanged();
+ MM_FixColors();
+ SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE);
+ return 0;
+}
+
+int Chat_IconsChanged(WPARAM wParam,LPARAM lParam)
+{
+ FreeMsgLogBitmaps();
+ LoadMsgLogBitmaps();
+ MM_IconsChanged();
+ SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, FALSE);
+ return 0;
+}
+
+static 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;
+}
+
+static 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->windowData.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 defined( _UNICODE )
+ 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;
+ }
+ #else
+ if ( gci->Flags & ID ) gci->pszID = si->ptszID;
+ if ( gci->Flags & NAME ) gci->pszName = si->ptszName;
+ #endif
+
+ LeaveCriticalSection(&cs);
+ return 0;
+ }
+
+ LeaveCriticalSection(&cs);
+ return 1;
+}
+
+void LoadModuleIcons(MODULEINFO * mi) {
+ int index;
+
+ HIMAGELIST hList = ImageList_Create(16, 16, IsWinVerXPPlus() ? ILC_COLOR32 | ILC_MASK : ILC_COLOR8 | ILC_MASK, 0, 0);
+
+ int overlayIcon = ImageList_AddIcon(hList, GetCachedIcon("chat_overlay"));
+ ImageList_SetOverlayImage(hList, overlayIcon, 1);
+
+ mi->hOnlineIconBig = LoadSkinnedProtoIconBig(mi->pszModule, ID_STATUS_ONLINE);
+ mi->hOnlineIcon = LoadSkinnedProtoIcon(mi->pszModule, ID_STATUS_ONLINE);
+ index = ImageList_AddIcon(hList, mi->hOnlineIcon);
+ mi->hOnlineTalkIcon = ImageList_GetIcon(hList, index, ILD_TRANSPARENT | INDEXTOOVERLAYMASK(1));
+
+ mi->hOfflineIconBig = LoadSkinnedProtoIconBig(mi->pszModule, ID_STATUS_OFFLINE);
+ mi->hOfflineIcon = LoadSkinnedProtoIcon(mi->pszModule, ID_STATUS_OFFLINE);
+ index = ImageList_AddIcon(hList, mi->hOfflineIcon);
+ mi->hOfflineTalkIcon = ImageList_GetIcon(hList, index, ILD_TRANSPARENT | INDEXTOOVERLAYMASK(1));
+
+ ImageList_Destroy(hList);
+}
+
+static 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_STRUCT_GCREGISTER_V1)
+ return GC_REGISTER_WRONGVER;
+
+ #ifndef _UNICODE
+ if (gcr->dwFlags & GC_UNICODE)
+ return GC_REGISTER_NOUNICODE;
+ #endif
+
+ 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->bFontSize = gcr->dwFlags&GC_FONTSIZE;
+ mi->bAckMsg = gcr->dwFlags&GC_ACKMSG ;
+ mi->bChanMgr = gcr->dwFlags&GC_CHANMGR ;
+ mi->bSingleFormat = gcr->dwFlags&GC_SINGLEFORMAT;
+ mi->iMaxText= gcr->iMaxText;
+ mi->nColorCount = gcr->nColors;
+ if ( gcr->nColors > 0) {
+ mi->crColors = mir_alloc(sizeof(COLORREF) * gcr->nColors);
+ memcpy(mi->crColors, gcr->pColors, sizeof(COLORREF) * gcr->nColors);
+ }
+
+ CheckColorsInModule((char*)gcr->pszModule);
+ CList_SetAllOffline(TRUE, gcr->pszModule);
+
+ LeaveCriticalSection(&cs);
+ return 0;
+ }
+
+ LeaveCriticalSection(&cs);
+ return GC_REGISTER_ERROR;
+}
+
+static 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_STRUCT_GCWINDOW_V1)
+ 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);
+
+ if (mi->hOfflineIcon == NULL) {
+ LoadModuleIcons(mi);
+ }
+ // 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->iSplitterY = g_Settings.iSplitterY;
+ si->iLogFilterFlags = (int)DBGetContactSettingDword(NULL, "Chat", "FilterFlags", 0x03E0);
+ si->bFilterEnabled = DBGetContactSettingByte(NULL, "Chat", "FilterEnabled", 0);
+ si->bNicklistEnabled = DBGetContactSettingByte(NULL, "Chat", "ShowNicklist", 1);
+ #if defined( _UNICODE )
+ if ( !( gcw->dwFlags & GC_UNICODE )) {
+ si->pszID = mir_strdup( gcw->pszID );
+ si->pszName = mir_strdup( gcw->pszName );
+ }
+ #endif
+
+ 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->windowData.hContact = CList_AddRoom( gcw->pszModule, ptszID, szTemp, si->iType);
+ si->windowData.codePage = DBGetContactSettingWord(si->windowData.hContact, si->pszModule, "CodePage", (WORD) CP_ACP);
+ si->pszHeader = Log_CreateRtfHeader(mi, si);
+ DBWriteContactSettingString(si->windowData.hContact, si->pszModule , "Topic", "");
+ DBDeleteContactSetting(si->windowData.hContact, "CList", "StatusMsg");
+ if (si->ptszStatusbarText)
+ DBWriteContactSettingTString(si->windowData.hContact, si->pszModule, "StatusBar", si->ptszStatusbarText);
+ else
+ DBWriteContactSettingString(si->windowData.hContact, si->pszModule, "StatusBar", "");
+ }
+ 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->hWnd )
+ RedrawWindow(GetDlgItem(si2->hWnd, IDC_CHAT_LIST), NULL, NULL, RDW_INVALIDATE);
+
+ }
+ }
+
+ LeaveCriticalSection(&cs);
+ mir_free( ptszID );
+ return 0;
+ }
+
+ LeaveCriticalSection(&cs);
+ return GC_NEWSESSION_ERROR;
+}
+
+static INT_PTR DoControl(GCEVENT * gce, WPARAM wp)
+{
+ if ( gce->pDest->iType == GC_EVENT_CONTROL ) {
+ switch (wp) {
+ case WINDOW_HIDDEN:
+ {
+ SESSION_INFO* 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:
+ {
+ SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ si->bInitDone = TRUE;
+ if (wp != SESSION_INITDONE || DBGetContactSettingByte(NULL, "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:
+ {
+ SESSION_INFO* 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);
+ }
+ SM_SendMessage(gce->pDest->ptszID, gce->pDest->pszModule, GC_EVENT_CONTROL + WM_USER + 500, wp, 0);
+ }
+
+ else if (gce->pDest->iType == GC_EVENT_CHUID && gce->pszText)
+ {
+ SM_ChangeUID( gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszNick, gce->ptszText);
+ }
+
+ else if (gce->pDest->iType == GC_EVENT_CHANGESESSIONAME && gce->pszText)
+ {
+ SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if ( si ) {
+ replaceStr( &si->ptszName, gce->ptszText );
+ if (si->hWnd)
+ SendMessage(si->hWnd, DM_UPDATETITLEBAR, 0, 0);
+
+ }
+ }
+
+ else if (gce->pDest->iType == GC_EVENT_SETITEMDATA) {
+ SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si)
+ si->dwItemData = gce->dwItemData;
+ }
+
+ else if (gce->pDest->iType ==GC_EVENT_GETITEMDATA) {
+ SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ gce->dwItemData = si->dwItemData;
+ return si->dwItemData;
+ }
+ return 0;
+ }
+ else if (gce->pDest->iType ==GC_EVENT_SETSBTEXT)
+ {
+ SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if (si) {
+ replaceStr( &si->ptszStatusbarText, gce->ptszText );
+ if ( si->ptszStatusbarText )
+ DBWriteContactSettingTString(si->windowData.hContact, si->pszModule, "StatusBar", si->ptszStatusbarText);
+ else
+ DBWriteContactSettingString(si->windowData.hContact, si->pszModule, "StatusBar", "");
+ if (si->hWnd)
+ {
+ SendMessage(si->hWnd, DM_UPDATESTATUSBAR, 0, 0);
+ }
+ }
+ }
+ else if (gce->pDest->iType == GC_EVENT_ACK)
+ {
+ SM_SendMessage(gce->pDest->ptszID, gce->pDest->pszModule, GC_ACKMESSAGE, 0, 0);
+ }
+ else if (gce->pDest->iType == GC_EVENT_SENDMESSAGE && gce->pszText)
+ {
+ SM_SendUserMessage( gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszText);
+ }
+ else if (gce->pDest->iType == GC_EVENT_SETSTATUSEX)
+ {
+ SM_SetStatusEx( gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszText, gce->dwItemData);
+ }
+ else 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( si, 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);
+ }
+ }
+ }
+}
+
+
+void ShowRoom(SESSION_INFO * si, WPARAM wp, BOOL bSetForeground)
+{
+ HWND hParent = NULL;
+ if (!si)
+ return;
+
+ //Do we need to create a window?
+ if (si->hWnd == NULL)
+ {
+ hParent = GetParentWindow(si->windowData.hContact, TRUE);
+ si->hWnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_CHANNEL), hParent, RoomWndProc, (LPARAM)si);
+ }
+ SendMessage(si->hWnd, DM_UPDATETABCONTROL, -1, (LPARAM)si);
+ SendMessage(GetParent(si->hWnd), CM_ACTIVATECHILD, 0, (LPARAM) si->hWnd);
+ SendMessage(GetParent(si->hWnd), CM_POPUPWINDOW, 0, (LPARAM) si->hWnd);
+ SendMessage(si->hWnd, WM_MOUSEACTIVATE, 0, 0);
+ SetFocus(GetDlgItem(si->hWnd, IDC_CHAT_MESSAGE));
+}
+
+static INT_PTR Service_AddEvent(WPARAM wParam, LPARAM lParam)
+{
+ GCEVENT *gce = (GCEVENT*)lParam, save_gce;
+ GCDEST *gcd = NULL, save_gcd;
+ TCHAR* pWnd = NULL;
+ char* pMod = NULL;
+ BOOL bIsHighlighted = FALSE;
+ BOOL bRemoveFlag = FALSE;
+ int iRetVal = GC_EVENT_ERROR;
+
+ if ( gce == NULL )
+ return GC_EVENT_ERROR;
+
+ gcd = gce->pDest;
+ if ( gcd == NULL )
+ return GC_EVENT_ERROR;
+
+ if ( gce->cbSize != SIZEOF_STRUCT_GCEVENT_V1 && gce->cbSize != SIZEOF_STRUCT_GCEVENT_V2 )
+ return GC_EVENT_WRONGVER;
+
+ if ( !IsEventSupported( gcd->iType ) )
+ return GC_EVENT_ERROR;
+
+ EnterCriticalSection(&cs);
+
+ #if defined( _UNICODE )
+ 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 );
+ gce->ptszText = a2tf( gce->ptszText, gce->dwFlags );
+ gce->ptszUserInfo = a2tf( gce->ptszUserInfo, gce->dwFlags );
+ }
+ #endif
+
+ // 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:
+ {
+ SESSION_INFO* si = SM_FindSession(gce->pDest->ptszID, gce->pDest->pszModule);
+ if ( si ) {
+ if ( gce->pszText ) {
+ replaceStr( &si->ptszTopic, gce->ptszText);
+ DBWriteContactSettingTString( si->windowData.hContact, si->pszModule , "Topic", RemoveFormatting( si->ptszTopic ));
+ if ( DBGetContactSettingByte( NULL, "Chat", "TopicOnClist", 0 ))
+ DBWriteContactSettingTString( si->windowData.hContact, "CList" , "StatusMsg", RemoveFormatting( si->ptszTopic ));
+ } }
+ break;
+ }
+ case GC_EVENT_ADDSTATUS:
+ SM_GiveStatus( gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID, gce->ptszStatus );
+ break;
+
+ case GC_EVENT_REMOVESTATUS:
+ SM_TakeStatus( gce->pDest->ptszID, gce->pDest->pszModule, gce->ptszUID, gce->ptszStatus);
+ break;
+
+ case GC_EVENT_MESSAGE:
+ case GC_EVENT_ACTION:
+ if ( !gce->bIsMe && gce->pDest->pszID && gce->pszText ) {
+ SESSION_INFO* si = SM_FindSession( gce->pDest->ptszID, gce->pDest->pszModule );
+ if ( si )
+ if ( IsHighlighted( si, gce->ptszText ))
+ bIsHighlighted = TRUE;
+ }
+ break;
+
+ case GC_EVENT_NICK:
+ SM_ChangeNick( gce->pDest->ptszID, gce->pDest->pszModule, gce);
+ break;
+
+ case GC_EVENT_JOIN:
+ AddUser(gce);
+ break;
+
+ case GC_EVENT_PART:
+ case GC_EVENT_QUIT:
+ case GC_EVENT_KICK:
+ bRemoveFlag = TRUE;
+ 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 );
+ if ( !bRemoveFlag ) {
+ iRetVal = 0;
+ goto LBL_Exit;
+ } }
+
+ // add to log
+ if ( pWnd ) {
+ SESSION_INFO* 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 defined( _UNICODE )
+ if ( !( gce->dwFlags & GC_UNICODE )) {
+ 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;
+ }
+ #endif
+
+ 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)
+{
+ HookEvent_Ex(ME_CLIST_PREBUILDCONTACTMENU, CList_PrebuildContactMenu);
+}
+
+void CreateServiceFunctions(void)
+{
+ CreateServiceFunction_Ex(MS_GC_REGISTER, Service_Register);
+ CreateServiceFunction_Ex(MS_GC_NEWSESSION, Service_NewChat);
+ CreateServiceFunction_Ex(MS_GC_EVENT, Service_AddEvent);
+ CreateServiceFunction_Ex(MS_GC_GETEVENTPTR, Service_GetAddEventPtr);
+ CreateServiceFunction_Ex(MS_GC_GETINFO, Service_GetInfo);
+ CreateServiceFunction_Ex(MS_GC_GETSESSIONCOUNT, Service_GetCount);
+
+ CreateServiceFunction_Ex("GChat/DblClickEvent", CList_EventDoubleclickedSvc);
+ CreateServiceFunction_Ex("GChat/PrebuildMenuEvent", CList_PrebuildContactMenuSvc);
+ CreateServiceFunction_Ex("GChat/JoinChat", CList_JoinChat);
+ CreateServiceFunction_Ex("GChat/LeaveChat", CList_LeaveChat);
+}
+
+void CreateHookableEvents(void)
+{
+ hSendEvent = CreateHookableEvent(ME_GC_EVENT);
+ hBuildMenuEvent = CreateHookableEvent(ME_GC_BUILDMENU);
+}
+
+void DestroyHookableEvents(void)
+{
+ DestroyHookableEvent(hSendEvent);
+ DestroyHookableEvent(hBuildMenuEvent);
+}
diff --git a/plugins/Scriver/chat/tools.c b/plugins/Scriver/chat/tools.c new file mode 100644 index 0000000000..2dd4bedf3f --- /dev/null +++ b/plugins/Scriver/chat/tools.c @@ -0,0 +1,976 @@ +/*
+Chat module plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+Copyright 2003-2009 Miranda ICQ/IM project,
+
+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.
+*/
+
+#include "../commonheaders.h"
+#include "chat.h"
+#include <string.h>
+#include <shlwapi.h>
+
+extern HINSTANCE g_hInst;
+extern FONTINFO aFonts[OPTIONS_FONTCOUNT];
+extern HMENU g_hMenu;
+extern HANDLE hBuildMenuEvent ;
+extern HANDLE hSendEvent;
+
+TCHAR* RemoveFormatting(const TCHAR* pszWord)
+{
+ static TCHAR szTemp[10000];
+ int i = 0;
+ int j = 0;
+
+ if ( pszWord == 0 || lstrlen(pszWord) == 0 )
+ return NULL;
+
+ while(j < 9999 && i <= lstrlen( pszWord )) {
+ 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 {
+ szTemp[j] = pszWord[i];
+ j++;
+ i++;
+ } }
+
+ return (TCHAR*) &szTemp;
+}
+
+static void __stdcall ShowRoomFromPopup(void * pi)
+{
+ SESSION_INFO* si = (SESSION_INFO*) pi;
+ ShowRoom(si, WINDOW_VISIBLE, TRUE);
+}
+
+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);;
+
+ CallFunctionAsync(ShowRoomFromPopup, si);
+
+ PUDeletePopUp(hWnd);
+ return TRUE;
+ }
+ break;
+ case WM_CONTEXTMENU:
+ {
+ SESSION_INFO* si = (SESSION_INFO*)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd,(LPARAM)0);
+ if (si->windowData.hContact)
+ if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->windowData.hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->windowData.hContact, (LPARAM)"chaticon");
+
+ PUDeletePopUp( 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 pd = {0};
+ va_list marker;
+ static TCHAR szBuf[4*1024];
+
+ if (!fmt || lstrlen(fmt) == 0 || lstrlen(fmt) > 2000)
+ return 0;
+
+ va_start(marker, fmt);
+ _vsntprintf(szBuf, 4096, fmt, marker);
+ va_end(marker);
+
+ pd.lchContact = hContact;
+
+ if ( hIcon )
+ pd.lchIcon = hIcon ;
+ else
+ pd.lchIcon = GetCachedIcon("chat_window");
+
+ 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 = g_Settings.crLogBackground;
+ pd.colorText = crBkg;
+ }
+
+ pd.PluginWindowProc = PopupDlgProc;
+ pd.PluginData = si;
+ return PUAddPopUpT(&pd);
+}
+
+static BOOL DoTrayIcon(SESSION_INFO* si, GCEVENT * gce)
+{
+ int iEvent = gce->pDest->iType;
+
+ if ( iEvent&g_Settings.dwTrayIconFlags ) {
+ switch ( iEvent ) {
+ case GC_EVENT_MESSAGE|GC_EVENT_HIGHLIGHT :
+ case GC_EVENT_ACTION|GC_EVENT_HIGHLIGHT :
+ CList_AddEvent(si->windowData.hContact, LoadSkinnedIcon(SKINICON_EVENT_MESSAGE), "chaticon", 0, TranslateT("%s wants your attention in %s"), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_MESSAGE :
+ CList_AddEvent(si->windowData.hContact, GetCachedIcon("chat_log_message_in"), "chaticon", CLEF_ONLYAFEW, TranslateT("%s speaks in %s"), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_ACTION:
+ CList_AddEvent(si->windowData.hContact, GetCachedIcon("chat_log_action"), "chaticon", CLEF_ONLYAFEW, TranslateT("%s speaks in %s"), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_JOIN:
+ CList_AddEvent(si->windowData.hContact, GetCachedIcon("chat_log_join"), "chaticon", CLEF_ONLYAFEW, TranslateT("%s has joined %s"), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_PART:
+ CList_AddEvent(si->windowData.hContact, GetCachedIcon("chat_log_part"), "chaticon", CLEF_ONLYAFEW, TranslateT("%s has left %s"), gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_QUIT:
+ CList_AddEvent(si->windowData.hContact, GetCachedIcon("chat_log_quit"), "chaticon", CLEF_ONLYAFEW, TranslateT("%s has disconnected"), gce->ptszNick);
+ break;
+ case GC_EVENT_NICK:
+ CList_AddEvent(si->windowData.hContact, GetCachedIcon("chat_log_nick"), "chaticon", CLEF_ONLYAFEW, TranslateT("%s is now known as %s"), gce->ptszNick, gce->pszText);
+ break;
+ case GC_EVENT_KICK:
+ CList_AddEvent(si->windowData.hContact, GetCachedIcon("chat_log_kick"), "chaticon", CLEF_ONLYAFEW, TranslateT("%s kicked %s from %s"), gce->pszStatus, gce->ptszNick, si->ptszName);
+ break;
+ case GC_EVENT_NOTICE:
+ CList_AddEvent(si->windowData.hContact, GetCachedIcon("chat_log_notice"), "chaticon", CLEF_ONLYAFEW, TranslateT("Notice from %s"), gce->ptszNick);
+ break;
+ case GC_EVENT_TOPIC:
+ CList_AddEvent(si->windowData.hContact, GetCachedIcon("chat_log_topic"), "chaticon", CLEF_ONLYAFEW, TranslateT("Topic change in %s"), si->ptszName);
+ break;
+ case GC_EVENT_INFORMATION:
+ CList_AddEvent(si->windowData.hContact, GetCachedIcon("chat_log_info"), "chaticon", CLEF_ONLYAFEW, TranslateT("Information in %s"), si->ptszName);
+ break;
+ case GC_EVENT_ADDSTATUS:
+ CList_AddEvent(si->windowData.hContact, GetCachedIcon("chat_log_addstatus"), "chaticon", 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->windowData.hContact, GetCachedIcon("chat_log_removestatus"), "chaticon", 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)
+{
+ int iEvent = gce->pDest->iType;
+
+ if ( iEvent & g_Settings.dwPopupFlags ) {
+ switch (iEvent) {
+ case GC_EVENT_MESSAGE|GC_EVENT_HIGHLIGHT :
+ ShowPopup(si->windowData.hContact, si, LoadSkinnedIcon(SKINICON_EVENT_MESSAGE), si->pszModule, si->ptszName, aFonts[16].color, TranslateT("%s says: %s"), gce->ptszNick, RemoveFormatting( gce->ptszText ));
+ break;
+ case GC_EVENT_ACTION|GC_EVENT_HIGHLIGHT :
+ ShowPopup(si->windowData.hContact, si, LoadSkinnedIcon(SKINICON_EVENT_MESSAGE), si->pszModule, si->ptszName, aFonts[16].color, _T("%s %s"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_MESSAGE :
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_message_in"), si->pszModule, si->ptszName, aFonts[9].color, TranslateT("%s says: %s"), gce->ptszNick, RemoveFormatting( gce->ptszText));
+ break;
+ case GC_EVENT_ACTION:
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_action"), si->pszModule, si->ptszName, aFonts[15].color, _T("%s %s"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_JOIN:
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_join"), si->pszModule, si->ptszName, aFonts[3].color, TranslateT("%s has joined"), gce->ptszNick);
+ break;
+ case GC_EVENT_PART:
+ if (!gce->pszText)
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_part"), si->pszModule, si->ptszName, aFonts[4].color, TranslateT("%s has left"), gce->ptszNick);
+ else
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_part"), si->pszModule, si->ptszName, aFonts[4].color, TranslateT("%s has left (%s)"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_QUIT:
+ if (!gce->pszText)
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_quit"), si->pszModule, si->ptszName, aFonts[5].color, TranslateT("%s has disconnected"), gce->ptszNick);
+ else
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_quit"), si->pszModule, si->ptszName, aFonts[5].color, TranslateT("%s has disconnected (%s)"), gce->ptszNick,RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_NICK:
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_nick"), si->pszModule, si->ptszName, aFonts[7].color, TranslateT("%s is now known as %s"), gce->ptszNick, gce->ptszText);
+ break;
+ case GC_EVENT_KICK:
+ if (!gce->pszText)
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_kick"), si->pszModule, si->ptszName, aFonts[6].color, TranslateT("%s kicked %s"), (char *)gce->pszStatus, gce->ptszNick);
+ else
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_kick"), si->pszModule, si->ptszName, aFonts[6].color, TranslateT("%s kicked %s (%s)"), (char *)gce->pszStatus, gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_NOTICE:
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_notice"), si->pszModule, si->ptszName, aFonts[8].color, TranslateT("Notice from %s: %s"), gce->ptszNick, RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_TOPIC:
+ if (!gce->ptszNick)
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_topic"), si->pszModule, si->ptszName, aFonts[11].color, TranslateT("The topic is \'%s\'"), RemoveFormatting(gce->ptszText));
+ else
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_topic"), si->pszModule, si->ptszName, aFonts[11].color, TranslateT("The topic is \'%s\' (set by %s)"), RemoveFormatting(gce->ptszText), gce->ptszNick);
+ break;
+ case GC_EVENT_INFORMATION:
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_info"), si->pszModule, si->ptszName, aFonts[12].color, _T("%s"), RemoveFormatting(gce->ptszText));
+ break;
+ case GC_EVENT_ADDSTATUS:
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_addstatus"), si->pszModule, si->ptszName, aFonts[13].color, TranslateT("%s enables \'%s\' status for %s"), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick);
+ break;
+ case GC_EVENT_REMOVESTATUS:
+ ShowPopup(si->windowData.hContact, si, GetCachedIcon("chat_log_removestatus"), si->pszModule, si->ptszName, aFonts[14].color, TranslateT("%s disables \'%s\' status for %s"), gce->ptszText, (char *)gce->pszStatus, gce->ptszNick);
+ break;
+ } }
+
+ return TRUE;
+}
+
+BOOL DoSoundsFlashPopupTrayStuff(SESSION_INFO* si, GCEVENT * gce, BOOL bHighlight, int bManyFix)
+{
+ BOOL bInactive;
+ int iEvent;
+
+ if (!gce || !si || gce->bIsMe || si->iType == GCW_SERVER)
+ return FALSE;
+
+ bInactive = si->hWnd == NULL || GetForegroundWindow() != GetParent(si->hWnd);
+ // bInactive |= GetActiveWindow() != si->hWnd; // Removed this, because it seemed to be FALSE, even when window was focused, causing incorrect notifications
+
+ iEvent = gce->pDest->iType;
+
+ if ( bHighlight ) {
+ gce->pDest->iType |= GC_EVENT_HIGHLIGHT;
+ if (bInactive || !g_Settings.SoundsFocus)
+ SkinPlaySound("ChatHighlight");
+ if (bInactive && si->hWnd && DBGetContactSettingByte(NULL, "Chat", "FlashWindowHighlight", 0) != 0)
+ SendMessage(GetParent(si->hWnd), CM_STARTFLASHING, 0, 0);
+ if (DBGetContactSettingByte(si->windowData.hContact, "CList", "Hidden", 0) != 0)
+ DBDeleteContactSetting(si->windowData.hContact, "CList", "Hidden");
+ if (bInactive)
+ DoTrayIcon(si, gce);
+ if (bInactive || !g_Settings.PopUpInactiveOnly)
+ DoPopup(si, gce);
+ if (bInactive && si->hWnd)
+ SendMessage(si->hWnd, GC_SETMESSAGEHIGHLIGHT, 0, 0);
+ return TRUE;
+ }
+
+ // do blinking icons in tray
+ if (bInactive || !g_Settings.TrayIconInactiveOnly)
+ DoTrayIcon(si, gce);
+
+ // stupid thing to not create multiple popups for a QUIT event for instance
+ if (bManyFix == 0) {
+ // do popups
+ if (bInactive || !g_Settings.PopUpInactiveOnly)
+ DoPopup(si, gce);
+
+ // do sounds and flashing
+ switch (iEvent) {
+ case GC_EVENT_JOIN:
+ if (bInactive || !g_Settings.SoundsFocus)
+ SkinPlaySound("ChatJoin");
+ break;
+ case GC_EVENT_PART:
+ if (bInactive || !g_Settings.SoundsFocus)
+ SkinPlaySound("ChatPart");
+ break;
+ case GC_EVENT_QUIT:
+ if (bInactive || !g_Settings.SoundsFocus)
+ SkinPlaySound("ChatQuit");
+ break;
+ case GC_EVENT_ADDSTATUS:
+ case GC_EVENT_REMOVESTATUS:
+ if (bInactive || !g_Settings.SoundsFocus)
+ SkinPlaySound("ChatMode");
+ break;
+ case GC_EVENT_KICK:
+ if (bInactive || !g_Settings.SoundsFocus)
+ SkinPlaySound("ChatKick");
+ break;
+ case GC_EVENT_MESSAGE:
+ if (bInactive || !g_Settings.SoundsFocus)
+ SkinPlaySound("ChatMessage");
+ if (bInactive && g_Settings.FlashWindow && si->hWnd)
+ SendMessage(GetParent(si->hWnd), CM_STARTFLASHING, 0, 0);
+
+ if (bInactive && !( si->wState & STATE_TALK )) {
+ si->wState |= STATE_TALK;
+ DBWriteContactSettingWord(si->windowData.hContact, si->pszModule,"ApparentMode",(LPARAM)(WORD) 40071);
+ }
+ if (bInactive && si->hWnd)
+ SendMessage(si->hWnd, GC_SETTABHIGHLIGHT, 0, 0);
+ break;
+ case GC_EVENT_ACTION:
+ if (bInactive || !g_Settings.SoundsFocus)
+ SkinPlaySound("ChatAction");
+ break;
+ case GC_EVENT_NICK:
+ if (bInactive || !g_Settings.SoundsFocus)
+ SkinPlaySound("ChatNick");
+ break;
+ case GC_EVENT_NOTICE:
+ if (bInactive || !g_Settings.SoundsFocus)
+ SkinPlaySound("ChatNotice");
+ break;
+ case GC_EVENT_TOPIC:
+ if (bInactive || !g_Settings.SoundsFocus)
+ SkinPlaySound("ChatTopic");
+ break;
+ } }
+
+ return TRUE;
+}
+
+int 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)DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_INPUTBKGCOLOUR, SRMSGDEFSET_INPUTBKGCOLOUR);
+
+ LoadMsgDlgFont(MSGFONTID_MESSAGEAREA, NULL, &crFG, FALSE);
+
+ 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;
+ 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;
+}
+
+BOOL IsHighlighted(SESSION_INFO* si, const TCHAR* pszText)
+{
+ if ( g_Settings.HighlightEnabled && g_Settings.pszHighlightWords && pszText && si->pMe ) {
+ TCHAR* p1 = g_Settings.pszHighlightWords;
+ TCHAR* p2 = NULL;
+ const TCHAR* p3 = pszText;
+ static TCHAR szWord1[1000];
+ static TCHAR szWord2[1000];
+ static TCHAR szTrimString[] = _T(":,.!?;\'>)");
+
+ // compare word for word
+ while (*p1 != '\0') {
+ // find the next/first word in the highlight word string
+ // skip 'spaces' be4 the word
+ while(*p1 == ' ' && *p1 != '\0')
+ p1 += 1;
+
+ //find the end of the word
+ p2 = _tcschr(p1, ' ');
+ if (!p2)
+ p2 = _tcschr(p1, '\0');
+ if (p1 == p2)
+ return FALSE;
+
+ // copy the word into szWord1
+ lstrcpyn(szWord1, p1, p2-p1>998?999:p2-p1+1);
+ p1 = p2;
+
+ // replace %m with the users nickname
+ p2 = _tcschr(szWord1, '%');
+ if (p2 && p2[1] == 'm') {
+ TCHAR szTemp[50];
+
+ p2[1] = 's';
+ lstrcpyn(szTemp, szWord1, SIZEOF(szTemp));
+ mir_sntprintf(szWord1, SIZEOF(szWord1), szTemp, si->pMe->pszNick);
+ }
+
+ // time to get the next/first word in the incoming text string
+ while(*p3 != '\0')
+ {
+ // skip 'spaces' be4 the word
+ while(*p3 == ' ' && *p3 != '\0')
+ p3 += 1;
+
+ //find the end of the word
+ p2 = _tcschr(p3, ' ');
+ if (!p2)
+ p2 = _tcschr(p3, '\0');
+
+
+ if (p3 != p2) {
+ // eliminate ending character if needed
+ if (p2-p3 > 1 && _tcschr(szTrimString, p2[-1]))
+ p2 -= 1;
+
+ // copy the word into szWord2 and remove formatting
+ lstrcpyn(szWord2, p3, p2-p3>998?999:p2-p3+1);
+
+ // reset the pointer if it was touched because of an ending character
+ if (*p2 != '\0' && *p2 != ' ')
+ p2 += 1;
+ p3 = p2;
+
+ CharLower(szWord1);
+ CharLower(szWord2);
+
+ // compare the words, using wildcards
+ if (WCCmp(szWord1, RemoveFormatting(szWord2)))
+ return TRUE;
+ } }
+
+ p3 = pszText;
+ } }
+
+ return FALSE;
+}
+
+BOOL LogToFile(SESSION_INFO* si, GCEVENT * gce)
+{
+ MODULEINFO * mi = NULL;
+ TCHAR szBuffer[4096];
+ TCHAR szLine[4096];
+ TCHAR szTime[100];
+ FILE *hFile = NULL;
+ TCHAR tszFile[MAX_PATH];
+ TCHAR tszFolder[MAX_PATH];
+ TCHAR p = '\0';
+ BOOL bFileJustCreated = TRUE;
+
+ if (!si || !gce)
+ return FALSE;
+
+ mi = MM_FindModule(si->pszModule);
+ if ( !mi )
+ return FALSE;
+
+ szBuffer[0] = '\0';
+
+ lstrcpyn(tszFile, GetChatLogsFilename(si->windowData.hContact, gce->time), MAX_PATH);
+ bFileJustCreated = !PathFileExists(tszFile);
+ _tcscpy(tszFolder, tszFile);
+ PathRemoveFileSpec(tszFolder);
+ if (!PathIsDirectory(tszFolder))
+ CallService(MS_UTILS_CREATEDIRTREET, 0, (LPARAM)tszFolder);
+
+ lstrcpyn(szTime, MakeTimeStamp(g_Settings.pszTimeStampLog, gce->time), 99);
+
+ hFile = _tfopen(tszFile, _T("ab+"));
+ if (hFile) {
+ TCHAR szTemp[512], szTemp2[512];
+ TCHAR* pszNick = NULL;
+#ifdef _UNICODE
+ if (bFileJustCreated)
+ fputws((const wchar_t*)"\377\376", hFile); //UTF-16 LE BOM == FF FE
+#endif
+ 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;
+ }
+ if (p)
+ mir_sntprintf(szLine, SIZEOF(szLine), TranslateT("%s %c %s\r\n"), szTime, p, szBuffer);
+ else
+ mir_sntprintf(szLine, SIZEOF(szLine), TranslateT("%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 + 1024 * 10;
+ if (dwSize > trimlimit) {
+ BYTE * pBuffer = 0;
+ BYTE * pBufferTemp = 0;
+ size_t read = 0;
+
+ pBuffer = (BYTE *)mir_alloc(g_Settings.LoggingLimit * 1024 + 2);
+ pBuffer[g_Settings.LoggingLimit*1024] = '\0';
+ pBuffer[g_Settings.LoggingLimit*1024+1] = '\0';
+ fseek(hFile, -g_Settings.LoggingLimit*1024, SEEK_END);
+ read = fread(pBuffer, 1, g_Settings.LoggingLimit * 1024, hFile);
+ fclose(hFile);
+ hFile = NULL;
+
+ // trim to whole lines, should help with broken log files I hope.
+ pBufferTemp = (BYTE*)_tcschr((TCHAR*)pBuffer, _T('\n'));
+ if (pBufferTemp) {
+ pBufferTemp+= sizeof(TCHAR);
+ read = read - (pBufferTemp - pBuffer);
+ } else pBufferTemp = pBuffer;
+
+ if (read > 0) {
+ hFile = _tfopen(tszFile, _T("wb"));
+ if (hFile) {
+#ifdef _UNICODE
+ fputws((const wchar_t*)"\377\376", hFile); //UTF-16 LE BOM == FF FE
+#endif
+ fwrite(pBufferTemp, 1, read, hFile);
+ fclose(hFile);
+ hFile = NULL;
+ } }
+ mir_free(pBuffer);
+ } } }
+
+ if (hFile)
+ fclose(hFile);
+ hFile = NULL;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+UINT CreateGCMenu(HWND hwnd, HMENU *hMenu, int iIndex, POINT pt, SESSION_INFO* si, TCHAR* pszUID, TCHAR* pszWordText)
+{
+ GCMENUITEMS gcmi = {0};
+ int i;
+ HMENU hSubMenu = 0;
+
+ *hMenu = GetSubMenu(g_hMenu, iIndex);
+ gcmi.pszID = si->ptszID;
+ gcmi.pszModule = si->pszModule;
+ gcmi.pszUID = pszUID;
+
+ if (iIndex == 1) {
+ int iLen = GetRichTextLength(hwnd, CP_ACP, FALSE);
+
+ EnableMenuItem(*hMenu, IDM_CLEAR, MF_ENABLED);
+ EnableMenuItem(*hMenu, ID_COPYALL, MF_ENABLED);
+ if (!iLen) {
+ EnableMenuItem(*hMenu, ID_COPYALL, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem(*hMenu, IDM_CLEAR, MF_BYCOMMAND | MF_GRAYED);
+ }
+
+ 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 );
+ SetSearchEngineIcons(*hMenu, g_dat->hSearchEngineIconList);
+ }
+ 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 );
+ DWORD dwState = gcmi.Item[i].bDisabled ? MF_GRAYED : 0;
+
+ if ( gcmi.Item[i].uType == MENU_NEWPOPUP ) {
+ hSubMenu = CreateMenu();
+ AppendMenu( *hMenu, dwState|MF_POPUP, (UINT_PTR)hSubMenu, ptszDescr );
+ }
+ else if (gcmi.Item[i].uType == MENU_POPUPHMENU)
+ AppendMenu( hSubMenu==0?*hMenu:hSubMenu, dwState|MF_POPUP, gcmi.Item[i].dwID, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_POPUPITEM)
+ AppendMenu( hSubMenu==0?*hMenu:hSubMenu, dwState|MF_STRING, gcmi.Item[i].dwID, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_POPUPCHECK)
+ AppendMenu( hSubMenu==0?*hMenu:hSubMenu, dwState|MF_CHECKED|MF_STRING, gcmi.Item[i].dwID, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_POPUPSEPARATOR)
+ AppendMenu( hSubMenu==0?*hMenu:hSubMenu, MF_SEPARATOR, 0, ptszDescr );
+ else if (gcmi.Item[i].uType == MENU_SEPARATOR)
+ AppendMenu( *hMenu, MF_SEPARATOR, 0, ptszDescr );
+ else if (gcmi.Item[i].uType == MENU_HMENU)
+ AppendMenu( *hMenu, dwState|MF_POPUP, gcmi.Item[i].dwID, ptszDescr);
+ else if (gcmi.Item[i].uType == MENU_ITEM)
+ AppendMenu( *hMenu, dwState|MF_STRING, gcmi.Item[i].dwID, ptszDescr );
+ else if (gcmi.Item[i].uType == MENU_CHECK)
+ AppendMenu( *hMenu, dwState|MF_CHECKED|MF_STRING, gcmi.Item[i].dwID, ptszDescr );
+
+ mir_free( ptszDescr );
+ }
+ return TrackPopupMenu(*hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, 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)
+{
+ #if defined( _UNICODE )
+ SESSION_INFO* si;
+ #endif
+ 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 defined( _UNICODE )
+ if (( si = SM_FindSession(pszID, pszModule)) == NULL )
+ return FALSE;
+
+ if ( !( si->dwFlags & GC_UNICODE )) {
+ gcd->pszID = t2a( pszID );
+ gch->pszUID = t2a( pszUID );
+ gch->pszText = t2a( pszText );
+ }
+ else {
+ #endif
+ replaceStr( &gcd->ptszID, pszID );
+ replaceStr( &gch->ptszUID, pszUID);
+ replaceStr( &gch->ptszText, pszText);
+ #if defined( _UNICODE )
+ }
+ #endif
+ 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)
+{
+ #if defined( _UNICODE )
+ SESSION_INFO* si;
+ #endif
+ GCHOOK gch = {0};
+ GCDEST gcd = {0};
+
+ gcd.pszModule = (char*)pszModule;
+ #if defined( _UNICODE )
+ if (( si = SM_FindSession(pszID, pszModule)) == NULL )
+ return FALSE;
+
+ if ( !( si->dwFlags & GC_UNICODE )) {
+ gcd.pszID = t2a( pszID );
+ gch.pszUID = t2a( pszUID );
+ gch.pszText = t2a( pszText );
+ }
+ else {
+ #endif
+ gcd.ptszID = mir_tstrdup( pszID );
+ gch.ptszUID = mir_tstrdup( pszUID );
+ gch.ptszText = mir_tstrdup( pszText );
+ #if defined( _UNICODE )
+ }
+ #endif
+
+ 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 )
+{
+ if ( str == NULL )
+ return NULL;
+
+ #if defined( _UNICODE )
+ if ( flags & GC_UNICODE )
+ return mir_tstrdup( str );
+ else {
+ int codepage = CallService( MS_LANGPACK_GETCODEPAGE, 0, 0 );
+
+ int cbLen = MultiByteToWideChar( codepage, 0, (char*)str, -1, 0, 0 );
+ TCHAR* result = ( TCHAR* )mir_alloc( sizeof(TCHAR)*( cbLen+1 ));
+ if ( result == NULL )
+ return NULL;
+
+ MultiByteToWideChar( codepage, 0, (char*)str, -1, result, cbLen );
+ result[ cbLen ] = 0;
+ return result;
+ }
+ #else
+ return mir_strdup( str );
+ #endif
+}
+
+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;
+}
+
+TCHAR* GetChatLogsFilename (HANDLE hContact, time_t tTime)
+{ REPLACEVARSARRAY rva[11];
+ REPLACEVARSDATA dat = {0};
+ static TCHAR tszFileName[MAX_PATH];
+ TCHAR *p = {0}, *tszParsedName = {0};
+ int i;
+
+ if (g_Settings.pszLogDir[_tcslen(g_Settings.pszLogDir)-1] == '\\')
+ _tcscat(g_Settings.pszLogDir, _T("%userid%.log"));
+ if(!tTime)
+ time(&tTime);
+
+ // day 1-31
+ 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;
+
+ dat.cbSize = sizeof(dat);
+ dat.dwFlags = RVF_TCHAR;
+ dat.hContact = hContact;
+ dat.variables = rva;
+ tszParsedName = (TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)g_Settings.pszLogDir, (LPARAM)&dat);
+ _tcsncpy(tszFileName, tszParsedName, MAX_PATH);
+ mir_free(tszParsedName);
+ for (i=0; i < SIZEOF(rva);i++)
+ mir_free(rva[i].lptzValue);
+
+ for (p = tszFileName + 2; *p; ++p) {
+ if (*p == ':' || *p == '*' || *p == '?' || *p == '"' || *p == '<' || *p == '>' || *p == '|' )
+ *p = _T('_');
+ }
+
+ return tszFileName;
+}
diff --git a/plugins/Scriver/chat/window.c b/plugins/Scriver/chat/window.c new file mode 100644 index 0000000000..762bb0e95c --- /dev/null +++ b/plugins/Scriver/chat/window.c @@ -0,0 +1,2200 @@ +/*
+Chat module plugin for Miranda IM
+
+Copyright (C) 2003 Jörgen Persson
+Copyright 2003-2009 Miranda ICQ/IM project,
+
+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.
+*/
+
+#include "../commonheaders.h"
+#include "chat.h"
+#include "../utils.h"
+#include "../statusicon.h"
+
+#ifndef WM_UNICHAR
+#define WM_UNICHAR 0x0109
+#endif
+
+extern HBRUSH hListBkgBrush;
+extern HBRUSH hListSelectedBkgBrush;
+extern HANDLE hSendEvent;
+extern HINSTANCE g_hInst;
+extern struct CREOleCallback reOleCallback;
+extern HMENU g_hMenu;
+extern TABLIST * g_TabList;
+extern HANDLE hHookWinPopup;
+extern HCURSOR hCurSplitNS, hCurSplitWE;
+
+static WNDPROC OldSplitterProc;
+static WNDPROC OldMessageProc;
+static WNDPROC OldNicklistProc;
+static WNDPROC OldFilterButtonProc;
+static WNDPROC OldLogProc;
+
+static ToolbarButton toolbarButtons[] = {
+ {_T("Bold"), IDC_CHAT_BOLD, 0, 4, 24},
+ {_T("Italic"), IDC_CHAT_ITALICS, 0, 0, 24},
+ {_T("Underline"), IDC_CHAT_UNDERLINE, 0, 0, 24},
+ {_T("Text color"), IDC_CHAT_COLOR, 0, 0, 24},
+ {_T("Background color"), IDC_CHAT_BKGCOLOR, 0, 0, 24},
+// {_T("Font size"), IDC_CHAT_FONTSIZE, 0, 0, 48},
+ {_T("Smiley"), IDC_CHAT_SMILEY, 0, 8, 24},
+ {_T("History"), IDC_CHAT_HISTORY, 1, 0, 24},
+ {_T("Filter"), IDC_CHAT_FILTER, 1, 0, 24},
+ {_T("Manager"), IDC_CHAT_CHANMGR, 1, 0, 24},
+ {_T("Nick list"), IDC_CHAT_SHOWNICKLIST, 1, 0, 24},
+ {_T("Send"), IDOK, 1, 0, 38},
+};
+
+typedef struct
+{
+ time_t lastEnterTime;
+ TCHAR* szSearchQuery;
+ TCHAR* szSearchResult;
+ SESSION_INFO *lastSession;
+} MESSAGESUBDATA;
+
+
+static LRESULT CALLBACK SplitterSubclassProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ switch(msg) {
+ case WM_NCHITTEST:
+ return HTCLIENT;
+
+ case WM_SETCURSOR:
+ {
+ RECT rc;
+ GetClientRect(hwnd, &rc);
+ SetCursor(rc.right > rc.bottom ? hCurSplitNS : hCurSplitWE);
+ return TRUE;
+ }
+ return 0;
+ case WM_LBUTTONDOWN:
+ SetCapture(hwnd);
+ return 0;
+
+ case WM_MOUSEMOVE:
+ if (GetCapture()==hwnd) {
+ RECT rc;
+ GetClientRect(hwnd,&rc);
+ SendMessage(GetParent(hwnd),GC_SPLITTERMOVED,rc.right>rc.bottom?(short)HIWORD(GetMessagePos())+rc.bottom/2:(short)LOWORD(GetMessagePos())+rc.right/2,(LPARAM)hwnd);
+ }
+ return 0;
+
+ case WM_LBUTTONUP:
+ ReleaseCapture();
+ PostMessage(GetParent(hwnd),WM_SIZE, 0, 0);
+ return 0;
+ }
+ return CallWindowProc(OldSplitterProc,hwnd,msg,wParam,lParam);
+}
+
+static void InitButtons(HWND hwndDlg, SESSION_INFO* si)
+{
+ MODULEINFO * pInfo = MM_FindModule(si->pszModule);
+
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_SMILEY,BM_SETIMAGE,IMAGE_ICON,(LPARAM)GetCachedIcon("chat_smiley"));
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_BOLD,BM_SETIMAGE,IMAGE_ICON,(LPARAM)GetCachedIcon("chat_bold"));
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_ITALICS,BM_SETIMAGE,IMAGE_ICON,(LPARAM)GetCachedIcon("chat_italics"));
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_UNDERLINE,BM_SETIMAGE,IMAGE_ICON,(LPARAM)GetCachedIcon("chat_underline"));
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_COLOR,BM_SETIMAGE,IMAGE_ICON,(LPARAM)GetCachedIcon("chat_fgcol"));
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_BKGCOLOR,BM_SETIMAGE,IMAGE_ICON,(LPARAM)GetCachedIcon("chat_bkgcol"));
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_HISTORY,BM_SETIMAGE,IMAGE_ICON,(LPARAM)GetCachedIcon("chat_history"));
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_CHANMGR,BM_SETIMAGE,IMAGE_ICON,(LPARAM)GetCachedIcon("chat_settings"));
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_SHOWNICKLIST,BM_SETIMAGE,IMAGE_ICON,(LPARAM)GetCachedIcon(si->bNicklistEnabled?"chat_nicklist":"chat_nicklist2"));
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_FILTER,BM_SETIMAGE,IMAGE_ICON,(LPARAM)GetCachedIcon(si->bFilterEnabled?"chat_filter":"chat_filter2"));
+ SendDlgItemMessage(hwndDlg, IDOK, BM_SETIMAGE, IMAGE_ICON, (LPARAM) GetCachedIcon("scriver_SEND"));
+
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_SMILEY, BUTTONSETASFLATBTN, 0, 0);
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_BOLD, BUTTONSETASFLATBTN, 0, 0);
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_ITALICS, BUTTONSETASFLATBTN, 0, 0);
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_UNDERLINE, BUTTONSETASFLATBTN, 0, 0);
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_BKGCOLOR, BUTTONSETASFLATBTN, 0, 0);
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_COLOR, BUTTONSETASFLATBTN, 0, 0);
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_HISTORY, BUTTONSETASFLATBTN, 0, 0);
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_SHOWNICKLIST, BUTTONSETASFLATBTN, 0, 0);
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_CHANMGR, BUTTONSETASFLATBTN, 0, 0);
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_FILTER, BUTTONSETASFLATBTN, 0, 0);
+ SendDlgItemMessage(hwndDlg,IDOK, BUTTONSETASFLATBTN, 0, 0);
+
+ SendMessage(GetDlgItem(hwndDlg,IDC_CHAT_SMILEY), BUTTONADDTOOLTIP, (WPARAM)Translate("Insert a smiley"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_CHAT_BOLD), BUTTONADDTOOLTIP, (WPARAM)Translate("Make the text bold (CTRL+B)"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_CHAT_ITALICS), BUTTONADDTOOLTIP, (WPARAM)Translate("Make the text italicized (CTRL+I)"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_CHAT_UNDERLINE), BUTTONADDTOOLTIP, (WPARAM)Translate("Make the text underlined (CTRL+U)"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_CHAT_BKGCOLOR), BUTTONADDTOOLTIP, (WPARAM)Translate("Select a background color for the text (CTRL+L)"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_CHAT_COLOR), BUTTONADDTOOLTIP, (WPARAM)Translate("Select a foreground color for the text (CTRL+K)"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_CHAT_HISTORY), BUTTONADDTOOLTIP, (WPARAM)Translate("Show the history (CTRL+H)"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_CHAT_SHOWNICKLIST), BUTTONADDTOOLTIP, (WPARAM)Translate("Show/hide the nicklist (CTRL+N)"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_CHAT_CHANMGR), BUTTONADDTOOLTIP, (WPARAM)Translate("Control this room (CTRL+O)"), 0);
+ SendMessage(GetDlgItem(hwndDlg,IDC_CHAT_FILTER), BUTTONADDTOOLTIP, (WPARAM)Translate("Enable/disable the event filter (CTRL+F)"), 0);
+ SendMessage(GetDlgItem(hwndDlg, IDOK), BUTTONADDTOOLTIP, (WPARAM) Translate("Send Message"), 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_BOLD, BUTTONSETASPUSHBTN, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_ITALICS, BUTTONSETASPUSHBTN, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_UNDERLINE, BUTTONSETASPUSHBTN, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_COLOR, BUTTONSETASPUSHBTN, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_BKGCOLOR, BUTTONSETASPUSHBTN, 0, 0);
+// SendDlgItemMessage(hwndDlg, IDC_CHAT_SHOWNICKLIST, BUTTONSETASPUSHBTN, 0, 0);
+// SendDlgItemMessage(hwndDlg, IDC_CHAT_FILTER, BUTTONSETASPUSHBTN, 0, 0);
+
+ if (pInfo)
+ {
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_BOLD), pInfo->bBold);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_ITALICS), pInfo->bItalics);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_UNDERLINE), pInfo->bUnderline);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_COLOR), pInfo->bColor);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_BKGCOLOR), pInfo->bBkgColor);
+ if (si->iType == GCW_CHATROOM)
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_CHANMGR), pInfo->bChanMgr);
+ }
+}
+
+
+static void MessageDialogResize(HWND hwndDlg, SESSION_INFO *si, int w, int h) {
+ int logBottom, toolbarTopY;
+ HDWP hdwp;
+ BOOL bNick = si->iType!=GCW_SERVER && si->bNicklistEnabled;
+ BOOL bToolbar = SendMessage(GetParent(hwndDlg), CM_GETTOOLBARSTATUS, 0, 0);
+ int buttonVisibility = bToolbar ? g_dat->chatBbuttonVisibility : 0;
+ int hSplitterMinTop = TOOLBAR_HEIGHT + si->windowData.minLogBoxHeight, hSplitterMinBottom = si->windowData.minEditBoxHeight;
+ int toolbarHeight = bToolbar ? IsToolbarVisible(SIZEOF(toolbarButtons), g_dat->chatBbuttonVisibility) ? TOOLBAR_HEIGHT : TOOLBAR_HEIGHT / 3 : 0;
+
+ si->iSplitterY = si->desiredInputAreaHeight + SPLITTER_HEIGHT + 3;
+
+ if (h - si->iSplitterY < hSplitterMinTop) {
+ si->iSplitterY = h - hSplitterMinTop;
+ }
+ if (si->iSplitterY < hSplitterMinBottom) {
+ si->iSplitterY = hSplitterMinBottom;
+ }
+
+ ShowToolbarControls(hwndDlg, SIZEOF(toolbarButtons), toolbarButtons, buttonVisibility, SW_SHOW);
+ ShowWindow(GetDlgItem(hwndDlg, IDC_CHAT_SPLITTERX), bNick?SW_SHOW:SW_HIDE);
+ if (si->iType != GCW_SERVER)
+ ShowWindow(GetDlgItem(hwndDlg, IDC_CHAT_LIST), si->bNicklistEnabled?SW_SHOW:SW_HIDE);
+ else
+ ShowWindow(GetDlgItem(hwndDlg, IDC_CHAT_LIST), SW_HIDE);
+
+ if (si->iType == GCW_SERVER) {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_SHOWNICKLIST), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_FILTER), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_CHANMGR), FALSE);
+ } else {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_SHOWNICKLIST), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_FILTER), TRUE);
+ if (si->iType == GCW_CHATROOM)
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_CHANMGR), MM_FindModule(si->pszModule)->bChanMgr);
+ }
+
+ hdwp = BeginDeferWindowPos(20);
+ toolbarTopY = bToolbar ? h - si->iSplitterY - toolbarHeight : h - si->iSplitterY;
+ if (si->windowData.hwndLog != NULL) {
+ logBottom = toolbarTopY / 2;
+ } else {
+ logBottom = toolbarTopY;
+ }
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_CHAT_LOG), 0, 1, 0, bNick?w - si->iSplitterX - 1:w - 2, logBottom, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_CHAT_LIST), 0, w - si->iSplitterX + 2, 0, si->iSplitterX - 3, toolbarTopY, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_CHAT_SPLITTERX), 0, w - si->iSplitterX, 1, 2, toolbarTopY - 1, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_CHAT_SPLITTERY), 0, 0, h - si->iSplitterY, w, SPLITTER_HEIGHT, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), 0, 1, h - si->iSplitterY + SPLITTER_HEIGHT, w - 2, si->iSplitterY - SPLITTER_HEIGHT - 1, SWP_NOZORDER);
+/*
+
+ toolbarTopY = h - toolbarHeight;
+ if (si->windowData.hwndLog != NULL) {
+ logBottom = (h - si->iSplitterY) / 2;
+ } else {
+ logBottom = h - si->iSplitterY;
+ }
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_CHAT_LOG), 0, 0, 0, bNick?w - si->iSplitterX:w, logBottom, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_CHAT_LIST), 0, w - si->iSplitterX + 2, 0, si->iSplitterX - 1, h - si->iSplitterY, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_CHAT_SPLITTERX), 0, w - si->iSplitterX, 1, 2, h - si->iSplitterY, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_CHAT_SPLITTERY), 0, 0, h - si->iSplitterY, w, splitterHeight, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), 0, 0, h - si->iSplitterY + splitterHeight, bSend?w-64:w, si->iSplitterY - toolbarHeight - splitterHeight, SWP_NOZORDER);
+ hdwp = DeferWindowPos(hdwp, GetDlgItem(hwndDlg, IDOK), 0, w - 64, h - si->iSplitterY + splitterHeight, 64, si->iSplitterY - toolbarHeight - splitterHeight - 1, SWP_NOZORDER);
+
+*/
+
+ hdwp = ResizeToolbar(hwndDlg, hdwp, w, toolbarTopY + 1, toolbarHeight - 1, SIZEOF(toolbarButtons), toolbarButtons, buttonVisibility);
+ EndDeferWindowPos(hdwp);
+ if (si->windowData.hwndLog != NULL) {
+ RECT rect;
+ POINT pt;
+ IEVIEWWINDOW ieWindow;
+ GetWindowRect(GetDlgItem(hwndDlg,IDC_CHAT_LOG), &rect);
+ pt.x = 0;
+ pt.y = rect.top;
+ ScreenToClient(GetDlgItem(hwndDlg,IDC_CHAT_LOG),&pt);
+ ieWindow.cbSize = sizeof(IEVIEWWINDOW);
+ ieWindow.iType = IEW_SETPOS;
+ ieWindow.parent = hwndDlg;
+ ieWindow.hwnd = si->windowData.hwndLog;
+ ieWindow.x = 0;
+ ieWindow.y = logBottom + 1;
+ ieWindow.cx = bNick ? w - si->iSplitterX:w;
+ ieWindow.cy = logBottom;
+ CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow);
+ } else {
+ RedrawWindow(GetDlgItem(hwndDlg,IDC_CHAT_LOG), NULL, NULL, RDW_INVALIDATE);
+ }
+ RedrawWindow(GetDlgItem(hwndDlg,IDC_CHAT_LIST), NULL, NULL, RDW_INVALIDATE);
+ RedrawWindow(GetDlgItem(hwndDlg,IDC_CHAT_MESSAGE), NULL, NULL, RDW_INVALIDATE);
+}
+
+
+static LRESULT CALLBACK MessageSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static int start;
+ int result;
+ MESSAGESUBDATA *dat;
+ SESSION_INFO* Parentsi;
+ CommonWindowData *windowData;
+ BOOL isShift = GetKeyState(VK_SHIFT) & 0x8000;
+ BOOL isCtrl = GetKeyState(VK_CONTROL) & 0x8000;
+ BOOL isAlt = GetKeyState(VK_MENU) & 0x8000;
+
+ Parentsi=(SESSION_INFO*)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA);
+ dat = (MESSAGESUBDATA *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ windowData = &Parentsi->windowData;
+
+ result = InputAreaShortcuts(hwnd, msg, wParam, lParam, windowData);
+ if (result != -1) {
+ return result;
+ }
+
+ switch (msg) {
+ case EM_SUBCLASSED:
+ dat = (MESSAGESUBDATA *) mir_alloc(sizeof(MESSAGESUBDATA));
+ ZeroMemory(dat, sizeof(MESSAGESUBDATA));
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) dat);
+ return 0;
+
+ case WM_MOUSEWHEEL:
+ if ((GetWindowLong(hwnd, GWL_STYLE) & WS_VSCROLL) == 0) {
+ SendMessage(GetDlgItem(GetParent(hwnd), IDC_CHAT_LOG), WM_MOUSEWHEEL, wParam, lParam);
+ }
+ dat->lastEnterTime = 0;
+ return TRUE;
+
+ case EM_REPLACESEL:
+ PostMessage(hwnd, EM_ACTIVATE, 0, 0);
+ break;
+
+ case EM_ACTIVATE:
+ SetActiveWindow(GetParent(hwnd));
+ break;
+
+ case WM_KEYDOWN:
+ {
+ if (wParam == VK_RETURN) {
+ mir_free(dat->szSearchQuery);
+ dat->szSearchQuery = NULL;
+ mir_free(dat->szSearchResult);
+ dat->szSearchResult = NULL;
+ if (( isCtrl != 0 ) ^ (0 != DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONENTER, SRMSGDEFSET_SENDONENTER))) {
+ PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+ if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONDBLENTER, SRMSGDEFSET_SENDONDBLENTER)) {
+ if (dat->lastEnterTime + 2 < time(NULL))
+ dat->lastEnterTime = time(NULL);
+ else {
+ SendMessage(hwnd, WM_KEYDOWN, VK_BACK, 0);
+ SendMessage(hwnd, WM_KEYUP, VK_BACK, 0);
+ PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0);
+ return 0;
+ } } } else {
+ dat->lastEnterTime = 0;
+ }
+
+
+ if (wParam == VK_TAB && isShift && !isCtrl) { // SHIFT-TAB (go to nick list)
+ SetFocus(GetDlgItem(GetParent(hwnd), IDC_CHAT_LIST));
+ return TRUE;
+ }
+
+ if (wParam == VK_TAB && !isCtrl && !isShift) { //tab-autocomplete
+ int iLen, end, topicStart;
+ BOOL isTopic = FALSE;
+ BOOL isRoom = FALSE;
+ TCHAR* pszText = NULL;
+ GETTEXTEX gt = {0};
+ LRESULT lResult = (LRESULT)SendMessage(hwnd, EM_GETSEL, (WPARAM)NULL, (LPARAM)NULL);
+
+ SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
+ start = LOWORD(lResult);
+ end = HIWORD(lResult);
+ SendMessage(hwnd, EM_SETSEL, end, end);
+
+ #if defined( _UNICODE )
+ gt.codepage = 1200;
+ #else
+ gt.codepage = CP_ACP;
+ #endif
+ iLen = GetRichTextLength(hwnd, gt.codepage, TRUE);
+ if (iLen >0) {
+ TCHAR *pszName = NULL;
+ pszText = mir_alloc(iLen + 100 * sizeof(TCHAR));
+ gt.cb = iLen + 99 * sizeof(TCHAR);
+ gt.flags = GT_DEFAULT;
+
+ 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 = 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) {
+ dat->szSearchQuery = mir_alloc( sizeof(TCHAR)*( end-start+1 ));
+ lstrcpyn( dat->szSearchQuery, pszText+start, end-start+1);
+ 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 = NULL;
+ if (pszName == NULL) {
+ if (end !=start) {
+ SendMessage(hwnd, EM_SETSEL, start, end);
+ SendMessage(hwnd, EM_REPLACESEL, FALSE, (LPARAM) dat->szSearchQuery);
+ }
+ mir_free(dat->szSearchQuery);
+ dat->szSearchQuery = NULL;
+ } else {
+ dat->szSearchResult = mir_tstrdup(pszName);
+ if (end !=start) {
+ if (!isRoom && !isTopic && g_Settings.AddColonToAutoComplete && start == 0) {
+ pszText = mir_alloc((_tcslen(pszName) + 4) * sizeof(TCHAR));
+ _tcscpy(pszText, pszName);
+ _tcscat(pszText, _T(": "));
+ pszName = pszText;
+ }
+ SendMessage(hwnd, EM_SETSEL, start, end);
+ SendMessage(hwnd, EM_REPLACESEL, FALSE, (LPARAM) pszName);
+ }
+ mir_free(pszText);
+ }
+ }
+
+ SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE);
+ 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 == 0x49 && isCtrl && !isAlt) { // ctrl-i (italics)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_ITALICS, IsDlgButtonChecked(GetParent(hwnd), IDC_CHAT_ITALICS) == BST_UNCHECKED?BST_CHECKED:BST_UNCHECKED);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHAT_ITALICS, 0), 0);
+ return TRUE;
+ }
+
+ if (wParam == 0x42 && isCtrl && !isAlt) { // ctrl-b (bold)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_BOLD, IsDlgButtonChecked(GetParent(hwnd), IDC_CHAT_BOLD) == BST_UNCHECKED?BST_CHECKED:BST_UNCHECKED);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHAT_BOLD, 0), 0);
+ return TRUE;
+ }
+
+ if (wParam == 0x55 && isCtrl && !isAlt) { // ctrl-u (paste clean text)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_UNDERLINE, IsDlgButtonChecked(GetParent(hwnd), IDC_CHAT_UNDERLINE) == BST_UNCHECKED?BST_CHECKED:BST_UNCHECKED);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHAT_UNDERLINE, 0), 0);
+ return TRUE;
+ }
+
+ if (wParam == 0x4b && isCtrl && !isAlt) { // ctrl-k (paste clean text)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_COLOR, IsDlgButtonChecked(GetParent(hwnd), IDC_CHAT_COLOR) == BST_UNCHECKED?BST_CHECKED:BST_UNCHECKED);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHAT_COLOR, 0), 0);
+ return TRUE;
+ }
+
+ if (wParam == VK_SPACE && isCtrl && !isAlt) { // ctrl-space (paste clean text)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_BKGCOLOR, BST_UNCHECKED);
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_COLOR, BST_UNCHECKED);
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_BOLD, BST_UNCHECKED);
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_UNDERLINE, BST_UNCHECKED);
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_ITALICS, BST_UNCHECKED);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHAT_BKGCOLOR, 0), 0);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHAT_COLOR, 0), 0);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHAT_BOLD, 0), 0);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHAT_UNDERLINE, 0), 0);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHAT_ITALICS, 0), 0);
+ return TRUE;
+ }
+
+ if (wParam == 0x4c && isCtrl && !isAlt) { // ctrl-l (paste clean text)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_BKGCOLOR, IsDlgButtonChecked(GetParent(hwnd), IDC_CHAT_BKGCOLOR) == BST_UNCHECKED?BST_CHECKED:BST_UNCHECKED);
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHAT_BKGCOLOR, 0), 0);
+ return TRUE;
+ }
+
+ if (wParam == 0x46 && isCtrl && !isAlt) { // ctrl-f (paste clean text)
+ if (IsWindowEnabled(GetDlgItem(GetParent(hwnd), IDC_CHAT_FILTER)))
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHAT_FILTER, 0), 0);
+ return TRUE;
+ }
+
+ if (wParam == 0x4e && isCtrl && !isAlt) { // ctrl-n (nicklist)
+ if (IsWindowEnabled(GetDlgItem(GetParent(hwnd), IDC_CHAT_SHOWNICKLIST)))
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHAT_SHOWNICKLIST, 0), 0);
+ return TRUE;
+ }
+
+ if (wParam == 0x48 && isCtrl && !isAlt) { // ctrl-h (history)
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHAT_HISTORY, 0), 0);
+ return TRUE;
+ }
+
+ if (wParam == 0x4f && isCtrl && !isAlt) { // ctrl-o (options)
+ if (IsWindowEnabled(GetDlgItem(GetParent(hwnd), IDC_CHAT_CHANMGR)))
+ SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(IDC_CHAT_CHANMGR, 0), 0);
+ return TRUE;
+ }
+
+ if (wParam == VK_NEXT || wParam == VK_PRIOR) {
+ HWND htemp = GetParent(hwnd);
+ SendDlgItemMessage(htemp, IDC_CHAT_LOG, msg, wParam, lParam);
+ return TRUE;
+ }
+ break;
+ }
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_KILLFOCUS:
+ dat->lastEnterTime = 0;
+ break;
+ case WM_CONTEXTMENU:
+ InputAreaContextMenu(hwnd, wParam, lParam, Parentsi->windowData.hContact);
+ return TRUE;
+
+ case WM_KEYUP:
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_MBUTTONUP:
+ {
+ CHARFORMAT2 cf;
+ UINT u = 0;
+ UINT u2 = 0;
+ COLORREF cr;
+
+ LoadMsgDlgFont(MSGFONTID_MESSAGEAREA, NULL, &cr, FALSE);
+
+ cf.cbSize = sizeof(CHARFORMAT2);
+ cf.dwMask = CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_BACKCOLOR|CFM_COLOR;
+ SendMessage(hwnd, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+
+ if (MM_FindModule(Parentsi->pszModule) && MM_FindModule(Parentsi->pszModule)->bColor) {
+ int index = GetColorIndex(Parentsi->pszModule, cf.crTextColor);
+ u = IsDlgButtonChecked(GetParent(hwnd), IDC_CHAT_COLOR);
+
+ if (index >= 0) {
+ Parentsi->bFGSet = TRUE;
+ Parentsi->iFG = index;
+ }
+
+ if (u == BST_UNCHECKED && cf.crTextColor != cr)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_COLOR, BST_CHECKED);
+ else if (u == BST_CHECKED && cf.crTextColor == cr)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_COLOR, BST_UNCHECKED);
+ }
+
+ if (MM_FindModule(Parentsi->pszModule) && MM_FindModule(Parentsi->pszModule)->bBkgColor) {
+ int index = GetColorIndex(Parentsi->pszModule, cf.crBackColor);
+ COLORREF crB = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_INPUTBKGCOLOUR, SRMSGDEFSET_INPUTBKGCOLOUR);
+ u = IsDlgButtonChecked(GetParent(hwnd), IDC_CHAT_BKGCOLOR);
+
+ if (index >= 0) {
+ Parentsi->bBGSet = TRUE;
+ Parentsi->iBG = index;
+ }
+ if (u == BST_UNCHECKED && cf.crBackColor != crB)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_BKGCOLOR, BST_CHECKED);
+ else if (u == BST_CHECKED && cf.crBackColor == crB)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_BKGCOLOR, BST_UNCHECKED);
+ }
+
+ if (MM_FindModule(Parentsi->pszModule) && MM_FindModule(Parentsi->pszModule)->bBold) {
+ u = IsDlgButtonChecked(GetParent(hwnd), IDC_CHAT_BOLD);
+ u2 = cf.dwEffects;
+ u2 &= CFE_BOLD;
+ if (u == BST_UNCHECKED && u2)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_BOLD, BST_CHECKED);
+ else if (u == BST_CHECKED && u2 == 0)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_BOLD, BST_UNCHECKED);
+ }
+
+ if (MM_FindModule(Parentsi->pszModule) && MM_FindModule(Parentsi->pszModule)->bItalics) {
+ u = IsDlgButtonChecked(GetParent(hwnd), IDC_CHAT_ITALICS);
+ u2 = cf.dwEffects;
+ u2 &= CFE_ITALIC;
+ if (u == BST_UNCHECKED && u2)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_ITALICS, BST_CHECKED);
+ else if (u == BST_CHECKED && u2 == 0)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_ITALICS, BST_UNCHECKED);
+ }
+
+ if (MM_FindModule(Parentsi->pszModule) && MM_FindModule(Parentsi->pszModule)->bUnderline) {
+ u = IsDlgButtonChecked(GetParent(hwnd), IDC_CHAT_UNDERLINE);
+ u2 = cf.dwEffects;
+ u2 &= CFE_UNDERLINE;
+ if (u == BST_UNCHECKED && u2)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_UNDERLINE, BST_CHECKED);
+ else if (u == BST_CHECKED && u2 == 0)
+ CheckDlgButton(GetParent(hwnd), IDC_CHAT_UNDERLINE, BST_UNCHECKED);
+ } }
+ break;
+
+ case EM_UNSUBCLASSED:
+ mir_free(dat->szSearchQuery);
+ mir_free(dat->szSearchResult);
+ mir_free(dat);
+ return 0;
+ }
+
+ return CallWindowProc(OldMessageProc, hwnd, msg, wParam, lParam);
+}
+
+static INT_PTR CALLBACK FilterWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ static SESSION_INFO* si = NULL;
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ si = (SESSION_INFO *)lParam;
+ CheckDlgButton(hwndDlg, IDC_CHAT_1, si->iLogFilterFlags&GC_EVENT_ACTION);
+ CheckDlgButton(hwndDlg, IDC_CHAT_2, si->iLogFilterFlags&GC_EVENT_MESSAGE);
+ CheckDlgButton(hwndDlg, IDC_CHAT_3, si->iLogFilterFlags&GC_EVENT_NICK);
+ CheckDlgButton(hwndDlg, IDC_CHAT_4, si->iLogFilterFlags&GC_EVENT_JOIN);
+ CheckDlgButton(hwndDlg, IDC_CHAT_5, si->iLogFilterFlags&GC_EVENT_PART);
+ CheckDlgButton(hwndDlg, IDC_CHAT_6, si->iLogFilterFlags&GC_EVENT_TOPIC);
+ CheckDlgButton(hwndDlg, IDC_CHAT_7, si->iLogFilterFlags&GC_EVENT_ADDSTATUS);
+ CheckDlgButton(hwndDlg, IDC_CHAT_8, si->iLogFilterFlags&GC_EVENT_INFORMATION);
+ CheckDlgButton(hwndDlg, IDC_CHAT_9, si->iLogFilterFlags&GC_EVENT_QUIT);
+ CheckDlgButton(hwndDlg, IDC_CHAT_10, si->iLogFilterFlags&GC_EVENT_KICK);
+ CheckDlgButton(hwndDlg, IDC_CHAT_11, si->iLogFilterFlags&GC_EVENT_NOTICE);
+ break;
+
+ 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_ACTIVATE:
+ if (LOWORD(wParam) == WA_INACTIVE) {
+ int iFlags = 0;
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_1) == BST_CHECKED)
+ iFlags |= GC_EVENT_ACTION;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_2) == BST_CHECKED)
+ iFlags |= GC_EVENT_MESSAGE;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_3) == BST_CHECKED)
+ iFlags |= GC_EVENT_NICK;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_4) == BST_CHECKED)
+ iFlags |= GC_EVENT_JOIN;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_5) == BST_CHECKED)
+ iFlags |= GC_EVENT_PART;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_6) == BST_CHECKED)
+ iFlags |= GC_EVENT_TOPIC;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_7) == BST_CHECKED)
+ iFlags |= GC_EVENT_ADDSTATUS;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_8) == BST_CHECKED)
+ iFlags |= GC_EVENT_INFORMATION;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_9) == BST_CHECKED)
+ iFlags |= GC_EVENT_QUIT;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_10) == BST_CHECKED)
+ iFlags |= GC_EVENT_KICK;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_11) == BST_CHECKED)
+ iFlags |= GC_EVENT_NOTICE;
+
+ if (iFlags&GC_EVENT_ADDSTATUS)
+ iFlags |= GC_EVENT_REMOVESTATUS;
+
+ SendMessage(si->hWnd, GC_CHANGEFILTERFLAG, 0, (LPARAM)iFlags);
+ if (si->bFilterEnabled)
+ SendMessage(si->hWnd, GC_REDRAWLOG, 0, 0);
+ PostMessage(hwndDlg, WM_CLOSE, 0, 0);
+ }
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+ }
+
+ return(FALSE);
+}
+
+static LRESULT CALLBACK ButtonSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_RBUTTONUP:
+ {
+ HWND hFilter = GetDlgItem(GetParent(hwnd), IDC_CHAT_FILTER);
+ HWND hColor = GetDlgItem(GetParent(hwnd), IDC_CHAT_COLOR);
+ HWND hBGColor = GetDlgItem(GetParent(hwnd), IDC_CHAT_BKGCOLOR);
+
+ if (DBGetContactSettingByte(NULL, "Chat", "RightClickFilter", 0) != 0) {
+ if (hFilter == hwnd)
+ SendMessage(GetParent(hwnd), GC_SHOWFILTERMENU, 0, 0);
+ if (hColor == hwnd)
+ SendMessage(GetParent(hwnd), GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_CHAT_COLOR);
+ if (hBGColor == hwnd)
+ SendMessage(GetParent(hwnd), GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_CHAT_BKGCOLOR);
+ } }
+ break;
+ }
+
+ return CallWindowProc(OldFilterButtonProc, hwnd, msg, wParam, lParam);
+}
+
+static LRESULT CALLBACK LogSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static BOOL inMenu = FALSE;
+ SESSION_INFO* si =(SESSION_INFO*)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA);
+ int result = InputAreaShortcuts(hwnd, msg, wParam, lParam, &si->windowData);
+ if (result != -1) {
+ return result;
+ }
+ switch (msg) {
+ case WM_MEASUREITEM:
+ MeasureMenuItem(wParam, lParam);
+ return TRUE;
+ case WM_DRAWITEM:
+ return DrawMenuItem(wParam, lParam);
+ case WM_SETCURSOR:
+ if (inMenu) {
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ return TRUE;
+ }
+ break;
+ case WM_LBUTTONUP:
+ {
+ CHARRANGE sel;
+
+ SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM) &sel);
+ if (sel.cpMin != sel.cpMax)
+ {
+ SendMessage(hwnd, WM_COPY, 0, 0);
+ sel.cpMin = sel.cpMax ;
+ SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM) & sel);
+ }
+ SetFocus(GetDlgItem(GetParent(hwnd), IDC_CHAT_MESSAGE));
+ 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_CONTEXTMENU:
+ {
+ CHARRANGE sel, all = { 0, -1 };
+ POINT pt;
+ UINT uID = 0;
+ HMENU hMenu = 0;
+ TCHAR *pszWord = NULL;
+ POINTL ptl;
+
+ SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM) & sel);
+ if (lParam == 0xFFFFFFFF) {
+ SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM) & pt, (LPARAM) sel.cpMax);
+ ClientToScreen(hwnd, &pt);
+ } else {
+ pt.x = (short) LOWORD(lParam);
+ pt.y = (short) HIWORD(lParam);
+ }
+ ptl.x = (LONG)pt.x;
+ ptl.y = (LONG)pt.y;
+ ScreenToClient(hwnd, (LPPOINT)&ptl);
+ pszWord = GetRichTextWord(hwnd, &ptl);
+ inMenu = TRUE;
+ uID = CreateGCMenu(hwnd, &hMenu, 1, pt, si, NULL, pszWord);
+ inMenu = FALSE;
+ switch (uID) {
+ case 0:
+ PostMessage(GetParent(hwnd), WM_MOUSEACTIVATE, 0, 0 );
+ break;
+
+ case ID_COPYALL:
+ SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM) & sel);
+ SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM) & all);
+ SendMessage(hwnd, WM_COPY, 0, 0);
+ SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM) & sel);
+ PostMessage(GetParent(hwnd), WM_MOUSEACTIVATE, 0, 0 );
+ break;
+
+ case IDM_CLEAR:
+ if (si)
+ {
+ SetWindowText(hwnd, _T(""));
+ LM_RemoveAll(&si->pLog, &si->pLogEnd);
+ si->iEventCount = 0;
+ si->LastTime = 0;
+ PostMessage(GetParent(hwnd), WM_MOUSEACTIVATE, 0, 0 );
+ }
+ break;
+
+ case IDM_SEARCH_GOOGLE:
+ case IDM_SEARCH_BING:
+ case IDM_SEARCH_YAHOO:
+ case IDM_SEARCH_WIKIPEDIA:
+ case IDM_SEARCH_FOODNETWORK:
+ case IDM_SEARCH_GOOGLE_MAPS:
+ case IDM_SEARCH_GOOGLE_TRANSLATE:
+ SearchWord(pszWord, uID - IDM_SEARCH_GOOGLE + SEARCHENGINE_GOOGLE);
+ PostMessage(GetParent(hwnd), WM_MOUSEACTIVATE, 0, 0 );
+ break;
+ default:
+ PostMessage(GetParent(hwnd), WM_MOUSEACTIVATE, 0, 0 );
+ DoEventHookAsync(GetParent(hwnd), si->ptszID, si->pszModule, GC_USER_LOGMENU, NULL, NULL, (LPARAM)uID);
+ break;
+ }
+ DestroyGCMenu(&hMenu, 5);
+ mir_free(pszWord);
+ break;
+ }
+ case WM_CHAR:
+ SetFocus(GetDlgItem(GetParent(hwnd), IDC_CHAT_MESSAGE));
+ SendMessage(GetDlgItem(GetParent(hwnd), IDC_CHAT_MESSAGE), WM_CHAR, wParam, lParam);
+ break;
+ }
+
+ return CallWindowProc(OldLogProc, hwnd, msg, wParam, lParam);
+}
+
+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 );
+ //SetWindowPos(hwndToolTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ 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) {
+ // /GetChatToolTipText
+ // wParam = roomID parentdat->ptszID
+ // lParam = userID ui1->pszUID
+ 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);
+ }
+}
+
+static LRESULT CALLBACK NicklistSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ SESSION_INFO* si =(SESSION_INFO*)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA);
+ int result = InputAreaShortcuts(hwnd, msg, wParam, lParam, &si->windowData);
+ if (result != -1) {
+ return result;
+ }
+ switch (msg) {
+ case WM_ERASEBKGND:
+ {
+ HDC dc = (HDC)wParam;
+ if (dc) {
+ int height, index, items = 0;
+
+ index = SendMessage(hwnd, LB_GETTOPINDEX, 0, 0);
+ if (index == LB_ERR || si->nUsersInNicklist <= 0)
+ return 0;
+
+ items = si->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;
+
+ case WM_RBUTTONDOWN:
+ 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;
+ DWORD item;
+ int height=0;
+ USERINFO * ui;
+
+ 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(si->ptszID, si->pszModule, (int)item);
+ 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, si, uinew.pszUID, NULL);
+
+ switch (uID) {
+ case 0:
+ break;
+
+ case ID_MESS:
+ DoEventHookAsync(GetParent(hwnd), si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui->pszUID, NULL, (LPARAM)NULL);
+ break;
+
+ default:
+ DoEventHookAsync(GetParent(hwnd), si->ptszID, si->pszModule, GC_USER_NICKLISTMENU, ui->pszUID, NULL, (LPARAM)uID);
+ break;
+ }
+ DestroyGCMenu(&hMenu, 1);
+ return TRUE;
+ } }
+ break;
+
+ case WM_GETDLGCODE :
+ {
+ BOOL isAlt = GetKeyState(VK_MENU) & 0x8000;
+ BOOL isCtrl = (GetKeyState(VK_CONTROL) & 0x8000) && !isAlt;
+
+ LPMSG lpmsg;
+ if ( ( lpmsg = (LPMSG)lParam ) != NULL ) {
+ if ( lpmsg->message == WM_KEYDOWN
+ && (lpmsg->wParam == VK_RETURN || lpmsg->wParam == VK_ESCAPE || (lpmsg->wParam == VK_TAB && (isAlt || isCtrl))))
+ return DLGC_WANTALLKEYS;
+ }
+ break;
+ }
+ case WM_KEYDOWN:
+ if (wParam == VK_RETURN) {
+ int index = SendMessage(hwnd, LB_GETCURSEL, 0, 0);
+ if (index!=LB_ERR) {
+ USERINFO *ui = SM_GetUserFromIndex(si->ptszID, si->pszModule, index);
+ DoEventHookAsync(GetParent(hwnd), si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui->pszUID, NULL, (LPARAM)NULL);
+ }
+ break;
+ }
+ 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) {
+ si->szSearch[0] = 0;
+ }
+ 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 (wParam == 27 && si->szSearch[0]) { // escape - reset everything
+ si->szSearch[0] = 0;
+ 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
+ */
+ char *str = t2a(si->szSearch);
+ mir_free(str);
+ 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_SETCURSEL, i, 0);
+ InvalidateRect(hwnd, NULL, FALSE);
+ return 0;
+ }
+ }
+ }
+ if (i == iItems) {
+ MessageBeep(MB_OK);
+ si->szSearch[lstrlen(si->szSearch) - 1] = '\0';
+ }
+ return 0;
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ {
+ POINT pt;
+ RECT clientRect;
+ BOOL bInClient;
+ pt.x=LOWORD(lParam);
+ pt.y=HIWORD(lParam);
+ GetClientRect(hwnd,&clientRect);
+ bInClient=PtInRect(&clientRect, pt);
+ //Mouse capturing/releasing
+ if ( bInClient && GetCapture()!=hwnd)
+ SetCapture(hwnd);
+ else if (!bInClient)
+ ReleaseCapture();
+
+ if (bInClient) {
+ //hit test item under mouse
+ DWORD nItemUnderMouse=(DWORD)SendMessage(hwnd, LB_ITEMFROMPOINT, 0, lParam);
+ if ( HIWORD( nItemUnderMouse ) == 1 )
+ nItemUnderMouse = (DWORD)(-1);
+ else
+ nItemUnderMouse &= 0xFFFF;
+
+ ProcessNickListHovering(hwnd, (int)nItemUnderMouse, &pt, si);
+ } else {
+ ProcessNickListHovering(hwnd, -1, &pt, NULL);
+ } }
+ break;
+ }
+
+ return CallWindowProc(OldNicklistProc, hwnd, msg, wParam, lParam);
+}
+
+
+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 = 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);
+}
+
+INT_PTR CALLBACK RoomWndProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ static HMENU hToolbarMenu;
+ SESSION_INFO * si;
+ si = (SESSION_INFO *)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
+ if (!si && uMsg!=WM_INITDIALOG) return FALSE;
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ {
+ SESSION_INFO* psi = (SESSION_INFO*)lParam;
+ int mask;
+ RECT minEditInit;
+ HWND hNickList = GetDlgItem(hwndDlg,IDC_CHAT_LIST);
+ NotifyLocalWinEvent(psi->windowData.hContact, hwndDlg, MSG_WINDOW_EVT_OPENING);
+
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg,GWLP_USERDATA,(LONG_PTR)psi);
+ si = psi;
+ RichUtil_SubClass(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ RichUtil_SubClass(GetDlgItem(hwndDlg, IDC_CHAT_LOG));
+ RichUtil_SubClass(GetDlgItem(hwndDlg, IDC_CHAT_LIST));
+ OldSplitterProc=(WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_CHAT_SPLITTERX),GWLP_WNDPROC,(LONG_PTR)SplitterSubclassProc);
+ OldNicklistProc=(WNDPROC)SetWindowLongPtr(hNickList,GWLP_WNDPROC,(LONG_PTR)NicklistSubclassProc);
+ OldLogProc=(WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_CHAT_LOG),GWLP_WNDPROC,(LONG_PTR)LogSubclassProc);
+ OldFilterButtonProc=(WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_CHAT_FILTER),GWLP_WNDPROC,(LONG_PTR)ButtonSubclassProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_CHAT_COLOR),GWLP_WNDPROC,(LONG_PTR)ButtonSubclassProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_CHAT_BKGCOLOR),GWLP_WNDPROC,(LONG_PTR)ButtonSubclassProc);
+ OldMessageProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), GWLP_WNDPROC,(LONG_PTR)MessageSubclassProc);
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), &minEditInit);
+ si->windowData.minEditBoxHeight = minEditInit.bottom - minEditInit.top;
+ si->windowData.minLogBoxHeight = si->windowData.minEditBoxHeight;
+
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SUBCLASSED, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_AUTOURLDETECT, 1, 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);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_KEYEVENTS | ENM_CHANGE | ENM_REQUESTRESIZE);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_LIMITTEXT, (WPARAM)sizeof(TCHAR)*0x7FFFFFFF, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_SETOLECALLBACK, 0, (LPARAM) & reOleCallback);
+
+ if (DBGetContactSettingByte(NULL, "Chat", "UseIEView", 0)) {
+ IEVIEWWINDOW ieWindow;
+ IEVIEWEVENT iee;
+
+ ZeroMemory(&ieWindow, sizeof(ieWindow));
+ ieWindow.cbSize = sizeof(ieWindow);
+ ieWindow.iType = IEW_CREATE;
+ ieWindow.dwFlags = 0;
+ ieWindow.dwMode = IEWM_CHAT;
+ ieWindow.parent = hwndDlg;
+ ieWindow.x = 0;
+ ieWindow.y = 0;
+ ieWindow.cx = 200;
+ ieWindow.cy = 300;
+ CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow);
+ si->windowData.hwndLog = ieWindow.hwnd;
+ ZeroMemory(&iee, sizeof(iee));
+ iee.cbSize = sizeof(iee);
+ iee.iType = IEE_CLEAR_LOG;
+ iee.hwnd = si->windowData.hwndLog;
+ iee.hContact = si->windowData.hContact;
+ iee.codepage = si->windowData.codePage;
+ iee.pszProto = si->pszModule;
+ CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&iee);
+ }
+
+ EnableWindow(GetDlgItem(hwndDlg, IDC_CHAT_SMILEY), TRUE);
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_HIDESELECTION, TRUE, 0);
+
+ SendMessage(hwndDlg, GC_SETWNDPROPS, 0, 0);
+ SendMessage(hwndDlg, DM_UPDATESTATUSBAR, 0, 0);
+ SendMessage(hwndDlg, DM_UPDATETITLEBAR, 0, 0);
+
+ SendMessage(GetParent(hwndDlg), CM_ADDCHILD, (WPARAM) hwndDlg, (LPARAM) psi->windowData.hContact);
+ PostMessage(hwndDlg, GC_UPDATENICKLIST, 0, 0);
+ NotifyLocalWinEvent(psi->windowData.hContact, hwndDlg, MSG_WINDOW_EVT_OPEN);
+ }
+ break;
+
+ case GC_SETWNDPROPS:
+ {
+ LoadGlobalSettings();
+ InitButtons(hwndDlg, si);
+
+ SendMessage(hwndDlg, DM_UPDATESTATUSBAR, 0, 0);
+ SendMessage(hwndDlg, DM_UPDATETITLEBAR, 0, 0);
+ SendMessage(hwndDlg, GC_FIXTABICONS, 0, 0);
+
+ { // log
+ //int iIndent = 0;
+ //PARAFORMAT2 pf2;
+ //if (g_Settings.dwIconFlags)
+ // iIndent += (14*1440)/g_dat->logPixelSX;
+ //if (g_Settings.ShowTime && g_Settings.LogIndentEnabled)
+ // iIndent += g_Settings.LogTextIndent*1440/g_dat->logPixelSX;
+ //pf2.cbSize = sizeof(pf2);
+ //pf2.dwMask = PFM_OFFSET;
+ //pf2.dxOffset = iIndent * 1440 / g_dat->logPixelSX;
+ //SendDlgItemMessage(hwndDlg, IDC_CHAT_LOG, EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_SETBKGNDCOLOR , 0, g_Settings.crLogBackground);
+ }
+
+ { //messagebox
+ COLORREF crFore;
+
+ CHARFORMAT2 cf;
+ LoadMsgDlgFont(MSGFONTID_MESSAGEAREA, NULL, &crFore, FALSE);
+ cf.cbSize = sizeof(CHARFORMAT2);
+ cf.dwMask = CFM_COLOR|CFM_BOLD|CFM_UNDERLINE|CFM_BACKCOLOR;
+ cf.dwEffects = 0;
+ cf.crTextColor = crFore;
+ cf.crBackColor = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_INPUTBKGCOLOUR, SRMSGDEFSET_INPUTBKGCOLOUR);
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), EM_SETBKGNDCOLOR , 0, DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_INPUTBKGCOLOUR, SRMSGDEFSET_INPUTBKGCOLOUR));
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, WM_SETFONT, (WPARAM) g_Settings.MessageBoxFont, MAKELPARAM(TRUE, 0));
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, (WPARAM)SCF_ALL , (LPARAM)&cf);
+ }
+ { // nicklist
+ int ih;
+ int ih2;
+ int font;
+ int height;
+
+ ih = GetTextPixelSize( _T("AQG_glo'"), g_Settings.UserListFont,FALSE);
+ ih2 = GetTextPixelSize( _T("AQG_glo'"), g_Settings.UserListHeadingsFont,FALSE);
+ height = DBGetContactSettingByte(NULL, "Chat", "NicklistRowDist", 12);
+ font = ih > ih2?ih:ih2;
+ // make sure we have space for icon!
+ if (DBGetContactSettingByte(NULL, "Chat", "ShowContactStatus", 0))
+ font = font > 16 ? font : 16;
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LIST), LB_SETITEMHEIGHT, 0, (LPARAM)height > font ? height : font);
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_CHAT_LIST), NULL, TRUE);
+ }
+ SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_REQUESTRESIZE, 0, 0);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ SendMessage(hwndDlg, GC_REDRAWLOG2, 0, 0);
+ }
+ break;
+
+ case DM_UPDATETITLEBAR:
+ {
+ TitleBarData tbd = {0};
+ TCHAR szTemp [100];
+ if (g_dat->flags & SMF_STATUSICON) {
+ MODULEINFO* mi = MM_FindModule(si->pszModule);
+ tbd.hIcon = (si->wStatus == ID_STATUS_ONLINE) ? mi->hOnlineIcon : mi->hOfflineIcon;
+ tbd.hIconBig = (si->wStatus == ID_STATUS_ONLINE) ? mi->hOnlineIconBig : mi->hOfflineIconBig;
+ }
+ else {
+ tbd.hIcon = GetCachedIcon("chat_window");
+ tbd.hIconBig = g_dat->hIconChatBig;
+ }
+ tbd.hIconNot = (si->wState & (GC_EVENT_HIGHLIGHT | STATE_TALK)) ? GetCachedIcon("chat_overlay") : NULL;
+
+ switch(si->iType) {
+ case GCW_CHATROOM:
+ mir_sntprintf(szTemp, SIZEOF(szTemp),
+ (si->nUsersInNicklist == 1) ? TranslateT("%s: Chat Room (%u user)") : TranslateT("%s: Chat Room (%u users)"),
+ si->ptszName, si->nUsersInNicklist);
+ 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);
+ break;
+ }
+ tbd.iFlags = TBDF_TEXT | TBDF_ICON;
+ tbd.pszText = szTemp;
+ SendMessage(GetParent(hwndDlg), CM_UPDATETITLEBAR, (WPARAM) &tbd, (LPARAM) hwndDlg);
+ SendMessage(hwndDlg, DM_UPDATETABCONTROL, 0, 0);
+ }
+ break;
+
+ case DM_UPDATESTATUSBAR:
+ {
+ StatusIconData sid;
+ StatusBarData sbd;
+ HICON hIcon;
+ MODULEINFO* mi = MM_FindModule(si->pszModule);
+ TCHAR szTemp[512];
+ hIcon = si->wStatus==ID_STATUS_ONLINE ? mi->hOnlineIcon : mi->hOfflineIcon;
+ mir_sntprintf(szTemp, SIZEOF(szTemp), _T("%s : %s"), mi->ptszModDispName, si->ptszStatusbarText ? si->ptszStatusbarText : _T(""));
+ sbd.iItem = 0;
+ sbd.iFlags = SBDF_TEXT | SBDF_ICON;
+ sbd.hIcon = hIcon;
+ sbd.pszText = szTemp;
+ SendMessage(GetParent(hwndDlg), CM_UPDATESTATUSBAR, (WPARAM) &sbd, (LPARAM) hwndDlg);
+ sbd.iItem = 1;
+ sbd.hIcon = NULL;
+ sbd.pszText = _T("");
+ SendMessage(GetParent(hwndDlg), CM_UPDATESTATUSBAR, (WPARAM) &sbd, (LPARAM) hwndDlg);
+ sid.cbSize = sizeof(sid);
+ sid.szModule = SRMMMOD;
+ sid.dwId = 0;
+ #if defined( _UNICODE )
+ sid.flags = 0;
+ #else
+ sid.flags = MBF_DISABLED;
+ #endif
+ ModifyStatusIcon((WPARAM)si->windowData.hContact, (LPARAM) &sid);
+ // SendMessage(hwndDlg, GC_FIXTABICONS, 0, (LPARAM)si);
+ }
+ break;
+ case DM_GETCODEPAGE:
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, si->windowData.codePage);
+ return TRUE;
+ case DM_SETCODEPAGE:
+ si->windowData.codePage = (int) lParam;
+ si->pszHeader = Log_CreateRtfHeader(MM_FindModule(si->pszModule), si);
+ SendMessage(hwndDlg, GC_REDRAWLOG2, 0, 0);
+ break;
+ case DM_SWITCHINFOBAR:
+ case DM_SWITCHTOOLBAR:
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ break;
+ case WM_SIZE:
+ {
+
+ if (wParam == SIZE_MAXIMIZED)
+ PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0);
+
+ if (IsIconic(hwndDlg)) break;
+
+ if (wParam==SIZE_RESTORED || wParam==SIZE_MAXIMIZED) {
+ int dlgWidth, dlgHeight;
+ RECT rc;
+ dlgWidth = LOWORD(lParam);
+ dlgHeight = HIWORD(lParam);
+ /*if (dlgWidth == 0 && dlgHeight ==0) */{
+ GetClientRect(hwndDlg, &rc);
+ dlgWidth = rc.right - rc.left;
+ dlgHeight = rc.bottom - rc.top;
+ }
+
+ MessageDialogResize(hwndDlg, si, dlgWidth, dlgHeight);
+
+ }
+ }
+ 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);
+ mir_forkthread(phase2, si);
+ }
+ else Log_StreamInEvent(hwndDlg, si->pLogEnd, si, TRUE);
+ }
+ 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);
+ break;
+
+ case GC_REDRAWLOG3:
+ si->LastTime = 0;
+ if (si->pLog)
+ Log_StreamInEvent(hwndDlg, si->pLogEnd, si, TRUE);
+ break;
+
+ case GC_ADDLOG:
+ if (si->pLogEnd)
+ Log_StreamInEvent(hwndDlg, si->pLog, si, FALSE);
+ else
+ SendMessage(hwndDlg, GC_EVENT_CONTROL + WM_USER+500, WINDOW_CLEARLOG, 0);
+ break;
+
+
+ case DM_UPDATETABCONTROL:
+ {
+ TabControlData tcd;
+ tcd.iFlags = TCDF_TEXT;
+ tcd.pszText = si->ptszName;
+ SendMessage(GetParent(hwndDlg), CM_UPDATETABCONTROL, (WPARAM) &tcd, (LPARAM) hwndDlg);
+
+ }
+ case GC_FIXTABICONS:
+ {
+ TabControlData tcd;
+ HICON hIcon;
+ if (!(si->wState & GC_EVENT_HIGHLIGHT))
+ {
+ if (si->wState & STATE_TALK)
+ hIcon = (si->wStatus==ID_STATUS_ONLINE) ? MM_FindModule(si->pszModule)->hOnlineTalkIcon : MM_FindModule(si->pszModule)->hOfflineTalkIcon;
+ else
+ hIcon = (si->wStatus==ID_STATUS_ONLINE) ? MM_FindModule(si->pszModule)->hOnlineIcon : MM_FindModule(si->pszModule)->hOfflineIcon;
+ } else {
+ hIcon = g_dat->hMsgIcon;
+ }
+ tcd.iFlags = TCDF_ICON;
+ tcd.hIcon = hIcon;
+ SendMessage(GetParent(hwndDlg), CM_UPDATETABCONTROL, (WPARAM) &tcd, (LPARAM) hwndDlg);
+ }
+ break;
+
+ case GC_SETMESSAGEHIGHLIGHT:
+ {
+ si->wState |= GC_EVENT_HIGHLIGHT;
+ SendMessage(si->hWnd, GC_FIXTABICONS, 0, 0);
+ SendMessage(hwndDlg, DM_UPDATETITLEBAR, 0, 0);
+ if (DBGetContactSettingByte(NULL, "Chat", "FlashWindowHighlight", 0) != 0 && GetActiveWindow() != hwndDlg && GetForegroundWindow() != GetParent(hwndDlg))
+ SendMessage(GetParent(si->hWnd), CM_STARTFLASHING, 0, 0);
+ }
+ break;
+
+ case GC_SETTABHIGHLIGHT:
+ {
+ SendMessage(si->hWnd, GC_FIXTABICONS, 0, 0);
+ SendMessage(hwndDlg, DM_UPDATETITLEBAR, 0, 0);
+ if (g_Settings.FlashWindow && GetActiveWindow() != GetParent(hwndDlg) && GetForegroundWindow() != GetParent(hwndDlg))
+ SendMessage(GetParent(si->hWnd), CM_STARTFLASHING, 0, 0);
+ }
+ break;
+
+ case DM_ACTIVATE:
+ {
+ if (si->wState & STATE_TALK) {
+ si->wState &= ~STATE_TALK;
+
+ DBWriteContactSettingWord(si->windowData.hContact, si->pszModule ,"ApparentMode",(LPARAM) 0);
+ }
+
+ if (si->wState & GC_EVENT_HIGHLIGHT) {
+ si->wState &= ~GC_EVENT_HIGHLIGHT;
+
+ if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->windowData.hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->windowData.hContact, (LPARAM)"chaticon");
+ }
+
+ SendMessage(hwndDlg, GC_FIXTABICONS, 0, 0);
+ if (!si->hWnd) {
+ ShowRoom(si, (WPARAM)WINDOW_VISIBLE, TRUE);
+ SendMessage(hwndDlg, WM_MOUSEACTIVATE, 0, 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:
+ if (!MeasureMenuItem(wParam, lParam)) {
+ MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *) lParam;
+
+ if (mis->CtlType == ODT_MENU)
+ {
+ return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam);
+ } else
+ {
+ int ih = GetTextPixelSize( _T("AQGgl'"), g_Settings.UserListFont,FALSE);
+ int ih2 = GetTextPixelSize( _T("AQGg'"), g_Settings.UserListHeadingsFont,FALSE);
+ int font = ih > ih2?ih:ih2;
+ int height = DBGetContactSettingByte(NULL, "Chat", "NicklistRowDist", 12);
+ // make sure we have space for icon!
+ if (DBGetContactSettingByte(NULL, "Chat", "ShowContactStatus", 0))
+ font = font > 16 ? font : 16;
+ mis->itemHeight = height > font?height:font;
+ }
+
+ return TRUE;
+ }
+
+ case WM_DRAWITEM:
+ if (!DrawMenuItem(wParam, lParam)) {
+ DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *) lParam;
+ if (dis->CtlType == ODT_MENU) {
+ return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam);
+ } else
+ if (dis->CtlID == IDC_CHAT_LIST) {
+ HFONT hFont, hOldFont;
+ HICON hIcon;
+ int offset;
+ int height;
+ int index = dis->itemID;
+ USERINFO * ui = SM_GetUserFromIndex(si->ptszID, si->pszModule, index);
+ if (ui) {
+ int x_offset = 2;
+
+ height = dis->rcItem.bottom - dis->rcItem.top;
+
+ if (height&1)
+ height++;
+ if (height == 10)
+ offset = 0;
+ else
+ offset = height/2 - 5;
+ hIcon = SM_GetStatusIcon(si, ui);
+ hFont = (ui->iStatusEx == 0) ? g_Settings.UserListFont : g_Settings.UserListHeadingsFont;
+ hOldFont = (HFONT) SelectObject(dis->hDC, hFont);
+ SetBkMode(dis->hDC, TRANSPARENT);
+
+ if (dis->itemAction == ODA_FOCUS && dis->itemState & ODS_SELECTED)
+ FillRect(dis->hDC, &dis->rcItem, hListSelectedBkgBrush);
+ else //if (dis->itemState & ODS_INACTIVE)
+ FillRect(dis->hDC, &dis->rcItem, hListBkgBrush);
+
+ 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-3,hIcon,16,16,0,NULL, DI_NORMAL);
+ CallService(MS_SKIN2_RELEASEICON,(WPARAM)hIcon, 0);
+ x_offset += 18;
+ }
+ DrawIconEx(dis->hDC,x_offset, dis->rcItem.top + offset,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-3,hIcon,16,16,0,NULL, DI_NORMAL);
+ CallService(MS_SKIN2_RELEASEICON,(WPARAM)hIcon, 0);
+ x_offset += 18;
+ }
+
+ SetTextColor(dis->hDC, ui->iStatusEx == 0?g_Settings.crUserListColor:g_Settings.crUserListHeadingsColor);
+ TextOut(dis->hDC, dis->rcItem.left+x_offset, dis->rcItem.top, ui->pszNick, lstrlen(ui->pszNick));
+ SelectObject(dis->hDC, hOldFont);
+ }
+ return TRUE;
+ } }
+
+ case GC_UPDATENICKLIST:
+ {
+ int index=0;
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LIST, WM_SETREDRAW, FALSE, 0);
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LIST), LB_RESETCONTENT, 0, 0);
+ for (index=0; index<si->nUsersInNicklist; index++) {
+ USERINFO * ui = SM_GetUserFromIndex(si->ptszID, si->pszModule, index);
+ if (ui) {
+ char szIndicator = SM_GetStatusIndicator(si, ui);
+ if (szIndicator>'\0') {
+ static TCHAR ptszBuf[128];
+ mir_sntprintf( ptszBuf, SIZEOF(ptszBuf), _T("%c%s"), szIndicator, ui->pszNick);
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LIST), LB_ADDSTRING, 0, (LPARAM)ptszBuf);
+ } else {
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LIST), LB_ADDSTRING, 0, (LPARAM)ui->pszNick);
+ }
+ }
+ }
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_LIST, WM_SETREDRAW, TRUE, 0);
+ InvalidateRect(GetDlgItem(hwndDlg, IDC_CHAT_LIST), NULL, FALSE) ;
+ UpdateWindow(GetDlgItem(hwndDlg, IDC_CHAT_LIST)) ;
+ SendMessage(hwndDlg, DM_UPDATETITLEBAR, 0, 0);
+ }
+ break;
+
+ case GC_EVENT_CONTROL + WM_USER+500:
+ {
+ switch(wParam) {
+ case SESSION_OFFLINE:
+ SendMessage(hwndDlg, DM_UPDATESTATUSBAR, 0, 0);
+ SendMessage(si->hWnd, GC_UPDATENICKLIST, (WPARAM)0, (LPARAM)0);
+ return TRUE;
+
+ case SESSION_ONLINE:
+ SendMessage(hwndDlg, DM_UPDATESTATUSBAR, 0, 0);
+ return TRUE;
+
+ case WINDOW_HIDDEN:
+ SendMessage(hwndDlg, GC_CLOSEWINDOW, 0, 0);
+ return TRUE;
+
+ case WINDOW_CLEARLOG:
+ SetDlgItemText(hwndDlg, IDC_CHAT_LOG, _T(""));
+ return TRUE;
+
+ case SESSION_TERMINATE:
+ if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->windowData.hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->windowData.hContact, (LPARAM)"chaticon");
+ si->wState &= ~STATE_TALK;
+ DBWriteContactSettingWord(si->windowData.hContact, si->pszModule ,"ApparentMode",(LPARAM) 0);
+ SendMessage(hwndDlg, GC_CLOSEWINDOW, 0, 0);
+ 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 (DBGetContactSettingByte(NULL, "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, DM_UPDATESTATUSBAR, 0, 0);
+ ShowWindow(hwndDlg, SW_SHOW);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ SetForegroundWindow(hwndDlg);
+ return TRUE;
+ } }
+ break;
+
+ case GC_SPLITTERMOVED:
+ if ((HWND)lParam==GetDlgItem(hwndDlg,IDC_CHAT_SPLITTERX)) {
+ POINT pt;
+ RECT rc;
+ 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;
+ }
+ else if ((HWND)lParam==GetDlgItem(hwndDlg,IDC_CHAT_SPLITTERY)) {
+ POINT pt;
+ RECT rc;
+ int oldSplitterY;
+ GetClientRect(hwndDlg,&rc);
+ pt.x=0; pt.y=wParam;
+ ScreenToClient(hwndDlg,&pt);
+ oldSplitterY=si->iSplitterY;
+ si->iSplitterY=rc.bottom-pt.y;
+ g_Settings.iSplitterY = si->iSplitterY;
+ }
+ PostMessage(hwndDlg,WM_SIZE,0,0);
+ 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:
+ si->iLogFilterFlags = lParam;
+ break;
+
+ case GC_SHOWFILTERMENU:
+ {
+ RECT rc;
+ HWND hwnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_FILTER), hwndDlg, FilterWndProc, (LPARAM)si);
+ TranslateDialogDefault(hwnd);
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_CHAT_FILTER), &rc);
+ SetWindowPos(hwnd, HWND_TOP, rc.left-85, (IsWindowVisible(GetDlgItem(hwndDlg, IDC_CHAT_FILTER))||IsWindowVisible(GetDlgItem(hwndDlg, IDC_CHAT_BOLD)))?rc.top-206:rc.top-186, 0, 0, SWP_NOSIZE|SWP_SHOWWINDOW);
+ }
+ break;
+
+ case GC_SHOWCOLORCHOOSER:
+ {
+ HWND ColorWindow;
+ RECT rc;
+ BOOL bFG = lParam == IDC_CHAT_COLOR?TRUE:FALSE;
+ COLORCHOOSER * pCC = mir_alloc(sizeof(COLORCHOOSER));
+
+ GetWindowRect(GetDlgItem(hwndDlg, bFG?IDC_CHAT_COLOR:IDC_CHAT_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_CHAT_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:
+ {
+ SCROLLINFO si = { 0 };
+ if ((GetWindowLong(GetDlgItem(hwndDlg, IDC_CHAT_LOG), GWL_STYLE) & WS_VSCROLL) != 0){
+ CHARRANGE sel;
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_PAGE | SIF_RANGE;
+ GetScrollInfo(GetDlgItem(hwndDlg, IDC_CHAT_LOG), SB_VERT, &si);
+ si.fMask = SIF_POS;
+ si.nPos = si.nMax - si.nPage + 1;
+ SetScrollInfo(GetDlgItem(hwndDlg, IDC_CHAT_LOG), SB_VERT, &si, TRUE);
+ sel.cpMin = sel.cpMax = GetRichTextLength(GetDlgItem(hwndDlg, IDC_CHAT_LOG), CP_ACP, FALSE);
+ SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), EM_EXSETSEL, 0, (LPARAM) & sel);
+ PostMessage(GetDlgItem(hwndDlg, IDC_CHAT_LOG), WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, 0), 0);
+ } }
+ break;
+
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) != WA_ACTIVE)
+ break;
+
+ //fall through
+ case WM_MOUSEACTIVATE:
+ {
+ if (uMsg != WM_ACTIVATE)
+ SetFocus(GetDlgItem(hwndDlg,IDC_CHAT_MESSAGE));
+
+ SetActiveSession(si->ptszID, si->pszModule);
+
+ if (DBGetContactSettingWord(si->windowData.hContact, si->pszModule ,"ApparentMode", 0) != 0)
+ DBWriteContactSettingWord(si->windowData.hContact, si->pszModule ,"ApparentMode",(LPARAM) 0);
+ if (CallService(MS_CLIST_GETEVENT, (WPARAM)si->windowData.hContact, (LPARAM)0))
+ CallService(MS_CLIST_REMOVEEVENT, (WPARAM)si->windowData.hContact, (LPARAM)"chaticon");
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR pNmhdr;
+
+ pNmhdr = (LPNMHDR)lParam;
+ switch (pNmhdr->code) {
+ case EN_REQUESTRESIZE:
+ if (pNmhdr->idFrom == IDC_CHAT_MESSAGE) {
+ REQRESIZE *rr = (REQRESIZE *)lParam;
+ int height = rr->rc.bottom - rr->rc.top + 1;
+ if (height < g_dat->minInputAreaHeight) {
+ height = g_dat->minInputAreaHeight;
+ }
+ if (si->desiredInputAreaHeight != height) {
+ si->desiredInputAreaHeight = height;
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0);
+ }
+ }
+ break;
+ case EN_MSGFILTER:
+ if (pNmhdr->idFrom == IDC_CHAT_LOG && ((MSGFILTER *) lParam)->msg == WM_RBUTTONUP){
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ break;
+ case EN_LINK:
+ if (pNmhdr->idFrom == IDC_CHAT_LOG) {
+ switch (((ENLINK *) lParam)->msg) {
+ case WM_RBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_LBUTTONDBLCLK:
+ if (HandleLinkClick(g_hInst, hwndDlg, GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE),(ENLINK*)lParam)) {
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
+ return TRUE;
+ }
+ break;
+ } }
+ break;
+ case TTN_NEEDTEXT:
+ if (pNmhdr->idFrom == (UINT_PTR)GetDlgItem(hwndDlg,IDC_CHAT_LIST))
+ {
+ LPNMTTDISPINFO lpttd = (LPNMTTDISPINFO)lParam;
+ POINT p;
+ int item;
+ USERINFO * ui;
+ SESSION_INFO* parentdat =(SESSION_INFO*)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
+
+ GetCursorPos( &p );
+ ScreenToClient(GetDlgItem(hwndDlg, IDC_CHAT_LIST), &p);
+ item = LOWORD(SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LIST), LB_ITEMFROMPOINT, 0, MAKELPARAM(p.x, p.y)));
+ ui = SM_GetUserFromIndex(parentdat->ptszID, parentdat->pszModule, item);
+ if ( ui != NULL ) {
+ static TCHAR ptszBuf[ 1024 ];
+ mir_sntprintf( ptszBuf, SIZEOF(ptszBuf), _T("%s: %s\r\n%s: %s\r\n%s: %s"),
+ TranslateT( "Nick name" ), ui->pszNick,
+ TranslateT( "Unique id" ), ui->pszUID,
+ TranslateT( "Status" ), TM_WordToString( parentdat->pStatuses, ui->Status ));
+ lpttd->lpszText = ptszBuf;
+ } }
+ break;
+ } }
+ break;
+
+ case WM_COMMAND:
+ if (!lParam && CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM) si->windowData.hContact))
+ break;
+ switch (LOWORD(wParam)) {
+ case IDC_CHAT_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_CHAT_LIST),&hti.pt);
+
+ item = LOWORD(SendMessage(GetDlgItem(hwndDlg, IDC_CHAT_LIST), LB_ITEMFROMPOINT, 0, MAKELPARAM(hti.pt.x, hti.pt.y)));
+ ui = SM_GetUserFromIndex(si->ptszID, si->pszModule, item);
+ if (ui) {
+ if (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);
+ }
+ else DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_PRIVMESS, ui->pszUID, NULL, (LPARAM)NULL);
+ }
+
+ return TRUE;
+ }
+
+ if ( HIWORD(wParam) == LBN_KILLFOCUS )
+ RedrawWindow(GetDlgItem(hwndDlg, IDC_CHAT_LIST), NULL, NULL, RDW_INVALIDATE);
+ break;
+
+ case IDOK:
+ {
+ char* pszRtf;
+ TCHAR* ptszText, *p1;
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDOK)))
+ break;
+
+ pszRtf = GetRichTextRTF(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ {
+ TCmdList *cmdListNew = tcmdlist_last(si->windowData.cmdList);
+ while (cmdListNew != NULL && cmdListNew->temporary) {
+ si->windowData.cmdList = tcmdlist_remove(si->windowData.cmdList, cmdListNew);
+ cmdListNew = tcmdlist_last(si->windowData.cmdList);
+ }
+ }
+ si->windowData.cmdList = tcmdlist_append(si->windowData.cmdList, pszRtf, 20, FALSE);
+ ptszText = DoRtfToTags(pszRtf, si);
+ p1 = _tcschr(ptszText, '\0');
+
+ //remove trailing linebreaks
+ while ( p1 > ptszText && (*p1 == '\0' || *p1 == '\r' || *p1 == '\n')) {
+ *p1 = '\0';
+ p1--;
+ }
+
+ if ( MM_FindModule(si->pszModule)->bAckMsg ) {
+ EnableWindow(GetDlgItem(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(""));
+
+ EnableWindow(GetDlgItem(hwndDlg,IDOK),FALSE);
+
+ DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_MESSAGE, NULL, ptszText, (LPARAM)NULL);
+ mir_free(pszRtf);
+ #if defined( _UNICODE )
+ mir_free(ptszText);
+ #endif
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ }
+ break;
+
+ case IDC_CHAT_SHOWNICKLIST:
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDC_CHAT_SHOWNICKLIST)))
+ break;
+ if (si->iType == GCW_SERVER)
+ break;
+
+ si->bNicklistEnabled = !si->bNicklistEnabled;
+
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_SHOWNICKLIST,BM_SETIMAGE,IMAGE_ICON,(LPARAM)GetCachedIcon(si->bNicklistEnabled?"chat_nicklist":"chat_nicklist2"));
+ SendMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0);
+ SendMessage(hwndDlg, WM_SIZE, 0, 0);
+ break;
+
+ case IDC_CHAT_MESSAGE:
+ if (HIWORD(wParam) == EN_CHANGE) {
+ si->windowData.cmdListCurrent = NULL;
+ EnableWindow(GetDlgItem(hwndDlg, IDOK), GetRichTextLength(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE), si->windowData.codePage, FALSE) != 0);
+ }
+ break;
+
+ case IDC_CHAT_SMILEY:
+ {
+ SMADD_SHOWSEL3 smaddInfo;
+ RECT rc;
+
+ GetWindowRect(GetDlgItem(hwndDlg, IDC_CHAT_SMILEY), &rc);
+
+ smaddInfo.cbSize = sizeof(SMADD_SHOWSEL3);
+ smaddInfo.hwndParent = GetParent(hwndDlg);
+ smaddInfo.hwndTarget = GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE);
+ smaddInfo.targetMessage = EM_REPLACESEL;
+ smaddInfo.targetWParam = TRUE;
+ smaddInfo.Protocolname = si->pszModule;
+ //smaddInfo.Direction = 3;
+ smaddInfo.Direction = 0;
+ smaddInfo.xPosition = rc.left;
+ smaddInfo.yPosition = rc.bottom;
+ smaddInfo.hContact = si->windowData.hContact;
+ 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 ( pInfo )
+ ShellExecute(hwndDlg, NULL, GetChatLogsFilename(si->windowData.hContact, 0), NULL, NULL, SW_SHOW);
+ }
+ break;
+
+ case IDC_CHAT_CHANMGR:
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDC_CHAT_CHANMGR)))
+ break;
+ DoEventHookAsync(hwndDlg, si->ptszID, si->pszModule, GC_USER_CHANMGR, NULL, NULL, (LPARAM)NULL);
+ break;
+
+ case IDC_CHAT_FILTER:
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDC_CHAT_FILTER)))
+ break;
+
+ si->bFilterEnabled = !si->bFilterEnabled;
+ SendDlgItemMessage(hwndDlg,IDC_CHAT_FILTER,BM_SETIMAGE,IMAGE_ICON,(LPARAM)GetCachedIcon(si->bFilterEnabled?"chat_filter":"chat_filter2"));
+ if (si->bFilterEnabled && DBGetContactSettingByte(NULL, "Chat", "RightClickFilter", 0) == 0) {
+ SendMessage(hwndDlg, GC_SHOWFILTERMENU, 0, 0);
+ break;
+ }
+ SendMessage(hwndDlg, GC_REDRAWLOG, 0, 0);
+ break;
+
+ case IDC_CHAT_BKGCOLOR:
+ {
+ MODULEINFO * pInfo = MM_FindModule(si->pszModule);
+ CHARFORMAT2 cf;
+
+ cf.cbSize = sizeof(CHARFORMAT2);
+ cf.dwEffects = 0;
+
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDC_CHAT_BKGCOLOR)))
+ break;
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_BKGCOLOR)) {
+ if (DBGetContactSettingByte(NULL, "Chat", "RightClickFilter", 0) == 0)
+ SendMessage(hwndDlg, GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_CHAT_BKGCOLOR);
+ else if (si->bBGSet){
+ cf.dwMask = CFM_BACKCOLOR;
+ cf.crBackColor = pInfo->crColors[si->iBG];
+ if (pInfo->bSingleFormat) {
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
+ } else {
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ } }
+ else {
+ cf.dwMask = CFM_BACKCOLOR;
+ cf.crBackColor = (COLORREF)DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_INPUTBKGCOLOUR, SRMSGDEFSET_INPUTBKGCOLOUR);
+ if (pInfo->bSingleFormat) {
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
+ } else {
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ } }
+ break;
+
+ case IDC_CHAT_COLOR:
+ {
+ MODULEINFO * pInfo = MM_FindModule(si->pszModule);
+ CHARFORMAT2 cf;
+ cf.cbSize = sizeof(CHARFORMAT2);
+ cf.dwEffects = 0;
+
+ if (!IsWindowEnabled(GetDlgItem(hwndDlg,IDC_CHAT_COLOR)))
+ break;
+
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_COLOR) ) {
+ if (DBGetContactSettingByte(NULL, "Chat", "RightClickFilter", 0) == 0)
+ SendMessage(hwndDlg, GC_SHOWCOLORCHOOSER, 0, (LPARAM)IDC_CHAT_COLOR);
+ else if (si->bFGSet) {
+ cf.dwMask = CFM_COLOR;
+ cf.crTextColor = pInfo->crColors[si->iFG];
+ if (pInfo->bSingleFormat) {
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
+ } else {
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ } }
+ else {
+ COLORREF cr;
+
+ LoadMsgDlgFont(MSGFONTID_MESSAGEAREA, NULL, &cr, FALSE);
+ cf.dwMask = CFM_COLOR;
+ cf.crTextColor = cr;
+ if (pInfo->bSingleFormat) {
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
+ } else {
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+
+ } }
+ break;
+
+ case IDC_CHAT_BOLD:
+ case IDC_CHAT_ITALICS:
+ case IDC_CHAT_UNDERLINE:
+
+ {
+ MODULEINFO * pInfo = MM_FindModule(si->pszModule);
+ 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_CHAT_ITALICS && !IsWindowEnabled(GetDlgItem(hwndDlg,IDC_CHAT_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_CHAT_ITALICS))
+ cf.dwEffects |= CFE_ITALIC;
+ if (IsDlgButtonChecked(hwndDlg, IDC_CHAT_UNDERLINE))
+ cf.dwEffects |= CFE_UNDERLINE;
+ if (pInfo->bSingleFormat) {
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
+ } else {
+ SendDlgItemMessage(hwndDlg, IDC_CHAT_MESSAGE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
+ }
+ }
+ break;
+ case IDCANCEL:
+ PostMessage(hwndDlg, WM_CLOSE, 0, 0);
+ }
+ break;
+
+ case WM_KEYDOWN:
+ SetFocus(GetDlgItem(hwndDlg, IDC_CHAT_MESSAGE));
+ break;
+
+
+
+ case WM_GETMINMAXINFO:
+ {
+ MINMAXINFO* mmi = (MINMAXINFO*)lParam;
+ mmi->ptMinTrackSize.x = si->iSplitterX + 43;
+ if (mmi->ptMinTrackSize.x < 350)
+ mmi->ptMinTrackSize.x = 350;
+
+ mmi->ptMinTrackSize.y = si->windowData.minLogBoxHeight + TOOLBAR_HEIGHT + si->windowData.minEditBoxHeight + 5;
+ }
+ break;
+
+ case WM_LBUTTONDBLCLK:
+ if (LOWORD(lParam) < 30)
+ PostMessage(hwndDlg, GC_SCROLLTOBOTTOM, 0, 0);
+ else
+ SendMessage(GetParent(hwndDlg), WM_SYSCOMMAND, SC_MINIMIZE, 0);
+ break;
+
+ case WM_LBUTTONDOWN:
+ SendMessage(GetParent(hwndDlg), WM_LBUTTONDOWN, wParam, lParam);
+ return TRUE;
+
+ case WM_RBUTTONUP:
+ {
+ int i;
+ POINT pt;
+ MENUITEMINFO mii;
+ hToolbarMenu = CreatePopupMenu();
+ for (i = 0; i < SIZEOF(toolbarButtons); i++) {
+ ZeroMemory(&mii, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_ID | MIIM_STRING | MIIM_STATE | MIIM_DATA | MIIM_BITMAP;
+ mii.fType = MFT_STRING;
+ mii.fState = (g_dat->chatBbuttonVisibility & (1<< i)) ? MFS_CHECKED : MFS_UNCHECKED;
+ mii.wID = i + 1;
+ mii.dwItemData = (ULONG_PTR)g_dat->hChatButtonIconList;
+ mii.hbmpItem = HBMMENU_CALLBACK;
+ mii.dwTypeData = TranslateTS((toolbarButtons[i].name));
+ InsertMenuItem(hToolbarMenu, i, TRUE, &mii);
+ }
+// CallService(MS_LANGPACK_TRANSLATEMENU, (WPARAM) hToolbarMenu, 0);
+ pt.x = (short) LOWORD(GetMessagePos());
+ pt.y = (short) HIWORD(GetMessagePos());
+ i = TrackPopupMenu(hToolbarMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL);
+ if (i > 0) {
+ g_dat->chatBbuttonVisibility ^= (1 << (i - 1));
+ DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_CHATBUTTONVISIBILITY, g_dat->chatBbuttonVisibility);
+ SM_BroadcastMessage(NULL, GC_SETWNDPROPS, 0, 0, TRUE);
+ }
+ DestroyMenu(hToolbarMenu);
+ return TRUE;
+ }
+
+ case DM_GETCONTEXTMENU:
+ {
+ HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) si->windowData.hContact, 0);
+ SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)hMenu);
+ return TRUE;
+ }
+
+ case WM_CONTEXTMENU:
+ if (GetParent(hwndDlg) == (HWND) wParam) {
+ POINT pt;
+ HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) si->windowData.hContact, 0);
+ GetCursorPos(&pt);
+ TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, hwndDlg, NULL);
+ DestroyMenu(hMenu);
+ }
+ break;
+
+ case WM_CLOSE:
+ SendMessage(hwndDlg, GC_CLOSEWINDOW, 0, 0);
+ break;
+
+ case GC_CLOSEWINDOW:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+
+ NotifyLocalWinEvent(si->windowData.hContact, hwndDlg, MSG_WINDOW_EVT_CLOSING);
+ si->hWnd = NULL;
+ SetWindowLongPtr(hwndDlg,GWLP_USERDATA,0);
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_CHAT_SPLITTERY),GWLP_WNDPROC,(LONG_PTR)OldSplitterProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_CHAT_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_CHAT_FILTER),GWLP_WNDPROC,(LONG_PTR)OldFilterButtonProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_CHAT_COLOR),GWLP_WNDPROC,(LONG_PTR)OldFilterButtonProc);
+ SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_CHAT_BKGCOLOR),GWLP_WNDPROC,(LONG_PTR)OldFilterButtonProc);
+
+ SendMessage(GetParent(hwndDlg), CM_REMOVECHILD, 0, (LPARAM) hwndDlg);
+ if (si->windowData.hwndLog != NULL) {
+ IEVIEWWINDOW ieWindow;
+ ieWindow.cbSize = sizeof(IEVIEWWINDOW);
+ ieWindow.iType = IEW_DESTROY;
+ ieWindow.hwnd = si->windowData.hwndLog;
+ CallService(MS_IEVIEW_WINDOW, 0, (LPARAM)&ieWindow);
+ }
+
+ NotifyLocalWinEvent(si->windowData.hContact, hwndDlg, MSG_WINDOW_EVT_CLOSE);
+ break;
+ }
+ return(FALSE);
+}
|