From 1c51a6e0409bbfd61383a942636d6766154b5225 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sat, 23 Jun 2012 19:20:55 +0000 Subject: srmm plusified git-svn-id: http://svn.miranda-ng.org/main/trunk@583 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/SRMM/cmdlist.c | 168 ---- plugins/SRMM/cmdlist.cpp | 166 ++++ plugins/SRMM/commonheaders.h | 4 - plugins/SRMM/globals.c | 188 ---- plugins/SRMM/globals.cpp | 188 ++++ plugins/SRMM/msgdialog.c | 2024 ------------------------------------------ plugins/SRMM/msgdialog.cpp | 2014 +++++++++++++++++++++++++++++++++++++++++ plugins/SRMM/msglog.c | 645 -------------- plugins/SRMM/msglog.cpp | 645 ++++++++++++++ plugins/SRMM/msgoptions.c | 658 -------------- plugins/SRMM/msgoptions.cpp | 656 ++++++++++++++ plugins/SRMM/msgs.c | 589 ------------ plugins/SRMM/msgs.cpp | 567 ++++++++++++ plugins/SRMM/msgs.h | 23 +- plugins/SRMM/msgtimedout.c | 112 --- plugins/SRMM/msgtimedout.cpp | 112 +++ plugins/SRMM/richutil.c | 269 ------ plugins/SRMM/richutil.cpp | 269 ++++++ plugins/SRMM/srmm.c | 82 -- plugins/SRMM/srmm.cpp | 82 ++ plugins/SRMM/srmm_10.vcxproj | 20 +- plugins/SRMM/statusicon.c | 221 ----- plugins/SRMM/statusicon.cpp | 221 +++++ 23 files changed, 4949 insertions(+), 4974 deletions(-) delete mode 100644 plugins/SRMM/cmdlist.c create mode 100644 plugins/SRMM/cmdlist.cpp delete mode 100644 plugins/SRMM/globals.c create mode 100644 plugins/SRMM/globals.cpp delete mode 100644 plugins/SRMM/msgdialog.c create mode 100644 plugins/SRMM/msgdialog.cpp delete mode 100644 plugins/SRMM/msglog.c create mode 100644 plugins/SRMM/msglog.cpp delete mode 100644 plugins/SRMM/msgoptions.c create mode 100644 plugins/SRMM/msgoptions.cpp delete mode 100644 plugins/SRMM/msgs.c create mode 100644 plugins/SRMM/msgs.cpp delete mode 100644 plugins/SRMM/msgtimedout.c create mode 100644 plugins/SRMM/msgtimedout.cpp delete mode 100644 plugins/SRMM/richutil.c create mode 100644 plugins/SRMM/richutil.cpp delete mode 100644 plugins/SRMM/srmm.c create mode 100644 plugins/SRMM/srmm.cpp delete mode 100644 plugins/SRMM/statusicon.c create mode 100644 plugins/SRMM/statusicon.cpp (limited to 'plugins') diff --git a/plugins/SRMM/cmdlist.c b/plugins/SRMM/cmdlist.c deleted file mode 100644 index 88b1055ca2..0000000000 --- a/plugins/SRMM/cmdlist.c +++ /dev/null @@ -1,168 +0,0 @@ -/* -Copyright 2000-2010 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ -#include "commonheaders.h" - -int tcmdlist_append(SortedList *list, TCHAR *data) -{ - TCmdList *new_list; - - if (!data) - return list->realCount - 1; - - if (list->realCount >= 20) - { - TCmdList* n = (TCmdList*)list->items[0]; - mir_free(n->szCmd); - mir_free(n); - li.List_Remove(list, 0); - } - - new_list = mir_alloc(sizeof(TCmdList)); - new_list->szCmd = mir_tstrdup(data); - - li.List_InsertPtr(list, new_list); - - return list->realCount - 1; -} - -void tcmdlist_free(SortedList *list) -{ - int i; - TCmdList** n = (TCmdList**)list->items; - - for (i = 0; i < list->realCount; ++i) - { - mir_free(n[i]->szCmd); - mir_free(n[i]); - } - li.List_Destroy(list); - mir_free(list); -} - -static SortedList msgQueue = { NULL, 0, 0, 5, NULL }; -static CRITICAL_SECTION csMsgQueue; -static UINT_PTR timerId; - -void MessageFailureProcess(TMsgQueue *item, const char* err); - -static VOID CALLBACK MsgTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) -{ - int i, ntl = 0; - TMsgQueue **tmlst = NULL; - - EnterCriticalSection(&csMsgQueue); - - for (i = 0; i < msgQueue.realCount; ++i) - { - TMsgQueue *item = (TMsgQueue*)msgQueue.items[i]; - if (dwTime - item->ts > g_dat->msgTimeout) - { - if (!ntl) - tmlst = (TMsgQueue**)alloca((msgQueue.realCount - i) * sizeof(TMsgQueue*)); - tmlst[ntl++] = item; - - li.List_Remove(&msgQueue, i--); - } - } - LeaveCriticalSection(&csMsgQueue); - - for (i = 0; i < ntl; ++i) - MessageFailureProcess(tmlst[i], LPGEN("The message send timed out.")); -} - -void msgQueue_add(HANDLE hContact, HANDLE id, const TCHAR* szMsg, HANDLE hDbEvent) -{ - TMsgQueue *item; - - item = mir_alloc(sizeof(TMsgQueue)); - item->hContact = hContact; - item->id = id; - item->szMsg = mir_tstrdup(szMsg); - item->hDbEvent = hDbEvent; - item->ts = GetTickCount(); - - EnterCriticalSection(&csMsgQueue); - if (!msgQueue.realCount && !timerId) - timerId = SetTimer(NULL, 0, 5000, MsgTimer); - li.List_InsertPtr(&msgQueue, item); - LeaveCriticalSection(&csMsgQueue); - -} - -void msgQueue_processack(HANDLE hContact, HANDLE id, BOOL success, const char* szErr) -{ - int i; - TMsgQueue* item = NULL;; - - EnterCriticalSection(&csMsgQueue); - - for (i = 0; i < msgQueue.realCount; ++i) - { - item = (TMsgQueue*)msgQueue.items[i]; - if (item->hContact == hContact && item->id == id) - { - li.List_Remove(&msgQueue, i); - - if (!msgQueue.realCount && timerId) - { - KillTimer(NULL, timerId); - timerId = 0; - } - break; - } - item = NULL; - } - LeaveCriticalSection(&csMsgQueue); - - if (item) - { - if (success) - { - mir_free(item->szMsg); - mir_free(item); - } - else - MessageFailureProcess(item, szErr); - } -} - -void msgQueue_init(void) -{ - InitializeCriticalSection(&csMsgQueue); -} - -void msgQueue_destroy(void) -{ - int i; - - EnterCriticalSection(&csMsgQueue); - - for (i = 0; i < msgQueue.realCount; ++i) - { - TMsgQueue* item = (TMsgQueue*)msgQueue.items[i]; - mir_free(item->szMsg); - mir_free(item); - } - li.List_Destroy(&msgQueue); - - LeaveCriticalSection(&csMsgQueue); - - DeleteCriticalSection(&csMsgQueue); -} diff --git a/plugins/SRMM/cmdlist.cpp b/plugins/SRMM/cmdlist.cpp new file mode 100644 index 0000000000..426c26031d --- /dev/null +++ b/plugins/SRMM/cmdlist.cpp @@ -0,0 +1,166 @@ +/* +Copyright 2000-2010 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "commonheaders.h" + +int tcmdlist_append(SortedList *list, TCHAR *data) +{ + TCmdList *new_list; + + if (!data) + return list->realCount - 1; + + if (list->realCount >= 20) + { + TCmdList* n = (TCmdList*)list->items[0]; + mir_free(n->szCmd); + mir_free(n); + li.List_Remove(list, 0); + } + + new_list = (TCmdList*)mir_alloc(sizeof(TCmdList)); + new_list->szCmd = mir_tstrdup(data); + + li.List_InsertPtr(list, new_list); + + return list->realCount - 1; +} + +void tcmdlist_free(SortedList *list) +{ + int i; + TCmdList** n = (TCmdList**)list->items; + + for (i = 0; i < list->realCount; ++i) + { + mir_free(n[i]->szCmd); + mir_free(n[i]); + } + li.List_Destroy(list); + mir_free(list); +} + +static SortedList msgQueue = { NULL, 0, 0, 5, NULL }; +static CRITICAL_SECTION csMsgQueue; +static UINT_PTR timerId; + +void MessageFailureProcess(TMsgQueue *item, const char* err); + +static VOID CALLBACK MsgTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) +{ + int i, ntl = 0; + TMsgQueue **tmlst = NULL; + + EnterCriticalSection(&csMsgQueue); + + for (i = 0; i < msgQueue.realCount; ++i) + { + TMsgQueue *item = (TMsgQueue*)msgQueue.items[i]; + if (dwTime - item->ts > g_dat->msgTimeout) + { + if (!ntl) + tmlst = (TMsgQueue**)alloca((msgQueue.realCount - i) * sizeof(TMsgQueue*)); + tmlst[ntl++] = item; + + li.List_Remove(&msgQueue, i--); + } + } + LeaveCriticalSection(&csMsgQueue); + + for (i = 0; i < ntl; ++i) + MessageFailureProcess(tmlst[i], LPGEN("The message send timed out.")); +} + +void msgQueue_add(HANDLE hContact, HANDLE id, const TCHAR* szMsg, HANDLE hDbEvent) +{ + TMsgQueue *item = (TMsgQueue*)mir_alloc(sizeof(TMsgQueue)); + item->hContact = hContact; + item->id = id; + item->szMsg = mir_tstrdup(szMsg); + item->hDbEvent = hDbEvent; + item->ts = GetTickCount(); + + EnterCriticalSection(&csMsgQueue); + if (!msgQueue.realCount && !timerId) + timerId = SetTimer(NULL, 0, 5000, MsgTimer); + li.List_InsertPtr(&msgQueue, item); + LeaveCriticalSection(&csMsgQueue); + +} + +void msgQueue_processack(HANDLE hContact, HANDLE id, BOOL success, const char* szErr) +{ + int i; + TMsgQueue* item = NULL;; + + EnterCriticalSection(&csMsgQueue); + + for (i = 0; i < msgQueue.realCount; ++i) + { + item = (TMsgQueue*)msgQueue.items[i]; + if (item->hContact == hContact && item->id == id) + { + li.List_Remove(&msgQueue, i); + + if (!msgQueue.realCount && timerId) + { + KillTimer(NULL, timerId); + timerId = 0; + } + break; + } + item = NULL; + } + LeaveCriticalSection(&csMsgQueue); + + if (item) + { + if (success) + { + mir_free(item->szMsg); + mir_free(item); + } + else + MessageFailureProcess(item, szErr); + } +} + +void msgQueue_init(void) +{ + InitializeCriticalSection(&csMsgQueue); +} + +void msgQueue_destroy(void) +{ + int i; + + EnterCriticalSection(&csMsgQueue); + + for (i = 0; i < msgQueue.realCount; ++i) + { + TMsgQueue* item = (TMsgQueue*)msgQueue.items[i]; + mir_free(item->szMsg); + mir_free(item); + } + li.List_Destroy(&msgQueue); + + LeaveCriticalSection(&csMsgQueue); + + DeleteCriticalSection(&csMsgQueue); +} diff --git a/plugins/SRMM/commonheaders.h b/plugins/SRMM/commonheaders.h index fec878afd7..89911bcab1 100644 --- a/plugins/SRMM/commonheaders.h +++ b/plugins/SRMM/commonheaders.h @@ -70,10 +70,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "richutil.h" #include "version.h" -#if _MSC_VER >= 1500 - #define wEffects wReserved -#endif - extern struct LIST_INTERFACE li; extern HINSTANCE g_hInst; diff --git a/plugins/SRMM/globals.c b/plugins/SRMM/globals.c deleted file mode 100644 index 802bc9fccc..0000000000 --- a/plugins/SRMM/globals.c +++ /dev/null @@ -1,188 +0,0 @@ -/* -Copyright 2000-2012 Miranda /IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ -#include "commonheaders.h" - -struct GlobalMessageData *g_dat; -static HANDLE g_hooks[4]; - -static int dbaddedevent(WPARAM wParam, LPARAM lParam); -static int ackevent(WPARAM wParam, LPARAM lParam); -static int AvatarChanged(WPARAM wParam, LPARAM lParam); - -typedef struct IconDefStruct -{ - const char *szName; - const char *szDescr; - int defIconID; -} IconList; - -static const IconList iconList[] = -{ - { "INCOMING", LPGEN("Incoming message (10x10)"), IDI_INCOMING }, - { "OUTGOING", LPGEN("Outgoing message (10x10)"), IDI_OUTGOING }, - { "NOTICE", LPGEN("Notice (10x10)"), IDI_NOTICE }, -}; - - -HANDLE hIconLibItem[SIZEOF(iconList)]; - -static void InitIcons(void) -{ - TCHAR szFile[MAX_PATH]; - char szSettingName[100]; - SKINICONDESC sid = {0}; - unsigned i; - - GetModuleFileName(g_hInst, szFile, SIZEOF(szFile)); - - sid.cbSize = sizeof(SKINICONDESC); - sid.ptszDefaultFile = szFile; - sid.pszName = szSettingName; - sid.pszSection = LPGEN("Messaging"); - sid.flags = SIDF_PATH_TCHAR; - sid.cx = 10; sid.cy = 10; - - for (i = 0; i < SIZEOF(iconList); i++) - { - mir_snprintf(szSettingName, sizeof(szSettingName), "SRMM_%s", iconList[i].szName); - sid.pszDescription = (char*)iconList[i].szDescr; - sid.iDefaultIndex = -iconList[i].defIconID; - hIconLibItem[i] = Skin_AddIcon(&sid); - } -} - -static int IconsChanged(WPARAM wParam, LPARAM lParam) -{ - FreeMsgLogIcons(); - LoadMsgLogIcons(); - - return 0; -} - -void InitGlobals() -{ - g_dat = (struct GlobalMessageData *)mir_alloc(sizeof(struct GlobalMessageData)); - g_dat->hMessageWindowList = (HANDLE) CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); - g_hooks[0] = HookEvent(ME_DB_EVENT_ADDED, dbaddedevent); - g_hooks[1] = HookEvent(ME_PROTO_ACK, ackevent); - g_hooks[2] = HookEvent(ME_SKIN2_ICONSCHANGED, IconsChanged); - g_hooks[3] = HookEvent(ME_AV_AVATARCHANGED, AvatarChanged); - - ReloadGlobals(); - InitIcons(); -} - -void FreeGlobals() -{ - int i; - mir_free(g_dat); - - for (i=0; i < SIZEOF(g_hooks); ++i) - if (g_hooks[i]) - UnhookEvent(g_hooks[i]); -} - -void ReloadGlobals() -{ - g_dat->flags = 0; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWINFOLINE, SRMSGDEFSET_SHOWINFOLINE)) - g_dat->flags |= SMF_SHOWINFO; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWBUTTONLINE, SRMSGDEFSET_SHOWBUTTONLINE)) - g_dat->flags |= SMF_SHOWBTNS; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDBUTTON, SRMSGDEFSET_SENDBUTTON)) - g_dat->flags |= SMF_SENDBTN; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPING, SRMSGDEFSET_SHOWTYPING)) - g_dat->flags |= SMF_SHOWTYPING; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGWIN, SRMSGDEFSET_SHOWTYPINGWIN)) - g_dat->flags |= SMF_SHOWTYPINGWIN; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGNOWIN, SRMSGDEFSET_SHOWTYPINGNOWIN)) - g_dat->flags |= SMF_SHOWTYPINGTRAY; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, SRMSGDEFSET_SHOWTYPINGCLIST)) - g_dat->flags |= SMF_SHOWTYPINGCLIST; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWLOGICONS, SRMSGDEFSET_SHOWLOGICONS)) - g_dat->flags |= SMF_SHOWICONS; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTIME, SRMSGDEFSET_SHOWTIME)) - g_dat->flags |= SMF_SHOWTIME; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AVATARENABLE, SRMSGDEFSET_AVATARENABLE)) - g_dat->flags |= SMF_AVATAR; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWDATE, SRMSGDEFSET_SHOWDATE)) - g_dat->flags |= SMF_SHOWDATE; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSECS, SRMSGDEFSET_SHOWSECS)) - g_dat->flags |= SMF_SHOWSECS; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_HIDENAMES, SRMSGDEFSET_HIDENAMES)) - g_dat->flags |= SMF_HIDENAMES; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CHARCOUNT, SRMSGDEFSET_CHARCOUNT)) - g_dat->flags |= SMF_SHOWREADCHAR; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONENTER, SRMSGDEFSET_SENDONENTER)) - g_dat->flags |= SMF_SENDONENTER; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONDBLENTER, SRMSGDEFSET_SENDONDBLENTER)) - g_dat->flags |= SMF_SENDONDBLENTER; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, SRMSGDEFSET_AUTOCLOSE)) - g_dat->flags |= SMF_AUTOCLOSE; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOMIN, SRMSGDEFSET_AUTOMIN)) - g_dat->flags |= SMF_AUTOMIN; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGUNKNOWN, SRMSGDEFSET_TYPINGUNKNOWN)) - g_dat->flags |= SMF_TYPINGUNKNOWN; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CTRLSUPPORT, SRMSGDEFSET_CTRLSUPPORT)) - g_dat->flags |= SMF_CTRLSUPPORT; - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWFORMAT, SRMSGDEFSET_SHOWFORMAT)) - g_dat->flags |= SMF_SHOWFORMAT; - - g_dat->openFlags = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_POPFLAGS, SRMSGDEFSET_POPFLAGS); - g_dat->nFlashMax = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, SRMSGDEFSET_FLASHCOUNT); - - g_dat->msgTimeout = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_MSGTIMEOUT, SRMSGDEFSET_MSGTIMEOUT); - if (g_dat->msgTimeout < SRMSGSET_MSGTIMEOUT_MIN) g_dat->msgTimeout = SRMSGDEFSET_MSGTIMEOUT; -} - -static int dbaddedevent(WPARAM wParam, LPARAM lParam) -{ - HANDLE hContact = (HANDLE)wParam; - if (hContact) - { - HWND h = WindowList_Find(g_dat->hMessageWindowList, hContact); - if (h) SendMessage(h, HM_DBEVENTADDED, (WPARAM)hContact, lParam); - } - return 0; -} - -static int ackevent(WPARAM wParam, LPARAM lParam) -{ - ACKDATA *pAck = (ACKDATA *)lParam; - - if (!pAck) return 0; - if (pAck->type == ACKTYPE_MESSAGE) - { - msgQueue_processack(pAck->hContact, pAck->hProcess, pAck->result == ACKRESULT_SUCCESS, (char*)pAck->lParam); - - if (pAck->result == ACKRESULT_SUCCESS) - SkinPlaySound("SendMsg"); - } - return 0; -} - -int AvatarChanged(WPARAM wParam, LPARAM lParam) -{ - HANDLE hContact = (HANDLE)wParam; - HWND h = WindowList_Find(g_dat->hMessageWindowList, hContact); - if (h) SendMessage(h, HM_AVATARACK, wParam, lParam); - return 0; -} - diff --git a/plugins/SRMM/globals.cpp b/plugins/SRMM/globals.cpp new file mode 100644 index 0000000000..2a5f4d5da6 --- /dev/null +++ b/plugins/SRMM/globals.cpp @@ -0,0 +1,188 @@ +/* +Copyright 2000-2012 Miranda /IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "commonheaders.h" + +struct GlobalMessageData *g_dat; +static HANDLE g_hooks[4]; + +static int dbaddedevent(WPARAM wParam, LPARAM lParam); +static int ackevent(WPARAM wParam, LPARAM lParam); +static int AvatarChanged(WPARAM wParam, LPARAM lParam); + +typedef struct IconDefStruct +{ + const char *szName; + const char *szDescr; + int defIconID; +} IconList; + +static const IconList iconList[] = +{ + { "INCOMING", LPGEN("Incoming message (10x10)"), IDI_INCOMING }, + { "OUTGOING", LPGEN("Outgoing message (10x10)"), IDI_OUTGOING }, + { "NOTICE", LPGEN("Notice (10x10)"), IDI_NOTICE }, +}; + + +HANDLE hIconLibItem[SIZEOF(iconList)]; + +static void InitIcons(void) +{ + TCHAR szFile[MAX_PATH]; + char szSettingName[100]; + SKINICONDESC sid = {0}; + unsigned i; + + GetModuleFileName(g_hInst, szFile, SIZEOF(szFile)); + + sid.cbSize = sizeof(SKINICONDESC); + sid.ptszDefaultFile = szFile; + sid.pszName = szSettingName; + sid.pszSection = LPGEN("Messaging"); + sid.flags = SIDF_PATH_TCHAR; + sid.cx = 10; sid.cy = 10; + + for (i = 0; i < SIZEOF(iconList); i++) + { + mir_snprintf(szSettingName, sizeof(szSettingName), "SRMM_%s", iconList[i].szName); + sid.pszDescription = (char*)iconList[i].szDescr; + sid.iDefaultIndex = -iconList[i].defIconID; + hIconLibItem[i] = Skin_AddIcon(&sid); + } +} + +static int IconsChanged(WPARAM wParam, LPARAM lParam) +{ + FreeMsgLogIcons(); + LoadMsgLogIcons(); + + return 0; +} + +void InitGlobals() +{ + g_dat = (struct GlobalMessageData *)mir_alloc(sizeof(struct GlobalMessageData)); + g_dat->hMessageWindowList = (HANDLE) CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); + g_hooks[0] = HookEvent(ME_DB_EVENT_ADDED, dbaddedevent); + g_hooks[1] = HookEvent(ME_PROTO_ACK, ackevent); + g_hooks[2] = HookEvent(ME_SKIN2_ICONSCHANGED, IconsChanged); + g_hooks[3] = HookEvent(ME_AV_AVATARCHANGED, AvatarChanged); + + ReloadGlobals(); + InitIcons(); +} + +void FreeGlobals() +{ + int i; + mir_free(g_dat); + + for (i=0; i < SIZEOF(g_hooks); ++i) + if (g_hooks[i]) + UnhookEvent(g_hooks[i]); +} + +void ReloadGlobals() +{ + g_dat->flags = 0; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWINFOLINE, SRMSGDEFSET_SHOWINFOLINE)) + g_dat->flags |= SMF_SHOWINFO; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWBUTTONLINE, SRMSGDEFSET_SHOWBUTTONLINE)) + g_dat->flags |= SMF_SHOWBTNS; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDBUTTON, SRMSGDEFSET_SENDBUTTON)) + g_dat->flags |= SMF_SENDBTN; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPING, SRMSGDEFSET_SHOWTYPING)) + g_dat->flags |= SMF_SHOWTYPING; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGWIN, SRMSGDEFSET_SHOWTYPINGWIN)) + g_dat->flags |= SMF_SHOWTYPINGWIN; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGNOWIN, SRMSGDEFSET_SHOWTYPINGNOWIN)) + g_dat->flags |= SMF_SHOWTYPINGTRAY; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, SRMSGDEFSET_SHOWTYPINGCLIST)) + g_dat->flags |= SMF_SHOWTYPINGCLIST; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWLOGICONS, SRMSGDEFSET_SHOWLOGICONS)) + g_dat->flags |= SMF_SHOWICONS; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTIME, SRMSGDEFSET_SHOWTIME)) + g_dat->flags |= SMF_SHOWTIME; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AVATARENABLE, SRMSGDEFSET_AVATARENABLE)) + g_dat->flags |= SMF_AVATAR; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWDATE, SRMSGDEFSET_SHOWDATE)) + g_dat->flags |= SMF_SHOWDATE; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSECS, SRMSGDEFSET_SHOWSECS)) + g_dat->flags |= SMF_SHOWSECS; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_HIDENAMES, SRMSGDEFSET_HIDENAMES)) + g_dat->flags |= SMF_HIDENAMES; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CHARCOUNT, SRMSGDEFSET_CHARCOUNT)) + g_dat->flags |= SMF_SHOWREADCHAR; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONENTER, SRMSGDEFSET_SENDONENTER)) + g_dat->flags |= SMF_SENDONENTER; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONDBLENTER, SRMSGDEFSET_SENDONDBLENTER)) + g_dat->flags |= SMF_SENDONDBLENTER; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, SRMSGDEFSET_AUTOCLOSE)) + g_dat->flags |= SMF_AUTOCLOSE; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOMIN, SRMSGDEFSET_AUTOMIN)) + g_dat->flags |= SMF_AUTOMIN; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGUNKNOWN, SRMSGDEFSET_TYPINGUNKNOWN)) + g_dat->flags |= SMF_TYPINGUNKNOWN; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CTRLSUPPORT, SRMSGDEFSET_CTRLSUPPORT)) + g_dat->flags |= SMF_CTRLSUPPORT; + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWFORMAT, SRMSGDEFSET_SHOWFORMAT)) + g_dat->flags |= SMF_SHOWFORMAT; + + g_dat->openFlags = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_POPFLAGS, SRMSGDEFSET_POPFLAGS); + g_dat->nFlashMax = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, SRMSGDEFSET_FLASHCOUNT); + + g_dat->msgTimeout = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_MSGTIMEOUT, SRMSGDEFSET_MSGTIMEOUT); + if (g_dat->msgTimeout < SRMSGSET_MSGTIMEOUT_MIN) g_dat->msgTimeout = SRMSGDEFSET_MSGTIMEOUT; +} + +static int dbaddedevent(WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE)wParam; + if (hContact) + { + HWND h = WindowList_Find(g_dat->hMessageWindowList, hContact); + if (h) SendMessage(h, HM_DBEVENTADDED, (WPARAM)hContact, lParam); + } + return 0; +} + +static int ackevent(WPARAM wParam, LPARAM lParam) +{ + ACKDATA *pAck = (ACKDATA *)lParam; + + if (!pAck) return 0; + if (pAck->type == ACKTYPE_MESSAGE) + { + msgQueue_processack(pAck->hContact, pAck->hProcess, pAck->result == ACKRESULT_SUCCESS, (char*)pAck->lParam); + + if (pAck->result == ACKRESULT_SUCCESS) + SkinPlaySound("SendMsg"); + } + return 0; +} + +int AvatarChanged(WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE)wParam; + HWND h = WindowList_Find(g_dat->hMessageWindowList, hContact); + if (h) SendMessage(h, HM_AVATARACK, wParam, lParam); + return 0; +} + diff --git a/plugins/SRMM/msgdialog.c b/plugins/SRMM/msgdialog.c deleted file mode 100644 index 1e8849997a..0000000000 --- a/plugins/SRMM/msgdialog.c +++ /dev/null @@ -1,2024 +0,0 @@ -/* -Copyright 2000-2012 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "commonheaders.h" -#include "statusicon.h" - -#define TIMERID_FLASHWND 1 -#define TIMERID_TYPE 2 -#define TIMEOUT_FLASHWND 900 -#define TIMEOUT_TYPEOFF 10000 //send type off after 10 seconds of inactivity -#define SB_CHAR_WIDTH 45 -#define SB_TIME_WIDTH 60 -#define SB_GRIP_WIDTH 20 // pixels - buffer used to prevent sizegrip from overwriting statusbar icons -#define VALID_AVATAR(x) (x==PA_FORMAT_PNG||x==PA_FORMAT_JPEG||x==PA_FORMAT_ICON||x==PA_FORMAT_BMP||x==PA_FORMAT_GIF) - -extern HCURSOR hCurSplitNS, hCurSplitWE, hCurHyperlinkHand; -extern HANDLE hHookWinEvt, hHookWinPopup; -extern struct CREOleCallback reOleCallback; - -static void UpdateReadChars(HWND hwndDlg, HWND hwndStatus); - -static const UINT infoLineControls[] = { IDC_PROTOCOL, IDC_NAME }; -static const UINT buttonLineControls[] = { IDC_ADD, IDC_USERMENU, IDC_DETAILS, IDC_HISTORY }; -static const UINT sendControls[] = { IDC_MESSAGE }; - -static void NotifyLocalWinEvent(HANDLE hContact, HWND hwnd, unsigned int type) { - MessageWindowEventData mwe = { 0 }; - - if (hContact==NULL || hwnd==NULL) return; - mwe.cbSize = sizeof(mwe); - mwe.hContact = hContact; - mwe.hwndWindow = hwnd; - mwe.szModule = SRMMMOD; - mwe.uType = type; - mwe.uFlags = MSG_WINDOW_UFLAG_MSG_BOTH; - mwe.hwndInput = GetDlgItem(hwnd, IDC_MESSAGE); - mwe.hwndLog = GetDlgItem(hwnd, IDC_LOG); - NotifyEventHooks(hHookWinEvt, 0, (LPARAM)&mwe); -} - -static char *MsgServiceName(HANDLE hContact) -{ - char szServiceName[100]; - char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); - if (szProto == NULL) - return PSS_MESSAGE; - - mir_snprintf(szServiceName, SIZEOF(szServiceName), "%s%sW", szProto, PSS_MESSAGE); - if (ServiceExists(szServiceName)) - return PSS_MESSAGE "W"; - return PSS_MESSAGE; -} - -static BOOL IsUtfSendAvailable(HANDLE hContact) -{ - char* szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); - if ( szProto == NULL ) - return FALSE; - - return ( CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_IMSENDUTF ) ? TRUE : FALSE; -} - -static int RTL_Detect(const TCHAR *ptszText) -{ - WORD *infoTypeC2; - int i; - int iLen = (int)_tcslen(ptszText); - - infoTypeC2 = (WORD*)alloca(sizeof(WORD) * (iLen + 2)); - GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE2, ptszText, iLen, infoTypeC2); - - for(i = 0; i < iLen; i++) { - if(infoTypeC2[i] == C2_RIGHTTOLEFT) - return 1; - } - return 0; -} - -HANDLE SendMessageDirect(const TCHAR *szMsg, HANDLE hContact, char *szProto) -{ - int flags = 0; - int bufSize = 0; - char *sendBuffer = NULL; - - if (RTL_Detect(szMsg)) flags |= PREF_RTL; - - if (IsUtfSendAvailable(hContact)) - { - flags |= PREF_UTF; - sendBuffer = mir_utf8encodeT(szMsg); - if (!sendBuffer || !sendBuffer[0]) - { - mir_free(sendBuffer); - return NULL; - } - bufSize = (int)strlen(sendBuffer) + 1; - } - else - { - flags |= PREF_TCHAR; - sendBuffer = mir_t2a(szMsg); - if (!sendBuffer || !sendBuffer[0]) - { - mir_free(sendBuffer); - return NULL; - } - bufSize = (int)strlen(sendBuffer) + 1; - - { - size_t bufSizeT = (_tcslen(szMsg) + 1) * sizeof(TCHAR) ; - - sendBuffer = (char*)mir_realloc(sendBuffer, bufSizeT + bufSize); - memcpy((TCHAR*)&sendBuffer[bufSize], szMsg, bufSizeT); - bufSize += (int)bufSizeT; - } - - } - - if (hContact == NULL) - { - mir_free(sendBuffer); - return NULL; - } - - if (sendBuffer) - { - HANDLE hNewEvent, hSendId; - DBEVENTINFO dbei = { 0 }; - dbei.cbSize = sizeof(dbei); - dbei.eventType = EVENTTYPE_MESSAGE; - dbei.flags = DBEF_SENT | (flags & PREF_UTF ? DBEF_UTF : 0) | (flags & PREF_RTL ? DBEF_RTL : 0); - dbei.szModule = szProto; - dbei.timestamp = (DWORD)time(NULL); - dbei.cbBlob = (DWORD)bufSize; - dbei.pBlob = (PBYTE)sendBuffer; - - hNewEvent = (HANDLE) CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei); - hSendId = (HANDLE) CallContactService(hContact, MsgServiceName(hContact), flags, (LPARAM) sendBuffer); - msgQueue_add(hContact, hSendId, szMsg, hNewEvent); - mir_free(sendBuffer); - - return hNewEvent; - } - return NULL; -} - - -static void AddToFileList(TCHAR ***pppFiles,int *totalCount,const TCHAR* szFilename) -{ - *pppFiles=(TCHAR**)mir_realloc(*pppFiles,(++*totalCount+1)*sizeof(TCHAR*)); - (*pppFiles)[*totalCount] = NULL; - (*pppFiles)[*totalCount-1] = mir_tstrdup( szFilename ); - - if ( GetFileAttributes(szFilename) & FILE_ATTRIBUTE_DIRECTORY ) { - WIN32_FIND_DATA fd; - HANDLE hFind; - TCHAR szPath[MAX_PATH]; - mir_sntprintf(szPath, SIZEOF(szPath), _T("%s\\*"), szFilename); - if (( hFind = FindFirstFile( szPath, &fd )) != INVALID_HANDLE_VALUE ) { - do { - if ( !_tcscmp(fd.cFileName,_T(".")) || !_tcscmp(fd.cFileName,_T(".."))) continue; - mir_sntprintf(szPath, SIZEOF(szPath), _T("%s\\%s"), szFilename, fd.cFileName); - AddToFileList(pppFiles,totalCount,szPath); - } - while( FindNextFile( hFind,&fd )); - FindClose( hFind ); - } } } - -static void ShowMultipleControls(HWND hwndDlg, const UINT * controls, int cControls, int state) -{ - int i; - for (i = 0; i < cControls; i++) - ShowWindow(GetDlgItem(hwndDlg, controls[i]), state); -} - -static void UpdateReadChars(HWND hwndDlg, HWND hwndStatus) -{ - if (hwndStatus && (g_dat->flags & SMF_SHOWREADCHAR)) - { - TCHAR buf[32]; - int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)); - - mir_sntprintf(buf, SIZEOF(buf), _T("%d"), len); - SendMessage(hwndStatus, SB_SETTEXT, 1, (LPARAM) buf); - } -} - -static void ShowTime(struct MessageWindowData *dat) -{ - if (dat->hwndStatus && dat->hTimeZone) - { - SYSTEMTIME st; - GetSystemTime(&st); - if (dat->wMinute != st.wMinute) - { - TCHAR buf[32]; - unsigned i = (g_dat->flags & SMF_SHOWREADCHAR) ? 2 : 1; - - tmi.printDateTime(dat->hTimeZone, _T("t"), buf, SIZEOF(buf), 0); - SendMessage(dat->hwndStatus, SB_SETTEXT, i, (LPARAM) buf); - dat->wMinute = st.wMinute; - } - } -} - -static void SetupStatusBar(HWND hwndDlg, struct MessageWindowData *dat) -{ - int icons_width, cx, i = 0, statwidths[4]; - RECT rc; - - icons_width = GetStatusIconsCount(dat->hContact) * (GetSystemMetrics(SM_CXSMICON) + 2) + SB_GRIP_WIDTH; - GetWindowRect(dat->hwndStatus, &rc); - cx = rc.right - rc.left; - - if (dat->hTimeZone) - { - if (g_dat->flags & SMF_SHOWREADCHAR) - statwidths[i++] = cx - SB_TIME_WIDTH - SB_CHAR_WIDTH - icons_width; - statwidths[i++] = cx - SB_TIME_WIDTH - icons_width; - } - else if (g_dat->flags & SMF_SHOWREADCHAR) - statwidths[i++] = cx - SB_CHAR_WIDTH - icons_width; - - statwidths[i++] = cx - icons_width; - statwidths[i++] = -1; - SendMessage(dat->hwndStatus, SB_SETPARTS, i, (LPARAM) statwidths); - - UpdateReadChars(hwndDlg, dat->hwndStatus); - ShowTime(dat); - SendMessage(hwndDlg, DM_STATUSICONCHANGE, 0, 0); -} - -static void SetDialogToType(HWND hwndDlg) -{ - struct MessageWindowData *dat; - - dat = (struct MessageWindowData *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - if (dat->hContact) - ShowMultipleControls(hwndDlg, infoLineControls, SIZEOF(infoLineControls), (g_dat->flags&SMF_SHOWINFO) ? SW_SHOW : SW_HIDE); - else - ShowMultipleControls(hwndDlg, infoLineControls, SIZEOF(infoLineControls), SW_HIDE); - - if (dat->hContact) { - ShowMultipleControls(hwndDlg, buttonLineControls, SIZEOF(buttonLineControls), (g_dat->flags&SMF_SHOWBTNS) ? SW_SHOW : SW_HIDE); - if (!DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) - ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), SW_HIDE); - } - else ShowMultipleControls(hwndDlg, buttonLineControls, SIZEOF(buttonLineControls), SW_HIDE); - - ShowMultipleControls(hwndDlg, sendControls, SIZEOF(sendControls), SW_SHOW); - if (!dat->hwndStatus) { - int grip = (GetWindowLongPtr(hwndDlg, GWL_STYLE) & WS_THICKFRAME) ? SBARS_SIZEGRIP : 0; - dat->hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | grip, 0, 0, 0, 0, hwndDlg, NULL, g_hInst, NULL); - SendMessage(dat->hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON), 0); - } - - ShowWindow(GetDlgItem(hwndDlg, IDCANCEL), SW_HIDE); - ShowWindow(GetDlgItem(hwndDlg, IDC_SPLITTER), SW_SHOW); - ShowWindow(GetDlgItem(hwndDlg, IDOK), (g_dat->flags & SMF_SENDBTN) ? SW_SHOW : SW_HIDE); - EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)) != 0); - if (dat->avatarPic == NULL || !(g_dat->flags & SMF_AVATAR)) - ShowWindow(GetDlgItem(hwndDlg, IDC_AVATAR), SW_HIDE); - SendMessage(hwndDlg, DM_UPDATETITLE, 0, 0); - SendMessage(hwndDlg, WM_SIZE, 0, 0); -} - -struct MsgEditSubclassData -{ - DWORD lastEnterTime; -}; - -static void SetEditorText(HWND hwnd, const TCHAR* txt) -{ - SetWindowText(hwnd, txt); - SendMessage(hwnd, EM_SETSEL, -1, -1); -} - -#define EM_SUBCLASSED (WM_USER+0x101) -#define EM_UNSUBCLASSED (WM_USER+0x102) -#define ENTERCLICKTIME 1000 //max time in ms during which a double-tap on enter will cause a send - -static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - struct MessageWindowData *pdat = (struct MessageWindowData *)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA); - struct MsgEditSubclassData *dat = (struct MsgEditSubclassData *) GetWindowLongPtr(hwnd, GWLP_USERDATA); - - switch (msg) { - case WM_DROPFILES: - SendMessage(GetParent(hwnd), WM_DROPFILES, (WPARAM)wParam, (LPARAM)lParam); - break; - - case EM_SUBCLASSED: - dat = (struct MsgEditSubclassData *) mir_alloc(sizeof(struct MsgEditSubclassData)); - SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) dat); - dat->lastEnterTime = 0; - return 0; - - case WM_CHAR: - if (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_READONLY) - break; - - if (wParam == 1 && GetKeyState(VK_CONTROL) & 0x8000) { //ctrl-a - SendMessage(hwnd, EM_SETSEL, 0, -1); - return 0; - } - - if (wParam == 23 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w - SendMessage(GetParent(hwnd), WM_CLOSE, 0, 0); - return 0; - } - break; - - case WM_KEYDOWN: - if (wParam == VK_RETURN) - { - if (!(GetKeyState(VK_SHIFT) & 0x8000) && - ((GetKeyState(VK_CONTROL) & 0x8000) != 0) != ((g_dat->flags & SMF_SENDONENTER) != 0)) - { - PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); - return 0; - } - if (g_dat->flags & SMF_SENDONDBLENTER) - { - if (dat->lastEnterTime + ENTERCLICKTIME < GetTickCount()) - dat->lastEnterTime = GetTickCount(); - 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_INSERT && (GetKeyState(VK_SHIFT) & 0x8000)) || (wParam == 'V' && (GetKeyState(VK_CONTROL) & 0x8000))) && - !(GetKeyState(VK_MENU) & 0x8000)) // ctrl-v (paste clean text) - { - SendMessage(hwnd, WM_PASTE, 0, 0); - return 0; - } - - if (wParam == VK_UP && (GetKeyState(VK_CONTROL) & 0x8000) && - ((g_dat->flags & (SMF_AUTOCLOSE | SMF_CTRLSUPPORT)) == SMF_CTRLSUPPORT)) - { - if (pdat->cmdList->realCount) - { - if (pdat->cmdListInd < 0) - { - pdat->cmdListInd = pdat->cmdList->realCount - 1; - SetEditorText(hwnd, tcmdlist_getitem(pdat->cmdList, pdat->cmdListInd)); - } - else if (pdat->cmdListInd > 0) - { - SetEditorText(hwnd, tcmdlist_getitem(pdat->cmdList, --pdat->cmdListInd)); - } - } - EnableWindow(GetDlgItem(GetParent(hwnd), IDOK), GetWindowTextLength(hwnd) != 0); - UpdateReadChars(GetParent(hwnd), pdat->hwndStatus); - return 0; - } - else if (wParam == VK_DOWN && (GetKeyState(VK_CONTROL) & 0x8000) && - ((g_dat->flags & (SMF_AUTOCLOSE | SMF_CTRLSUPPORT)) == SMF_CTRLSUPPORT)) - { - if (pdat->cmdList->realCount && pdat->cmdListInd >= 0) - { - if (pdat->cmdListInd < (pdat->cmdList->realCount - 1)) - { - SetEditorText(hwnd, tcmdlist_getitem(pdat->cmdList, ++pdat->cmdListInd)); - } - else - { - pdat->cmdListInd = -1; - SetEditorText(hwnd, tcmdlist_getitem(pdat->cmdList, pdat->cmdList->realCount - 1)); - } - } - - EnableWindow(GetDlgItem(GetParent(hwnd), IDOK), GetWindowTextLength(hwnd) != 0); - UpdateReadChars(GetParent(hwnd), pdat->hwndStatus); - } - break; - - case WM_LBUTTONDOWN: - case WM_RBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_MOUSEWHEEL: - case WM_KILLFOCUS: - dat->lastEnterTime = 0; - break; - - case WM_SYSCHAR: - dat->lastEnterTime = 0; - if ((wParam == 's' || wParam == 'S') && GetKeyState(VK_MENU) & 0x8000) - { - PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); - return 0; - } - break; - - case WM_CONTEXTMENU: - { - HMENU hMenu; - CHARRANGE sel; - static const CHARRANGE all = {0, -1}; - - MessageWindowPopupData mwpd = {0}; - mwpd.cbSize = sizeof(mwpd); - mwpd.uType = MSG_WINDOWPOPUP_SHOWING; - mwpd.uFlags = MSG_WINDOWPOPUP_INPUT; - mwpd.hContact = pdat->hContact; - mwpd.hwnd = hwnd; - - hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)); - - mwpd.hMenu = GetSubMenu(hMenu, 2); - TranslateMenu(mwpd.hMenu); - - SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); - if (sel.cpMin == sel.cpMax) - { - EnableMenuItem(mwpd.hMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(mwpd.hMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(mwpd.hMenu, IDM_DELETE, MF_BYCOMMAND | MF_GRAYED); - } - if (!SendMessage(hwnd, EM_CANUNDO, 0, 0)) - { - EnableMenuItem(mwpd.hMenu, IDM_UNDO, MF_BYCOMMAND | MF_GRAYED); - } - if (!SendMessage(hwnd, EM_CANREDO, 0, 0)) - { - EnableMenuItem(mwpd.hMenu, IDM_REDO, MF_BYCOMMAND | MF_GRAYED); - } - if (!SendMessage(hwnd, EM_CANPASTE, 0, 0)) - { - if (!IsClipboardFormatAvailable(CF_HDROP)) - EnableMenuItem(mwpd.hMenu, IDM_PASTE, MF_BYCOMMAND | MF_GRAYED); - EnableMenuItem(mwpd.hMenu, IDM_PASTESEND, MF_BYCOMMAND | MF_GRAYED); - } - if (lParam == 0xFFFFFFFF) - { - SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&mwpd.pt, (LPARAM)sel.cpMax); - ClientToScreen(hwnd, &mwpd.pt); - } - else - { - mwpd.pt.x = GET_X_LPARAM(lParam); - mwpd.pt.y = GET_Y_LPARAM(lParam); - } - - - // First notification - NotifyEventHooks(hHookWinPopup, 0, (LPARAM)&mwpd); - - // Someone added items? - if (GetMenuItemCount(mwpd.hMenu) > 0) - { - SetCursor(LoadCursor(NULL, IDC_ARROW)); - mwpd.selection = TrackPopupMenu(mwpd.hMenu, TPM_RETURNCMD, mwpd.pt.x, mwpd.pt.y, 0, hwnd, NULL); - } - - // Second notification - mwpd.uType = MSG_WINDOWPOPUP_SELECTED; - NotifyEventHooks(hHookWinPopup, 0, (LPARAM)&mwpd); - - switch (mwpd.selection) - { - case IDM_UNDO: - SendMessage(hwnd, WM_UNDO, 0, 0); - break; - - case IDM_REDO: - SendMessage(hwnd, EM_REDO, 0, 0); - break; - - case IDM_CUT: - SendMessage(hwnd, WM_CUT, 0, 0); - break; - - case IDM_COPY: - SendMessage(hwnd, WM_COPY, 0, 0); - break; - - case IDM_PASTE: - SendMessage(hwnd, WM_PASTE, 0, 0); - break; - - case IDM_PASTESEND: - SendMessage(hwnd, EM_PASTESPECIAL, CF_TEXT, 0); - PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); - break; - - case IDM_DELETE: - SendMessage(hwnd, EM_REPLACESEL, TRUE, 0); - break; - - case IDM_SELECTALL: - SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&all); - break; - - case IDM_CLEAR: - SetWindowText(hwnd, _T( "" )); - break; - } - DestroyMenu(hMenu); - return 0; - } - - case WM_PASTE: - if (IsClipboardFormatAvailable(CF_HDROP)) - { - if (OpenClipboard(hwnd)) - { - HANDLE hDrop = GetClipboardData(CF_HDROP); - if (hDrop) - SendMessage(hwnd, WM_DROPFILES, (WPARAM)hDrop, 0); - CloseClipboard(); - } - } - else - SendMessage(hwnd, EM_PASTESPECIAL, CF_TEXT, 0); - return 0; - - case EM_UNSUBCLASSED: - mir_free(dat); - return 0; - } - return CallWindowProc(pdat->OldMessageEditProc, hwnd, msg, wParam, lParam); -} - -static LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - struct MessageWindowData *pdat = (struct MessageWindowData *)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA); - - switch (msg) { - case WM_NCHITTEST: - return HTCLIENT; - - case WM_SETCURSOR: - { - RECT rc; - GetClientRect(hwnd, &rc); - SetCursor(rc.right > rc.bottom ? hCurSplitNS : hCurSplitWE); - return TRUE; - } - - case WM_LBUTTONDOWN: - SetCapture(hwnd); - return 0; - - case WM_MOUSEMOVE: - if (GetCapture() == hwnd) { - RECT rc; - GetClientRect(hwnd, &rc); - SendMessage(GetParent(hwnd), DM_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(); - return 0; - } - return CallWindowProc(pdat->OldSplitterProc, hwnd, msg, wParam, lParam); -} - -static int MessageDialogResize(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL * urc) -{ - struct MessageWindowData *dat = (struct MessageWindowData *) lParam; - - if (!(g_dat->flags&SMF_SHOWINFO) && !(g_dat->flags&SMF_SHOWBTNS)) { - int i; - for (i = 0; i < SIZEOF(buttonLineControls); i++) - if (buttonLineControls[i] == urc->wId) - OffsetRect(&urc->rcItem, 0, -dat->lineHeight); - } - - switch (urc->wId) { - case IDC_NAME: - { - int len; - HWND h; - - h = GetDlgItem(hwndDlg, IDC_NAME); - len = GetWindowTextLength(h); - if (len > 0) { - HDC hdc; - SIZE textSize; - TCHAR buf[256]; - HFONT hFont; - - GetWindowText(h, buf, SIZEOF(buf)); - - hdc = GetDC(h); - hFont = SelectObject(hdc, (HFONT) SendMessage(GetDlgItem(hwndDlg, IDOK), WM_GETFONT, 0, 0)); - GetTextExtentPoint32(hdc, buf, lstrlen(buf), &textSize); - urc->rcItem.right = urc->rcItem.left + textSize.cx + 10; - if ((g_dat->flags&SMF_SHOWBTNS) && urc->rcItem.right > urc->dlgNewSize.cx - dat->nLabelRight) - urc->rcItem.right = urc->dlgNewSize.cx - dat->nLabelRight; - SelectObject(hdc, hFont); - ReleaseDC(h, hdc); - } - } - case IDC_PROTOCOL: - return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; - - case IDC_ADD: - case IDC_USERMENU: - case IDC_DETAILS: - case IDC_HISTORY: - return RD_ANCHORX_RIGHT | RD_ANCHORY_TOP; - - case IDC_LOG: - if (!(g_dat->flags&SMF_SHOWINFO) && !(g_dat->flags&SMF_SHOWBTNS)) - urc->rcItem.top -= dat->lineHeight; - urc->rcItem.bottom -= dat->splitterPos - dat->originalSplitterPos; - return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; - - case IDC_SPLITTER: - urc->rcItem.top -= dat->splitterPos - dat->originalSplitterPos; - urc->rcItem.bottom -= dat->splitterPos - dat->originalSplitterPos; - return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM; - - case IDC_MESSAGE: - { - if (!(g_dat->flags & SMF_SENDBTN)) - urc->rcItem.right = urc->dlgNewSize.cx - urc->rcItem.left; - if ((g_dat->flags & SMF_AVATAR) && dat->avatarPic) { - urc->rcItem.left = dat->avatarWidth+4; - } - urc->rcItem.top -= dat->splitterPos - dat->originalSplitterPos; - if (!(g_dat->flags & SMF_SENDBTN)) - return RD_ANCHORX_CUSTOM | RD_ANCHORY_BOTTOM; - return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM; - } - - case IDCANCEL: - case IDOK: - urc->rcItem.top -= dat->splitterPos - dat->originalSplitterPos; - return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; - - case IDC_AVATAR: - urc->rcItem.top=urc->rcItem.bottom-(dat->avatarHeight + 2); - urc->rcItem.right=urc->rcItem.left+(dat->avatarWidth + 2); - return RD_ANCHORX_LEFT|RD_ANCHORY_BOTTOM; - } - return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; -} - -void ShowAvatar(HWND hwndDlg, struct MessageWindowData *dat) -{ - if (g_dat->flags & SMF_AVATAR) - { - AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)dat->hContact, 0); - if (ace && (INT_PTR)ace != CALLSERVICE_NOTFOUND && (ace->dwFlags & AVS_BITMAP_VALID) && !(ace->dwFlags & AVS_HIDEONCLIST)) - dat->avatarPic = ace->hbmPic; - else - dat->avatarPic = NULL; - } - else - dat->avatarPic = NULL; - - SendMessage(hwndDlg, DM_UPDATESIZEBAR, 0, 0); - SendMessage(hwndDlg, DM_AVATARSIZECHANGE, 0, 0); -} - -static void NotifyTyping(struct MessageWindowData *dat, int mode) -{ - DWORD protoStatus; - DWORD protoCaps; - DWORD typeCaps; - - if (!dat->hContact) - return; - // Don't send to protocols who don't support typing - // Don't send to users who are unchecked in the typing notification options - // Don't send to protocols that are offline - // Don't send to users who are not visible and - // Don't send to users who are not on the visible list when you are in invisible mode. - - if (!DBGetContactSettingByte(dat->hContact, SRMMMOD, SRMSGSET_TYPING, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW))) - return; - - if (!dat->szProto) - return; - - protoStatus = CallProtoService(dat->szProto, PS_GETSTATUS, 0, 0); - protoCaps = CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_1, 0); - typeCaps = CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_4, 0); - - if (!(typeCaps & PF4_SUPPORTTYPING)) - return; - - if (protoStatus < ID_STATUS_ONLINE) - return; - - if (protoCaps & PF1_VISLIST && DBGetContactSettingWord(dat->hContact, dat->szProto, "ApparentMode", 0) == ID_STATUS_OFFLINE) - return; - - if (protoCaps & PF1_INVISLIST && protoStatus == ID_STATUS_INVISIBLE && DBGetContactSettingWord(dat->hContact, dat->szProto, "ApparentMode", 0) != ID_STATUS_ONLINE) - return; - - if (!(g_dat->flags & SMF_TYPINGUNKNOWN) && DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) - return; - - // End user check - dat->nTypeMode = mode; - CallService(MS_PROTO_SELFISTYPING, (WPARAM) dat->hContact, dat->nTypeMode); -} - -void Button_SetIcon_IcoLib(HWND hwndDlg, int itemId, int iconId, const char* tooltip) -{ - HWND hWnd = GetDlgItem( hwndDlg, itemId ); - SendMessage( hWnd, BM_SETIMAGE, IMAGE_ICON, ( LPARAM )LoadSkinnedIcon( iconId )); - SendMessage( hWnd, BUTTONSETASFLATBTN, TRUE, 0 ); - SendMessage( hWnd, BUTTONADDTOOLTIP, (WPARAM)tooltip, 0); -} - -void Button_FreeIcon_IcoLib(HWND hwndDlg, int itemId) -{ - HICON hIcon = ( HICON )SendDlgItemMessage(hwndDlg, itemId, BM_SETIMAGE, IMAGE_ICON, 0 ); - CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); -} - -void Window_FreeIcon_IcoLib(HWND hwndDlg) -{ - HICON hIcon = (HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0); - CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); - - hIcon = (HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0); - CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); -} - -INT_PTR CALLBACK DlgProcMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - struct MessageWindowData *dat; - - dat = (struct MessageWindowData *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - switch (msg) - { - case WM_INITDIALOG: - { - struct NewMessageWindowLParam *newData = (struct NewMessageWindowLParam *) lParam; - TranslateDialogDefault(hwndDlg); - dat = (struct MessageWindowData *) mir_calloc(sizeof(struct MessageWindowData)); - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) dat); - - dat->hContact = newData->hContact; - dat->hTimeZone = tmi.createByContact(dat->hContact, TZF_KNOWNONLY); - dat->wMinute = 61; - - NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPENING); - if (newData->szInitialText) - { - int len; - - if(newData->isWchar) - SetDlgItemText(hwndDlg, IDC_MESSAGE, (TCHAR *)newData->szInitialText); - else - - SetDlgItemTextA(hwndDlg, IDC_MESSAGE, newData->szInitialText); - len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)); - PostMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), EM_SETSEL, len, len); - } - - dat->szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) dat->hContact, 0); - RichUtil_SubClass(GetDlgItem(hwndDlg, IDC_LOG)); - RichUtil_SubClass(GetDlgItem(hwndDlg, IDC_MESSAGE)); - - // avatar stuff - dat->limitAvatarH = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, SRMSGDEFSET_LIMITAVHEIGHT)?DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, SRMSGDEFSET_AVHEIGHT):0; - - if (dat->hContact && dat->szProto != NULL) - dat->wStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE); - else - dat->wStatus = ID_STATUS_OFFLINE; - dat->wOldStatus = dat->wStatus; - dat->splitterPos = (int) DBGetContactSettingDword(DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)?dat->hContact:NULL, SRMMMOD, "splitterPos", (DWORD) - 1); - dat->cmdList = li.List_Create(0, 20); - dat->cmdListInd = -1; - dat->nTypeMode = PROTOTYPE_SELFTYPING_OFF; - SetTimer(hwndDlg, TIMERID_TYPE, 1000, NULL); - { - RECT rc, rc2; - GetWindowRect(GetDlgItem(hwndDlg, IDC_USERMENU), &rc); - GetWindowRect(hwndDlg, &rc2); - dat->nLabelRight = rc2.right - rc.left; - } - { - RECT rc; - POINT pt; - GetWindowRect(GetDlgItem(hwndDlg, IDC_SPLITTER), &rc); - pt.y = (rc.top + rc.bottom) / 2; - pt.x = 0; - ScreenToClient(hwndDlg, &pt); - dat->originalSplitterPos = pt.y; - if (dat->splitterPos == -1) - dat->splitterPos = dat->originalSplitterPos;// + 60; - GetWindowRect(GetDlgItem(hwndDlg, IDC_ADD), &rc); - dat->lineHeight = rc.bottom - rc.top + 3; - } - WindowList_Add(g_dat->hMessageWindowList, hwndDlg, dat->hContact); - GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &dat->minEditInit); - SendMessage(hwndDlg, DM_UPDATESIZEBAR, 0, 0); - dat->hwndStatus = NULL; - Button_SetIcon_IcoLib(hwndDlg, IDC_ADD, SKINICON_OTHER_ADDCONTACT, "Add Contact Permanently to List" ); - Button_SetIcon_IcoLib(hwndDlg, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, "View User's Details" ); - Button_SetIcon_IcoLib(hwndDlg, IDC_HISTORY, SKINICON_OTHER_HISTORY, "View User's History" ); - Button_SetIcon_IcoLib(hwndDlg, IDC_USERMENU, SKINICON_OTHER_DOWNARROW, "User Menu" ); - SendDlgItemMessage(hwndDlg, IDC_NAME, BUTTONSETASFLATBTN, TRUE, 0 ); - - EnableWindow(GetDlgItem(hwndDlg, IDC_PROTOCOL), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_AVATAR), FALSE); - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETOLECALLBACK, 0, (LPARAM) & reOleCallback); - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_LINK | ENM_SCROLL); - /* duh, how come we didnt use this from the start? */ - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_AUTOURLDETECT, (WPARAM) TRUE, 0); - if (dat->hContact && dat->szProto) { - int nMax; - nMax = CallProtoService(dat->szProto, PS_GETCAPS, PFLAG_MAXLENOFMESSAGE, (LPARAM) dat->hContact); - if (nMax) - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_LIMITTEXT, (WPARAM) nMax, 0); - /* get around a lame bug in the Windows template resource code where richedits are limited to 0x7FFF */ - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_LIMITTEXT, (WPARAM) sizeof(TCHAR) * 0x7FFFFFFF, 0); - } - - dat->OldMessageEditProc = (WNDPROC) SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE), GWLP_WNDPROC, (LONG_PTR) MessageEditSubclassProc); - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SUBCLASSED, 0, 0); - dat->OldSplitterProc = (WNDPROC) SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTER), GWLP_WNDPROC, (LONG_PTR) SplitterSubclassProc); - - if (dat->hContact) - { - int historyMode = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, SRMSGDEFSET_LOADHISTORY); - // This finds the first message to display, it works like shit - dat->hDbEventFirst = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) dat->hContact, 0); - switch (historyMode) - { - case LOADHISTORY_COUNT: - { - int i; - HANDLE hPrevEvent; - DBEVENTINFO dbei = { 0 }; - dbei.cbSize = sizeof(dbei); - for (i = DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADCOUNT, SRMSGDEFSET_LOADCOUNT); i--; ) - { - if (dat->hDbEventFirst == NULL) - hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->hContact, 0); - else - hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) dat->hDbEventFirst, 0); - if (hPrevEvent == NULL) - break; - - dbei.cbBlob = 0; - dat->hDbEventFirst = hPrevEvent; - CallService(MS_DB_EVENT_GET, (WPARAM) hPrevEvent, (LPARAM) &dbei); - if (!DbEventIsShown(&dbei, dat)) - i++; - } - break; - } - case LOADHISTORY_TIME: - { - HANDLE hPrevEvent; - DBEVENTINFO dbei = { 0 }; - DWORD firstTime; - - dbei.cbSize = sizeof(dbei); - if (dat->hDbEventFirst == NULL) - dbei.timestamp = (DWORD)time(NULL); - else - CallService(MS_DB_EVENT_GET, (WPARAM) dat->hDbEventFirst, (LPARAM) & dbei); - firstTime = dbei.timestamp - 60 * DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, SRMSGDEFSET_LOADTIME); - for (;;) - { - if (dat->hDbEventFirst == NULL) - hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->hContact, 0); - else - hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) dat->hDbEventFirst, 0); - if (hPrevEvent == NULL) - break; - dbei.cbBlob = 0; - CallService(MS_DB_EVENT_GET, (WPARAM) hPrevEvent, (LPARAM) & dbei); - if (dbei.timestamp < firstTime) - break; - dat->hDbEventFirst = hPrevEvent; - } - break; - } - } - } - - { - DBEVENTINFO dbei = { 0 }; - HANDLE hdbEvent; - - dbei.cbSize = sizeof(dbei); - hdbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->hContact, 0); - if (hdbEvent) - { - do { - ZeroMemory(&dbei, sizeof(dbei)); - dbei.cbSize = sizeof(dbei); - CallService(MS_DB_EVENT_GET, (WPARAM) hdbEvent, (LPARAM) & dbei); - if (( dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei)) && !(dbei.flags & DBEF_SENT)) { - dat->lastMessage = dbei.timestamp; - PostMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0); - break; - } - } - while (hdbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) hdbEvent, 0)); - } - } - - SendMessage(hwndDlg, DM_OPTIONSAPPLIED, 1, 0); - - //restore saved msg if any... - if (dat->hContact) - { - DBVARIANT dbv; - if (!DBGetContactSettingTString(dat->hContact, SRMSGMOD, DBSAVEDMSG, &dbv)) - { - if (dbv.ptszVal[0]) - { - SetDlgItemText(hwndDlg, IDC_MESSAGE, dbv.ptszVal); - EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE); - UpdateReadChars(hwndDlg, dat->hwndStatus); - PostMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), EM_SETSEL, -1, -1); - } - DBFreeVariant(&dbv); - } - } - - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETEVENTMASK, 0, ENM_CHANGE); - - { - int flag = newData->noActivate ? RWPF_HIDDEN : 0; - int savePerContact = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT); - if (Utils_RestoreWindowPositionEx(hwndDlg, flag, savePerContact ? dat->hContact : NULL, SRMMMOD, "")) { - if (savePerContact) { - if (Utils_RestoreWindowPositionEx(hwndDlg, flag | RWPF_NOMOVE, NULL, SRMMMOD, "")) - SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW); - } - else - SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW); - } - if (!savePerContact && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CASCADE, SRMSGDEFSET_CASCADE)) - WindowList_Broadcast(g_dat->hMessageWindowList, DM_CASCADENEWWINDOW, (WPARAM) hwndDlg, (LPARAM) & dat->windowWasCascaded); - } - if (newData->noActivate) - { - SetWindowPos(hwndDlg, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW); - SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL); - } - else - { - SetWindowPos(hwndDlg, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); - SetForegroundWindow(hwndDlg); - SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); - } - - SendMessage(hwndDlg, DM_GETAVATAR, 0, 0); - - NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPEN); - return FALSE; - } - - case WM_CONTEXTMENU: - if (dat->hwndStatus && dat->hwndStatus == (HWND) wParam) { - POINT pt, pt2; - HMENU hMenu; - RECT rc; - - GetCursorPos(&pt); - pt2.x = pt.x; pt2.y = pt.y; - ScreenToClient(dat->hwndStatus, &pt); - - // no popup menu for status icons - this is handled via NM_RCLICK notification and the plugins that added the icons - SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 1, (LPARAM)&rc); - if (pt.x >= rc.left) break; - - hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) dat->hContact, 0); - - TrackPopupMenu(hMenu, 0, pt2.x, pt2.y, 0, hwndDlg, NULL); - DestroyMenu(hMenu); - } - break; - - // Mod from tabsrmm - case WM_DROPFILES: - if (dat->szProto==NULL) break; - if (!(CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_1,0)&PF1_FILESEND)) break; - if (dat->wStatus==ID_STATUS_OFFLINE) break; - if (dat->hContact!=NULL) { - TCHAR szFilename[MAX_PATH]; - HDROP hDrop = (HDROP)wParam; - int fileCount = DragQueryFile(hDrop,-1,NULL,0), totalCount = 0, i; - TCHAR** ppFiles = NULL; - for ( i=0; i < fileCount; i++ ) { - DragQueryFile(hDrop, i, szFilename, SIZEOF(szFilename)); - AddToFileList(&ppFiles, &totalCount, szFilename); - } - CallServiceSync(MS_FILE_SENDSPECIFICFILEST, (WPARAM)dat->hContact, (LPARAM)ppFiles); - for(i=0;ppFiles[i];i++) mir_free(ppFiles[i]); - mir_free(ppFiles); - } - break; - - case HM_AVATARACK: - ShowAvatar(hwndDlg, dat); - break; - - case DM_AVATARCALCSIZE: - { - BITMAP bminfo; - - if (dat->avatarPic == NULL || !(g_dat->flags&SMF_AVATAR)) - { - dat->avatarWidth=50; - dat->avatarHeight=50; - ShowWindow(GetDlgItem(hwndDlg, IDC_AVATAR), SW_HIDE); - return 0; - } - GetObject(dat->avatarPic, sizeof(bminfo), &bminfo); - dat->avatarWidth=bminfo.bmWidth+2; - dat->avatarHeight=bminfo.bmHeight+2; - if (dat->limitAvatarH&&dat->avatarHeight>dat->limitAvatarH) { - dat->avatarWidth = bminfo.bmWidth * dat->limitAvatarH / bminfo.bmHeight + 2; - dat->avatarHeight = dat->limitAvatarH + 2; - } - ShowWindow(GetDlgItem(hwndDlg, IDC_AVATAR), SW_SHOW); - } - break; - - case DM_UPDATESIZEBAR: - dat->minEditBoxSize.cx = dat->minEditInit.right - dat->minEditInit.left; - dat->minEditBoxSize.cy = dat->minEditInit.bottom - dat->minEditInit.top; - if(g_dat->flags&SMF_AVATAR) { - SendMessage(hwndDlg, DM_AVATARCALCSIZE, 0, 0); - if(dat->avatarPic && dat->minEditBoxSize.cy <= dat->avatarHeight) - dat->minEditBoxSize.cy = dat->avatarHeight; - } - break; - - case DM_AVATARSIZECHANGE: - { - RECT rc; - GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &rc); - if (rc.bottom-rc.topminEditBoxSize.cy) { - SendMessage(hwndDlg, DM_SPLITTERMOVED, rc.top-(rc.bottom-rc.top-dat->minEditBoxSize.cy-4), (LPARAM) GetDlgItem(hwndDlg, IDC_SPLITTER)); - } - SendMessage(hwndDlg, WM_SIZE, 0, 0); - } - break; - - case DM_GETAVATAR: - { - PROTO_AVATAR_INFORMATIONT ai = { sizeof(ai), dat->hContact }; - CallProtoService(dat->szProto, PS_GETAVATARINFOT, GAIF_FORCE, (LPARAM)&ai); - - ShowAvatar(hwndDlg, dat); - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 1); - } - break; - - case DM_TYPING: - dat->nTypeSecs = (INT_PTR)lParam > 0 ? (int)lParam : 0; - break; - - case DM_UPDATEWINICON: - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON)) { - WORD wStatus; - - Window_FreeIcon_IcoLib(hwndDlg); - - if (dat->szProto) { - wStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE); - SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) LoadSkinnedProtoIconBig(dat->szProto, wStatus)); - SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM) LoadSkinnedProtoIcon(dat->szProto, wStatus)); - break; - } - } - SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) LoadSkinnedIconBig(SKINICON_EVENT_MESSAGE)); - SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM) LoadSkinnedIcon(SKINICON_EVENT_MESSAGE)); - break; - - case DM_USERNAMETOCLIP: - if (dat->hContact) - { - TCHAR buf[128] = _T(""); - CONTACTINFO ci = {0}; - ci.cbSize = sizeof(ci); - ci.hContact = dat->hContact; - ci.szProto = dat->szProto; - ci.dwFlag = CNF_UNIQUEID | CNF_TCHAR; - if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) - { - switch (ci.type) - { - case CNFT_ASCIIZ: - mir_sntprintf(buf, SIZEOF(buf), _T("%s"), ci.pszVal); - mir_free(ci.pszVal); - break; - - case CNFT_DWORD: - mir_sntprintf(buf, SIZEOF(buf), _T("%u"), ci.dVal); - break; - } - } - if (buf[0] && OpenClipboard(hwndDlg)) - { - HGLOBAL hData; - - EmptyClipboard(); - hData = GlobalAlloc(GMEM_MOVEABLE, _tcslen(buf) * sizeof(TCHAR) + 1); - _tcscpy(GlobalLock(hData), buf); - GlobalUnlock(hData); - SetClipboardData(CF_UNICODETEXT, hData); - CloseClipboard(); - } - } - break; - - case DM_UPDATELASTMESSAGE: - if (!dat->hwndStatus || dat->nTypeSecs) - break; - - if (dat->lastMessage) - { - TCHAR date[64], time[64], fmt[128]; - - tmi.printTimeStamp(NULL, dat->lastMessage, _T("d"), date, SIZEOF(date), 0); - tmi.printTimeStamp(NULL, dat->lastMessage, _T("t"), time, SIZEOF(time), 0); - mir_sntprintf(fmt, SIZEOF(fmt), TranslateT("Last message received on %s at %s."), date, time); - SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM) fmt); - } - else { - SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM) _T("")); - } - SendMessage(dat->hwndStatus, SB_SETICON, 0, (LPARAM) NULL); - break; - - case DM_OPTIONSAPPLIED: - SetDialogToType(hwndDlg); - if (dat->hBkgBrush) - DeleteObject(dat->hBkgBrush); - { - COLORREF colour = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR); - dat->hBkgBrush = CreateSolidBrush(colour); - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETBKGNDCOLOR, 0, colour); - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETBKGNDCOLOR, 0, colour); - } - { // avatar stuff - dat->avatarPic = NULL; - dat->limitAvatarH = 0; - if (CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_AVATARS) - { - dat->limitAvatarH = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, SRMSGDEFSET_LIMITAVHEIGHT) ? - DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, SRMSGDEFSET_AVHEIGHT) : 0; - } - if (!wParam) SendMessage(hwndDlg, DM_GETAVATAR, 0, 0); - } - InvalidateRect(GetDlgItem(hwndDlg, IDC_MESSAGE), NULL, FALSE); - { - HFONT hFont; - LOGFONT lf; - CHARFORMAT cf = {0}; - hFont = (HFONT) SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_GETFONT, 0, 0); - if (hFont != NULL && hFont != (HFONT) SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0)) - DeleteObject(hFont); - LoadMsgDlgFont(MSGFONTID_MESSAGEAREA, &lf, &cf.crTextColor); - hFont = CreateFontIndirect(&lf); - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_SETFONT, (WPARAM) hFont, MAKELPARAM(TRUE, 0)); - - cf.cbSize = sizeof(CHARFORMAT); - cf.dwMask = CFM_COLOR; - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_ALL, (WPARAM) &cf); - } - - /* - * configure message history for proper RTL formatting - */ - - { - PARAFORMAT2 pf2; - ZeroMemory((void *)&pf2, sizeof(pf2)); - pf2.cbSize = sizeof(pf2); - - pf2.wEffects = PFE_RTLPARA; - pf2.dwMask = PFM_RTLPARA; - SetDlgItemText(hwndDlg, IDC_LOG, _T("")); - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETPARAFORMAT, 0, (LPARAM)&pf2); - pf2.wEffects = 0; - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETPARAFORMAT, 0, (LPARAM)&pf2); - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETLANGOPTIONS, 0, (LPARAM) SendDlgItemMessage(hwndDlg, IDC_LOG, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD); - } - SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); - SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0); - break; - - case DM_UPDATETITLE: - { - TCHAR newtitle[256], oldtitle[256], *szStatus; - TCHAR *contactName, *pszNewTitleEnd; - DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) wParam; - - pszNewTitleEnd = _T("Message Session"); - if (dat->hContact) - { - if (dat->szProto) - { - TCHAR buf[128] = _T(""); - int statusIcon = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON); - - dat->wStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE); - contactName = ( TCHAR* )CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) dat->hContact, GCDNF_TCHAR); - - if (strcmp(dat->szProto, "MetaContacts")) - { - CONTACTINFO ci = {0}; - ci.cbSize = sizeof(ci); - ci.hContact = dat->hContact; - ci.szProto = dat->szProto; - ci.dwFlag = CNF_DISPLAYUID | CNF_TCHAR; - if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) { - switch (ci.type) { - case CNFT_ASCIIZ: - mir_sntprintf(buf, SIZEOF(buf), _T("%s"), (TCHAR*)ci.pszVal); - mir_free(ci.pszVal); - break; - case CNFT_DWORD: - mir_sntprintf(buf, SIZEOF(buf), _T("%u"), ci.dVal); - break; - } - } - } - if (buf[0]) - SetDlgItemText(hwndDlg, IDC_NAME, buf); - else - SetDlgItemText(hwndDlg, IDC_NAME, contactName); - - szStatus = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, dat->szProto == NULL ? ID_STATUS_OFFLINE : DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE), GSMDF_TCHAR); - if (statusIcon) - mir_sntprintf(newtitle, SIZEOF(newtitle), _T("%s - %s"), contactName, TranslateTS(pszNewTitleEnd)); - else - mir_sntprintf(newtitle, SIZEOF(newtitle), _T("%s (%s): %s"), contactName, szStatus, TranslateTS(pszNewTitleEnd)); - - if (!cws || (!strcmp(cws->szModule, dat->szProto) && !strcmp(cws->szSetting, "Status"))) - { - InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOCOL), NULL, TRUE); - if (statusIcon) - SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0); - } - - // log - if ((dat->wStatus != dat->wOldStatus || lParam != 0) && - DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, SRMSGDEFSET_SHOWSTATUSCH)) - { - DBEVENTINFO dbei; - TCHAR buffer[200]; - HANDLE hNewEvent; - int iLen; - - TCHAR *szOldStatus = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM) dat->wOldStatus, GSMDF_TCHAR); - TCHAR *szNewStatus = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM) dat->wStatus, GSMDF_TCHAR); - - if (dat->wStatus == ID_STATUS_OFFLINE) - { - iLen = mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("signed off (was %s)"), szOldStatus); - SendMessage(hwndDlg, DM_TYPING, 0, 0); - } - else if (dat->wOldStatus == ID_STATUS_OFFLINE) - iLen = mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("signed on (%s)"), szNewStatus); - else - iLen = mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("is now %s (was %s)"), szNewStatus, szOldStatus); - - { - char* blob = ( char* )alloca(1000); - int ansiLen = WideCharToMultiByte(CP_ACP, 0, buffer, -1, blob, 1000, 0, 0); - memcpy( blob+ansiLen, buffer, sizeof(TCHAR)*(iLen+1)); - dbei.cbBlob = ansiLen + sizeof(TCHAR)*(iLen+1); - dbei.cbSize = sizeof(dbei); - dbei.pBlob = (PBYTE) blob; - dbei.eventType = EVENTTYPE_STATUSCHANGE; - dbei.flags = 0; - dbei.timestamp = (DWORD)time(NULL); - dbei.szModule = dat->szProto; - hNewEvent = (HANDLE) CallService(MS_DB_EVENT_ADD, (WPARAM) dat->hContact, (LPARAM) & dbei); - if (dat->hDbEventFirst == NULL) - { - dat->hDbEventFirst = hNewEvent; - SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); - } - } - } - dat->wOldStatus = dat->wStatus; - } - } - else lstrcpyn(newtitle, pszNewTitleEnd, SIZEOF(newtitle)); - - GetWindowText(hwndDlg, oldtitle, SIZEOF(oldtitle)); - if ( _tcscmp(newtitle, oldtitle )) { //swt() flickers even if the title hasn't actually changed - SetWindowText(hwndDlg, newtitle); - SendMessage(hwndDlg, WM_SIZE, 0, 0); - } - break; - } - - case DM_NEWTIMEZONE: - dat->hTimeZone = tmi.createByContact(dat->hContact, TZF_KNOWNONLY); - dat->wMinute = 61; - SendMessage(hwndDlg, WM_SIZE, 0, 0); - break; - - case DM_GETWINDOWSTATE: - { - UINT state = 0; - - state |= MSG_WINDOW_STATE_EXISTS; - if (IsWindowVisible(hwndDlg)) - state |= MSG_WINDOW_STATE_VISIBLE; - if (GetForegroundWindow()==hwndDlg) - state |= MSG_WINDOW_STATE_FOCUS; - if (IsIconic(hwndDlg)) - state |= MSG_WINDOW_STATE_ICONIC; - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, state); - return TRUE; - - } - - case DM_CASCADENEWWINDOW: - if ((HWND) wParam == hwndDlg) - break; - { - RECT rcThis, rcNew; - GetWindowRect(hwndDlg, &rcThis); - GetWindowRect((HWND) wParam, &rcNew); - if (abs(rcThis.left - rcNew.left) < 3 && abs(rcThis.top - rcNew.top) < 3) { - int offset = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME); - SetWindowPos((HWND) wParam, 0, rcNew.left + offset, rcNew.top + offset, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE); - *(int *) lParam = 1; - } - } - break; - - case WM_ACTIVATE: - if (LOWORD(wParam) != WA_ACTIVE) - break; - - SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); - //fall through - - case WM_MOUSEACTIVATE: - if (KillTimer(hwndDlg, TIMERID_FLASHWND)) - FlashWindow(hwndDlg, FALSE); - break; - - case WM_GETMINMAXINFO: - { - MINMAXINFO* mmi = (MINMAXINFO *) lParam; - RECT rcWindow, rcLog; - GetWindowRect(hwndDlg, &rcWindow); - GetWindowRect(GetDlgItem(hwndDlg, IDC_LOG), &rcLog); - mmi->ptMinTrackSize.x = rcWindow.right - rcWindow.left - ((rcLog.right - rcLog.left) - dat->minEditBoxSize.cx); - mmi->ptMinTrackSize.y = rcWindow.bottom - rcWindow.top - ((rcLog.bottom - rcLog.top) - dat->minEditBoxSize.cy); - return 0; - } - - case WM_SIZE: - { - UTILRESIZEDIALOG urd = {0}; - BOOL bottomScroll = TRUE; - - if (IsIconic(hwndDlg)) - break; - - if (dat->hwndStatus) - { - SendMessage(dat->hwndStatus, WM_SIZE, 0, 0); - SetupStatusBar(hwndDlg, dat); - } - - if (GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LOG), GWL_STYLE) & WS_VSCROLL) - { - SCROLLINFO si = {0}; - si.cbSize = sizeof(si); - si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; - GetScrollInfo(GetDlgItem(hwndDlg, IDC_LOG), SB_VERT, &si); - bottomScroll = (si.nPos + (int)si.nPage + 5) >= si.nMax; - } - - urd.cbSize = sizeof(urd); - urd.hInstance = g_hInst; - urd.hwndDlg = hwndDlg; - urd.lParam = (LPARAM) dat; - urd.lpTemplate = MAKEINTRESOURCEA(IDD_MSG); - urd.pfnResizer = MessageDialogResize; - CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM) & urd); - - // The statusbar sometimes draws over these 2 controls so - // redraw them - if (dat->hwndStatus) - { - RedrawWindow(GetDlgItem(hwndDlg, IDOK), NULL, NULL, RDW_INVALIDATE); - RedrawWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), NULL, NULL, RDW_INVALIDATE); - } - if ((g_dat->flags & SMF_AVATAR) && dat->avatarPic) - RedrawWindow(GetDlgItem(hwndDlg, IDC_AVATAR), NULL, NULL, RDW_INVALIDATE); - - if (bottomScroll) - PostMessage(hwndDlg, DM_SCROLLLOGTOBOTTOM, 0, 0); - break; - } - - case DM_SPLITTERMOVED: - { - if ((HWND) lParam == GetDlgItem(hwndDlg, IDC_SPLITTER)) - { - POINT pt; - RECT rc; - RECT rcLog; - int oldSplitterY; - HWND hwndLog = GetDlgItem(hwndDlg, IDC_LOG); - - GetClientRect(hwndDlg, &rc); - GetWindowRect(hwndLog, &rcLog); - - pt.x = 0; - pt.y = wParam; - ScreenToClient(hwndDlg, &pt); - - oldSplitterY = dat->splitterPos; - dat->splitterPos = rc.bottom - pt.y + 23; - GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &rc); - if (rc.bottom - rc.top + (dat->splitterPos - oldSplitterY) < dat->minEditBoxSize.cy) - dat->splitterPos = oldSplitterY + dat->minEditBoxSize.cy - (rc.bottom - rc.top); - if (rcLog.bottom - rcLog.top - (dat->splitterPos - oldSplitterY) < dat->minEditBoxSize.cy) - dat->splitterPos = oldSplitterY - dat->minEditBoxSize.cy + (rcLog.bottom - rcLog.top); - - SendMessage(hwndDlg, WM_SIZE, 0, 0); - } - } - break; - - case DM_REMAKELOG: - StreamInEvents(hwndDlg, dat->hDbEventFirst, -1, 0); - break; - - case DM_APPENDTOLOG: //takes wParam=hDbEvent - StreamInEvents(hwndDlg, (HANDLE) wParam, 1, 1); - break; - - case DM_SCROLLLOGTOBOTTOM: - { - HWND hwndLog = GetDlgItem(hwndDlg, IDC_LOG); - if (GetWindowLongPtr(hwndLog, GWL_STYLE) & WS_VSCROLL) - { - SCROLLINFO si = {0}; - si.cbSize = sizeof(si); - si.fMask = SIF_PAGE | SIF_RANGE; - GetScrollInfo(hwndLog, SB_VERT, &si); - si.fMask = SIF_POS; - si.nPos = si.nMax - si.nPage; - SetScrollInfo(hwndLog, SB_VERT, &si, TRUE); - SendMessage(hwndLog, WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, 0), 0); - } - } - break; - - case HM_DBEVENTADDED: - if ((HANDLE) wParam != dat->hContact) - break; - { - DBEVENTINFO dbei = { 0 }; - - dbei.cbSize = sizeof(dbei); - CallService(MS_DB_EVENT_GET, lParam, (LPARAM) & dbei); - if (dat->hDbEventFirst == NULL) - dat->hDbEventFirst = (HANDLE) lParam; - if (DbEventIsShown(&dbei, dat) && !(dbei.flags & DBEF_READ)) - { - if ((dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei)) && !(dbei.flags & DBEF_SENT)) - { - if (GetForegroundWindow() == hwndDlg) - SkinPlaySound("RecvMsgActive"); - else - SkinPlaySound("RecvMsgInactive"); - } - if (( dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei)) && dat->hwndStatus && !(dbei.flags & DBEF_SENT)) - { - dat->lastMessage = dbei.timestamp; - SendMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0); - } - if ((HANDLE) lParam != dat->hDbEventFirst && (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, lParam, 0) == NULL) - SendMessage(hwndDlg, DM_APPENDTOLOG, lParam, 0); - else - SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); - - if (!(dbei.flags & DBEF_SENT) && dbei.eventType != EVENTTYPE_STATUSCHANGE) - { - if (GetActiveWindow() == hwndDlg && GetForegroundWindow() == hwndDlg) - { - HWND hwndLog = GetDlgItem(hwndDlg, IDC_LOG); - if (GetWindowLongPtr(hwndLog, GWL_STYLE) & WS_VSCROLL) - { - SCROLLINFO si = {0}; - si.cbSize = sizeof(si); - si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; - GetScrollInfo(hwndLog, SB_VERT, &si); - if ((si.nPos + (int)si.nPage + 5) < si.nMax) - SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL); - } - } - else - SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL); - } - } - } - break; - - case WM_TIMECHANGE: - PostMessage(hwndDlg, DM_NEWTIMEZONE, 0, 0); - PostMessage(hwndDlg, DM_REMAKELOG, 0, 0); - break; - - case WM_TIMER: - if (wParam == TIMERID_FLASHWND) - { - FlashWindow(hwndDlg, TRUE); - if (dat->nFlash > 2 * g_dat->nFlashMax) - { - KillTimer(hwndDlg, TIMERID_FLASHWND); - FlashWindow(hwndDlg, FALSE); - dat->nFlash = 0; - } - dat->nFlash++; - } - else if (wParam == TIMERID_TYPE) - { - ShowTime(dat); - if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON && GetTickCount() - dat->nLastTyping > TIMEOUT_TYPEOFF) - NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); - - if (dat->showTyping) - { - if (dat->nTypeSecs) - { - dat->nTypeSecs--; - if (GetForegroundWindow() == hwndDlg) - SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0); - } - else - { - SendMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0); - if (g_dat->flags & SMF_SHOWTYPINGWIN) - SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0); - dat->showTyping = 0; - } - } - else - { - if (dat->nTypeSecs) - { - TCHAR szBuf[256]; - TCHAR* szContactName = (TCHAR*) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) dat->hContact, GCDNF_TCHAR); - HICON hTyping = LoadSkinnedIcon(SKINICON_OTHER_TYPING); - - mir_sntprintf(szBuf, SIZEOF(szBuf), TranslateT("%s is typing a message..."), szContactName); - dat->nTypeSecs--; - - SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM) szBuf); - SendMessage(dat->hwndStatus, SB_SETICON, 0, (LPARAM) hTyping); - if ((g_dat->flags & SMF_SHOWTYPINGWIN) && GetForegroundWindow() != hwndDlg) - { - HICON hIcon = (HICON)SendMessage(hwndDlg, WM_GETICON, ICON_SMALL, 0); - SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)hTyping ); - CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); - } - dat->showTyping = 1; - } - } - } - break; - - case WM_MEASUREITEM: - { - LPMEASUREITEMSTRUCT mis = (LPMEASUREITEMSTRUCT) lParam; - if (mis->CtlType == ODT_MENU) - return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); - } - break; - - case WM_DRAWITEM: - { - LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam; - if (dis->CtlType == ODT_MENU) - return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); - else if (dis->hwndItem == dat->hwndStatus) - { - DrawStatusIcons(dat->hContact, dis->hDC, dis->rcItem, 2); - return TRUE; - } - else if (dis->CtlID == IDC_PROTOCOL) - { - if (dat->szProto) - { - HICON hIcon; - int dwStatus; - - dwStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE); - hIcon = LoadSkinnedProtoIcon(dat->szProto, dwStatus); - if (hIcon) - { - if (DBGetContactSettingDword(dat->hContact, dat->szProto, "IdleTS", 0)) - { - HIMAGELIST hImageList; - - hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON), IsWinVerXPPlus()? ILC_COLOR32 | ILC_MASK : ILC_COLOR16 | ILC_MASK, 1, 0); - ImageList_AddIcon(hImageList, hIcon); - ImageList_DrawEx(hImageList, 0, dis->hDC, dis->rcItem.left, dis->rcItem.top, 0, 0, CLR_NONE, CLR_NONE, ILD_SELECTED); - ImageList_Destroy(hImageList); - } - else - DrawIconEx(dis->hDC, dis->rcItem.left, dis->rcItem.top, hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL); - CallService(MS_SKIN2_RELEASEICON,(WPARAM)hIcon, 0); - return TRUE; - } - } - } - else if (dis->CtlID == IDC_AVATAR && dat->avatarPic && (g_dat->flags & SMF_AVATAR)) - { - BITMAP bminfo; - HPEN hPen, hOldPen; - - hPen = CreatePen(PS_SOLID, 1, RGB(0,0,0)); - hOldPen = SelectObject(dis->hDC, hPen); - Rectangle(dis->hDC, 0, 0, dat->avatarWidth, dat->avatarHeight); - SelectObject(dis->hDC,hOldPen); - DeleteObject(hPen); - GetObject(dat->avatarPic, sizeof(bminfo), &bminfo); - { - HDC hdcMem = CreateCompatibleDC(dis->hDC); - HBITMAP hbmMem = (HBITMAP)SelectObject(hdcMem, dat->avatarPic); - { - SetStretchBltMode(dis->hDC, HALFTONE); - StretchBlt(dis->hDC, 1, 1, dat->avatarWidth-2, dat->avatarHeight-2, hdcMem, 0, 0, - bminfo.bmWidth, bminfo.bmHeight, SRCCOPY); - } - SelectObject(hdcMem,hbmMem); - DeleteDC(hdcMem); - } - return TRUE; - } - } - break; - - case WM_COMMAND: - if (!lParam && CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM) dat->hContact)) - break; - - switch (LOWORD(wParam)) - { - case IDOK: - if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDOK))) - break; - { - HANDLE hNewEvent; - - int bufSize = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)) + 1; - TCHAR* temp = (TCHAR*)alloca(bufSize * sizeof(TCHAR)); - GetDlgItemText(hwndDlg, IDC_MESSAGE, temp, bufSize); - if (!temp[0]) break; - - hNewEvent = SendMessageDirect(temp, dat->hContact, dat->szProto); - if (hNewEvent) - { - tcmdlist_append(dat->cmdList, temp); - - dat->cmdListInd = -1; - if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) - NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); - - EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE); - SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); - - if (dat->hDbEventFirst == NULL) - { - dat->hDbEventFirst = hNewEvent; - SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); - } - - SetDlgItemText(hwndDlg, IDC_MESSAGE, _T("")); - - if (g_dat->flags & SMF_AUTOCLOSE) - DestroyWindow(hwndDlg); - else if (g_dat->flags & SMF_AUTOMIN) - ShowWindow(hwndDlg, SW_MINIMIZE); - } - } - return TRUE; - - case IDCANCEL: - DestroyWindow(hwndDlg); - return TRUE; - - case IDC_USERMENU: - case IDC_NAME: - if (GetKeyState(VK_SHIFT) & 0x8000) // copy user name - SendMessage(hwndDlg, DM_USERNAMETOCLIP, 0, 0); - else { - RECT rc; - HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) dat->hContact, 0); - GetWindowRect(GetDlgItem(hwndDlg, LOWORD(wParam)), &rc); - TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL); - DestroyMenu(hMenu); - } - break; - - case IDC_HISTORY: - CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM) dat->hContact, 0); - break; - - case IDC_DETAILS: - CallService(MS_USERINFO_SHOWDIALOG, (WPARAM) dat->hContact, 0); - break; - - case IDC_ADD: - { - ADDCONTACTSTRUCT acs = { 0 }; - - acs.handle = dat->hContact; - acs.handleType = HANDLE_CONTACT; - acs.szProto = 0; - CallService(MS_ADDCONTACT_SHOW, (WPARAM) hwndDlg, (LPARAM) & acs); - } - if (!DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) - ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), FALSE); - break; - - case IDC_MESSAGE: - if (HIWORD(wParam) == EN_CHANGE) - { - int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)); - UpdateReadChars(hwndDlg, dat->hwndStatus); - EnableWindow(GetDlgItem(hwndDlg, IDOK), len != 0); - if (!(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000)) - { - dat->nLastTyping = GetTickCount(); - if (len) - { - if (dat->nTypeMode == PROTOTYPE_SELFTYPING_OFF) - NotifyTyping(dat, PROTOTYPE_SELFTYPING_ON); - } - else if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) - NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); - } - } - break; - } - break; - - case WM_NOTIFY: - if (dat && ((LPNMHDR) lParam)->hwndFrom == dat->hwndStatus) - { - if (((LPNMHDR) lParam)->code == NM_CLICK || ((LPNMHDR) lParam)->code == NM_RCLICK) - { - NMMOUSE *nm = (NMMOUSE *) lParam; - RECT rc; - - SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 1, (LPARAM)&rc); - if (nm->pt.x >= rc.left) - CheckIconClick(dat->hContact, dat->hwndStatus, nm->pt, rc, 2, ((LPNMHDR) lParam)->code == NM_RCLICK ? MBCF_RIGHTBUTTON : 0); - return TRUE; - } - } - - switch (((LPNMHDR) lParam)->idFrom) - { - case IDC_LOG: - switch (((LPNMHDR) lParam)->code) - { - case EN_MSGFILTER: - switch (((MSGFILTER *) lParam)->msg) - { - case WM_LBUTTONDOWN: - { - HCURSOR hCur = GetCursor(); - if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE) - || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE)) - { - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); - return TRUE; - } - break; - } - case WM_MOUSEMOVE: - { - HCURSOR hCur = GetCursor(); - if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE) - || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE)) - SetCursor(LoadCursor(NULL, IDC_ARROW)); - break; - } - case WM_RBUTTONUP: - { - HMENU hMenu, hSubMenu; - POINT pt; - CHARRANGE sel, all = { 0, -1 }; - - hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)); - hSubMenu = GetSubMenu(hMenu, 0); - TranslateMenu(hSubMenu); - SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXGETSEL, 0, (LPARAM) & sel); - if (sel.cpMin == sel.cpMax) - EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED); - pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam); - pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam); - ClientToScreen(((NMHDR *) lParam)->hwndFrom, &pt); - - switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) - { - case IDM_COPY: - SendMessage(((NMHDR *) lParam)->hwndFrom, WM_COPY, 0, 0); - break; - case IDM_COPYALL: - SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & all); - SendMessage(((NMHDR *) lParam)->hwndFrom, WM_COPY, 0, 0); - SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & sel); - break; - case IDM_SELECTALL: - SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & all); - break; - case IDM_CLEAR: - SetDlgItemText(hwndDlg, IDC_LOG, _T("")); - dat->hDbEventFirst = NULL; - break; - } - DestroyMenu(hSubMenu); - DestroyMenu(hMenu); - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); - return TRUE; - } - } - break; - - case EN_VSCROLL: - if (LOWORD(wParam) == IDC_LOG && GetWindowLongPtr((HWND)lParam, GWL_STYLE) & WS_VSCROLL) - { - SCROLLINFO si = {0}; - si.cbSize = sizeof(si); - si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; - GetScrollInfo((HWND)lParam, SB_VERT, &si); - if ((si.nPos + (int)si.nPage + 5) >= si.nMax) - if (KillTimer(hwndDlg, TIMERID_FLASHWND)) - FlashWindow(hwndDlg, FALSE); - } - break; - - case EN_LINK: - switch (((ENLINK *) lParam)->msg) { - case WM_SETCURSOR: - SetCursor(hCurHyperlinkHand); - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); - return TRUE; - - case WM_RBUTTONDOWN: - case WM_LBUTTONUP: - { - TEXTRANGE tr; - CHARRANGE sel; - - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXGETSEL, 0, (LPARAM) & sel); - if (sel.cpMin != sel.cpMax) - break; - tr.chrg = ((ENLINK *) lParam)->chrg; - tr.lpstrText = _alloca((tr.chrg.cpMax - tr.chrg.cpMin + 8) * sizeof(TCHAR)); - SendDlgItemMessage(hwndDlg, IDC_LOG, EM_GETTEXTRANGE, 0, (LPARAM) & tr); - if (_tcschr(tr.lpstrText, '@') != NULL && _tcschr(tr.lpstrText, ':') == NULL && _tcschr(tr.lpstrText, '/') == NULL) - { - memmove(tr.lpstrText + 7, tr.lpstrText, (tr.chrg.cpMax - tr.chrg.cpMin + 1) * sizeof(TCHAR)); - memcpy(tr.lpstrText, _T("mailto:"), 7 * sizeof(TCHAR)); - } - if (((ENLINK *) lParam)->msg == WM_RBUTTONDOWN) - { - HMENU hMenu, hSubMenu; - POINT pt; - - hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)); - hSubMenu = GetSubMenu(hMenu, 1); - TranslateMenu(hSubMenu); - pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam); - pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam); - ClientToScreen(((NMHDR *) lParam)->hwndFrom, &pt); - - switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) - { - case IDM_OPENLINK: - ShellExecute(NULL, _T("open"), tr.lpstrText, NULL, NULL, SW_SHOW); - break; - - case IDM_COPYLINK: - if (OpenClipboard(hwndDlg)) - { - HGLOBAL hData; - EmptyClipboard(); - hData = GlobalAlloc(GMEM_MOVEABLE, (_tcslen(tr.lpstrText) + 1) * sizeof(TCHAR)); - _tcscpy(GlobalLock(hData), tr.lpstrText); - GlobalUnlock(hData); - SetClipboardData(CF_UNICODETEXT, hData); - CloseClipboard(); - } - break; - } - - DestroyMenu(hMenu); - SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); - return TRUE; - } - else - { - ShellExecute(NULL, _T("open"), tr.lpstrText, NULL, NULL, SW_SHOW); - SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); - } - break; - } - } - } - } - break; - - case DM_STATUSICONCHANGE: - SendMessage(dat->hwndStatus, SB_SETTEXT, (WPARAM)(SBT_OWNERDRAW | (SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 1)), (LPARAM)0); - break; - - case WM_CLOSE: - DestroyWindow(hwndDlg); - break; - - case WM_DESTROY: - if (!dat) return 0; - NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSING); - //save string from the editor - if(dat->hContact) - { - TCHAR* msg; - int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)) + 1; - msg = (TCHAR*)alloca(sizeof(TCHAR) * len); - GetDlgItemText(hwndDlg, IDC_MESSAGE, msg, len); - if (msg[0]) - DBWriteContactSettingTString(dat->hContact, SRMSGMOD, DBSAVEDMSG, msg); - else - DBDeleteContactSetting(dat->hContact, SRMSGMOD, DBSAVEDMSG); - } - KillTimer(hwndDlg, TIMERID_TYPE); - if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) - NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); - - if (dat->hBkgBrush) - DeleteObject(dat->hBkgBrush); - if (dat->hwndStatus) - DestroyWindow(dat->hwndStatus); - tcmdlist_free(dat->cmdList); - WindowList_Remove(g_dat->hMessageWindowList, hwndDlg); - DBWriteContactSettingDword(DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)?dat->hContact:NULL, SRMMMOD, "splitterPos", dat->splitterPos); - SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTER), GWLP_WNDPROC, (LONG_PTR) dat->OldSplitterProc); - SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_UNSUBCLASSED, 0, 0); - SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE), GWLP_WNDPROC, (LONG_PTR) dat->OldMessageEditProc); - { - HFONT hFont; - hFont = (HFONT) SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_GETFONT, 0, 0); - if (hFont != NULL && hFont != (HFONT) SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0)) - DeleteObject(hFont); - } - { - WINDOWPLACEMENT wp = { 0 }; - HANDLE hContact; - - if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)) - hContact = dat->hContact; - else - hContact = NULL; - wp.length = sizeof(wp); - GetWindowPlacement(hwndDlg, &wp); - if (!dat->windowWasCascaded) - { - DBWriteContactSettingDword(hContact, SRMMMOD, "x", wp.rcNormalPosition.left); - DBWriteContactSettingDword(hContact, SRMMMOD, "y", wp.rcNormalPosition.top); - } - DBWriteContactSettingDword(hContact, SRMMMOD, "width", wp.rcNormalPosition.right - wp.rcNormalPosition.left); - DBWriteContactSettingDword(hContact, SRMMMOD, "height", wp.rcNormalPosition.bottom - wp.rcNormalPosition.top); - } - - NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSE); - if (dat->hContact&&DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DELTEMP, SRMSGDEFSET_DELTEMP)) - if (DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) - CallService(MS_DB_CONTACT_DELETE, (WPARAM)dat->hContact, 0); - - Button_FreeIcon_IcoLib(hwndDlg, IDC_ADD); - Button_FreeIcon_IcoLib(hwndDlg, IDC_DETAILS); - Button_FreeIcon_IcoLib(hwndDlg, IDC_HISTORY); - Button_FreeIcon_IcoLib(hwndDlg, IDC_USERMENU); - Window_FreeIcon_IcoLib(hwndDlg); - mir_free(dat); - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); - break; - } - return FALSE; -} diff --git a/plugins/SRMM/msgdialog.cpp b/plugins/SRMM/msgdialog.cpp new file mode 100644 index 0000000000..3b4261c305 --- /dev/null +++ b/plugins/SRMM/msgdialog.cpp @@ -0,0 +1,2014 @@ +/* +Copyright 2000-2012 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "commonheaders.h" +#include "statusicon.h" + +#define TIMERID_FLASHWND 1 +#define TIMERID_TYPE 2 +#define TIMEOUT_FLASHWND 900 +#define TIMEOUT_TYPEOFF 10000 //send type off after 10 seconds of inactivity +#define SB_CHAR_WIDTH 45 +#define SB_TIME_WIDTH 60 +#define SB_GRIP_WIDTH 20 // pixels - buffer used to prevent sizegrip from overwriting statusbar icons +#define VALID_AVATAR(x) (x == PA_FORMAT_PNG || x == PA_FORMAT_JPEG || x == PA_FORMAT_ICON || x == PA_FORMAT_BMP || x == PA_FORMAT_GIF) + +extern HCURSOR hCurSplitNS, hCurSplitWE, hCurHyperlinkHand; +extern HANDLE hHookWinEvt, hHookWinPopup; +extern CREOleCallback reOleCallback; + +static void UpdateReadChars(HWND hwndDlg, HWND hwndStatus); + +static const UINT infoLineControls[] = { IDC_PROTOCOL, IDC_NAME }; +static const UINT buttonLineControls[] = { IDC_ADD, IDC_USERMENU, IDC_DETAILS, IDC_HISTORY }; +static const UINT sendControls[] = { IDC_MESSAGE }; + +static void NotifyLocalWinEvent(HANDLE hContact, HWND hwnd, unsigned int type) +{ + if (hContact == NULL || hwnd == NULL) + return; + + MessageWindowEventData mwe = { 0 }; + mwe.cbSize = sizeof(mwe); + mwe.hContact = hContact; + mwe.hwndWindow = hwnd; + mwe.szModule = SRMMMOD; + mwe.uType = type; + mwe.uFlags = MSG_WINDOW_UFLAG_MSG_BOTH; + mwe.hwndInput = GetDlgItem(hwnd, IDC_MESSAGE); + mwe.hwndLog = GetDlgItem(hwnd, IDC_LOG); + NotifyEventHooks(hHookWinEvt, 0, (LPARAM)&mwe); +} + +static char *MsgServiceName(HANDLE hContact) +{ + char szServiceName[100]; + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (szProto == NULL) + return PSS_MESSAGE; + + mir_snprintf(szServiceName, SIZEOF(szServiceName), "%s%sW", szProto, PSS_MESSAGE); + if (ServiceExists(szServiceName)) + return PSS_MESSAGE "W"; + return PSS_MESSAGE; +} + +static BOOL IsUtfSendAvailable(HANDLE hContact) +{ + char* szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if ( szProto == NULL ) + return FALSE; + + return ( CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_IMSENDUTF ) ? TRUE : FALSE; +} + +static int RTL_Detect(const TCHAR *ptszText) +{ + WORD *infoTypeC2; + int i; + int iLen = (int)_tcslen(ptszText); + + infoTypeC2 = (WORD*)alloca(sizeof(WORD) * (iLen + 2)); + GetStringTypeEx(LOCALE_USER_DEFAULT, CT_CTYPE2, ptszText, iLen, infoTypeC2); + + for(i = 0; i < iLen; i++) { + if(infoTypeC2[i] == C2_RIGHTTOLEFT) + return 1; + } + return 0; +} + +HANDLE SendMessageDirect(const TCHAR *szMsg, HANDLE hContact, char *szProto) +{ + int flags = 0; + int bufSize = 0; + char *sendBuffer = NULL; + + if (RTL_Detect(szMsg)) flags |= PREF_RTL; + + if (IsUtfSendAvailable(hContact)) { + flags |= PREF_UTF; + sendBuffer = mir_utf8encodeT(szMsg); + if (!sendBuffer || !sendBuffer[0]) { + mir_free(sendBuffer); + return NULL; + } + bufSize = (int)strlen(sendBuffer) + 1; + } + else { + flags |= PREF_TCHAR; + sendBuffer = mir_t2a(szMsg); + if (!sendBuffer || !sendBuffer[0]) + { + mir_free(sendBuffer); + return NULL; + } + bufSize = (int)strlen(sendBuffer) + 1; + + size_t bufSizeT = (_tcslen(szMsg) + 1) * sizeof(TCHAR) ; + sendBuffer = (char*)mir_realloc(sendBuffer, bufSizeT + bufSize); + memcpy((TCHAR*)&sendBuffer[bufSize], szMsg, bufSizeT); + bufSize += (int)bufSizeT; + } + + if (hContact == NULL) { + mir_free(sendBuffer); + return NULL; + } + + if (sendBuffer) { + HANDLE hNewEvent, hSendId; + DBEVENTINFO dbei = { 0 }; + dbei.cbSize = sizeof(dbei); + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.flags = DBEF_SENT | (flags & PREF_UTF ? DBEF_UTF : 0) | (flags & PREF_RTL ? DBEF_RTL : 0); + dbei.szModule = szProto; + dbei.timestamp = (DWORD)time(NULL); + dbei.cbBlob = (DWORD)bufSize; + dbei.pBlob = (PBYTE)sendBuffer; + + hNewEvent = (HANDLE) CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei); + hSendId = (HANDLE) CallContactService(hContact, MsgServiceName(hContact), flags, (LPARAM) sendBuffer); + msgQueue_add(hContact, hSendId, szMsg, hNewEvent); + mir_free(sendBuffer); + + return hNewEvent; + } + return NULL; +} + + +static void AddToFileList(TCHAR ***pppFiles,int *totalCount,const TCHAR* szFilename) +{ + *pppFiles=(TCHAR**)mir_realloc(*pppFiles,(++*totalCount+1)*sizeof(TCHAR*)); + (*pppFiles)[*totalCount] = NULL; + (*pppFiles)[*totalCount-1] = mir_tstrdup( szFilename ); + + if ( GetFileAttributes(szFilename) & FILE_ATTRIBUTE_DIRECTORY ) { + WIN32_FIND_DATA fd; + HANDLE hFind; + TCHAR szPath[MAX_PATH]; + mir_sntprintf(szPath, SIZEOF(szPath), _T("%s\\*"), szFilename); + if (( hFind = FindFirstFile( szPath, &fd )) != INVALID_HANDLE_VALUE ) { + do { + if ( !_tcscmp(fd.cFileName,_T(".")) || !_tcscmp(fd.cFileName,_T(".."))) continue; + mir_sntprintf(szPath, SIZEOF(szPath), _T("%s\\%s"), szFilename, fd.cFileName); + AddToFileList(pppFiles,totalCount,szPath); + } + while( FindNextFile( hFind,&fd )); + FindClose( hFind ); + } } } + +static void ShowMultipleControls(HWND hwndDlg, const UINT * controls, int cControls, int state) +{ + int i; + for (i = 0; i < cControls; i++) + ShowWindow(GetDlgItem(hwndDlg, controls[i]), state); +} + +static void UpdateReadChars(HWND hwndDlg, HWND hwndStatus) +{ + if (hwndStatus && (g_dat->flags & SMF_SHOWREADCHAR)) + { + TCHAR buf[32]; + int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)); + + mir_sntprintf(buf, SIZEOF(buf), _T("%d"), len); + SendMessage(hwndStatus, SB_SETTEXT, 1, (LPARAM) buf); + } +} + +static void ShowTime(struct SrmmWindowData *dat) +{ + if (dat->hwndStatus && dat->hTimeZone) + { + SYSTEMTIME st; + GetSystemTime(&st); + if (dat->wMinute != st.wMinute) + { + TCHAR buf[32]; + unsigned i = (g_dat->flags & SMF_SHOWREADCHAR) ? 2 : 1; + + tmi.printDateTime(dat->hTimeZone, _T("t"), buf, SIZEOF(buf), 0); + SendMessage(dat->hwndStatus, SB_SETTEXT, i, (LPARAM) buf); + dat->wMinute = st.wMinute; + } + } +} + +static void SetupStatusBar(HWND hwndDlg, struct SrmmWindowData *dat) +{ + int icons_width, cx, i = 0, statwidths[4]; + RECT rc; + + icons_width = GetStatusIconsCount(dat->hContact) * (GetSystemMetrics(SM_CXSMICON) + 2) + SB_GRIP_WIDTH; + GetWindowRect(dat->hwndStatus, &rc); + cx = rc.right - rc.left; + + if (dat->hTimeZone) + { + if (g_dat->flags & SMF_SHOWREADCHAR) + statwidths[i++] = cx - SB_TIME_WIDTH - SB_CHAR_WIDTH - icons_width; + statwidths[i++] = cx - SB_TIME_WIDTH - icons_width; + } + else if (g_dat->flags & SMF_SHOWREADCHAR) + statwidths[i++] = cx - SB_CHAR_WIDTH - icons_width; + + statwidths[i++] = cx - icons_width; + statwidths[i++] = -1; + SendMessage(dat->hwndStatus, SB_SETPARTS, i, (LPARAM) statwidths); + + UpdateReadChars(hwndDlg, dat->hwndStatus); + ShowTime(dat); + SendMessage(hwndDlg, DM_STATUSICONCHANGE, 0, 0); +} + +static void SetDialogToType(HWND hwndDlg) +{ + struct SrmmWindowData *dat; + + dat = (struct SrmmWindowData *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + if (dat->hContact) + ShowMultipleControls(hwndDlg, infoLineControls, SIZEOF(infoLineControls), (g_dat->flags&SMF_SHOWINFO) ? SW_SHOW : SW_HIDE); + else + ShowMultipleControls(hwndDlg, infoLineControls, SIZEOF(infoLineControls), SW_HIDE); + + if (dat->hContact) { + ShowMultipleControls(hwndDlg, buttonLineControls, SIZEOF(buttonLineControls), (g_dat->flags&SMF_SHOWBTNS) ? SW_SHOW : SW_HIDE); + if (!DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) + ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), SW_HIDE); + } + else ShowMultipleControls(hwndDlg, buttonLineControls, SIZEOF(buttonLineControls), SW_HIDE); + + ShowMultipleControls(hwndDlg, sendControls, SIZEOF(sendControls), SW_SHOW); + if (!dat->hwndStatus) { + int grip = (GetWindowLongPtr(hwndDlg, GWL_STYLE) & WS_THICKFRAME) ? SBARS_SIZEGRIP : 0; + dat->hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | grip, 0, 0, 0, 0, hwndDlg, NULL, g_hInst, NULL); + SendMessage(dat->hwndStatus, SB_SETMINHEIGHT, GetSystemMetrics(SM_CYSMICON), 0); + } + + ShowWindow(GetDlgItem(hwndDlg, IDCANCEL), SW_HIDE); + ShowWindow(GetDlgItem(hwndDlg, IDC_SPLITTER), SW_SHOW); + ShowWindow(GetDlgItem(hwndDlg, IDOK), (g_dat->flags & SMF_SENDBTN) ? SW_SHOW : SW_HIDE); + EnableWindow(GetDlgItem(hwndDlg, IDOK), GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)) != 0); + if (dat->avatarPic == NULL || !(g_dat->flags & SMF_AVATAR)) + ShowWindow(GetDlgItem(hwndDlg, IDC_AVATAR), SW_HIDE); + SendMessage(hwndDlg, DM_UPDATETITLE, 0, 0); + SendMessage(hwndDlg, WM_SIZE, 0, 0); +} + +struct MsgEditSubclassData +{ + DWORD lastEnterTime; +}; + +static void SetEditorText(HWND hwnd, const TCHAR* txt) +{ + SetWindowText(hwnd, txt); + SendMessage(hwnd, EM_SETSEL, -1, -1); +} + +#define EM_SUBCLASSED (WM_USER+0x101) +#define EM_UNSUBCLASSED (WM_USER+0x102) +#define ENTERCLICKTIME 1000 //max time in ms during which a double-tap on enter will cause a send + +static LRESULT CALLBACK MessageEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + struct SrmmWindowData *pdat = (struct SrmmWindowData *)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA); + struct MsgEditSubclassData *dat = (struct MsgEditSubclassData *) GetWindowLongPtr(hwnd, GWLP_USERDATA); + + switch (msg) { + case WM_DROPFILES: + SendMessage(GetParent(hwnd), WM_DROPFILES, (WPARAM)wParam, (LPARAM)lParam); + break; + + case EM_SUBCLASSED: + dat = (struct MsgEditSubclassData *) mir_alloc(sizeof(struct MsgEditSubclassData)); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) dat); + dat->lastEnterTime = 0; + return 0; + + case WM_CHAR: + if (GetWindowLongPtr(hwnd, GWL_STYLE) & ES_READONLY) + break; + + if (wParam == 1 && GetKeyState(VK_CONTROL) & 0x8000) { //ctrl-a + SendMessage(hwnd, EM_SETSEL, 0, -1); + return 0; + } + + if (wParam == 23 && GetKeyState(VK_CONTROL) & 0x8000) { // ctrl-w + SendMessage(GetParent(hwnd), WM_CLOSE, 0, 0); + return 0; + } + break; + + case WM_KEYDOWN: + if (wParam == VK_RETURN) + { + if (!(GetKeyState(VK_SHIFT) & 0x8000) && + ((GetKeyState(VK_CONTROL) & 0x8000) != 0) != ((g_dat->flags & SMF_SENDONENTER) != 0)) + { + PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); + return 0; + } + if (g_dat->flags & SMF_SENDONDBLENTER) + { + if (dat->lastEnterTime + ENTERCLICKTIME < GetTickCount()) + dat->lastEnterTime = GetTickCount(); + 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_INSERT && (GetKeyState(VK_SHIFT) & 0x8000)) || (wParam == 'V' && (GetKeyState(VK_CONTROL) & 0x8000))) && + !(GetKeyState(VK_MENU) & 0x8000)) // ctrl-v (paste clean text) + { + SendMessage(hwnd, WM_PASTE, 0, 0); + return 0; + } + + if (wParam == VK_UP && (GetKeyState(VK_CONTROL) & 0x8000) && + ((g_dat->flags & (SMF_AUTOCLOSE | SMF_CTRLSUPPORT)) == SMF_CTRLSUPPORT)) + { + if (pdat->cmdList->realCount) + { + if (pdat->cmdListInd < 0) + { + pdat->cmdListInd = pdat->cmdList->realCount - 1; + SetEditorText(hwnd, tcmdlist_getitem(pdat->cmdList, pdat->cmdListInd)); + } + else if (pdat->cmdListInd > 0) + { + SetEditorText(hwnd, tcmdlist_getitem(pdat->cmdList, --pdat->cmdListInd)); + } + } + EnableWindow(GetDlgItem(GetParent(hwnd), IDOK), GetWindowTextLength(hwnd) != 0); + UpdateReadChars(GetParent(hwnd), pdat->hwndStatus); + return 0; + } + else if (wParam == VK_DOWN && (GetKeyState(VK_CONTROL) & 0x8000) && + ((g_dat->flags & (SMF_AUTOCLOSE | SMF_CTRLSUPPORT)) == SMF_CTRLSUPPORT)) + { + if (pdat->cmdList->realCount && pdat->cmdListInd >= 0) + { + if (pdat->cmdListInd < (pdat->cmdList->realCount - 1)) + { + SetEditorText(hwnd, tcmdlist_getitem(pdat->cmdList, ++pdat->cmdListInd)); + } + else + { + pdat->cmdListInd = -1; + SetEditorText(hwnd, tcmdlist_getitem(pdat->cmdList, pdat->cmdList->realCount - 1)); + } + } + + EnableWindow(GetDlgItem(GetParent(hwnd), IDOK), GetWindowTextLength(hwnd) != 0); + UpdateReadChars(GetParent(hwnd), pdat->hwndStatus); + } + break; + + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_MOUSEWHEEL: + case WM_KILLFOCUS: + dat->lastEnterTime = 0; + break; + + case WM_SYSCHAR: + dat->lastEnterTime = 0; + if ((wParam == 's' || wParam == 'S') && GetKeyState(VK_MENU) & 0x8000) + { + PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); + return 0; + } + break; + + case WM_CONTEXTMENU: + { + HMENU hMenu; + CHARRANGE sel; + static const CHARRANGE all = {0, -1}; + + MessageWindowPopupData mwpd = {0}; + mwpd.cbSize = sizeof(mwpd); + mwpd.uType = MSG_WINDOWPOPUP_SHOWING; + mwpd.uFlags = MSG_WINDOWPOPUP_INPUT; + mwpd.hContact = pdat->hContact; + mwpd.hwnd = hwnd; + + hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)); + + mwpd.hMenu = GetSubMenu(hMenu, 2); + TranslateMenu(mwpd.hMenu); + + SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin == sel.cpMax) + { + EnableMenuItem(mwpd.hMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(mwpd.hMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(mwpd.hMenu, IDM_DELETE, MF_BYCOMMAND | MF_GRAYED); + } + if (!SendMessage(hwnd, EM_CANUNDO, 0, 0)) + { + EnableMenuItem(mwpd.hMenu, IDM_UNDO, MF_BYCOMMAND | MF_GRAYED); + } + if (!SendMessage(hwnd, EM_CANREDO, 0, 0)) + { + EnableMenuItem(mwpd.hMenu, IDM_REDO, MF_BYCOMMAND | MF_GRAYED); + } + if (!SendMessage(hwnd, EM_CANPASTE, 0, 0)) + { + if (!IsClipboardFormatAvailable(CF_HDROP)) + EnableMenuItem(mwpd.hMenu, IDM_PASTE, MF_BYCOMMAND | MF_GRAYED); + EnableMenuItem(mwpd.hMenu, IDM_PASTESEND, MF_BYCOMMAND | MF_GRAYED); + } + if (lParam == 0xFFFFFFFF) + { + SendMessage(hwnd, EM_POSFROMCHAR, (WPARAM)&mwpd.pt, (LPARAM)sel.cpMax); + ClientToScreen(hwnd, &mwpd.pt); + } + else + { + mwpd.pt.x = GET_X_LPARAM(lParam); + mwpd.pt.y = GET_Y_LPARAM(lParam); + } + + + // First notification + NotifyEventHooks(hHookWinPopup, 0, (LPARAM)&mwpd); + + // Someone added items? + if (GetMenuItemCount(mwpd.hMenu) > 0) + { + SetCursor(LoadCursor(NULL, IDC_ARROW)); + mwpd.selection = TrackPopupMenu(mwpd.hMenu, TPM_RETURNCMD, mwpd.pt.x, mwpd.pt.y, 0, hwnd, NULL); + } + + // Second notification + mwpd.uType = MSG_WINDOWPOPUP_SELECTED; + NotifyEventHooks(hHookWinPopup, 0, (LPARAM)&mwpd); + + switch (mwpd.selection) + { + case IDM_UNDO: + SendMessage(hwnd, WM_UNDO, 0, 0); + break; + + case IDM_REDO: + SendMessage(hwnd, EM_REDO, 0, 0); + break; + + case IDM_CUT: + SendMessage(hwnd, WM_CUT, 0, 0); + break; + + case IDM_COPY: + SendMessage(hwnd, WM_COPY, 0, 0); + break; + + case IDM_PASTE: + SendMessage(hwnd, WM_PASTE, 0, 0); + break; + + case IDM_PASTESEND: + SendMessage(hwnd, EM_PASTESPECIAL, CF_TEXT, 0); + PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0); + break; + + case IDM_DELETE: + SendMessage(hwnd, EM_REPLACESEL, TRUE, 0); + break; + + case IDM_SELECTALL: + SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&all); + break; + + case IDM_CLEAR: + SetWindowText(hwnd, _T( "" )); + break; + } + DestroyMenu(hMenu); + return 0; + } + + case WM_PASTE: + if (IsClipboardFormatAvailable(CF_HDROP)) + { + if (OpenClipboard(hwnd)) + { + HANDLE hDrop = GetClipboardData(CF_HDROP); + if (hDrop) + SendMessage(hwnd, WM_DROPFILES, (WPARAM)hDrop, 0); + CloseClipboard(); + } + } + else + SendMessage(hwnd, EM_PASTESPECIAL, CF_TEXT, 0); + return 0; + + case EM_UNSUBCLASSED: + mir_free(dat); + return 0; + } + return CallWindowProc(pdat->OldMessageEditProc, hwnd, msg, wParam, lParam); +} + +static LRESULT CALLBACK SplitterSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + struct SrmmWindowData *pdat = (struct SrmmWindowData *)GetWindowLongPtr(GetParent(hwnd),GWLP_USERDATA); + + switch (msg) { + case WM_NCHITTEST: + return HTCLIENT; + + case WM_SETCURSOR: + { + RECT rc; + GetClientRect(hwnd, &rc); + SetCursor(rc.right > rc.bottom ? hCurSplitNS : hCurSplitWE); + return TRUE; + } + + case WM_LBUTTONDOWN: + SetCapture(hwnd); + return 0; + + case WM_MOUSEMOVE: + if (GetCapture() == hwnd) { + RECT rc; + GetClientRect(hwnd, &rc); + SendMessage(GetParent(hwnd), DM_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(); + return 0; + } + return CallWindowProc(pdat->OldSplitterProc, hwnd, msg, wParam, lParam); +} + +static int MessageDialogResize(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL * urc) +{ + struct SrmmWindowData *dat = (struct SrmmWindowData *) lParam; + + if (!(g_dat->flags&SMF_SHOWINFO) && !(g_dat->flags&SMF_SHOWBTNS)) { + int i; + for (i = 0; i < SIZEOF(buttonLineControls); i++) + if (buttonLineControls[i] == urc->wId) + OffsetRect(&urc->rcItem, 0, -dat->lineHeight); + } + + switch (urc->wId) { + case IDC_NAME: + { + int len; + HWND h; + + h = GetDlgItem(hwndDlg, IDC_NAME); + len = GetWindowTextLength(h); + if (len > 0) { + TCHAR buf[256]; + GetWindowText(h, buf, SIZEOF(buf)); + + HDC hdc = GetDC(h); + HFONT hFont = (HFONT)SelectObject(hdc, (HFONT) SendMessage(GetDlgItem(hwndDlg, IDOK), WM_GETFONT, 0, 0)); + + SIZE textSize; + GetTextExtentPoint32(hdc, buf, lstrlen(buf), &textSize); + urc->rcItem.right = urc->rcItem.left + textSize.cx + 10; + if ((g_dat->flags&SMF_SHOWBTNS) && urc->rcItem.right > urc->dlgNewSize.cx - dat->nLabelRight) + urc->rcItem.right = urc->dlgNewSize.cx - dat->nLabelRight; + SelectObject(hdc, hFont); + ReleaseDC(h, hdc); + } + } + case IDC_PROTOCOL: + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; + + case IDC_ADD: + case IDC_USERMENU: + case IDC_DETAILS: + case IDC_HISTORY: + return RD_ANCHORX_RIGHT | RD_ANCHORY_TOP; + + case IDC_LOG: + if (!(g_dat->flags&SMF_SHOWINFO) && !(g_dat->flags&SMF_SHOWBTNS)) + urc->rcItem.top -= dat->lineHeight; + urc->rcItem.bottom -= dat->splitterPos - dat->originalSplitterPos; + return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; + + case IDC_SPLITTER: + urc->rcItem.top -= dat->splitterPos - dat->originalSplitterPos; + urc->rcItem.bottom -= dat->splitterPos - dat->originalSplitterPos; + return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM; + + case IDC_MESSAGE: + { + if (!(g_dat->flags & SMF_SENDBTN)) + urc->rcItem.right = urc->dlgNewSize.cx - urc->rcItem.left; + if ((g_dat->flags & SMF_AVATAR) && dat->avatarPic) { + urc->rcItem.left = dat->avatarWidth+4; + } + urc->rcItem.top -= dat->splitterPos - dat->originalSplitterPos; + if (!(g_dat->flags & SMF_SENDBTN)) + return RD_ANCHORX_CUSTOM | RD_ANCHORY_BOTTOM; + return RD_ANCHORX_WIDTH | RD_ANCHORY_BOTTOM; + } + + case IDCANCEL: + case IDOK: + urc->rcItem.top -= dat->splitterPos - dat->originalSplitterPos; + return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; + + case IDC_AVATAR: + urc->rcItem.top=urc->rcItem.bottom-(dat->avatarHeight + 2); + urc->rcItem.right=urc->rcItem.left+(dat->avatarWidth + 2); + return RD_ANCHORX_LEFT|RD_ANCHORY_BOTTOM; + } + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; +} + +void ShowAvatar(HWND hwndDlg, struct SrmmWindowData *dat) +{ + if (g_dat->flags & SMF_AVATAR) + { + AVATARCACHEENTRY *ace = (AVATARCACHEENTRY *)CallService(MS_AV_GETAVATARBITMAP, (WPARAM)dat->hContact, 0); + if (ace && (INT_PTR)ace != CALLSERVICE_NOTFOUND && (ace->dwFlags & AVS_BITMAP_VALID) && !(ace->dwFlags & AVS_HIDEONCLIST)) + dat->avatarPic = ace->hbmPic; + else + dat->avatarPic = NULL; + } + else + dat->avatarPic = NULL; + + SendMessage(hwndDlg, DM_UPDATESIZEBAR, 0, 0); + SendMessage(hwndDlg, DM_AVATARSIZECHANGE, 0, 0); +} + +static void NotifyTyping(struct SrmmWindowData *dat, int mode) +{ + DWORD protoStatus; + DWORD protoCaps; + DWORD typeCaps; + + if (!dat->hContact) + return; + // Don't send to protocols who don't support typing + // Don't send to users who are unchecked in the typing notification options + // Don't send to protocols that are offline + // Don't send to users who are not visible and + // Don't send to users who are not on the visible list when you are in invisible mode. + + if (!DBGetContactSettingByte(dat->hContact, SRMMMOD, SRMSGSET_TYPING, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW))) + return; + + if (!dat->szProto) + return; + + protoStatus = CallProtoService(dat->szProto, PS_GETSTATUS, 0, 0); + protoCaps = CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_1, 0); + typeCaps = CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_4, 0); + + if (!(typeCaps & PF4_SUPPORTTYPING)) + return; + + if (protoStatus < ID_STATUS_ONLINE) + return; + + if (protoCaps & PF1_VISLIST && DBGetContactSettingWord(dat->hContact, dat->szProto, "ApparentMode", 0) == ID_STATUS_OFFLINE) + return; + + if (protoCaps & PF1_INVISLIST && protoStatus == ID_STATUS_INVISIBLE && DBGetContactSettingWord(dat->hContact, dat->szProto, "ApparentMode", 0) != ID_STATUS_ONLINE) + return; + + if (!(g_dat->flags & SMF_TYPINGUNKNOWN) && DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) + return; + + // End user check + dat->nTypeMode = mode; + CallService(MS_PROTO_SELFISTYPING, (WPARAM) dat->hContact, dat->nTypeMode); +} + +void Button_SetIcon_IcoLib(HWND hwndDlg, int itemId, int iconId, const char* tooltip) +{ + HWND hWnd = GetDlgItem( hwndDlg, itemId ); + SendMessage( hWnd, BM_SETIMAGE, IMAGE_ICON, ( LPARAM )LoadSkinnedIcon( iconId )); + SendMessage( hWnd, BUTTONSETASFLATBTN, TRUE, 0 ); + SendMessage( hWnd, BUTTONADDTOOLTIP, (WPARAM)tooltip, 0); +} + +void Button_FreeIcon_IcoLib(HWND hwndDlg, int itemId) +{ + HICON hIcon = ( HICON )SendDlgItemMessage(hwndDlg, itemId, BM_SETIMAGE, IMAGE_ICON, 0 ); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); +} + +void Window_FreeIcon_IcoLib(HWND hwndDlg) +{ + HICON hIcon = (HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); + + hIcon = (HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); +} + +INT_PTR CALLBACK DlgProcMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + struct SrmmWindowData *dat; + + dat = (struct SrmmWindowData *) GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + switch (msg) + { + case WM_INITDIALOG: + { + struct NewMessageWindowLParam *newData = (struct NewMessageWindowLParam *) lParam; + TranslateDialogDefault(hwndDlg); + dat = (struct SrmmWindowData *) mir_calloc(sizeof(struct SrmmWindowData)); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR) dat); + + dat->hContact = newData->hContact; + dat->hTimeZone = tmi.createByContact(dat->hContact, TZF_KNOWNONLY); + dat->wMinute = 61; + + NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPENING); + if (newData->szInitialText) + { + int len; + + if(newData->isWchar) + SetDlgItemText(hwndDlg, IDC_MESSAGE, (TCHAR *)newData->szInitialText); + else + + SetDlgItemTextA(hwndDlg, IDC_MESSAGE, newData->szInitialText); + len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)); + PostMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), EM_SETSEL, len, len); + } + + dat->szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) dat->hContact, 0); + RichUtil_SubClass(GetDlgItem(hwndDlg, IDC_LOG)); + RichUtil_SubClass(GetDlgItem(hwndDlg, IDC_MESSAGE)); + + // avatar stuff + dat->limitAvatarH = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, SRMSGDEFSET_LIMITAVHEIGHT)?DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, SRMSGDEFSET_AVHEIGHT):0; + + if (dat->hContact && dat->szProto != NULL) + dat->wStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE); + else + dat->wStatus = ID_STATUS_OFFLINE; + dat->wOldStatus = dat->wStatus; + dat->splitterPos = (int) DBGetContactSettingDword(DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)?dat->hContact:NULL, SRMMMOD, "splitterPos", (DWORD) - 1); + dat->cmdList = li.List_Create(0, 20); + dat->cmdListInd = -1; + dat->nTypeMode = PROTOTYPE_SELFTYPING_OFF; + SetTimer(hwndDlg, TIMERID_TYPE, 1000, NULL); + { + RECT rc, rc2; + GetWindowRect(GetDlgItem(hwndDlg, IDC_USERMENU), &rc); + GetWindowRect(hwndDlg, &rc2); + dat->nLabelRight = rc2.right - rc.left; + } + { + RECT rc; + POINT pt; + GetWindowRect(GetDlgItem(hwndDlg, IDC_SPLITTER), &rc); + pt.y = (rc.top + rc.bottom) / 2; + pt.x = 0; + ScreenToClient(hwndDlg, &pt); + dat->originalSplitterPos = pt.y; + if (dat->splitterPos == -1) + dat->splitterPos = dat->originalSplitterPos;// + 60; + GetWindowRect(GetDlgItem(hwndDlg, IDC_ADD), &rc); + dat->lineHeight = rc.bottom - rc.top + 3; + } + WindowList_Add(g_dat->hMessageWindowList, hwndDlg, dat->hContact); + GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &dat->minEditInit); + SendMessage(hwndDlg, DM_UPDATESIZEBAR, 0, 0); + dat->hwndStatus = NULL; + Button_SetIcon_IcoLib(hwndDlg, IDC_ADD, SKINICON_OTHER_ADDCONTACT, "Add Contact Permanently to List" ); + Button_SetIcon_IcoLib(hwndDlg, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, "View User's Details" ); + Button_SetIcon_IcoLib(hwndDlg, IDC_HISTORY, SKINICON_OTHER_HISTORY, "View User's History" ); + Button_SetIcon_IcoLib(hwndDlg, IDC_USERMENU, SKINICON_OTHER_DOWNARROW, "User Menu" ); + SendDlgItemMessage(hwndDlg, IDC_NAME, BUTTONSETASFLATBTN, TRUE, 0 ); + + EnableWindow(GetDlgItem(hwndDlg, IDC_PROTOCOL), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_AVATAR), FALSE); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETOLECALLBACK, 0, (LPARAM) & reOleCallback); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETEVENTMASK, 0, ENM_MOUSEEVENTS | ENM_LINK | ENM_SCROLL); + /* duh, how come we didnt use this from the start? */ + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_AUTOURLDETECT, (WPARAM) TRUE, 0); + if (dat->hContact && dat->szProto) { + int nMax; + nMax = CallProtoService(dat->szProto, PS_GETCAPS, PFLAG_MAXLENOFMESSAGE, (LPARAM) dat->hContact); + if (nMax) + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_LIMITTEXT, (WPARAM) nMax, 0); + /* get around a lame bug in the Windows template resource code where richedits are limited to 0x7FFF */ + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_LIMITTEXT, (WPARAM) sizeof(TCHAR) * 0x7FFFFFFF, 0); + } + + dat->OldMessageEditProc = (WNDPROC) SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE), GWLP_WNDPROC, (LONG_PTR) MessageEditSubclassProc); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SUBCLASSED, 0, 0); + dat->OldSplitterProc = (WNDPROC) SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTER), GWLP_WNDPROC, (LONG_PTR) SplitterSubclassProc); + + if (dat->hContact) + { + int historyMode = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, SRMSGDEFSET_LOADHISTORY); + // This finds the first message to display, it works like shit + dat->hDbEventFirst = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) dat->hContact, 0); + switch (historyMode) + { + case LOADHISTORY_COUNT: + { + int i; + HANDLE hPrevEvent; + DBEVENTINFO dbei = { 0 }; + dbei.cbSize = sizeof(dbei); + for (i = DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADCOUNT, SRMSGDEFSET_LOADCOUNT); i--; ) + { + if (dat->hDbEventFirst == NULL) + hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->hContact, 0); + else + hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) dat->hDbEventFirst, 0); + if (hPrevEvent == NULL) + break; + + dbei.cbBlob = 0; + dat->hDbEventFirst = hPrevEvent; + CallService(MS_DB_EVENT_GET, (WPARAM) hPrevEvent, (LPARAM) &dbei); + if (!DbEventIsShown(&dbei, dat)) + i++; + } + break; + } + case LOADHISTORY_TIME: + { + HANDLE hPrevEvent; + DBEVENTINFO dbei = { 0 }; + DWORD firstTime; + + dbei.cbSize = sizeof(dbei); + if (dat->hDbEventFirst == NULL) + dbei.timestamp = (DWORD)time(NULL); + else + CallService(MS_DB_EVENT_GET, (WPARAM) dat->hDbEventFirst, (LPARAM) & dbei); + firstTime = dbei.timestamp - 60 * DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, SRMSGDEFSET_LOADTIME); + for (;;) + { + if (dat->hDbEventFirst == NULL) + hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->hContact, 0); + else + hPrevEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) dat->hDbEventFirst, 0); + if (hPrevEvent == NULL) + break; + dbei.cbBlob = 0; + CallService(MS_DB_EVENT_GET, (WPARAM) hPrevEvent, (LPARAM) & dbei); + if (dbei.timestamp < firstTime) + break; + dat->hDbEventFirst = hPrevEvent; + } + break; + } + } + } + + { + DBEVENTINFO dbei = { 0 }; + HANDLE hdbEvent; + + dbei.cbSize = sizeof(dbei); + hdbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDLAST, (WPARAM) dat->hContact, 0); + if (hdbEvent) + { + do { + ZeroMemory(&dbei, sizeof(dbei)); + dbei.cbSize = sizeof(dbei); + CallService(MS_DB_EVENT_GET, (WPARAM) hdbEvent, (LPARAM) & dbei); + if (( dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei)) && !(dbei.flags & DBEF_SENT)) { + dat->lastMessage = dbei.timestamp; + PostMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0); + break; + } + } + while (hdbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDPREV, (WPARAM) hdbEvent, 0)); + } + } + + SendMessage(hwndDlg, DM_OPTIONSAPPLIED, 1, 0); + + //restore saved msg if any... + if (dat->hContact) + { + DBVARIANT dbv; + if (!DBGetContactSettingTString(dat->hContact, SRMSGMOD, DBSAVEDMSG, &dbv)) + { + if (dbv.ptszVal[0]) + { + SetDlgItemText(hwndDlg, IDC_MESSAGE, dbv.ptszVal); + EnableWindow(GetDlgItem(hwndDlg, IDOK), TRUE); + UpdateReadChars(hwndDlg, dat->hwndStatus); + PostMessage(GetDlgItem(hwndDlg, IDC_MESSAGE), EM_SETSEL, -1, -1); + } + DBFreeVariant(&dbv); + } + } + + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETEVENTMASK, 0, ENM_CHANGE); + + { + int flag = newData->noActivate ? RWPF_HIDDEN : 0; + int savePerContact = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT); + if (Utils_RestoreWindowPositionEx(hwndDlg, flag, savePerContact ? dat->hContact : NULL, SRMMMOD, "")) { + if (savePerContact) { + if (Utils_RestoreWindowPositionEx(hwndDlg, flag | RWPF_NOMOVE, NULL, SRMMMOD, "")) + SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW); + } + else + SetWindowPos(hwndDlg, 0, 0, 0, 450, 300, SWP_NOZORDER | SWP_NOMOVE | SWP_SHOWWINDOW); + } + if (!savePerContact && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CASCADE, SRMSGDEFSET_CASCADE)) + WindowList_Broadcast(g_dat->hMessageWindowList, DM_CASCADENEWWINDOW, (WPARAM) hwndDlg, (LPARAM) & dat->windowWasCascaded); + } + if (newData->noActivate) + { + SetWindowPos(hwndDlg, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW); + SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL); + } + else + { + SetWindowPos(hwndDlg, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); + SetForegroundWindow(hwndDlg); + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + } + + SendMessage(hwndDlg, DM_GETAVATAR, 0, 0); + + NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPEN); + return FALSE; + } + + case WM_CONTEXTMENU: + if (dat->hwndStatus && dat->hwndStatus == (HWND) wParam) { + POINT pt, pt2; + HMENU hMenu; + RECT rc; + + GetCursorPos(&pt); + pt2.x = pt.x; pt2.y = pt.y; + ScreenToClient(dat->hwndStatus, &pt); + + // no popup menu for status icons - this is handled via NM_RCLICK notification and the plugins that added the icons + SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 1, (LPARAM)&rc); + if (pt.x >= rc.left) break; + + hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) dat->hContact, 0); + + TrackPopupMenu(hMenu, 0, pt2.x, pt2.y, 0, hwndDlg, NULL); + DestroyMenu(hMenu); + } + break; + + // Mod from tabsrmm + case WM_DROPFILES: + if (dat->szProto == NULL) break; + if (!(CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_1,0)&PF1_FILESEND)) break; + if (dat->wStatus == ID_STATUS_OFFLINE) break; + if (dat->hContact != NULL) { + TCHAR szFilename[MAX_PATH]; + HDROP hDrop = (HDROP)wParam; + int fileCount = DragQueryFile(hDrop,-1,NULL,0), totalCount = 0, i; + TCHAR** ppFiles = NULL; + for ( i=0; i < fileCount; i++ ) { + DragQueryFile(hDrop, i, szFilename, SIZEOF(szFilename)); + AddToFileList(&ppFiles, &totalCount, szFilename); + } + CallServiceSync(MS_FILE_SENDSPECIFICFILEST, (WPARAM)dat->hContact, (LPARAM)ppFiles); + for(i=0;ppFiles[i];i++) mir_free(ppFiles[i]); + mir_free(ppFiles); + } + break; + + case HM_AVATARACK: + ShowAvatar(hwndDlg, dat); + break; + + case DM_AVATARCALCSIZE: + { + BITMAP bminfo; + + if (dat->avatarPic == NULL || !(g_dat->flags&SMF_AVATAR)) + { + dat->avatarWidth=50; + dat->avatarHeight=50; + ShowWindow(GetDlgItem(hwndDlg, IDC_AVATAR), SW_HIDE); + return 0; + } + GetObject(dat->avatarPic, sizeof(bminfo), &bminfo); + dat->avatarWidth=bminfo.bmWidth+2; + dat->avatarHeight=bminfo.bmHeight+2; + if (dat->limitAvatarH&&dat->avatarHeight>dat->limitAvatarH) { + dat->avatarWidth = bminfo.bmWidth * dat->limitAvatarH / bminfo.bmHeight + 2; + dat->avatarHeight = dat->limitAvatarH + 2; + } + ShowWindow(GetDlgItem(hwndDlg, IDC_AVATAR), SW_SHOW); + } + break; + + case DM_UPDATESIZEBAR: + dat->minEditBoxSize.cx = dat->minEditInit.right - dat->minEditInit.left; + dat->minEditBoxSize.cy = dat->minEditInit.bottom - dat->minEditInit.top; + if(g_dat->flags&SMF_AVATAR) { + SendMessage(hwndDlg, DM_AVATARCALCSIZE, 0, 0); + if(dat->avatarPic && dat->minEditBoxSize.cy <= dat->avatarHeight) + dat->minEditBoxSize.cy = dat->avatarHeight; + } + break; + + case DM_AVATARSIZECHANGE: + { + RECT rc; + GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &rc); + if (rc.bottom-rc.topminEditBoxSize.cy) { + SendMessage(hwndDlg, DM_SPLITTERMOVED, rc.top-(rc.bottom-rc.top-dat->minEditBoxSize.cy-4), (LPARAM) GetDlgItem(hwndDlg, IDC_SPLITTER)); + } + SendMessage(hwndDlg, WM_SIZE, 0, 0); + } + break; + + case DM_GETAVATAR: + { + PROTO_AVATAR_INFORMATIONT ai = { sizeof(ai), dat->hContact }; + CallProtoService(dat->szProto, PS_GETAVATARINFOT, GAIF_FORCE, (LPARAM)&ai); + + ShowAvatar(hwndDlg, dat); + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 1); + } + break; + + case DM_TYPING: + dat->nTypeSecs = (INT_PTR)lParam > 0 ? (int)lParam : 0; + break; + + case DM_UPDATEWINICON: + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON)) { + WORD wStatus; + + Window_FreeIcon_IcoLib(hwndDlg); + + if (dat->szProto) { + wStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE); + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) LoadSkinnedProtoIconBig(dat->szProto, wStatus)); + SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM) LoadSkinnedProtoIcon(dat->szProto, wStatus)); + break; + } + } + SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM) LoadSkinnedIconBig(SKINICON_EVENT_MESSAGE)); + SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM) LoadSkinnedIcon(SKINICON_EVENT_MESSAGE)); + break; + + case DM_USERNAMETOCLIP: + if (dat->hContact) + { + TCHAR buf[128] = _T(""); + CONTACTINFO ci = {0}; + ci.cbSize = sizeof(ci); + ci.hContact = dat->hContact; + ci.szProto = dat->szProto; + ci.dwFlag = CNF_UNIQUEID | CNF_TCHAR; + if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) + { + switch (ci.type) + { + case CNFT_ASCIIZ: + mir_sntprintf(buf, SIZEOF(buf), _T("%s"), ci.pszVal); + mir_free(ci.pszVal); + break; + + case CNFT_DWORD: + mir_sntprintf(buf, SIZEOF(buf), _T("%u"), ci.dVal); + break; + } + } + if (buf[0] && OpenClipboard(hwndDlg)) + { + HGLOBAL hData; + + EmptyClipboard(); + hData = GlobalAlloc(GMEM_MOVEABLE, _tcslen(buf) * sizeof(TCHAR) + 1); + _tcscpy((TCHAR*)GlobalLock(hData), buf); + GlobalUnlock(hData); + SetClipboardData(CF_UNICODETEXT, hData); + CloseClipboard(); + } + } + break; + + case DM_UPDATELASTMESSAGE: + if (!dat->hwndStatus || dat->nTypeSecs) + break; + + if (dat->lastMessage) + { + TCHAR date[64], time[64], fmt[128]; + + tmi.printTimeStamp(NULL, dat->lastMessage, _T("d"), date, SIZEOF(date), 0); + tmi.printTimeStamp(NULL, dat->lastMessage, _T("t"), time, SIZEOF(time), 0); + mir_sntprintf(fmt, SIZEOF(fmt), TranslateT("Last message received on %s at %s."), date, time); + SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM) fmt); + } + else { + SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM) _T("")); + } + SendMessage(dat->hwndStatus, SB_SETICON, 0, (LPARAM) NULL); + break; + + case DM_OPTIONSAPPLIED: + SetDialogToType(hwndDlg); + if (dat->hBkgBrush) + DeleteObject(dat->hBkgBrush); + { + COLORREF colour = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR); + dat->hBkgBrush = CreateSolidBrush(colour); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETBKGNDCOLOR, 0, colour); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETBKGNDCOLOR, 0, colour); + } + { // avatar stuff + dat->avatarPic = NULL; + dat->limitAvatarH = 0; + if (CallProtoService(dat->szProto, PS_GETCAPS, PFLAGNUM_4, 0) & PF4_AVATARS) + { + dat->limitAvatarH = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, SRMSGDEFSET_LIMITAVHEIGHT) ? + DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, SRMSGDEFSET_AVHEIGHT) : 0; + } + if (!wParam) SendMessage(hwndDlg, DM_GETAVATAR, 0, 0); + } + InvalidateRect(GetDlgItem(hwndDlg, IDC_MESSAGE), NULL, FALSE); + { + HFONT hFont; + LOGFONT lf; + CHARFORMAT cf = {0}; + hFont = (HFONT) SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_GETFONT, 0, 0); + if (hFont != NULL && hFont != (HFONT) SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0)) + DeleteObject(hFont); + LoadMsgDlgFont(MSGFONTID_MESSAGEAREA, &lf, &cf.crTextColor); + hFont = CreateFontIndirect(&lf); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_SETFONT, (WPARAM) hFont, MAKELPARAM(TRUE, 0)); + + cf.cbSize = sizeof(CHARFORMAT); + cf.dwMask = CFM_COLOR; + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_SETCHARFORMAT, SCF_ALL, (WPARAM) &cf); + } + + /* + * configure message history for proper RTL formatting + */ + + { + PARAFORMAT2 pf2; + ZeroMemory((void *)&pf2, sizeof(pf2)); + pf2.cbSize = sizeof(pf2); + + pf2.wEffects = PFE_RTLPARA; + pf2.dwMask = PFM_RTLPARA; + SetDlgItemText(hwndDlg, IDC_LOG, _T("")); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETPARAFORMAT, 0, (LPARAM)&pf2); + pf2.wEffects = 0; + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETPARAFORMAT, 0, (LPARAM)&pf2); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_SETLANGOPTIONS, 0, (LPARAM) SendDlgItemMessage(hwndDlg, IDC_LOG, EM_GETLANGOPTIONS, 0, 0) & ~IMF_AUTOKEYBOARD); + } + SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); + SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0); + break; + + case DM_UPDATETITLE: + { + TCHAR newtitle[256], oldtitle[256], *szStatus; + TCHAR *contactName, *pszNewTitleEnd; + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) wParam; + + pszNewTitleEnd = _T("Message Session"); + if (dat->hContact) + { + if (dat->szProto) + { + TCHAR buf[128] = _T(""); + int statusIcon = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON); + + dat->wStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE); + contactName = ( TCHAR* )CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) dat->hContact, GCDNF_TCHAR); + + if (strcmp(dat->szProto, "MetaContacts")) + { + CONTACTINFO ci = {0}; + ci.cbSize = sizeof(ci); + ci.hContact = dat->hContact; + ci.szProto = dat->szProto; + ci.dwFlag = CNF_DISPLAYUID | CNF_TCHAR; + if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) { + switch (ci.type) { + case CNFT_ASCIIZ: + mir_sntprintf(buf, SIZEOF(buf), _T("%s"), (TCHAR*)ci.pszVal); + mir_free(ci.pszVal); + break; + case CNFT_DWORD: + mir_sntprintf(buf, SIZEOF(buf), _T("%u"), ci.dVal); + break; + } + } + } + if (buf[0]) + SetDlgItemText(hwndDlg, IDC_NAME, buf); + else + SetDlgItemText(hwndDlg, IDC_NAME, contactName); + + szStatus = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, dat->szProto == NULL ? ID_STATUS_OFFLINE : DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE), GSMDF_TCHAR); + if (statusIcon) + mir_sntprintf(newtitle, SIZEOF(newtitle), _T("%s - %s"), contactName, TranslateTS(pszNewTitleEnd)); + else + mir_sntprintf(newtitle, SIZEOF(newtitle), _T("%s (%s): %s"), contactName, szStatus, TranslateTS(pszNewTitleEnd)); + + if (!cws || (!strcmp(cws->szModule, dat->szProto) && !strcmp(cws->szSetting, "Status"))) + { + InvalidateRect(GetDlgItem(hwndDlg, IDC_PROTOCOL), NULL, TRUE); + if (statusIcon) + SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0); + } + + // log + if ((dat->wStatus != dat->wOldStatus || lParam != 0) && + DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, SRMSGDEFSET_SHOWSTATUSCH)) + { + DBEVENTINFO dbei; + TCHAR buffer[200]; + HANDLE hNewEvent; + int iLen; + + TCHAR *szOldStatus = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM) dat->wOldStatus, GSMDF_TCHAR); + TCHAR *szNewStatus = (TCHAR*)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM) dat->wStatus, GSMDF_TCHAR); + + if (dat->wStatus == ID_STATUS_OFFLINE) + { + iLen = mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("signed off (was %s)"), szOldStatus); + SendMessage(hwndDlg, DM_TYPING, 0, 0); + } + else if (dat->wOldStatus == ID_STATUS_OFFLINE) + iLen = mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("signed on (%s)"), szNewStatus); + else + iLen = mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("is now %s (was %s)"), szNewStatus, szOldStatus); + + { + char* blob = ( char* )alloca(1000); + int ansiLen = WideCharToMultiByte(CP_ACP, 0, buffer, -1, blob, 1000, 0, 0); + memcpy( blob+ansiLen, buffer, sizeof(TCHAR)*(iLen+1)); + dbei.cbBlob = ansiLen + sizeof(TCHAR)*(iLen+1); + dbei.cbSize = sizeof(dbei); + dbei.pBlob = (PBYTE) blob; + dbei.eventType = EVENTTYPE_STATUSCHANGE; + dbei.flags = 0; + dbei.timestamp = (DWORD)time(NULL); + dbei.szModule = dat->szProto; + hNewEvent = (HANDLE) CallService(MS_DB_EVENT_ADD, (WPARAM) dat->hContact, (LPARAM) & dbei); + if (dat->hDbEventFirst == NULL) + { + dat->hDbEventFirst = hNewEvent; + SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); + } + } + } + dat->wOldStatus = dat->wStatus; + } + } + else lstrcpyn(newtitle, pszNewTitleEnd, SIZEOF(newtitle)); + + GetWindowText(hwndDlg, oldtitle, SIZEOF(oldtitle)); + if ( _tcscmp(newtitle, oldtitle )) { //swt() flickers even if the title hasn't actually changed + SetWindowText(hwndDlg, newtitle); + SendMessage(hwndDlg, WM_SIZE, 0, 0); + } + break; + } + + case DM_NEWTIMEZONE: + dat->hTimeZone = tmi.createByContact(dat->hContact, TZF_KNOWNONLY); + dat->wMinute = 61; + SendMessage(hwndDlg, WM_SIZE, 0, 0); + break; + + case DM_GETWINDOWSTATE: + { + UINT state = 0; + + state |= MSG_WINDOW_STATE_EXISTS; + if (IsWindowVisible(hwndDlg)) + state |= MSG_WINDOW_STATE_VISIBLE; + if (GetForegroundWindow() == hwndDlg) + state |= MSG_WINDOW_STATE_FOCUS; + if (IsIconic(hwndDlg)) + state |= MSG_WINDOW_STATE_ICONIC; + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, state); + return TRUE; + + } + + case DM_CASCADENEWWINDOW: + if ((HWND) wParam == hwndDlg) + break; + { + RECT rcThis, rcNew; + GetWindowRect(hwndDlg, &rcThis); + GetWindowRect((HWND) wParam, &rcNew); + if (abs(rcThis.left - rcNew.left) < 3 && abs(rcThis.top - rcNew.top) < 3) { + int offset = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME); + SetWindowPos((HWND) wParam, 0, rcNew.left + offset, rcNew.top + offset, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE); + *(int *) lParam = 1; + } + } + break; + + case WM_ACTIVATE: + if (LOWORD(wParam) != WA_ACTIVE) + break; + + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + //fall through + + case WM_MOUSEACTIVATE: + if (KillTimer(hwndDlg, TIMERID_FLASHWND)) + FlashWindow(hwndDlg, FALSE); + break; + + case WM_GETMINMAXINFO: + { + MINMAXINFO* mmi = (MINMAXINFO *) lParam; + RECT rcWindow, rcLog; + GetWindowRect(hwndDlg, &rcWindow); + GetWindowRect(GetDlgItem(hwndDlg, IDC_LOG), &rcLog); + mmi->ptMinTrackSize.x = rcWindow.right - rcWindow.left - ((rcLog.right - rcLog.left) - dat->minEditBoxSize.cx); + mmi->ptMinTrackSize.y = rcWindow.bottom - rcWindow.top - ((rcLog.bottom - rcLog.top) - dat->minEditBoxSize.cy); + return 0; + } + + case WM_SIZE: + { + UTILRESIZEDIALOG urd = {0}; + BOOL bottomScroll = TRUE; + + if (IsIconic(hwndDlg)) + break; + + if (dat->hwndStatus) + { + SendMessage(dat->hwndStatus, WM_SIZE, 0, 0); + SetupStatusBar(hwndDlg, dat); + } + + if (GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_LOG), GWL_STYLE) & WS_VSCROLL) + { + SCROLLINFO si = {0}; + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; + GetScrollInfo(GetDlgItem(hwndDlg, IDC_LOG), SB_VERT, &si); + bottomScroll = (si.nPos + (int)si.nPage + 5) >= si.nMax; + } + + urd.cbSize = sizeof(urd); + urd.hInstance = g_hInst; + urd.hwndDlg = hwndDlg; + urd.lParam = (LPARAM) dat; + urd.lpTemplate = MAKEINTRESOURCEA(IDD_MSG); + urd.pfnResizer = MessageDialogResize; + CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM) & urd); + + // The statusbar sometimes draws over these 2 controls so + // redraw them + if (dat->hwndStatus) + { + RedrawWindow(GetDlgItem(hwndDlg, IDOK), NULL, NULL, RDW_INVALIDATE); + RedrawWindow(GetDlgItem(hwndDlg, IDC_MESSAGE), NULL, NULL, RDW_INVALIDATE); + } + if ((g_dat->flags & SMF_AVATAR) && dat->avatarPic) + RedrawWindow(GetDlgItem(hwndDlg, IDC_AVATAR), NULL, NULL, RDW_INVALIDATE); + + if (bottomScroll) + PostMessage(hwndDlg, DM_SCROLLLOGTOBOTTOM, 0, 0); + break; + } + + case DM_SPLITTERMOVED: + { + if ((HWND) lParam == GetDlgItem(hwndDlg, IDC_SPLITTER)) + { + POINT pt; + RECT rc; + RECT rcLog; + int oldSplitterY; + HWND hwndLog = GetDlgItem(hwndDlg, IDC_LOG); + + GetClientRect(hwndDlg, &rc); + GetWindowRect(hwndLog, &rcLog); + + pt.x = 0; + pt.y = wParam; + ScreenToClient(hwndDlg, &pt); + + oldSplitterY = dat->splitterPos; + dat->splitterPos = rc.bottom - pt.y + 23; + GetWindowRect(GetDlgItem(hwndDlg, IDC_MESSAGE), &rc); + if (rc.bottom - rc.top + (dat->splitterPos - oldSplitterY) < dat->minEditBoxSize.cy) + dat->splitterPos = oldSplitterY + dat->minEditBoxSize.cy - (rc.bottom - rc.top); + if (rcLog.bottom - rcLog.top - (dat->splitterPos - oldSplitterY) < dat->minEditBoxSize.cy) + dat->splitterPos = oldSplitterY - dat->minEditBoxSize.cy + (rcLog.bottom - rcLog.top); + + SendMessage(hwndDlg, WM_SIZE, 0, 0); + } + } + break; + + case DM_REMAKELOG: + StreamInEvents(hwndDlg, dat->hDbEventFirst, -1, 0); + break; + + case DM_APPENDTOLOG: //takes wParam=hDbEvent + StreamInEvents(hwndDlg, (HANDLE) wParam, 1, 1); + break; + + case DM_SCROLLLOGTOBOTTOM: + { + HWND hwndLog = GetDlgItem(hwndDlg, IDC_LOG); + if (GetWindowLongPtr(hwndLog, GWL_STYLE) & WS_VSCROLL) + { + SCROLLINFO si = {0}; + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_RANGE; + GetScrollInfo(hwndLog, SB_VERT, &si); + si.fMask = SIF_POS; + si.nPos = si.nMax - si.nPage; + SetScrollInfo(hwndLog, SB_VERT, &si, TRUE); + SendMessage(hwndLog, WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, 0), 0); + } + } + break; + + case HM_DBEVENTADDED: + if ((HANDLE) wParam != dat->hContact) + break; + { + DBEVENTINFO dbei = { 0 }; + + dbei.cbSize = sizeof(dbei); + CallService(MS_DB_EVENT_GET, lParam, (LPARAM) & dbei); + if (dat->hDbEventFirst == NULL) + dat->hDbEventFirst = (HANDLE) lParam; + if (DbEventIsShown(&dbei, dat) && !(dbei.flags & DBEF_READ)) + { + if ((dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei)) && !(dbei.flags & DBEF_SENT)) + { + if (GetForegroundWindow() == hwndDlg) + SkinPlaySound("RecvMsgActive"); + else + SkinPlaySound("RecvMsgInactive"); + } + if (( dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei)) && dat->hwndStatus && !(dbei.flags & DBEF_SENT)) + { + dat->lastMessage = dbei.timestamp; + SendMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0); + } + if ((HANDLE) lParam != dat->hDbEventFirst && (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, lParam, 0) == NULL) + SendMessage(hwndDlg, DM_APPENDTOLOG, lParam, 0); + else + SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); + + if (!(dbei.flags & DBEF_SENT) && dbei.eventType != EVENTTYPE_STATUSCHANGE) + { + if (GetActiveWindow() == hwndDlg && GetForegroundWindow() == hwndDlg) + { + HWND hwndLog = GetDlgItem(hwndDlg, IDC_LOG); + if (GetWindowLongPtr(hwndLog, GWL_STYLE) & WS_VSCROLL) + { + SCROLLINFO si = {0}; + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; + GetScrollInfo(hwndLog, SB_VERT, &si); + if ((si.nPos + (int)si.nPage + 5) < si.nMax) + SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL); + } + } + else + SetTimer(hwndDlg, TIMERID_FLASHWND, TIMEOUT_FLASHWND, NULL); + } + } + } + break; + + case WM_TIMECHANGE: + PostMessage(hwndDlg, DM_NEWTIMEZONE, 0, 0); + PostMessage(hwndDlg, DM_REMAKELOG, 0, 0); + break; + + case WM_TIMER: + if (wParam == TIMERID_FLASHWND) + { + FlashWindow(hwndDlg, TRUE); + if (dat->nFlash > 2 * g_dat->nFlashMax) + { + KillTimer(hwndDlg, TIMERID_FLASHWND); + FlashWindow(hwndDlg, FALSE); + dat->nFlash = 0; + } + dat->nFlash++; + } + else if (wParam == TIMERID_TYPE) + { + ShowTime(dat); + if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON && GetTickCount() - dat->nLastTyping > TIMEOUT_TYPEOFF) + NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); + + if (dat->showTyping) + { + if (dat->nTypeSecs) + { + dat->nTypeSecs--; + if (GetForegroundWindow() == hwndDlg) + SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0); + } + else + { + SendMessage(hwndDlg, DM_UPDATELASTMESSAGE, 0, 0); + if (g_dat->flags & SMF_SHOWTYPINGWIN) + SendMessage(hwndDlg, DM_UPDATEWINICON, 0, 0); + dat->showTyping = 0; + } + } + else + { + if (dat->nTypeSecs) + { + TCHAR szBuf[256]; + TCHAR* szContactName = (TCHAR*) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) dat->hContact, GCDNF_TCHAR); + HICON hTyping = LoadSkinnedIcon(SKINICON_OTHER_TYPING); + + mir_sntprintf(szBuf, SIZEOF(szBuf), TranslateT("%s is typing a message..."), szContactName); + dat->nTypeSecs--; + + SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM) szBuf); + SendMessage(dat->hwndStatus, SB_SETICON, 0, (LPARAM) hTyping); + if ((g_dat->flags & SMF_SHOWTYPINGWIN) && GetForegroundWindow() != hwndDlg) + { + HICON hIcon = (HICON)SendMessage(hwndDlg, WM_GETICON, ICON_SMALL, 0); + SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)hTyping ); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); + } + dat->showTyping = 1; + } + } + } + break; + + case WM_MEASUREITEM: + { + LPMEASUREITEMSTRUCT mis = (LPMEASUREITEMSTRUCT) lParam; + if (mis->CtlType == ODT_MENU) + return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam); + } + break; + + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT) lParam; + if (dis->CtlType == ODT_MENU) + return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam); + else if (dis->hwndItem == dat->hwndStatus) + { + DrawStatusIcons(dat->hContact, dis->hDC, dis->rcItem, 2); + return TRUE; + } + else if (dis->CtlID == IDC_PROTOCOL) + { + if (dat->szProto) + { + HICON hIcon; + int dwStatus; + + dwStatus = DBGetContactSettingWord(dat->hContact, dat->szProto, "Status", ID_STATUS_OFFLINE); + hIcon = LoadSkinnedProtoIcon(dat->szProto, dwStatus); + if (hIcon) + { + if (DBGetContactSettingDword(dat->hContact, dat->szProto, "IdleTS", 0)) + { + HIMAGELIST hImageList; + + hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON), IsWinVerXPPlus()? ILC_COLOR32 | ILC_MASK : ILC_COLOR16 | ILC_MASK, 1, 0); + ImageList_AddIcon(hImageList, hIcon); + ImageList_DrawEx(hImageList, 0, dis->hDC, dis->rcItem.left, dis->rcItem.top, 0, 0, CLR_NONE, CLR_NONE, ILD_SELECTED); + ImageList_Destroy(hImageList); + } + else + DrawIconEx(dis->hDC, dis->rcItem.left, dis->rcItem.top, hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL); + CallService(MS_SKIN2_RELEASEICON,(WPARAM)hIcon, 0); + return TRUE; + } + } + } + else if (dis->CtlID == IDC_AVATAR && dat->avatarPic && (g_dat->flags & SMF_AVATAR)) + { + HPEN hPen = CreatePen(PS_SOLID, 1, RGB(0,0,0)); + HPEN hOldPen = (HPEN)SelectObject(dis->hDC, hPen); + Rectangle(dis->hDC, 0, 0, dat->avatarWidth, dat->avatarHeight); + SelectObject(dis->hDC,hOldPen); + DeleteObject(hPen); + + BITMAP bminfo; + GetObject(dat->avatarPic, sizeof(bminfo), &bminfo); + { + HDC hdcMem = CreateCompatibleDC(dis->hDC); + HBITMAP hbmMem = (HBITMAP)SelectObject(hdcMem, dat->avatarPic); + { + SetStretchBltMode(dis->hDC, HALFTONE); + StretchBlt(dis->hDC, 1, 1, dat->avatarWidth-2, dat->avatarHeight-2, hdcMem, 0, 0, + bminfo.bmWidth, bminfo.bmHeight, SRCCOPY); + } + SelectObject(hdcMem,hbmMem); + DeleteDC(hdcMem); + } + return TRUE; + } + } + break; + + case WM_COMMAND: + if (!lParam && CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM) dat->hContact)) + break; + + switch (LOWORD(wParam)) + { + case IDOK: + if (!IsWindowEnabled(GetDlgItem(hwndDlg, IDOK))) + break; + { + HANDLE hNewEvent; + + int bufSize = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)) + 1; + TCHAR* temp = (TCHAR*)alloca(bufSize * sizeof(TCHAR)); + GetDlgItemText(hwndDlg, IDC_MESSAGE, temp, bufSize); + if (!temp[0]) break; + + hNewEvent = SendMessageDirect(temp, dat->hContact, dat->szProto); + if (hNewEvent) + { + tcmdlist_append(dat->cmdList, temp); + + dat->cmdListInd = -1; + if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) + NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); + + EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE); + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + + if (dat->hDbEventFirst == NULL) + { + dat->hDbEventFirst = hNewEvent; + SendMessage(hwndDlg, DM_REMAKELOG, 0, 0); + } + + SetDlgItemText(hwndDlg, IDC_MESSAGE, _T("")); + + if (g_dat->flags & SMF_AUTOCLOSE) + DestroyWindow(hwndDlg); + else if (g_dat->flags & SMF_AUTOMIN) + ShowWindow(hwndDlg, SW_MINIMIZE); + } + } + return TRUE; + + case IDCANCEL: + DestroyWindow(hwndDlg); + return TRUE; + + case IDC_USERMENU: + case IDC_NAME: + if (GetKeyState(VK_SHIFT) & 0x8000) // copy user name + SendMessage(hwndDlg, DM_USERNAMETOCLIP, 0, 0); + else { + RECT rc; + HMENU hMenu = (HMENU) CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM) dat->hContact, 0); + GetWindowRect(GetDlgItem(hwndDlg, LOWORD(wParam)), &rc); + TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL); + DestroyMenu(hMenu); + } + break; + + case IDC_HISTORY: + CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM) dat->hContact, 0); + break; + + case IDC_DETAILS: + CallService(MS_USERINFO_SHOWDIALOG, (WPARAM) dat->hContact, 0); + break; + + case IDC_ADD: + { + ADDCONTACTSTRUCT acs = { 0 }; + + acs.handle = dat->hContact; + acs.handleType = HANDLE_CONTACT; + acs.szProto = 0; + CallService(MS_ADDCONTACT_SHOW, (WPARAM) hwndDlg, (LPARAM) & acs); + } + if (!DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) + ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), FALSE); + break; + + case IDC_MESSAGE: + if (HIWORD(wParam) == EN_CHANGE) + { + int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)); + UpdateReadChars(hwndDlg, dat->hwndStatus); + EnableWindow(GetDlgItem(hwndDlg, IDOK), len != 0); + if (!(GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_SHIFT) & 0x8000)) + { + dat->nLastTyping = GetTickCount(); + if (len) + { + if (dat->nTypeMode == PROTOTYPE_SELFTYPING_OFF) + NotifyTyping(dat, PROTOTYPE_SELFTYPING_ON); + } + else if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) + NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); + } + } + break; + } + break; + + case WM_NOTIFY: + if (dat && ((LPNMHDR) lParam)->hwndFrom == dat->hwndStatus) + { + if (((LPNMHDR) lParam)->code == NM_CLICK || ((LPNMHDR) lParam)->code == NM_RCLICK) + { + NMMOUSE *nm = (NMMOUSE *) lParam; + RECT rc; + + SendMessage(dat->hwndStatus, SB_GETRECT, SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 1, (LPARAM)&rc); + if (nm->pt.x >= rc.left) + CheckIconClick(dat->hContact, dat->hwndStatus, nm->pt, rc, 2, ((LPNMHDR) lParam)->code == NM_RCLICK ? MBCF_RIGHTBUTTON : 0); + return TRUE; + } + } + + switch (((LPNMHDR) lParam)->idFrom) + { + case IDC_LOG: + switch (((LPNMHDR) lParam)->code) + { + case EN_MSGFILTER: + switch (((MSGFILTER *) lParam)->msg) + { + case WM_LBUTTONDOWN: + { + HCURSOR hCur = GetCursor(); + if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE) + || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE)) + { + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); + return TRUE; + } + break; + } + case WM_MOUSEMOVE: + { + HCURSOR hCur = GetCursor(); + if (hCur == LoadCursor(NULL, IDC_SIZENS) || hCur == LoadCursor(NULL, IDC_SIZEWE) + || hCur == LoadCursor(NULL, IDC_SIZENESW) || hCur == LoadCursor(NULL, IDC_SIZENWSE)) + SetCursor(LoadCursor(NULL, IDC_ARROW)); + break; + } + case WM_RBUTTONUP: + { + HMENU hMenu, hSubMenu; + POINT pt; + CHARRANGE sel, all = { 0, -1 }; + + hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)); + hSubMenu = GetSubMenu(hMenu, 0); + TranslateMenu(hSubMenu); + SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXGETSEL, 0, (LPARAM) & sel); + if (sel.cpMin == sel.cpMax) + EnableMenuItem(hSubMenu, IDM_COPY, MF_BYCOMMAND | MF_GRAYED); + pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam); + pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam); + ClientToScreen(((NMHDR *) lParam)->hwndFrom, &pt); + + switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) + { + case IDM_COPY: + SendMessage(((NMHDR *) lParam)->hwndFrom, WM_COPY, 0, 0); + break; + case IDM_COPYALL: + SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & all); + SendMessage(((NMHDR *) lParam)->hwndFrom, WM_COPY, 0, 0); + SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & sel); + break; + case IDM_SELECTALL: + SendMessage(((NMHDR *) lParam)->hwndFrom, EM_EXSETSEL, 0, (LPARAM) & all); + break; + case IDM_CLEAR: + SetDlgItemText(hwndDlg, IDC_LOG, _T("")); + dat->hDbEventFirst = NULL; + break; + } + DestroyMenu(hSubMenu); + DestroyMenu(hMenu); + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); + return TRUE; + } + } + break; + + case EN_VSCROLL: + if (LOWORD(wParam) == IDC_LOG && GetWindowLongPtr((HWND)lParam, GWL_STYLE) & WS_VSCROLL) + { + SCROLLINFO si = {0}; + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; + GetScrollInfo((HWND)lParam, SB_VERT, &si); + if ((si.nPos + (int)si.nPage + 5) >= si.nMax) + if (KillTimer(hwndDlg, TIMERID_FLASHWND)) + FlashWindow(hwndDlg, FALSE); + } + break; + + case EN_LINK: + switch (((ENLINK *) lParam)->msg) { + case WM_SETCURSOR: + SetCursor(hCurHyperlinkHand); + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); + return TRUE; + + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + { + TEXTRANGE tr; + CHARRANGE sel; + + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_EXGETSEL, 0, (LPARAM) & sel); + if (sel.cpMin != sel.cpMax) + break; + tr.chrg = ((ENLINK *) lParam)->chrg; + tr.lpstrText = (TCHAR*)_alloca((tr.chrg.cpMax - tr.chrg.cpMin + 8) * sizeof(TCHAR)); + SendDlgItemMessage(hwndDlg, IDC_LOG, EM_GETTEXTRANGE, 0, (LPARAM) & tr); + if (_tcschr(tr.lpstrText, '@') != NULL && _tcschr(tr.lpstrText, ':') == NULL && _tcschr(tr.lpstrText, '/') == NULL) + { + memmove(tr.lpstrText + 7, tr.lpstrText, (tr.chrg.cpMax - tr.chrg.cpMin + 1) * sizeof(TCHAR)); + memcpy(tr.lpstrText, _T("mailto:"), 7 * sizeof(TCHAR)); + } + if (((ENLINK *) lParam)->msg == WM_RBUTTONDOWN) + { + HMENU hMenu, hSubMenu; + POINT pt; + + hMenu = LoadMenu(g_hInst, MAKEINTRESOURCE(IDR_CONTEXT)); + hSubMenu = GetSubMenu(hMenu, 1); + TranslateMenu(hSubMenu); + pt.x = (short) LOWORD(((ENLINK *) lParam)->lParam); + pt.y = (short) HIWORD(((ENLINK *) lParam)->lParam); + ClientToScreen(((NMHDR *) lParam)->hwndFrom, &pt); + + switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, NULL)) + { + case IDM_OPENLINK: + ShellExecute(NULL, _T("open"), tr.lpstrText, NULL, NULL, SW_SHOW); + break; + + case IDM_COPYLINK: + if (OpenClipboard(hwndDlg)) + { + HGLOBAL hData; + EmptyClipboard(); + hData = GlobalAlloc(GMEM_MOVEABLE, (_tcslen(tr.lpstrText) + 1) * sizeof(TCHAR)); + _tcscpy((TCHAR*)GlobalLock(hData), tr.lpstrText); + GlobalUnlock(hData); + SetClipboardData(CF_UNICODETEXT, hData); + CloseClipboard(); + } + break; + } + + DestroyMenu(hMenu); + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); + return TRUE; + } + else + { + ShellExecute(NULL, _T("open"), tr.lpstrText, NULL, NULL, SW_SHOW); + SetFocus(GetDlgItem(hwndDlg, IDC_MESSAGE)); + } + break; + } + } + } + } + break; + + case DM_STATUSICONCHANGE: + SendMessage(dat->hwndStatus, SB_SETTEXT, (WPARAM)(SBT_OWNERDRAW | (SendMessage(dat->hwndStatus, SB_GETPARTS, 0, 0) - 1)), (LPARAM)0); + break; + + case WM_CLOSE: + DestroyWindow(hwndDlg); + break; + + case WM_DESTROY: + if (!dat) return 0; + NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSING); + //save string from the editor + if(dat->hContact) + { + TCHAR* msg; + int len = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_MESSAGE)) + 1; + msg = (TCHAR*)alloca(sizeof(TCHAR) * len); + GetDlgItemText(hwndDlg, IDC_MESSAGE, msg, len); + if (msg[0]) + DBWriteContactSettingTString(dat->hContact, SRMSGMOD, DBSAVEDMSG, msg); + else + DBDeleteContactSetting(dat->hContact, SRMSGMOD, DBSAVEDMSG); + } + KillTimer(hwndDlg, TIMERID_TYPE); + if (dat->nTypeMode == PROTOTYPE_SELFTYPING_ON) + NotifyTyping(dat, PROTOTYPE_SELFTYPING_OFF); + + if (dat->hBkgBrush) + DeleteObject(dat->hBkgBrush); + if (dat->hwndStatus) + DestroyWindow(dat->hwndStatus); + tcmdlist_free(dat->cmdList); + WindowList_Remove(g_dat->hMessageWindowList, hwndDlg); + DBWriteContactSettingDword(DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)?dat->hContact:NULL, SRMMMOD, "splitterPos", dat->splitterPos); + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_SPLITTER), GWLP_WNDPROC, (LONG_PTR) dat->OldSplitterProc); + SendDlgItemMessage(hwndDlg, IDC_MESSAGE, EM_UNSUBCLASSED, 0, 0); + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_MESSAGE), GWLP_WNDPROC, (LONG_PTR) dat->OldMessageEditProc); + { + HFONT hFont; + hFont = (HFONT) SendDlgItemMessage(hwndDlg, IDC_MESSAGE, WM_GETFONT, 0, 0); + if (hFont != NULL && hFont != (HFONT) SendDlgItemMessage(hwndDlg, IDOK, WM_GETFONT, 0, 0)) + DeleteObject(hFont); + } + { + WINDOWPLACEMENT wp = { 0 }; + HANDLE hContact; + + if (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)) + hContact = dat->hContact; + else + hContact = NULL; + wp.length = sizeof(wp); + GetWindowPlacement(hwndDlg, &wp); + if (!dat->windowWasCascaded) + { + DBWriteContactSettingDword(hContact, SRMMMOD, "x", wp.rcNormalPosition.left); + DBWriteContactSettingDword(hContact, SRMMMOD, "y", wp.rcNormalPosition.top); + } + DBWriteContactSettingDword(hContact, SRMMMOD, "width", wp.rcNormalPosition.right - wp.rcNormalPosition.left); + DBWriteContactSettingDword(hContact, SRMMMOD, "height", wp.rcNormalPosition.bottom - wp.rcNormalPosition.top); + } + + NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_CLOSE); + if (dat->hContact&&DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DELTEMP, SRMSGDEFSET_DELTEMP)) + if (DBGetContactSettingByte(dat->hContact, "CList", "NotOnList", 0)) + CallService(MS_DB_CONTACT_DELETE, (WPARAM)dat->hContact, 0); + + Button_FreeIcon_IcoLib(hwndDlg, IDC_ADD); + Button_FreeIcon_IcoLib(hwndDlg, IDC_DETAILS); + Button_FreeIcon_IcoLib(hwndDlg, IDC_HISTORY); + Button_FreeIcon_IcoLib(hwndDlg, IDC_USERMENU); + Window_FreeIcon_IcoLib(hwndDlg); + mir_free(dat); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0); + break; + } + return FALSE; +} diff --git a/plugins/SRMM/msglog.c b/plugins/SRMM/msglog.c deleted file mode 100644 index 82bb0f8da5..0000000000 --- a/plugins/SRMM/msglog.c +++ /dev/null @@ -1,645 +0,0 @@ -/* -Copyright 2000-2010 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ -#include "commonheaders.h" - -extern HANDLE hIconLibItem[]; - -static int logPixelSY; -#define LOGICON_MSG_IN 0 -#define LOGICON_MSG_OUT 1 -#define LOGICON_MSG_NOTICE 2 -static PBYTE pLogIconBmpBits[3]; -static int logIconBmpSize[ SIZEOF(pLogIconBmpBits) ]; - -#define STREAMSTAGE_HEADER 0 -#define STREAMSTAGE_EVENTS 1 -#define STREAMSTAGE_TAIL 2 -#define STREAMSTAGE_STOP 3 -struct LogStreamData -{ - int stage; - HANDLE hContact; - HANDLE hDbEvent, hDbEventLast; - char *buffer; - int bufferOffset, bufferLen; - int eventsToInsert; - int isEmpty; - struct MessageWindowData *dlgDat; -}; - -static char szSep2[40], szSep2_RTL[50]; - -static void AppendToBuffer(char **buffer, int *cbBufferEnd, int *cbBufferAlloced, const char *fmt, ...) -{ - va_list va; - int charsDone; - - va_start(va, fmt); - for (;;) { - charsDone = mir_vsnprintf(*buffer + *cbBufferEnd, *cbBufferAlloced - *cbBufferEnd, fmt, va); - if (charsDone >= 0) - break; - *cbBufferAlloced += 1024; - *buffer = (char *) mir_realloc(*buffer, *cbBufferAlloced); - } - va_end(va); - *cbBufferEnd += charsDone; -} - -static const TCHAR *bbcodes[] = { _T("[b]"), _T("[i]"), _T("[u]"), _T("[s]"), _T("[/b]"), _T("[/i]"), _T("[/u]"), _T("[/s]") }; -static const char *bbcodefmt[] = { "\\b ", "\\i ", "\\ul ", "\\strike ", "\\b0 ", "\\i0 ", "\\ul0 ", "\\strike0 " }; - -static int AppendToBufferWithRTF(char **buffer, int *cbBufferEnd, int *cbBufferAlloced, TCHAR* line) -{ - DWORD textCharsCount = 0; - char *d; - int lineLen; - - if (line == NULL) - return 0; - - lineLen = (int)_tcslen(line) * 9 + 8; - if (*cbBufferEnd + lineLen > *cbBufferAlloced) - { - cbBufferAlloced[0] += (lineLen + 1024 - lineLen % 1024); - *buffer = (char *) mir_realloc(*buffer, *cbBufferAlloced); - } - - d = *buffer + *cbBufferEnd; - strcpy(d, "{\\uc1 "); - d += 6; - - for (; *line; line++, textCharsCount++) - { - if (*line == '\r' && line[1] == '\n') - { - memcpy(d, "\\par ", 5); - line++; - d += 5; - } - else if (*line == '\n') { - memcpy(d, "\\par ", 5); - d += 5; - } - else if (*line == '\t') - { - memcpy(d, "\\tab ", 5); - d += 5; - } - else if (*line == '\\' || *line == '{' || *line == '}') - { - *d++ = '\\'; - *d++ = (char) *line; - } - else if (*line == '[' && (g_dat->flags & SMF_SHOWFORMAT)) - { - int i, found = 0; - for (i = 0; i < SIZEOF(bbcodes); ++i) - { - if (line[1] == bbcodes[i][1]) - { - size_t lenb = _tcslen(bbcodes[i]); - if (!_tcsnicmp(line, bbcodes[i], lenb)) - { - size_t len = strlen(bbcodefmt[i]); - memcpy(d, bbcodefmt[i], len); - d += len; - line += lenb - 1; - found = 1; - break; - } - } - } - if (!found) - { - if (!_tcsnicmp(line, _T("[url"), 4)) - { - TCHAR* tag = _tcschr(line + 4, ']'); - if (tag) - { - TCHAR *tagu = (line[4] == '=') ? line + 5 : tag + 1; - TCHAR *tage = _tcsstr(tag, _T("[/url]")); - if (!tage) tage = _tcsstr(tag, _T("[/URL]")); - if (tage) - { - *tag = 0; - *tage = 0; - d += sprintf(d, "{\\field{\\*\\fldinst HYPERLINK \"%s\"}{\\fldrslt %s}}", mir_t2a(tagu), mir_t2a(tag + 1)); -// d += sprintf(d, "{\\field{\\*\\fldinst HYPERLINK \"%s\"}{\\fldrslt \\ul\\cf%d %s}}", mir_t2a(tagu), msgDlgFontCount, mir_t2a(tag + 1)); - line = tage + 5; - found = 1; - } - } - } - else if (!_tcsnicmp(line, _T("[color="), 7)) - { - TCHAR* tag = _tcschr(line + 7, ']'); - if (tag) - { - line = tag; - found = 1; - } - } - else if (!_tcsnicmp(line, _T("[/color]"), 8)) - { - line += 7; - found = 1; - } - } - if (!found) - { - if (*line < 128) *d++ = (char) *line; - else d += sprintf(d, "\\u%d ?", *line); - } - } - else if (*line < 128) *d++ = (char) *line; - else d += sprintf(d, "\\u%d ?", *line); - } - - *(d++) = '}'; - *d = 0; - - *cbBufferEnd = (int) (d - *buffer); - return textCharsCount; -} - -#define FONT_FORMAT "{\\f%u\\fnil\\fcharset%u %S;}" - -static char *CreateRTFHeader(struct MessageWindowData *dat) -{ - char *buffer; - int bufferAlloced, bufferEnd; - int i; - LOGFONT lf; - COLORREF colour; - HDC hdc; - - hdc = GetDC(NULL); - logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); - ReleaseDC(NULL, hdc); - bufferEnd = 0; - bufferAlloced = 1024; - buffer = (char *) mir_alloc(bufferAlloced); - buffer[0] = '\0'; - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "{\\rtf1\\ansi\\deff0{\\fonttbl"); - - for (i = 0; i < msgDlgFontCount; i++) { - LoadMsgDlgFont(i, &lf, NULL); - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, FONT_FORMAT, i, lf.lfCharSet, lf.lfFaceName); - } - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}{\\colortbl "); - for (i = 0; i < msgDlgFontCount; i++) { - LoadMsgDlgFont(i, NULL, &colour); - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - } - if (GetSysColorBrush(COLOR_HOTLIGHT) == NULL) - colour = RGB(0, 0, 255); - else - colour = GetSysColor(COLOR_HOTLIGHT); - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}"); - //AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}\\pard"); - return buffer; -} - -//mir_free() the return value -static char *CreateRTFTail(struct MessageWindowData *dat) -{ - char *buffer; - int bufferAlloced, bufferEnd; - - bufferEnd = 0; - bufferAlloced = 1024; - buffer = (char *) mir_alloc(bufferAlloced); - buffer[0] = '\0'; - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}"); - return buffer; -} - -//return value is static -static char *SetToStyle(int style) -{ - static char szStyle[128]; - LOGFONT lf; - - LoadMsgDlgFont(style, &lf, NULL); - wsprintfA(szStyle, "\\f%u\\cf%u\\b%d\\i%d\\fs%u", style, style, lf.lfWeight >= FW_BOLD ? 1 : 0, lf.lfItalic, 2 * abs(lf.lfHeight) * 74 / logPixelSY); - return szStyle; -} - -int DbEventIsForMsgWindow(DBEVENTINFO *dbei) -{ - DBEVENTTYPEDESCR* et = ( DBEVENTTYPEDESCR* )CallService( MS_DB_EVENT_GETTYPE, ( WPARAM )dbei->szModule, ( LPARAM )dbei->eventType ); - return et && ( et->flags & DETF_MSGWINDOW ); -} - -int DbEventIsShown(DBEVENTINFO * dbei, struct MessageWindowData *dat) -{ - switch (dbei->eventType) { - case EVENTTYPE_MESSAGE: - return 1; - case EVENTTYPE_JABBER_CHATSTATES: - case EVENTTYPE_JABBER_PRESENCE: - case EVENTTYPE_STATUSCHANGE: - case EVENTTYPE_FILE: - return (dbei->flags & DBEF_READ) == 0; - } - return DbEventIsForMsgWindow(dbei); -} - -//mir_free() the return value -static char *CreateRTFFromDbEvent(struct MessageWindowData *dat, HANDLE hContact, HANDLE hDbEvent, struct LogStreamData *streamData) -{ - char *buffer; - int bufferAlloced, bufferEnd; - DBEVENTINFO dbei = { 0 }; - int showColon = 0; - - dbei.cbSize = sizeof(dbei); - dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM) hDbEvent, 0); - if (dbei.cbBlob == -1) - return NULL; - dbei.pBlob = (PBYTE) mir_alloc(dbei.cbBlob); - CallService(MS_DB_EVENT_GET, (WPARAM) hDbEvent, (LPARAM) & dbei); - if (!DbEventIsShown(&dbei, dat)) { - mir_free(dbei.pBlob); - return NULL; - } - if (!(dbei.flags & DBEF_SENT) && (dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei))) - { - CallService(MS_DB_EVENT_MARKREAD, (WPARAM) hContact, (LPARAM) hDbEvent); - CallService(MS_CLIST_REMOVEEVENT, (WPARAM) hContact, (LPARAM) hDbEvent); - } - else if (dbei.eventType == EVENTTYPE_STATUSCHANGE || dbei.eventType == EVENTTYPE_JABBER_CHATSTATES || dbei.eventType == EVENTTYPE_JABBER_PRESENCE) { - CallService(MS_DB_EVENT_MARKREAD, (WPARAM) hContact, (LPARAM) hDbEvent); - } - bufferEnd = 0; - bufferAlloced = 1024; - buffer = (char *) mir_alloc(bufferAlloced); - buffer[0] = '\0'; - - if (!dat->bIsAutoRTL && !streamData->isEmpty) - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\par"); - - if (dbei.flags & DBEF_RTL) { - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\rtlpar"); - dat->bIsAutoRTL = TRUE; - } - else - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\ltrpar"); - - streamData->isEmpty = 0; - - if (dat->bIsAutoRTL) { - if(dbei.flags & DBEF_RTL) { - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\ltrch\\rtlch"); - }else{ - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\rtlch\\ltrch"); - } - } - - if (g_dat->flags&SMF_SHOWICONS) { - int i; - - switch (dbei.eventType) { - case EVENTTYPE_MESSAGE: - if (dbei.flags & DBEF_SENT) { - i = LOGICON_MSG_OUT; - } - else { - i = LOGICON_MSG_IN; - } - break; - case EVENTTYPE_JABBER_CHATSTATES: - case EVENTTYPE_JABBER_PRESENCE: - case EVENTTYPE_STATUSCHANGE: - case EVENTTYPE_FILE: - default: - i = LOGICON_MSG_NOTICE; - break; - } - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\f0\\fs14"); - while (bufferAlloced - bufferEnd < logIconBmpSize[i]) - bufferAlloced += 1024; - buffer = (char *) mir_realloc(buffer, bufferAlloced); - CopyMemory(buffer + bufferEnd, pLogIconBmpBits[i], logIconBmpSize[i]); - bufferEnd += logIconBmpSize[i]; - } - if (g_dat->flags & SMF_SHOWTIME) - { - const TCHAR* szFormat; - TCHAR str[64]; - - if (g_dat->flags & SMF_SHOWSECS) - szFormat = g_dat->flags & SMF_SHOWDATE ? _T("d s") : _T("s"); - else - szFormat = g_dat->flags & SMF_SHOWDATE ? _T("d t") : _T("t"); - - tmi.printTimeStamp(NULL, dbei.timestamp, szFormat, str, SIZEOF(str), 0); - - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYTIME : MSGFONTID_YOURTIME)); - AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, str); - showColon = 1; - } - if (!(g_dat->flags&SMF_HIDENAMES) && dbei.eventType != EVENTTYPE_STATUSCHANGE && dbei.eventType != EVENTTYPE_JABBER_CHATSTATES && dbei.eventType != EVENTTYPE_JABBER_PRESENCE) { - TCHAR* szName; - CONTACTINFO ci = {0}; - - if (dbei.flags & DBEF_SENT) { - ci.cbSize = sizeof(ci); - ci.szProto = dbei.szModule; - ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; - if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) { - // CNF_DISPLAY always returns a string type - szName = ci.pszVal; - } - } - else szName = ( TCHAR* ) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR); - - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYNAME : MSGFONTID_YOURNAME)); - AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, szName); - showColon = 1; - if (ci.pszVal) - mir_free(ci.pszVal); - } - - if (showColon) - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "%s :", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYCOLON : MSGFONTID_YOURCOLON)); - - switch (dbei.eventType) { - default: - case EVENTTYPE_MESSAGE: - { - TCHAR* msg = DbGetEventTextT( &dbei, CP_ACP ); - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYMSG : MSGFONTID_YOURMSG)); - AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, msg); - - mir_free(msg); - break; - } - case EVENTTYPE_JABBER_CHATSTATES: - case EVENTTYPE_JABBER_PRESENCE: - case EVENTTYPE_STATUSCHANGE: - { - TCHAR *msg, *szName; - CONTACTINFO ci = {0}; - - if (dbei.flags & DBEF_SENT) { - ci.cbSize = sizeof(ci); - ci.hContact = NULL; - ci.szProto = dbei.szModule; - ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; - - if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) { - // CNF_DISPLAY always returns a string type - szName = ci.pszVal; - } - } - else szName = ( TCHAR* )CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR); - - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(MSGFONTID_NOTICE)); - AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, szName); - AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, _T(" ")); - - msg = DbGetEventTextT( &dbei, CP_ACP ); - if ( msg ) { - AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, msg); - mir_free( msg ); - } - mir_free(ci.pszVal); - break; - } - case EVENTTYPE_FILE: - { - char* filename = dbei.pBlob + sizeof(DWORD); - char* descr = filename + strlen( filename ) + 1; - TCHAR* ptszFileName = DbGetEventStringT( &dbei, filename ); - - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(MSGFONTID_NOTICE)); - AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, - (dbei.flags & DBEF_SENT) ? TranslateT("File sent") : TranslateT("File received")); - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, ": "); - AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, ptszFileName); - mir_free( ptszFileName ); - - if ( *descr != 0 ) { - TCHAR* ptszDescr = DbGetEventStringT( &dbei, descr ); - AppendToBuffer( &buffer, &bufferEnd, &bufferAlloced, " (" ); - AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, ptszDescr); - AppendToBuffer( &buffer, &bufferEnd, &bufferAlloced, ")" ); - mir_free( ptszDescr ); - } - break; - } } - - if(dat->bIsAutoRTL) - AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\par"); - - mir_free(dbei.pBlob); - return buffer; -} - -static DWORD CALLBACK LogStreamInEvents(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb) -{ - struct LogStreamData *dat = (struct LogStreamData *) dwCookie; - - if (dat->buffer == NULL) - { - dat->bufferOffset = 0; - switch (dat->stage) - { - case STREAMSTAGE_HEADER: - dat->buffer = CreateRTFHeader(dat->dlgDat); - dat->stage = STREAMSTAGE_EVENTS; - break; - - case STREAMSTAGE_EVENTS: - if (dat->eventsToInsert) - { - do - { - dat->buffer = CreateRTFFromDbEvent(dat->dlgDat, dat->hContact, dat->hDbEvent, dat); - if (dat->buffer) - dat->hDbEventLast = dat->hDbEvent; - dat->hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) dat->hDbEvent, 0); - if (--dat->eventsToInsert == 0) - break; - } while (dat->buffer == NULL && dat->hDbEvent); - if (dat->buffer) - { - dat->isEmpty = 0; - break; - } - } - dat->stage = STREAMSTAGE_TAIL; - //fall through - case STREAMSTAGE_TAIL: - dat->buffer = CreateRTFTail(dat->dlgDat); - dat->stage = STREAMSTAGE_STOP; - break; - case STREAMSTAGE_STOP: - *pcb = 0; - return 0; - } - dat->bufferLen = (int)strlen(dat->buffer); - } - *pcb = min(cb, dat->bufferLen - dat->bufferOffset); - CopyMemory(pbBuff, dat->buffer + dat->bufferOffset, *pcb); - dat->bufferOffset += *pcb; - if (dat->bufferOffset == dat->bufferLen) - { - mir_free(dat->buffer); - dat->buffer = NULL; - } - return 0; -} - -void StreamInEvents(HWND hwndDlg, HANDLE hDbEventFirst, int count, int fAppend) -{ - EDITSTREAM stream = {0}; - struct LogStreamData streamData = {0}; - struct MessageWindowData *dat = (struct MessageWindowData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - CHARRANGE oldSel, sel; - POINT scrollPos; - BOOL bottomScroll = TRUE; - - HWND hwndLog = GetDlgItem(hwndDlg, IDC_LOG); - - SendMessage(hwndLog, WM_SETREDRAW, FALSE, 0); - SendMessage(hwndLog, EM_EXGETSEL, 0, (LPARAM) & oldSel); - streamData.hContact = dat->hContact; - streamData.hDbEvent = hDbEventFirst; - streamData.dlgDat = dat; - streamData.eventsToInsert = count; - streamData.isEmpty = !fAppend || GetWindowTextLength(hwndLog) == 0; - stream.pfnCallback = LogStreamInEvents; - stream.dwCookie = (DWORD_PTR)&streamData; - - if (!streamData.isEmpty) - { - bottomScroll = (GetFocus() != hwndLog); - if (bottomScroll && (GetWindowLongPtr(hwndLog, GWL_STYLE) & WS_VSCROLL)) - { - SCROLLINFO si = {0}; - si.cbSize = sizeof(si); - si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; - GetScrollInfo(hwndLog, SB_VERT, &si); - bottomScroll = (si.nPos + (int)si.nPage) >= si.nMax; - } - if (!bottomScroll) - SendMessage(hwndLog, EM_GETSCROLLPOS, 0, (LPARAM) & scrollPos); - } - if (fAppend) - { - sel.cpMin = sel.cpMax = -1; - SendMessage(hwndLog, EM_EXSETSEL, 0, (LPARAM) & sel); - } - - strcpy(szSep2, fAppend ? "\\par\\sl0" : "\\sl1000"); - strcpy(szSep2_RTL, fAppend ? "\\rtlpar\\rtlmark\\par\\sl1000" : "\\sl1000"); - - SendMessage(hwndLog, EM_STREAMIN, fAppend ? SFF_SELECTION | SF_RTF : SF_RTF, (LPARAM) & stream); - if (bottomScroll) - { - sel.cpMin = sel.cpMax = -1; - SendMessage(hwndLog, EM_EXSETSEL, 0, (LPARAM) & sel); - if (GetWindowLongPtr(hwndLog, GWL_STYLE) & WS_VSCROLL) - { - SendMessage(hwndDlg, DM_SCROLLLOGTOBOTTOM, 0, 0); - PostMessage(hwndDlg, DM_SCROLLLOGTOBOTTOM, 0, 0); - } - } - else - { - SendMessage(hwndLog, EM_EXSETSEL, 0, (LPARAM) & oldSel); - SendMessage(hwndLog, EM_SETSCROLLPOS, 0, (LPARAM) & scrollPos); - } - - SendMessage(hwndLog, WM_SETREDRAW, TRUE, 0); - if (bottomScroll) - RedrawWindow(hwndLog, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); - - dat->hDbEventLast = streamData.hDbEventLast; -} - -#define RTFPICTHEADERMAXSIZE 78 -void LoadMsgLogIcons(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, SRMMMOD, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR)); - bih.biSize = sizeof(bih); - bih.biBitCount = 24; - bih.biCompression = BI_RGB; - bih.biHeight = 10; - bih.biPlanes = 1; - bih.biWidth = 10; - 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 = (HANDLE)CallService(MS_SKIN2_GETICONBYHANDLE, 0, (LPARAM)hIconLibItem[i]); - pLogIconBmpBits[i] = (PBYTE) mir_alloc(RTFPICTHEADERMAXSIZE + (bih.biSize + widthBytes * bih.biHeight) * 2); - //I can't seem to get binary mode working. No matter. - rtfHeaderSize = sprintf(pLogIconBmpBits[i], "{\\pict\\dibitmap0\\wbmbitspixel%u\\wbmplanes1\\wbmwidthbytes%u\\picw%u\\pich%u ", bih.biBitCount, widthBytes, bih.biWidth, bih.biHeight); - hoBmp = (HBITMAP) SelectObject(hdcMem, hBmp); - FillRect(hdcMem, &rc, hBkgBrush); - DrawIconEx(hdcMem, 0, 0, hIcon, bih.biWidth, bih.biHeight, 0, NULL, DI_NORMAL); - CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); - - 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 FreeMsgLogIcons(void) -{ - int i; - for (i = 0; i < SIZEOF(pLogIconBmpBits); i++) - mir_free(pLogIconBmpBits[i]); -} diff --git a/plugins/SRMM/msglog.cpp b/plugins/SRMM/msglog.cpp new file mode 100644 index 0000000000..e32c98ae50 --- /dev/null +++ b/plugins/SRMM/msglog.cpp @@ -0,0 +1,645 @@ +/* +Copyright 2000-2010 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "commonheaders.h" + +extern HANDLE hIconLibItem[]; + +static int logPixelSY; +#define LOGICON_MSG_IN 0 +#define LOGICON_MSG_OUT 1 +#define LOGICON_MSG_NOTICE 2 +static PBYTE pLogIconBmpBits[3]; +static int logIconBmpSize[ SIZEOF(pLogIconBmpBits) ]; + +#define STREAMSTAGE_HEADER 0 +#define STREAMSTAGE_EVENTS 1 +#define STREAMSTAGE_TAIL 2 +#define STREAMSTAGE_STOP 3 +struct LogStreamData +{ + int stage; + HANDLE hContact; + HANDLE hDbEvent, hDbEventLast; + char *buffer; + int bufferOffset, bufferLen; + int eventsToInsert; + int isEmpty; + struct SrmmWindowData *dlgDat; +}; + +static char szSep2[40], szSep2_RTL[50]; + +static void AppendToBuffer(char **buffer, int *cbBufferEnd, int *cbBufferAlloced, const char *fmt, ...) +{ + va_list va; + int charsDone; + + va_start(va, fmt); + for (;;) { + charsDone = mir_vsnprintf(*buffer + *cbBufferEnd, *cbBufferAlloced - *cbBufferEnd, fmt, va); + if (charsDone >= 0) + break; + *cbBufferAlloced += 1024; + *buffer = (char *) mir_realloc(*buffer, *cbBufferAlloced); + } + va_end(va); + *cbBufferEnd += charsDone; +} + +static const TCHAR *bbcodes[] = { _T("[b]"), _T("[i]"), _T("[u]"), _T("[s]"), _T("[/b]"), _T("[/i]"), _T("[/u]"), _T("[/s]") }; +static const char *bbcodefmt[] = { "\\b ", "\\i ", "\\ul ", "\\strike ", "\\b0 ", "\\i0 ", "\\ul0 ", "\\strike0 " }; + +static int AppendToBufferWithRTF(char **buffer, int *cbBufferEnd, int *cbBufferAlloced, TCHAR* line) +{ + DWORD textCharsCount = 0; + char *d; + int lineLen; + + if (line == NULL) + return 0; + + lineLen = (int)_tcslen(line) * 9 + 8; + if (*cbBufferEnd + lineLen > *cbBufferAlloced) + { + cbBufferAlloced[0] += (lineLen + 1024 - lineLen % 1024); + *buffer = (char *) mir_realloc(*buffer, *cbBufferAlloced); + } + + d = *buffer + *cbBufferEnd; + strcpy(d, "{\\uc1 "); + d += 6; + + for (; *line; line++, textCharsCount++) + { + if (*line == '\r' && line[1] == '\n') + { + memcpy(d, "\\par ", 5); + line++; + d += 5; + } + else if (*line == '\n') { + memcpy(d, "\\par ", 5); + d += 5; + } + else if (*line == '\t') + { + memcpy(d, "\\tab ", 5); + d += 5; + } + else if (*line == '\\' || *line == '{' || *line == '}') + { + *d++ = '\\'; + *d++ = (char) *line; + } + else if (*line == '[' && (g_dat->flags & SMF_SHOWFORMAT)) + { + int i, found = 0; + for (i = 0; i < SIZEOF(bbcodes); ++i) + { + if (line[1] == bbcodes[i][1]) + { + size_t lenb = _tcslen(bbcodes[i]); + if (!_tcsnicmp(line, bbcodes[i], lenb)) + { + size_t len = strlen(bbcodefmt[i]); + memcpy(d, bbcodefmt[i], len); + d += len; + line += lenb - 1; + found = 1; + break; + } + } + } + if (!found) + { + if (!_tcsnicmp(line, _T("[url"), 4)) + { + TCHAR* tag = _tcschr(line + 4, ']'); + if (tag) + { + TCHAR *tagu = (line[4] == '=') ? line + 5 : tag + 1; + TCHAR *tage = _tcsstr(tag, _T("[/url]")); + if (!tage) tage = _tcsstr(tag, _T("[/URL]")); + if (tage) + { + *tag = 0; + *tage = 0; + d += sprintf(d, "{\\field{\\*\\fldinst HYPERLINK \"%s\"}{\\fldrslt %s}}", mir_t2a(tagu), mir_t2a(tag + 1)); +// d += sprintf(d, "{\\field{\\*\\fldinst HYPERLINK \"%s\"}{\\fldrslt \\ul\\cf%d %s}}", mir_t2a(tagu), msgDlgFontCount, mir_t2a(tag + 1)); + line = tage + 5; + found = 1; + } + } + } + else if (!_tcsnicmp(line, _T("[color="), 7)) + { + TCHAR* tag = _tcschr(line + 7, ']'); + if (tag) + { + line = tag; + found = 1; + } + } + else if (!_tcsnicmp(line, _T("[/color]"), 8)) + { + line += 7; + found = 1; + } + } + if (!found) + { + if (*line < 128) *d++ = (char) *line; + else d += sprintf(d, "\\u%d ?", *line); + } + } + else if (*line < 128) *d++ = (char) *line; + else d += sprintf(d, "\\u%d ?", *line); + } + + *(d++) = '}'; + *d = 0; + + *cbBufferEnd = (int) (d - *buffer); + return textCharsCount; +} + +#define FONT_FORMAT "{\\f%u\\fnil\\fcharset%u %S;}" + +static char *CreateRTFHeader(struct SrmmWindowData *dat) +{ + char *buffer; + int bufferAlloced, bufferEnd; + int i; + LOGFONT lf; + COLORREF colour; + HDC hdc; + + hdc = GetDC(NULL); + logPixelSY = GetDeviceCaps(hdc, LOGPIXELSY); + ReleaseDC(NULL, hdc); + bufferEnd = 0; + bufferAlloced = 1024; + buffer = (char *) mir_alloc(bufferAlloced); + buffer[0] = '\0'; + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "{\\rtf1\\ansi\\deff0{\\fonttbl"); + + for (i = 0; i < msgDlgFontCount; i++) { + LoadMsgDlgFont(i, &lf, NULL); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, FONT_FORMAT, i, lf.lfCharSet, lf.lfFaceName); + } + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}{\\colortbl "); + for (i = 0; i < msgDlgFontCount; i++) { + LoadMsgDlgFont(i, NULL, &colour); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + } + if (GetSysColorBrush(COLOR_HOTLIGHT) == NULL) + colour = RGB(0, 0, 255); + else + colour = GetSysColor(COLOR_HOTLIGHT); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\red%u\\green%u\\blue%u;", GetRValue(colour), GetGValue(colour), GetBValue(colour)); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}"); + //AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}\\pard"); + return buffer; +} + +//mir_free() the return value +static char *CreateRTFTail(struct SrmmWindowData *dat) +{ + char *buffer; + int bufferAlloced, bufferEnd; + + bufferEnd = 0; + bufferAlloced = 1024; + buffer = (char *) mir_alloc(bufferAlloced); + buffer[0] = '\0'; + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "}"); + return buffer; +} + +//return value is static +static char *SetToStyle(int style) +{ + static char szStyle[128]; + LOGFONT lf; + + LoadMsgDlgFont(style, &lf, NULL); + wsprintfA(szStyle, "\\f%u\\cf%u\\b%d\\i%d\\fs%u", style, style, lf.lfWeight >= FW_BOLD ? 1 : 0, lf.lfItalic, 2 * abs(lf.lfHeight) * 74 / logPixelSY); + return szStyle; +} + +int DbEventIsForMsgWindow(DBEVENTINFO *dbei) +{ + DBEVENTTYPEDESCR* et = ( DBEVENTTYPEDESCR* )CallService( MS_DB_EVENT_GETTYPE, ( WPARAM )dbei->szModule, ( LPARAM )dbei->eventType ); + return et && ( et->flags & DETF_MSGWINDOW ); +} + +int DbEventIsShown(DBEVENTINFO * dbei, struct SrmmWindowData *dat) +{ + switch (dbei->eventType) { + case EVENTTYPE_MESSAGE: + return 1; + case EVENTTYPE_JABBER_CHATSTATES: + case EVENTTYPE_JABBER_PRESENCE: + case EVENTTYPE_STATUSCHANGE: + case EVENTTYPE_FILE: + return (dbei->flags & DBEF_READ) == 0; + } + return DbEventIsForMsgWindow(dbei); +} + +//mir_free() the return value +static char *CreateRTFFromDbEvent(struct SrmmWindowData *dat, HANDLE hContact, HANDLE hDbEvent, struct LogStreamData *streamData) +{ + char *buffer; + int bufferAlloced, bufferEnd; + DBEVENTINFO dbei = { 0 }; + int showColon = 0; + + dbei.cbSize = sizeof(dbei); + dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM) hDbEvent, 0); + if (dbei.cbBlob == -1) + return NULL; + dbei.pBlob = (PBYTE) mir_alloc(dbei.cbBlob); + CallService(MS_DB_EVENT_GET, (WPARAM) hDbEvent, (LPARAM) & dbei); + if (!DbEventIsShown(&dbei, dat)) { + mir_free(dbei.pBlob); + return NULL; + } + if (!(dbei.flags & DBEF_SENT) && (dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei))) + { + CallService(MS_DB_EVENT_MARKREAD, (WPARAM) hContact, (LPARAM) hDbEvent); + CallService(MS_CLIST_REMOVEEVENT, (WPARAM) hContact, (LPARAM) hDbEvent); + } + else if (dbei.eventType == EVENTTYPE_STATUSCHANGE || dbei.eventType == EVENTTYPE_JABBER_CHATSTATES || dbei.eventType == EVENTTYPE_JABBER_PRESENCE) { + CallService(MS_DB_EVENT_MARKREAD, (WPARAM) hContact, (LPARAM) hDbEvent); + } + bufferEnd = 0; + bufferAlloced = 1024; + buffer = (char *) mir_alloc(bufferAlloced); + buffer[0] = '\0'; + + if (!dat->bIsAutoRTL && !streamData->isEmpty) + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\par"); + + if (dbei.flags & DBEF_RTL) { + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\rtlpar"); + dat->bIsAutoRTL = TRUE; + } + else + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\ltrpar"); + + streamData->isEmpty = 0; + + if (dat->bIsAutoRTL) { + if(dbei.flags & DBEF_RTL) { + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\ltrch\\rtlch"); + }else{ + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\rtlch\\ltrch"); + } + } + + if (g_dat->flags&SMF_SHOWICONS) { + int i; + + switch (dbei.eventType) { + case EVENTTYPE_MESSAGE: + if (dbei.flags & DBEF_SENT) { + i = LOGICON_MSG_OUT; + } + else { + i = LOGICON_MSG_IN; + } + break; + case EVENTTYPE_JABBER_CHATSTATES: + case EVENTTYPE_JABBER_PRESENCE: + case EVENTTYPE_STATUSCHANGE: + case EVENTTYPE_FILE: + default: + i = LOGICON_MSG_NOTICE; + break; + } + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\f0\\fs14"); + while (bufferAlloced - bufferEnd < logIconBmpSize[i]) + bufferAlloced += 1024; + buffer = (char *) mir_realloc(buffer, bufferAlloced); + CopyMemory(buffer + bufferEnd, pLogIconBmpBits[i], logIconBmpSize[i]); + bufferEnd += logIconBmpSize[i]; + } + if (g_dat->flags & SMF_SHOWTIME) + { + const TCHAR* szFormat; + TCHAR str[64]; + + if (g_dat->flags & SMF_SHOWSECS) + szFormat = g_dat->flags & SMF_SHOWDATE ? _T("d s") : _T("s"); + else + szFormat = g_dat->flags & SMF_SHOWDATE ? _T("d t") : _T("t"); + + tmi.printTimeStamp(NULL, dbei.timestamp, szFormat, str, SIZEOF(str), 0); + + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYTIME : MSGFONTID_YOURTIME)); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, str); + showColon = 1; + } + if (!(g_dat->flags&SMF_HIDENAMES) && dbei.eventType != EVENTTYPE_STATUSCHANGE && dbei.eventType != EVENTTYPE_JABBER_CHATSTATES && dbei.eventType != EVENTTYPE_JABBER_PRESENCE) { + TCHAR* szName; + CONTACTINFO ci = {0}; + + if (dbei.flags & DBEF_SENT) { + ci.cbSize = sizeof(ci); + ci.szProto = dbei.szModule; + ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; + if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) { + // CNF_DISPLAY always returns a string type + szName = ci.pszVal; + } + } + else szName = ( TCHAR* ) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR); + + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYNAME : MSGFONTID_YOURNAME)); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, szName); + showColon = 1; + if (ci.pszVal) + mir_free(ci.pszVal); + } + + if (showColon) + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "%s :", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYCOLON : MSGFONTID_YOURCOLON)); + + switch (dbei.eventType) { + default: + case EVENTTYPE_MESSAGE: + { + TCHAR* msg = DbGetEventTextT( &dbei, CP_ACP ); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYMSG : MSGFONTID_YOURMSG)); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, msg); + + mir_free(msg); + break; + } + case EVENTTYPE_JABBER_CHATSTATES: + case EVENTTYPE_JABBER_PRESENCE: + case EVENTTYPE_STATUSCHANGE: + { + TCHAR *msg, *szName; + CONTACTINFO ci = {0}; + + if (dbei.flags & DBEF_SENT) { + ci.cbSize = sizeof(ci); + ci.hContact = NULL; + ci.szProto = dbei.szModule; + ci.dwFlag = CNF_DISPLAY | CNF_TCHAR; + + if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci)) { + // CNF_DISPLAY always returns a string type + szName = ci.pszVal; + } + } + else szName = ( TCHAR* )CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR); + + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(MSGFONTID_NOTICE)); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, szName); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, _T(" ")); + + msg = DbGetEventTextT( &dbei, CP_ACP ); + if ( msg ) { + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, msg); + mir_free( msg ); + } + mir_free(ci.pszVal); + break; + } + case EVENTTYPE_FILE: + { + char* filename = (char*)dbei.pBlob + sizeof(DWORD); + char* descr = filename + strlen( filename ) + 1; + TCHAR* ptszFileName = DbGetEventStringT( &dbei, filename ); + + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, " %s ", SetToStyle(MSGFONTID_NOTICE)); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, + (dbei.flags & DBEF_SENT) ? TranslateT("File sent") : TranslateT("File received")); + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, ": "); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, ptszFileName); + mir_free( ptszFileName ); + + if ( *descr != 0 ) { + TCHAR* ptszDescr = DbGetEventStringT( &dbei, descr ); + AppendToBuffer( &buffer, &bufferEnd, &bufferAlloced, " (" ); + AppendToBufferWithRTF(&buffer, &bufferEnd, &bufferAlloced, ptszDescr); + AppendToBuffer( &buffer, &bufferEnd, &bufferAlloced, ")" ); + mir_free( ptszDescr ); + } + break; + } } + + if(dat->bIsAutoRTL) + AppendToBuffer(&buffer, &bufferEnd, &bufferAlloced, "\\par"); + + mir_free(dbei.pBlob); + return buffer; +} + +static DWORD CALLBACK LogStreamInEvents(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb) +{ + struct LogStreamData *dat = (struct LogStreamData *) dwCookie; + + if (dat->buffer == NULL) + { + dat->bufferOffset = 0; + switch (dat->stage) + { + case STREAMSTAGE_HEADER: + dat->buffer = CreateRTFHeader(dat->dlgDat); + dat->stage = STREAMSTAGE_EVENTS; + break; + + case STREAMSTAGE_EVENTS: + if (dat->eventsToInsert) + { + do + { + dat->buffer = CreateRTFFromDbEvent(dat->dlgDat, dat->hContact, dat->hDbEvent, dat); + if (dat->buffer) + dat->hDbEventLast = dat->hDbEvent; + dat->hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) dat->hDbEvent, 0); + if (--dat->eventsToInsert == 0) + break; + } while (dat->buffer == NULL && dat->hDbEvent); + if (dat->buffer) + { + dat->isEmpty = 0; + break; + } + } + dat->stage = STREAMSTAGE_TAIL; + //fall through + case STREAMSTAGE_TAIL: + dat->buffer = CreateRTFTail(dat->dlgDat); + dat->stage = STREAMSTAGE_STOP; + break; + case STREAMSTAGE_STOP: + *pcb = 0; + return 0; + } + dat->bufferLen = (int)strlen(dat->buffer); + } + *pcb = min(cb, dat->bufferLen - dat->bufferOffset); + CopyMemory(pbBuff, dat->buffer + dat->bufferOffset, *pcb); + dat->bufferOffset += *pcb; + if (dat->bufferOffset == dat->bufferLen) + { + mir_free(dat->buffer); + dat->buffer = NULL; + } + return 0; +} + +void StreamInEvents(HWND hwndDlg, HANDLE hDbEventFirst, int count, int fAppend) +{ + EDITSTREAM stream = {0}; + struct LogStreamData streamData = {0}; + struct SrmmWindowData *dat = (struct SrmmWindowData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + CHARRANGE oldSel, sel; + POINT scrollPos; + BOOL bottomScroll = TRUE; + + HWND hwndLog = GetDlgItem(hwndDlg, IDC_LOG); + + SendMessage(hwndLog, WM_SETREDRAW, FALSE, 0); + SendMessage(hwndLog, EM_EXGETSEL, 0, (LPARAM) & oldSel); + streamData.hContact = dat->hContact; + streamData.hDbEvent = hDbEventFirst; + streamData.dlgDat = dat; + streamData.eventsToInsert = count; + streamData.isEmpty = !fAppend || GetWindowTextLength(hwndLog) == 0; + stream.pfnCallback = LogStreamInEvents; + stream.dwCookie = (DWORD_PTR)&streamData; + + if (!streamData.isEmpty) + { + bottomScroll = (GetFocus() != hwndLog); + if (bottomScroll && (GetWindowLongPtr(hwndLog, GWL_STYLE) & WS_VSCROLL)) + { + SCROLLINFO si = {0}; + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS; + GetScrollInfo(hwndLog, SB_VERT, &si); + bottomScroll = (si.nPos + (int)si.nPage) >= si.nMax; + } + if (!bottomScroll) + SendMessage(hwndLog, EM_GETSCROLLPOS, 0, (LPARAM) & scrollPos); + } + if (fAppend) + { + sel.cpMin = sel.cpMax = -1; + SendMessage(hwndLog, EM_EXSETSEL, 0, (LPARAM) & sel); + } + + strcpy(szSep2, fAppend ? "\\par\\sl0" : "\\sl1000"); + strcpy(szSep2_RTL, fAppend ? "\\rtlpar\\rtlmark\\par\\sl1000" : "\\sl1000"); + + SendMessage(hwndLog, EM_STREAMIN, fAppend ? SFF_SELECTION | SF_RTF : SF_RTF, (LPARAM) & stream); + if (bottomScroll) + { + sel.cpMin = sel.cpMax = -1; + SendMessage(hwndLog, EM_EXSETSEL, 0, (LPARAM) & sel); + if (GetWindowLongPtr(hwndLog, GWL_STYLE) & WS_VSCROLL) + { + SendMessage(hwndDlg, DM_SCROLLLOGTOBOTTOM, 0, 0); + PostMessage(hwndDlg, DM_SCROLLLOGTOBOTTOM, 0, 0); + } + } + else + { + SendMessage(hwndLog, EM_EXSETSEL, 0, (LPARAM) & oldSel); + SendMessage(hwndLog, EM_SETSCROLLPOS, 0, (LPARAM) & scrollPos); + } + + SendMessage(hwndLog, WM_SETREDRAW, TRUE, 0); + if (bottomScroll) + RedrawWindow(hwndLog, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); + + dat->hDbEventLast = streamData.hDbEventLast; +} + +#define RTFPICTHEADERMAXSIZE 78 +void LoadMsgLogIcons(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, SRMMMOD, SRMSGSET_BKGCOLOUR, SRMSGDEFSET_BKGCOLOUR)); + bih.biSize = sizeof(bih); + bih.biBitCount = 24; + bih.biCompression = BI_RGB; + bih.biHeight = 10; + bih.biPlanes = 1; + bih.biWidth = 10; + 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 = Skin_GetIconByHandle(hIconLibItem[i]); + pLogIconBmpBits[i] = (PBYTE) mir_alloc(RTFPICTHEADERMAXSIZE + (bih.biSize + widthBytes * bih.biHeight) * 2); + //I can't seem to get binary mode working. No matter. + rtfHeaderSize = sprintf((char*)pLogIconBmpBits[i], "{\\pict\\dibitmap0\\wbmbitspixel%u\\wbmplanes1\\wbmwidthbytes%u\\picw%u\\pich%u ", bih.biBitCount, widthBytes, bih.biWidth, bih.biHeight); + hoBmp = (HBITMAP) SelectObject(hdcMem, hBmp); + FillRect(hdcMem, &rc, hBkgBrush); + DrawIconEx(hdcMem, 0, 0, hIcon, bih.biWidth, bih.biHeight, 0, NULL, DI_NORMAL); + CallService(MS_SKIN2_RELEASEICON, (WPARAM)hIcon, 0); + + SelectObject(hdcMem, hoBmp); + GetDIBits(hdc, hBmp, 0, bih.biHeight, pBmpBits, (BITMAPINFO *) & bih, DIB_RGB_COLORS); + { + int n; + for (n = 0; n < sizeof(BITMAPINFOHEADER); n++) + sprintf((char*)pLogIconBmpBits[i] + rtfHeaderSize + n * 2, "%02X", ((PBYTE) & bih)[n]); + for (n = 0; n < widthBytes * bih.biHeight; n += 4) + sprintf((char*)pLogIconBmpBits[i] + rtfHeaderSize + (bih.biSize + n) * 2, "%02X%02X%02X%02X", pBmpBits[n], pBmpBits[n + 1], pBmpBits[n + 2], pBmpBits[n + 3]); + } + logIconBmpSize[i] = rtfHeaderSize + (bih.biSize + widthBytes * bih.biHeight) * 2 + 1; + pLogIconBmpBits[i][logIconBmpSize[i] - 1] = '}'; + } + mir_free(pBmpBits); + DeleteDC(hdcMem); + DeleteObject(hBmp); + ReleaseDC(NULL, hdc); + DeleteObject(hBkgBrush); +} + +void FreeMsgLogIcons(void) +{ + int i; + for (i = 0; i < SIZEOF(pLogIconBmpBits); i++) + mir_free(pLogIconBmpBits[i]); +} diff --git a/plugins/SRMM/msgoptions.c b/plugins/SRMM/msgoptions.c deleted file mode 100644 index 86e8c0321f..0000000000 --- a/plugins/SRMM/msgoptions.c +++ /dev/null @@ -1,658 +0,0 @@ -/* -Copyright 2000-2010 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ -#include "commonheaders.h" - -#include "m_fontservice.h" -#include "m_modernopt.h" - -#define FONTF_BOLD 1 -#define FONTF_ITALIC 2 -struct FontOptionsList -{ - const TCHAR* szDescr; - COLORREF defColour; - const TCHAR* szDefFace; - BYTE defStyle; - char defSize; -} -static const fontOptionsList[] = -{ - { LPGENT("Outgoing messages"), RGB(106, 106, 106), _T("Arial"), 0, -12}, - { LPGENT("Incoming messages"), RGB(0, 0, 0), _T("Arial"), 0, -12}, - { LPGENT("Outgoing name"), RGB(89, 89, 89), _T("Arial"), FONTF_BOLD, -12}, - { LPGENT("Outgoing time"), RGB(0, 0, 0), _T("Terminal"), FONTF_BOLD, -9}, - { LPGENT("Outgoing colon"), RGB(89, 89, 89), _T("Arial"), 0, -11}, - { LPGENT("Incoming name"), RGB(215, 0, 0), _T("Arial"), FONTF_BOLD, -12}, - { LPGENT("Incoming time"), RGB(0, 0, 0), _T("Terminal"), FONTF_BOLD, -9}, - { LPGENT("Incoming colon"), RGB(215, 0, 0), _T("Arial"), 0, -11}, - { LPGENT("Message area"), RGB(0, 0, 0), _T("Arial"), 0, -12}, - { LPGENT("Notices"), RGB(90, 90, 160), _T("Arial"), 0, -12}, -}; - -const int msgDlgFontCount = SIZEOF(fontOptionsList); - -static BYTE MsgDlgGetFontDefaultCharset(const TCHAR* szFont) -{ - return DEFAULT_CHARSET; -} - -void LoadMsgDlgFont(int i, LOGFONT* lf, COLORREF * colour) -{ - char str[32]; - int style; - DBVARIANT dbv; - - if ( colour ) { - mir_snprintf(str, SIZEOF(str), "SRMFont%dCol", i); - *colour = DBGetContactSettingDword(NULL, SRMMMOD, str, fontOptionsList[i].defColour); - } - if ( lf ) { - mir_snprintf(str, SIZEOF(str), "SRMFont%dSize", i); - lf->lfHeight = (char) DBGetContactSettingByte(NULL, SRMMMOD, str, fontOptionsList[i].defSize); - lf->lfWidth = 0; - lf->lfEscapement = 0; - lf->lfOrientation = 0; - mir_snprintf(str, SIZEOF(str), "SRMFont%dSty", i); - style = DBGetContactSettingByte(NULL, SRMMMOD, str, fontOptionsList[i].defStyle); - lf->lfWeight = style & FONTF_BOLD ? FW_BOLD : FW_NORMAL; - lf->lfItalic = style & FONTF_ITALIC ? 1 : 0; - lf->lfUnderline = 0; - lf->lfStrikeOut = 0; - lf->lfOutPrecision = OUT_DEFAULT_PRECIS; - lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; - lf->lfQuality = DEFAULT_QUALITY; - lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; - mir_snprintf(str, SIZEOF(str), "SRMFont%d", i); - if (DBGetContactSettingTString(NULL, SRMMMOD, str, &dbv)) - _tcscpy(lf->lfFaceName, fontOptionsList[i].szDefFace); - else { - lstrcpyn(lf->lfFaceName, dbv.ptszVal, SIZEOF(lf->lfFaceName)); - DBFreeVariant(&dbv); - } - mir_snprintf(str, SIZEOF(str), "SRMFont%dSet", i); - lf->lfCharSet = DBGetContactSettingByte(NULL, SRMMMOD, str, MsgDlgGetFontDefaultCharset(lf->lfFaceName)); -} } - -void RegisterSRMMFonts( void ) -{ - FontIDT fontid = {0}; - ColourIDT colourid = {0}; - char idstr[10]; - int i, index = 0; - - fontid.cbSize = sizeof(FontID); - fontid.flags = FIDF_ALLOWREREGISTER | FIDF_DEFAULTVALID; - for ( i = 0; i < msgDlgFontCount; i++, index++ ) { - strcpy(fontid.dbSettingsGroup, SRMMMOD); - _tcscpy(fontid.group, LPGENT("Message Log")); - _tcscpy(fontid.name, fontOptionsList[i].szDescr); - mir_snprintf(idstr, SIZEOF(idstr), "SRMFont%d", index); - strcpy(fontid.prefix, idstr); - fontid.order = index; - - fontid.flags &= ~FIDF_CLASSMASK; - fontid.flags |= (fontOptionsList[i].defStyle == FONTF_BOLD) ? FIDF_CLASSHEADER : FIDF_CLASSGENERAL; - - fontid.deffontsettings.colour = fontOptionsList[i].defColour; - fontid.deffontsettings.size = fontOptionsList[i].defSize; - fontid.deffontsettings.style = fontOptionsList[i].defStyle; - _tcscpy(fontid.deffontsettings.szFace, fontOptionsList[i].szDefFace); - fontid.deffontsettings.charset = MsgDlgGetFontDefaultCharset(fontOptionsList[i].szDefFace); - CallService(MS_FONT_REGISTERT, (WPARAM)&fontid, 0); - } - - colourid.cbSize = sizeof(ColourID); - strcpy(colourid.dbSettingsGroup, SRMMMOD); - strcpy(colourid.setting, SRMSGSET_BKGCOLOUR); - colourid.defcolour = SRMSGDEFSET_BKGCOLOUR; - _tcscpy(colourid.name, LPGENT("Background")); - _tcscpy(colourid.group, LPGENT("Message Log")); - CallService(MS_COLOUR_REGISTERT, (WPARAM)&colourid, 0); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -struct CheckBoxValues_t -{ - DWORD style; - TCHAR* szDescr; -} -static const statusValues[] = -{ - { MODEF_OFFLINE, LPGENT("Offline") }, - { PF2_ONLINE, LPGENT("Online") }, - { PF2_SHORTAWAY, LPGENT("Away") }, - { PF2_LONGAWAY, LPGENT("NA") }, - { PF2_LIGHTDND, LPGENT("Occupied") }, - { PF2_HEAVYDND, LPGENT("DND") }, - { PF2_FREECHAT, LPGENT("Free for chat") }, - { PF2_INVISIBLE, LPGENT("Invisible") }, - { PF2_OUTTOLUNCH, LPGENT("Out to lunch") }, - { PF2_ONTHEPHONE, LPGENT("On the phone") } -}; - -static void FillCheckBoxTree(HWND hwndTree, const struct CheckBoxValues_t *values, int nValues, DWORD style) -{ - TVINSERTSTRUCT tvis; - int i; - - tvis.hParent = NULL; - tvis.hInsertAfter = TVI_LAST; - tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_STATE; - for (i = 0; i < nValues; i++) { - tvis.item.lParam = values[i].style; - tvis.item.pszText = TranslateTS(values[i].szDescr); - tvis.item.stateMask = TVIS_STATEIMAGEMASK; - tvis.item.state = INDEXTOSTATEIMAGEMASK((style & tvis.item.lParam) != 0 ? 2 : 1); - TreeView_InsertItem( hwndTree, &tvis ); -} } - -static DWORD MakeCheckBoxTreeFlags(HWND hwndTree) -{ - DWORD flags = 0; - TVITEM tvi; - - tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE; - tvi.hItem = TreeView_GetRoot(hwndTree); - while (tvi.hItem) { - TreeView_GetItem(hwndTree, &tvi); - if (((tvi.state & TVIS_STATEIMAGEMASK) >> 12 == 2)) - flags |= tvi.lParam; - tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem); - } - return flags; -} - -static INT_PTR CALLBACK DlgProcOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_INITDIALOG: - { - DWORD avatarHeight, msgTimeout; - - TranslateDialogDefault(hwndDlg); - SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_POPLIST), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_POPLIST), GWL_STYLE) | TVS_NOHSCROLL | TVS_CHECKBOXES); - FillCheckBoxTree(GetDlgItem(hwndDlg, IDC_POPLIST), statusValues, SIZEOF(statusValues), DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_POPFLAGS, SRMSGDEFSET_POPFLAGS)); - CheckDlgButton(hwndDlg, IDC_DONOTSTEALFOCUS, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DONOTSTEALFOCUS, SRMSGDEFSET_DONOTSTEALFOCUS)); - SetDlgItemInt(hwndDlg, IDC_NFLASHES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, SRMSGDEFSET_FLASHCOUNT), FALSE); - CheckDlgButton(hwndDlg, IDC_SHOWBUTTONLINE, g_dat->flags&SMF_SHOWBTNS); - CheckDlgButton(hwndDlg, IDC_SHOWINFOLINE, g_dat->flags&SMF_SHOWINFO); - CheckDlgButton(hwndDlg, IDC_AUTOMIN, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOMIN, SRMSGDEFSET_AUTOMIN)); - CheckDlgButton(hwndDlg, IDC_AUTOCLOSE, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, SRMSGDEFSET_AUTOCLOSE)); - CheckDlgButton(hwndDlg, IDC_SAVEPERCONTACT, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)); - CheckDlgButton(hwndDlg, IDC_CASCADE, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CASCADE, SRMSGDEFSET_CASCADE)); - CheckDlgButton(hwndDlg, IDC_SENDONENTER, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONENTER, SRMSGDEFSET_SENDONENTER)); - CheckDlgButton(hwndDlg, IDC_SENDONDBLENTER, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONDBLENTER, SRMSGDEFSET_SENDONDBLENTER)); - CheckDlgButton(hwndDlg, IDC_STATUSWIN, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON)); - - CheckDlgButton(hwndDlg, IDC_AVATARSUPPORT, g_dat->flags&SMF_AVATAR); - CheckDlgButton(hwndDlg, IDC_LIMITAVATARH, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, SRMSGDEFSET_LIMITAVHEIGHT)); - avatarHeight = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, SRMSGDEFSET_AVHEIGHT); - SetDlgItemInt(hwndDlg, IDC_AVATARHEIGHT, avatarHeight, FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_LIMITAVATARH), IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)); - if (!IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)) - EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), FALSE); - else EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH)); - CheckDlgButton(hwndDlg, IDC_SHOWSENDBTN, g_dat->flags&SMF_SENDBTN); - CheckDlgButton(hwndDlg, IDC_CHARCOUNT, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CHARCOUNT, SRMSGDEFSET_CHARCOUNT)); - CheckDlgButton(hwndDlg, IDC_CTRLSUPPORT, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CTRLSUPPORT, SRMSGDEFSET_CTRLSUPPORT)); - CheckDlgButton(hwndDlg, IDC_DELTEMP, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DELTEMP, SRMSGDEFSET_DELTEMP)); - msgTimeout = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_MSGTIMEOUT, SRMSGDEFSET_MSGTIMEOUT); - SetDlgItemInt(hwndDlg, IDC_SECONDS, msgTimeout >= SRMSGSET_MSGTIMEOUT_MIN ? msgTimeout / 1000 : SRMSGDEFSET_MSGTIMEOUT / 1000, FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_CASCADE), !IsDlgButtonChecked(hwndDlg, IDC_SAVEPERCONTACT)); - EnableWindow(GetDlgItem(hwndDlg, IDC_CTRLSUPPORT), !IsDlgButtonChecked(hwndDlg, IDC_AUTOCLOSE)); - return TRUE; - } - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_AUTOMIN: - CheckDlgButton(hwndDlg, IDC_AUTOCLOSE, BST_UNCHECKED); - break; - case IDC_AUTOCLOSE: - CheckDlgButton(hwndDlg, IDC_AUTOMIN, BST_UNCHECKED); - EnableWindow(GetDlgItem(hwndDlg, IDC_CTRLSUPPORT), !IsDlgButtonChecked(hwndDlg, IDC_AUTOCLOSE)); - break; - case IDC_SENDONENTER: - CheckDlgButton(hwndDlg, IDC_SENDONDBLENTER, BST_UNCHECKED); - break; - case IDC_SENDONDBLENTER: - CheckDlgButton(hwndDlg, IDC_SENDONENTER, BST_UNCHECKED); - break; - case IDC_SAVEPERCONTACT: - EnableWindow(GetDlgItem(hwndDlg, IDC_CASCADE), !IsDlgButtonChecked(hwndDlg, IDC_SAVEPERCONTACT)); - break; - case IDC_SECONDS: - if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()) - return 0; - break; - case IDC_AVATARSUPPORT: - EnableWindow(GetDlgItem(hwndDlg, IDC_LIMITAVATARH), IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)); - if (!IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)) - EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), FALSE); - else EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH)); - break; - case IDC_LIMITAVATARH: - EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH)); - break; - case IDC_AVATARHEIGHT: - if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()) - return 0; - break; - } - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - case WM_NOTIFY: - switch (((LPNMHDR) lParam)->idFrom) { - case IDC_POPLIST: - 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) { - TVITEM tvi; - tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; - tvi.hItem = hti.hItem; - TreeView_GetItem(((LPNMHDR) lParam)->hwndFrom, &tvi); - tvi.iImage = tvi.iSelectedImage = tvi.iImage == 1 ? 2 : 1; - TreeView_SetItem(((LPNMHDR) lParam)->hwndFrom, &tvi); - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - } - } - break; - case 0: - switch (((LPNMHDR) lParam)->code) { - case PSN_APPLY: - { - DWORD avatarHeight, msgTimeout; - - DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_POPFLAGS, MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg, IDC_POPLIST))); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_DONOTSTEALFOCUS, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DONOTSTEALFOCUS)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWBUTTONLINE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWBUTTONLINE)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWINFOLINE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWINFOLINE)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOMIN, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOMIN)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOCLOSE)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SAVEPERCONTACT)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_CASCADE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CASCADE)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONENTER, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SENDONENTER)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONDBLENTER, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SENDONDBLENTER)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_STATUSWIN)); - - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_AVATARENABLE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH)); - avatarHeight = GetDlgItemInt(hwndDlg, IDC_AVATARHEIGHT, NULL, TRUE); - DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, avatarHeight<=0?SRMSGDEFSET_AVHEIGHT:avatarHeight); - - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDBUTTON, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSENDBTN)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_CHARCOUNT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CHARCOUNT)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_CTRLSUPPORT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CTRLSUPPORT)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_DELTEMP, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DELTEMP)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, (BYTE) GetDlgItemInt(hwndDlg, IDC_NFLASHES, NULL, TRUE)); - - msgTimeout = GetDlgItemInt(hwndDlg, IDC_SECONDS, NULL, TRUE) * 1000; - if (msgTimeout < SRMSGSET_MSGTIMEOUT_MIN) msgTimeout = SRMSGDEFSET_MSGTIMEOUT; - DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_MSGTIMEOUT, msgTimeout); - - ReloadGlobals(); - WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0); - return TRUE; - } - } - break; - } - break; - case WM_DESTROY: - break; - } - return FALSE; -} - -static INT_PTR CALLBACK DlgProcLogOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static HBRUSH hBkgColourBrush; - - switch (msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - switch (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, SRMSGDEFSET_LOADHISTORY)) { - case LOADHISTORY_UNREAD: - CheckDlgButton(hwndDlg, IDC_LOADUNREAD, BST_CHECKED); - break; - case LOADHISTORY_COUNT: - CheckDlgButton(hwndDlg, IDC_LOADCOUNT, BST_CHECKED); - EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTN), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTSPIN), TRUE); - break; - case LOADHISTORY_TIME: - CheckDlgButton(hwndDlg, IDC_LOADTIME, BST_CHECKED); - EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMEN), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMESPIN), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_STMINSOLD), TRUE); - break; - } - SendDlgItemMessage(hwndDlg, IDC_LOADCOUNTSPIN, UDM_SETRANGE, 0, MAKELONG(100, 0)); - SendDlgItemMessage(hwndDlg, IDC_LOADCOUNTSPIN, UDM_SETPOS, 0, DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADCOUNT, SRMSGDEFSET_LOADCOUNT)); - SendDlgItemMessage(hwndDlg, IDC_LOADTIMESPIN, UDM_SETRANGE, 0, MAKELONG(12 * 60, 0)); - SendDlgItemMessage(hwndDlg, IDC_LOADTIMESPIN, UDM_SETPOS, 0, DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, SRMSGDEFSET_LOADTIME)); - - CheckDlgButton(hwndDlg, IDC_SHOWLOGICONS, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWLOGICONS, SRMSGDEFSET_SHOWLOGICONS)); - CheckDlgButton(hwndDlg, IDC_SHOWNAMES, !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_HIDENAMES, SRMSGDEFSET_HIDENAMES)); - CheckDlgButton(hwndDlg, IDC_SHOWTIMES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTIME, SRMSGDEFSET_SHOWTIME)); - EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSECS), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); - CheckDlgButton(hwndDlg, IDC_SHOWSECS, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSECS, SRMSGDEFSET_SHOWSECS)); - EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWDATES), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); - CheckDlgButton(hwndDlg, IDC_SHOWDATES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWDATE, SRMSGDEFSET_SHOWDATE)); - CheckDlgButton(hwndDlg, IDC_SHOWSTATUSCHANGES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, SRMSGDEFSET_SHOWSTATUSCH)); - CheckDlgButton(hwndDlg, IDC_SHOWFORMATTING, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWFORMAT, SRMSGDEFSET_SHOWFORMAT)); - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_LOADUNREAD: - case IDC_LOADCOUNT: - case IDC_LOADTIME: - EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTN), IsDlgButtonChecked(hwndDlg, IDC_LOADCOUNT)); - EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTSPIN), IsDlgButtonChecked(hwndDlg, IDC_LOADCOUNT)); - EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMEN), IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)); - EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMESPIN), IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)); - EnableWindow(GetDlgItem(hwndDlg, IDC_STMINSOLD), IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)); - break; - - case IDC_SHOWTIMES: - EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSECS), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); - EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWDATES), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); - break; - - case IDC_LOADCOUNTN: - case IDC_LOADTIMEN: - if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()) - return TRUE; - break; - } - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - case WM_NOTIFY: - switch (((LPNMHDR) lParam)->idFrom) { - case 0: - switch (((LPNMHDR) lParam)->code) { - case PSN_APPLY: - if (IsDlgButtonChecked(hwndDlg, IDC_LOADCOUNT)) - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, LOADHISTORY_COUNT); - else if (IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)) - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, LOADHISTORY_TIME); - else - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, LOADHISTORY_UNREAD); - DBWriteContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADCOUNT, (WORD) SendDlgItemMessage(hwndDlg, IDC_LOADCOUNTSPIN, UDM_GETPOS, 0, 0)); - DBWriteContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, (WORD) SendDlgItemMessage(hwndDlg, IDC_LOADTIMESPIN, UDM_GETPOS, 0, 0)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWLOGICONS, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWLOGICONS)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_HIDENAMES, (BYTE) ! IsDlgButtonChecked(hwndDlg, IDC_SHOWNAMES)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTIME, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSECS, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSECS)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWDATE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWDATES)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUSCHANGES)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWFORMAT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWFORMATTING)); - - FreeMsgLogIcons(); - LoadMsgLogIcons(); - ReloadGlobals(); - WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0); - return TRUE; - } - break; - } - break; - case WM_DESTROY: - DeleteObject(hBkgColourBrush); - break; - } - return FALSE; -} - -static ResetCList(HWND hwndDlg) -{ - int i; - - if (CallService(MS_CLUI_GETCAPS, 0, 0) & CLUIF_DISABLEGROUPS && !DBGetContactSettingByte(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT)) - SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETUSEGROUPS, (WPARAM) FALSE, 0); - else - SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETUSEGROUPS, (WPARAM) TRUE, 0); - SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETHIDEEMPTYGROUPS, 1, 0); - SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETGREYOUTFLAGS, 0, 0); - SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETLEFTMARGIN, 2, 0); - SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETBKBITMAP, 0, (LPARAM) (HBITMAP) NULL); - SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0); - SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETINDENT, 10, 0); - for (i = 0; i <= FONTID_MAX; i++) - SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT)); -} - -static void RebuildList(HWND hwndDlg, HANDLE hItemNew, HANDLE hItemUnknown) -{ - HANDLE hContact, hItem; - BYTE defType = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW); - - if (hItemNew && defType) { - SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM) hItemNew, 1); - } - if (hItemUnknown && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGUNKNOWN, SRMSGDEFSET_TYPINGUNKNOWN)) { - SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM) hItemUnknown, 1); - } - hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - do { - hItem = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM) hContact, 0); - if (hItem && DBGetContactSettingByte(hContact, SRMMMOD, SRMSGSET_TYPING, defType)) { - SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM) hItem, 1); - } - } while (hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0)); -} - -static void SaveList(HWND hwndDlg, HANDLE hItemNew, HANDLE hItemUnknown) -{ - HANDLE hContact, hItem; - - if (hItemNew) { - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, (BYTE) (SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItemNew, 0) ? 1 : 0)); - } - if (hItemUnknown) { - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGUNKNOWN, (BYTE) (SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItemUnknown, 0) ? 1 : 0)); - } - hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - do { - hItem = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM) hContact, 0); - if (hItem) { - DBWriteContactSettingByte(hContact, SRMMMOD, SRMSGSET_TYPING, (BYTE) (SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItem, 0) ? 1 : 0)); - } - } while (hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0)); -} - -static INT_PTR CALLBACK DlgProcTypeOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - static HANDLE hItemNew, hItemUnknown; - - switch (msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - { - CLCINFOITEM cii = { 0 }; - cii.cbSize = sizeof(cii); - cii.flags = CLCIIF_GROUPFONT | CLCIIF_CHECKBOX; - cii.pszText = TranslateT("** New contacts **"); - hItemNew = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_ADDINFOITEM, 0, (LPARAM) & cii); - cii.pszText = TranslateT("** Unknown contacts **"); - hItemUnknown = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_ADDINFOITEM, 0, (LPARAM) & cii); - } - SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CLIST), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CLIST), GWL_STYLE) | (CLS_SHOWHIDDEN) | (CLS_NOHIDEOFFLINE)); - ResetCList(hwndDlg); - RebuildList(hwndDlg, hItemNew, hItemUnknown); - CheckDlgButton(hwndDlg, IDC_SHOWNOTIFY, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPING, SRMSGDEFSET_SHOWTYPING)); - CheckDlgButton(hwndDlg, IDC_TYPEWIN, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGWIN, SRMSGDEFSET_SHOWTYPINGWIN)); - CheckDlgButton(hwndDlg, IDC_TYPETRAY, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGNOWIN, SRMSGDEFSET_SHOWTYPINGNOWIN)); - CheckDlgButton(hwndDlg, IDC_NOTIFYTRAY, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, SRMSGDEFSET_SHOWTYPINGCLIST)); - CheckDlgButton(hwndDlg, IDC_NOTIFYBALLOON, !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, SRMSGDEFSET_SHOWTYPINGCLIST)); - EnableWindow(GetDlgItem(hwndDlg, IDC_TYPEWIN), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); - EnableWindow(GetDlgItem(hwndDlg, IDC_TYPETRAY), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); - EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY)); - EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY)); - if (!ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) { - EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), FALSE); - CheckDlgButton(hwndDlg, IDC_NOTIFYTRAY, BST_CHECKED); - SetWindowText(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), TranslateT("Show balloon popup (unsupported system)")); - } - break; - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_TYPETRAY: - if (IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY)) { - if (!ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) { - EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), TRUE); - } - else { - EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), TRUE); - } - } - else { - EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), FALSE); - } - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - case IDC_SHOWNOTIFY: - EnableWindow(GetDlgItem(hwndDlg, IDC_TYPEWIN), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); - EnableWindow(GetDlgItem(hwndDlg, IDC_TYPETRAY), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); - EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); - EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY) - && ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)); - //fall-thru - case IDC_TYPEWIN: - case IDC_NOTIFYTRAY: - case IDC_NOTIFYBALLOON: - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - } - break; - case WM_NOTIFY: - switch (((NMHDR *) lParam)->idFrom) { - case IDC_CLIST: - switch (((NMHDR *) lParam)->code) { - case CLN_OPTIONSCHANGED: - ResetCList(hwndDlg); - break; - case CLN_CHECKCHANGED: - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - } - break; - case 0: - switch (((LPNMHDR) lParam)->code) { - case PSN_APPLY: - { - SaveList(hwndDlg, hItemNew, hItemUnknown); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPING, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGWIN, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_TYPEWIN)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGNOWIN, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY)); - DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_NOTIFYTRAY)); - ReloadGlobals(); - WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0); - } - } - break; - } - break; - } - return FALSE; -} - -static int OptInitialise(WPARAM wParam, LPARAM lParam) -{ - OPTIONSDIALOGPAGE odp = { 0 }; - odp.cbSize = sizeof(odp); - odp.position = 910000000; - odp.hInstance = g_hInst; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGDLG); - odp.pszTab = LPGEN("Messaging"); - odp.pszTitle = LPGEN("Message Sessions"); - odp.pfnDlgProc = DlgProcOptions; - odp.flags = ODPF_BOLDGROUPS; - Options_AddPage(wParam, &odp); - - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGLOG); - odp.pszTab = LPGEN("Messaging Log"); - odp.pfnDlgProc = DlgProcLogOptions; - odp.nIDBottomSimpleControl = IDC_STMSGLOGGROUP; - Options_AddPage(wParam, &odp); - - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGTYPE); - odp.pszTab = LPGEN("Typing Notify"); - odp.pfnDlgProc = DlgProcTypeOptions; - odp.nIDBottomSimpleControl = 0; - Options_AddPage(wParam, &odp); - return 0; -} - -static int ModernOptInitialise(WPARAM wParam, LPARAM lParam) -{ - static int iBoldControls[] = - { - IDC_TXT_TITLE1, IDC_TXT_TITLE2, IDC_TXT_TITLE3, - MODERNOPT_CTRL_LAST - }; - - MODERNOPTOBJECT obj = {0}; - - obj.cbSize = sizeof(obj); - obj.dwFlags = MODEROPT_FLG_TCHAR|MODEROPT_FLG_NORESIZE; - obj.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); - obj.hInstance = g_hInst; - obj.iSection = MODERNOPT_PAGE_MSGS; - obj.iType = MODERNOPT_TYPE_SECTIONPAGE; - obj.iBoldControls = iBoldControls; - obj.lpzClassicGroup = NULL; - obj.lpzClassicPage = "Message Sessions"; - obj.lpzClassicTab = "Messaging"; - obj.lpzHelpUrl = "http://wiki.miranda-im.org/"; - - obj.lpzTemplate = MAKEINTRESOURCEA(IDD_MODERNOPT_MSGDLG); - obj.pfnDlgProc = DlgProcOptions; - CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj); - - obj.lpzTemplate = MAKEINTRESOURCEA(IDD_MODERNOPT_MSGLOG); - obj.pfnDlgProc = DlgProcLogOptions; - CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj); - - return 0; -} - -static HANDLE oHooks[2]; - -void InitOptions(void) -{ - oHooks[0] = HookEvent(ME_OPT_INITIALISE, OptInitialise); - oHooks[1] = HookEvent(ME_MODERNOPT_INITIALIZE, ModernOptInitialise); -} - -void UnloadOptions(void) -{ - int i; - for (i=0; i < SIZEOF(oHooks); ++i) - if (oHooks[i]) - UnhookEvent(oHooks[i]); -} diff --git a/plugins/SRMM/msgoptions.cpp b/plugins/SRMM/msgoptions.cpp new file mode 100644 index 0000000000..a3458d348a --- /dev/null +++ b/plugins/SRMM/msgoptions.cpp @@ -0,0 +1,656 @@ +/* +Copyright 2000-2010 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "commonheaders.h" + +#include "m_fontservice.h" +#include "m_modernopt.h" + +#define FONTF_BOLD 1 +#define FONTF_ITALIC 2 +struct FontOptionsList +{ + const TCHAR* szDescr; + COLORREF defColour; + const TCHAR* szDefFace; + BYTE defStyle; + char defSize; +} +static const fontOptionsList[] = +{ + { LPGENT("Outgoing messages"), RGB(106, 106, 106), _T("Arial"), 0, -12}, + { LPGENT("Incoming messages"), RGB(0, 0, 0), _T("Arial"), 0, -12}, + { LPGENT("Outgoing name"), RGB(89, 89, 89), _T("Arial"), FONTF_BOLD, -12}, + { LPGENT("Outgoing time"), RGB(0, 0, 0), _T("Terminal"), FONTF_BOLD, -9}, + { LPGENT("Outgoing colon"), RGB(89, 89, 89), _T("Arial"), 0, -11}, + { LPGENT("Incoming name"), RGB(215, 0, 0), _T("Arial"), FONTF_BOLD, -12}, + { LPGENT("Incoming time"), RGB(0, 0, 0), _T("Terminal"), FONTF_BOLD, -9}, + { LPGENT("Incoming colon"), RGB(215, 0, 0), _T("Arial"), 0, -11}, + { LPGENT("Message area"), RGB(0, 0, 0), _T("Arial"), 0, -12}, + { LPGENT("Notices"), RGB(90, 90, 160), _T("Arial"), 0, -12}, +}; + +const int msgDlgFontCount = SIZEOF(fontOptionsList); + +static BYTE MsgDlgGetFontDefaultCharset(const TCHAR* szFont) +{ + return DEFAULT_CHARSET; +} + +void LoadMsgDlgFont(int i, LOGFONT* lf, COLORREF * colour) +{ + char str[32]; + int style; + DBVARIANT dbv; + + if ( colour ) { + mir_snprintf(str, SIZEOF(str), "SRMFont%dCol", i); + *colour = DBGetContactSettingDword(NULL, SRMMMOD, str, fontOptionsList[i].defColour); + } + if ( lf ) { + mir_snprintf(str, SIZEOF(str), "SRMFont%dSize", i); + lf->lfHeight = (char) DBGetContactSettingByte(NULL, SRMMMOD, str, fontOptionsList[i].defSize); + lf->lfWidth = 0; + lf->lfEscapement = 0; + lf->lfOrientation = 0; + mir_snprintf(str, SIZEOF(str), "SRMFont%dSty", i); + style = DBGetContactSettingByte(NULL, SRMMMOD, str, fontOptionsList[i].defStyle); + lf->lfWeight = style & FONTF_BOLD ? FW_BOLD : FW_NORMAL; + lf->lfItalic = style & FONTF_ITALIC ? 1 : 0; + lf->lfUnderline = 0; + lf->lfStrikeOut = 0; + lf->lfOutPrecision = OUT_DEFAULT_PRECIS; + lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf->lfQuality = DEFAULT_QUALITY; + lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; + mir_snprintf(str, SIZEOF(str), "SRMFont%d", i); + if (DBGetContactSettingTString(NULL, SRMMMOD, str, &dbv)) + _tcscpy(lf->lfFaceName, fontOptionsList[i].szDefFace); + else { + lstrcpyn(lf->lfFaceName, dbv.ptszVal, SIZEOF(lf->lfFaceName)); + DBFreeVariant(&dbv); + } + mir_snprintf(str, SIZEOF(str), "SRMFont%dSet", i); + lf->lfCharSet = DBGetContactSettingByte(NULL, SRMMMOD, str, MsgDlgGetFontDefaultCharset(lf->lfFaceName)); +} } + +void RegisterSRMMFonts( void ) +{ + FontIDT fontid = {0}; + ColourIDT colourid = {0}; + char idstr[10]; + int i, index = 0; + + fontid.cbSize = sizeof(FontID); + fontid.flags = FIDF_ALLOWREREGISTER | FIDF_DEFAULTVALID; + for ( i = 0; i < msgDlgFontCount; i++, index++ ) { + strcpy(fontid.dbSettingsGroup, SRMMMOD); + _tcscpy(fontid.group, LPGENT("Message Log")); + _tcscpy(fontid.name, fontOptionsList[i].szDescr); + mir_snprintf(idstr, SIZEOF(idstr), "SRMFont%d", index); + strcpy(fontid.prefix, idstr); + fontid.order = index; + + fontid.flags &= ~FIDF_CLASSMASK; + fontid.flags |= (fontOptionsList[i].defStyle == FONTF_BOLD) ? FIDF_CLASSHEADER : FIDF_CLASSGENERAL; + + fontid.deffontsettings.colour = fontOptionsList[i].defColour; + fontid.deffontsettings.size = fontOptionsList[i].defSize; + fontid.deffontsettings.style = fontOptionsList[i].defStyle; + _tcscpy(fontid.deffontsettings.szFace, fontOptionsList[i].szDefFace); + fontid.deffontsettings.charset = MsgDlgGetFontDefaultCharset(fontOptionsList[i].szDefFace); + CallService(MS_FONT_REGISTERT, (WPARAM)&fontid, 0); + } + + colourid.cbSize = sizeof(ColourID); + strcpy(colourid.dbSettingsGroup, SRMMMOD); + strcpy(colourid.setting, SRMSGSET_BKGCOLOUR); + colourid.defcolour = SRMSGDEFSET_BKGCOLOUR; + _tcscpy(colourid.name, LPGENT("Background")); + _tcscpy(colourid.group, LPGENT("Message Log")); + CallService(MS_COLOUR_REGISTERT, (WPARAM)&colourid, 0); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +struct CheckBoxValues_t +{ + DWORD style; + TCHAR* szDescr; +} +static const statusValues[] = +{ + { MODEF_OFFLINE, LPGENT("Offline") }, + { PF2_ONLINE, LPGENT("Online") }, + { PF2_SHORTAWAY, LPGENT("Away") }, + { PF2_LONGAWAY, LPGENT("NA") }, + { PF2_LIGHTDND, LPGENT("Occupied") }, + { PF2_HEAVYDND, LPGENT("DND") }, + { PF2_FREECHAT, LPGENT("Free for chat") }, + { PF2_INVISIBLE, LPGENT("Invisible") }, + { PF2_OUTTOLUNCH, LPGENT("Out to lunch") }, + { PF2_ONTHEPHONE, LPGENT("On the phone") } +}; + +static void FillCheckBoxTree(HWND hwndTree, const struct CheckBoxValues_t *values, int nValues, DWORD style) +{ + TVINSERTSTRUCT tvis; + int i; + + tvis.hParent = NULL; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_STATE; + for (i = 0; i < nValues; i++) { + tvis.item.lParam = values[i].style; + tvis.item.pszText = TranslateTS(values[i].szDescr); + tvis.item.stateMask = TVIS_STATEIMAGEMASK; + tvis.item.state = INDEXTOSTATEIMAGEMASK((style & tvis.item.lParam) != 0 ? 2 : 1); + TreeView_InsertItem( hwndTree, &tvis ); +} } + +static DWORD MakeCheckBoxTreeFlags(HWND hwndTree) +{ + DWORD flags = 0; + TVITEM tvi; + + tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE; + tvi.hItem = TreeView_GetRoot(hwndTree); + while (tvi.hItem) { + TreeView_GetItem(hwndTree, &tvi); + if (((tvi.state & TVIS_STATEIMAGEMASK) >> 12 == 2)) + flags |= tvi.lParam; + tvi.hItem = TreeView_GetNextSibling(hwndTree, tvi.hItem); + } + return flags; +} + +static INT_PTR CALLBACK DlgProcOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_INITDIALOG: + { + DWORD avatarHeight, msgTimeout; + + TranslateDialogDefault(hwndDlg); + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_POPLIST), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_POPLIST), GWL_STYLE) | TVS_NOHSCROLL | TVS_CHECKBOXES); + FillCheckBoxTree(GetDlgItem(hwndDlg, IDC_POPLIST), statusValues, SIZEOF(statusValues), DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_POPFLAGS, SRMSGDEFSET_POPFLAGS)); + CheckDlgButton(hwndDlg, IDC_DONOTSTEALFOCUS, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DONOTSTEALFOCUS, SRMSGDEFSET_DONOTSTEALFOCUS)); + SetDlgItemInt(hwndDlg, IDC_NFLASHES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, SRMSGDEFSET_FLASHCOUNT), FALSE); + CheckDlgButton(hwndDlg, IDC_SHOWBUTTONLINE, g_dat->flags&SMF_SHOWBTNS); + CheckDlgButton(hwndDlg, IDC_SHOWINFOLINE, g_dat->flags&SMF_SHOWINFO); + CheckDlgButton(hwndDlg, IDC_AUTOMIN, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOMIN, SRMSGDEFSET_AUTOMIN)); + CheckDlgButton(hwndDlg, IDC_AUTOCLOSE, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, SRMSGDEFSET_AUTOCLOSE)); + CheckDlgButton(hwndDlg, IDC_SAVEPERCONTACT, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, SRMSGDEFSET_SAVEPERCONTACT)); + CheckDlgButton(hwndDlg, IDC_CASCADE, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CASCADE, SRMSGDEFSET_CASCADE)); + CheckDlgButton(hwndDlg, IDC_SENDONENTER, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONENTER, SRMSGDEFSET_SENDONENTER)); + CheckDlgButton(hwndDlg, IDC_SENDONDBLENTER, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONDBLENTER, SRMSGDEFSET_SENDONDBLENTER)); + CheckDlgButton(hwndDlg, IDC_STATUSWIN, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, SRMSGDEFSET_STATUSICON)); + + CheckDlgButton(hwndDlg, IDC_AVATARSUPPORT, g_dat->flags&SMF_AVATAR); + CheckDlgButton(hwndDlg, IDC_LIMITAVATARH, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, SRMSGDEFSET_LIMITAVHEIGHT)); + avatarHeight = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, SRMSGDEFSET_AVHEIGHT); + SetDlgItemInt(hwndDlg, IDC_AVATARHEIGHT, avatarHeight, FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMITAVATARH), IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)); + if (!IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)) + EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), FALSE); + else EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH)); + CheckDlgButton(hwndDlg, IDC_SHOWSENDBTN, g_dat->flags&SMF_SENDBTN); + CheckDlgButton(hwndDlg, IDC_CHARCOUNT, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CHARCOUNT, SRMSGDEFSET_CHARCOUNT)); + CheckDlgButton(hwndDlg, IDC_CTRLSUPPORT, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_CTRLSUPPORT, SRMSGDEFSET_CTRLSUPPORT)); + CheckDlgButton(hwndDlg, IDC_DELTEMP, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DELTEMP, SRMSGDEFSET_DELTEMP)); + msgTimeout = DBGetContactSettingDword(NULL, SRMMMOD, SRMSGSET_MSGTIMEOUT, SRMSGDEFSET_MSGTIMEOUT); + SetDlgItemInt(hwndDlg, IDC_SECONDS, msgTimeout >= SRMSGSET_MSGTIMEOUT_MIN ? msgTimeout / 1000 : SRMSGDEFSET_MSGTIMEOUT / 1000, FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_CASCADE), !IsDlgButtonChecked(hwndDlg, IDC_SAVEPERCONTACT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_CTRLSUPPORT), !IsDlgButtonChecked(hwndDlg, IDC_AUTOCLOSE)); + return TRUE; + } + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_AUTOMIN: + CheckDlgButton(hwndDlg, IDC_AUTOCLOSE, BST_UNCHECKED); + break; + case IDC_AUTOCLOSE: + CheckDlgButton(hwndDlg, IDC_AUTOMIN, BST_UNCHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_CTRLSUPPORT), !IsDlgButtonChecked(hwndDlg, IDC_AUTOCLOSE)); + break; + case IDC_SENDONENTER: + CheckDlgButton(hwndDlg, IDC_SENDONDBLENTER, BST_UNCHECKED); + break; + case IDC_SENDONDBLENTER: + CheckDlgButton(hwndDlg, IDC_SENDONENTER, BST_UNCHECKED); + break; + case IDC_SAVEPERCONTACT: + EnableWindow(GetDlgItem(hwndDlg, IDC_CASCADE), !IsDlgButtonChecked(hwndDlg, IDC_SAVEPERCONTACT)); + break; + case IDC_SECONDS: + if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()) + return 0; + break; + case IDC_AVATARSUPPORT: + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMITAVATARH), IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)); + if (!IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)) + EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), FALSE); + else EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH)); + break; + case IDC_LIMITAVATARH: + EnableWindow(GetDlgItem(hwndDlg, IDC_AVATARHEIGHT), IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH)); + break; + case IDC_AVATARHEIGHT: + if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()) + return 0; + break; + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case IDC_POPLIST: + 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) { + TVITEM tvi; + tvi.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvi.hItem = hti.hItem; + TreeView_GetItem(((LPNMHDR) lParam)->hwndFrom, &tvi); + tvi.iImage = tvi.iSelectedImage = tvi.iImage == 1 ? 2 : 1; + TreeView_SetItem(((LPNMHDR) lParam)->hwndFrom, &tvi); + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + break; + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + { + DWORD avatarHeight, msgTimeout; + + DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_POPFLAGS, MakeCheckBoxTreeFlags(GetDlgItem(hwndDlg, IDC_POPLIST))); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_DONOTSTEALFOCUS, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DONOTSTEALFOCUS)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWBUTTONLINE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWBUTTONLINE)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWINFOLINE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWINFOLINE)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOMIN, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOMIN)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_AUTOCLOSE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AUTOCLOSE)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SAVEPERCONTACT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SAVEPERCONTACT)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_CASCADE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CASCADE)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONENTER, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SENDONENTER)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDONDBLENTER, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SENDONDBLENTER)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_STATUSICON, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_STATUSWIN)); + + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_AVATARENABLE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_AVATARSUPPORT)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LIMITAVHEIGHT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_LIMITAVATARH)); + avatarHeight = GetDlgItemInt(hwndDlg, IDC_AVATARHEIGHT, NULL, TRUE); + DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_AVHEIGHT, avatarHeight<=0?SRMSGDEFSET_AVHEIGHT:avatarHeight); + + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SENDBUTTON, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSENDBTN)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_CHARCOUNT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CHARCOUNT)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_CTRLSUPPORT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_CTRLSUPPORT)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_DELTEMP, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_DELTEMP)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_FLASHCOUNT, (BYTE) GetDlgItemInt(hwndDlg, IDC_NFLASHES, NULL, TRUE)); + + msgTimeout = GetDlgItemInt(hwndDlg, IDC_SECONDS, NULL, TRUE) * 1000; + if (msgTimeout < SRMSGSET_MSGTIMEOUT_MIN) msgTimeout = SRMSGDEFSET_MSGTIMEOUT; + DBWriteContactSettingDword(NULL, SRMMMOD, SRMSGSET_MSGTIMEOUT, msgTimeout); + + ReloadGlobals(); + WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0); + return TRUE; + } + } + break; + } + break; + case WM_DESTROY: + break; + } + return FALSE; +} + +static INT_PTR CALLBACK DlgProcLogOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static HBRUSH hBkgColourBrush; + + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + switch (DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, SRMSGDEFSET_LOADHISTORY)) { + case LOADHISTORY_UNREAD: + CheckDlgButton(hwndDlg, IDC_LOADUNREAD, BST_CHECKED); + break; + case LOADHISTORY_COUNT: + CheckDlgButton(hwndDlg, IDC_LOADCOUNT, BST_CHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTN), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTSPIN), TRUE); + break; + case LOADHISTORY_TIME: + CheckDlgButton(hwndDlg, IDC_LOADTIME, BST_CHECKED); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMEN), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMESPIN), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_STMINSOLD), TRUE); + break; + } + SendDlgItemMessage(hwndDlg, IDC_LOADCOUNTSPIN, UDM_SETRANGE, 0, MAKELONG(100, 0)); + SendDlgItemMessage(hwndDlg, IDC_LOADCOUNTSPIN, UDM_SETPOS, 0, DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADCOUNT, SRMSGDEFSET_LOADCOUNT)); + SendDlgItemMessage(hwndDlg, IDC_LOADTIMESPIN, UDM_SETRANGE, 0, MAKELONG(12 * 60, 0)); + SendDlgItemMessage(hwndDlg, IDC_LOADTIMESPIN, UDM_SETPOS, 0, DBGetContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, SRMSGDEFSET_LOADTIME)); + + CheckDlgButton(hwndDlg, IDC_SHOWLOGICONS, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWLOGICONS, SRMSGDEFSET_SHOWLOGICONS)); + CheckDlgButton(hwndDlg, IDC_SHOWNAMES, !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_HIDENAMES, SRMSGDEFSET_HIDENAMES)); + CheckDlgButton(hwndDlg, IDC_SHOWTIMES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTIME, SRMSGDEFSET_SHOWTIME)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSECS), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); + CheckDlgButton(hwndDlg, IDC_SHOWSECS, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSECS, SRMSGDEFSET_SHOWSECS)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWDATES), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); + CheckDlgButton(hwndDlg, IDC_SHOWDATES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWDATE, SRMSGDEFSET_SHOWDATE)); + CheckDlgButton(hwndDlg, IDC_SHOWSTATUSCHANGES, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, SRMSGDEFSET_SHOWSTATUSCH)); + CheckDlgButton(hwndDlg, IDC_SHOWFORMATTING, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWFORMAT, SRMSGDEFSET_SHOWFORMAT)); + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_LOADUNREAD: + case IDC_LOADCOUNT: + case IDC_LOADTIME: + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTN), IsDlgButtonChecked(hwndDlg, IDC_LOADCOUNT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADCOUNTSPIN), IsDlgButtonChecked(hwndDlg, IDC_LOADCOUNT)); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMEN), IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)); + EnableWindow(GetDlgItem(hwndDlg, IDC_LOADTIMESPIN), IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)); + EnableWindow(GetDlgItem(hwndDlg, IDC_STMINSOLD), IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)); + break; + + case IDC_SHOWTIMES: + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWSECS), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); + EnableWindow(GetDlgItem(hwndDlg, IDC_SHOWDATES), IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); + break; + + case IDC_LOADCOUNTN: + case IDC_LOADTIMEN: + if (HIWORD(wParam) != EN_CHANGE || (HWND) lParam != GetFocus()) + return TRUE; + break; + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case WM_NOTIFY: + switch (((LPNMHDR) lParam)->idFrom) { + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + if (IsDlgButtonChecked(hwndDlg, IDC_LOADCOUNT)) + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, LOADHISTORY_COUNT); + else if (IsDlgButtonChecked(hwndDlg, IDC_LOADTIME)) + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, LOADHISTORY_TIME); + else + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_LOADHISTORY, LOADHISTORY_UNREAD); + DBWriteContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADCOUNT, (WORD) SendDlgItemMessage(hwndDlg, IDC_LOADCOUNTSPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingWord(NULL, SRMMMOD, SRMSGSET_LOADTIME, (WORD) SendDlgItemMessage(hwndDlg, IDC_LOADTIMESPIN, UDM_GETPOS, 0, 0)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWLOGICONS, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWLOGICONS)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_HIDENAMES, (BYTE) ! IsDlgButtonChecked(hwndDlg, IDC_SHOWNAMES)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTIME, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWTIMES)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSECS, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSECS)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWDATE, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWDATES)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWSTATUSCH, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWSTATUSCHANGES)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWFORMAT, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWFORMATTING)); + + FreeMsgLogIcons(); + LoadMsgLogIcons(); + ReloadGlobals(); + WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0); + return TRUE; + } + break; + } + break; + case WM_DESTROY: + DeleteObject(hBkgColourBrush); + break; + } + return FALSE; +} + +static void ResetCList(HWND hwndDlg) +{ + if (CallService(MS_CLUI_GETCAPS, 0, 0) & CLUIF_DISABLEGROUPS && !DBGetContactSettingByte(NULL, "CList", "UseGroups", SETTING_USEGROUPS_DEFAULT)) + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETUSEGROUPS, (WPARAM) FALSE, 0); + else + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETUSEGROUPS, (WPARAM) TRUE, 0); + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETHIDEEMPTYGROUPS, 1, 0); + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETGREYOUTFLAGS, 0, 0); + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETLEFTMARGIN, 2, 0); + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETBKBITMAP, 0, (LPARAM) (HBITMAP) NULL); + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETBKCOLOR, GetSysColor(COLOR_WINDOW), 0); + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETINDENT, 10, 0); + for (int i = 0; i <= FONTID_MAX; i++) + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETTEXTCOLOR, i, GetSysColor(COLOR_WINDOWTEXT)); +} + +static void RebuildList(HWND hwndDlg, HANDLE hItemNew, HANDLE hItemUnknown) +{ + HANDLE hContact, hItem; + BYTE defType = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, SRMSGDEFSET_TYPINGNEW); + + if (hItemNew && defType) { + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM) hItemNew, 1); + } + if (hItemUnknown && DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGUNKNOWN, SRMSGDEFSET_TYPINGUNKNOWN)) { + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM) hItemUnknown, 1); + } + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + do { + hItem = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM) hContact, 0); + if (hItem && DBGetContactSettingByte(hContact, SRMMMOD, SRMSGSET_TYPING, defType)) { + SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_SETCHECKMARK, (WPARAM) hItem, 1); + } + } while (hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0)); +} + +static void SaveList(HWND hwndDlg, HANDLE hItemNew, HANDLE hItemUnknown) +{ + HANDLE hContact, hItem; + + if (hItemNew) { + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGNEW, (BYTE) (SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItemNew, 0) ? 1 : 0)); + } + if (hItemUnknown) { + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_TYPINGUNKNOWN, (BYTE) (SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItemUnknown, 0) ? 1 : 0)); + } + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + do { + hItem = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_FINDCONTACT, (WPARAM) hContact, 0); + if (hItem) { + DBWriteContactSettingByte(hContact, SRMMMOD, SRMSGSET_TYPING, (BYTE) (SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_GETCHECKMARK, (WPARAM) hItem, 0) ? 1 : 0)); + } + } while (hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0)); +} + +static INT_PTR CALLBACK DlgProcTypeOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static HANDLE hItemNew, hItemUnknown; + + switch (msg) { + case WM_INITDIALOG: + TranslateDialogDefault(hwndDlg); + { + CLCINFOITEM cii = { 0 }; + cii.cbSize = sizeof(cii); + cii.flags = CLCIIF_GROUPFONT | CLCIIF_CHECKBOX; + cii.pszText = TranslateT("** New contacts **"); + hItemNew = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_ADDINFOITEM, 0, (LPARAM) & cii); + cii.pszText = TranslateT("** Unknown contacts **"); + hItemUnknown = (HANDLE) SendDlgItemMessage(hwndDlg, IDC_CLIST, CLM_ADDINFOITEM, 0, (LPARAM) & cii); + } + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CLIST), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CLIST), GWL_STYLE) | (CLS_SHOWHIDDEN) | (CLS_NOHIDEOFFLINE)); + ResetCList(hwndDlg); + RebuildList(hwndDlg, hItemNew, hItemUnknown); + CheckDlgButton(hwndDlg, IDC_SHOWNOTIFY, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPING, SRMSGDEFSET_SHOWTYPING)); + CheckDlgButton(hwndDlg, IDC_TYPEWIN, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGWIN, SRMSGDEFSET_SHOWTYPINGWIN)); + CheckDlgButton(hwndDlg, IDC_TYPETRAY, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGNOWIN, SRMSGDEFSET_SHOWTYPINGNOWIN)); + CheckDlgButton(hwndDlg, IDC_NOTIFYTRAY, DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, SRMSGDEFSET_SHOWTYPINGCLIST)); + CheckDlgButton(hwndDlg, IDC_NOTIFYBALLOON, !DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, SRMSGDEFSET_SHOWTYPINGCLIST)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TYPEWIN), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TYPETRAY), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY)); + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY)); + if (!ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), FALSE); + CheckDlgButton(hwndDlg, IDC_NOTIFYTRAY, BST_CHECKED); + SetWindowText(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), TranslateT("Show balloon popup (unsupported system)")); + } + break; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDC_TYPETRAY: + if (IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY)) { + if (!ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) { + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), TRUE); + } + else { + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), TRUE); + } + } + else { + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), FALSE); + } + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + case IDC_SHOWNOTIFY: + EnableWindow(GetDlgItem(hwndDlg, IDC_TYPEWIN), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TYPETRAY), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYTRAY), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); + EnableWindow(GetDlgItem(hwndDlg, IDC_NOTIFYBALLOON), IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY) + && ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)); + //fall-thru + case IDC_TYPEWIN: + case IDC_NOTIFYTRAY: + case IDC_NOTIFYBALLOON: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + break; + case WM_NOTIFY: + switch (((NMHDR *) lParam)->idFrom) { + case IDC_CLIST: + switch (((NMHDR *) lParam)->code) { + case CLN_OPTIONSCHANGED: + ResetCList(hwndDlg); + break; + case CLN_CHECKCHANGED: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + break; + case 0: + switch (((LPNMHDR) lParam)->code) { + case PSN_APPLY: + { + SaveList(hwndDlg, hItemNew, hItemUnknown); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPING, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_SHOWNOTIFY)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGWIN, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_TYPEWIN)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGNOWIN, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_TYPETRAY)); + DBWriteContactSettingByte(NULL, SRMMMOD, SRMSGSET_SHOWTYPINGCLIST, (BYTE) IsDlgButtonChecked(hwndDlg, IDC_NOTIFYTRAY)); + ReloadGlobals(); + WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0); + } + } + break; + } + break; + } + return FALSE; +} + +static int OptInitialise(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + odp.cbSize = sizeof(odp); + odp.position = 910000000; + odp.hInstance = g_hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGDLG); + odp.pszTab = LPGEN("Messaging"); + odp.pszTitle = LPGEN("Message Sessions"); + odp.pfnDlgProc = DlgProcOptions; + odp.flags = ODPF_BOLDGROUPS; + Options_AddPage(wParam, &odp); + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGLOG); + odp.pszTab = LPGEN("Messaging Log"); + odp.pfnDlgProc = DlgProcLogOptions; + odp.nIDBottomSimpleControl = IDC_STMSGLOGGROUP; + Options_AddPage(wParam, &odp); + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_MSGTYPE); + odp.pszTab = LPGEN("Typing Notify"); + odp.pfnDlgProc = DlgProcTypeOptions; + odp.nIDBottomSimpleControl = 0; + Options_AddPage(wParam, &odp); + return 0; +} + +static int ModernOptInitialise(WPARAM wParam, LPARAM lParam) +{ + static int iBoldControls[] = + { + IDC_TXT_TITLE1, IDC_TXT_TITLE2, IDC_TXT_TITLE3, + MODERNOPT_CTRL_LAST + }; + + MODERNOPTOBJECT obj = {0}; + + obj.cbSize = sizeof(obj); + obj.dwFlags = MODEROPT_FLG_TCHAR|MODEROPT_FLG_NORESIZE; + obj.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); + obj.hInstance = g_hInst; + obj.iSection = MODERNOPT_PAGE_MSGS; + obj.iType = MODERNOPT_TYPE_SECTIONPAGE; + obj.iBoldControls = iBoldControls; + obj.lpzClassicGroup = NULL; + obj.lpzClassicPage = "Message Sessions"; + obj.lpzClassicTab = "Messaging"; + obj.lpzHelpUrl = "http://wiki.miranda-im.org/"; + + obj.lpzTemplate = MAKEINTRESOURCEA(IDD_MODERNOPT_MSGDLG); + obj.pfnDlgProc = DlgProcOptions; + CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj); + + obj.lpzTemplate = MAKEINTRESOURCEA(IDD_MODERNOPT_MSGLOG); + obj.pfnDlgProc = DlgProcLogOptions; + CallService(MS_MODERNOPT_ADDOBJECT, wParam, (LPARAM)&obj); + + return 0; +} + +static HANDLE oHooks[2]; + +void InitOptions(void) +{ + oHooks[0] = HookEvent(ME_OPT_INITIALISE, OptInitialise); + oHooks[1] = HookEvent(ME_MODERNOPT_INITIALIZE, ModernOptInitialise); +} + +void UnloadOptions(void) +{ + int i; + for (i=0; i < SIZEOF(oHooks); ++i) + if (oHooks[i]) + UnhookEvent(oHooks[i]); +} diff --git a/plugins/SRMM/msgs.c b/plugins/SRMM/msgs.c deleted file mode 100644 index 8ebb549339..0000000000 --- a/plugins/SRMM/msgs.c +++ /dev/null @@ -1,589 +0,0 @@ -/* -Copyright 2000-2012 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ -#include "commonheaders.h" -#include "statusicon.h" - -/* Missing MinGW GUIDs */ -#ifdef __MINGW32__ -const CLSID IID_IRichEditOle = { 0x00020D00, 0x00, 0x00, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; -const CLSID IID_IRichEditOleCallback = { 0x00020D03, 0x00, 0x00, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; -#endif - -static void InitREOleCallback(void); - -HCURSOR hCurSplitNS, hCurSplitWE, hCurHyperlinkHand; -HANDLE hHookWinEvt, hHookWinPopup, hMsgMenuItem; -static HANDLE hServices[7]; -static HANDLE hHooks[8]; - -static int SRMMStatusToPf2(int status) -{ - switch (status) { - case ID_STATUS_ONLINE: return PF2_ONLINE; - case ID_STATUS_AWAY: return PF2_SHORTAWAY; - case ID_STATUS_DND: return PF2_HEAVYDND; - case ID_STATUS_NA: return PF2_LONGAWAY; - case ID_STATUS_OCCUPIED: return PF2_LIGHTDND; - case ID_STATUS_FREECHAT: return PF2_FREECHAT; - case ID_STATUS_INVISIBLE: return PF2_INVISIBLE; - case ID_STATUS_ONTHEPHONE: return PF2_ONTHEPHONE; - case ID_STATUS_OUTTOLUNCH: return PF2_OUTTOLUNCH; - case ID_STATUS_OFFLINE: return MODEF_OFFLINE; - } - return 0; -} - -static int MessageEventAdded(WPARAM wParam, LPARAM lParam) -{ - DBEVENTINFO dbei = {0}; - HWND hwnd; - - dbei.cbSize = sizeof(dbei); - CallService(MS_DB_EVENT_GET, lParam, (LPARAM) & dbei); - - if (dbei.flags & (DBEF_SENT | DBEF_READ) || !(dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei))) - return 0; - - CallServiceSync(MS_CLIST_REMOVEEVENT, wParam, (LPARAM) 1); - /* does a window for the contact exist? */ - hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE) wParam); - if (hwnd) - { - if (!DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DONOTSTEALFOCUS, SRMSGDEFSET_DONOTSTEALFOCUS)) - { - ShowWindow(hwnd, SW_RESTORE); - SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); - SetForegroundWindow(hwnd); - SkinPlaySound("RecvMsgActive"); - } - else - { - if (GetForegroundWindow() == hwnd) - SkinPlaySound("RecvMsgActive"); - else - SkinPlaySound("RecvMsgInactive"); - } - return 0; - } - /* new message */ - SkinPlaySound("AlertMsg"); - { - char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) wParam, 0); - if (szProto && (g_dat->openFlags & SRMMStatusToPf2(CallProtoService(szProto, PS_GETSTATUS, 0, 0)))) - { - struct NewMessageWindowLParam newData = { 0 }; - newData.hContact = (HANDLE) wParam; - newData.noActivate = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DONOTSTEALFOCUS, SRMSGDEFSET_DONOTSTEALFOCUS); - CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSG), NULL, DlgProcMessage, (LPARAM) & newData); - return 0; - } - } - { - TCHAR toolTip[256], *contactName; - CLISTEVENT cle = {0}; - cle.cbSize = sizeof(cle); - cle.hContact = (HANDLE) wParam; - cle.hDbEvent = (HANDLE) lParam; - cle.flags = CLEF_TCHAR; - cle.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); - cle.pszService = "SRMsg/ReadMessage"; - contactName = (TCHAR*) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, wParam, GCDNF_TCHAR); - mir_sntprintf(toolTip, SIZEOF(toolTip), TranslateT("Message from %s"), contactName); - cle.ptszTooltip = toolTip; - CallService(MS_CLIST_ADDEVENT, 0, (LPARAM) & cle); - } - return 0; -} - -INT_PTR SendMessageCmd(HANDLE hContact, char* msg, int isWchar) -{ - char *szProto; - HWND hwnd; - - /* does the HCONTACT's protocol support IM messages? */ - szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); - if (!szProto || (!CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMSEND)) - return 1; - - if (hwnd = WindowList_Find(g_dat->hMessageWindowList, hContact)) - { - if (msg) - { - HWND hEdit; - hEdit = GetDlgItem(hwnd, IDC_MESSAGE); - SendMessage(hEdit, EM_SETSEL, -1, SendMessage(hEdit, WM_GETTEXTLENGTH, 0, 0)); - if (isWchar) - SendMessage(hEdit, EM_REPLACESEL, FALSE, (LPARAM)msg); - else - SendMessageA(hEdit, EM_REPLACESEL, FALSE, (LPARAM)msg); - } - ShowWindow(hwnd, SW_RESTORE); - SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); - SetForegroundWindow(hwnd); - } - else - { - struct NewMessageWindowLParam newData = { 0 }; - newData.hContact = hContact; - newData.szInitialText = msg; - newData.isWchar = isWchar; - hwnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSG), NULL, DlgProcMessage, (LPARAM)&newData); - } - return 0; -} - -static INT_PTR SendMessageCommand_W(WPARAM wParam, LPARAM lParam) -{ - return SendMessageCmd((HANDLE)wParam, (char*)lParam, TRUE); -} - -static INT_PTR SendMessageCommand(WPARAM wParam, LPARAM lParam) -{ - return SendMessageCmd((HANDLE)wParam, (char*)lParam, FALSE); -} - -static INT_PTR ReadMessageCommand(WPARAM wParam, LPARAM lParam) -{ - CLISTEVENT *cle = (CLISTEVENT *) lParam; - - if (cle) - SendMessageCmd(cle->hContact, NULL, 0); - - return 0; -} - -static int TypingMessage(WPARAM wParam, LPARAM lParam) -{ - HWND hwnd; - int foundWin = 0; - - if (!(g_dat->flags&SMF_SHOWTYPING)) - return 0; - if (hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE) wParam)) { - SendMessage(hwnd, DM_TYPING, 0, lParam); - foundWin = 1; - } - if (lParam && !foundWin && (g_dat->flags&SMF_SHOWTYPINGTRAY)) { - TCHAR szTip[256]; - mir_sntprintf(szTip, SIZEOF(szTip), TranslateT("%s is typing a message"), (TCHAR *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, wParam, GCDNF_TCHAR)); - - if (ServiceExists(MS_CLIST_SYSTRAY_NOTIFY) && !(g_dat->flags&SMF_SHOWTYPINGCLIST)) { - MIRANDASYSTRAYNOTIFY tn = {0}; - tn.cbSize = sizeof(tn); - tn.tszInfoTitle = TranslateT("Typing Notification"); - tn.tszInfo = szTip; - tn.dwInfoFlags = NIIF_INFO; - tn.dwInfoFlags |= NIIF_INTERN_UNICODE; - tn.uTimeout = 1000 * 4; - CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM) & tn); - } - else { - CLISTEVENT cle = {0}; - - cle.cbSize = sizeof(cle); - cle.hContact = (HANDLE) wParam; - cle.hDbEvent = (HANDLE) 1; - cle.flags = CLEF_ONLYAFEW | CLEF_TCHAR; - cle.hIcon = LoadSkinnedIcon( SKINICON_OTHER_TYPING ); - cle.pszService = "SRMsg/ReadMessage"; - cle.ptszTooltip = szTip; - CallServiceSync(MS_CLIST_REMOVEEVENT, wParam, (LPARAM) 1); - CallServiceSync(MS_CLIST_ADDEVENT, wParam, (LPARAM) & cle); - CallService(MS_SKIN2_RELEASEICON,(WPARAM)cle.hIcon, 0); - } - } - return 0; -} - -static int MessageSettingChanged(WPARAM wParam, LPARAM lParam) -{ - DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam; - HANDLE hContact = (HANDLE)wParam; - - if (cws->szModule == NULL) return 0; - - if (!strcmp(cws->szModule, "CList")) - WindowList_Broadcast(g_dat->hMessageWindowList, DM_UPDATETITLE, (WPARAM) cws, 0); - else if (hContact) - { - if (cws->szSetting && !strcmp(cws->szSetting, "Timezone")) - WindowList_Broadcast(g_dat->hMessageWindowList, DM_NEWTIMEZONE, (WPARAM) cws, 0); - else - { - char * szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); - if (szProto && !strcmp(cws->szModule, szProto)) - WindowList_Broadcast(g_dat->hMessageWindowList, DM_UPDATETITLE, (WPARAM) cws, 0); - } - } - return 0; -} - -static int ContactDeleted(WPARAM wParam, LPARAM lParam) -{ - HWND hwnd; - if (hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE) wParam)) - SendMessage(hwnd, WM_CLOSE, 0, 0); - - return 0; -} - -static void RestoreUnreadMessageAlerts(void) -{ - CLISTEVENT cle = {0}; - DBEVENTINFO dbei = {0}; - TCHAR toolTip[256]; - int windowAlreadyExists; - HANDLE hDbEvent, hContact; - int autoPopup; - - dbei.cbSize = sizeof(dbei); - cle.cbSize = sizeof(cle); - cle.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); - cle.pszService = "SRMsg/ReadMessage"; - cle.flags = CLEF_TCHAR; - cle.ptszTooltip = toolTip; - - hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); - while (hContact) - { - hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) hContact, 0); - while (hDbEvent) - { - autoPopup = 0; - dbei.cbBlob = 0; - CallService(MS_DB_EVENT_GET, (WPARAM) hDbEvent, (LPARAM) & dbei); - if (!(dbei.flags & (DBEF_SENT | DBEF_READ)) && ( dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei))) - { - windowAlreadyExists = WindowList_Find(g_dat->hMessageWindowList, hContact) != NULL; - if (windowAlreadyExists) - continue; - { - char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); - if (szProto && (g_dat->openFlags & SRMMStatusToPf2(CallProtoService(szProto, PS_GETSTATUS, 0, 0)))) - { - autoPopup = 1; - } - } - if (autoPopup && !windowAlreadyExists) - { - struct NewMessageWindowLParam newData = {0}; - newData.hContact = hContact; - newData.noActivate = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DONOTSTEALFOCUS, SRMSGDEFSET_DONOTSTEALFOCUS); - CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSG), NULL, DlgProcMessage, (LPARAM) & newData); - } - else - { - cle.hContact = hContact; - cle.hDbEvent = hDbEvent; - mir_sntprintf(toolTip, SIZEOF(toolTip), TranslateT("Message from %s"), (TCHAR *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR)); - CallService(MS_CLIST_ADDEVENT, 0, (LPARAM) & cle); - } - } - hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) hDbEvent, 0); - } - hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); - } -} - -void RegisterSRMMFonts( void ); - -static int FontsChanged(WPARAM wParam,LPARAM lParam) -{ - WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0); - return 0; -} - -static int SplitmsgModulesLoaded(WPARAM wParam, LPARAM lParam) -{ - RegisterSRMMFonts(); - LoadMsgLogIcons(); - { - CLISTMENUITEM mi = { 0 }; - mi.cbSize = sizeof(mi); - mi.position = -2000090000; - mi.flags = CMIF_ICONFROMICOLIB | CMIF_DEFAULT; - mi.icolibItem = LoadSkinnedIconHandle( SKINICON_EVENT_MESSAGE ); - mi.pszName = LPGEN("&Message"); - mi.pszService = MS_MSG_SENDMESSAGE; - hMsgMenuItem = Menu_AddContactMenuItem(&mi); - } - HookEvent(ME_FONT_RELOAD, FontsChanged); - - RestoreUnreadMessageAlerts(); - return 0; -} - -int PreshutdownSendRecv(WPARAM wParam, LPARAM lParam) -{ - WindowList_BroadcastAsync(g_dat->hMessageWindowList, WM_CLOSE, 0, 0); - DeinitStatusIcons(); - return 0; -} - -int SplitmsgShutdown(void) -{ - int i; - - DestroyCursor(hCurSplitNS); - DestroyCursor(hCurHyperlinkHand); - DestroyCursor(hCurSplitWE); - - for (i=0; i < SIZEOF(hHooks); ++i) - if (hHooks[i]) - UnhookEvent(hHooks[i]); - - for ( i=0; i < SIZEOF(hServices); ++i) - if (hServices[i]) - DestroyServiceFunction(hServices[i]); - - FreeMsgLogIcons(); - FreeLibrary(GetModuleHandleA("riched20")); - OleUninitialize(); - RichUtil_Unload(); - msgQueue_destroy(); - FreeGlobals(); - return 0; -} - -static int IconsChanged(WPARAM wParam, LPARAM lParam) -{ - FreeMsgLogIcons(); - LoadMsgLogIcons(); - WindowList_Broadcast(g_dat->hMessageWindowList, DM_REMAKELOG, 0, 0); - // change all the icons - WindowList_Broadcast(g_dat->hMessageWindowList, DM_UPDATEWINICON, 0, 0); - return 0; -} - -static int 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 ) { - // leave this menu item hidden for chats - if ( !DBGetContactSettingByte( hContact, szProto, "ChatRoom", 0 )) - if ( CallProtoService( szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMSEND ) - clmi.flags &= ~CMIF_HIDDEN; - } - - CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMsgMenuItem, ( LPARAM )&clmi ); - } - return 0; -} - -static INT_PTR GetWindowAPI(WPARAM wParam, LPARAM lParam) -{ - return PLUGIN_MAKE_VERSION(0,0,0,4); -} - -static INT_PTR GetWindowClass(WPARAM wParam, LPARAM lParam) -{ - char *szBuf = (char*)wParam; - int size = (int)lParam; - mir_snprintf(szBuf, size, SRMMMOD); - return 0; -} - -static INT_PTR GetWindowData(WPARAM wParam, LPARAM lParam) -{ - MessageWindowInputData *mwid = (MessageWindowInputData*)wParam; - MessageWindowData *mwd = (MessageWindowData*)lParam; - HWND hwnd; - - if (mwid==NULL||mwd==NULL) return 1; - if (mwid->cbSize!=sizeof(MessageWindowInputData)||mwd->cbSize!=sizeof(MessageWindowData)) return 1; - if (mwid->hContact==NULL) return 1; - if (mwid->uFlags!=MSG_WINDOW_UFLAG_MSG_BOTH) return 1; - hwnd = WindowList_Find(g_dat->hMessageWindowList, mwid->hContact); - mwd->uFlags = MSG_WINDOW_UFLAG_MSG_BOTH; - mwd->hwndWindow = hwnd; - mwd->local = 0; - mwd->uState = SendMessage(hwnd, DM_GETWINDOWSTATE, 0, 0); - return 0; -} - -int LoadSendRecvMessageModule(void) -{ - if (LoadLibraryA("riched20.dll") == NULL) { - if (IDYES != - MessageBox(0, - TranslateT - ("Miranda could not load the built-in message module, riched20.dll is missing. If you are using Windows 95 or WINE please make sure you have riched20.dll installed. Press 'Yes' to continue loading Miranda."), - TranslateT("Information"), MB_YESNO | MB_ICONINFORMATION)) - return 1; - return 0; - } - - InitGlobals(); - RichUtil_Load(); - OleInitialize(NULL); - InitREOleCallback(); - InitOptions(); - msgQueue_init(); - - hHooks[0] = HookEvent(ME_DB_EVENT_ADDED, MessageEventAdded); - hHooks[1] = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, MessageSettingChanged); - hHooks[2] = HookEvent(ME_DB_CONTACT_DELETED, ContactDeleted); - hHooks[3] = HookEvent(ME_SYSTEM_MODULESLOADED, SplitmsgModulesLoaded); - hHooks[4] = HookEvent(ME_SKIN_ICONSCHANGED, IconsChanged); - hHooks[5] = HookEvent(ME_PROTO_CONTACTISTYPING, TypingMessage); - hHooks[6] = HookEvent(ME_SYSTEM_PRESHUTDOWN, PreshutdownSendRecv); - hHooks[7] = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PrebuildContactMenu); - - hServices[0] = CreateServiceFunction(MS_MSG_SENDMESSAGE, SendMessageCommand); - hServices[1] = CreateServiceFunction(MS_MSG_SENDMESSAGEW, SendMessageCommand_W); - hServices[2] = CreateServiceFunction(MS_MSG_GETWINDOWAPI, GetWindowAPI); - hServices[3] = CreateServiceFunction(MS_MSG_GETWINDOWCLASS, GetWindowClass); - hServices[4] = CreateServiceFunction(MS_MSG_GETWINDOWDATA, GetWindowData); - hServices[5] = CreateServiceFunction("SRMsg/ReadMessage", ReadMessageCommand); - - hHookWinEvt = CreateHookableEvent(ME_MSG_WINDOWEVENT); - hHookWinPopup = CreateHookableEvent(ME_MSG_WINDOWPOPUP); - - SkinAddNewSoundEx("RecvMsgActive", LPGEN("Instant messages"), LPGEN("Incoming (Focused Window)")); - SkinAddNewSoundEx("RecvMsgInactive", LPGEN("Instant messages"), LPGEN("Incoming (Unfocused Window)")); - SkinAddNewSoundEx("AlertMsg", LPGEN("Instant messages"), LPGEN("Incoming (New Session)")); - SkinAddNewSoundEx("SendMsg", LPGEN("Instant messages"), LPGEN("Outgoing")); - SkinAddNewSoundEx("SendError", LPGEN("Instant messages"), LPGEN("Message send error")); - - hCurSplitNS = LoadCursor(NULL, IDC_SIZENS); - hCurSplitWE = LoadCursor(NULL, IDC_SIZEWE); - hCurHyperlinkHand = LoadCursor(NULL, IDC_HAND); - if (hCurHyperlinkHand == NULL) - hCurHyperlinkHand = LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_HYPERLINKHAND)); - - InitStatusIcons(); - return 0; -} - -static IRichEditOleCallbackVtbl reOleCallbackVtbl; -struct CREOleCallback reOleCallback; - -static STDMETHODIMP_(ULONG) CREOleCallback_QueryInterface(struct CREOleCallback *lpThis, REFIID riid, LPVOID * ppvObj) -{ - if (IsEqualIID(riid, &IID_IRichEditOleCallback)) { - *ppvObj = lpThis; - lpThis->lpVtbl->AddRef((IRichEditOleCallback *) lpThis); - return S_OK; - } - *ppvObj = NULL; - return E_NOINTERFACE; -} - -static STDMETHODIMP_(ULONG) CREOleCallback_AddRef(struct CREOleCallback *lpThis) -{ - if (lpThis->refCount == 0) { - if (S_OK != StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &lpThis->pictStg)) - lpThis->pictStg = NULL; - lpThis->nextStgId = 0; - } - return ++lpThis->refCount; -} - -static STDMETHODIMP_(ULONG) CREOleCallback_Release(struct CREOleCallback *lpThis) -{ - if (--lpThis->refCount == 0) { - if (lpThis->pictStg) - lpThis->pictStg->lpVtbl->Release(lpThis->pictStg); - } - return lpThis->refCount; -} - -static STDMETHODIMP_(HRESULT) CREOleCallback_ContextSensitiveHelp(struct CREOleCallback *lpThis, BOOL fEnterMode) -{ - return S_OK; -} - -static STDMETHODIMP_(HRESULT) CREOleCallback_DeleteObject(struct CREOleCallback *lpThis, LPOLEOBJECT lpoleobj) -{ - return S_OK; -} - -static STDMETHODIMP_(HRESULT) CREOleCallback_GetClipboardData(struct CREOleCallback *lpThis, CHARRANGE * lpchrg, DWORD reco, LPDATAOBJECT * lplpdataobj) -{ - return E_NOTIMPL; -} - -static STDMETHODIMP_(HRESULT) CREOleCallback_GetContextMenu(struct CREOleCallback *lpThis, WORD seltype, LPOLEOBJECT lpoleobj, CHARRANGE * lpchrg, HMENU * lphmenu) -{ - return E_INVALIDARG; -} - -static STDMETHODIMP_(HRESULT) CREOleCallback_GetDragDropEffect(struct CREOleCallback *lpThis, BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect) -{ - return S_OK; -} - -static STDMETHODIMP_(HRESULT) CREOleCallback_GetInPlaceContext(struct CREOleCallback *lpThis, LPOLEINPLACEFRAME * lplpFrame, LPOLEINPLACEUIWINDOW * lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo) -{ - return E_INVALIDARG; -} - -static STDMETHODIMP_(HRESULT) CREOleCallback_GetNewStorage(struct CREOleCallback *lpThis, LPSTORAGE * lplpstg) -{ - WCHAR szwName[64]; - char szName[64]; - wsprintfA(szName, "s%u", lpThis->nextStgId++); - MultiByteToWideChar(CP_ACP, 0, szName, -1, szwName, SIZEOF(szwName)); - if (lpThis->pictStg == NULL) - return STG_E_MEDIUMFULL; - return lpThis->pictStg->lpVtbl->CreateStorage(lpThis->pictStg, szwName, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, lplpstg); -} - -static STDMETHODIMP_(HRESULT) CREOleCallback_QueryAcceptData(struct CREOleCallback *lpThis, LPDATAOBJECT lpdataobj, CLIPFORMAT * lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict) -{ - return S_OK; -} - -static STDMETHODIMP_(HRESULT) CREOleCallback_QueryInsertObject(struct CREOleCallback *lpThis, LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp) -{ - return S_OK; -} - -static STDMETHODIMP_(HRESULT) CREOleCallback_ShowContainerUI(struct CREOleCallback *lpThis, BOOL fShow) -{ - return S_OK; -} - -static void InitREOleCallback(void) -{ - reOleCallback.lpVtbl = &reOleCallbackVtbl; - reOleCallback.lpVtbl->AddRef = (ULONG(__stdcall *) (IRichEditOleCallback *)) CREOleCallback_AddRef; - reOleCallback.lpVtbl->Release = (ULONG(__stdcall *) (IRichEditOleCallback *)) CREOleCallback_Release; - reOleCallback.lpVtbl->QueryInterface = (ULONG(__stdcall *) (IRichEditOleCallback *, REFIID, PVOID *)) CREOleCallback_QueryInterface; - reOleCallback.lpVtbl->ContextSensitiveHelp = (HRESULT(__stdcall *) (IRichEditOleCallback *, BOOL)) CREOleCallback_ContextSensitiveHelp; - reOleCallback.lpVtbl->DeleteObject = (HRESULT(__stdcall *) (IRichEditOleCallback *, LPOLEOBJECT)) CREOleCallback_DeleteObject; - reOleCallback.lpVtbl->GetClipboardData = (HRESULT(__stdcall *) (IRichEditOleCallback *, CHARRANGE *, DWORD, LPDATAOBJECT *)) CREOleCallback_GetClipboardData; - reOleCallback.lpVtbl->GetContextMenu = (HRESULT(__stdcall *) (IRichEditOleCallback *, WORD, LPOLEOBJECT, CHARRANGE *, HMENU *)) CREOleCallback_GetContextMenu; - reOleCallback.lpVtbl->GetDragDropEffect = (HRESULT(__stdcall *) (IRichEditOleCallback *, BOOL, DWORD, LPDWORD)) CREOleCallback_GetDragDropEffect; - reOleCallback.lpVtbl->GetInPlaceContext = (HRESULT(__stdcall *) (IRichEditOleCallback *, LPOLEINPLACEFRAME *, LPOLEINPLACEUIWINDOW *, LPOLEINPLACEFRAMEINFO)) - CREOleCallback_GetInPlaceContext; - reOleCallback.lpVtbl->GetNewStorage = (HRESULT(__stdcall *) (IRichEditOleCallback *, LPSTORAGE *)) CREOleCallback_GetNewStorage; - reOleCallback.lpVtbl->QueryAcceptData = (HRESULT(__stdcall *) (IRichEditOleCallback *, LPDATAOBJECT, CLIPFORMAT *, DWORD, BOOL, HGLOBAL)) CREOleCallback_QueryAcceptData; - reOleCallback.lpVtbl->QueryInsertObject = (HRESULT(__stdcall *) (IRichEditOleCallback *, LPCLSID, LPSTORAGE, LONG)) CREOleCallback_QueryInsertObject; - reOleCallback.lpVtbl->ShowContainerUI = (HRESULT(__stdcall *) (IRichEditOleCallback *, BOOL)) CREOleCallback_ShowContainerUI; - reOleCallback.refCount = 0; -} diff --git a/plugins/SRMM/msgs.cpp b/plugins/SRMM/msgs.cpp new file mode 100644 index 0000000000..ce278f36bd --- /dev/null +++ b/plugins/SRMM/msgs.cpp @@ -0,0 +1,567 @@ +/* +Copyright 2000-2012 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "commonheaders.h" +#include "statusicon.h" + +/* Missing MinGW GUIDs */ +#ifdef __MINGW32__ +const CLSID IID_IRichEditOle = { 0x00020D00, 0x00, 0x00, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; +const CLSID IID_IRichEditOleCallback = { 0x00020D03, 0x00, 0x00, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; +#endif + +HCURSOR hCurSplitNS, hCurSplitWE, hCurHyperlinkHand; +HANDLE hHookWinEvt, hHookWinPopup, hMsgMenuItem; +static HANDLE hServices[7]; +static HANDLE hHooks[8]; + +static int SRMMStatusToPf2(int status) +{ + switch (status) { + case ID_STATUS_ONLINE: return PF2_ONLINE; + case ID_STATUS_AWAY: return PF2_SHORTAWAY; + case ID_STATUS_DND: return PF2_HEAVYDND; + case ID_STATUS_NA: return PF2_LONGAWAY; + case ID_STATUS_OCCUPIED: return PF2_LIGHTDND; + case ID_STATUS_FREECHAT: return PF2_FREECHAT; + case ID_STATUS_INVISIBLE: return PF2_INVISIBLE; + case ID_STATUS_ONTHEPHONE: return PF2_ONTHEPHONE; + case ID_STATUS_OUTTOLUNCH: return PF2_OUTTOLUNCH; + case ID_STATUS_OFFLINE: return MODEF_OFFLINE; + } + return 0; +} + +static int MessageEventAdded(WPARAM wParam, LPARAM lParam) +{ + DBEVENTINFO dbei = {0}; + HWND hwnd; + + dbei.cbSize = sizeof(dbei); + CallService(MS_DB_EVENT_GET, lParam, (LPARAM) & dbei); + + if (dbei.flags & (DBEF_SENT | DBEF_READ) || !(dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei))) + return 0; + + CallServiceSync(MS_CLIST_REMOVEEVENT, wParam, (LPARAM) 1); + /* does a window for the contact exist? */ + hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE) wParam); + if (hwnd) + { + if (!DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DONOTSTEALFOCUS, SRMSGDEFSET_DONOTSTEALFOCUS)) + { + ShowWindow(hwnd, SW_RESTORE); + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); + SetForegroundWindow(hwnd); + SkinPlaySound("RecvMsgActive"); + } + else + { + if (GetForegroundWindow() == hwnd) + SkinPlaySound("RecvMsgActive"); + else + SkinPlaySound("RecvMsgInactive"); + } + return 0; + } + /* new message */ + SkinPlaySound("AlertMsg"); + { + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) wParam, 0); + if (szProto && (g_dat->openFlags & SRMMStatusToPf2(CallProtoService(szProto, PS_GETSTATUS, 0, 0)))) + { + struct NewMessageWindowLParam newData = { 0 }; + newData.hContact = (HANDLE) wParam; + newData.noActivate = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DONOTSTEALFOCUS, SRMSGDEFSET_DONOTSTEALFOCUS); + CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSG), NULL, DlgProcMessage, (LPARAM) & newData); + return 0; + } + } + { + TCHAR toolTip[256], *contactName; + CLISTEVENT cle = {0}; + cle.cbSize = sizeof(cle); + cle.hContact = (HANDLE) wParam; + cle.hDbEvent = (HANDLE) lParam; + cle.flags = CLEF_TCHAR; + cle.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); + cle.pszService = "SRMsg/ReadMessage"; + contactName = (TCHAR*) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, wParam, GCDNF_TCHAR); + mir_sntprintf(toolTip, SIZEOF(toolTip), TranslateT("Message from %s"), contactName); + cle.ptszTooltip = toolTip; + CallService(MS_CLIST_ADDEVENT, 0, (LPARAM) & cle); + } + return 0; +} + +INT_PTR SendMessageCmd(HANDLE hContact, char* msg, int isWchar) +{ + char *szProto; + HWND hwnd; + + /* does the HCONTACT's protocol support IM messages? */ + szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (!szProto || (!CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMSEND)) + return 1; + + if (hwnd = WindowList_Find(g_dat->hMessageWindowList, hContact)) + { + if (msg) + { + HWND hEdit; + hEdit = GetDlgItem(hwnd, IDC_MESSAGE); + SendMessage(hEdit, EM_SETSEL, -1, SendMessage(hEdit, WM_GETTEXTLENGTH, 0, 0)); + if (isWchar) + SendMessage(hEdit, EM_REPLACESEL, FALSE, (LPARAM)msg); + else + SendMessageA(hEdit, EM_REPLACESEL, FALSE, (LPARAM)msg); + } + ShowWindow(hwnd, SW_RESTORE); + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); + SetForegroundWindow(hwnd); + } + else + { + struct NewMessageWindowLParam newData = { 0 }; + newData.hContact = hContact; + newData.szInitialText = msg; + newData.isWchar = isWchar; + hwnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSG), NULL, DlgProcMessage, (LPARAM)&newData); + } + return 0; +} + +static INT_PTR SendMessageCommand_W(WPARAM wParam, LPARAM lParam) +{ + return SendMessageCmd((HANDLE)wParam, (char*)lParam, TRUE); +} + +static INT_PTR SendMessageCommand(WPARAM wParam, LPARAM lParam) +{ + return SendMessageCmd((HANDLE)wParam, (char*)lParam, FALSE); +} + +static INT_PTR ReadMessageCommand(WPARAM wParam, LPARAM lParam) +{ + CLISTEVENT *cle = (CLISTEVENT *) lParam; + + if (cle) + SendMessageCmd(cle->hContact, NULL, 0); + + return 0; +} + +static int TypingMessage(WPARAM wParam, LPARAM lParam) +{ + HWND hwnd; + int foundWin = 0; + + if (!(g_dat->flags&SMF_SHOWTYPING)) + return 0; + if (hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE) wParam)) { + SendMessage(hwnd, DM_TYPING, 0, lParam); + foundWin = 1; + } + if (lParam && !foundWin && (g_dat->flags&SMF_SHOWTYPINGTRAY)) { + TCHAR szTip[256]; + mir_sntprintf(szTip, SIZEOF(szTip), TranslateT("%s is typing a message"), (TCHAR *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, wParam, GCDNF_TCHAR)); + + if (ServiceExists(MS_CLIST_SYSTRAY_NOTIFY) && !(g_dat->flags&SMF_SHOWTYPINGCLIST)) { + MIRANDASYSTRAYNOTIFY tn = {0}; + tn.cbSize = sizeof(tn); + tn.tszInfoTitle = TranslateT("Typing Notification"); + tn.tszInfo = szTip; + tn.dwInfoFlags = NIIF_INFO; + tn.dwInfoFlags |= NIIF_INTERN_UNICODE; + tn.uTimeout = 1000 * 4; + CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM) & tn); + } + else { + CLISTEVENT cle = {0}; + + cle.cbSize = sizeof(cle); + cle.hContact = (HANDLE) wParam; + cle.hDbEvent = (HANDLE) 1; + cle.flags = CLEF_ONLYAFEW | CLEF_TCHAR; + cle.hIcon = LoadSkinnedIcon( SKINICON_OTHER_TYPING ); + cle.pszService = "SRMsg/ReadMessage"; + cle.ptszTooltip = szTip; + CallServiceSync(MS_CLIST_REMOVEEVENT, wParam, (LPARAM) 1); + CallServiceSync(MS_CLIST_ADDEVENT, wParam, (LPARAM) & cle); + CallService(MS_SKIN2_RELEASEICON,(WPARAM)cle.hIcon, 0); + } + } + return 0; +} + +static int MessageSettingChanged(WPARAM wParam, LPARAM lParam) +{ + DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING *) lParam; + HANDLE hContact = (HANDLE)wParam; + + if (cws->szModule == NULL) return 0; + + if (!strcmp(cws->szModule, "CList")) + WindowList_Broadcast(g_dat->hMessageWindowList, DM_UPDATETITLE, (WPARAM) cws, 0); + else if (hContact) + { + if (cws->szSetting && !strcmp(cws->szSetting, "Timezone")) + WindowList_Broadcast(g_dat->hMessageWindowList, DM_NEWTIMEZONE, (WPARAM) cws, 0); + else + { + char * szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, wParam, 0); + if (szProto && !strcmp(cws->szModule, szProto)) + WindowList_Broadcast(g_dat->hMessageWindowList, DM_UPDATETITLE, (WPARAM) cws, 0); + } + } + return 0; +} + +static int ContactDeleted(WPARAM wParam, LPARAM lParam) +{ + HWND hwnd; + if (hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE) wParam)) + SendMessage(hwnd, WM_CLOSE, 0, 0); + + return 0; +} + +static void RestoreUnreadMessageAlerts(void) +{ + CLISTEVENT cle = {0}; + DBEVENTINFO dbei = {0}; + TCHAR toolTip[256]; + int windowAlreadyExists; + HANDLE hDbEvent, hContact; + int autoPopup; + + dbei.cbSize = sizeof(dbei); + cle.cbSize = sizeof(cle); + cle.hIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); + cle.pszService = "SRMsg/ReadMessage"; + cle.flags = CLEF_TCHAR; + cle.ptszTooltip = toolTip; + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact) + { + hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDFIRSTUNREAD, (WPARAM) hContact, 0); + while (hDbEvent) + { + autoPopup = 0; + dbei.cbBlob = 0; + CallService(MS_DB_EVENT_GET, (WPARAM) hDbEvent, (LPARAM) & dbei); + if (!(dbei.flags & (DBEF_SENT | DBEF_READ)) && ( dbei.eventType == EVENTTYPE_MESSAGE || DbEventIsForMsgWindow(&dbei))) + { + windowAlreadyExists = WindowList_Find(g_dat->hMessageWindowList, hContact) != NULL; + if (windowAlreadyExists) + continue; + { + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (szProto && (g_dat->openFlags & SRMMStatusToPf2(CallProtoService(szProto, PS_GETSTATUS, 0, 0)))) + { + autoPopup = 1; + } + } + if (autoPopup && !windowAlreadyExists) + { + struct NewMessageWindowLParam newData = {0}; + newData.hContact = hContact; + newData.noActivate = DBGetContactSettingByte(NULL, SRMMMOD, SRMSGSET_DONOTSTEALFOCUS, SRMSGDEFSET_DONOTSTEALFOCUS); + CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSG), NULL, DlgProcMessage, (LPARAM) & newData); + } + else + { + cle.hContact = hContact; + cle.hDbEvent = hDbEvent; + mir_sntprintf(toolTip, SIZEOF(toolTip), TranslateT("Message from %s"), (TCHAR *) CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM) hContact, GCDNF_TCHAR)); + CallService(MS_CLIST_ADDEVENT, 0, (LPARAM) & cle); + } + } + hDbEvent = (HANDLE) CallService(MS_DB_EVENT_FINDNEXT, (WPARAM) hDbEvent, 0); + } + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } +} + +void RegisterSRMMFonts( void ); + +static int FontsChanged(WPARAM wParam,LPARAM lParam) +{ + WindowList_Broadcast(g_dat->hMessageWindowList, DM_OPTIONSAPPLIED, 0, 0); + return 0; +} + +static int SplitmsgModulesLoaded(WPARAM wParam, LPARAM lParam) +{ + RegisterSRMMFonts(); + LoadMsgLogIcons(); + { + CLISTMENUITEM mi = { 0 }; + mi.cbSize = sizeof(mi); + mi.position = -2000090000; + mi.flags = CMIF_ICONFROMICOLIB | CMIF_DEFAULT; + mi.icolibItem = LoadSkinnedIconHandle( SKINICON_EVENT_MESSAGE ); + mi.pszName = LPGEN("&Message"); + mi.pszService = MS_MSG_SENDMESSAGE; + hMsgMenuItem = Menu_AddContactMenuItem(&mi); + } + HookEvent(ME_FONT_RELOAD, FontsChanged); + + RestoreUnreadMessageAlerts(); + return 0; +} + +int PreshutdownSendRecv(WPARAM wParam, LPARAM lParam) +{ + WindowList_BroadcastAsync(g_dat->hMessageWindowList, WM_CLOSE, 0, 0); + DeinitStatusIcons(); + return 0; +} + +int SplitmsgShutdown(void) +{ + int i; + + DestroyCursor(hCurSplitNS); + DestroyCursor(hCurHyperlinkHand); + DestroyCursor(hCurSplitWE); + + for (i=0; i < SIZEOF(hHooks); ++i) + if (hHooks[i]) + UnhookEvent(hHooks[i]); + + for ( i=0; i < SIZEOF(hServices); ++i) + if (hServices[i]) + DestroyServiceFunction(hServices[i]); + + FreeMsgLogIcons(); + FreeLibrary(GetModuleHandleA("riched20")); + OleUninitialize(); + RichUtil_Unload(); + msgQueue_destroy(); + FreeGlobals(); + return 0; +} + +static int IconsChanged(WPARAM wParam, LPARAM lParam) +{ + FreeMsgLogIcons(); + LoadMsgLogIcons(); + WindowList_Broadcast(g_dat->hMessageWindowList, DM_REMAKELOG, 0, 0); + // change all the icons + WindowList_Broadcast(g_dat->hMessageWindowList, DM_UPDATEWINICON, 0, 0); + return 0; +} + +static int 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 ) { + // leave this menu item hidden for chats + if ( !DBGetContactSettingByte( hContact, szProto, "ChatRoom", 0 )) + if ( CallProtoService( szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMSEND ) + clmi.flags &= ~CMIF_HIDDEN; + } + + CallService( MS_CLIST_MODIFYMENUITEM, ( WPARAM )hMsgMenuItem, ( LPARAM )&clmi ); + } + return 0; +} + +static INT_PTR GetWindowAPI(WPARAM wParam, LPARAM lParam) +{ + return PLUGIN_MAKE_VERSION(0,0,0,4); +} + +static INT_PTR GetWindowClass(WPARAM wParam, LPARAM lParam) +{ + char *szBuf = (char*)wParam; + int size = (int)lParam; + mir_snprintf(szBuf, size, SRMMMOD); + return 0; +} + +static INT_PTR GetWindowData(WPARAM wParam, LPARAM lParam) +{ + MessageWindowInputData *mwid = (MessageWindowInputData*)wParam; + MessageWindowData *mwd = (MessageWindowData*)lParam; + HWND hwnd; + + if (mwid == NULL || mwd == NULL) return 1; + if (mwid->cbSize != sizeof(MessageWindowInputData) || mwd->cbSize != sizeof(SrmmWindowData)) return 1; + if (mwid->hContact == NULL) return 1; + if (mwid->uFlags != MSG_WINDOW_UFLAG_MSG_BOTH) return 1; + hwnd = WindowList_Find(g_dat->hMessageWindowList, mwid->hContact); + mwd->uFlags = MSG_WINDOW_UFLAG_MSG_BOTH; + mwd->hwndWindow = hwnd; + mwd->local = 0; + mwd->uState = SendMessage(hwnd, DM_GETWINDOWSTATE, 0, 0); + return 0; +} + +int LoadSendRecvMessageModule(void) +{ + if (LoadLibraryA("riched20.dll") == NULL) { + if (IDYES != + MessageBox(0, + TranslateT + ("Miranda could not load the built-in message module, riched20.dll is missing. If you are using Windows 95 or WINE please make sure you have riched20.dll installed. Press 'Yes' to continue loading Miranda."), + TranslateT("Information"), MB_YESNO | MB_ICONINFORMATION)) + return 1; + return 0; + } + + InitGlobals(); + RichUtil_Load(); + OleInitialize(NULL); + InitOptions(); + msgQueue_init(); + + hHooks[0] = HookEvent(ME_DB_EVENT_ADDED, MessageEventAdded); + hHooks[1] = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, MessageSettingChanged); + hHooks[2] = HookEvent(ME_DB_CONTACT_DELETED, ContactDeleted); + hHooks[3] = HookEvent(ME_SYSTEM_MODULESLOADED, SplitmsgModulesLoaded); + hHooks[4] = HookEvent(ME_SKIN_ICONSCHANGED, IconsChanged); + hHooks[5] = HookEvent(ME_PROTO_CONTACTISTYPING, TypingMessage); + hHooks[6] = HookEvent(ME_SYSTEM_PRESHUTDOWN, PreshutdownSendRecv); + hHooks[7] = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PrebuildContactMenu); + + hServices[0] = CreateServiceFunction(MS_MSG_SENDMESSAGE, SendMessageCommand); + hServices[1] = CreateServiceFunction(MS_MSG_SENDMESSAGEW, SendMessageCommand_W); + hServices[2] = CreateServiceFunction(MS_MSG_GETWINDOWAPI, GetWindowAPI); + hServices[3] = CreateServiceFunction(MS_MSG_GETWINDOWCLASS, GetWindowClass); + hServices[4] = CreateServiceFunction(MS_MSG_GETWINDOWDATA, GetWindowData); + hServices[5] = CreateServiceFunction("SRMsg/ReadMessage", ReadMessageCommand); + + hHookWinEvt = CreateHookableEvent(ME_MSG_WINDOWEVENT); + hHookWinPopup = CreateHookableEvent(ME_MSG_WINDOWPOPUP); + + SkinAddNewSoundEx("RecvMsgActive", LPGEN("Instant messages"), LPGEN("Incoming (Focused Window)")); + SkinAddNewSoundEx("RecvMsgInactive", LPGEN("Instant messages"), LPGEN("Incoming (Unfocused Window)")); + SkinAddNewSoundEx("AlertMsg", LPGEN("Instant messages"), LPGEN("Incoming (New Session)")); + SkinAddNewSoundEx("SendMsg", LPGEN("Instant messages"), LPGEN("Outgoing")); + SkinAddNewSoundEx("SendError", LPGEN("Instant messages"), LPGEN("Message send error")); + + hCurSplitNS = LoadCursor(NULL, IDC_SIZENS); + hCurSplitWE = LoadCursor(NULL, IDC_SIZEWE); + hCurHyperlinkHand = LoadCursor(NULL, IDC_HAND); + if (hCurHyperlinkHand == NULL) + hCurHyperlinkHand = LoadCursor(g_hInst, MAKEINTRESOURCE(IDC_HYPERLINKHAND)); + + InitStatusIcons(); + return 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////// + +CREOleCallback reOleCallback; + +STDMETHODIMP CREOleCallback::QueryInterface(REFIID riid, LPVOID * ppvObj) +{ + if (IsEqualIID(riid, IID_IRichEditOleCallback)) { + *ppvObj = this; + AddRef(); + return S_OK; + } + *ppvObj = NULL; + return E_NOINTERFACE; +} + +STDMETHODIMP_(ULONG) CREOleCallback::AddRef() +{ + if (refCount == 0) { + if (S_OK != StgCreateDocfile(NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_DELETEONRELEASE, 0, &pictStg)) + pictStg = NULL; + nextStgId = 0; + } + return ++refCount; +} + +STDMETHODIMP_(ULONG) CREOleCallback::Release() +{ + if (--refCount == 0) { + if (pictStg) + pictStg->Release(); + } + return refCount; +} + +STDMETHODIMP CREOleCallback::ContextSensitiveHelp(BOOL fEnterMode) +{ + return S_OK; +} + +STDMETHODIMP CREOleCallback::DeleteObject(LPOLEOBJECT lpoleobj) +{ + return S_OK; +} + +STDMETHODIMP CREOleCallback::GetClipboardData(CHARRANGE * lpchrg, DWORD reco, LPDATAOBJECT * lplpdataobj) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CREOleCallback::GetContextMenu(WORD seltype, LPOLEOBJECT lpoleobj, CHARRANGE * lpchrg, HMENU * lphmenu) +{ + return E_INVALIDARG; +} + +STDMETHODIMP CREOleCallback::GetDragDropEffect(BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect) +{ + return S_OK; +} + +STDMETHODIMP CREOleCallback::GetInPlaceContext(LPOLEINPLACEFRAME * lplpFrame, LPOLEINPLACEUIWINDOW * lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo) +{ + return E_INVALIDARG; +} + +STDMETHODIMP CREOleCallback::GetNewStorage(LPSTORAGE * lplpstg) +{ + WCHAR szwName[64]; + char szName[64]; + wsprintfA(szName, "s%u", nextStgId++); + MultiByteToWideChar(CP_ACP, 0, szName, -1, szwName, SIZEOF(szwName)); + if (pictStg == NULL) + return STG_E_MEDIUMFULL; + return pictStg->CreateStorage(szwName, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, 0, lplpstg); +} + +STDMETHODIMP CREOleCallback::QueryAcceptData(LPDATAOBJECT lpdataobj, CLIPFORMAT * lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict) +{ + return S_OK; +} + +STDMETHODIMP CREOleCallback::QueryInsertObject(LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp) +{ + return S_OK; +} + +STDMETHODIMP CREOleCallback::ShowContainerUI(BOOL fShow) +{ + return S_OK; +} diff --git a/plugins/SRMM/msgs.h b/plugins/SRMM/msgs.h index 842b291a08..4a02e67a32 100644 --- a/plugins/SRMM/msgs.h +++ b/plugins/SRMM/msgs.h @@ -31,7 +31,7 @@ struct NewMessageWindowLParam int noActivate; }; -struct MessageWindowData +struct SrmmWindowData { HANDLE hContact; HANDLE hDbEventFirst, hDbEventLast; @@ -89,18 +89,33 @@ struct MessageWindowData #define EVENTTYPE_JABBER_PRESENCE 2001 #define EVENTTYPE_STATUSCHANGE 25368 -struct CREOleCallback +struct CREOleCallback : public IRichEditOleCallback { - IRichEditOleCallbackVtbl *lpVtbl; + CREOleCallback() : refCount(0) {} unsigned refCount; IStorage *pictStg; int nextStgId; + + STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR * lplpObj); + STDMETHOD_(ULONG,AddRef) (THIS); + STDMETHOD_(ULONG,Release) (THIS); + + STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode); + STDMETHOD(GetNewStorage) (LPSTORAGE FAR * lplpstg); + STDMETHOD(GetInPlaceContext) (LPOLEINPLACEFRAME FAR * lplpFrame, LPOLEINPLACEUIWINDOW FAR * lplpDoc, LPOLEINPLACEFRAMEINFO lpFrameInfo); + STDMETHOD(ShowContainerUI) (BOOL fShow); + STDMETHOD(QueryInsertObject) (LPCLSID lpclsid, LPSTORAGE lpstg, LONG cp); + STDMETHOD(DeleteObject) (LPOLEOBJECT lpoleobj); + STDMETHOD(QueryAcceptData) (LPDATAOBJECT lpdataobj, CLIPFORMAT FAR * lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict); + STDMETHOD(GetClipboardData) (CHARRANGE FAR * lpchrg, DWORD reco, LPDATAOBJECT FAR * lplpdataobj); + STDMETHOD(GetDragDropEffect) (BOOL fDrag, DWORD grfKeyState, LPDWORD pdwEffect); + STDMETHOD(GetContextMenu) (WORD seltype, LPOLEOBJECT lpoleobj, CHARRANGE FAR * lpchrg, HMENU FAR * lphmenu) ; }; INT_PTR CALLBACK DlgProcMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK ErrorDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); int DbEventIsForMsgWindow(DBEVENTINFO *dbei); -int DbEventIsShown(DBEVENTINFO * dbei, struct MessageWindowData *dat); +int DbEventIsShown(DBEVENTINFO * dbei, struct SrmmWindowData *dat); void StreamInEvents(HWND hwndDlg, HANDLE hDbEventFirst, int count, int fAppend); HANDLE SendMessageDirect(const TCHAR *szMsg, HANDLE hContact, char *szProto); diff --git a/plugins/SRMM/msgtimedout.c b/plugins/SRMM/msgtimedout.c deleted file mode 100644 index 1b1773aa8e..0000000000 --- a/plugins/SRMM/msgtimedout.c +++ /dev/null @@ -1,112 +0,0 @@ -/* -Copyright 2000-2010 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "commonheaders.h" -#include "msgs.h" - -typedef struct -{ - const char *szMsg; - TMsgQueue *item; -} ErrorDlgParam; - -INT_PTR SendMessageCmd(HANDLE hContact, char* msg, int isWchar); - -INT_PTR CALLBACK ErrorDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - TMsgQueue *item = (TMsgQueue*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - - switch (msg) - { - case WM_INITDIALOG: - { - RECT rc, rcParent; - ErrorDlgParam *param = (ErrorDlgParam *) lParam; - item = param->item; - - TranslateDialogDefault(hwndDlg); - - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)item); - - if (!param->szMsg || !param->szMsg[0]) - SetDlgItemText(hwndDlg, IDC_ERRORTEXT, TranslateT("An unknown error has occured.")); - else - { - TCHAR* ptszError = (TCHAR*)CallService(MS_LANGPACK_PCHARTOTCHAR, 0, (LPARAM)param->szMsg); - SetDlgItemText(hwndDlg, IDC_ERRORTEXT, ptszError); - mir_free(ptszError); - } - - SetDlgItemText(hwndDlg, IDC_MSGTEXT, item->szMsg); - - GetWindowRect(hwndDlg, &rc); - GetWindowRect(GetParent(hwndDlg), &rcParent); - SetWindowPos(hwndDlg, 0, (rcParent.left + rcParent.right - (rc.right - rc.left)) / 2, - (rcParent.top + rcParent.bottom - (rc.bottom - rc.top)) / 2, - 0, 0, SWP_NOZORDER | SWP_NOSIZE); - } - return TRUE; - - case WM_DESTROY: - mir_free(item->szMsg); - mir_free(item); - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDOK: - { - char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) item->hContact, 0); - SendMessageDirect(item->szMsg, item->hContact, szProto); - } - - DestroyWindow(hwndDlg); - break; - - case IDCANCEL: - DestroyWindow(hwndDlg); - break; - } - break; - } - return FALSE; -} - -void MessageFailureProcess(TMsgQueue *item, const char* err) -{ - HWND hwnd; - ErrorDlgParam param = { err, item }; - - CallService(MS_DB_EVENT_DELETE, (WPARAM)item->hContact, (LPARAM)item->hDbEvent); - - hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE)item->hContact); - if (hwnd == NULL) - { - SendMessageCmd(item->hContact, NULL, 0); - hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE)item->hContact); - } - else - SendMessage(hwnd, DM_REMAKELOG, 0, 0); - - SkinPlaySound("SendError"); - CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSGSENDERROR), hwnd, ErrorDlgProc, (LPARAM) ¶m); -} - diff --git a/plugins/SRMM/msgtimedout.cpp b/plugins/SRMM/msgtimedout.cpp new file mode 100644 index 0000000000..5b85682d87 --- /dev/null +++ b/plugins/SRMM/msgtimedout.cpp @@ -0,0 +1,112 @@ +/* +Copyright 2000-2010 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "commonheaders.h" +#include "msgs.h" + +typedef struct +{ + const char *szMsg; + TMsgQueue *item; +} ErrorDlgParam; + +INT_PTR SendMessageCmd(HANDLE hContact, char* msg, int isWchar); + +INT_PTR CALLBACK ErrorDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + TMsgQueue *item = (TMsgQueue*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + switch (msg) + { + case WM_INITDIALOG: + { + RECT rc, rcParent; + ErrorDlgParam *param = (ErrorDlgParam *) lParam; + item = param->item; + + TranslateDialogDefault(hwndDlg); + + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)item); + + if (!param->szMsg || !param->szMsg[0]) + SetDlgItemText(hwndDlg, IDC_ERRORTEXT, TranslateT("An unknown error has occured.")); + else + { + TCHAR* ptszError = (TCHAR*)CallService(MS_LANGPACK_PCHARTOTCHAR, 0, (LPARAM)param->szMsg); + SetDlgItemText(hwndDlg, IDC_ERRORTEXT, ptszError); + mir_free(ptszError); + } + + SetDlgItemText(hwndDlg, IDC_MSGTEXT, item->szMsg); + + GetWindowRect(hwndDlg, &rc); + GetWindowRect(GetParent(hwndDlg), &rcParent); + SetWindowPos(hwndDlg, 0, (rcParent.left + rcParent.right - (rc.right - rc.left)) / 2, + (rcParent.top + rcParent.bottom - (rc.bottom - rc.top)) / 2, + 0, 0, SWP_NOZORDER | SWP_NOSIZE); + } + return TRUE; + + case WM_DESTROY: + mir_free(item->szMsg); + mir_free(item); + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + { + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) item->hContact, 0); + SendMessageDirect(item->szMsg, item->hContact, szProto); + } + + DestroyWindow(hwndDlg); + break; + + case IDCANCEL: + DestroyWindow(hwndDlg); + break; + } + break; + } + return FALSE; +} + +void MessageFailureProcess(TMsgQueue *item, const char* err) +{ + HWND hwnd; + ErrorDlgParam param = { err, item }; + + CallService(MS_DB_EVENT_DELETE, (WPARAM)item->hContact, (LPARAM)item->hDbEvent); + + hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE)item->hContact); + if (hwnd == NULL) + { + SendMessageCmd(item->hContact, NULL, 0); + hwnd = WindowList_Find(g_dat->hMessageWindowList, (HANDLE)item->hContact); + } + else + SendMessage(hwnd, DM_REMAKELOG, 0, 0); + + SkinPlaySound("SendError"); + CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_MSGSENDERROR), hwnd, ErrorDlgProc, (LPARAM) ¶m); +} + diff --git a/plugins/SRMM/richutil.c b/plugins/SRMM/richutil.c deleted file mode 100644 index a8253be098..0000000000 --- a/plugins/SRMM/richutil.c +++ /dev/null @@ -1,269 +0,0 @@ -/* -Copyright 2000-2010 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ -#include "commonheaders.h" -#include "richutil.h" - -/* - To initialize this library, call: - RichUtil_Load(); - Before the application exits, call: - RichUtil_Unload(); - - Then to use the library (it draws the xp border around it), you need - to make sure you control has the WS_EX_CLIENTEDGE flag. Then you just - subclass it with: - RichUtil_SubClass(hwndEdit); - - If no xptheme is present, the window isn't subclassed the SubClass function - just returns. And if WS_EX_CLIENTEDGE isn't present, the subclass does nothing. - Otherwise it removes the border and draws it by itself. -*/ - -static SortedList sListInt; - -static int RichUtil_CmpVal(void *p1, void *p2) -{ - TRichUtil *tp1 = (TRichUtil*)p1; - TRichUtil *tp2 = (TRichUtil*)p2; - return (int)((INT_PTR)tp1->hwnd - (INT_PTR)tp2->hwnd); -} - -// UxTheme Stuff -static HMODULE mTheme; - -static HANDLE (WINAPI *MyOpenThemeData)(HWND, LPCWSTR); -static HRESULT (WINAPI *MyCloseThemeData)(HANDLE); -static BOOL (WINAPI *MyIsThemeActive)(VOID); -static HRESULT (WINAPI *MyDrawThemeBackground)(HANDLE, HDC, int, int, LPCRECT, LPCRECT); -static HRESULT (WINAPI *MyGetThemeBackgroundContentRect)(HANDLE, HDC, int, int, LPCRECT, LPRECT); -static HRESULT (WINAPI *MyDrawThemeParentBackground)(HWND, HDC, LPRECT); -static BOOL (WINAPI *MyIsThemeBackgroundPartiallyTransparent)(HANDLE, int, int); - -static CRITICAL_SECTION csRich; - -static LRESULT CALLBACK RichUtil_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); -static void RichUtil_ClearUglyBorder(TRichUtil *ru); - -void RichUtil_Load(void) -{ - sListInt.increment = 10; - sListInt.sortFunc = RichUtil_CmpVal; - - mTheme = IsWinVerXPPlus() ? GetModuleHandleA("uxtheme") : 0; - - InitializeCriticalSection(&csRich); - if (!mTheme) return; - - MyOpenThemeData = (HANDLE (WINAPI *)(HWND, LPCWSTR))GetProcAddress(mTheme, "OpenThemeData"); - MyCloseThemeData = (HRESULT (WINAPI *)(HANDLE))GetProcAddress(mTheme, "CloseThemeData"); - MyIsThemeActive = (BOOL (WINAPI *)(VOID))GetProcAddress(mTheme, "IsThemeActive"); - MyDrawThemeBackground = (HRESULT (WINAPI *)(HANDLE, HDC, int, int, const RECT*, const RECT *))GetProcAddress(mTheme, "DrawThemeBackground"); - MyGetThemeBackgroundContentRect = (HRESULT (WINAPI *)(HANDLE, HDC, int, int, const RECT *, RECT *))GetProcAddress(mTheme, "GetThemeBackgroundContentRect"); - MyDrawThemeParentBackground = (HRESULT (WINAPI *)(HWND, HDC, RECT*))GetProcAddress(mTheme, "DrawThemeParentBackground"); - MyIsThemeBackgroundPartiallyTransparent = (BOOL (WINAPI *)(HANDLE, int, int))GetProcAddress(mTheme, "IsThemeBackgroundPartiallyTransparent"); - - if (!MyOpenThemeData || - !MyCloseThemeData || - !MyIsThemeActive || - !MyDrawThemeBackground || - !MyGetThemeBackgroundContentRect || - !MyDrawThemeParentBackground || - !MyIsThemeBackgroundPartiallyTransparent) - { - FreeLibrary(mTheme); - mTheme = NULL; - } -} - -void RichUtil_Unload(void) -{ - li.List_Destroy(&sListInt); - DeleteCriticalSection(&csRich); - if (mTheme) - FreeLibrary(mTheme); -} - -int RichUtil_SubClass(HWND hwndEdit) -{ - if (IsWindow(hwndEdit)) - { - int idx; - - TRichUtil *ru = (TRichUtil*)mir_calloc(sizeof(TRichUtil)); - - ru->hwnd = hwndEdit; - ru->hasUglyBorder = 0; - - EnterCriticalSection(&csRich); - if (!li.List_GetIndex(&sListInt, ru, &idx)) - li.List_Insert(&sListInt, ru, idx); - LeaveCriticalSection(&csRich); - - ru->origProc = (WNDPROC)SetWindowLongPtr(ru->hwnd, GWLP_WNDPROC, (LONG_PTR)&RichUtil_Proc); - RichUtil_ClearUglyBorder(ru); - return 1; - } - return 0; -} - -static LRESULT CALLBACK RichUtil_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - TRichUtil *ru; - - EnterCriticalSection(&csRich); - ru = li.List_Find(&sListInt, (TRichUtil*)&hwnd); - LeaveCriticalSection(&csRich); - - if (ru == NULL) return 0; - - switch(msg) - { - case WM_CHAR: - { - HWND hwndMsg = GetDlgItem(GetParent(hwnd), IDC_MESSAGE); - if (hwndMsg != hwnd) - { - SetFocus(hwndMsg); - SendMessage(hwndMsg, WM_CHAR, wParam, lParam); - } - break; - } - - case WM_THEMECHANGED: - case WM_STYLECHANGED: - { - RichUtil_ClearUglyBorder(ru); - break; - } - - case WM_NCPAINT: - { - LRESULT ret = CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam); - if (ru->hasUglyBorder && MyIsThemeActive()) - { - HANDLE hTheme = MyOpenThemeData(ru->hwnd, L"EDIT"); - if (hTheme) - { - RECT rcBorder; - RECT rcClient; - int nState; - HDC hdc = GetWindowDC(ru->hwnd); - LONG style = GetWindowLongPtr(hwnd, GWL_STYLE); - - GetWindowRect(hwnd, &rcBorder); - rcBorder.right -= rcBorder.left; rcBorder.bottom -= rcBorder.top; - rcBorder.left = rcBorder.top = 0; - CopyRect(&rcClient, &rcBorder); - rcClient.left += ru->rect.left; - rcClient.top += ru->rect.top; - rcClient.right -= ru->rect.right; - rcClient.bottom -= ru->rect.bottom; - ExcludeClipRect(hdc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); - - if (MyIsThemeBackgroundPartiallyTransparent(hTheme, EP_EDITTEXT, ETS_NORMAL)) - MyDrawThemeParentBackground(hwnd, hdc, &rcBorder); - - if (style & WS_DISABLED) - nState = ETS_DISABLED; - else if (style & ES_READONLY) - nState = ETS_READONLY; - else - nState = ETS_NORMAL; - - MyDrawThemeBackground(hTheme, hdc, EP_EDITTEXT, nState, &rcBorder, NULL); - MyCloseThemeData(hTheme); - ReleaseDC(hwnd, hdc); - return 0; - } - } - return ret; - } - case WM_NCCALCSIZE: - { - LRESULT ret = CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam); - NCCALCSIZE_PARAMS *ncsParam = (NCCALCSIZE_PARAMS*)lParam; - - if (ru->hasUglyBorder && MyIsThemeActive()) - { - HANDLE hTheme = MyOpenThemeData(hwnd, L"EDIT"); - - if (hTheme) - { - RECT rcClient ={0}; - HDC hdc = GetDC(GetParent(hwnd)); - - if (MyGetThemeBackgroundContentRect(hTheme, hdc, EP_EDITTEXT, ETS_NORMAL, &ncsParam->rgrc[0], &rcClient) == S_OK) - { - ru->rect.left = rcClient.left-ncsParam->rgrc[0].left; - ru->rect.top = rcClient.top-ncsParam->rgrc[0].top; - ru->rect.right = ncsParam->rgrc[0].right-rcClient.right; - ru->rect.bottom = ncsParam->rgrc[0].bottom-rcClient.bottom; - ncsParam->rgrc[0] = rcClient; - - MyCloseThemeData(hTheme); - ReleaseDC(GetParent(hwnd), hdc); - return WVR_REDRAW; - } - ReleaseDC(GetParent(hwnd), hdc); - MyCloseThemeData(hTheme); - } - } - return ret; - } - - case WM_ENABLE: - RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_NOCHILDREN | RDW_UPDATENOW | RDW_FRAME); - break; - - case WM_GETDLGCODE: - return CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam) & ~DLGC_HASSETSEL; - - case WM_NCDESTROY: - { - LRESULT ret = CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam); - - if (IsWindow(hwnd)) - { - if ((WNDPROC)GetWindowLongPtr(hwnd, GWLP_WNDPROC) == &RichUtil_Proc) - SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)ru->origProc); - } - - EnterCriticalSection(&csRich); - li.List_RemovePtr(&sListInt, ru); - LeaveCriticalSection(&csRich); - - mir_free(ru); - return ret; - } - } - return CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam); -} - -static void RichUtil_ClearUglyBorder(TRichUtil *ru) -{ - if (mTheme && MyIsThemeActive() && GetWindowLongPtr(ru->hwnd, GWL_EXSTYLE) & WS_EX_CLIENTEDGE) - { - ru->hasUglyBorder = 1; - SetWindowLongPtr(ru->hwnd, GWL_EXSTYLE, GetWindowLongPtr(ru->hwnd, GWL_EXSTYLE) ^ WS_EX_CLIENTEDGE); - } - // Redraw window since the style may have changed - SetWindowPos(ru->hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); - RedrawWindow(ru->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_NOCHILDREN | RDW_UPDATENOW | RDW_FRAME); -} diff --git a/plugins/SRMM/richutil.cpp b/plugins/SRMM/richutil.cpp new file mode 100644 index 0000000000..5210f1bf00 --- /dev/null +++ b/plugins/SRMM/richutil.cpp @@ -0,0 +1,269 @@ +/* +Copyright 2000-2010 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "commonheaders.h" +#include "richutil.h" + +/* + To initialize this library, call: + RichUtil_Load(); + Before the application exits, call: + RichUtil_Unload(); + + Then to use the library (it draws the xp border around it), you need + to make sure you control has the WS_EX_CLIENTEDGE flag. Then you just + subclass it with: + RichUtil_SubClass(hwndEdit); + + If no xptheme is present, the window isn't subclassed the SubClass function + just returns. And if WS_EX_CLIENTEDGE isn't present, the subclass does nothing. + Otherwise it removes the border and draws it by itself. +*/ + +static SortedList sListInt; + +static int RichUtil_CmpVal(void *p1, void *p2) +{ + TRichUtil *tp1 = (TRichUtil*)p1; + TRichUtil *tp2 = (TRichUtil*)p2; + return (int)((INT_PTR)tp1->hwnd - (INT_PTR)tp2->hwnd); +} + +// UxTheme Stuff +static HMODULE mTheme; + +static HANDLE (WINAPI *MyOpenThemeData)(HWND, LPCWSTR); +static HRESULT (WINAPI *MyCloseThemeData)(HANDLE); +static BOOL (WINAPI *MyIsThemeActive)(VOID); +static HRESULT (WINAPI *MyDrawThemeBackground)(HANDLE, HDC, int, int, LPCRECT, LPCRECT); +static HRESULT (WINAPI *MyGetThemeBackgroundContentRect)(HANDLE, HDC, int, int, LPCRECT, LPRECT); +static HRESULT (WINAPI *MyDrawThemeParentBackground)(HWND, HDC, LPRECT); +static BOOL (WINAPI *MyIsThemeBackgroundPartiallyTransparent)(HANDLE, int, int); + +static CRITICAL_SECTION csRich; + +static LRESULT CALLBACK RichUtil_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +static void RichUtil_ClearUglyBorder(TRichUtil *ru); + +void RichUtil_Load(void) +{ + sListInt.increment = 10; + sListInt.sortFunc = RichUtil_CmpVal; + + mTheme = IsWinVerXPPlus() ? GetModuleHandleA("uxtheme") : 0; + + InitializeCriticalSection(&csRich); + if (!mTheme) return; + + MyOpenThemeData = (HANDLE (WINAPI *)(HWND, LPCWSTR))GetProcAddress(mTheme, "OpenThemeData"); + MyCloseThemeData = (HRESULT (WINAPI *)(HANDLE))GetProcAddress(mTheme, "CloseThemeData"); + MyIsThemeActive = (BOOL (WINAPI *)(VOID))GetProcAddress(mTheme, "IsThemeActive"); + MyDrawThemeBackground = (HRESULT (WINAPI *)(HANDLE, HDC, int, int, const RECT*, const RECT *))GetProcAddress(mTheme, "DrawThemeBackground"); + MyGetThemeBackgroundContentRect = (HRESULT (WINAPI *)(HANDLE, HDC, int, int, const RECT *, RECT *))GetProcAddress(mTheme, "GetThemeBackgroundContentRect"); + MyDrawThemeParentBackground = (HRESULT (WINAPI *)(HWND, HDC, RECT*))GetProcAddress(mTheme, "DrawThemeParentBackground"); + MyIsThemeBackgroundPartiallyTransparent = (BOOL (WINAPI *)(HANDLE, int, int))GetProcAddress(mTheme, "IsThemeBackgroundPartiallyTransparent"); + + if (!MyOpenThemeData || + !MyCloseThemeData || + !MyIsThemeActive || + !MyDrawThemeBackground || + !MyGetThemeBackgroundContentRect || + !MyDrawThemeParentBackground || + !MyIsThemeBackgroundPartiallyTransparent) + { + FreeLibrary(mTheme); + mTheme = NULL; + } +} + +void RichUtil_Unload(void) +{ + li.List_Destroy(&sListInt); + DeleteCriticalSection(&csRich); + if (mTheme) + FreeLibrary(mTheme); +} + +int RichUtil_SubClass(HWND hwndEdit) +{ + if (IsWindow(hwndEdit)) + { + int idx; + + TRichUtil *ru = (TRichUtil*)mir_calloc(sizeof(TRichUtil)); + + ru->hwnd = hwndEdit; + ru->hasUglyBorder = 0; + + EnterCriticalSection(&csRich); + if (!li.List_GetIndex(&sListInt, ru, &idx)) + li.List_Insert(&sListInt, ru, idx); + LeaveCriticalSection(&csRich); + + ru->origProc = (WNDPROC)SetWindowLongPtr(ru->hwnd, GWLP_WNDPROC, (LONG_PTR)&RichUtil_Proc); + RichUtil_ClearUglyBorder(ru); + return 1; + } + return 0; +} + +static LRESULT CALLBACK RichUtil_Proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + TRichUtil *ru; + + EnterCriticalSection(&csRich); + ru = (TRichUtil *)li.List_Find(&sListInt, (TRichUtil*)&hwnd); + LeaveCriticalSection(&csRich); + + if (ru == NULL) return 0; + + switch(msg) + { + case WM_CHAR: + { + HWND hwndMsg = GetDlgItem(GetParent(hwnd), IDC_MESSAGE); + if (hwndMsg != hwnd) + { + SetFocus(hwndMsg); + SendMessage(hwndMsg, WM_CHAR, wParam, lParam); + } + break; + } + + case WM_THEMECHANGED: + case WM_STYLECHANGED: + { + RichUtil_ClearUglyBorder(ru); + break; + } + + case WM_NCPAINT: + { + LRESULT ret = CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam); + if (ru->hasUglyBorder && MyIsThemeActive()) + { + HANDLE hTheme = MyOpenThemeData(ru->hwnd, L"EDIT"); + if (hTheme) + { + RECT rcBorder; + RECT rcClient; + int nState; + HDC hdc = GetWindowDC(ru->hwnd); + LONG style = GetWindowLongPtr(hwnd, GWL_STYLE); + + GetWindowRect(hwnd, &rcBorder); + rcBorder.right -= rcBorder.left; rcBorder.bottom -= rcBorder.top; + rcBorder.left = rcBorder.top = 0; + CopyRect(&rcClient, &rcBorder); + rcClient.left += ru->rect.left; + rcClient.top += ru->rect.top; + rcClient.right -= ru->rect.right; + rcClient.bottom -= ru->rect.bottom; + ExcludeClipRect(hdc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); + + if (MyIsThemeBackgroundPartiallyTransparent(hTheme, EP_EDITTEXT, ETS_NORMAL)) + MyDrawThemeParentBackground(hwnd, hdc, &rcBorder); + + if (style & WS_DISABLED) + nState = ETS_DISABLED; + else if (style & ES_READONLY) + nState = ETS_READONLY; + else + nState = ETS_NORMAL; + + MyDrawThemeBackground(hTheme, hdc, EP_EDITTEXT, nState, &rcBorder, NULL); + MyCloseThemeData(hTheme); + ReleaseDC(hwnd, hdc); + return 0; + } + } + return ret; + } + case WM_NCCALCSIZE: + { + LRESULT ret = CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam); + NCCALCSIZE_PARAMS *ncsParam = (NCCALCSIZE_PARAMS*)lParam; + + if (ru->hasUglyBorder && MyIsThemeActive()) + { + HANDLE hTheme = MyOpenThemeData(hwnd, L"EDIT"); + + if (hTheme) + { + RECT rcClient ={0}; + HDC hdc = GetDC(GetParent(hwnd)); + + if (MyGetThemeBackgroundContentRect(hTheme, hdc, EP_EDITTEXT, ETS_NORMAL, &ncsParam->rgrc[0], &rcClient) == S_OK) + { + ru->rect.left = rcClient.left-ncsParam->rgrc[0].left; + ru->rect.top = rcClient.top-ncsParam->rgrc[0].top; + ru->rect.right = ncsParam->rgrc[0].right-rcClient.right; + ru->rect.bottom = ncsParam->rgrc[0].bottom-rcClient.bottom; + ncsParam->rgrc[0] = rcClient; + + MyCloseThemeData(hTheme); + ReleaseDC(GetParent(hwnd), hdc); + return WVR_REDRAW; + } + ReleaseDC(GetParent(hwnd), hdc); + MyCloseThemeData(hTheme); + } + } + return ret; + } + + case WM_ENABLE: + RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE | RDW_NOCHILDREN | RDW_UPDATENOW | RDW_FRAME); + break; + + case WM_GETDLGCODE: + return CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam) & ~DLGC_HASSETSEL; + + case WM_NCDESTROY: + { + LRESULT ret = CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam); + + if (IsWindow(hwnd)) + { + if ((WNDPROC)GetWindowLongPtr(hwnd, GWLP_WNDPROC) == &RichUtil_Proc) + SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)ru->origProc); + } + + EnterCriticalSection(&csRich); + li.List_RemovePtr(&sListInt, ru); + LeaveCriticalSection(&csRich); + + mir_free(ru); + return ret; + } + } + return CallWindowProc(ru->origProc, hwnd, msg, wParam, lParam); +} + +static void RichUtil_ClearUglyBorder(TRichUtil *ru) +{ + if (mTheme && MyIsThemeActive() && GetWindowLongPtr(ru->hwnd, GWL_EXSTYLE) & WS_EX_CLIENTEDGE) + { + ru->hasUglyBorder = 1; + SetWindowLongPtr(ru->hwnd, GWL_EXSTYLE, GetWindowLongPtr(ru->hwnd, GWL_EXSTYLE) ^ WS_EX_CLIENTEDGE); + } + // Redraw window since the style may have changed + SetWindowPos(ru->hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED); + RedrawWindow(ru->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_NOCHILDREN | RDW_UPDATENOW | RDW_FRAME); +} diff --git a/plugins/SRMM/srmm.c b/plugins/SRMM/srmm.c deleted file mode 100644 index 801b856a61..0000000000 --- a/plugins/SRMM/srmm.c +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright 2000-2012 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "commonheaders.h" - -int LoadSendRecvMessageModule(void); -int SplitmsgShutdown(void); - -PLUGINLINK* pluginLink; -HINSTANCE g_hInst; -int hLangpack; - -struct MM_INTERFACE mmi; -struct UTF8_INTERFACE utfi; -struct LIST_INTERFACE li; -TIME_API tmi; - -PLUGININFOEX pluginInfo = { - sizeof(PLUGININFOEX), - "Send/Receive Messages", - __VERSION_DWORD, - "Send and receive instant messages", - "Miranda IM Development Team", - "rainwater@miranda-im.org", - "Copyright 2000-2012 Miranda IM project", - "http://www.miranda-im.org", - UNICODE_AWARE, - DEFMOD_SRMESSAGE, // replace internal version (if any) - {0x657fe89b, 0xd121, 0x40c2, { 0x8a, 0xc9, 0xb9, 0xfa, 0x57, 0x55, 0xb3, 0xc }} //{657FE89B-D121-40c2-8AC9-B9FA5755B30C} -}; - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - g_hInst = hinstDLL; - return TRUE; -} - -__declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion) -{ - return &pluginInfo; -} - -static const MUUID interfaces[] = {MIID_SRMM, MIID_LAST}; -__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) -{ - return interfaces; -} - -int __declspec(dllexport) Load(PLUGINLINK * link) -{ - pluginLink = link; - mir_getMMI(&mmi); - mir_getUTFI(&utfi); - mir_getLI(&li); - mir_getTMI(&tmi); - mir_getLP(&pluginInfo); - - return LoadSendRecvMessageModule(); -} - -int __declspec(dllexport) Unload(void) -{ - UnloadOptions(); - return SplitmsgShutdown(); -} diff --git a/plugins/SRMM/srmm.cpp b/plugins/SRMM/srmm.cpp new file mode 100644 index 0000000000..20ef673b8e --- /dev/null +++ b/plugins/SRMM/srmm.cpp @@ -0,0 +1,82 @@ +/* +Copyright 2000-2012 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "commonheaders.h" + +int LoadSendRecvMessageModule(void); +int SplitmsgShutdown(void); + +PLUGINLINK* pluginLink; +HINSTANCE g_hInst; +int hLangpack; + +struct MM_INTERFACE mmi; +struct UTF8_INTERFACE utfi; +struct LIST_INTERFACE li; +TIME_API tmi; + +PLUGININFOEX pluginInfo = { + sizeof(PLUGININFOEX), + "Send/Receive Messages", + __VERSION_DWORD, + "Send and receive instant messages", + "Miranda IM Development Team", + "rainwater@miranda-im.org", + "Copyright 2000-2012 Miranda IM project", + "http://www.miranda-im.org", + UNICODE_AWARE, + DEFMOD_SRMESSAGE, // replace internal version (if any) + {0x657fe89b, 0xd121, 0x40c2, { 0x8a, 0xc9, 0xb9, 0xfa, 0x57, 0x55, 0xb3, 0xc }} //{657FE89B-D121-40c2-8AC9-B9FA5755B30C} +}; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + g_hInst = hinstDLL; + return TRUE; +} + +extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +static const MUUID interfaces[] = {MIID_SRMM, MIID_LAST}; +extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) +{ + return interfaces; +} + +extern "C" int __declspec(dllexport) Load(PLUGINLINK * link) +{ + pluginLink = link; + mir_getMMI(&mmi); + mir_getUTFI(&utfi); + mir_getLI(&li); + mir_getTMI(&tmi); + mir_getLP(&pluginInfo); + + return LoadSendRecvMessageModule(); +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + UnloadOptions(); + return SplitmsgShutdown(); +} diff --git a/plugins/SRMM/srmm_10.vcxproj b/plugins/SRMM/srmm_10.vcxproj index bde897fe7b..e6f96a5014 100644 --- a/plugins/SRMM/srmm_10.vcxproj +++ b/plugins/SRMM/srmm_10.vcxproj @@ -201,18 +201,18 @@ - - - - - - - - - + + + + + + + + + Create - + diff --git a/plugins/SRMM/statusicon.c b/plugins/SRMM/statusicon.c deleted file mode 100644 index cd7ac3872e..0000000000 --- a/plugins/SRMM/statusicon.c +++ /dev/null @@ -1,221 +0,0 @@ -/* -Copyright 2000-2010 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ -#include "commonheaders.h" -#include "statusicon.h" - -struct StatusIconListNode { - StatusIconData sid; - struct StatusIconListNode *next; -}; - -HANDLE hHookIconPressedEvt; -struct StatusIconListNode *status_icon_list = 0; -int status_icon_list_size = 0; - -INT_PTR AddStatusIcon(WPARAM wParam, LPARAM lParam) { - StatusIconData *sid = (StatusIconData *)lParam; - struct StatusIconListNode *siln = (struct StatusIconListNode *)mir_calloc(sizeof(struct StatusIconListNode)); - - siln->sid.cbSize = sid->cbSize; - siln->sid.szModule = mir_strdup(sid->szModule); - siln->sid.dwId = sid->dwId; - siln->sid.hIcon = sid->hIcon; - siln->sid.hIconDisabled = sid->hIconDisabled; - siln->sid.flags = sid->flags; - if(sid->szTooltip) siln->sid.szTooltip = mir_strdup(sid->szTooltip); - else siln->sid.szTooltip = 0; - - siln->next = status_icon_list; - status_icon_list = siln; - status_icon_list_size++; - - WindowList_Broadcast(g_dat->hMessageWindowList, DM_STATUSICONCHANGE, 0, 0); - return 0; -} - -INT_PTR RemoveStatusIcon(WPARAM wParam, LPARAM lParam) { - StatusIconData *sid = (StatusIconData *)lParam; - struct StatusIconListNode *current = status_icon_list, *prev = 0; - - while(current) { - if(strcmp(current->sid.szModule, sid->szModule) == 0 && current->sid.dwId == sid->dwId) { - if(prev) prev->next = current->next; - else status_icon_list = current->next; - - status_icon_list_size--; - - mir_free(current->sid.szModule); - DestroyIcon(current->sid.hIcon); - if(current->sid.hIconDisabled) DestroyIcon(current->sid.hIconDisabled); - mir_free(current->sid.szTooltip); - mir_free(current); - WindowList_Broadcast(g_dat->hMessageWindowList, DM_STATUSICONCHANGE, 0, 0); - return 0; - } - - prev = current; - current = current->next; - } - - return 1; -} - -void RemoveAllStatusIcons(void) { - struct StatusIconListNode *current; - - while(status_icon_list) { - current = status_icon_list; - status_icon_list = status_icon_list->next; - status_icon_list_size--; - - mir_free(current->sid.szModule); - DestroyIcon(current->sid.hIcon); - if(current->sid.hIconDisabled) DestroyIcon(current->sid.hIconDisabled); - if(current->sid.szTooltip) mir_free(current->sid.szTooltip); - mir_free(current); - } - - WindowList_Broadcast(g_dat->hMessageWindowList, DM_STATUSICONCHANGE, 0, 0); -} - -INT_PTR ModifyStatusIcon(WPARAM wParam, LPARAM lParam) { - HANDLE hContact = (HANDLE)wParam; - - StatusIconData *sid = (StatusIconData *)lParam; - struct StatusIconListNode *current = status_icon_list, *prev = 0; - - while(current) { - if(strcmp(current->sid.szModule, sid->szModule) == 0 && current->sid.dwId == sid->dwId) { - if (!hContact) { - current->sid.flags = sid->flags; - if(sid->hIcon) { - DestroyIcon(current->sid.hIcon); - current->sid.hIcon = sid->hIcon; - } - if(sid->hIconDisabled) { - DestroyIcon(current->sid.hIconDisabled); - current->sid.hIconDisabled = sid->hIconDisabled; - } - if(sid->szTooltip) { - mir_free(current->sid.szTooltip); - current->sid.szTooltip = mir_strdup(sid->szTooltip); - } - - WindowList_Broadcast(g_dat->hMessageWindowList, DM_STATUSICONCHANGE, 0, 0); - } else { - char buff[256]; - HWND hwnd; - sprintf(buff, "SRMMStatusIconFlags%d", sid->dwId); - DBWriteContactSettingByte(hContact, sid->szModule, buff, (BYTE)sid->flags); - if (hwnd = WindowList_Find(g_dat->hMessageWindowList, hContact)) { - PostMessage(hwnd, DM_STATUSICONCHANGE, 0, 0); - } - } - return 0; - } - - current = current->next; - } - - return 1; -} - -void DrawStatusIcons(HANDLE hContact, HDC hDC, RECT r, int gap) { - struct StatusIconListNode *current = status_icon_list; - HICON hIcon; - char buff[256]; - int flags; - int x = r.left; - while(current && x < r.right) { - sprintf(buff, "SRMMStatusIconFlags%d", current->sid.dwId); - flags = DBGetContactSettingByte(hContact, current->sid.szModule, buff, current->sid.flags); - if (!(flags & MBF_HIDDEN)) { - if ((flags & MBF_DISABLED) && current->sid.hIconDisabled) hIcon = current->sid.hIconDisabled; - else hIcon = current->sid.hIcon; - - SetBkMode(hDC, TRANSPARENT); - DrawIconEx(hDC, x, (r.top + r.bottom - GetSystemMetrics(SM_CYSMICON)) >> 1, hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL); - - x += GetSystemMetrics(SM_CYSMICON) + gap; - } - current = current->next; - } -} - -void CheckIconClick(HANDLE hContact, HWND hwndFrom, POINT pt, RECT r, int gap, int click_flags) { - StatusIconClickData sicd; - struct StatusIconListNode *current = status_icon_list; - int iconNum = (pt.x - r.left) / (GetSystemMetrics(SM_CXSMICON) + gap); - char buff[256]; - int flags; - - while(current && iconNum >= 0) { - sprintf(buff, "SRMMStatusIconFlags%d", current->sid.dwId); - flags = DBGetContactSettingByte(hContact, current->sid.szModule, buff, current->sid.flags); - if (!(flags & MBF_HIDDEN)) iconNum--; - if(iconNum >= 0) - current = current->next; - } - - if(current) { - sicd.cbSize = sizeof(StatusIconClickData); - ClientToScreen(hwndFrom, &pt); - sicd.clickLocation = pt; - sicd.dwId = current->sid.dwId; - sicd.szModule = current->sid.szModule; - sicd.flags = click_flags; - - NotifyEventHooks(hHookIconPressedEvt, (WPARAM)hContact, (LPARAM)&sicd); - } -} - -HANDLE hServiceIcon[3]; -int InitStatusIcons() { - hServiceIcon[0] = CreateServiceFunction(MS_MSG_ADDICON, AddStatusIcon); - hServiceIcon[1] = CreateServiceFunction(MS_MSG_REMOVEICON, RemoveStatusIcon); - hServiceIcon[2] = CreateServiceFunction(MS_MSG_MODIFYICON, ModifyStatusIcon); - hHookIconPressedEvt = CreateHookableEvent(ME_MSG_ICONPRESSED); - - return 0; -} - -int DeinitStatusIcons() { - int i; - DestroyHookableEvent(hHookIconPressedEvt); - for(i = 0; i < 3; i++) DestroyServiceFunction(hServiceIcon[i]); - RemoveAllStatusIcons(); - return 0; -} - -int GetStatusIconsCount(HANDLE hContact) { - char buff[256]; - int count = 0; - int flags; - struct StatusIconListNode *current = status_icon_list; - while(current) { - sprintf(buff, "SRMMStatusIconFlags%d", (int)current->sid.dwId); - flags = DBGetContactSettingByte(hContact, current->sid.szModule, buff, current->sid.flags); - if (!(flags & MBF_HIDDEN)) { - count ++; - } - current = current->next; - } - return count; -} diff --git a/plugins/SRMM/statusicon.cpp b/plugins/SRMM/statusicon.cpp new file mode 100644 index 0000000000..7e45c4c844 --- /dev/null +++ b/plugins/SRMM/statusicon.cpp @@ -0,0 +1,221 @@ +/* +Copyright 2000-2010 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "commonheaders.h" +#include "statusicon.h" + +struct StatusIconListNode { + StatusIconData sid; + struct StatusIconListNode *next; +}; + +HANDLE hHookIconPressedEvt; +struct StatusIconListNode *status_icon_list = 0; +int status_icon_list_size = 0; + +INT_PTR AddStatusIcon(WPARAM wParam, LPARAM lParam) { + StatusIconData *sid = (StatusIconData *)lParam; + struct StatusIconListNode *siln = (struct StatusIconListNode *)mir_calloc(sizeof(struct StatusIconListNode)); + + siln->sid.cbSize = sid->cbSize; + siln->sid.szModule = mir_strdup(sid->szModule); + siln->sid.dwId = sid->dwId; + siln->sid.hIcon = sid->hIcon; + siln->sid.hIconDisabled = sid->hIconDisabled; + siln->sid.flags = sid->flags; + if(sid->szTooltip) siln->sid.szTooltip = mir_strdup(sid->szTooltip); + else siln->sid.szTooltip = 0; + + siln->next = status_icon_list; + status_icon_list = siln; + status_icon_list_size++; + + WindowList_Broadcast(g_dat->hMessageWindowList, DM_STATUSICONCHANGE, 0, 0); + return 0; +} + +INT_PTR RemoveStatusIcon(WPARAM wParam, LPARAM lParam) { + StatusIconData *sid = (StatusIconData *)lParam; + struct StatusIconListNode *current = status_icon_list, *prev = 0; + + while(current) { + if(strcmp(current->sid.szModule, sid->szModule) == 0 && current->sid.dwId == sid->dwId) { + if(prev) prev->next = current->next; + else status_icon_list = current->next; + + status_icon_list_size--; + + mir_free(current->sid.szModule); + DestroyIcon(current->sid.hIcon); + if(current->sid.hIconDisabled) DestroyIcon(current->sid.hIconDisabled); + mir_free(current->sid.szTooltip); + mir_free(current); + WindowList_Broadcast(g_dat->hMessageWindowList, DM_STATUSICONCHANGE, 0, 0); + return 0; + } + + prev = current; + current = current->next; + } + + return 1; +} + +void RemoveAllStatusIcons(void) { + struct StatusIconListNode *current; + + while(status_icon_list) { + current = status_icon_list; + status_icon_list = status_icon_list->next; + status_icon_list_size--; + + mir_free(current->sid.szModule); + DestroyIcon(current->sid.hIcon); + if(current->sid.hIconDisabled) DestroyIcon(current->sid.hIconDisabled); + if(current->sid.szTooltip) mir_free(current->sid.szTooltip); + mir_free(current); + } + + WindowList_Broadcast(g_dat->hMessageWindowList, DM_STATUSICONCHANGE, 0, 0); +} + +INT_PTR ModifyStatusIcon(WPARAM wParam, LPARAM lParam) { + HANDLE hContact = (HANDLE)wParam; + + StatusIconData *sid = (StatusIconData *)lParam; + struct StatusIconListNode *current = status_icon_list, *prev = 0; + + while(current) { + if(strcmp(current->sid.szModule, sid->szModule) == 0 && current->sid.dwId == sid->dwId) { + if (!hContact) { + current->sid.flags = sid->flags; + if(sid->hIcon) { + DestroyIcon(current->sid.hIcon); + current->sid.hIcon = sid->hIcon; + } + if(sid->hIconDisabled) { + DestroyIcon(current->sid.hIconDisabled); + current->sid.hIconDisabled = sid->hIconDisabled; + } + if(sid->szTooltip) { + mir_free(current->sid.szTooltip); + current->sid.szTooltip = mir_strdup(sid->szTooltip); + } + + WindowList_Broadcast(g_dat->hMessageWindowList, DM_STATUSICONCHANGE, 0, 0); + } else { + char buff[256]; + HWND hwnd; + sprintf(buff, "SRMMStatusIconFlags%d", sid->dwId); + DBWriteContactSettingByte(hContact, sid->szModule, buff, (BYTE)sid->flags); + if (hwnd = WindowList_Find(g_dat->hMessageWindowList, hContact)) { + PostMessage(hwnd, DM_STATUSICONCHANGE, 0, 0); + } + } + return 0; + } + + current = current->next; + } + + return 1; +} + +void DrawStatusIcons(HANDLE hContact, HDC hDC, RECT r, int gap) { + struct StatusIconListNode *current = status_icon_list; + HICON hIcon; + char buff[256]; + int flags; + int x = r.left; + while(current && x < r.right) { + sprintf(buff, "SRMMStatusIconFlags%d", current->sid.dwId); + flags = DBGetContactSettingByte(hContact, current->sid.szModule, buff, current->sid.flags); + if (!(flags & MBF_HIDDEN)) { + if ((flags & MBF_DISABLED) && current->sid.hIconDisabled) hIcon = current->sid.hIconDisabled; + else hIcon = current->sid.hIcon; + + SetBkMode(hDC, TRANSPARENT); + DrawIconEx(hDC, x, (r.top + r.bottom - GetSystemMetrics(SM_CYSMICON)) >> 1, hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL); + + x += GetSystemMetrics(SM_CYSMICON) + gap; + } + current = current->next; + } +} + +void CheckIconClick(HANDLE hContact, HWND hwndFrom, POINT pt, RECT r, int gap, int click_flags) { + StatusIconClickData sicd; + struct StatusIconListNode *current = status_icon_list; + int iconNum = (pt.x - r.left) / (GetSystemMetrics(SM_CXSMICON) + gap); + char buff[256]; + int flags; + + while(current && iconNum >= 0) { + sprintf(buff, "SRMMStatusIconFlags%d", current->sid.dwId); + flags = DBGetContactSettingByte(hContact, current->sid.szModule, buff, current->sid.flags); + if (!(flags & MBF_HIDDEN)) iconNum--; + if(iconNum >= 0) + current = current->next; + } + + if(current) { + sicd.cbSize = sizeof(StatusIconClickData); + ClientToScreen(hwndFrom, &pt); + sicd.clickLocation = pt; + sicd.dwId = current->sid.dwId; + sicd.szModule = current->sid.szModule; + sicd.flags = click_flags; + + NotifyEventHooks(hHookIconPressedEvt, (WPARAM)hContact, (LPARAM)&sicd); + } +} + +HANDLE hServiceIcon[3]; +int InitStatusIcons() { + hServiceIcon[0] = CreateServiceFunction(MS_MSG_ADDICON, AddStatusIcon); + hServiceIcon[1] = CreateServiceFunction(MS_MSG_REMOVEICON, RemoveStatusIcon); + hServiceIcon[2] = CreateServiceFunction(MS_MSG_MODIFYICON, ModifyStatusIcon); + hHookIconPressedEvt = CreateHookableEvent(ME_MSG_ICONPRESSED); + + return 0; +} + +int DeinitStatusIcons() { + int i; + DestroyHookableEvent(hHookIconPressedEvt); + for(i = 0; i < 3; i++) DestroyServiceFunction(hServiceIcon[i]); + RemoveAllStatusIcons(); + return 0; +} + +int GetStatusIconsCount(HANDLE hContact) { + char buff[256]; + int count = 0; + int flags; + struct StatusIconListNode *current = status_icon_list; + while(current) { + sprintf(buff, "SRMMStatusIconFlags%d", (int)current->sid.dwId); + flags = DBGetContactSettingByte(hContact, current->sid.szModule, buff, current->sid.flags); + if (!(flags & MBF_HIDDEN)) { + count ++; + } + current = current->next; + } + return count; +} -- cgit v1.2.3